RO EN

Clear separation between ReadModel and DomainModel (optional)

Clear separation between ReadModel and DomainModel (optional)
Doru Bulubasa
30 July 2025

In a well-structured project, the separation between ReadModel and DomainModel is an essential step to maintain clarity, performance, and adherence to SOLID principles. Although it is an optional stage, it becomes very useful once the application grows in complexity.


🎯 What does this separation mean?

  • The DomainModel contains the business logic, rules, aggregate entities, and constraints that govern the application's domain.

  • The ReadModel (or DTO for reading) is a simplified projection, optimized for the user interface and query-type requests.


📌 Concrete example

Let's assume you have a Post entity in the domain:

public class Post

{

    public Guid Id { get; private set; }

    public string Title { get; private set; }

    public string Content { get; private set; }

    public DateTime CreatedAt { get; private set; }

    // Business logic: validations, updates, publishing, etc.

}

On the other hand, in the reading area, you can have a model dedicated to the interface:

public class PostReadDto

{

    public Guid Id { get; set; }

    public string Title { get; set; }

    public string Excerpt { get; set; } // first 100 characters

    public string FormattedDate { get; set; } // e.g., "July 30, 2025"

}


🧠 Benefits of separation

  • Performance – DTOs can avoid unnecessary mappings and contain only what is needed.

  • Architectural clarity – The domain model remains clean, without UI-related properties.

  • Independence – You can adjust the UI without affecting the business logic.

  • Testability – You can write unit tests on the DomainModel without dealing with data formatting for the UI.


🔄 Typical flow with separation

Query → MediatR → Handler → Repo → Projection (ReadModel/DTO) → UI


📌 Recommendations

  • In the query handler, use Select with direct projection to the DTO (avoiding AutoMapper if you don't need complex mappings).

  • Return ReadModel only for reading – avoid exposing the public structure of the DomainModel.


✅ Conclusion

A clear separation between ReadModel and DomainModel helps you develop robust, well-organized, and easy-to-maintain applications. It is an architectural investment that shows its value in the long term, especially in enterprise applications.