Ok, let me first explain what it is all about.
Eric Evans describes Domain Driven Design in his book Domain-Driven Design: Tackling Complexity in the Heart of Software . He says that the most complex part of software is the business or the domain logic. Software is written to support a business process and the logic that is needed to support this process is called the domain logic. Once this logic is implemented correctly, it is not likely to change very often.
The user interface is more likely to change, especially a web interface like the web site for online banking, therefore it is recommended to separate the domain logic from the user interface and other infrastructure logic (like database or file persistence, logging, etc.).
In DDD the domain logic is designed using a language that is known by the domain experts, and in the implementation (the domain) we will see objects, fields and methods that are using the same language. (Evans calls this the Ubiquitous language) This means the developers and all other people who are working with the domain should know this language.
Ok this can be very abstract, I know, so I will give you an example. For this example I use something everyone is familiar with, a Bank. A bank has clients. These clients have accounts and can do transactions between accounts. The words in bold are important for the bank, without these words/things a bank doesn't exist. Therefore we will add them to out Ubiquitous language. In the domain design we can see the following diagram:
(you can see that I didn't talk about all the details of the classes you see here, but I think they are obvious...)
Now we have the design, we can implement it in any language we want, but it is important that the ubiquitous language is used in the domain itself.
Domain Driven Design is not only about the language. Separating the domain from technical things like user interface is even more important. The complexity of the software is the domain not how we show the domain, or how we implement the persistent. So we should be able to decouple the domain completely from all other things and to test it with some kind of automatic testing framework. (This is needed to get the proof that the implementation of the domain works correctly, but that will be another topic.)
The question is: How do we decouple the domain from the rest of the application? There are a couple of different possibilities here:
- Layered Architecture
- Sunflower Architecture
In a Layered Architecture there are layers. A layer can communicate with all the layers bellow itself by using method calls. To communicate with layers on top of itself, a layer should use some kind of event based system. (See image)
In the diagram you can see that the domain is on top of the infrastructure/platform layer, which means it depends on this layer and we can't easily change from platform. An example: When we use the Win32-API for events (messages) we can't use the domain on other systems than Windows. So we can't easily deploy the domain on a Linux machine and the Testing Framework should understand the same platform/infrastructure. Other technical stuff like the user interface are build on top of the domain layer.
The sunflower architecture I like the most. It looks like the following image.
The domain is completely decoupled from everything and around the domain we see the other technical stuff like logging, persistence, etc. With this model it is even possible to use a product from an other vendor and couple it via adapters to the domain. (An adapter is just a class that translates message to and from the domain.) This way the domain doesn't have to know anything about the infrastructure layer and can be tested without any problems.
"Ok, we have those nice architectures, but how to implement that in my projects?" you may think. I would say make a library for every single layer or service. So a library for the domain, a library for the GUI and for the persistence. This way the code is physically decoupled as well, which makes it even easier to test and to replace implementations. Even updating an existing service is easy because the file is not cluttered with other things that has nothing to do with the problem.
This is also in line with the OO-rule "Single responsibility". Which tells that every single object (or module, or service or library) should have one task to do and it should do that well.
Besides a ubiquitous language, Evans also describes a lot of design patterns that can be used in domain driven design. I will give you a list with patterns, but I will describe them in some other posts, because I still want to describe where the domain could be placed in the application. First the patterns list:
- Value objects
Some of these I will combine in one post, but others I need to take separately.
I realize that I give a very short introduction of Domain Driven Design. For more information you can go to some of the following websites:
- domaindrivendesign.org The main website of Domain Driven Design.
- infoq.com - contains a free book called Domain Driven Design Quicly, which is basically a summary of the book, as well as a lot of other information about programming techniques and technology.
- codebetter.com - collection of blogs that discuss different techniques.