In most projects, I use JavaScript or TypeScript as language and Node.js as backend runtime. Wherever useful, I apply selected parts of DDD. The architectural patterns I am most interested in are Event-driven Architecture, CQRS and Event Sourcing. For the frontend, I professionally work with various libraries, such as React or lit-html. Personally, I favor to use native technologies, such as Web Components.
Implementing Domain-Driven Design.torrent
By the end of this chapter, you will have gained a basic understanding of DDD and why you should strongly consider applying the tenets of DDD when architecting/implementing modern software applications, especially the more complex ones.
As we enter an age of encountering our most complex business problems, we need to embrace new ways of thinking, development philosophy, and an arsenal of techniques to iteratively evolve mature software solutions that will stand the test of time. We need better ways of communicating, analyzing problems, arriving at a collective understanding, creating and modeling abstractions, and then implementing and enhancing the solution.
Java stalwarts such as the Spring Framework and more recent innovations such as Spring Boot and Quarkus make it a no-brainer to create production-grade applications literally in a matter of minutes. Furthermore, frameworks such as Axon and Lagom, among others, make it relatively simple to implement advanced architecture patterns such are CQRS and event sourcing, which is very complementary to implementing DDD-based solutions.
Finally on our list of best domain-driven design books: JavaScript Domain-Driven Design. The book starts you off by teaching domain-driven concepts in JavaScript alongside working with UML diagrams.
In this article, we are going to learn about tactical domain-driven design. Tactical DDD is a set of design patterns and building blocks that you can use to design domain-driven systems. Even for projects that are not domain-driven, you can benefit from using some of the tactical DDD patterns.
Compared to strategic domain-driven design, tactical design is much more hands-on and closer to the actual code. Strategic design deals with abstract wholes whereas tactical design deals with classes and modules. The purpose of tactical design is to refine the domain model to a stage where it can be converted into working code.
This pattern certainly has its place but should be the exception rather than the norm in a domain-driven application. The reason is the following: A CRUD application is only about structuring, displaying and editing data. It normally does not support the underlying business process. When a user enters something into the system, changes something or removes something, there is a business reason behind that decision. Maybe the change is happening as a part of a larger business process? In a CRUD system, the reason for a change is lost and the business process is in the head of the user.
A true domain-driven user interface will be based on actions that are themselves part of the ubiquitous language (and thereby the domain model) and the business processes are built into the system as opposed to in the heads of the users. This, in turn, leads to a more robust, but arguably less flexible system than a pure CRUD application. I am going to illustrate this difference with a caricatural example:
The key takeaways are the following: Not all applications are suitable for domain-driven design, and a domain-driven application has not only a domain-driven backend but also a domain-driven user interface.
There are multiple ways of dealing with this one. The simplest solution is to defer invariant enforcement until the aggregate is saved, add setters for all properties and bind the entities to the form directly. I personally do not like this approach since I believe it is more data-driven than domain-driven. The risk is high that the entities degrade into anemic holders of data with the business logic ending up in a service layer (or worse, in the UI).
In a domain-driven system, domain events are an excellent way of achieving eventual consistency. Any system or module that needs to update itself when something happens in another module or system can subscribe to the domain events coming from that system:
When you work with domain-driven code, there will be times where you run into cases where a class does not really fit into the value object, entity or domain event mold. In my experience, this typically happens in the following cases:
I like to use interfaces at the top of the hierarchy since you can combine them in any way you like and even have enums implement them. Some of the interfaces are marker interfaces without any methods that are only used to indicate what role the implementing class plays in the domain model. In the diagram above, the classes and interfaces are the following:
This first encounter with tactical domain-driven design proved to me that you can benefit from it even if the project in all other aspects is not domain driven. My favorite DDD building block that I tend to use in all of the projects I participate in is the value object. It is easy to introduce and immediately makes the code easier to read and understand since it brings context to your attributes. The immutability also tends to make complex things simpler.
Like other software design patterns, tactical domain-driven design offers solutions to a set of problems that you typically run into, especially when building enterprise software. The more tools you have at your disposal, the easier it will be for you to tackle the problems you inevitably run into in your career as a software developer.
In the next article in this series, we are going to learn what the hexagonal architecture is, how it plays nicely together with domain-driven design and how the outside world can interact with the domain model in a controlled and extendable manner.
Implementing Domain-Driven Design presents a top-down approach to understanding domain-driven design (DDD) in a way that fluently connects strategic patterns to fundamental tactical programming tools. Vaughn Vernon couples guided approaches to implementation with modern architectures, highlighting the importance and value of focusing on the business domain while balancing technical considerations.
The picture I got was a middle managers look on DDD: it's another practice that involves moving stickers on the wall until developers get at least some understanding of what the business wants. The book went into very little detail explaining the building blocks of a software system designed in domain-driven manner. And what it seems like no detail on how actual domain concepts should map into the software.
To me this book felt like the actual "distilled" version of DDD. Still it only paints a picture with the theory on DDD. I felt like I still required more practical examples to really finish digesting all the information I recieved. And there is no better way to do this than to look at a real project template built with DDD and to read a few articles with different opinions and points of view on implementing DDD.
For this there is an absolutely brilliant repository by Sairyss on GitHub. domain-driven-hexagon properly implements hexagonal architecture with some of more advanced practices in TypeScript and Nest.js. Most aspects of DDD are explained in a simple language with an example in the code and links to relevant articles. Despite the fact that it is written in TypeScript you will still largely benefit from the information displayed in the repository and most likely interpret code examples well enough even if you are not familiar with JavaScript.
So if you as a developer find yourself interested in Domain-Driven Design but not invested enough to read Eric Evans' blue book you should start with "Domain-Driven Design Quickly" by Abel Avram and Floyd Marinescu and then see some practical examples in domain-driven-hexagon to really build an understanding of DDD. I hope this article saved you from investing your precious time into an unworthy book and paved a better path of getting to know DDD.
The most common challenge when implementing Domain-Driven Design is finding subject matter experts to collaborate with on a project that is outside of their typical realm. Developers and domain experts need to have enough overlapping knowledge in order to bring a successful product to life.
Domain-driven design (DDD) advocates modeling based on the reality of business as relevant to your use cases. In the context of building applications, DDD talks about problems as domains. It describes independent problem areas as Bounded Contexts (each Bounded Context correlates to a microservice), and emphasizes a common language to talk about these problems. It also suggests many technical concepts and patterns, like domain entities with rich models (no anemic-domain model), value objects, aggregates, and aggregate root (or root entity) rules to support the internal implementation. This section introduces the design and implementation of those internal patterns.
Sometimes these DDD technical rules and patterns are perceived as obstacles that have a steep learning curve for implementing DDD approaches. But the important part is not the patterns themselves, but organizing the code so it is aligned to the business problems, and using the same business terms (ubiquitous language). In addition, DDD approaches should be applied only if you are implementing complex microservices with significant business rules. Simpler responsibilities, like a CRUD service, can be managed with simpler approaches.
A microservice's application layer in .NET is commonly coded as an ASP.NET Core Web API project. The project implements the microservice's interaction, remote network access, and the external Web APIs used from the UI or client apps. It includes queries if using a CQRS approach, commands accepted by the microservice, and even the event-driven communication between microservices (integration events). The ASP.NET Core Web API that represents the application layer must not contain business rules or domain knowledge (especially domain rules for transactions or updates); these should be owned by the domain model class library. The application layer must only coordinate tasks and must not hold or define any domain state (domain model). It delegates the execution of business rules to the domain model classes themselves (aggregate roots and domain entities), which will ultimately update the data within those domain entities. 2ff7e9595c
Comments