Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I use factory to update object?

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);
     }
}
like image 493
dream83619 Avatar asked Jul 21 '17 03:07

dream83619


3 Answers

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.

like image 81
GhostCat Avatar answered Oct 26 '22 08:10

GhostCat


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.

like image 24
Constantin Galbenu Avatar answered Oct 26 '22 07:10

Constantin Galbenu


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);
 }
like image 32
VoiceOfUnreason Avatar answered Oct 26 '22 06:10

VoiceOfUnreason