Let’s continue to look at the supple design patterns of domain-driven design (DDD). Previously we learned about Intention-Revealing Interfaces, Side-Effect-Free Functions, and Assertions. These patterns help greatly reduce mental overload and should lead to a supple design without surprises.
In this post, I would like to cover Conceptual Contours, Standalone Classes, Closure of Operations, and Declarative Style of Design. One overarching theme of these is coupling and cohesion. They help us reduce coupling and increase cohesion, which can have multiple benefits.
When we design and create our objects and classes, we should always keep the concepts that they represent in mind. Sometimes after coding for some time, I like to stop and take a look at what I’ve created. Is the code still in line with my original concept? Should I refactor some interface? Or is my understanding now different than when I started?
These are the moments where conceptual contours emerge. I think that most of the time we don’t get these right in the first place. Only through continuous refactoring, we eventually arrive at a point where there is the right amount of coupling and cohesion.
The benefits we get when we take the time to refactor towards these conceptual contours are readability and maybe even reusability. If the components we created have low coupling and high cohesion, there should be a higher probability that they can be reused for another feature or story.
With Standalone Classes, we have no coupling at all. You may think that this is impossible. There always has to be some coupling. Otherwise, the class cannot be useful. However, more often than not, we can reduce the coupling to the most primitive types in a language, for example.
Let’s take a look at an example in the domain of a webshop. Prices of products are calculated by applying a discount on a default price based on various conditions. We could implement this requirement in various ways. Let us first consider the following possibility:
This design can be reasonable because it’s easy to use by clients, and the base price is encapsulated within the product. If we like to focus on low coupling instead, we could come up with this design:
As you can see the dependency is gone and we have two standalone classes (If you think of Amount as a base type not counted for coupling). The advantage of this design is that we can test both classes in isolation now.
Closure of Operation
Closure of operations is a concept from mathematics. It states that a set is closed under an operation if the execution of that operation on members of the set always produces a member of that same set. Such operations have only arguments and return values of the same type.
Besides mathematics, there are some other domains where we could apply closure of operation like metallurgy, atmosphere, or color (the original sample in Eric Evans book on DDD [Eva04]).
Declarative Style of Design
The basic definition of the declarative style of design (or just declarative programming) is: Describe what you want to accomplish instead of how. Most of the time, there needs to exist an abstraction layer that implements how below the layer with the definition of what.
Now you already can imagine a drawback of declarative style. The effort to build something that executes your model can be very high. However, there are advantages too, of course.
The declarative style could be seen as the ultimate supple design. If we design our own domain-specific languages (DSL) for example, the design becomes ultimately supple. Working in the declarative model layer becomes simple and intuitive.
Wrap Up / Final Thoughts
Low coupling and high cohesion are worthwhile goals of software development stated by many mentors of our profession. The patterns in this post provide some guidance on how to achieve those properties with a supple design.
I especially like the idea of DSL. We built one at opus software for our measurement system, and it turned out to work pretty well. However, I understand that not every system can profit from a specific DSL.
[Eva04] Eric Evans: Domain-Driven Design – Tackling Complexity in the Heart of Software (homepage)