Domain Driven and Modular Design! part 1

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.

No alt text provided for this image

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.

No alt text provided for this image

DDD in summary is: Organizing the code so it is aligned to the business problems and using the business terms (Ubiquitous language).

No alt text provided for this image

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:

  •  Make development more efficient (small team works)
  •  Less time to coordinate with other developers and more on developing
  •  Each service can maintain or develop separately without any side effects to others
  •  Less dependency and easy to test.
  •  Microservices follows the single responsibility principle.
  •  The demanding service can be deployed on multiple servers to enhance performance.

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.

No alt text provided for this image

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.

Leave a Comment