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
Copy file name to clipboardExpand all lines: dddsample/src/site/apt/characterization.apt
+34-5Lines changed: 34 additions & 5 deletions
Original file line number
Diff line number
Diff line change
@@ -29,7 +29,15 @@
29
29
30
30
{Aggregates}
31
31
32
-
In real life most things are connected, directly or indirectly. Mimicking this approach when building large software systems tend to bring unnecessary complexity and poor performance. DDD provides tactics to help you sort these things out, aggregates being one of the most important ones. Aggregates help with decoupling of large structures by setting rules for relations between entities. Aggregates can also have properties, methods, and invariants that doesn't fit within one single class. Java and other OO-languages typically miss specific language constructs to handle aggregates and in the sample application responsibilities that belong to an aggregate is most often implemented in the aggregate root. <<<{{{xref/se/citerus/dddsample/domain/model/cargo/package-summary.html}cargo}}>>>: cargo is the central aggregate in the sample application. <<<Cargo>>> is the aggregate root and the aggregate also contains the <Value Objects> <<<DeliveryHistory>>>, <<<Itinereray>>>, <<<Leg>>> and a few more classes. <<<{{{xref/se/citerus/dddsample/domain/model/handling/package-summary.html}handling}}>>>: handling is another important aggregate. It contains the HandlingEvents that are registered throughout a cargo's progress from <<<RECEIVED>>> to <<<CLAIMED>>>. The <<<HandlingEvent>>>s have a relation to the <<<Cargo>>> for which the event belongs, this is allowed since <<<HandlingEvent>>> is an aggregate root and so is <<<Cargo>>>. The main reason for not making <<<HandlingEvent>>> part of the cargo aggregate is performance. <<<HandlingEvent>>>s are received from external parties and systems, e.g. warehouse management systems, port handling systems, that call our <<<{{{xref/se/citerus/dddsample/domain/service/HandlingEventService.html}HandlingEventService}}>>> webservice. The number of events can be very high and it is important that our webservice can dispatch the remote calls quickly. To be able to support this use case we need to handle the remote webservice calls asynchronously, i.e. we do not want to load the big cargo structure for each received <<<HandlingEvent>>>. Since all relationships in an aggregate must be handled synchronously we put the <<<HandlingEvent>>> in an aggregate of its own and we are able processes the events quickly and at the same time eliminate dead-locking situations in the system. <Editors note: We are aware that this example may need a little more work to drive the full benefits of aggregates home. This is one of the problems with a small sample app, real-world complexity is hard to simulate.>
32
+
In real life most things are connected, directly or indirectly. Mimicking this approach when building large software systems tend to bring unnecessary complexity and poor performance. DDD provides tactics to help you sort these things out, aggregates being one of the most important ones. Aggregates help with decoupling of large structures by setting rules for relations between entities. Aggregates can also have properties, methods, and invariants that doesn't fit within one single class. Java and other OO-languages typically miss specific language constructs to handle aggregates and in the sample application responsibilities that belong to an aggregate is most often implemented in the aggregate root.
33
+
34
+
<<<{{{xref/se/citerus/dddsample/domain/model/cargo/package-summary.html}cargo}}>>>: cargo is the central aggregate in the sample application. <<<Cargo>>> is the aggregate root and the aggregate also contains the <Value Objects> <<<DeliveryHistory>>>, <<<Itinereray>>>, <<<Leg>>> and a few more classes.
35
+
36
+
<<<{{{xref/se/citerus/dddsample/domain/model/handling/package-summary.html}handling}}>>>: handling is another important aggregate. It contains the HandlingEvents that are registered throughout a cargo's progress from <<<RECEIVED>>> to <<<CLAIMED>>>. The <<<HandlingEvent>>>s have a relation to the <<<Cargo>>> for which the event belongs, this is allowed since <<<HandlingEvent>>> is an aggregate root and so is <<<Cargo>>>.
37
+
38
+
The main reason for not making <<<HandlingEvent>>> part of the cargo aggregate is performance. <<<HandlingEvent>>>s are received from external parties and systems, e.g. warehouse management systems, port handling systems, that call our <<<{{{xref/se/citerus/dddsample/domain/service/HandlingEventService.html}HandlingEventService}}>>> webservice. The number of events can be very high and it is important that our webservice can dispatch the remote calls quickly. To be able to support this use case we need to handle the remote webservice calls asynchronously, i.e. we do not want to load the big cargo structure for each received <<<HandlingEvent>>>. Since all relationships in an aggregate must be handled synchronously we put the <<<HandlingEvent>>> in an aggregate of its own and we are able processes the events quickly and at the same time eliminate dead-locking situations in the system.
39
+
40
+
<Editors note: We are aware that this example may need a little more work to drive the full benefits of aggregates home. This is one of the problems with a small sample app, real-world complexity is hard to simulate.>
33
41
34
42
[images/aggregates.gif]
35
43
@@ -47,10 +55,31 @@
47
55
48
56
*Domain services
49
57
50
-
Domain services are a natural part of the domain and provide services such as message forwarding etc. In the sample application the <<<{{{xref/se/citerus/dddsample/domain/service/RoutingService.html}RoutingService}}>>> provides access to the routing system and is used to find possible routes for a give specification.
58
+
Domain services are expressed in terms of the ubiquitous language and the domain types, i.e.
59
+
the method arguments and the return values are proper domain classes. Sometimes, only the service
60
+
interface (<what> the service does) is part of the domain layer, but the implementation (<how> the service does it)
61
+
is part of the application layer. This is analogous to how repository interfaces are part of the domain layer, but the
62
+
Hibernate implementations are not.
51
63
52
-
*Application services
64
+
A good example of that is the <<<{{{xref/se/citerus/dddsample/domain/service/RoutingService.html}RoutingService}}>>>,
65
+
which provides access to the routing system and is used to find possible routes for a give specification.
66
+
The {{{xref/se/citerus/dddsample/application/routing/ExternalRoutingService.html}implementation}} communicates with
67
+
another team's context and translates to and from an external API and data model.
68
+
69
+
On the other hand, if the service is possible to implement strictly using the domain layer,
70
+
both the interface and the implementation are part of the domain layer. That is the case for the
71
+
<<<{{{xref/se/citerus/dddsample/domain/service/impl/BookingServiceImpl.html}BookingService}}>>>, for example.
53
72
54
-
The application services in the sample application are responsible for driving workflow and coordinating transaction management (by use of the declarative transaction management support in Spring). They also provide a high-level abstraction for clients to use when interacting with the domain. These services are typically designed to support specific use cases or stories. The <<<{{{xref/se/citerus/dddsample/domain/service/TrackingService.html}TrackingService}}>>> is used by the public web application for tracking cargo and the <<<{{{xref/se/citerus/dddsample/domain/service/BookingService.html}BookingService}}>>> is used by the internal administration application for booking new cargo.
73
+
*Application services
55
74
56
-
The services are all defined in types of the domain, i.e. the method arguments and the return values are proper domain classes. In some situation, e.g. when dealing with graphs of lazy-loaded domain objects or when passing services' return values over network boundaries, the services are wrapped in facades. The facades handle ORM session management issues and/or convert the domain objects to more portable {{{http://martinfowler.com/eaaCatalog/dataTransferObject.html}Data Transfer Objects}}) that can be tailored to specific use cases. See <<<{{{xref/se/citerus/dddsample/application/remoting/BookingServiceFacadeImpl.html}BookingServiceFacadeImpl}}>>> for an example.
75
+
The application services in the sample application are responsible for driving workflow and coordinating
76
+
transaction management (by use of the declarative transaction management support in Spring).
77
+
They also provide a high-level abstraction for clients to use when interacting with the domain.
78
+
These services are typically designed to support specific use cases or fulfill technical requirements (web services, etc).
79
+
80
+
In some situations, e.g. when dealing with graphs of lazy-loaded
81
+
domain objects or when passing services' return values over network boundaries, the services are wrapped in facades.
82
+
The facades handle ORM session management issues and/or convert the domain objects to more portable
83
+
{{{http://martinfowler.com/eaaCatalog/dataTransferObject.html}Data Transfer Objects}}) that can be tailored
84
+
to specific use cases.
85
+
See <<<{{{xref/se/citerus/dddsample/application/remoting/BookingServiceFacadeImpl.html}BookingServiceFacadeImpl}}>>> for an example.
0 commit comments