JavaScript Domain-Driven Design

By Philipp Fehre
    What do you get with a Packt Subscription?

  • Instant access to this title and 7,500+ eBooks & Videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Free Chapter
    A Typical JavaScript Project
About this book

JavaScript backs some of the most advanced applications. It is time to adapt modern software development practices from JavaScript to model complex business needs.

JavaScript Domain-Driven Design allows you to leverage your JavaScript skills to create advanced applications. You'll start with learning domain-driven concepts and working with UML diagrams. You'll follow this up with how to set up your projects and utilize the TDD tools. Different objects and prototypes will help you create model for your business process and see how DDD develops common language for developers and domain experts. Context map will help you manage interactions in a system. By the end of the book, you will learn to use other design patterns such as DSLs to extend DDD with object-oriented design base, and then get an insight into how to select the right scenarios to implement DDD.

Publication date:
July 2015
Publisher
Packt
Pages
206
ISBN
9781784394325

 

Chapter 1. A Typical JavaScript Project

Welcome to domain-driven design in JavaScript. In this book, we will explore a practical approach to developing software with advanced business logic. There are many strategies to keep development flowing and the code and thoughts organized, there are frameworks building on conventions, there are different software paradigms such as object orientation and functional programming, or methodologies such as test-driven development. All these pieces solve problems, and are like tools in a toolbox to help manage growing complexity in software, but they also mean that today when starting something new, there are loads of decisions to make even before we get started at all. Do we want to develop a single-page application, do we want to develop following the standards of a framework closely or do we want to set our own? These kinds of decisions are important, but they also largely depend on the context of the application, and in most cases the best answer to the questions is: it depends.

So, how do we really start? Do we really even know what our problem is, and, if we understand it, does this understanding match that of others? Developers are very seldom the domain experts on a given topic. Therefore, the development process needs input from outside through experts of the business domain when it comes to specifying the behavior a system should have. Of course, this is not only true for a completely new project developed from the ground up, but also can be applied to any new feature added during development of to an application or product. So, even if your project is well on its way already, there will come a time when a new feature just seems to bog the whole thing down and, at this stage, you may want to think about alternative ways to go about approaching this new piece of functionality.

Domain-driven design gives us another useful piece to play with, especially to solve the need to interact with other developers, business experts, and product owners. As in the modern era, JavaScript becomes a more and more persuasive choice to build projects in and, in many cases like browser-based web applications, it actually is the only viable choice. Today, the need to design software with JavaScript is more pressing than ever. In the past, the issues of a more involved software design were focused on either backend or client application development, with the rise of JavaScript as a language to develop complete systems in, this has changed. The development of a JavaScript client in the browser is a complex part of developing the application as a whole, and so is the development of server-side JavaScript applications with the rise of Node.js. In modern development, JavaScript plays a major role and therefore needs to receive the same amount of attention in development practices and processes as other languages and frameworks have in the past. A browser based client-side application often holds the same amount, or even more logic, than the backend. With this change, a lot of new problems and solutions have arisen, the first being the movement toward better encapsulation and modularization of JavaScript projects. New frameworks have arisen and established themselves as the bases for many projects. Last but not least, JavaScript made the jump from being the language in the browser to move more and more to the server side, by means of Node.js or as the query language of choice in some NoSQL databases. Let me take you on a tour of developing a piece of software, taking you through the stages of creating an application from start to finish using the concepts domain-driven design introduced and how they can be interpreted and applied.

In this chapter, you will cover:

  • The core idea of domain-driven design

  • Our business scenario—managing an orc dungeon

  • Tracking the business logic

  • Understanding the core problem and selecting the right solution

  • Learning what domain-driven design is

 

The core idea of domain-driven design


There are many software development methodologies around, all with pros and cons but all also have a core idea, which is to be applied and understood to get the methodology right. For a domain-driven design, the core lies in the realization that since we are not the experts in the domain the software is placed in, we need to gather input from other people who are experts. This realization means that we need to optimize our development process to gather and incorporate this input.

So, what does this mean for JavaScript? When thinking about a browser application to expose a certain functionality to a consumer, we need to think about many things, for example:

  • How does the user expect the application to behave in the browser?

  • How does the business workflow work?

  • What does the user know about the workflow?

