1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/// Trait for representing an **Aggregate Root**.
///
/// > An Aggregate is a group of associated objects which are considered as one unit with regard to
/// > data changes. The Aggregate is demarcated by a boundary which separates the objects inside
/// > from those outside. Each Aggregate has one root. The root is an Entity, and it is the only
/// > object accessible from outside. The root can hold references to any of the aggregate objects,
/// > and the other objects can hold references to each other, but an outside object can hold
/// > references only to the root object. If there are other Entities inside the boundary, the
/// > identity of those entities is local, making sense only inside the aggregate.
///
/// # Examples
///
/// Derive its implementation using the [ddd_rs::AggregateRoot](crate::AggregateRoot) macro:
///
/// ```
/// // The `AggregateRoot` usually holds references to other entities, acting as a means to access
/// // and even modify them.
/// //
/// // Note that we also need to derive the `Entity` trait, since an `AggregateRoot` is an `Entity`.
/// #[derive(ddd_rs::AggregateRoot, ddd_rs::Entity)]
/// struct MyAggregateRoot {
/// #[entity(id)]
/// id: u32,
/// foo: Foo,
/// bars: Vec<Bar>,
/// }
///
/// #[derive(ddd_rs::Entity)]
/// struct Foo {
/// #[entity(id)]
/// id: u32,
/// foo: String,
/// }
///
/// #[derive(ddd_rs::Entity)]
/// struct Bar {
/// #[entity(id)]
/// id: String,
/// bar: u32,
/// }
/// ```
/// Extensions to the [AggregateRoot] behavior.
///
/// # Examples
///
/// Implement this trait explicitly when you need non-trivial use-cases, such as registering domain
/// events on immutable instances of your entity:
///
/// ```
/// use std::sync::Mutex;
///
/// use ddd_rs::domain::AggregateRootEx;
///
/// // The `DomainEvent` will usually be an arithmetic enum type, in order to allow for multiple
/// // distinguishable event kinds within a single type.
/// #[derive(Debug, PartialEq)]
/// enum MyDomainEvent {
/// DidSomething { something: String },
/// DidSomethingElse { something_else: String },
/// }
///
/// // The `AggregateRoot` owns a list of its own `DomainEvent`s.
/// //
/// // The [Interior Mutability](https://doc.rust-lang.org/reference/interior-mutability.html)
/// // pattern may be relevant when semantically immutable actions need to register domain events.
/// #[derive(ddd_rs::AggregateRoot, ddd_rs::Entity)]
/// struct MyAggregateRoot {
/// #[entity(id)]
/// id: u32,
/// domain_events: Mutex<Vec<MyDomainEvent>>,
/// }
///
/// // The aggregate root's methods may register domain events upon different actions.
/// impl MyAggregateRoot {
/// pub fn new(id: u32) -> Self {
/// Self {
/// id,
/// domain_events: Default::default(),
/// }
/// }
///
/// pub fn do_something(&self, something: impl ToString) {
/// let something = something.to_string();
///
/// // Do something...
///
/// self.register_domain_event(MyDomainEvent::DidSomething { something });
/// }
///
/// pub fn do_something_else(&mut self, something_else: impl ToString) {
/// let something_else = something_else.to_string();
///
/// // Do something else...
///
/// self.register_domain_event(MyDomainEvent::DidSomethingElse { something_else });
/// }
///
/// fn register_domain_event(&self, domain_event: <Self as AggregateRootEx>::DomainEvent) {
/// let mut domain_events = self.domain_events.lock().unwrap();
///
/// domain_events.push(domain_event);
/// }
/// }
///
/// impl AggregateRootEx for MyAggregateRoot {
/// type DomainEvent = MyDomainEvent;
///
/// fn take_domain_events(&mut self) -> Vec<Self::DomainEvent> {
/// let mut domain_events = self.domain_events.lock().unwrap();
///
/// domain_events.drain(..).collect()
/// }
/// }
///
/// let aggregate_root = MyAggregateRoot::new(42);
///
/// // This registers a `MyDomainEvent::DidSomething` event.
/// //
/// // Note that this happens under an immutable reference to the aggregate.
/// aggregate_root.do_something("foo");
///
/// let mut aggregate_root = aggregate_root;
///
/// // This registers a `MyDomainEvent::DidSomethingElse` event.
/// aggregate_root.do_something_else("bar");
///
/// // Take the domain events and assert that they are gone afterwards.
/// let domain_events = aggregate_root.take_domain_events();
///
/// assert_eq!(
/// domain_events[0],
/// MyDomainEvent::DidSomething {
/// something: "foo".to_string()
/// }
/// );
/// assert_eq!(
/// domain_events[1],
/// MyDomainEvent::DidSomethingElse {
/// something_else: "bar".to_string()
/// }
/// );
///
/// assert!(aggregate_root.take_domain_events().is_empty());
/// ```
///
/// Otherwise, derive its implementation using the [ddd_rs::AggregateRoot](crate::AggregateRoot)
/// macro and the `#[aggregate_root(domain_events)]` attribute:
///
/// ```
/// use ddd_rs::domain::AggregateRootEx;
///
/// #[derive(Debug, PartialEq)]
/// enum MyDomainEvent {
/// DidSomething { something: String },
/// }
///
/// #[derive(ddd_rs::AggregateRoot, ddd_rs::Entity)]
/// struct MyAggregateRoot {
/// #[entity(id)]
/// id: u32,
/// #[aggregate_root(domain_events)]
/// domain_events: Vec<MyDomainEvent>,
/// }
///
/// impl MyAggregateRoot {
/// pub fn new(id: u32) -> Self {
/// Self {
/// id,
/// domain_events: Default::default(),
/// }
/// }
///
/// pub fn do_something(&mut self, something: impl ToString) {
/// let something = something.to_string();
///
/// // Do something...
///
/// // The `register_domain_event` method is automatically derived.
/// self.register_domain_event(MyDomainEvent::DidSomething { something });
/// }
/// }
///
/// // This time around, the aggregate may only register domain events on mutable methods.
/// let mut aggregate_root = MyAggregateRoot::new(42);
///
/// aggregate_root.do_something("foo");
///
/// let domain_events = aggregate_root.take_domain_events();
///
/// assert_eq!(
/// domain_events[0],
/// MyDomainEvent::DidSomething {
/// something: "foo".to_string()
/// }
/// );
///
/// assert!(aggregate_root.take_domain_events().is_empty());
/// ```