Background Image
Table of Contents Table of Contents
Previous Page  431 / 478 Next Page
Information
Show Menu
Previous Page 431 / 478 Next Page
Page Background

the Internet, or the UI—and trying to keep them separate from the core business logic

of your application.

Ports and Adapters/Hexagonal/Clean Architecture

Integrated tests are most useful at the

boundaries

of a system—at the points where our

code integrates with external systems, like a database, filesystem, or UI components.

Similarly, it’s at the boundaries that the downsides of test isolation and mocks are at

their worst, because it’s at the boundaries that you’re most likely to be annoyed if your

tests are tightly coupled to an implementation, or to need more reassurance that things

are integrated properly.

Conversely, code at the

core

of our application—code that’s purely concerned with our

business domain and business rules, code that’s entirely under our control—this code

has less need for integrated tests, since we control and understand all of it.

So one way of getting what we want is to try and minimise the amount of our code that

has to deal with boundaries. Then we test our core business logic with isolated tests and

test our integration points with integrated tests.

Steve Freeman and Nat Pryce, in their book

Growing Object-Oriented Software

, call

this approach “Ports and Adapters” (see

Figure 22-1 )

.

We actually started moving towards a ports and adapters architecture in

Chapter 19 ,

when we found that writing isolated unit tests was encouraging us to push ORM code

out of the main application, and hide it in helper functions from the model layer.

This pattern is also sometimes known as “The Clean architecture” or “Hexagonal Ar‐

chitecture”. See the further reading section at the end for more info.

Functional Core, Imperative Shell

Gary Bernhardt pushes this further, recommending an architecture he calls “Functional

Core, Imperative Shell”, whereby the “shell” of the application, the place where interac‐

tion with boundaries happens, follows the imperative programming paradigm, and can

be tested by integrated tests, acceptance tests, or even (gasp!) not at all, if it’s keptminimal

enough. But the core of the application is actually written following the functional pro‐

gramming paradigm (complete with the “no side effects” corollary), which actually

allows fully isolated, “pure” unit tests,

entirely without mocks

.

Check out Gary’s presentation titled

“Boundaries”

for more on this approach.

Architectural Solutions

|

403