These three questions already involve three different types of experts: a person skilled in user experience can help with the first query, a business domain expert can address the second query, and a third person can research the target audience and provide input on the last query. Bringing all of this together is the goal we are trying to achieve.

While the different types of people matter, the core idea is that the process of getting them involved is always the same. We provide a common way to talk about the process and establish a quick feedback loop for them to review. In JavaScript, this can be easier than in most other languages due to the nature of it being run in a browser, readily available to be modified and prototyped with; an advantage Java Enterprise Applications can only dream of. We can work closely with the user experience designer adjusting the expected interface and at the same time change the workflow dynamically to suit our business needs, first on the frontend in the browser and later moving the knowledge out of the prototype to the backend, if necessary.

 

Managing an orc dungeon


When talking about domain-driven design, it is often stated in the context of having complex business logic to deal with. In fact, most software development practices are not really useful when dealing with a very small, cut-out problem. Like with every tool, you need to be clear when it is the right time to use it. So, what does really fall in to the realm of complex business logic? It means that the software has to describe a real-world scenario, which normally involves human thinking and interaction.

Writing software that deals with decisions, which 90 per cent of the time go a certain way and ten per cent of the time it's some other way, is notoriously hard, especially when explaining it to people not familiar with software. These kind of decisions are the core of many business problems, but even though this is an interesting problem to solve, following how the next accounting software is developed does not make an interesting read. With this in mind, I would like to introduce you to the problem we are trying to solve, that is, managing a dungeon.

An orc

Inside the dungeon

Running an orc dungeon seems pretty simple from the outside, but managing it without getting killed is actually rather complicated. For this reason, we are contacted by an orc master who struggles with keeping his dungeon running smoothly. When we arrive at the dungeon, he explains to us how it actually works and what factors come into play.

Tip

Even greenfield projects often have some status quo that work. This is important to keep in mind since it means that we don't have to come up with the feature set, but match the feature set of the current reality.

Many outside factors play a role and the dungeon is not as independent at it would like to be. After all, it is part of the orc kingdom, and the king demands that his dungeons make him money. However, money is just part of the deal. How does it actually make money? The prisoners need to mine gold and to do that there needs to be a certain amount of prisoners in the dungeon that need to be kept. The way an orc kingdom is run also results in the constant arrival of new prisoners, new captures from war, those who couldn't afford their taxes, and so on. There always needs to be room for new prisoners. The good thing is that every dungeon is interconnected, and to achieve its goals it can rely on others by requesting a prisoner transfer to either fill up free cells or get rid of overflowing prisoners in its cells. These options allow the dungeon masters to keep a close watch on prisoners being kept and the amount of cell space available. Sending off prisoners into other dungeons as needed and requesting new ones from other dungeons, in case there is too much free cell space available, keeps the mining workforce at an optimal level for maximizing the profit, while at the same time being ready to accommodate the eventual arrival of a high value inmate sent directly to the dungeon. So far, the explanation is sound, but let's dig a little deeper and see what is going on.

Managing incoming prisoners

Prisoners can arrive for a couple of reasons, such as if a dungeon is overflowing and decides to transfer some of its inmates to a dungeon with free cells and, unless they flee on the way, they will eventually arrive at our dungeon sooner or later. Another source of prisoners is the ever expanding orc kingdom itself. The orcs will constantly enslave new folk and telling our king, "Sorry we don't have room", is not a valid option, it might actually result in us being one of the new prisoners. Looking at this, our dungeon will fill up eventually, but we need to make sure this doesn't happen.

The way to handle this is by transferring inmates early enough to make room. This is obviously going to be the most complicated thing; we need to weigh several factors to decide when and how many prisoners to transfer. The reason we can't simply solve this via thresholds is that looking at the dungeon structure, this is not the only way we can lose inmates. After all, people are not always happy with being gold mining slaves and may decide the risk of dying in a prison is as high as dying while fleeing. Therefore, they decide to do so.

The same is true while prisoners are on the move between different dungeons as well, and not unlikely. So even though we have a hard limit of physical cells, we need to deal with the soft number of incoming and outgoing prisoners. This is a classical problem in business software. Matching these numbers against each other and optimizing for a certain outcome is basically what computer data analysis is all about.

The current state of the art

