Skip to content

joshski/double-hexagon-example

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

double-hexagon-example

An example of a design pattern I like to call the "double hexagon". Inspired by the hexagonal architecture the double hexagon involves running the exact same tests against the application domain logic and the external user interface. Using ports and adapters in both the test and application code means two hexagons are in use, one for the tests and one for the application code.

@aslakhellesoy taught me how to do this.

Understanding the code

The app test runs the same two simple test cases against both the Account domain object and the HTTP API by enumerating two different configurations generated by factories.

There are two implementations of the AccountStore contract:

These are covered by the same contract test that ensures they are interchangeable.

There are three implementations of the BankApp interface, so the same tests can run against three different targets:

To make the same tests run against these alternative implementations, the tests themselves need adapters (hence the double hexagon):

Running the tests

Run the core tests using the mocha shim:

./mocha

...which passes the --harmony flag to node, for async/await support as well as any additional standard mocha arguments.

With no arguments mocha will run all tests against two configurations of the app, first directly targeting the domain logic, secondly targeting the HTTP API, third via the browser app.

The third hexagon pair uses a browser, so it will only run under electron-mocha via a similar shim:

./electron-mocha
AccountStore (MemoryAccountStore)
  ✓ assigns accountNumbers when creating accounts
  ✓ stores and retrieves accounts
  ✓ gets different account objects for the same account number
  ✓ stores copies of accounts

AccountStore (FlatFileAccountStore)
  ✓ assigns accountNumbers when creating accounts
  ✓ stores and retrieves accounts
  ✓ gets different account objects for the same account number
  ✓ stores copies of accounts

AppCore (MemoryAccountStore)
  making a transfer
    ✓ decreases the balance of the sender account
    ✓ increases the balance of the receiver account

AppCore (FlatFileAccountStore)
  making a transfer
    ✓ decreases the balance of the sender account
    ✓ increases the balance of the receiver account

AppViaApi (MemoryAccountStore)
  making a transfer
    ✓ decreases the balance of the sender account
    ✓ increases the balance of the receiver account

AppViaApi (FlatFileAccountStore)
  making a transfer
    ✓ decreases the balance of the sender account
    ✓ increases the balance of the receiver account

AppViaDom (MemoryAccountStore)
  making a transfer
    ✓ decreases the balance of the sender account (110ms)
    ✓ increases the balance of the receiver account (115ms)

AppViaDom (FlatFileAccountStore)
  making a transfer
    ✓ decreases the balance of the sender account (96ms)
    ✓ increases the balance of the receiver account (113ms)

20 passing (968ms)

Use the -f flag to run a subset for a particular hexagon-pair:

./mocha -f Core
./mocha -f Api
./electron-mocha -f Dom

...or all configurations using a particular AccountStore implementation:

./mocha -f FlatFileAccountStore
./electron-mocha -f MemoryAccountStore

About

An example of the double hexagon design pattern

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published