You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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
Copy file name to clipboardExpand all lines: modules/ROOT/pages/architecture/hexagonale_architecture.adoc
+97-44Lines changed: 97 additions & 44 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -36,23 +36,31 @@ image::hexagonal_component_architecture_overview.drawio.svg["devonfw hexagonal a
36
36
// - Reservation.java
37
37
// - Table.java
38
38
// - 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
42
47
// - usecase
43
48
// - AddReservationUc.java
49
+
// - ManageReservationUc.java
44
50
// - AddTableUc.java
51
+
// - [service]
52
+
// - [FindFreeTableService.java]
45
53
// - adapter
46
54
// - in
47
-
// - rest --> Discussion point (why not more business drivem (what does it do))
55
+
// - rest
48
56
// - RestController.java
49
57
// - model
50
58
// - ReservationDto.java
51
59
// - mapper
52
60
// - ReservationMapper.java
53
61
// - out
54
62
// - jpa
55
-
// - .java
63
+
// - JpaAdapter.java
56
64
// - model
57
65
// - ReservationEntity.java
58
66
// - TableEntity.java
@@ -63,39 +71,49 @@ image::hexagonal_component_architecture_overview.drawio.svg["devonfw hexagonal a
63
71
64
72
[source,plaintext]
65
73
----
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
99
117
----
100
118
101
119
[cols="1,1", options="header"]
@@ -110,14 +128,49 @@ application/
110
128
Related Factories or Builders are located here as well.
111
129
The entities in our domain are usually rich.
112
130
113
-
| core.service
114
-
| Services provide a reusable part of the applications business logic that is used by multiple use cases.
115
-
116
131
| 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)
118
136
119
137
| 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.
121
174
122
175
| adapter
123
176
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
137
190
| Outbound adapters define outgoing connections where the application actively interacts with context outside.
138
191
That can be database connections, file operations, API calls, message producing and many more.
139
192
Inside the adapters further packages are differentiating the protocols that is used (e.g. `.jpa`).
0 commit comments