With all this in mind, it becomes clear that the orc master's current system of keeping track via a badly written note on a napkin is not perfect. In fact, it almost got him killed multiple times already. To give you an example of what can happen, he tells the story of how one time the king captured four clan leaders and wanted to make them miners just to humiliate them. However, when arriving at the dungeon, he realized that there was no room and had to travel to the next dungeon to drop them off, all while having them laugh at him because he obviously didn't know how to run a kingdom. This was due to our orc master having forgotten about the arrival of eight transfers just the day before. Another time, the orc master was not able to deliver any gold when the king's sheriff arrived because he didn't know he only had one-third of his required prisoners to actually mine anything. This time it was due to having multiple people count the inmates, and instead of recoding them cell-by-cell, they actually tried to do it in their head. While being orc, this is a setup for failure. All this comes down to bad organization, and having your system to manage dungeon inmates drawn on the back of a napkin certainly qualifies as such.

Digital dungeon management

Guided by the recent failures, the orc master has finally realized it is time to move to modern times, and he wants to revolutionize the way to manage his dungeon by making everything digital. He strives to have a system that basically takes the busywork out of managing by automatically calculating the necessary transfers according to the current amount of cells filled. He would like to just sit back, relax and let the computer do all the work for him.

Tip

A common pattern when talking with a business expert about software is that they are not aware of what can be done. Always remember that we, as developers, are the software experts and therefore are the only ones who are able to manage these expectations.

It is time now for us to think about what we need to know about the details and how to deal with the different scenarios. The orc master is not really familiar with the concepts of software development, so we need to make sure we talk in a language he can follow and understand, while making sure we get all the answers we need. We are hired for our expertise in software development, so we need to make sure to manage the expectations as well as the feature set and development flow. The development itself is of course going to be an iterative process, since we can't expect to get a list of everything needed right in one go. It also means that we will need to keep possible changes in mind. This is an essential part of structuring complex business software.

Developing software containing more complex business logic is prone to changing rapidly as the business is adapting itself and the users leverage the functionality the software provides. Therefore, it is essential to keep a common language between the people who understand the business and the developers who understand the software.

Tip

Incorporate the business terms wherever possible, it will ease communication between the business domain experts and you as a developer and therefore prevent misunderstandings early on.

Specification

To create a good understanding of what a piece of software needs to do, at least to be useful in the best way, is to get an understanding of what the future users were doing before your software existed. Therefore, we sit down with the orc master as he is managing his incoming and outgoing prisoners, and let him walk us through what he is doing on a day-to-day basis.

The dungeon is comprised of 100 cells that are either occupied by a prisoner or empty at the moment. When managing these cells, we can identify distinct tasks by watching the orc do his job. Drawing out what we see, we can roughly sketch it like this:

There are a couple of organizational important events and states to be tracked, they are:

  1. Currently available or empty cells

  2. Outgoing transfer states

  3. Incoming transfer states

Each transfer can be in multiple states that the master has to know about to make further decisions on what to do next. Keeping a view of the world like this is not easy especially accounting for the amount of concurrent updates happening. Tracking the state of everything results in further tasks for our master to do:

  1. Update the tracking

  2. Start outgoing transfers when too many cells are occupied

  3. Respond to incoming transfers by starting to track them

  4. Ask for incoming transfers if the occupied cells are to low

So, what does each of them involve?

Tracking available cells

The current state of the dungeon is reflected by the state of its cells, so the first task is to get this knowledge. In its basic form, this is easily achievable by simply counting every occupied and every empty cell, writing down what the values are. Right now, our orc master tours the dungeon in the morning, noting each free cell assuming that the other one must be occupied. To make sure he does not get into trouble, he no longer trusts his subordinates to do that! The problem being that there only is one central sheet to keep track of everything, so his keepers may overwrite each other's information accidently if there is more than one person counting and writing down cells. Also, this is a good start and is sufficient as it is right now, although it misses some information that would be interesting to have, for example, the amount of inmates fleeing the dungeon and an understanding of the expected free cells based on this rate. For us, this means that we need to be able track this information inside the application, since ultimately we want to project the expected amount of free cells so that we can effectively create recommendations or warnings based on the dungeon state.

Starting outgoing transfers

