What is a Domain Model?
Imagine you just won a contract to build a skyscraper. Now imagine gathering your digging tools from the shed right away, landing up at the construction site by afternoon, and starting to dig right away.
The notion sounds laughable. Yet we build software like this every day. Facebook's mantra for a long time was to Run fast and break things. Developers tend to instinctively jump into code, probably that home page or that user API, when they start discussing a project.
Carpenters have a saying, "Measure twice, cut once." While carpentry is an excellent example of irreversibility of things, software development is far more forgiving and flexible. You can afford to make mistakes and correct them over time.
That does not necessarily mean the cost is insignificant. In fact, the later the correction is in a product's life, the higher the costs. Costs can even be literally infinite if one is dealing with a Big Ball of Mud.
It is more effective to step back, think about the problem deeply, map your business rules and workflows, pick specific areas that are core to your business to focus on, and only then get down to development.
There are many ways of stating the business problem and laying down specifics around business rules and data elements. A product requirements document used to serve as the go-to document for planning and ideation, but we have found it to be the least productive. A requirements document is a good starting point but fails to convey the business problem clearly and succinctly.
This is where Domain Models come handy.
The domain is a fancy way of saying the problem you're trying to solve. Most programmers spend their days trying to improve or automate business processes; the domain is the set of activities that those processes support.
Domain-Driven Design (or DDD) is the concept that helps you structure your code around the language, data, and behavior of your domain.
The term Domain Model did not originate with Domain-Driven Design. It goes as far back as 1980s with Ivar Jacobson and Grady Booch in their seminal book on Unified Modeling Language (UML).
Because Domain Models are primarily shaped by the domain they represent, they tend to be represented and interpreted in different ways. For some, DDD is purely an ideation process. For others, it is the technology that reflects the business problem accurately.
DDD novices struggle to understand what the term Domain Model stands for. Here are some aspects that can help understand Domain Models better.
A Domain Model is a Map.
Image Courtesy: The Guardian - Twisted Tracks
A Domain Model is a conceptual map that depicts a real business case. Like any good map, the model simplifies the terrain of the business case by making it easier to understand.
The model attempts to represent your domain with the help of a cluster of objects, working together to solve the business problem. These objects would typically enclose both information as well as the behavior of the domain.
Most importantly, the model is a simplification of the real business cases. Just like a subway map, it strives to improve understandability by simplifying things, at the cost of hiding some details.
The simplification is a feature and not a liability - it is necessary to get all players in a software development lifecycle - Business Users, Product Owners, Developers, QA - to a common ground.
Equally important is to understand that the the map is not the terrain. It is not a stand-in for the domain itself and it is not expected to represent the domain in totality.
So while modeling your domain, the focus will be breadth, not depth. You want to capture the problem space in entirety, rather than concentrate on details.
A Domain Model can only be validated by a Business User.
Since the Domain Model represents the problem space of the business, it can only be vetted and validated by a Business user. A Product Owner can stand in as a replacement for the business user, but they will eventually need to seek consensus on the model.
It is vital to get the model to represent the business processes as closely as possible. If you get the model right, your software delivers value to the end-user. If the model is wrong, your software becomes an obstacle to work around.
Because non-technical users are involved, a visual representation of the domain model works best for collaboration and concensus.
Still, a model in code should be verifiable by business people as well, as long as they can recognize domain elements and can read code. Ultimately, your software codebase is the absolute source of truth.
While it is possible to discuss and conjure up a perfectly logical domain, reality tends to be nuanced and contains complexity. Business users are the only people who can clarify and confirm the model.
In reality, the primary purpose of a domain model is to capture the model in the Business user's mind succinctly and visually for other stakeholders in the project.
A Domain may be made up of one or more Models.
Image Courtesy: Martin Fowler - Bounded Context
Each business tends to have one core problem it intends to solve. But for the product to be useful and valuable to users, many other supporting aspects have to be put in place.
For example, a Banking application's core value is in providing Accounting Services. But it needs to ensure only authorized users can access an account's details. So Security and Authentication, though a separate concern, is a very important area without which the banking application will not be able to deliver value.
In reality, most products deal with more than one core area in their functionality. Most business problems hold two or more of such supporting areas, called Subdomains within them.
Each such subdomain has a clear boundary, represented as Bounded Contexts in software. Such Bounded Contexts encapsulate Architecture Patterns within themselves.
A Domain Model is expressed in the domain's Ubiquitous Language.
Because Business Users contribute to developing Domain Models, the models tend to be rich in domain-specific terms. This rigorously defined language used by all stakeholders of the project is called the domain's Ubiquitous Language and is carried forward into the software implementation as well.
This language is often full of jargon, which is vital for people collaborating on complex systems because they encode domain experience. Jargons convey rich meanings of domain concepts and ensure their understanding among developers when used in code.
The Ubiquitous Language is one of the primary ways in which DDD manages to succinctly express the business problem, while still carrying rich, clear information into code.
These aspects make it seem like we should build Domain Models whenever we build software. But there is a caveat.
Beware of looking for Domain Models where none exist.
If all you have is a hammer, everything looks like a nail. - Abraham Maslow
In large, complex products, there is a real necessity to map the domain to uncover hidden complexities and relationships. But in simple projects where the business logic is extremely trivial or limited in scope, one can make do with trial and error.
Consider the earlier Banking Application example. It would be essential to construct a domain model for the Banking functionality of the application, but may not be necessary for the User Management subdomain. The constructs and business logic to manage application users can be straightforward and trivial.
It is crucial to recognize if your business problem has enough complexity to need modeling to avoid wasting time and effort. Even when deemed necessary, it is also vital to identify the core areas of the business and focus on them exclusively.
Also know that every problem can look trivial in the beginning.
Every software application starts small and clean in the beginning. But over time, products tend to grow complex with more and more features.
So while domain models do not make sense in projects that will not benefit from a domain-driven approach, it is also essential to start on the right path right from the beginning.
An excellent place to start evaluating would be discussions with Business users. They can explicitly point out any complex areas in the domain. Another useful heuristic is to assess the product's lifespan. If the product is expected to be around for a long time, is expected to handle all aspects of the user experience eventually, and deals with a reasonably involved area, it will grow in complexity. Remember that you should only focus on the core domain, and not on supporting fields of the product, even when you choose to model your business problem.
When unsure, err on the side of good design.
When you are not sure, it would be better to start with a domain model. It is easier to start with a simple domain model and refactor it over time (or even discard it ), than start with no model and grow one later.
The architecture associated with the model does not matter. You can start with a simple monolithic CRUD application, and then eventually scale it by DDD and CQRS principles to grow your business.