Skip to content

Commit 501a839

Browse files
author
Fabian Baumeister
committed
fix: Add inbound ports and make services optional
After dicussing with @chris-toenjes-deye we decided the following points: - Services should be marked optional. The usual business logic belongs inside the use case implementation. Only in cases of better structuring or reusable business logic, it should be moved to a service - A differentiation between inbound and outbound ports is added. Inbound ports are used to describe use cases the core provides as interfaces to the inbound adapters. Reasoning: - In the past only outbound ports where described. Use cases should be used directly. This was a pragmatic approach to reduce the effort of implementing interfaces whith the same signature as the implementation. But this differs from the idea of making the implementation transparent to the inbound adapters. Refs: #39
1 parent a4a0fd2 commit 501a839

1 file changed

Lines changed: 97 additions & 44 deletions

File tree

modules/ROOT/pages/architecture/hexagonale_architecture.adoc

Lines changed: 97 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -36,23 +36,31 @@ image::hexagonal_component_architecture_overview.drawio.svg["devonfw hexagonal a
3636
// - Reservation.java
3737
// - Table.java
3838
// - ports
39-
// - StoreReservationPort.java
40-
// - service
41-
// - FindTableService.java --> diese logik Würde ich eher in einem RestaurantEntity abbilden
39+
// - in
40+
// - AddReservationPort.java
41+
// - CancelReservationPort.java
42+
// - AlterReservationPort.java
43+
// - AddTablePort.java
44+
// - RemoveTablePort.java
45+
// - out
46+
// - StoreReservationPort.java
4247
// - usecase
4348
// - AddReservationUc.java
49+
// - ManageReservationUc.java
4450
// - AddTableUc.java
51+
// - [service]
52+
// - [FindFreeTableService.java]
4553
// - adapter
4654
// - in
47-
// - rest --> Discussion point (why not more business drivem (what does it do))
55+
// - rest
4856
// - RestController.java
4957
// - model
5058
// - ReservationDto.java
5159
// - mapper
5260
// - ReservationMapper.java
5361
// - out
5462
// - jpa
55-
// - .java
63+
// - JpaAdapter.java
5664
// - model
5765
// - ReservationEntity.java
5866
// - TableEntity.java
@@ -63,39 +71,49 @@ image::hexagonal_component_architecture_overview.drawio.svg["devonfw hexagonal a
6371

6472
[source,plaintext]
6573
----
66-
application/
67-
├── config/
68-
│ └── Configuration.java
69-
├── core/
70-
│ ├── domain/
71-
│ │ ├── Customer.java
72-
│ │ ├── CustomerFactory.java
73-
│ │ ├── Reservation.java
74-
│ │ └── Table.java
75-
│ ├── ports/
76-
│ │ └── StoreReservationPort.java
77-
│ ├── service/
78-
│ │ └── FindTableService.java
79-
│ └── usecase/
80-
│ ├── AddReservationUc.java
81-
│ └── AddTableUc.java
82-
└── adapter/
83-
├── in/
84-
│ └── rest
85-
│ ├── RestController.java
86-
│ ├── model/
87-
│ │ └── ReservationDto.java
88-
│ └── mapper/
89-
│ └── ReservationMapper.java
90-
└── out/
91-
└── jpa/
92-
├── .java
93-
├── model/
94-
│ ├── ReservationEntity.java
95-
│ └── TableEntity.java
96-
└── mapper/
97-
├── ReservationJpaMapper.java
98-
└── TableJpaMapper.java
74+
.
75+
└── application/
76+
├── config/
77+
│ └── Configuration.java
78+
│ └── Configuration.java
79+
├── core/
80+
│ ├── domain/
81+
│ │ ├── Customer.java
82+
│ │ ├── CustomerFactory.java
83+
│ │ ├── Reservation.java
84+
│ │ └── Table.java
85+
│ ├── ports/
86+
│ │ ├── in/
87+
│ │ │ ├── AddReservationPort.java
88+
│ │ │ ├── CancelReservationPort.java
89+
│ │ │ ├── AlterReservationPort.java
90+
│ │ │ ├── AddTablePort.java
91+
│ │ │ └── RemoveTablePort.java
92+
│ │ └── out/
93+
│ │ └── StoreReservationPort.java
94+
│ ├── usecase/
95+
│ │ ├── AddReservationUc.java
96+
│ │ ├── ManageReservationUc.java
97+
│ │ └── AddTableUc.java
98+
│ └── [service]/
99+
│ └── [FindFreeTableService.java]
100+
└── adapter/
101+
├── in/
102+
│ └── rest/
103+
│ ├── RestController.java
104+
│ ├── model/
105+
│ │ └── ReservationDto.java
106+
│ └── mapper/
107+
│ └── ReservationMapper.java
108+
└── out/
109+
└── jpa/
110+
├── JpaAdapter.java
111+
├── model/
112+
│ ├── ReservationEntity.java
113+
│ └── TableEntity.java
114+
└── mapper/
115+
├── ReservationJpaMapper.java
116+
└── TableJpaMapper.java
99117
----
100118

101119
[cols="1,1", options="header"]
@@ -110,14 +128,49 @@ application/
110128
Related Factories or Builders are located here as well.
111129
The entities in our domain are usually rich.
112130

113-
| core.service
114-
| Services provide a reusable part of the applications business logic that is used by multiple use cases.
115-
116131
| core.usecase
117-
| Use Cases are the main entrypoint of the applications core. They validate the given input and orchestrate the domain entities, services and ports to implement a Business Use Case.
132+
| Use Cases are the main entrypoint of the applications core.
133+
They validate the given input and orchestrate the domain entities, services and ports to implement a Business Use Case.
134+
Usually a use case implementation should only include a small dedicated use case.
135+
Depending of the size and adjacency of the use cases a grouping might make sense (e.g. ManageTableUc)
118136

119137
| core.port
120-
| Ports are interfaces, that are used by the core and should be implemented by an according adapter. Ports should not be technology specific. One big advantage of the hexagonal architecture is, that the adapters can be changed without changing the core and therefore, without touching the business logic.
138+
| Ports are interfaces, that are used by the core and should be implemented by an according adapter.
139+
Ports should not be technology specific.
140+
One big advantage of the hexagonal architecture is, that the adapters can be changed without changing the core and therefore, without touching the business logic.
141+
It needs to be distinguished between inbound ports and outbound ports.
142+
143+
| core.port.in
144+
| Inbound ports are the entry of the application.
145+
They provide interfaces that are called from inbound adapters and hide the actual implementation.
146+
A proposal of structuring inbound ports is naming them like single use cases (e.g. CancelReservationPort).
147+
Each port should only provide a single method.
148+
.Design Decision
149+
[%collapsible]
150+
====
151+
Inbound Ports are not as relevant for the hexagonal architecture as the outbound ports.
152+
Outbound ports are used for the dependency inversion pattern.
153+
For inbound ports could also call the use cases directly.
154+
Therefore, an pragmatic alternative would be leaving out the inbound ports.
155+
156+
It was decided to include the inbound ports nonetheless. They should implement single use cases that are offered.
157+
Each interface should clearly mark the use case that contains only one method.
158+
Use cases from the interface might be grouped logically in the use case implementation class.
159+
====
160+
161+
| core.port.out
162+
| Outbound ports decouple the interaction with external systems.
163+
This might include other services that are called, files that are written, databases, event streaming and everything the application is actively triggering outside of the core.
164+
Outbound ports should describe the business need for the communication (e.g. StoreReservationPort). How this is then realized depends on the adapter that implements it.
165+
This way a technology can be easily replaced.
166+
For example storing the reservation could be be realized in a first prototype by writing the objects to a file.
167+
Later it could be replaced with a database.
168+
The core logic would be untouched by that.
169+
170+
| [optional] core.service
171+
| Services can be considered as business helper classes.
172+
They provide a reusable part of the applications business logic that is used by multiple use cases or that helps to structure the application in a logical way.
173+
Services are optional as they can be used, when there's a real need. Usually a use case should contain the business logic.
121174

122175
| adapter
123176
a| Adapters connect the application core to the surrounding context. They have the following tasks:
@@ -137,4 +190,4 @@ Inside the adapters further packages are differentiating the protocols that is u
137190
| Outbound adapters define outgoing connections where the application actively interacts with context outside.
138191
That can be database connections, file operations, API calls, message producing and many more.
139192
Inside the adapters further packages are differentiating the protocols that is used (e.g. `.jpa`).
140-
|===
193+
|===

0 commit comments

Comments
 (0)