The second part is to actually handle getting rid of prisoners in case the dungeon fills up. In this concrete case, this means that if the number of free cells drops beneath 10, it is time to move prisoners out, since there may be new prisoners coming at any time. This strategy works pretty reliably since, from experience, it has been established that there are hardly any larger transports, so the recommendation is to stick with it in the beginning. However, we can already see some optimizations which currently are too complex.

Tip

Drawing from the experience of the business is important, as it is possible to encode such knowledge and reduces mistakes, but be mindful since encoding detailed experience is probably one of the most complex things to do.

In the future, we want to optimize this based on the rate of inmates fleeing the dungeon, new prisoners arriving due to being captured, as well as the projection of new arrivals from transfers. All this is impossible right now, since it will just overwhelm the current tracking system, but it actually comes down to capturing as much data as possible and analyzing it, which is something modern computer systems are good at. After all, it could save the orc master's head!

Tracking the state of incoming transfers

On some days, a raven will arrive bringing news that some prisoners have been sent on their way to be transferred to our dungeon. There really is nothing we can do about it, but the protocol is to send the raven out five days prior to the prisoners actually arriving to give the dungeon a chance to prepare. Should prisoners flee along the way, another raven will be sent informing the dungeon of this embarrassing situation. These messages have to be sifted through every day, to make sure there actually is room available for those arriving. This is a big part of projecting the amount of filled cells, and also the most variable part, we get told. It is important to note that every message should only be processed once, but it can arrive at any time during the day. Right now, they are all dealt with by one orc, who throws them out immediately after noting what the content results in. One problem with the current system is that since other dungeons are managed the same way ours is currently, they react with quick and large transfers when they get in trouble, which makes this quite unpredictable.

Initiating incoming transfers

Besides keeping the prisoners where they belong, mining gold is the second major goal of the dungeon. To do this, there needs to be a certain amount of prisoners available to man the machines, otherwise production will essentially halt. This means that whenever too many cells become abandoned it is time to fill them, so the orc master sends a raven to request new prisoners in. This again takes five days and, unless they flee along the way, works reliably. In the past, it still has been a major problem for the dungeon due to the long delay. If the filled cells drop below 50, the dungeon will no longer produce any gold and not making money is a reason to replace the current dungeon master. If all the orc master does is react to the situation, it means that there will probably be about five days in which no gold will be mined. This is one of the major pain points in the current system because projecting the amount of filled cells five days out seems rather impossible, so all the orcs can do right now is react.

All in all, this gives us a rough idea what the dungeon master is looking for and which tasks need to be accomplished to replace the current system. Of course, this does not have to happen in one go, but can be done gradually so everybody adjusts. Right now, it is time for us to identify where to start.

 

From greenfield to application


We are JavaScript developers, so it seems obvious for us to build a web application to implement this. As the problem is described, it is clear that starting out simply and growing the application as we further analyze the situation is clearly the way to go. Right now, we don't really have a clear understanding how some parts should be handled since the business process has not evolved to this level, yet. Also, it is possible that new features will arise or things start being handled differently as our software begins to get used. The steps described leave room for optimization based on collected data, so we first need the data to see how predictions can work. This means that we need to start by tracking as many events as possible in the dungeon. Running down the list, the first step is always to get a view of which state we are in, this means tracking the available cells and providing an interface for this. To start out, this can be done via a counter, but this can't be our final solution. So, we then need to grow toward tracking events and summing those to be able to make predictions for the future.

The first route and model

Of course there are many other ways to get started, but what it boils down to in most cases is that it is time now to choose the base to build on. By this I mean deciding on a framework or set of libraries to build upon. This happens alongside the decision on what database is used to back our application and many other small decisions, which are influenced by influenced by those decisions around framework and libraries. A clear understanding on how the frontend should be built is important as well, since building a single-page application, which implements a large amount of logic in the frontend and is backed by an API layer that differs a lot from an application, which implements most logic on the server side.

Tip

Don't worry if you are unfamiliar with express or any other technology used in the following. You don't need to understand every single detail, but you will get the idea of how developing an application with a framework is achieved.

