The Model is the Value – Starting with a Domain Centric Design

This is the sixth post in the first Build-Measure-Learn cycle.
In the last post, I defined a set of test statements in BDD style, as a source for automated acceptance tests. Based on the given description of the first acceptance test, I am going to make a rough design for the automated acceptance tests. I rely on a Domain-Driven Design and have chosen the Hexagonal Architecture style, this also has implications on the way how the tests are implemented. I am developing a basic application design before implementing the automated acceptance tests, because I want to have some guidance for the upcoming development.

The Domain Model Stands in the Centre

The domain logic is the most valuable thing in a software application. Therefore, the domain logic stands in the centre of my design considerations. I will mainly rely on the approach of the Domain-Driven Design, using the patterns and practices described there. Eric Evans first stated this approach in his book (see [Evans2003]). (By the way I can strongly recommend reading this book.)

Currently, this project is still at a very early stage. There is not much knowledge about the domain logic. What is currently there? There are three epics, a major user task for importing text files and a detailed user story for importing a text with a single passage. In the sense of product development, I am just trying to find some valuable features on which I can base the system product. This also means that at this point in time a broader picture is not available. From my point of view, the strategic DDD patterns, Bounded Context[1] and Context Map[2], are not appropriate or helpful here. To use them I need a more detailed picture of the product features. For now, I assume that the target system is modelled by one bounded context.

Hexagonal Architecture

So what kind of conceptual considerations do I have to do now? It is about the architectural style. Vaughn Vernon describes several architecture styles in his book, (see [Vernon2013]). From my point of view, Hexagonal Architecture (a.k.a. Ports and Adapters, see [Cockburn2016]) is the most promising one. It is most promising because of three reasons. First, it allows many disparate clients to interact with the system. I can image a web application or native apps on a tablet, pc or smartphone as clients. The second reason is that testing is very easy. Adapters can be easily developed for test purposes. Additionally, last but not least, the Hexagonal Architecture is very versatile, because it can be the base for other architectures like Service-Oriented, REST or Event-Driven Architecture.

The following picture shows a general diagram of a Hexagonal Architecture.

Diagram of a Hexagonal Architecture
Diagram of a Hexagonal Architecture

The Hexagonal Architecture consists of three conceptual layers, the Domain, Application and Framework Layer. The Domain Layer contains all the business logic. It is the core of the architecture and the most valuable part of the system. The Application Layer wraps up the Domain core. It contains all of the application specific characteristics. It sits between the Domain and the Framework Layer and mediates between them. The Framework Layer forms the outer layer. It offers the services to communicate with the outside world. It adapts requests from the outside, e.g. HTTP, REST, SOAP or RMI, and sends requests to other systems, e.g. to a database, Mail-Server or Browser.

Acceptance Tests as Adapters in the Hexagonal Architecture

Now let us apply the architectural style (and some other DDD patterns) to the first acceptance test. I am going to use the 2nd scenario:

Scenario 2: A single text passage in a Word document
Given a text file which contains a single text passage
When the user starts the import on the given file
Then the file will be imported and the text is in the system available

Analysing the acceptance test results in the following picture:

Acceptance test in the Hexagonal Style
Acceptance test in the Hexagonal Style

The picture illustrates a static design with some elements. Relationships between the elements were deliberately omitted. The acceptance test is based on some test code and a mock for a document repository. A Repository is a tactical DDD pattern, it represents an illusion of an in-memory collection, which is typically implemented against a database. The test code works against a dedicated Application API, the so called Document Import API. The Import API is part of the application and it represents a kind of use case of the application. The Import API then calls the appropriate domain logic. In the picture the domain logic was denoted as Doc Model. The Doc Model consists of some kind of an Aggregate and an Entity, which represents a document. Repository, Entity and Aggregate are part of the tactical DDD pattern set (see [Vernon2013]). The Aggregate is responsible for building the entity of a document and also for storing the new document entity into the storage. To store or save a document the aggregate needs an instance of a repository. Here, we’ve come full circle with the responsibility of the acceptance test code. An implementation of the document repository depends on the technology and will therefore be part of the framework layer of the Hexagonal Architecture. For testing purpose, the infrastructure also provides a repository mock which will be used by the acceptance test.

Technology

Lastly, I think some of you like to know which kind of technology, I am going to deploy. Although at the moment only a few decisions have been taken. First of all, the system will be implemented with Scala (see [Scala]). The second decision affects the build system. Here I will deploy Sbt (see [Sbt]) and for the automation of the acceptance tests I will rely on the BDD framework Cucumber (see [Cucumber]).

What’s next?

In the next blog post I will describe how I would set up the acceptance test automation with Cucumber. Also I will give a first indication on how I am going to drive the development with the acceptance tests.

Footnotes

[1] A Bounded Context is a conceptual boundary where a domain model is applicable (see [Vernon2013]).

[2] A Context Map shows the relationships among Bounded Contexts (see [Vernon2013]).

Resources

[Cockburn2016] Alistair Cockburn, Hexagonal architecture <http://alistair.cockburn.us/Hexagonal+architecture>
accessed July 26th, 2017

[Cucumber] Cucumber.io
<https://cucumber.io/> accessed July 26th, 2017

[Evans2003] Eric Evans, Domain Driven Design: Tackling Complexity in the Heart of Software (1st edition, Addison-Wesley 2003)

[Sbt] Sbt – The interactive build tool
<http://www.scala-sbt.org/> accessed July 26th, 2017

[Scala] The Scala Programming Language
<http://www.scala-lang.org/> accessed July 26th, 2017

[Vernon2013] Vaughn Vernon, Implementing Domain-Driven Design
(1st edition, Addison-Wesley 2013)

Leave a Reply