Domain-Driven Design, part 4 — Implementation

It is great to model something and now we have reached the point where we turn the model into the code. We will implement the model, no persistence, no input, only the most important part — the domain model. The implementation will be supported by tests and we will see how easy it is to test domain objects. We will also discuss the connection to the ubiquitous language and model and practical aspect of object encapsulation.

Model

Implementing the Domain Model

During the implementation, we might think of generalizing or coding for the future. We should resist these ideas, these thoughts, and implement only the model which we know. Implementing only the known behavior also makes the development quicker and the testing easier.

We should implement the model as accurate as possible. But sometimes we can find a problem which is difficult or impossible to implement in the programming language we use. Then we have to do decisions that also changes the model and these decisions should be spread over the team so everyone understands the changed model.

Read Information from Object

We have two reading use cases in the cart story. It is showing the cart detail and calculating the cart total price. When we show the cart to the user, we also show the total price and when we show the total price, we usually show the detail or information extracted from the detail. So we can join these two use cases into one — calculate the cart detail. This decision may be changed in the future as we consider what is more practical.

Getters Intermezzo

Instead of tones of getters, I try to use immutable structures to pass information through the system. These structures are based on use cases needs.

Data Transfer Object over Array

Data transfer objects avoid these problems. It takes some time to write them but once we have them, it is comfortable to use them. Data transfer objects are not classic objects, we do not expect behavior, they supplement immutable structures that are missing in the PHP.

The Implementation

Value objects

The simplest and most important value object is usually the Price. Price is never ever, never ever a float. I decided to use integer as it is the simplest meaningful representation. If we need decimal points, I would use a Decimal class from library or a string. Not float, never ever.

As we can see the value object may contain logic, eg. validation and computation logic. Such value object is easy to test and safe to use.

DTOs for the cart detail and item are trivial. We use them for the reading point of view on the Cart.

Entities

The Item is an internal entity for the Cart, never leaves the Cart itself and therefore can be any time refactored by our needs.

We have a dedicated value object for product identifier in the model, and it might be implemented by a class or a native type. I decided for a simple string private property as there are no needs for wrapping the product identifier into a class.

Cart entity, our aggregate root, is thanks to previous concepts manageable. Doesn’t expose internals like Item and therefore can be refactored to accomplish new features.

Exceptions

Testing

We should focus on testing aggregates. Internal structure of aggregates may change, but their behavior is less likely to change. We can consider aggregate tests as unit tests because an aggregate is definitely a unit. But we can test whatever we want to, if there is an interesting internal class, it is a great idea to test it as well.

I started with tests for the Cart itself. From simple to more complex scenarios. I express the scenario in the test name with expected behavior.

Test-Driven Development

Write tests first is great because we write tests by use cases so we know what do we expect. It may happen that we don’t know the answer to the test question. This situation leads us to deepen the domain knowledge before writing a single line of code.

And by the way, DDD is about the design while TDD is about the development process.

The cart implementation was written using TDD. Test first, then implementation and some refactoring: https://github.com/simara-svatopluk/cart/commits/TDD

Complete Code

TL;DR

Contact

Developer interested in Domain-Driven Design & Modeling

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store