Harness the power of domain-driven design

Systems work when we all speak and understand the same language.

Read time 4min 30sec
Lorraine Steyn.
Lorraine Steyn.

Software design is complex, and the lack of good design plagues many teams. This is visible in code that has become "too difficult" to maintain and extend, and ultimately ends up with business being told they need to rewrite core systems, in the hopes of a better structured solution.

Of course, rewriting a system just exchanges a set of known issues for a set of unknown issues! In short, if the team hasn't learnt better design and refactoring techniques before they start the rewrite, the new code base is very likely to drift into the same sort of mess as the old code base, in a depressingly short space of time.

One of the approaches to avoid this happening and that can help to organise code, and thereby keep it maintainable for longer (saving considerable bucks in system rewrites/replacements), is domain-driven design (DDD).

DDD describes a methodology for modelling software according to the fundamental language and behaviour of the business domain. This is a powerful approach, as it helps to align the developers, and the code we write, more closely with the business. This in turn makes it easier to maintain and extend the code as business needs change.

One of the first steps in DDD is agreeing on the meaning of various business terms. Getting agreement, for example, that invoice value always means an amount including sales tax, and agreeing that we won't call this anything else. I worked with a system once, which had seven different meanings for invoice value (among many other sins), adding enormously to the confusion that accompanied changing any code.

DDD is an approach for handling software that is strong on principle but does not dictate implementation; it's what fits YOUR domain.

We call this agreement around naming, "ubiquitous language", in DDD. It is our first alignment that says we will be consistent and precise in the terms that we use. This means that even under the covers, in any place in code, data or communications where a term is used, ubiquitous language rules. It's not just a language between developers and business, but a commitment by all parties to use consistent language at all times. Pretty simple, yet very powerful.

Organising and structuring code is necessary to help humans understand the code we produce. The computer will run any old mess, so long as it's syntactically correct. Unfortunately, us humans often forget this truth and we write complex, difficult-to-understand code for a raft of incorrect reasons, that completely ignores our own fallibility.

Sometimes, it is because we really didn't understand the problem space when we started. Further complexities arose as we worked, and by the end, we had the well-known 'big ball of mud'. This is code that's horrible to follow: poor structure, complex interfaces, long methods that are hard to test, etc. It's also called spaghetti code because everything's so tangled up.

A great deal of business value lies trapped in legacy code bases. DDD assists teams to strategically refactor the code, taming any 'big ball of mud' and thereby extending the life of legacy systems.

But why wait for it to be a mess before applying good principles? DDD supports the Agile process, helping a team to align with business needs through a rigorous engineering design approach.

More in-depth design upfront definitely helps to reduce some of the unknowns. But upfront design is a Goldilocks problem. Too much upfront design can become "analysis paralysis" and can be out of date by the time we start development in a rapidly changing business environment. Too little leads to errors and missed functionality and generally unhappy users.

Finding the spot where Goldilocks's porridge is just right is partially experience, and mostly, good process. We're looking for an iterative process with a solid engineering approach. A merge of Agile and a modelling tool like DDD.

Not that DDD suits all situations. Its biggest value lies in aiding communication and understanding of complex problems. A simple problem may not benefit from a full DDD approach upfront, although many simple problems have turned into complex problems over time; so again, experience needs to lead the team in deciding when to look at a domain model to assist them.

We must also recognise that models are limited, and DDD practitioners tend to say that all models are wrong, but some are useful. This references the goal of modelling complexity, and not modelling the entire system. The model is only useful in clarifying concepts, and we mustn't fall in love with the perceived perfection of our model.

DDD is an approach for handling software that is strong on principle but does not dictate implementation; it's what fits YOUR domain. At the very least, it provides a strong set of guidelines or a methodology to cope with the complexity that is today's business domain and assists everyone to be on the same page, which can only be of benefit to all.

Lorraine Steyn

Simplifier-in-chief, Khanyisa Real Systems

Lorraine Steyn is simplifier-in-chief at Khanyisa Real Systems, a bespoke software development company she pioneered 32 years ago. Aside from leading a successful team of 60+ developers, Steyn is a respected international speaker on the topics of domain-driven design and systems thinking.

See also