Since we don't have a clear understanding, yet, which way the application will ultimately take, we try to push as many decisions as possible out, but decide on the stuff we immediately need. As we are developing in JavaScript, the application is going to be developed in Node.js and express is going to be our framework of choice. To make our life easier, we first decide that we are going to implement the frontend in plain HTML using EJS embedded JavaScript templates, since it will keep the logic in one place. This seems sensible since spreading the logic of a complex application across multiple layers will complicate things even further. Also, getting rid of the eventual errors during transport will ease our way toward a solid application in the beginning. We can push the decision about the database out and work with simple objects stored in RAM for our first prototype; this is, of course, no long-term solution, but we can at least validate some structure before we need to decide on another major piece of software, which brings along a lot of expectations as well. With all this in mind, we setup the application.

In the following section and throughout the book, we are using Node.js to build a small backend. At the time of the writing, the currently active version was Node.js 0.10.33. Node.js can be obtained from http://nodejs.org/ and is available for Windows, Mac OS X, and Linux. The foundation for our web application is provided by express, available via the Node Package Manager (NPM) at the time of writing in version 3.0.3:

$ npm install –g express
$ express --ejs inmatr

Tip

For the sake of brevity, the glue code in the following is omitted, but like all other code presented in the book, the code is available on the GitHub repository https://github.com/sideshowcoder/ddd-js-sample-code.

Creating the model

The most basic parts of the application are set up now. We can move on to creating our dungeon model in models/dungeon.js and add the following code to it to keep a model and its loading and saving logic:

var Dungeon = function(cells) {
  this.cells = cells
  this.bookedCells = 0
}

Tip

Downloading the example code

You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

Keeping in mind that this will eventually be stored in a database, we also need to be able to find a dungeon in some way, so the find method seems reasonable. This method should already adhere to the Node.js callback style to make our lives easier when switching to a real database. Even though we pushed this decision out, the assumption is clear since, even if we decide against a database, the dungeon reference will be stored and requested from outside the process in the future. The following shows an example with the find method:

var dungeons = {}
Dungeon.find = function(id, callback) {
  if(!dungeons[id]) {
    dungeons[id] = new Dungeon(100)
  }
  callback(null, dungeons[id])
}

The first route and loading the dungeon

Now that we have this in place, we can move on to actually react to requests. In express defining, the needed routes do this. Since we need to make sure we have our current dungeon available, we also use middleware to load it when a request comes in.

Using the methods we just created, we can add a middleware to the express stack to load the dungeon whenever a request comes in.

A middleware is a piece of code, which gets executed whenever a request reaches its level of the stack, for example, the router used to dispatch requests to defined functions is implemented as a middleware, as is logging and so on. This is a common pattern for many other kinds of interactions as well, such as user login. Our dungeon loading middleware looks like this, assuming for now we only manage one dungeon we can create it by adding a file in middleware/load_context.js with the following code:

function(req, res, next) {
  req.context = req.context || {}
  Dungeon.find('main', function(err, dungeon) {
    req.context.dungeon = dungeon
    next()
  })
}

Displaying the page

With this, we are now able to simply display information about the dungeon and track any changes made to it inside the request. Creating a view to render the state, as well as a form to modify it, are the essential parts of our GUI. Since we decided to implement the logic server-side, they are rather barebones. Creating a view under views/index.ejs allows us to render everything to the browser via express later. The following example is the HTML code for the frontend:

<h1>Inmatr</h1>
<p>You currently have <%= dungeon.free %> of
<%= dungeon.cells %> cells available.</p>

<form action="/cells/book" method="post">
  <select name="cells">
    <% for(var i = 1; i < 11; i++) { %>
    <option value="<%= i %>"><%= i %></option>
  <% } %>
  </select>
  <button type="submit" name="book" value="book">
  Book cells</button>
  <button type="submit" name="free" value="free">
  Free cells</button>
</form>

Gluing the application together via express

Now that we are almost done, we have a display for the state, a model to track what is changing, and a middleware to load this model as needed. Now, to glue it all together we will use express to register our routes and call the necessary functions. We mainly need two routes: one to display the page and one to accept and process the form input. Displaying the page is done when a user hits the index page, so we need to bind to the root path. Accepting the form input is already declared in the form itself as /cells/book. We can just create a route for it. In express, we define routes in relation to the main app object and according to the HTTP verbs as follows:

