[TYPO3-mvc] Persistence of value objects

Jochen Rau jochen.rau at typo3.org
Mon Apr 23 04:33:46 CEST 2012


Hi Stephan,

Wow, this is a long email. I apology for the brevity of my response.

On Fri, Apr 20, 2012 at 12:40:05AM +0000, Stephan Schuler wrote:
> When it comes to value objects, everything pretty much depends on what your data should be used for. In general I would say everything that is not allowed to be changed ever (!) is a candidate for being a value object.

You are talking about immutability data structures here. No need to call them Value Objects. In fact, I strongly believe that every data should be immutable.

> You talked about an address as being both, a good and a bad example. And indeed it is both, depending on what a single address object is to be used for. If it's the address where I live, it's definitely no value object since I might want to move at some time, or fix a typo or whatever.

Well, I said that an address is a good example of *not* using Value Objects at all.

> But think about an address as a part of an order. I am talking about a billing address or a shipping address. As soon as such an address is persisted together with an order, there should be no way to change it. At least not without making the order itself aware of this change.
> It becomes more clear when I move to a different place and want to change my default billing address: The orders I did in the past are not allowed to change just because orders I will do in the future should use another default billing address.

You are discussing this topic on a different level here. Of course there are 'things' (I try to avoid 'Entities') in you Domain that should not be changed once they are defined. Or other things that should not be duplicated. But even for those things, Value Objects would be a bad choice, because the test for equality is to simple to cover even basic domain needs.

The reason why Evans coined the Value Object is merely technical, not related to domain knowledge.

> This allows to two different sollutions:
> 
> Either I am not allowed to change address records as such. That's the value object approach. If I want to change my default billing address, I have to remove it from my account profile and create a new address that is bound to my account. The address objects that are connected to orders I did previously remain untouched. But this does not require my GUI to represent this 100%. I'm allowed to use input fields and an "update" button for my address, as long as the controller doesn't update the addess but replace it transparently for only the one situation the GUI shows.

The question is: How do you distinguish between correction a typo and moving to another place? Taking a Value Object doesn't help at all. In both cases you have totally different objects (from a machines perspective). To model such a case correctly you have to have three Objects:

- a Client, pointing to
- an (abstract) Place, pointing to
- a Representation (address, zip, city).

If you move to another place, exchange the current Place with the new one (and subsequently add a new Representation). If you correct a typo, just replace the Representation. You can archive the old places/representations if your domain requires you to do so.

> Or I am allowed to change address records. But because the requirement to leave persisted orders untouched is still active, the orderFactory is in charge to create deep copies/clonse of my default address and bind the cloned address to my user profile and prospective orders.
> Both approaches work quite well, but not using value objects results in multiple instances of the exactly same value pair on the persistence layer.

If you want to keep processed orders untouched, you have to dereference the representation according to the order date and take an archived representation.

You really don't need a Value Object here.

> Another example for value objects is a price. Each price consists of an amount with tax, another amount without tax and a tax value. As long as my products are part of a shopping cart or a products list, I can always calculate most of those values in realtime. But as soon as my product is part of an order the user has signed or payed, I should realy avoid any recalculation and store each and every calculated value instead. Not using value objects but flat copies leads to huge database tables because every order creates several price objects. Not using value objects but multiple references leads to the ability to change a product price for prospective orders and affecting past orders.

I suggest to persist the calculated total of an order as scalar with the order itself (as most ERP systems I know of do).

> The whole point is: There is no such thing like duplication and de-duplication of value objects. The only way to benefit from using value objects is to disallow every write operation on them and require themto be replaced completely instead.

Fine with me. But don't call it Value Objects and make immutability the default for all Entities. That would boost performance.

Best
Jochen




More information about the TYPO3-project-typo3v4mvc mailing list