What is Domain-Driven Design and why is it helpful?
Domain Driven Design (DDD) is an approach to software development, made popular by Eric Evans’ book, Domain Driven Design, published in 2003. It still receives a lot of attention today and is a highly respected tool in a lot of architects’ toolboxes.
Why? Quite simply, DDD is about guiding engineers to focus on the business domain (e.g. the terms, rules, and business goals that business experts apply to a given problem), rather than technical concepts or frameworks, and to collaborate very closely with domain experts to find a shared language and model for the domain.
Over recent years, DDD has proved incredibly useful where software businesses scaled fast and developed a need for vertical cuts through their products, teams, and codebase. For example, the rise of microservices requires tech teams to define modular boundaries and assert which logic belongs to which service. DDD is also helpful in creating a product that is aligned with business priorities with fewer iterations, as it focuses on closing the gap between the code and the reality of the business needs.
At Taxdoo, we focus on the domains of Taxes & Accounting. We tend to deal with complex software where the limits of our understanding can soon become limits of our products and codebase. Luckily Taxdoo offers us to spend 10% of our time as ‘innovation time’ where we are encouraged to learn and experiment.
Making use of that, a few of us engineers and domain experts founded a book club, where we spend our innovation time reading and sharing what we’ve learned together.
There’s no such thing as too much collaboration.
With knowledge sharing, it can be tempting to have only software engineers at the table. We’re learning about a coding concept, so why involve other parties?
Having domain experts in the book club prevents engineers from becoming too technical or jumping into ivory tower discussions.
At Taxdoo, we involve domain experts, called ‘Regulatory Analysts’, in our book club reviews and also our scrum ceremonies.
The result? We are using and constantly optimizing a shared language and mutual understanding about the rules and terms of our business that we use in our daily work and can be applied in our daily work. A huge bonus of involving domain experts so closely is that user stories are written by a domain expert, which reduces ambiguity and deviation. It took some time before both parties learned the terms used by the other, however, it has resulted in greater transparency and clearer requirements.
Business Process Model notation (BPMN): where analysis and implementation go hand in hand
Another interesting learning is that DDD discourages a separation between analysis and implementation.
Often, engineers collaborate with domain experts only until they think they understand the problem. Then they go and write the code, so that the implementation is hidden in the code and invisible to the domain experts. This then necessitates a step of translation, done by the developer, that often unconsciously changes domain logic or language. This drift in precision causes technical debt or bugs as the project progresses.
In Taxdoo, we use decision trees for our tax logic, and in the past, these trees were provided as diagrams by domain experts and then translated into code by us engineers. This approach was fine, however, we still weren’t quite accurate enough in communicating and understanding our requirements.
Last year we migrated this logic to BPMN, which is an industry-standard for business process modeling. The great thing about BPMN is that it combines the diagram and the implementation. This is done through an underlying XML layer. We can now collaborate by visually creating a diagram together and do not need an additional implementation that could impose the risk of misunderstandings or drift in language.
There’s still a long way to go, however moving to BPMN was a great start to close the gap between analysis and implementation.
Value Objects: capturing values in a transient state
DDD is a large concept that can be adopted on all levels of a company. That being said, not all companies have the capacity for this and in any case, it makes sense to experiment with concepts before applying them on a large scale. One application of the suggested code patterns that worked very well for us was the introduction of Value Objects.
In DDD, Value Objects represent values in a transient state, usually bound to one operation. They are distinct from entities, which are longer-living objects that have their own lifecycle and identity in the given context. In contrast, value objects don’t need any kind of identity, because two instances with the same values could be used interchangeably.
Here’s an example where we introduced such an object and how it helped us:
VAT IDs
The VAT identification number is assigned to a company by the financial authorities and used for value-added tax (VAT) purposes.
In our world of B2B taxes, the VAT ID is a type of value that we need to process often. When a customer provides us with a VAT ID through a form or support requests, we usually receive it as a simple String. A first improvement to the object (to make it a more powerful part of the domain model) would be to restructure it in a way so that it yields more information about its purpose.
While this refactoring is not really providing a lot of additional logic, it already helps to fulfill the claim of DDD refactoring: “Refactoring towards a deeper insight of the domain”. By making this value a dedicated class and destructuring the characters into fields, the code becomes clearer about the contents of the VAT ID String, which is especially useful if you’ve never seen a VAT ID before.
We could now also add validation to make the object even more helpful.
For Taxdoo’s use case, there’s a little more to it: a VatId country code is usually the IsoCountry code of the country where the company has registered. However there are some edge cases. In Greece, the country code for VatIDs is “EL” instead of “GR” and Northern Ireland also has its own country code of “XI” even though its usual IsoCountry code would still be “GB” for Great Britain.
To encapsulate that domain knowledge as part of our implementation, we can add a dedicated Getter that would translate the encoded country code into an IsoCountry:
By combining this domain knowledge we can provide an even more reliable parsing and validation. We know that the country code must either be castable to an IsoCountry or match one of the special cases mentioned above. If the provided country code prefix in the input String does not match these conditions, we know that the provided VAT ID is malformed:
In summary
Let’s recap: initially, we had a simple value, stored in a String. In the domain of tax evaluation, that value is often processed, parsed, and interpreted. We need to check for the validity of the VatId, we need to derive information and we need to send it across the network.
By making it a dedicated class, we strengthen our understanding of what a VatId is. If a new developer comes into our Taxes & Filings team and sees this code, the code represents the domain model that is useful when applied to our context. A lot of these principles could simply be regarded as “good OOP” or best practice, however in this case it helps us to understand the domain and share the attributes and capabilities of our models with the domain experts.
In a real-world use case, there’s much more knowledge that can be contained in a VAT ID model inside of the context of taxes: Is the VAT ID valid? When was it registered? Note that depending on the context, the VAT ID could receive an identity with its own lifecycle (it’s even called ID!). In such a case, it would not be a value object anymore but would become an Entity, because we would store it with an identifier, so that we can track its lifecycle and add relationships to other objects, for example, a “Company” object.
Thinking about your objects and if they need a lifecycle in your domain will help you to obtain a deeper insight into your domain. This is a great tool from the DDD toolbox.
Layered Architecture
Our final example: the isolation of a domain layer in the code base. While we applied this as part of our interpretation of Clean Architecture, the isolation of a domain layer is part of the layered architecture that is suggested by the book.
We did this by creating a dedicated package for the domain logic and extensive use of Java Interfaces whenever we wrote code that was related to persistence or other infrastructural tasks. The domain package contains the long-living domain logic (e.g. applying the tax evaluation), while database transactions, API clients, or serializers are hidden behind interfaces with their implementations in a separate data package. The resulting package structure looks like this:
This separation allows us to make changes to the infrastructure (e.g. moving from RDS to DynamoDB) without touching the domain logic since we only need to provide another implementation of the respective interface. At the same time, we can also test our domain logic (which is the most important one to test) without worrying about the setup of a database or external service. It’s also easy to check or lint: No class in the domain package must ever contain an import from the data layer.
4 Tips for Getting Started with DDD in your Organisation
- If you want to promote DDD or learn more about it in your company, involve domain experts from day one. They will prevent you from drifting into technicalities and you will collectively learn a shared language to discuss your daily collaboration.
- Getting started with DDD works especially well when you work with serverless architecture (like Taxdoo) since architectural changes can be done faster compared to on-premise (which means that servers would be hosted physically by the software company itself, requiring time and financial resources to maintain their own infrastructure and server hardware) and the architecture is divided into smaller components. You’ll also spend less time on maintenance of non-domain-logic components since most of that is handled by the cloud provider.
- Leave the larger and more complex patterns (for example Aggregates and Factories) for later and concentrate on the core idea. You don’t necessarily need to rewrite all code, to start your shift towards a more vivid domain model, but you can do that e.g. through the introduction of Value Objects.
- If you haven’t done that, you can also start by isolating a domain layer first. Once that is done, you can apply more of the DDD patterns inside that layer, if it seems reasonable for you.
Good starting points for further information would be the “Blue Book” or the summary in the form of the DDD reference, both by Eric Evans. If you prefer to watch conference talks, I can also recommend checking out the DDD Europe Youtube Channel which contains a lot of talks around DDD concepts or their (technical) implementations.
Do you have experience with DDD? What were your takeaways from it? If you are new or are leveling up your DDD knowledge, we hope that you found this article helpful. Please feel free to re-share this post on social media or amongst your connections.
Finally, this blog post would not have been possible without the help of Paul, Maria, Alex, and Kevin. Thank you for the book club sessions that we had, and for your thoughts and inspiration!
In Taxdoo you’ll find the room and other motivated colleagues to invest time into new concepts and experiments. Join Taxdoo if you would like to participate!
Working in tech is awesome, especially as a software developer.
The opportunity to build amazing products, being paid to learn and working with very smart colleagues are just some of the reasons why this profession is so rewarding.
However, software engineering isn’t always a walk in the park. Tight deadlines, adjusting to remote work, fixing major outages and generally, the velocity of the tech industry are some factors that can cause you stress as a developer. Therefore, it’s important to look after yourself and create simple, daily rituals that support a healthy working routine.
Ahead of World Mental Health Day on October the 10th, we asked our software engineers on how they take care of their mental wellbeing.
Here’s what they said
1. Fresh air
Our interim VP of Engineering swears by fresh air and regular doses of sunshine; living in Hamburg means that biking to work or going for a lunchtime stroll around the Alster is easy to integrate into your daily routine.
2. Meditation
Some of us have trouble not thinking about things, so meditation can help you put things into perspective and arrive in the current moment rather than being swept away by thought.
3. The Pomodoro Technique
This technique focuses on working in 25 minute sessions throughout the day.
This can be helpful for focussing efficiently and it encourages you to take regular breaks so that you avoid sitting for hours and hours without moving, drinking water or looking away from your computer screen.
4. Connect with colleagues
At Taxdoo, we encourage everyone to set up or attend ‘Donuts’ (informal online meetings), regardless of department.
Catching up with a colleague over a random Donut or setting up a Developer Donut is a great way to get to know your colleagues and helps you to feel connected and part of a team.
5. Take a break
Coding is awesome and the feeling of completing a task is great, however rest is also important. Why not use your lunch break to talk a walk around the block? You might be surprised at how refreshed you feel.
6. Find a job you love
We all spend a lot of time at work, so it is important to feel comfortable and motivated by your tasks, colleagues and environment.
How do you look after your mental health as a developer?
Today is World Youth Skills Day so we want to celebrate young people’s access to training and career opportunities by providing some inspiration for anyone interested in working in tech.
We asked our developers, product managers and even our CEO about the resources that sparked their interest in tech and helped to hone their skills; here are their recommendations.
Practise this
If you have 30 minutes a day, try completing a few exercises on FreeCodeCamp. This is a great way to learn to code in bitesize amounts of time.
Try this
A good starting point are the Hello World courses on Codecademy, which helps with learning tooling set-up and understanding how things work in that language. You can also test your knowledge by modifying the code and adding other statements.
Get stuck into this
A slightly more advanced course for learning frontend development is ToDoMVC, which also has a lot of other examples for each tech stack.
Build this
Learning by doing is the best method which this C# Unity Game 3D course from gamedev.tv definitely will help you to do so.
Read this
Clean Code is the classic book written by Uncle Bob, otherwise known as Robert Cecil Martin, who epitomizes the concept of clean code. From a product perspective, check out Lean Product Playbook.
Watch this
Silicon Valley (HBO)
our co-founder, Matthias Allmendinger, recommends this series as it sparked the entrepreneurial spirit that brought Taxdoo to life.
Eat this
Sushi. Ok, just kidding. Although our developers do love a good Bento box, feel free to pick your favourite brain food for learning to code. Happy hacking doesn’t happen on an empty stomach!
We hope this list was helpful! It is, of course, by no means complete- what else would you recommend for budding developers