How to Organise a Domain Driven Design Project?

I try to keep things very simple whenever I can, so usually something like this works for me:

Myapp.Domain – All domain specific classes share this namespace

Myapp.Data – Thin layer that abstracts the database from the domain.

Myapp.Application – All “support code”, logging, shared utility code, service consumers etc

Myapp.Web – The web UI

So classes will be for example:

  • Myapp.Domain.Sales.Order
  • Myapp.Domain.Sales.Customer
  • Myapp.Domain.Pricelist
  • Myapp.Data.OrderManager
  • Myapp.Data.CustomerManager
  • Myapp.Application.Utils
  • Myapp.Application.CacheTools

Etc.

The idea I try to keep in mind as I go along is that the “domain” namespace is what captures the actual logic of the application. So what goes there is what you can talk to the “domain experts” (The dudes who will be using the application) about.
If I am coding something because of something that they have mentioned, it should be in the domain namespace, and whenever I code something that they have not mentioned (like logging, tracing errors etc) it should NOT be in the domain namespace.

Because of this I am also wary about making too complicated object hierarchies. Ideally a somewhat simplified drawing of the domain model should be intuitively understandable by non-coders.

To this end I don’t normally start out by thinking about patterns in much detail. I try to model the domain as simple as I can get away with, following just standard object-oriented design guidelines. What needs to be an object? How are they related?

DDD in my mind is about handling complex software, but if your software is not itself very complex to begin with you could easily end up in a situation where the DDD way of doing things adds complexity rather than removes it.

Once you have a certain level of complexity in your model you will start to see how certain things should be organised, and then you will know which patterns to use, which classes are aggregates etc.

In my example, Myapp.Domain.Sales.Order would be an aggregate root in the sense that when it is instanced it will likely contain other objects, such as a customer object and collection of order lines, and you would only access the order lines for that particular order through the order object.

However, in order to keep things simple, I would not have a “master” object that only contains everything else and has no other purpose, so the order class will itself have values and properties that are useful in the application.

So I will reference things like:

Myapp.Domain.Sales.Order.TotalCost

Myapp.Domain.Sales.Order.OrderDate

Myapp.Domain.Sales.Order.Customer.PreferredInvoiceMethod

Myapp.Domain.Sales.Order.Customer.Address.Zip

etc.

Leave a Comment