1

I'm trying to design a monolithic application following DDD and clean code. Lets say I have Users, User Types, Products, Product Types and Purchases. I want to implement using different modules.

At the moment I'm thinking in Users, including the user types, Products, the same including the service types, and Purchases.

Each module contains uses cases, domain models and infrastructure components for its entities. Since I want to have the modules loosely decoupled between them I was thinking to make communication using events.

My problem is when I trying, for example, to create a Purchase I will have a CreatePurchase use case in Purchases module, receiving UserId, ProductId and maybe other data related to the purchase. But in Purchases module don't have any information about Products and Users, lets say for verify the ids are valids.

How can I solve this problem? I can assume in Purchases module that the ids are valids but in some other layer I have to verify for this.

Another option that I have thought of is to replicate certain information between modules handling the events, but it does not seem entirely correct to me to have the ids of Users and Products in Purchases just to verify if they exist.

In the same way, If I have another module, for example Billing, that clearly is a different module than Purchases, and at some point need to use purchases to generate an invoice or other reports, how can I get this data if there is in a different module?

Of course, I'm trying to do all this without to have direct dependencies from one module on another, just handling events that are all across the modules.

2 Answers 2

3

Replication is redundancy. It won't be a good idea, neither good practice. You would have to make modifications in multiple places in case of a requirement change.

User and User types are related, Product and Product Types are related. So the combination should go into two modules, such as: UserModule containing User and User types, while ProductModule should contain Product and Product types. Purchase shall go into a separate module.

You may have to make 1 or 2 additional calls in each use-case, but the code will follow separation of concern principle, best practices.

The use case of purchasing a product will be:

getProduct -> ProductModule
UserSessionDetails -> UserModule
purchase(product, user) -> ProductModule

Second, Billing is a different module than Purchase. Billing may have connection to external interface, different billing methods; while purchase is internal to your system. So, Billing and Purchase shall go in separation.

1

I'd like to add some more general thoughts to Irfan's excellent answer.

Modules are not meant to be completely independent. Modules are meant to isolate related parts of the code, and define clear interfaces with other modules: what is needed from other modules and what can other modules access to. This kind of design facilitates maintenance, since it leaves freedom to change a module implementation and reduces change propagation.

In your case, Purchase can know a little bit about Products, i.e. that a product has an id, and how to verify the id. It's not a problem. You just have to minimise the knowledge of other modules as much as possible, and never refer to the internals of those modules, since those might change in future.

As you mention a monolithic application, it's important to keep in mind that modules are not microservices: Modules are not supposed to be deployed independently. They will always be deployed with the other modules that are needed and can fully rely on them.

In this regard, duplicating code is not modular programming. On contrary: if you need to duplicate code, there is probably some common functionality that should be isolated in a separate module, for easier maintenance. Keeping the same code in several places would make maintenance a catastrophe: sooner or later someone will forget to keep the replicated code in sync.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.