Add readme and class diagram

This commit is contained in:
Ilkka Seppälä 2016-04-10 21:22:40 +03:00
parent 9b3aa785ed
commit ccc1ec921a
8 changed files with 364 additions and 10 deletions

29
hexagonal/README.md Normal file
View File

@ -0,0 +1,29 @@
---
layout: pattern
title: Hexagonal Architecture
folder: hexagonal
permalink: /patterns/hexagonal/
categories: Architectural
tags:
- Java
- Difficulty-Expert
---
## Intent
Allow an application to equally be driven by users, programs, automated test or batch scripts, and to be developed and tested in isolation from its eventual run-time devices and databases.
![Hexagonal Architecture class diagram](./etc/hexagonal.png)
## Applicability
Use Hexagonal Architecture pattern when
* it is important that the application is fully testable
* you use Domain Driven Design methodology and/or Microservices architectural style
## Real world examples
* [Apache Isis](https://isis.apache.org/)
## Credits
* [Alistair Cockburn - Hexagonal Architecture](http://alistair.cockburn.us/Hexagonal+architecture)

BIN
hexagonal/etc/hexagonal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

View File

@ -0,0 +1,325 @@
<?xml version="1.0" encoding="UTF-8"?>
<class-diagram version="1.1.9" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true"
realizations="true" associations="true" dependencies="false" nesting-relationships="true" router="FAN">
<class id="1" language="java" name="com.iluwatar.hexagonal.domain.LotteryTicket" project="hexagonal"
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicket.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="169" width="270" x="2042" y="351"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<interface id="2" language="java" name="com.iluwatar.hexagonal.banking.WireTransfers" project="hexagonal"
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/banking/WireTransfers.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="115" width="215" x="1490" y="351"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</interface>
<class id="3" language="java" name="com.iluwatar.hexagonal.administration.LotteryAdministrationImpl"
project="hexagonal"
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/administration/LotteryAdministrationImpl.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="133" width="311" x="992" y="124"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<interface id="4" language="java" name="com.iluwatar.hexagonal.database.LotteryTicketRepository" project="hexagonal"
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/database/LotteryTicketRepository.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="133" width="257" x="1745" y="351"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</interface>
<class id="5" language="java" name="com.iluwatar.hexagonal.domain.LotteryConstants" project="hexagonal"
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryConstants.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="169" width="227" x="205" y="124"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<class id="6" language="java" name="com.iluwatar.hexagonal.domain.LotteryTicketId" project="hexagonal"
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicketId.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="115" width="140" x="508" y="124"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<class id="7" language="java" name="com.iluwatar.hexagonal.domain.LotteryNumbers" project="hexagonal"
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryNumbers.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="277" width="206" x="2042" y="560"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<class id="8" language="java" name="com.iluwatar.hexagonal.notifications.LotteryNotificationsImpl" project="hexagonal"
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/notifications/LotteryNotificationsImpl.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="169" width="229" x="723" y="124"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<class id="9" language="java" name="com.iluwatar.hexagonal.banking.WireTransfersImpl" project="hexagonal"
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/banking/WireTransfersImpl.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="151" width="215" x="1787" y="124"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<interface id="10" language="java" name="com.iluwatar.hexagonal.administration.LotteryAdministration"
project="hexagonal" file="/hexagonal/src/main/java/com/iluwatar/hexagonal/administration/LotteryAdministration.java"
binary="false" corner="BOTTOM_RIGHT">
<position height="115" width="311" x="426" y="351"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</interface>
<class id="11" language="java" name="com.iluwatar.hexagonal.domain.LotteryNumbers.RandomNumberGenerator"
project="hexagonal" file="/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryNumbers.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="115" width="188" x="2042" y="877"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<class id="12" language="java" name="com.iluwatar.hexagonal.domain.LotteryTicketCheckResult" project="hexagonal"
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicketCheckResult.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="187" width="229" x="2352" y="124"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<class id="13" language="java" name="com.iluwatar.hexagonal.domain.PlayerDetails" project="hexagonal"
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/PlayerDetails.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="241" width="219" x="1106" y="560"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<class id="14" language="java" name="com.iluwatar.hexagonal.database.LotteryTicketInMemoryRepository"
project="hexagonal"
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/database/LotteryTicketInMemoryRepository.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="151" width="257" x="2042" y="124"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<interface id="15" language="java" name="com.iluwatar.hexagonal.service.LotteryService" project="hexagonal"
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/service/LotteryService.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="97" width="404" x="1046" y="351"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</interface>
<enumeration id="16" language="java" name="com.iluwatar.hexagonal.domain.LotteryTicketCheckResult.CheckResult"
project="hexagonal" file="/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicketCheckResult.java"
binary="false" corner="BOTTOM_RIGHT">
<position height="133" width="229" x="2352" y="351"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</enumeration>
<class id="17" language="java" name="com.iluwatar.hexagonal.App" project="hexagonal"
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/App.java" binary="false" corner="BOTTOM_RIGHT">
<position height="133" width="217" x="169" y="351"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<class id="18" language="java" name="com.iluwatar.hexagonal.service.LotteryServiceImpl" project="hexagonal"
file="/hexagonal/src/main/java/com/iluwatar/hexagonal/service/LotteryServiceImpl.java" binary="false"
corner="BOTTOM_RIGHT">
<position height="115" width="404" x="1343" y="124"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<interface id="19" language="java" name="com.iluwatar.hexagonal.notifications.LotteryNotifications"
project="hexagonal" file="/hexagonal/src/main/java/com/iluwatar/hexagonal/notifications/LotteryNotifications.java"
binary="false" corner="BOTTOM_RIGHT">
<position height="151" width="229" x="777" y="351"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</interface>
<association id="20">
<end type="SOURCE" refId="3" navigable="false">
<attribute id="21" name="repository"/>
<multiplicity id="22" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="4" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="23">
<end type="SOURCE" refId="3" navigable="false">
<attribute id="24" name="notifications"/>
<multiplicity id="25" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="19" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="26">
<end type="SOURCE" refId="18" navigable="false">
<attribute id="27" name="notifications"/>
<multiplicity id="28" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="19" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="29">
<end type="SOURCE" refId="14" navigable="false">
<attribute id="30" name="tickets"/>
<multiplicity id="31" minimum="0" maximum="2147483647"/>
</end>
<end type="TARGET" refId="1" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<realization id="32">
<end type="SOURCE" refId="8"/>
<end type="TARGET" refId="19"/>
</realization>
<realization id="33">
<end type="SOURCE" refId="18"/>
<end type="TARGET" refId="15"/>
</realization>
<realization id="34">
<end type="SOURCE" refId="3"/>
<end type="TARGET" refId="10"/>
</realization>
<association id="35">
<end type="SOURCE" refId="18" navigable="false">
<attribute id="36" name="bank"/>
<multiplicity id="37" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="2" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="38">
<end type="SOURCE" refId="18" navigable="false">
<attribute id="39" name="repository"/>
<multiplicity id="40" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="4" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="41">
<end type="SOURCE" refId="3" navigable="false">
<attribute id="42" name="bank"/>
<multiplicity id="43" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="2" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="44">
<end type="SOURCE" refId="12" navigable="false">
<attribute id="45" name="checkResult"/>
<multiplicity id="46" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="16" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<nesting id="47">
<end type="SOURCE" refId="12"/>
<end type="TARGET" refId="16"/>
</nesting>
<association id="48">
<end type="SOURCE" refId="17" navigable="false">
<attribute id="49" name="allPlayerDetails"/>
<multiplicity id="50" minimum="0" maximum="2147483647"/>
</end>
<end type="TARGET" refId="13" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="51">
<end type="SOURCE" refId="1" navigable="false">
<attribute id="52" name="playerDetails"/>
<multiplicity id="53" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="13" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="54">
<end type="SOURCE" refId="1" navigable="false">
<attribute id="55" name="lotteryNumbers"/>
<multiplicity id="56" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="7" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<realization id="57">
<end type="SOURCE" refId="14"/>
<end type="TARGET" refId="4"/>
</realization>
<nesting id="58">
<end type="SOURCE" refId="7"/>
<end type="TARGET" refId="11"/>
</nesting>
<realization id="59">
<end type="SOURCE" refId="9"/>
<end type="TARGET" refId="2"/>
</realization>
<association id="60">
<end type="SOURCE" refId="3" navigable="false">
<attribute id="61" name="service"/>
<multiplicity id="62" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="15" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</classifier-display>
<association-display labels="true" multiplicity="true"/>
</class-diagram>

View File

@ -27,7 +27,7 @@ import java.util.Map;
import com.iluwatar.hexagonal.banking.WireTransfers;
import com.iluwatar.hexagonal.banking.WireTransfersImpl;
import com.iluwatar.hexagonal.database.LotteryTicketRepository;
import com.iluwatar.hexagonal.database.LotteryTicketRepositoryMock;
import com.iluwatar.hexagonal.database.LotteryTicketInMemoryRepository;
import com.iluwatar.hexagonal.domain.LotteryConstants;
import com.iluwatar.hexagonal.domain.LotteryNumbers;
import com.iluwatar.hexagonal.domain.LotteryTicket;
@ -55,7 +55,7 @@ public class LotteryAdministrationImpl implements LotteryAdministration {
private final WireTransfers bank = new WireTransfersImpl();
public LotteryAdministrationImpl() {
repository = new LotteryTicketRepositoryMock();
repository = new LotteryTicketInMemoryRepository();
}
@Override

View File

@ -34,7 +34,7 @@ import com.iluwatar.hexagonal.domain.LotteryTicketId;
* Mock database for lottery tickets.
*
*/
public class LotteryTicketRepositoryMock implements LotteryTicketRepository {
public class LotteryTicketInMemoryRepository implements LotteryTicketRepository {
private static Map<LotteryTicketId, LotteryTicket> tickets = new HashMap<>();

View File

@ -27,7 +27,7 @@ import java.util.Optional;
import com.iluwatar.hexagonal.banking.WireTransfers;
import com.iluwatar.hexagonal.banking.WireTransfersImpl;
import com.iluwatar.hexagonal.database.LotteryTicketRepository;
import com.iluwatar.hexagonal.database.LotteryTicketRepositoryMock;
import com.iluwatar.hexagonal.database.LotteryTicketInMemoryRepository;
import com.iluwatar.hexagonal.domain.LotteryConstants;
import com.iluwatar.hexagonal.domain.LotteryNumbers;
import com.iluwatar.hexagonal.domain.LotteryTicket;
@ -51,7 +51,7 @@ public class LotteryServiceImpl implements LotteryService {
private final LotteryNotifications notifications = new LotteryNotificationsImpl();
public LotteryServiceImpl() {
repository = new LotteryTicketRepositoryMock();
repository = new LotteryTicketInMemoryRepository();
}
@Override

View File

@ -31,7 +31,7 @@ import org.junit.Before;
import org.junit.Test;
import com.iluwatar.hexagonal.database.LotteryTicketRepository;
import com.iluwatar.hexagonal.database.LotteryTicketRepositoryMock;
import com.iluwatar.hexagonal.database.LotteryTicketInMemoryRepository;
import com.iluwatar.hexagonal.domain.LotteryTicket;
import com.iluwatar.hexagonal.domain.LotteryTicketId;
import com.iluwatar.hexagonal.test.LotteryTestUtils;
@ -43,7 +43,7 @@ import com.iluwatar.hexagonal.test.LotteryTestUtils;
*/
public class LotteryTicketRepositoryTest {
private final LotteryTicketRepository repository = new LotteryTicketRepositoryMock();
private final LotteryTicketRepository repository = new LotteryTicketInMemoryRepository();
@Before
public void clear() {
@ -52,7 +52,7 @@ public class LotteryTicketRepositoryTest {
@Test
public void testCrudOperations() {
LotteryTicketRepository repository = new LotteryTicketRepositoryMock();
LotteryTicketRepository repository = new LotteryTicketInMemoryRepository();
assertEquals(repository.findAll().size(), 0);
LotteryTicket ticket = LotteryTestUtils.createLotteryTicket();
Optional<LotteryTicketId> id = repository.save(ticket);

View File

@ -38,7 +38,7 @@ import com.iluwatar.hexagonal.administration.LotteryAdministrationImpl;
import com.iluwatar.hexagonal.banking.WireTransfers;
import com.iluwatar.hexagonal.banking.WireTransfersImpl;
import com.iluwatar.hexagonal.database.LotteryTicketRepository;
import com.iluwatar.hexagonal.database.LotteryTicketRepositoryMock;
import com.iluwatar.hexagonal.database.LotteryTicketInMemoryRepository;
import com.iluwatar.hexagonal.domain.LotteryNumbers;
import com.iluwatar.hexagonal.domain.LotteryTicket;
import com.iluwatar.hexagonal.domain.LotteryTicketCheckResult;
@ -57,7 +57,7 @@ public class LotteryTest {
private final LotteryAdministration admin = new LotteryAdministrationImpl();
private final LotteryService service = new LotteryServiceImpl();
private final LotteryTicketRepository repository = new LotteryTicketRepositoryMock();
private final LotteryTicketRepository repository = new LotteryTicketInMemoryRepository();
private final WireTransfers wireTransfers = new WireTransfersImpl();
@Before