app.get('/', routes.index)
app.post('/cells/book', routes.cells.book)

Adding this to the main app.js file allows express to wire things up, the routes itself are implemented as follows in the routes/index.js file:

var routes = {
  index: function(req, res){
    res.render('index', req.context)
  },

cells: {
  book: function(req, res){
    var dungeon = req.context.dungeon
    var cells = parseInt(req.body.cells)
    if (req.body.book) {
    dungeon.book(cells)
  } else {
    dungeon.unbook(cells)
  }

      res.redirect('/')
    }
  }
}

With this done, we have a working application to track free and used cells.

The following shows the frontend output for the tracking system:

Moving the application forward

This is only the first step toward the application that will hopefully automate what is currently done by hand. With the first start in place, it is now time to make sure we can move the application along. We have to think about what this application is supposed to do and identify the next steps. After presenting the current state back to the business the next request is most likely to be to integrate some kind of login, since it will not be possible to modify the state of the dungeon unless you are authorized to do it. Since this is a web application, most people are familiar with them having a login. This moves us into a complicated space in which we need to start specifying the roles in the application along with their access patterns; so it is not clear if this is the way to go.

Another route to take is starting to move the application towards tracking events instead of pure numbers of the free cells. From a developer's point of view, this is probably the most interesting route but the immediate business value might be hard to justify, since without the login it seems unusable. We need to create an endpoint to record events such as fleeing prisoner, and then modify the state of the dungeon according to those tracked events. This is based on the assumption that the highest value for the application will lie in the prediction of the prisoner movement. When we want to track free cells in such a way, we will need to modify the way our first version of the application works. The logic on what events need to be created will have to move somewhere, most logically the frontend, and the dungeon will no longer be the single source of truth for the dungeon state. Rather, it will be an aggregator for the state, which is modified by the generation of events.

Thinking about the application in such a way makes some things clear. We are not completely sure what the value proposition of the application ultimately will be. This leads us down a dangerous path since the design decisions that we make now will impact how we build new features inside the application. This is also a problem in case our assumption about the main value proposition turns out to be wrong. In this case, we may have built quite a complex event tracking system which does not really solve the problem but complicates things. Every state modification needs to be transformed into a series of events where a simple state update on an object may have been enough. Not only does this design not solve the real problem, explaining it to the orc master is also tough. There are certain abstractions missing, and the communication is not following a pattern established as the business language. We need an alternative approach to keep the business more involved. Also, we need to keep development simple using abstraction on the business logic and not on the technologies, which are provided by the frameworks that are used.

 

Another look at the problem


So far, we have been looking at the application solely from a web developer's point of view. This is a classic case of when all you have is a hammer, everything looks like a nail. Have we really tackled the core problem already? What questions haven't we asked yet? These are important things to ask ourselves. Also, we need to figure out what we can ask our business experts to get a better idea on how to move forward. So what assumptions did we make beforehand and why?

Tip

Using the right tool for the job does extend to the abstractions that we make. Solving a problem when you already know the solution is a web application, which is not always helpful.

Thinking in an MVC web application

So far, we have been thinking about the problem in terms of a Model-View-Controller (MVC), web application. This brings along a certain set of assumptions that might not hold true in the case of our business domain. It is true that creating a web interface to manage input and output often does handle the presentation of an application today, but this does not mean that this part also holds the primary set of logic. In the case of our dungeon manager, it might only be one way to access and input data. An information system structured in this way has models holding the logic along with the data. These models are backed by a database, which is responsible for persistence, and is also used to implement some logic via constraints on the data. This means that our domain is pressed in the shape of the, most likely relational, database model.

All this locks us into a certain set of technologies: a webserver for hosting our application, a database for persistence, and a web layer for access and input. All these elements become the integral parts of our application and make change hard. Also, the model layer has no real abstraction besides being composed of a bunch of models. When we want to represent more complex interactions, this might not be enough. To be clear, there is no real issue with this as long as the developed application primarily consists of the interaction between systems, when however, the value proposition is mainly the business logic to be represented between parts of the system, this design starts to be not enough anymore.

Understanding the core problem

