Concepts

Domain Driven Design While Supermarket Shopping

One thing I’ve been interested in recently is Domain Driven Design – I’ve not really read into it in depth but from conversations with friends and colleagues I feel I’ve understood at least the high level concepts.

Essentially, the idea revolves around segregating code into 3 layers:

application

This contains the code that orchestrates the application from a very high level. In a system, the application layer should tell you all the different things that the code does. For example, in a Library system, the application layer would contain classes such as CheckoutBook, SearchForBook, etc. The application layer will call into the domain layer, which tells us how the system should do these things.

domain

This layer describes the different concepts the system needs. It contains all the business logic for the system. It is the code that is least likely to change, as business rules rarely do. The classes in this layer of a Library system would be things like Book, Index, Member, etc. The domain layer should not depend on anything outside of it, but many things will depend on it.

infrastructure

This layer purely looks at the adapters in and out of the core domain. This is the stuff that can change frequently (and should be able to change easily), and so nothing should depend on it! However, it will depend on the rest of the application. For a library system, the infrastructure layeer would be the objects that connect to the database, or the classes which take data from the user, e.g. from a form on the website.

Applying the above

In my very simple project, I used this structure to organise my code. This now gives me a context to refer back to when I read into DDD more deeply so I’ll understand it a little better.

The application layer contains one class – a ShoppingListGenerator. This class takes in a MealPlannerCreator and a Destination and essentially asks the MealPlan to create a list for itself and output it to the Destination. The MealPlannerCreator and Destination are interfaces, which meant that I could assume their behaviour (the MealPlannerCreator creates a meal plan, and the Destination outputs the shopping list), but I postponed the decision of how that would happen, or the implementation of the interfaces, until much later.

The domain layer contains two classes:

  • Meal
    POJO simply housing a list of ingredients and instructions for how to make the meal
  • MealPlan
    a simple list of Meals, and responsible for creating the shopping list for itself

With the domain classes, my focus was thinking about where the behaviour/logic should live. Should the Meal add itself to a MealPlan, or should the MealPlan add meals to itself? In fact, I initially had a separate ShoppingList class which took in the MealPlan and output a shopping list, but when I thought about it further I realised that extra class added no value. The MealPlan knew about its meals, why wouldn’t it make sense for it to just generate its own Shopping List?

The infrastructure layer contains the implementations of the two interfaces I mentioned in the application layer, and a Runner which will kick off the entire process. At the moment, I have a directory which represents my meal plan, and drop recipe files into it. These need to be in a certain format. The infrastructure layer of my project reads these files in, and converts them to a Meal domain object, and adds them to the MealPlanner. It also just prints the final shopping list to StdOut. This is pretty simplistic, so depending where I want to take this app and what the different use cases are, I can change these. I may want to send the ShoppingList straight to the supermarket website, for example. Having the interface in place makes switching out the implementations easier, if we do want to send the shopping list elsewhere, then only the implementation needs to change, and we’d pass this new implementation into the Runner.

I made each of these layers its own separate subproject, so that each could be deployed separately. Obviously, with such a small project it matters very little, but in a larger project this flexibility is invaluable – deployment is less risky and can be done much more frequently.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s