It's Evolution Time: Do Repeat Yourself

Nein, das ist kein Bild von Gipf-Oberfrick sondern...
Beitrag erstellt am: 22.04.24
This is the second post in my small series It's Evolution Time, in which we talk a little more about why repeating yourself is actually a good thing while the original DRY Principle that states "Don't Repeat Yourself" is valid as well.

The original DRY is all about the idea of a single source of truth: Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.

This is sound advice. Unfortunately though, the original idea has been twisted and torn by some into "just remove code duplication", which can lead to convoluted and unnecessarily tight coupling. But that is a topic for another post.

My advice to repeat yourself, addresses a slightly different aspect of software design than merely avoiding or getting rid of code duplication: It is about finding higher-order abstractions that form a meta model you can use when talking about and implementing a system. That is what I meant when I wrote:

"Repetition and duplication are not the same thing. Find some pattern or set of higher-order abstractions that you can use over and over again in your solution. This is about having simple and sound meta models that you can use to structure your software designs and implementation."

It is about crisp abstractions, closely related to an observation Eric Evans made in his hallmark blue book on Domain-driven Design: When we write software, objects are not enough. We need higher-level abstractions that give rhythm and rime to your system. The original tactical domain-driven design patterns were one specific attempt to offer such abstractions - though nowdays I hardly use them anymore. Instead I favor CQRS with Event Modeling and Functional Core - Imperative Shell that in combination offer me the aforementioned crisp abstractions. As a result, we can reduce a significant amount of inadvertent complexity.

Event Modeling

Let's start with Event Modeling: It enables me to build information complete complex information systems by applying a simple set of patterns over and over again that follow a concise meta model, based on CQRS:
Event Modeling Meta Model
As a result, I can structure my system as a series of (true vertical) slices:
  • Given - When - Then for command slices
  • Given - Then for read model update slices

Note that this kind of slicing offers high cohesion within a slice and loose coupling between slices:  
  • A command slice deals with a specific attempt to do something, depending only on state described via the input read model; it produces a single event (yes, usually exactly one!) as a result, signaling success or failure. It doesn't need to know how the input read model it uses was calculated and it doesn't care about where the resulting event is subsequently used.
  • A read model update slice on the other hand only depends on events and doesn't need to know how these events were calculated. Furthermore, it is independent from the possible consumers of the resulting read model.

There is a lot more to say about event modeling - you can find more information about it on this site, or you can just go to the source on: eventmodeling.org

Functional Core - Imperative Shell

Next, let's look at the idea of  Functional Core - Imperative Shell. Again, there is a simple concise meta model that uses only a small set of abstractions:
  • Immutable data with copy-on-write semantics
  • and side-effect free calculations that make up the functional core
  • with actions that cause effects, which live on the outer rims of our system, aka shell

You can read more on this approach here: FP einmal anders: Daten, Berechnungen und Aktionen (German)
Funktionale Systemstruktur

In a Nutshell

Combining Event Modeling and Functional Core - Imperative Shell offers a powerful, yet easy to grasp way to design and implement complex information systems. It gives you a small set of crisp higher-order abstractions that can be repeated over and over again - giving loose coupling and high cohesion, while honoring DRY. Try it!