Welcome to

Evaluate Expression

Home / DDD / Package structure in a Domain Driven Design project

Package structure in a Domain Driven Design project

Embarking on a new application is a great time to push the boundaries of what we are comfortable with. Whilst a few chapters into Eric Evan’s book, Domain Driven Design, my team and I started defining where our classes will live inside the new project.

As a result I’ve designed a question flowchart as a tool for reference when it is not immediately obvious where a class should go. If the class in question fits into multiple locations, it is an indicator that the class is doing too much and not following the Single Responsibility Principle (SRP).


Click for the full image

DDD clean architecture

DDD clean architecture

Here we have the concept of Clean Architecture, complete with labelled areas which map to the flow chart of questions above it.

The inner most layer is the Domain. This layer is manipulated by its surrounding layers. The Domain layer has no knowledge or visibility “outwards”. Its purpose is to represent core business concepts.

Is this class used in a discussion with anyone other than a dev on the team? – Domain

If the answer to this question is Yes. It is a Domain object, representing a core concept defined by the business. This is assuming that the class satisfies no other question which points to another package: Application, UI or Infrastructure, which we’ll cover shortly.

A quick identification of a domain object is one which is discussed with analysts, support, etc.

Lets take the example of an internal mailing system, where employees of a company have In and Out trays. The trays would be defined with the aid of an analyst or other expert, their purpose, their capacity and so on. A clear domain concept, therefore the Tray class or classes resides in the Domain layer and therefore the Domain package.

Let’s look at logging as another example. Asking ourselves the same question, logging who sent a message to who, and when, would be talked over with a support team monitoring these interactions. The Logging class or classes which handle this concept  (not logging’s specific implementation or presentation but an interface or similar abstraction) should be placed in the Domain package. The term “logging” is used when discussing with support or anyone other than a dev on the team.

When asking ourselves this question we don’t have to exclude the developers on the team. When discussing a domain object in terms of a use-case with fellow developers, this is equally valid when focusing on a business or analytical point of view.

In our internal mail system, Trays may be discussed. An employee may ask an analyst: “Where does the mail I want to sent go?“, the answer being: “In the Out Tray on your desk“. The first question would suffice to place this Tray class in the Domain. A follow-up question of: “What is a Tray?” could be answered by referring to the Tray class, which acts as “living” documentation. Referring to its usages shows its flow through the use cases.

A more established company, say one which has been around since the days of physical internal mail (I have been told this is how people really communicated), would have the idea of trays ingrained already. It would be fair for a developer to decide that the above conversation would not occur, except maybe if a new team member joined. Perhaps a youngster unaware of how mail once worked. Here comes to play the second question, which maps to the Domain layer also.

Would the concept of this class exist if done manually? – Domain

Our mail example was once done manually and still is, though its use has somewhat changed. Other use cases may be more difficult to imagine being done manually. If in doubt, if you could drive a car, ride a horse or walk to a different building and provide a piece of information on paper, then the information itself would be a domain object (not what it is written on). Here we have a request.

For the online services I use, I would expect someone, at some point during the development of the service to have discussed what the log-in process looks like, the parameters the users must provide. In this example the log-in request is the domain object, whilst the process of logging-in is a use case. Which leads us on to the next set of questions in the flow chart which direct us to the Application package.

Does this class describe a use case? – Application

So our class isn’t a domain object, we answered No to both questions above. It doesn’t feature in the centre of our architecture, so it may have a place one layer outwards with visibility inwards of the domain. In other words, our classes responsibility may be to manipulate Domain objects, to describe the flow of one of our domain objects, how it is transitioned or modified. An example of this would be what a mail clerk, who’s role is to take mail from an Out Tray to and deliver it to a specified In Tray. This is a use case.

So far this is the only definition I have defined as a class befitting the Application layer.

Like the Application package, the UI package has only one question leading to it.

Is this class externally facing? – UI

The UI layer, having visibility of the Application layer, handles the presentation to anything external to our app. An example of a UI class would be the model of our mailing system’s envelopes. They may have different colours to signify importance. These coloured envelopes have significance to users, however the process of delivery could function with plain envelopes.

Now we move onto the Infrastructure package.

The Infrastructure layer, in my experience tends to grow quite quickly, holding specific implementations of interfaces placed in inner-more layers. To aid discoverability of classes I find a good approach is to mimic the package structure of the Domain, Application and UI within the Infrastructure package. Akin to how a test package mimics the src. Do this if you feel it is worthwhile.

Does this class use I/O? – Infrastructure

This class will have answered “No” to all previous questions, provided is follows SRP. Answering “Yes” to this question indicates that this class communicates with the outside world, it may read/write to files or a database, or communicate with other apps or the internet via http. In a Clean Architecture world the infrastructure surrounds the Domain, Application and UI layers. With visibility inwards. An example of an I/O class in our mailing example would be requests for more envelope stock to a application which handles office inventory.

Does this class use any third party packages? – Infrastructure

