9

I use factory to create entity by command object, but when I want to update entity from command object, I can't find a good patten to do this. Should I just use factory to update entity, or if not, what is a good pattern?

interface ProductFactory {
    Product create(ProductCommand command);
    Product update(Product product, ProductCommand command);
}

my service:

class ProductServiceImpl {

     public Product updateProduct(long productId, ProductCommand command) {
         Product product = productRepository.findOne(productId);
         product = productFactory.update(product, productCommand);

         return productRepository.save(product);
     }
}
GhostCat
  • 137,827
  • 25
  • 176
  • 248
dream83619
  • 621
  • 7
  • 16
  • If your domain is mostly CRUD then do not attempt to apply the tactical DDD patterns. Do not attempt to craft a rich domain model. Just have dumb data bags, implement the logic into services directly and use scaffolding tools to generate repetitive code automatically. Believe it or not, that could be the most DDD-aligned solution because at it's core DDD is about properly identifying the sub-domains and solve their problems with the right solutions. Slapping a domain model on everything goes against what DDD promotes. – plalx Jul 21 '17 at 13:51
  • Call it a KISS answer, but what in DDD would prevent a class from having its own methods to update its objects? It's known sometimes as the [Do-it-myself pattern](http://principles-wiki.net/principles:tell_don_t_ask_information_expert). – Fuhrmanator Jul 21 '17 at 14:00

4 Answers4

6

On DDD one of the strategic paterns is the use of ubiquitous language in code. So, in your specific case, the class methods should be named according to what they do, like Product::changeTitle or Priduct::changePrice:

Also, there are multiple architectural styles. One of them is without a command object but with multiple parameters like this:

class ProductService {

     public void changeProductPrice(long productId, double newPrice) {
         Product product = productRepository.findOne(productId);
         product.changePrice(product, newPrice);

        productRepository.save(product);
     }
}

This style follows a lot the ubiquitous language.

The other style is with a command object parameter:

class ProductCommandHandler {

     public void handleChangeProductPrice(ChangeProductPrice command) {
         Product product = productRepository.findOne(command.getAggregateId ());
         product.handleChangeProductPrice(command);

        productRepository.save(product);
     }
}

This second style fits very good with the CQRS+Event sourcing where you could almost eliminate the Application layer by extracting a generic command handler that identifies and loads the aggregate from the repository, it sends it the command, it collects the events and then persist them to the Event store. I use a lot this style.

Constantin Galbenu
  • 16,951
  • 3
  • 38
  • 54
  • thank you for your help, I finally move both create and update method to model class, but it looks messed my model class, I still think this is a common problem in DDD, and don't know what is the best practice, but keep things is model class make it much understandable. – dream83619 Jul 21 '17 at 09:27
  • The most important things in DDD are: the bounded contexts and the ubiquitous language; avoid names like `updateProduct`. It's a good think that you moved them to the model (Aggregate/Entity) in this way your model owns its data, it controls what is is permitted and what is not permitted inside it; also, in this way you protect the encapsulation of the model, an important principle from OOP. – Constantin Galbenu Jul 21 '17 at 10:16
  • In my opinion passing commands to aggregates is most likely a [bad idea](https://stackoverflow.com/questions/30434458/passing-cqrs-commands-directly-to-domain-objects/30445004#30445004). You just said it, the most important thing in DDD is the ubiquitous language. Commands are merely message contracts at the application boundary, they shouldn't belong to the domain. Business experts would certainly be puzzled by `product.handleChangeProductPrice(command)`, but not so much by `product.changePrice(newPrice)`. – plalx Jul 21 '17 at 13:32
  • @plalx I respect your oppinion. However, I like that style as it removes **a lot** of code duplication. – Constantin Galbenu Jul 21 '17 at 14:17
  • @ConstantinGalbenu What kind of duplication? Do you have an example? Also, what about value objects? From what I can tell `product.changePrice(new Price(command.price))` is much simpler than `product.handleChangeProductPrice(command)` which has to do the mapping internally anyway. No? – plalx Jul 21 '17 at 17:30
  • @plalx *all* Application services/layer. The example is my in-production micro-framework https://github.com/xprt64/cqrs-es – Constantin Galbenu Jul 21 '17 at 19:09
  • 1
    Oh ok I get what you mean, you do not have to load the AR etc. Well, it does remove a lot of plumbing, but it also comes at a cost. I can't really tell which is better, but your approach is definitely more technical and less aligned with DDD and the ubiquitous language overall I think. – plalx Jul 21 '17 at 20:21
5

The naming alone answers your question. A factory is responsible for creating things. Yes, in the real world, sometimes factories take back things they created to update them (think of German car manufacturers here).

But in case of software, turning your factory into a "maintenance station" seems like bad practice. It clashes with the single responsibility principle for example. Beyond that - a factory that updates objects is very uncommon - thus surprising to the human readers of the source code. And you want to avoid surprising people reading your code.

My suggestion: staying in line with the "service" theme I already mentioned: would it make sense introduce an UpdateService class for example? Of course, when there is common code for update and create, then that should again be factored out into a common class.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • thanks, but if I create a separate class, how can I reuse the code both required for create and update. – dream83619 Jul 21 '17 at 07:34
  • By factoring out the common parts in another class? – GhostCat Jul 21 '17 at 07:41
  • thank you for your answer, but I finally end with the Rich Domain Model things, and move both create and update method to model class. – dream83619 Jul 21 '17 at 09:18
  • You are welcome. It is always nice to see questions that provoke further thinking - and to see how helpful but *diverse* answers come back ;-) – GhostCat Jul 21 '17 at 09:28
1

In Domain Driven Design, the application typically interacts with the aggregate root directly.

 public Product updateProduct(long productId, ProductCommand command) {
     Product product = productRepository.findOne(productId);

     product.update(productCommand);

     return productRepository.save(product);
 }
VoiceOfUnreason
  • 52,766
  • 5
  • 49
  • 91
  • If Product is a complex object, and I make it only a data class (only have getters/setters), can I put update method in other class, l want to put it in factory because I want to reuse code both in create and update. – dream83619 Jul 21 '17 at 05:58
1

Factories are for creating objects, not for updating them.

Updating a entity is a persistence aspect and is done by the repository.

You have to do the following in the application layer:

1) Call the repository to retrieve by id the entity you want to update.

2) Modify the entity properties you want, with the values you get from the command. This is done by calling entity methods that update the properties. You shouldn't do it in the factory. The factory is just for creating the entity. Modifying the entity is a behavior (method) offered by the entity.

3) Call the repository to persist the entity.

choquero70
  • 4,470
  • 2
  • 28
  • 48