OneTrueError - Automated exception handling

Why Domain Driven Design (DDD) is so great

This article aims to describe why I think that DDD aids you tremendously in creating robust and flexible applications.

Today we got several cool frameworks and libraries that we can use. ORMs, WCF, ServiceStack, SignalR, WebApi, IoC etc etc. Just thinking of all can make any serious developer go crazy of joy.

All those tools is so great that we almost can’t wait to use them. Here is a typical conversation with a customer:

Customer: I want to create a forum
You: Oohh ohh, wait! Yeah. I could use Sharepoint. No no. It’s so bloated and slow. oh oh! I got it. wait! SignalR+WebApi and KnockoutJS. So cool! Let’s do that!
Customer: But but. We just need a basic forum.
You: Shut it! Me wanna do SignalR

And so on. My point is that it’s so easy to forget that we should focus on solving a problem for the customer and not on which technology we should use.

The role of the database

A couple of years ago we said that we developed database driven applications. Erhm. Maybe a bit more than a couple of years ago, I’m getting old. It was the shit. If you said to a DBA that you have normalized the DB according to 3NF he would probably have gotten an orgasm. Today the whole look of applications as data driven has gotten so widely spread that most applications are today modeled according to the database model and it’s relations.

The problem with that is that the database forces you to couple your application thanks to all DB relations. It also forces you to model the business layer after the DB model. Especially today if you are using an OR/M.

Database centric applications usually lead to CRUD influenced UIs. That is that you show a big fat screen saying “Go ahead an edit the fields you want. I trust that you have full knowledge of which combinations of changes that are valid given the current state of the object“. That’s also a huge problem. Business rules are hard to test since it’s the user that enforces them. It will undoubtedly lead to that you have to go into the database and fix things: “Hey, it’s me the customer. Order XX have the field Y set to Z. That shouldn’t be possible, can you fix that?”. Those kind of bugs are very hard to locate and therefore fix.

Enter DDD

Domain driven design is all about understanding the problem that the customer is trying to solve. During the initial phase you don’t even think about architecture or programming. Your prime goal is to understand the business, all terms that customer uses and how he models the domain. The customer is in fact the architect. He might not draw everything, but he guides you and tell you how everything should be modeled.

So what you do is sitting down with the customer and discuss each business case. You listen to him and draw something which the customer can understand (read: NO UML). Then you use all of those sketches and notes to build the model = code.

Coding

In DDD you shouldn’t care about persistence, UIs or anything else. You just code vanilla classes which represents the model that the customer described. And since you just have POCOs it’s incredibly easy to test everything. I highly recommend that you try to use a TDD inspired approach together with DDD.

In DDD every class in the model should always be in a consistent state (i.e. being valid). That means that you’ll have no (or a very few) public setters in your classes. Instead you have methods in each class that represents an action that the customer described. If one or more classes (entities) are involved in an action you’ll create a new class which coordinates the work for the both entities (that class is called a service). Read this if you would like know more about how private setters affect your application.

Using methods also means that we can’t have CRUD UIs but instead have to code task based UIs. It’s hard when you come from CRUD type of applications, but the task based UI tends to become a lot less cluttered when you get used to coding them.

Finally you have a nice domain model where all business rules are encapsulated in your classes and hopefully tested with unit tests. The likelihood of bugs like the ones I described for CRUD applications are a lot less.

The event

Each time something happens (something that the the customer described) in a DDD application there is an event generated. These events allow you to create a more loosely coupled application.

For instance when a new users registered an UserRegistered event is generated. It can be subscribed to by an NotifyAdminOfNewUser handler or a SendAnWelcomeEmail handler. Or both. The point is that any part of the system can handle any event. You can even create a module/plugin based application where the plugins handle each others events. How cool isn’t that?

Persistence

Most people which have a hard time with DDD have it because they start at the wrong end. They start with the database and then try to fit the domain model according to the db model. That’s the wrong approach (which there of course are solutions for, but that’s out of the scope of this article).

It’s much better to start with the domain model as it’s seldom that you know all business requirements from start. If you start with the domain model you can test drive the model with your customer/client. Go through different scenarios and ask him/her what you think. By doing so you’ll find requirements that wasn’t know from start. Once completed you can build the database design. As you know got a much better understand of how and when the persistence layer is going to be used. As such, you know where you have to add relations, where you should use third normal form (3NF) and where you can but the child aggregates as a JSON string in a root aggregate column.

The repositories are used to abstract away all that knowledge. The calling layer should not have to be aware of if you are using table relations or have serialized child aggregates as JSON. That why the repositories are called an abstraction layer. And that’s where many developers get it wrong and thing that their OR/M is an abstraction, when it in reality just mirrors the database design.

This new point of view also allows us to separate the data model into several data sources if we would like (since the data is decoupled in your domain model). We do not have to use one database normalized to 3NF. We can use one big denormalized database (disk space is so expensive, isn’t it?) or even web services in our repositories.

