1

Let's say I have the following Aggregate Root:

class Order {
     private Collection<OrderItem> items;
     ...
     public void updateQuantity(int itemId, int quantity) { ... }
}

And let's say I use plain SQL to persist it. The question is: how do I persist Order and its items without exposing the collection? I see several ways which I don't like:

1) Add a method that returns the copied collection. I don't like it, because we need to make copies of each item as well (since it is Entity and can be changed) which is another challenge on its own.

2) Add getters for every property of items:

 class Order {
      public int getQuantity(int itemId) { ... }
 }

It is better since no one from outside cannot change the root's nested entities. But it can blow the root's class with tons of dummy getters.

3) Use the Hibernate way: get the items through java's reflection in the repository. That's "cheating". Also I am thinking about the way of creating DTO's as well, so I need a legit way to read the values.

4) Make the field to use default modifier and put the repository implementation (and the DTO's assembler as well) to the same package so that it will have access to the fields. Don't like it because repository implementation is not part of the domain.

I prefer the second approach, but there might be some other way I am missing?

Alexey Balchunas
  • 400
  • 3
  • 10

1 Answers1

1

I would expose a collection of OrderItems.

There is a good SO question "What is the best practice for read-only lists in NHibernate" where you can find a lot of information of How to expose collections right.

I do not see any concerns to hide collection of OrderItems as an internal state. If you expose updateQuantity method then there should be a possibility to check if quantity is updated on the specific item or not.

1) Add a method that returns the copied collection. I don't like it, because we need to make copies of each item as well (since it is Entity and can be changed) which is another challenge on its own.

Actually, entities can be changed and they are not immutable. Value objects should be immutable.

In your example Order looks like root entity or Aggregate Root and OrderItem looks like Entity. It has an identity within an Order at least so it is definitely not a Value Object.

3) Use the Hibernate way: get the items through java's reflection in the repository. That's "cheating". Also I am thinking about the way of creating DTO's as well, so I need a legit way to read the values.

Some people use two models:

  • "clean" Domain Model
  • and "dirty database depended" Persistence Model.

Well, I am not a big fan of this approach. Usually I try to make my ORM to generate decent database structure based on the Domain Model.

2) Add getters for every property of items:

It is better since no one from outside cannot change the root's nested entities. But it can blow the root's class with tons of dummy getters.

In order to prevent them from the outside changes there is a good practice not to expose public setters and to keep them private or protected at least.

Community
  • 1
  • 1
Ilya Palkin
  • 14,687
  • 2
  • 23
  • 36