When Domain Driven Design (DDD) and Behaviour Driven Development (BDD) were chosen to be used for the implementation of a Wallet Service, the two concepts were completely new to me. As I spent the next week going through articles and blogs, basically spending a lot of time on Google, on what exactly these two are it was a bit challenging to understand both of them, let alone combine them for a better development process. But as the week progressed, I focused solely on understanding what each of them are individually first. You can find an overview of BDD here. Here, we are going to look at what DDD is on it’s own and how it blends with BDD.

Domain Driven Design (DDD)

To understand DDD, we need to understand a few of its terminologies.

  1. The first one is “domain” which is crucial (since it is part of the name, “Domain” Driven Design, duh!) . Wikipedia defines it as “A sphere of knowledge, influence, or activity. The subject area to which the user applies a program is the domain of the software”. In layman’s terms, domain is what the system is being built for.

  2. Next comes “domain model”. But what is model in the first place!? Model is a solution to the problem at hand. It is a point of focus for your knowledge which is represented in a structured way. So combining domain and model gives you a domain model that represents your knowledge of the domain in either visual fashion or in the form of code.

  3. Finally, a new language (Not an another one!) called “ubiquitous language”. When developing something, it is always best to avoid translation to avoid confusion or loss of knowledge during transfer. This is where ubiquitous language comes in. It is a set of terms used by everyone involved in building the system. This basically means that each domain or domain model represents the same to PMs, Devs, QA and any other stakeholder.

Often, it is said that DDD is object orientation done right but DDD is a lot more than just object orientation. DDD also deals with the challenges of understanding a problem space and the even bigger challenge of communicating that understanding. Just like the title of the Eric Evans’ book, DDD tackles the business problem at its heart.

Example Time!

So let’s take the example of the Wallet Service to understand all of this. Since the aim of the service/system is to act as a virtual wallet that hold virtual currency, the “wallet” becomes the domain or the “business problem” at hand. A simple representation of the domain model for the wallet would thus look something like this:

public class Wallet
{
  public string Id { get; set; }
  public decimal Amount { get; set; }
}

If you think about the example for a minute, I’m pretty sure you are starting to the get the idea about how DDD works. You basically define your domain and create a domain model to represent its state. You then perform actions on these models to represent changes of state in your system. There are a few more things that are to be considered in DDD, but you this should give you a gist of it now. This should set you on the path to understand and create your own domains with their respective models as you start learning more.

How does DDD work with BDD?

The approach for most BDD practitioners is to test the behaviour of the system from end to end. DDD simplifies this. Testing just your domain using BDD three major advantages:

  1. Your core business logic is always tested
  2. The number of steps in your tests reduces
  3. Your domain testing is decoupled from your presentation/application testing

Let’s go back to the wallet to understand this better. You are now not dependent on your presentation (generally the frontend/view) or the application (service layer) to get to your core business logic (domain layer). This makes it easier to test the core functionality of the system on its own. A sample scenario would look something like this

Scenario: Add funds to wallet from a payment gateway
    Given a transaction with business profile Id and transaction data
    When the transaction record is inserted into the Db
    Then a record for the transaction should be as
    | Id | ReferenceId | Amount     |
    | 1  | s3a2l2t     | 200.250000 |

With DDD, you simply implement it as

AddFunds(walletId, amount)
{
  GetWallet(walletId);
  AddFunds(amount);
  GetTransactions(walletId);
}

You need not concern yourself with how the “walletId” is obtained or who it belongs to. Your objective with DDD is to check that if certain funds are added to a wallet, the system should just do that; nothing more, nothing less. Thus your scope of test is also limited and accurate to just that.

With this approach the UI stops being the centre of an application. Instead it becomes just a controller for the domain. When the UI is added only scenarios critical to the UI and the application are needed since the domain has already been proven to work.

Where can you learn more about DDD?

Stay tuned for a continuation on how you can take DDD a step further by using Event Sourcing to handle actions on domain and domain models.