The UI

Now that we got some data and a domain model it’s time to start create the UI. Again we model it after the domain model. Since it’s dictated after all methods that we got in your domain model it’s quite easy to know how we should structure it.

Outsourcing?

When you’ve modeled the domain model it’s fully possible to let others take care of the persistence and the UI. Just send them the domain model. In fact, you could even let two different teams take care of it. One that builds and optimizes the data layer (caching, db etc), and one that builds the UI.

Let the original team (the domain experts) continue with the next project (or iteration if you’re agile).

Conclusion

That’s why I love DDD ;)

This entry was posted in Architecture, CodeProject and tagged . Bookmark the permalink.
  • Daniel

    Nice article! I am new to DDD and TDD and I would appreciate if you can guide me in right direction ?

    • http://www.gauffin.org jgauffin

      The book by Mr Evans that describes DDD: http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215

      A DDD dedicated site with some articles (PDFs): http://domaindrivendesign.org/

      TDD (Test driven development) is quite easy to understand, but hard to master: Simply create the unit tests first.

      For instance start by writing a unit test :

      install xunit “install-package xunit” using nuget, then write:

      public class UserReposTests()
      {
          public void TestCreate()
          {
              var repos = new UserRepository();
              
              var user = repos.Create("Jonas", "Gauffin");
      
              Assert.NotNull(user);
          }
      }
      

      Then create the actual userrepository class and make the test succeed. Next create a new testmethod which tests another method in the subject class.

      TDD introduction: http://www.agiledata.org/essays/tdd.html

      • Daniel

        Thank you! I will check the links you provided.

  • Johan

    Nice article, very interesting! :)

    I’ll have to do some labs to try it out I think :)

  • Karl

    The Events section really sidetracked me from the purpose of your post. Events are just one of multiple ways to link disparate domains. Event systems, for example, are often poor at handling well ordered processes, requiring either complex event handlers or a complex event system. Events are also a poor solution when you require transactional and dependent interactions or completion/failure notification.

    It seems to me that DDD is more dependent on well-defined APIs and interface points, rather than an event system. Whether you use those APIs with an event system or dependency injection or messaging or procedural calls seems outside of the scope of DDD’s core philosophy.

    DDD is really just a method for breaking down large projects into domain scoped sub-projects so they can be split among teams and/or iterations, with the side-effect of increasing maintainability with deliberate modularity.

  • http://www.beemobile.se Piotr Kundu

    Great stuff. I would love to have you guestblogging on our site http://www.beemobile.se. A lot of times the technical solutions are overly complacated and do not address customers need as much as the address the developers urge to learn new stuff.

  • eriklott

    “We model our database after domain model. And this time the relations in the database isn’t that important since the database is just storage now”

    Face palm. Please don’t model your database after your domain model.

    • http://blog.gauffin.org/ jgauffin

      Thanks for your mature comment. You might at least want to explain why you think that’s a bad idea.

      • eriklott

        Tongue in cheek comment – no insult intended.

        If a developer happens to be using a relational database for their application, some of your advice could get them into trouble.

        The database should not be modelled after the domain; it should be modelled after the data. Relations in the database are of the utmost importance… it is a relational database. Much like your app, a relational database should be modelled in an application ignorant fashion.

        Model your app and your database separately according to their individual and independent requirements. Let your app’s repository and DA layer provide the mapping between the two. If you have to favour one over the other, FAVOR the data! It will outlive your app 10 fold.

        • http://blog.gauffin.org/ jgauffin

          I do not agree. I’ve seen a lot of poorly designed applications just because they modeled the database first and then tried to fit the domain model after the database design.

          The problem with is really that the requirements are rarely known when the application development is started. If the developer begins with the domain model they can develop it, show it to the customer and refactor it. Hence when they start building the database they can do it properly since most of the requirements are known.

          With that I mean that relations may not required everywhere, nor would 3NF. Sometimes it’s much better to put child aggregates serialized as JSON or similar in a column in the root aggregate. It all depends on how the data will be used.

          Do note that I’m not talking about a single aggregate when I say domain model. i.e. I’m not saying that there should be a one-to-one mapping between each entity and table. I’m talking about all classes in the domain model.

          Just as you say it’s the repositories responsibility to map the entities to the database.

          As for the data outliving the application I’ve never experienced that in my 20 years as a developer. At least not without modifications being done to the current database design. So if the DB is going through changes, there’s really no difference from what I’m recommending.

          • eriklott

            “We model our database after domain model”.

            I was reading this as ‘We model our database’s structure to match our domain model structure’, rather than temporal ‘after’. My bad.

            Yup, I agree: domain first, datastore second.

          • admin

            I’ve rewritten that part now. Thanks for the feedback. Much appreciated.