In the case of business applications, a lot of problems and their respective solutions are often not explicit. This is true for many areas and an example most developers might be familiar with is setting up a webserver. When asking a developer or administrator what he has to do to achieve this, it is described in only a few steps along the lines of: set up the operating system, install Apache, configure the site, and then start. For another developer of a system administrator, this might be enough to know what to do, but this is hardly reproducible for somebody from the outside or, even worse, for a computer.

Making all the steps explicit is essential to get a grasp of what the core business domain really consists of. In our case, we need to make sure to follow what the orc master currently does to keep his dungeon running. This can be done by either following him around, or making him walk us through his normal business process. We can't, however, rely on the business expert to explain the process to us in the necessary details. Also,we can't rely on our understanding of it to match what really needs to be done.

The main goal of this exercise, therefore, is to establish a baseline of understanding for what is going on and provide a shared language to talk about the problems, which will inadvertently arise. We are in an uncertain situation to start out with. This should not scare us, but we need to see it as the opportunity to increase our own understanding, as well as sometimes even the understanding of the currently executing person. Often business experts realize new details about their domain when questioning all the steps towards a goal, and they might even identify the possible problems.

Tip

Figuring out where the gaps in understanding a business process are is half the battle to implementing it correctly.

In the case of implementing a business process, we can assume that the status quo is the least we need to replicate to replace the tools the business is currently using. So, first of all, we need to either rebuild or incorporate all the tools the business is currently using. We can later find the places where optimization makes sense and is possible when we get a firm grasp on the problem in general. We should also aim for gradual replacement of processes one by one instead of one big switch, as this minimizes the risk for the business.

Communication is key

 

There are only two hard things in Computer Science: cache invalidation and naming things.

 
 --Phil Karlton

When working with applications, it often is a problem to create a shared language between developers, product owners, as well as the business people in general. It is often stated that naming things is one of the hardest problems of computer science, and it is true that having a describing name makes many things easier. It is also often the case that a clearly named object is easier to extend because its scope is already defined by its name. Therefore, it is often discouraged in object-oriented design to name things with general words, such as Manager, Creator or Processor. When thinking about this problem in the context of our business domain, it becomes clear that we can, and should, reuse the established business language as often as possible. It all comes down to communication. We, as the developers, are new to the field, so the business experts introducing us will already have an established language to describe problems in the domain where we are missing them.

As we follow along the steps of our business expert, we should take the time to get accustomed to the specific language that is in use throughout. This becomes even more essential as we start writing code. We will constantly need to check in with the domain experts to take their understanding into account, so when we use the business language to encode the domain, it will be easier for us to talk to everybody around us to develop a better understanding of the domain. This is quite abstract, so let me give you an example. Consider this naming for the dungeon:

function Dungeon(cells) {
  this.freeCells = cells
}

Now consider we want to record changes in the amount of prisoners, and write the following code:

var dungeon = new Dungeon(100)
dungeon.freeCells -= 5
dungeon.freeCells += 3

Even though this is natural to a developer, it does not use any business-specific language. We need to explain the meaning of things like += to non-developers to make them understand the meaning. Consider on the other hand encoding the same logic in the following methods:

Dungeon.prototype.inPrison = function (number) {
  this.freeCells -= number
}

Dungeon.prototype.free = function (number) {
  this.freeCells += number
}

Using these methods to express the same thing, it looks vastly more domain - specific then before. We can now describe the problem in the context of the domain and the code looks as follows:

var dungeon = new Dungeon(100)
dungeon.inPrison(5)
dungeon.free(3)

It will now become quite clear, even to non-developers, what is going on and therefore we can focus on talking about if the behavior is correct rather than about the details of the code.

 

The concepts of domain-driven design


When developing software, it is all too easy to get caught up in the details of implementation, without ever getting to the bottom of the problem. As software developers, our main goal is always to add value to the business, and for this to work, we first need to be clear what the problem we are trying to solve is. This has been attacked in several ways throughout the history of computer science. Structured programming gave the developers a way to break a problem into pieces, object-orientation attached those pieces to named things that allow for further structure and better associate meaning with parts of the program.

