Domain Driven and Modular Design! part 1
Reza Bashiri
Senior Software Engineer @ anton-paar | Full-stack developer .net core (C#) and React | event-sourcing and design patterns | CQRS | Docker | Blazor | Problem-Solving | Self-Organized, ??ML learning??
Domain Driven Design
Literally defined by Uncle Bob as “Tackling complexity in the heart of software”, in another world, all the aim of bringing technical concepts and business together concepts under a ubiquitous language classified as domain-driven design. Before any practical action, we have to understand the main concepts inside it however I am not going to discuss them in detail but you will have topics and resources to keep it up.
Domain:?
The business or problem which we are going to find a solution for it. That solution in software engineering would be an application or service.
Core Domain:
Represent the reason why the business exits in the first place and at least one more subdomain that support the core domain.?
Sub Domain:?
In DDD, a subdomain is a relative term. Domain and subdomain can be used interchangeably. When we use the word subdomain, we are emphasizing that the domain we are talking about is a child of another higher-level domain that we have identified. Every subdomain is, therefore, a domain, and most domains are a subdomain.?
A subdomain is living in the business context and defines different models in the domain.?
Bounded Context:?
Is the solution to be applied for models within a subdomain, bounded context is living in solution and models means differently in different bounded context.
The key to understanding the difference between a bounded context and a sub-domain is understanding the difference between a domain and a domain model. The domain, in effect, is the problem to be addressed with a software effort. It is the problem space. A domain can be decomposed into sub-domains that typically reflect some organizational structure. A common example of a sub-domain is Product Catalog or Accounting - the latter possibly a generic sub-domain. A domain model on the other hand is an abstraction of a domain taking what's necessary to satisfy requirements. It has to be created with the cooperation of developers and domain experts. If the design and analysis process was a mathematical function, the model would be its range. In fact, it would have to be a non-injective and non-surjective function.?
?Hospital example to elaborate the concepts:?
?Imagine we are making software for a Hospital, in which we have identified 3 subdomain
? Health Care (Core domain, where they actually want to cure the patient)
? Invoice (Supporting domain focused on invoicing)
? Knowledge (Generic domain, where doctors maintain procedures on how to operate on a patient for a particular disease)
Now we know that Bounded Contexts are boundaries under which terms have a very well-defined meaning. So let us apply those in Subdomains
Let's consider the term. Patient. What are the things that you think about when hearing the term patient?
1. Their current symptoms
2. Past medical records
3. Allergies
How about their bill-paying credibility? Current outstanding balance? Didn't think of it? The reason is you were thinking in the core subdomain space of Health Care. The bill-paying credibility makes sense only when you shift to the Invoice subdomain.
What we understand from this is the Patient term is inside a Bounded Context, its a boundary inside a subdomain where it has a very specific meaning
The reason it said
BC is in solution/implementation/programming space and not in business space
is because here we decide what fields and behaviors should be part of the Patient model
In the core domain space, you might represent the Patient like this
??? class Patient
????{
???? List<Allergy> alergies;
???? List<MedicalRecord> records;
???? Age age;
???
???? boolean isAllergicTo(Allergy allergy)
???? boolean canTakeLocalAnesthesia()
???
??? }
Whereas in the?Invoicing?subdomain you might want to represent it like this
??? class Patient {
????
???? CreditCard creditCard;
???? CreditScore creditScore;
???? Bill currentBill;
???
???? void charge(Amount amount)
??? }
Similarly, the term?Cure?in the Health Core subdomain would have the operations that were/are_to_be performed on a patient to cure the disease whereas in the?Knowledge subdomain?it would contain information about Symptoms, Diagnosis tests, Prescription suggestions, that go along with a disease.
You can now see the Health Care subdomain has multiple BCs and under a BC each term has a very specific meaning thus supporting the Ubiquitous Language
Aggregate:
Represent a collection of objects that are connected to each other, with the goal to treat them as a unit. They also have aggregate roots. The most important things about them are:
1.??????They have to be accessible just through aggregate root
2.??????An aggregate should be changed in a single transaction through aggregation root functions
ValueObject:
Don’t have a unique identifier, they represent attributes that various entities can share, like address in order entity.
Entity:
A domain entity in DDD must implement the domain logic or behavior related to the entity data (the object accessed in memory). For example, as part of an order entity class, you must have business logic and operations implemented as methods for tasks such as adding an order item, data validation, and total calculation.
DDD in summary is: Organizing the code so it is aligned to the business problems and using the business terms (Ubiquitous language).
Microservices
Is an architecture design model with a specific bounded context, configuration, and dependencies, and results from Domain Driven Design and DevOps.
Tip1:
Bounded contexts (subdomain from a business perspective) are the best candidates for being broken down into separate micro-services.
Pros:
Cons:
·????????Difficult to manage a large number of services
·????????Microservices have all the associated complexities of the distributed system.
·????????There is a higher chance of failure during communication between different services.
·????????The developer needs to solve problems, such as network latency and load balancing.
·????????Complex testing over a distributed environment.
Tip2:
Keep the microservice context boundaries relatively small but not as much as making chatty communication between them.
Does necessarily DDD lead to Micro-services?
No, This is a common misunderstanding of most system architectures, ?developers, and even experienced team leads make, you can shape your software based on DDD principles while having a monolith solution, and this is what I want to explore more.
Despite all microservices benefits and scale-up features, they have inside, communication and network latency are not easy to deal with especially for small companies, An software can still uses DDD benefits in monolith design and it would be a Modular system.
Modular design, modularity
It’s been around for a long time now. It’s basically a design approach that creates things out of independent parts with standard interfaces that can be stacked, rearranged, customized, reused and so on. In other words, this method is about taking a design and breaking it down into small parts (these are the modules). Then these small parts are created independently which later will be combined into a larger system. So the point is to be able to change or fit singular elements without replacing the entire system. Due to its reusability, modular design is very beneficial and sustainable. Adopting modular design and reusable patterns into your design workflow can improve the consistency and quality of your platform
Each module could be a bounded context in Domain Driven Design in a monolith application, by pushing each bounded context into an independent module we will come across benefits of both architectures without dealing challenges of micro services.