Skip to content

#450 Queue-Based-Load-Leveling Blog #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Dec 8, 2016
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,31 @@ title: Build Maintainable Systems With Hexagonal Architecture
author: ilu
---

![Hexagonal Architecture]({{ site.url }}{{ site.baseurl }}/assets/hexagonal-architecture.png)
![Hexagonal Architecture]({{ site.baseurl }}/assets/hexagonal-architecture.png)

## The fallacies of layered architecture

This blog post is about implementing Alistair Cockburn's [Hexagonal Architecture](http://alistair.cockburn.us/Hexagonal+architecture). To have something familiar to start with let's first talk about Layered Architecture. It is a well known architectural pattern that organizes application into layers each having their specific purpose. The database layer takes care of data transactions, the business layer is responsible for business logic and the presentation layer deals with the user input. The Layered Architecture implements so called separation of concerns principle which leads to more maintainable applications. Changes to one area in the software do not affect the other areas.

![Layers]({{ site.url }}{{ site.baseurl }}/assets/layers.png)
![Layers]({{ site.baseurl }}/assets/layers.png)

This way of building applications can be considered simple and effective. But it also has several drawbacks. When you see an application implemented with Layered Architecture, where is the application core? Is it the database? Maybe it's the business logic with some little things scattered over to the presentation layer. This is the typical problem with layers. There is no application core, there are just the layers and the core logic is scattered here and there. When the business logic starts to leak over to the presentation layer, the application can no longer be tested without the user interface.

## Core, ports and adapters

Hexagonal Architecture tackles this issue by building the application around the core. The main objective is to create fully testable systems that can be driven equally by users, programs and batch scripts in isolation of database.

However, the core alone may not be very useful. Something has to drive this application, call the business logic methods. It may be a HTTP request, automatic test or integration API. These interfaces we call the primary ports. Also, the core has its dependencies. For example, there may be a data storage module that the core calls upon to retrieve and update data. The interfaces of these modules that are driven by the core are called the secondary ports of the application.
The core alone is not very useful. Something has to drive this application, call the business logic methods. It may be a HTTP request, automatic test or integration API. These interfaces that drive the application we call the primary ports and the modules that use them are primary adapters.

Each of the ports may have one or more implementation. For example there may be a mock database for testing and a real database for running the application. The port implementations are called adapters. Thus the alias name Ports and Adapters for Hexagonal Architecture. Other architectural patterns describing the same concept are Uncle Bob's [Clean Architecture](https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html) and Jeffrey Palermo's [Onion Architecture](http://jeffreypalermo.com/blog/the-onion-architecture-part-1/).
Also, the core has its dependencies. For example, there may be a data storage module that the core calls upon to retrieve and update data. The interfaces of these modules that are driven by the core are called the secondary ports of the application.

The secondary ports may have one or more implementations. For example there may be a mock database for testing and a real database for running the application. The secondary port implementations are called secondary adapters. Here comes the alias name Ports and Adapters for Hexagonal Architecture. Other architectural patterns describing the same concept are Uncle Bob's [Clean Architecture](https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html) and Jeffrey Palermo's [Onion Architecture](http://jeffreypalermo.com/blog/the-onion-architecture-part-1/).

The name of the pattern comes from the following hexagonal drawing.

![Hexagon]({{ site.url }}{{ site.baseurl }}/assets/hexagon.png)
![Ports and adapters]({{ site.baseurl }}/assets/ports_and_adapters.png)

The diagram shows how the domain is in the middle surrounded by ports on each side of hexagon. The actual amount of ports does not have to be exactly six, it can be less or it can be more depending on the application needs.
The diagram shows how the domain is in the middle surrounded by ports on sides of the hexagon. The actual amount of ports does not have to be exactly six, it can be less or it can be more depending on the application needs. On the outer hexagon layer reside the primary and secondary adapters.

Naked Objects design pattern is considered an implementation of Hexagonal Architecture. Naked Objects is utilized by [Apache Isis](https://isis.apache.org/) framework. User defines the domain objects and the framework automatically generates user interface and REST API around it.

Expand All @@ -36,7 +38,7 @@ Next we will demonstrate Hexagonal Architecture by building a lottery system. Th

The secondary ports consist of lottery ticket database, banking for wire transfers and event log for handling and storing lottery events. The resulting hexagon of the system can be seen in the following diagram.

![Lottery system]({{ site.url }}{{ site.baseurl }}/assets/lottery.png)
![Lottery system]({{ site.baseurl }}/assets/lottery.png)

## Start from the core concepts

Expand All @@ -61,17 +63,17 @@ The lottery players use `submitTicket()` to submit tickets for lottery round. Af

`LotteryAdministration` and `LotteryService` have dependencies to lottery ticket database, banking and event log ports. We use [Guice](https://github.com/google/guice) dependency injection framework to provide the correct implementation classes for each purpose. The core logic is tested in [LotteryTest](https://github.com/iluwatar/java-design-patterns/blob/master/hexagonal/src/test/java/com/iluwatar/hexagonal/domain/LotteryTest.java).

## Primary port for the players
## Primary adapter for the players

Now that the core implementation is ready we need to define the primary port for the players. We introduce `ConsoleLottery` class to provide command line interface that allows players to interact with the lottery system.
Now that the core implementation is ready we need to define the primary adapter for the players. We introduce `ConsoleLottery` class to provide command line interface that allows players to interact with the lottery system.

<script src="http://gist-it.appspot.com/http://github.com/iluwatar/java-design-patterns/raw/master/hexagonal/src/main/java/com/iluwatar/hexagonal/service/ConsoleLottery.java?slice=41:"></script>

It has commands to view and transfer bank account funds, submit and check lottery tickets.

## Primary port for the administrators
## Primary adapter for the administrators

We also need to define the lottery administrator facing port. This is another command line interface named `ConsoleAdministration`.
We also need to define the lottery administrator facing adapter. This is another command line interface named `ConsoleAdministration`.

<script src="http://gist-it.appspot.com/http://github.com/iluwatar/java-design-patterns/raw/master/hexagonal/src/main/java/com/iluwatar/hexagonal/administration/ConsoleAdministration.java?slice=35:"></script>

Expand Down
Binary file added assets/ports_and_adapters.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 11 additions & 2 deletions cibuild.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,16 @@ git log --pretty=format:'%H' -n 1 >> _config.yml

bundle exec jekyll build

# - ignore everything below every webapp directory, so we dont mess with the source code
# credit: code snippet borrowed from jekyllrb.com website source
IGNORE_HREFS=$(ruby -e 'puts %w{
example\.com.*
https:\/\/github.com\/iluwatar\/java-design-patterns\/fork
https:\/\/sonarqube.com.*
}.map{|h| "/#{h}/"}.join(",")')
# - ignore example.com because they are just examples/fakes
# - ignore the fork link of our project, because it somehow is not valid (https://validator.w3.org/)
# - ignore sonarqube.com/api/badges/gate because of travis-only 'SSL Connect Error's

# - ignore everything below every webapp directory, so we dont mess with the source code
# - ignore the folder principles of the external dependency (git submodule) webpro/programming-principles
bundle exec htmlproofer ./_site/ --file-ignore "/.+\/(webapp|principles)\/.*/" --url-ignore "https://github.com/iluwatar/java-design-patterns/fork"
bundle exec htmlproofer ./_site/ --file-ignore "/.+\/(webapp|principles)\/.*/" --url-ignore $IGNORE_HREFS --check-html --allow-hash-href
2 changes: 1 addition & 1 deletion patterns
Submodule patterns updated 1100 files