Domain-driven designs focus on getting structure in the problem solving process and also provide the right starting point to begin a conversation every stakeholder can be part of. Language is an important part in this, since communication is an area where a lot of projects struggle, as there often is a mismatch between engineering and business. While engineering terms are often more specific, the business language leaves room for interpretation, leaving it up to the person and his or her context to resolve what has been talked about. Both forms of languages have their place, as they have been established as an effective form of communication in their specific scenario, but translating between these two is often where problems or bugs are introduced. To help with these problems, domain-driven design allows a developer to classify certain types of object in the communication in several forms, all of which are going to be introduced in detail throughout this book:

  • Value objects

  • Entities

  • Aggregates

  • Bounded context

These are concepts that have a certain meaning and allow classification objects, which are part of a business process. With this, we can attach meanings and patterns.

It is all about distractions

Considering the different ways to create a program, the main improvement that structured programming added to the way we program today is the idea that while working on a project, the programmer does not always have to have the whole project in his head to make sure to not duplicate functionality or interfere with the regular flow of the program. This is accomplished by encapsulating functionality in chunks to be reusable in other parts. Moving onward, object-oriented programming added the ability to further encapsulate functionality in objects, keeping data and functions together as one logical unit. One can say a similar thing for functional programming, which allows the programmer to think about his program as a flow of functions that are defined by their input and therefore can be composed as larger units. Domain-driven design now adds a layer on top, which adds abstractions to express business logic and can encapsulate it from the outside interaction. Creating a business layer that interacts with the outside world via a clearly defined API does this in this case.

Looking at these different practices, one thing shines through on all levels, and this is the idea of removing distractions. When working on a large codebase or on a complex problem, the more you have to keep in your head at once, the higher the level of distraction from the core problem. This is a major point of domain-driven design, and we are going to see how this plays out in the next chapter when we think about how we can go from a specification that we have seen before, toward a problem description we can continue to work with.

Focus on the problem at hand

In a lot of cases, stating the problem is actually not obvious. This is why working towards a shared understanding between business experts and developers is so important, both sides need to agree on what they expect from a feature, or a piece of software. Allowing developers to state in clear terms to the business what the feature solves allows the developers to focus on the problem at hand and get input more directly. Similar to the principles of test-driven or behavior-driven development, stating in a clear fashion what something is intended to do helps the development a long way. At this stage, creating a route to get from A to be B as well as objectively stating when a goal has been reached, is what we seek. This by no means saves us from reconfirming that the goal is still the one to achieve constantly with the business, but it allows us to make this communication clear. With the language established, this now does not have to involve multiple hour-long meetings with no clear outcome.

With all this in mind, it is now time to dive into the essence of domain-driven design. Throughout this book, we are going to move our orc dungeon to the 21st century, allowing it to flexibly adjust to its business needs. As a first step, we are going to sit down and see what running this dungeon is all about and how our new software can add value using the concepts and the mindset of domain-driven design.

 

Further reading


Domain-driven design, as seen in this chapter, is described in large by the book Domain-driven design, by Eric J. Evans. I would recommend every reader to follow up with his descriptions to provider a deeper insight into the ideas behind domain-driven design in general, outside a more specific topic as described here.

 

Summary


In this chapter, we went through the steps of getting started with an application as most projects are started today and contrasted it with the domain-driven design approach to development. We learned about the key focus of domain-driven design, as the communication between the developers and the other parties involved in a project.

The key point to takeaway is the strong focus on getting the core feature set of the application, before focusing on technology choices and other development-related problems that will otherwise subtract resources from the exploration. Another important aspect we learned about is how to gather specification in terms of usage. The key point here is to gain knowledge about how the work is currently achieved and how the application can help besides asking potential users for a specification.

The next chapter focuses deeper on the process of gathering knowledge about the use, expected usability of the application, and on the process of starting to build a language to aid the communication between the team developing the application, build domain experts and developers.

About the Author
  • Philipp Fehre

    Philipp Fehre is a software engineer, conference organizer, speaker, and educator. Having seen many different applications as a consultant, he moved on to educate developers as an advocate of the NoSQL technology and is now working as a backend software engineer. He has also been a writer for the German Linux magazine in the past.

    For years, he has been fascinated by the possibilities of JavaScript and followed Node.js from its beginnings, using it for research projects and production web services.

    Browse publications by this author
Latest Reviews (3 reviews total)
Met expectations 12345678
Meets me where I live right now.
JavaScript Domain-Driven Design
Unlock this book and the full library FREE for 7 days
Start now