All libraries should have as little impact on the codebase in the event of an upgrade, replacement or removal. Separating these reliances from the inner layers prevents pain in handling changes to these third party dependencies. How much of your codebase would be affected if your favourite library was deprecated in favour or a new or different implementation? Or a bug was found? Following this project structure results in only the Infrastructure layer being affected. The Application layer would still manipulate the same Domain layer objects, with no knowledge of the infrastructure package surrounding it having changed.. The only difference being the business functionality defined in the Application would be utilised using a shiny new, bug-free (we hope) library.

Complete example

In our mailing example the mail clerk who picks up and delivers mail may keep an audit of who delivers to who. The format and data inside an audit record would be a Domain object. Why? I can picture a Business Analyst reminding me to store the date and time down to milliseconds in the AuditRecord class, as the business expects this functionality to be used very frequently. I’ve just used AuditRecord in a discussion with someone other than a dev on the team. This places the AuditRecord class in the Domain layer.

The process of taking a piece of mail from a Tray and delivering it to another Tray is defined in a use case. Flowing my class through the diagram I find that this class goes in the Application layer.

It is suggested that the audit records be written to a message queue instead of a database. No problem. Since I’m talking to an external service this code is in the Infrastructure layer. Changing the way I store my records has no affect on the rest of the functionality, as the use case in the Application layer makes calls to the underlying interface for persisting these records. The audit records are constructed, formatted and move through the use cases as they always did.

Below is the example of mail delivery as a java project. Showing what the package structure would look like. Subject to change as the project would develop.

Here is a view of our current structure.

Here is a view of our current structure.

Let me know what you think, try the flowchart out on your own project. If you have any suggestion or additions I’d love to hear them.

3 thoughts on “Package structure in a Domain Driven Design project”
  1. […] in applications: User Interface, Application, Domain and Infrastructure. One of my colleagues wrote a post about how to decide where to place a class. We decided that Infrastructure was a crosscutting […]

  2. Ryan T May 31, 2017on8:37 pm Reply

    So how do you determine whether something goes into Infrastructure and then in a sub package of domain?

    Surely if your working through this diagram top to bottom it would be the other way around where you would put the class under Domain and then under a sub package of Infrastructure.

    However does this then break your rule of ‘it’s doing too much’ if you justify these sub packages – surely this is implying it fits under more than one category? Also the understanding was that each of these layers should only be interacting with each other through adjacent layers – if you specify a domain sub package in the infrastructure package does this not imply you are having a direct interaction between infrastructure and domain classes?

    Maybe my understanding of your example is confused so I decided to work on a login example. Here is how I analysed it and broke it down.

    1. submit login request with credentials ->
    2. credentials verified against database ->
    3. login response returned -> (end)

    LoginServlet (infrastructure) – externally facing, receives HTTP requests from users.

    LoginRequest (domain) – something that you may talk to support about

    Credentials (domain) – users know about this.

    Verify credentials (usecase) – this some processing under the hood; people may know of it but I don’t feel that it is something that will come up in conversation (then again support could talk about this).

    Database (domain / infastructure) – support will know about this; again it is an external facing application.

    LoginResponse (Usecase/Infastructure) – So there will be some under the hood processing and an outward communication back to the client. The users won’t know about the abstract LoginResponse however the users will know about the implementation of response (e.g. success or fail) – so does this also belong some what under domain?

    I still don’t know if I have a clear understanding of UI but if it’s correct then you could potentially have LoginResponse in usecase/infastructure and then the implementations of SuccessResponse and FailureResponse under UI?

    Sorry for the long message.

    • Thomas Heslin June 1, 2017on2:54 pm Reply

      Hey Ryan.

      Thanks for reading and delving deep into the concept with your question.
      A quick disclaimer. I refreshed my memory of the post before answering and in the process updated the wording and readability. However the message I try to get across in the post hasn’t changed.

      To answer your question. I believe that your query around having the following sub-packages: “domain”, “application” and “ui” under the “infrastructure” package highlights that that isn’t a good structure for the infrastructure package. It would be better to follow the structure of the other packages. Therefore the “infrastructure” package, for the Mail Delivery example, should have the following sub-packages: “audit”, “tray”.

      I agree completely that the LoginServlet would be placed in infrastructure.

      As for LoginRequest I believe that this would have a class in infrastructure as I would see it being tied to a HTTP request which the LoginServlet would read from. It could be called HttpLoginRequest. A similar Login class would be placed in Domain which would contain the fields necessary to send a log-in request, you’ve called this Credentials. The HttpLoginRequest could be marshalled into a Credentials objects which is passed into LogInUseCase (in the application package). Here we have a small example of an infrastructure class having visibility of both the application and domain layers.

      I would agree in saying that SuccessResponse and FailureResponse would be in UI and would be constructed within a LoginResponse object which lives in infrastructure. In the event that a message to the user needed changing, only this layer would need to change for something small like a spelling fix.

      I will updated the package structure diagram as I agree completely that the infrastructure package shouldn’t model the rest of the layers inside it, but instead continue to model the business flows.

      I hope this helps in answering your question. I believe much of your question was highlighting an issue with the package structure which I’ve iterated upon since writing the post and that it needs updating.

Leave a Reply

Your email address will not be published. Required fields are marked *

Thanks for reading!

>> <<