Domain-Driven Design



Naresh Bhatia

Naresh is a software architect in the Boston area. He started Archfirst after realizing that technologists spend too much time fighting technologies instead of solving real-world problems. Archfirst is a place where we can all learn best practices and techniques to make software development easier.


JoinJS – An Alternative to Complex ORMs 10th August, 2015

MyBatis vs. Other ORMs 01st July, 2015

Domain-Driven Design

Posted on .

Layered Architecture

Now let’s zoom into the Bullsfirst OMS and discuss DDD as it relates to a single bounded context. The first concept we’ll talk about is called Layered Architecture.

In general, to create a full-fledged software application we will have to implement a lot more than just the domain model – user interface, database access and external service adapters are just a few examples. If we start implementing these elements without much thought to their organization, we will soon have a ball of mud, with business logic intermingled with UI and data access code. This is bad because even a minor enhancement will require careful tracing of the entire application.

Creating applications that can handle very complex tasks requires separation of concerns. This is where the concept of a Layered Architecture comes in. The basic idea is to structure an application into four conceptual layers:

Layered Architecture

How does Bullsfirst OMS implement these layers? Here’s a high level overview

Bullsfirst OMS Layered Architecture

User Interface Layer

The OMS does not have a user interface. However, it exposes four services that allow other applications to interact with it:

  1. SecurityWebService provides user registration and authentication for front-end clients
  2. TradingWebService provides trading related functions such as order and account management
  3. MarketPriceListener listens to the exchange for market price change messages
  4. ExchangeMessageListener listens to the exchange for order status change messages

In the context of layered architecture, these four services provide the “user interface” for external applications – they translate incoming requests to method calls for the application layer and in the case of web services, translate the return values to SOAP responses. In addition, this layer is also responsible for transaction management by starting transactions for every service call.

Application Layer

The application layer is responsible for creation and retrieval of domain objects, as well as calling their methods to satisfy user commands. The Bullsfirst OMS application layer consists of three services: SecurityService, MarketDataService and AccountService. Each service receives commands and queries from the layer above and in turn interacts with the domain layer to perform requested actions. Let’s look at the following AccountService method as an example:

public void cancelOrder(String username, Long orderId) {

    // Check authorization on account
    Order order = brokerageAccountRepository.findOrder(orderId);

    // Cancel order

Note that the parameters to the method (username and orderId) are value objects. That’s because the layer above (the User Interface layer) does not have domain objects – all it has are some values sent by the client. Looking inside the method you will find that the value objects are used to fetch the real Order and call its pendingCancel method. You will also notice that the method has access to the brokerageAccountRepository which is part of the infrastructure layer. As we’ve now seen, the Application layer coordinates application activity by retrieving domain objects and calling their methods.

Domain Layer

We will look at this layer in more detail in the next section.

Infrastructure Layer

This layer consists of:

  • User and Account repositories for managing users and accounts in the database
  • Adapters for accessing reference data and market data from the exchange
  • TradingService proxy for sending trading commands to the exchange

Pages: 1 2 3 4 5 6 7 8


Naresh Bhatia

Naresh is a software architect in the Boston area. He started Archfirst after realizing that technologists spend too much time fighting technologies instead of solving real-world problems. Archfirst is a place where we can all learn best practices and techniques to make software development easier.

  • user

    AUTHOR Ilya

    Posted on 6:56 am March 25, 2015.

    > BrokerageAccount is the aggregate root – it “owns” Orders or Transactions.

    But the collections of orders/transactions will grow unbounded eventually. What will you do in that case?

  • user

    AUTHOR Naresh Bhatia

    Posted on 7:30 am March 25, 2015.

    Good point! To take care of this situation, I would break Orders and Transactions into seperate aggregate roots. This is not to take care of the read situation, but more of the write situation. A write must be transactional and must keep the aggregate consistent. With too many Orders and Transactions in the Account aggregate, we will run into version conflicts. This can be easily avoided by breaking Orders and Transactions into their own aggregate roots. In case of reads, we can always join as many entities we want and limit the results, so that’s not an issue – this follows from the Command Query Separation principle. Hope this clarifies.

  • user

    AUTHOR Matt

    Posted on 4:14 am March 26, 2015.

    I am curious how this would fit in with Micro Services?

  • user

    AUTHOR Naresh Bhatia

    Posted on 10:58 pm March 29, 2015.

    Good question, Matt. I would say that DDD is very compatible with micro services concepts. The micro services architecture style recommends breaking a large monolithic application into smaller services that communicate via lightweight mechanisms such as RESTful interfaces. This is analogous to the DDD concept of breaking a large domain into smaller sub-domains and drawing explicit boundaries around them, known as “bounded contexts”. Within each bounded context the domain terms have specific meaning. However they could have slightly different meanings across bounded concepts. For example, the term “Customer” may have a different set of attributes in the Order system vs. the Customer Support system. The analog of this in the micro services approach would be to break a large e-Commerce system into smaller micro services, an Order service to manage orders and a Customer Support service to manage support requests.

    For a detailed treatment of bounded contexts, you can refer to “Implementing Domain-Driven Design” by Vaughn Vernon (listed at the end of this post).

  • user

    AUTHOR Sridhar

    Posted on 12:17 pm April 7, 2015.

    Great work and love reading through the documentation.
    To understand your domain model better do we have a class diagram that we can refer to? Of course I can download the source code and view it from eclipse but wonder if you have already prepared one.

  • user

    AUTHOR Naresh Bhatia

    Posted on 1:16 am April 8, 2015.

    Sridhar, glad to know that you liked the work. I do have the full domain models for the OMS and the Exchange, but didn’t get the time to publish them yet. Will try to do it over the weekend.

  • user

    AUTHOR Nico Nel

    Posted on 2:38 am April 12, 2016.

    For someone that have been “aware” of DDD for a very long time and “thought” he know a good bit about it, but only recently really started digging into the various aspect of design (software, ux, etc) this is the best article I’ve read on the topic (and I’ve read a LOT lately while waiting for my blue book)
    Please share this, it’s really easy to follow for all levels of expertise and every stakeholder should gain this kind of understanding of the topic.

  • user

    AUTHOR Vijay Gupta

    Posted on 1:07 pm September 19, 2016.

    This is really a great article to understand the DDD. I was struggling to understand the DDD and read few online references but was not satisfied with my learning. This article provide complete picture of DDD in very concise, to the point manner.

    Many Thanks.

  • Leave a Reply

    View Comments (9) ...