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);
}
}
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.
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.
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With