What is a domain model?
The domain model is an advanced way of organizing the domain in object-oriented programming (OOP). Contrary to anemic models, where objects do not take full advantage of OOP capabilities by having limited data or behaviors, a domain model integrates both behaviors and data. This allows objects to not only store information, but to perform meaningful operations and handle their own methods, which greatly enriches the interaction and functionality of the system.
How is a domain model different from a database model?
Confusion is often created between domain models and database models. A database model, generally referred to as a schema, is structured specifically for data management in a persistence environment, such as a SQL database with tools like the Entity Framework. Here it is common to find classes that denote characteristics of database fields such as primary keys, foreign keys and data validations. In contrast, in a domain model, classes are not necessarily tied to the database structure but are focused on representing business logic and behavior. This implies that OOP principles such as inheritance and polymorphism are leveraged to create objects that interact more richly within the application.
What components can a domain model include?
When developing a domain model, several elements are considered that enhance its functionality and maintainability. These include:
-
Entities: these are the core elements that represent real-world objects and have a unique identity in the context of the domain.
-
Value objects: Unlike entities, these objects have no identity of their own and their main function is to group related data. A common example is a route that encompasses an origin and a destination.
-
Inheritance and relationships: Inheritance allows extending the functionalities of a base class, while relationships connect different entities and objects to form a more robust network.
-
Design patterns: These are used to manage complex structures and promote code reuse.
These components create a cohesive system where the entities of the domain model are able to perform shared operations without overloading the logic of the services.
Practical example: Domain model applied
When applying a domain model, the classic example is that of a Flight entity that not only holds data, such as flight details, but also handles meaningful behaviors. For example:
public class Flight { public public int NumeroAsientosDisponibles { get; private set; } private List<Booking> Reservations;
public void AgregarReservacion(Booking booking) { if (IsAvailable(booking.Pasajeros)) { Reservas.Add(booking); NumeroAsientosDisponibles -= booking.Pasajeros; } } }
public bool IsAvailable(int pasajeros) { return NumeroAsientosDisponibles >= pasajeros; } }}
Here, Flight handles its own bookings and validates seat availability internally. This not only simplifies the purpose of the object, but gives it a more meaningful scope compared to a purely transaction-centric approach.
How are services impacted by the domain model?
Adopting a domain model positively impacts the services layer of the application. Services, which previously might have redundant logic in the work of validations and behaviors, now delegate these responsibilities to the relevant domain objects. Thus, operations such as validating a route or checking the availability of a flight are now handled directly within domain objects, leaving services to focus on coordinating rather than validating.
On the way to further optimizing the code, this approach allows objects to be reused in different contexts without the need to duplicate logic in different parts of the application. This principle not only improves maintainability, but also speeds up software development and extension.
Want to see more contributions, questions and answers from the community?