Organizing our software into modules and contexts helps us going a long way toward clean and maintainable systems. Domain-Driven Design (DDD) describes some additional concepts or practices that go even further to organize code artifacts with standardized methods.
DDD’s large scale structure is comparable to classic software architecture. The big difference is that many traditional approaches are concerned with technical concepts like views, controllers, or data access. Large scale structure attempts to organize code according to domain concepts instead.
The first (and well-known) concept Eric Evans describes in his original book [Eva04] about DDD is the system metaphor. The idea to find an overarching metaphor for whole software systems isn’t new though. Extreme Programming describes it prominently as a way for shared understanding.
In DDD, the metaphor is also used to organize code on a larger scale. For example, we may discover that the system we build in the domain of some scientific calculations lends itself to the metaphor of a blackboard. There is data written to the board. Experts are standing in front of it, calculate new values, and write them on the board. With this metaphor, we can organize the code according to its concepts.
Metaphors can be inexact through. Therefore we should always ensure that it doesn’t get into the way of a design that does better resemble our domain.
We all know about layers in software. They help us divide components into different parts that have distinct (technical) responsibilities. In DDD, we try to layer the domain in addition to technical duties according to domain responsibilities.
For example, in the domain of an inventory system, there could be an infrastructure layer that contains storage locations with their capacities. For the products that can be stored, there is another layer which resides below the infrastructure layer. With such layering in place, the organization of code becomes even more apparent. Like with the technical layers, we should take care of the dependencies. Always depend on lower or inner layers and never allow cyclic dependencies.
In some domains, we may be able to divide the code into a knowledge level and a supporting worker or implementation level. The knowledge level describes what the software wants to achieve. For example, a domain-specific language (DSL) is a kind of knowledge level.
The worker or implementation level is then responsible for interpreting what the knowledge level describes and execute functionality accordingly. A prominent example from daily life is query languages. We state what we would like to query only but not how. The how is in the responsibility of some implementation that executes our query.
Pluggable Component Framework
The most rigid and limiting pattern of strategic design is the pluggable component framework. One way to implement it would be to define an abstract core. This core defines the interfaces of plugins that would like to contribute to a bigger process. That process may too has multiple implementations for which the abstract core defines the abstractions and interfaces.
Now we are free to combine different plugins into different applications. While this composition is very flexible and enables reuse of the plugins, the structure is stive and cannot be changed easily.
Wrap Up / Final Thoughts
The large scale structure part of DDD contains some interesting concepts. They focus on organizing code to improve the understandability of a system. I think if we implement one or more of these concepts while building our software, we can improve many aspects of the process.
New team members, as well as ourselves, profit from a big picture of the system. Modules are organized well according to their responsibility. The large scale structure should also be understandable by non-technical people and therefore helps us to improve communication with them.
[Eva04] Eric Evans: Domain-Driven Design – Tackling Complexity in the Heart of Software (homepage)