SlideShare a Scribd company logo
1 of 229
The aggregate is dead!
Long live the aggregate!
@_sara_p_
Sara Pellegrini
@MilanSavic14
Milan Savic
The aggregate
The aggregate
The aggregate
An aggregate is a cluster of associated objects
that we treat as a unit for the purpose of data changes.
From blue book - Domain-Driven Design: Tackling Complexity in the Heart of Software - Eric Evans
The aggregate is ... confusing
From theory to practice
From theory to practice
Cluster the ENTITIES and VALUE OBJECTS into AGGREGATES and define
boundaries around each.
From blue book - Domain-Driven Design: Tackling Complexity in the Heart of Software - Eric Evans
From theory to practice
Cluster the ENTITIES and VALUE OBJECTS into AGGREGATES and define
boundaries around each.
Choose one ENTITY to be the root of each AGGREGATE, and control all access to
the objects inside the boundary through the root.
From blue book - Domain-Driven Design: Tackling Complexity in the Heart of Software - Eric Evans
From theory to practice
Cluster the ENTITIES and VALUE OBJECTS into AGGREGATES and define
boundaries around each.
Choose one ENTITY to be the root of each AGGREGATE, and control all access to
the objects inside the boundary through the root. Allow external objects to hold
reference to the root only.
From blue book - Domain-Driven Design: Tackling Complexity in the Heart of Software - Eric Evans
Event Storming
Education domain
Event Storming
Education domain
1) A course cannot accept more than N students
Event Storming
Education domain
1) A course cannot accept more than N students
2) N, the Course Capacity, can change any time
to any positive integer different from the current one
Event Storming
Education domain
1) A course cannot accept more than N students
2) N, the Course Capacity, can change any time
to any positive integer different from the current one
(even if the number of currently subscribed students is larger than the new value)
time
Course
Created
Event
time
Course
Created
Event
Student
Subscribed
to Course
Event
time
Course
Created
Event
Student
Subscribed
to Course
Event
Student
Unsubscribed
from Course
Event
time
Course
Created
Event
Student
Subscribed
to Course
Event
Student
Unsubscribed
from Course
Event
Course
Capacity
Changed
Event
time
Course
Created
Event
Student
Subscribed
to Course
Event
Student
Unsubscribed
from Course
Event
Course
Capacity
Changed
Event
Create
Course
Command
Subscribe
Student to
Course
Command
Unsubscribe
Student to
Course
Command
Update
Course
Capacity
Command
time
Story Telling
Story Telling
Storytelling is at the heart of human communication.
Story Telling
Storytelling is at the heart of human communication.
Storytelling does not require any special competence/skill.
Story Telling
Storytelling is at the heart of human communication.
Storytelling does not require any special competence/skill.
It helps break down the barriers between technicians and business experts.
The aggregate is the boundary of consistency
The aggregate is the boundary of consistency
When a change to any object with the aggregate boundary is committed, all
invariants of the whole aggregate must be satisfied.
From blue book - Domain-Driven Design: Tackling Complexity in the Heart of Software - Eric Evans
Course
Created
Event
Student
Subscribed
to Course
Event
Student
Unsubscribed
from Course
Event
Course
Capacity
Changed
Event
Create
Course
Command
Subscribe
Student to
Course
Command
Unsubscribe
Student to
Course
Command
Update
Course
Capacity
Command
Course
Created
Event
Student
Subscribed
to Course
Event
Student
Unsubscribed
from Course
Event
Course
Capacity
Changed
Event
Create
Course
Command
Subscribe
Student to
Course
Command
Unsubscribe
Student to
Course
Command
Update
Course
Capacity
Command
1) A course cannot accept more than N students
2) N, the Course Capacity, can change any time to any
positive integer different from the current one
Course
Created
Event
Student
Subscribed
to Course
Event
Student
Unsubscribed
from Course
Event
Course
Capacity
Changed
Event
Create
Course
Command
Subscribe
Student to
Course
Command
Unsubscribe
Student to
Course
Command
Update
Course
Capacity
Command
Course
Course
Course Course
1) A course cannot accept more than N student
2) N, the Course Capacity, can change any time to any
positive integer different from the current one
Aggregate does not fit
Story Telling
Aggregate does not fit with Story Telling
Aggregate does not fit with Story Telling
It is not naturally part of the story: the story teller is forced to add this element
Aggregate does not fit with Story Telling
It is not naturally part of the story: the story teller is forced to add this element
Should business experts understand what a consistency boundary is?
Aggregate does not fit with Story Telling
It is not naturally part of the story: the story teller is forced to add this element
Should business experts understand what a consistency boundary is?
Leads back to the old modelling-first/data centric approach.
Moves the focus from the behavior to the model.
Aggregate Mixes technical and
business aspects
The nouns become our aggregates
Course
Created
Event
Student
Subscribed
to Course
Event
Student
Unsubscribed
from Course
Event
Course
Capacity
Changed
Event
Create
Course
Command
Subscribe
Student to
Course
Command
Unsubscribe
Student to
Course
Command
Update
Course
Capacity
Command
Course
Course
Course Course
The nouns become our aggregates
Course
Created
Event
Student
Subscribed
to Course
Event
Student
Unsubscribed
from Course
Event
Course
Capacity
Changed
Event
Create
Course
Command
Subscribe
Student to
Course
Command
Unsubscribe
Student to
Course
Command
Update
Course
Capacity
Command
Course
Course
Course Course
The course
Course
Create Course Command
Subscribe Student to Course
Command
Unsubscribe Student to Course
Command
Update Course Capacity
Command
Course Created
Event
Student Subscribed to Course
Event
Student Unsubscribed from
Course Event
Course Capacity Changed
Event
The COURSE
aggregate
<<Aggregate Root>>
Course Subscription
*
The COURSE
aggregate
<<Aggregate Root>>
Course Subscription
*
Subscribe Student to Course
Command
Unsubscribe Student to Course
Command
The COURSE
aggregate
<<Aggregate Root>>
Course Subscription
*
Subscribe Student to Course
Command
Unsubscribe Student to Course
Command
The COURSE
aggregate
<<Aggregate Root>>
Course Subscription
*
Subscribe Student to Course
Command
Unsubscribe Student to Course
Command
Update Course Capacity
Command
The COURSE
aggregate
<<Aggregate Root>>
Course Subscription
*
Subscribe Student to Course
Command
Unsubscribe Student to Course
Command
Update Course Capacity
Command
Event sourced COURSE aggregate
Course Created Event
Student Subscribed to Course
Event
Student Unsubscribed from
Course Event
Course Capacity Changed
Event
Event sourced COURSE aggregate
Course Created Event
Student Subscribed to Course
Event
Student Unsubscribed from
Course Event
Course Capacity Changed
Event
Subscribe Student to Course
Command
Unsubscribe Student to Course
Command
Event sourced COURSE aggregate
Course Created Event
Student Subscribed to Course
Event
Student Unsubscribed from
Course Event
Course Capacity Changed
Event
Subscribe Student to Course
Command
Unsubscribe Student to Course
Command
Update Course
Capacity Command
Event Storming of this problem:
Education domain
1) A course cannot accept more than N students
2) N, the Course Capacity, can change any time
to any positive integer different from the current one
(even if the number of currently subscribed students is larger than the new value)
3) The course title can change any time
to any title different from the current one
Event Storming of this problem:
Education domain
1) A course cannot accept more than N students
2) N, the Course Capacity, can change any time
to any positive integer different from the current one
(even if the number of currently subscribed students is larger than the new value)
3) The course title can change any time
to any title different from the current one
Course
Renamed
Event
Course
Renamed
Event
Rename
Course
Command
Course
Renamed
Event
Rename
Course
Command
Course
The larger the Aggregate
the greater the contention
The boundary of consistency
is also the boundary of concurrency
Concurrent command execution
Concurrent command execution
Update Course
Capacity Command
Rename Course
Command
Concurrent command execution
Update Course
Capacity Command
Rename Course
Command
<<Aggregate Root>>
Course Subscription
*
<<Aggregate Root>>
Course Subscription
*
Concurrent command execution
Update Course
Capacity Command
Rename Course
Command
<<Aggregate Root>>
Course Subscription
*
<<Aggregate Root>>
Course Subscription
*
Concurrent command execution
Update Course
Capacity Command
Rename Course
Command
<<Aggregate Root>>
Course Subscription
*
<<Aggregate Root>>
Course Subscription
*
Concurrent command execution
Update Course
Capacity Command
Rename Course
Command
<<Aggregate Root>>
Course Subscription
*
<<Aggregate Root>>
Course Subscription
*
Alternative solution
Alternative solution
<<Aggregate Root>>
Course Subscription
*
<<Aggregate Root>>
Course
Subscriptions
Subscription
*
Alternative solution: CourseInfo & CourseSubscription
<<Aggregate Root>>
Course
Info
Course CourseInfo & CourseSubscriptions
Course
More contention
Simpler
CourseInfo & CourseSubscriptions
Course
More contention
Simpler
CourseInfo & CourseSubscriptions
Less contention
Course
More contention
Simpler
CourseInfo & CourseSubscriptions
Less contention
Additional complexity
➔ Management of multiple aggregates
What if model changes…
What if model changes…
Now what???
What if model changes…
Now what???
State Persisted Aggregates
- Script
Event Sourced Aggregates
- ???
What if model changes…
Now what???
State Persisted Aggregates
- Script
Event Sourced Aggregates
- ???
What if model changes…
Now what???
State Persisted Aggregates
- Script
Event Sourced Aggregates
- ???
What if model changes…
Now what???
State Persisted Aggregates
- Script
Event Sourced Aggregates
- ???
Refactoring with Event Sourcing
Course
Created
….
Course
Renamed
Course
Capacity
Changed
….
Course
Capacity
Changed
…. ….
Refactoring with Event Sourcing
Course
Created
….
Course
Renamed
Course
Capacity
Changed
….
Course
Capacity
Changed
…. ….
….
Refactoring with Event Sourcing
Course
Created
….
Course
Renamed
Course
Capacity
Changed
….
Course
Capacity
Changed
…. ….
Course
Subscriptions
Created
….
Course
Info
Created
Refactoring with Event Sourcing
Course
Created
….
Course
Renamed
Course
Capacity
Changed
….
Course
Capacity
Changed
…. ….
Course
Subscriptions
Created
….
…. ….
Course
Info
Created
Refactoring with Event Sourcing
Course
Created
….
Course
Renamed
Course
Capacity
Changed
….
Course
Capacity
Changed
…. ….
Course
Subscriptions
Created
….
Course
Renamed
…. ….
Course
Info
Created
Refactoring with Event Sourcing
Course
Created
….
Course
Renamed
Course
Capacity
Changed
….
Course
Capacity
Changed
…. ….
Course
Subscriptions
Created
….
Course
Renamed
Course
Capacity
Changed
….
Course
Capacity
Changed
…. ….
Course
Info
Created
Refactoring with Event Sourcing
Course
Created
….
Course
Renamed
Course
Capacity
Changed
….
Course
Capacity
Changed
…. ….
Course
Subscriptions
Created
….
Course
Renamed
Course
Capacity
Changed
….
Course
Capacity
Changed
…. ….
Course
Info
Created
Aggregates
Are Hard to Refactor
Event Storming of this problem:
Education domain
1) A course cannot accept more than N students
2) N, the Course Capacity, can change any time
to any positive integer different from the current one
(even if the number of currently subscribed students is larger than the new value)
3) The course title can change any time
to any title different from the current one
4) The student cannot join more than 10 courses
Event Storming of this problem:
Education domain
1) A course cannot accept more than N students
2) N, the Course Capacity, can change any time
to any positive integer different from the current one
(even if the number of currently subscribed students is larger than the new value)
3) The course title can change any time
to any title different from the current one
4) The student cannot join more than 10 courses
Student
Created
Event
time
Student
Created
Event
time
Create
Student
Command
Student
Created
Event
Student
Subscribed
to Course
Event
time
Create
Student
Command
Student
Created
Event
Student
Subscribed
to Course
Event
Student
Unsubscribed
from Course
Event
time
Create
Student
Command
Create
Student
Command
Subscribe
Student to
Course
Command
Student
Created
Event
Student
Subscribed
to Course
Event
Unsubscribe
Student from
Course
Command
Student
Unsubscribed
from Course
Event
time
Course
Created
Event
Student
Subscribed
to Course
Event
Student
Unsubscribed
from Course
Event
Course
Capacity
Changed
Event
Create
Course
Command
Subscribe
Student to
Course
Command
Unsubscribe
Student to
Course
Command
Update
Course
Capacity
Command
Course
Course
Course Course
Create
Student
Command
Subscribe
Student to
Course
Command
Student
Created
Event
Student
Subscribed
to Course
Event
Unsubscribe
Student from
Course
Command
Student
Unsubscribed
from Course
Event
4) The student cannot join more than 10 courses
Create
Student
Command
Subscribe
Student to
Course
Command
Student
Created
Event
Student
Subscribed
to Course
Event
Unsubscribe
Student from
Course
Command
Student
Unsubscribed
from Course
Event
Student Student Student
4) The student cannot join more than 10 courses
Create Student
Command
Subscribe Student to
Course Command
Student Created
Event
Student Subscribed
Course Event
Student
Unsubscribe Student from
Course Command
Student Unsubscribed from
Course Event
The STUDENT aggregate
<<Aggregate Root>>
Student Subscription
*
We need some form of synchronization...
We need some form of synchronization...
Subscribe Student to
Course Command
Saga
We need some form of synchronization...
Subscribe Student to
Course Command
Saga
We need some form of synchronization...
Subscribe Student to
Course Command
Subscribe Student to
Course Command
Subscribe Student to
Course Command
Student
Course
1
1
Saga
We need some form of synchronization...
Subscribe Student to
Course Command
Subscribe Student to
Course Command
Subscribe Student to
Course Command
Student Subscribed
Course Event
Student Subscribed
Course Event
Student
Course
1
1
Saga
We need some form of synchronization...
Subscribe Student to
Course Command
Subscribe Student to
Course Command
Subscribe Student to
Course Command
Student Subscribed
Course Event
Student
Course
1
1
Saga
We need some form of synchronization...
Subscribe Student to
Course Command
Subscribe Student to
Course Command
Subscribe Student to
Course Command
Student Subscribed
Course Event
Student
Course
revert
1
1
2
Saga
We need some form of synchronization...
Subscribe Student to
Course Command
Subscribe Student to
Course Command
Subscribe Student to
Course Command
Student Subscribed
Course Event
Student
Course
revert
Unsubscribe Student
to Course Command
Student Unsubscribed
Course Event
Student
1
1
2
3
Transactions that span
Multiple Aggregates
Could Cause
Unnecessary Complexity
It's just a long transaction...
It's just a long transaction...
Long transaction are very common when the business rule spans bounded contexts.
It's just a long transaction...
Long transaction are very common when the business rule spans bounded contexts.
But when the rule spans multiple aggregates in the same bounded context?
It's just a long transaction...
Long transaction are very common when the business rule spans bounded contexts.
But when the rule spans multiple aggregates in the same bounded context?
Is this a necessary complexity or it can be avoided?
● Does not fit the story telling
● Does not fit the story telling
● Puts focus on model instead of behaviour
● Does not fit the story telling
● Puts focus on model instead of behaviour
● Mixes technical and business aspects
● Does not fit the story telling
● Puts focus on model instead of behaviour
● Mixes technical and business aspects
● Can cause unnecessary contention
● Does not fit the story telling
● Puts focus on model instead of behaviour
● Mixes technical and business aspects
● Can cause unnecessary contention
● Can cause unnecessary complexity
● Does not fit the story telling
● Puts focus on model instead of behaviour
● Mixes technical and business aspects
● Can cause unnecessary contention
● Can cause unnecessary complexity
● Hard to refactor
Is there a better way to implement the command model?
Is there a better way to implement the command model?
-
F
o
c
u
s
o
n
B
e
h
a
v
i
o
r
-
Lets restart from… story telling
Lets restart from… story telling
Lets restart from… story telling
Decision Decision Decision
Decision Decision
Lets restart from… story telling
Decision Decision Decision
Decision Decision
Lets restart from… story telling
Decision Decision Decision
Decision Decision
Lets restart from… story telling
Decision Decision Decision
Decision Decision
Lets restart from… story telling
Decision Decision Decision
Decision Decision
Lets restart from… story telling
Decision Decision Decision
Decision Decision
Focus on the decision
Focus on the decision
Decision block = Message handler
The message handler knows what it needs to make a decision
Focus on the decision
Decision block = Message handler
The message handler knows what it needs to make a decision
Event sourcing
Event sourcing
Event sourcing provides a huge advantage because it decouples
the persistence from the model needed for taking the decision
The message handler can build on the fly any model needed for
taking the decision starting from the correct event stream
Event sourcing
Event sourcing provides a huge advantage because it decouples
the persistence from the model needed for taking the decision
The message handler can build on the fly any model needed for
making the decision starting from the correct event stream
Event sourcing
Course
Created
Student
Created
….
Course
Renamed
….
Course
Capacity
Changed
….
Event store
Event sourcing
Course
Created
Student
Created
….
Course
Renamed
….
Course
Capacity
Changed
….
Update
Course
Capacity
Command
Event store
Event sourcing
Course
Created
Student
Created
….
Course
Renamed
….
Course
Capacity
Changed
….
Update
Course
Capacity
Command
Event store
Event sourcing
Course
Created
Student
Created
….
Course
Renamed
….
Course
Capacity
Changed
….
Update
Course
Capacity
Command
Decision based on the following
business rules:
● The course exists
● The new capacity is different from prev
Command Handler
Event store
Event sourcing
Course
Created
Student
Created
….
Course
Renamed
….
Course
Capacity
Changed
….
Update
Course
Capacity
Command
Decision based on the following
business rules:
● The course exists
● The new capacity is different from prev
Command Handler
Event store
Event sourcing
Course
Created
Student
Created
….
Course
Renamed
….
Course
Capacity
Changed
….
Update
Course
Capacity
Command
Decision based on the following
business rules:
● The course exists
● The new capacity is different from prev
Command Handler
Event store
Course
Capacity
Changed
Event Store
events = stream(AggregateIdentifier id)
events = stream(StreamQuery query)
Event Store
events = stream(AggregateIdentifier id)
events = stream(StreamQuery query)
Event Store
events = stream(AggregateIdentifier id)
events = stream(StreamQuery query)
Stream Query
Stream Query
{"StreamQuery": {
"DomainIdentifiers": [
{ "course": "7d9b35b6-b46a-43bf-8e4c-eb7e6c3a487d" }
], "Types": [
"CourseCreated",
"CourseCapacityChanged"]
}
}
Stream Query
{"StreamQuery": {
"DomainIdentifiers": [
{ "course": "7d9b35b6-b46a-43bf-8e4c-eb7e6c3a487d" }
], "Types": [
"CourseCreated",
"CourseCapacityChanged"]
}
}
Stream Query
{"StreamQuery": {
"DomainIdentifiers": [
{ "course": "7d9b35b6-b46a-43bf-8e4c-eb7e6c3a487d" }
], "Types": [
"CourseCreated",
"CourseCapacityChanged"]
}
}
Stream Query
{"StreamQuery": {
"DomainIdentifiers": [
{ "course": "7d9b35b6-b46a-43bf-8e4c-eb7e6c3a487d" }
], "Types": [
"CourseCreated",
"CourseCapacityChanged"]
}
}
The focus is on the Message Handler
The focus is on the Message Handler
Less waste of resources
No modelling phase
More flexibility
The focus is on the Message Handler
Less waste of resources
No upfront modelling required
The focus is on the Message Handler
Less waste of resources
No upfront modelling required
More flexibility
Concurrency
Course
Created
Student
Created
….
Course
Renamed
….
Course
Capacity
Changed
….
Concurrency
Update
Course
Capacity
Command
Rename
Course
Command
Course
Created
Student
Created
….
Course
Renamed
….
Course
Capacity
Changed
….
Concurrency
Update
Course
Capacity
Command
Rename
Course
Command
Course
Created
Student
Created
….
Course
Renamed
….
Course
Capacity
Changed
….
Decision based on the following
business rules:
● The course exists
● The new capacity is different from prev
Decision based on the following
business rules:
● The course exists
● The new name is different from prev one
Concurrency
Update
Course
Capacity
Command
Rename
Course
Command
Course
Created
Student
Created
….
Course
Renamed
….
Course
Capacity
Changed
….
Decision based on the following
business rules:
● The course exists
● The new capacity is different from prev
Decision based on the following
business rules:
● The course exists
● The new name is different from prev one
Concurrency
Update
Course
Capacity
Command
Rename
Course
Command
Course
Created
Student
Created
….
Course
Renamed
….
Course
Capacity
Changed
….
Course
Capacity
Changed
Course
Renamed
Decision based on the following
business rules:
● The course exists
● The new capacity is different from prev
Decision based on the following
business rules:
● The course exists
● The new name is different from prev one
Concurrency
Update
Course
Capacity
Command
Subscribe
Student to
Course
Command
Course
Created
Student
Created
….
Course
Renamed
….
Course
Capacity
Changed
….
Concurrency
Update
Course
Capacity
Command
Subscribe
Student to
Course
Command
Course
Created
Student
Created
….
Course
Renamed
….
Course
Capacity
Changed
….
Decision based on the following
business rules:
● The course exists
● The new capacity is different from prev
Decision based on the following
business rules:
● The course exists
● The number of current subscription is
LOWER than the capacity (N)
Concurrency
Update
Course
Capacity
Command
Subscribe
Student to
Course
Command
Course
Created
Student
Created
….
Course
Renamed
….
Course
Capacity
Changed
….
Decision based on the following
business rules:
● The course exists
● The new capacity is different from prev
Decision based on the following
business rules:
● The course exists
● The number of current subscription is
LOWER than the capacity (N)
Concurrency
Update
Course
Capacity
Command
Subscribe
Student to
Course
Command
Course
Created
Student
Created
….
Course
Renamed
….
Course
Capacity
Changed
….
Course
Capacity
Changed
Decision based on the following
business rules:
● The course exists
● The new capacity is different from prev
Decision based on the following
business rules:
● The course exists
● The number of current subscription is
LOWER than the capacity (N)
Concurrency
Update
Course
Capacity
Command
Subscribe
Student to
Course
Command
Course
Created
Student
Created
….
Course
Renamed
….
Course
Capacity
Changed
….
Course
Capacity
Changed
Student
Subscribed
to Course
Decision based on the following
business rules:
● The course exists
● The new capacity is different from prev
Decision based on the following
business rules:
● The course exists
● The number of current subscription is
LOWER than the capacity (N)
Concurrency
Update
Course
Capacity
Command
Subscribe
Student to
Course
Command
Course
Created
Student
Created
….
Course
Renamed
….
Course
Capacity
Changed
….
Course
Capacity
Changed
Student
Subscribed
to Course
Decision based on the following
business rules:
● The course exists
● The new capacity is different from prev
Decision based on the following
business rules:
● The course exists
● The number of current subscription is
LOWER than the capacity (N)
Event Store
append(Event[] events)
append(Event[] events, StreamQuery query, EventIdentifier lastEvent)
Event Store
append(Event[] events)
append(Event[] events, StreamQuery query, EventIdentifier lastEvent)
Event Store
append(Event[] events)
append(Event[] events, StreamQuery query, EventIdentifier lastEvent)
Conditional append
if (lastEventIdentifier(query) != lastEvent) {
rejectAppend();
}
Conditional append
if (lastEventIdentifier(query) != lastEvent) {
rejectAppend();
}
Warranty of consistency
The event(s) are appended only if the there is no other event matching the query
that has appended after the lastEvent
Concurrency
Update
Course
Capacity
Command
Subscribe
Student to
Course
Command
Course
Created
Student
Created
….
Course
Renamed
….
Course
Capacity
Changed
….
Decision based on the following
business rules:
● The course exists
● The new capacity is different from prev
Decision based on the following
business rules:
● The course exists
● The number of current subscription is
LOWER than the capacity (N)
...592
Concurrency
Update
Course
Capacity
Command
Subscribe
Student to
Course
Command
Course
Created
Student
Created
….
Course
Renamed
….
Course
Capacity
Changed
….
Course
Capacity
Changed
Decision based on the following
business rules:
● The course exists
● The new capacity is different from prev
Decision based on the following
business rules:
● The course exists
● The number of current subscription is
LOWER than the capacity (N)
...592 ...593
append(event, query, ...592)
Concurrency
Update
Course
Capacity
Command
Subscribe
Student to
Course
Command
Course
Created
Student
Created
….
Course
Renamed
….
Course
Capacity
Changed
….
Course
Capacity
Changed
Student
Subscribed
to Course
Decision based on the following
business rules:
● The course exists
● The new capacity is different from prev
Decision based on the following
business rules:
● The course exists
● The number of current subscription is
LOWER than the capacity (N)
...592 ...593
append(event, query, ...592)
Concurrency
Update
Course
Capacity
Command
Subscribe
Student to
Course
Command
Course
Created
Student
Created
….
Course
Renamed
….
Course
Capacity
Changed
….
Course
Capacity
Changed
Student
Subscribed
to Course
Decision based on the following
business rules:
● The course exists
● The new capacity is different from prev
Decision based on the following
business rules:
● The course exists
● The number of current subscription is
LOWER than the capacity (N)
...592 ...593
append(event, query, ...592)
...593 != ...592
Concurrency
Update
Course
Capacity
Command
Subscribe
Student to
Course
Command
Course
Created
Student
Created
….
Course
Renamed
….
Course
Capacity
Changed
….
Course
Capacity
Changed
Student
Subscribed
to Course
Decision based on the following
business rules:
● The course exists
● The new capacity is different from prev
Decision based on the following
business rules:
● The course exists
● The number of current subscription is
LOWER than the capacity (N)
...592 ...593
append(event, query, ...592)
...593 != ...592
Limited contention
Limited contention
Before the contention boundaries were those of the aggregate...
Now, the contention boundaries are those of the stream query
Limited contention
Before the contention boundaries were those of the aggregate...
Now, the contention boundaries are those of the stream query
Does not seem very artificial?
Student
Subscribed
to Course
Event
Student
Unsubscribed
from Course
Event
Subscribe
Student to
Course
Command
Unsubscribe
Student to
Course
Command
Course Course
Student
Subscribed
to Course
Event
Student
Unsubscribed
from Course
Event
Subscribe
Student to
Course
Command
Unsubscribe
Student to
Course
Command
Student Student
Course
Created
Student
Created
….
Course
Renamed
Course
Capacity
Changed
….
Student
Subscribed
to Course
Student
Subscribed
to Course
Course
Created
Student
Created
….
Course
Renamed
Course
Capacity
Changed
….
Student
Subscribed
to Course
Student
Subscribed
to Course
From the story-telling perspective
Student
Subscribed
to Course
Event
Student
Unsubscribed
from Course
Event
Subscribe
Student to
Course
Command
Unsubscribe
Student to
Course
Command
From the story-telling perspective
Student
Subscribed
to Course
Event
Student
Unsubscribed
from Course
Event
Subscribe
Student to
Course
Command
Unsubscribe
Student to
Course
Command
Decision Decision
Course
Created
Student
Created
….
Course
Renamed
Course
Capacity
Changed
….
Student
Subscribed
to Course
Student
Subscribed
to Course
Course
Created
Student
Created
….
Course
Renamed
Course
Capacity
Changed
….
Student
Subscribed
to Course
Student
Subscribed
to Course
Course
Created
Student
Created
….
Course
Renamed
Course
Capacity
Changed
….
Student
Subscribed
to Course
Student
Subscribed
to Course
Pure Events
Course
Created
Student
Created
….
Course
Renamed
Course
Capacity
Changed
….
Student
Subscribed
to Course
Student
Subscribed
to Course
Course
Created
Student
Created
….
Course
Renamed
Course
Capacity
Changed
….
Student
Subscribed
to Course
Student
Subscribed
to Course
Pure Events
Course: jdsj4 Student:gfh3j ---
Course: jdsj4 Course: jdsj4
--- Course: jdsj4 Student: gfh3j
Tags (Domain Identifiers)
Course
Created
Student
Created
….
Course
Renamed
Course
Capacity
Changed
….
Student
Subscribed
to Course
Student
Subscribed
to Course
Pure Events
Course: jdsj4 Student:gfh3j ---
Course: jdsj4 Course: jdsj4
--- Course: jdsj4 Student: gfh3j
Tags (Domain Identifiers)
Course
Created
Student
Created
….
Course
Renamed
Course
Capacity
Changed
….
Student
Subscribed
to Course
Course: jdsj4 Student:gfh3j ---
Course: jdsj4 Course: jdsj4
---
Course: jdsj4
Student: gfh3j
Pure Events
Tags (Domain Identifiers)
Subscribe
Student to
Course
Command
Subscribe
Student to
Course
Command
Decision based on the following business rules:
- A course cannot accept more than N student
- The student cannot join more than 10 courses
Student
Subscribed
to Course
Event
Subscribe
Student to
Course
Command
Decision based on the following business rules:
- A course cannot accept more than N student
- The student cannot join more than 10 courses
{"StreamQuery": {
"DomainIdentifiers": [
{ "course": "jdsj4..." },
{ "student": "gfh3..." }
], "Types": [
"Course Created",
"Student Created",
"Course Capacity Changed",
"Student Subscribed to Course",
"Student Unsubscribed from Course"]
}}
{"StreamQuery": {
"DomainIdentifiers": [
{ "course": "jdsj4..." },
{ "student": "gfh3..." }
], "Types": [
"Course Created",
"Student Created",
"Course Capacity Changed",
"Student Subscribed to Course",
"Student Unsubscribed from Course"]
}}
Subscribe
Student to
Course
Command
Decision based on the following business rules:
- A course cannot accept more than N student
- The student cannot join more than 10 courses
Course
Created
Student
Created
….
Course
Renamed
Course
Capacity
Changed
….
Course: jdsj4 Student:gfhl3 ---
Course: jdsj4 Course: jdsj4
---
Pure Events
Tags
(Domain Identifiers)
Subscribe
Student to
Course
Command
Decision based on the following business rules:
- A course cannot accept more than N student
- The student cannot join more than 10 courses
Course
Created
Student
Created
….
Course
Renamed
Course
Capacity
Changed
….
Course: jdsj4 Student:gfhl3 ---
Course: jdsj4 Course: jdsj4
---
Pure Events
Tags
(Domain Identifiers)
Student
Subscribed
to Course
Event
Subscribe
Student to
Course
Command
Decision based on the following business rules:
- A course cannot accept more than N student
- The student cannot join more than 10 courses
Course
Created
Student
Created
….
Course
Renamed
Course
Capacity
Changed
….
Course: jdsj4 Student:gfhl3 ---
Course: jdsj4 Course: jdsj4
---
Pure Events
Tags
(Domain Identifiers)
Student
Subscribed
to Course
Course: jdsj4
Student: gfh3
Append Events with Domain Identifiers
append(DomainEvent[] events)
append(DomainEvent[] events, StreamQuery query, EventIdentifier lastEvent)
Domain Event
DomainEvent {
Event event,
DomainIdentifiers[] identifiers
}
Domain Identifier
KEY: VALUE
Domain Identifier
KEY: VALUE
The concept in the domain
Domain Identifier
KEY: VALUE
The concept in the domain The unique instance identifier
Domain Identifier
KEY: VALUE
The concept in the domain The unique instance identifier
This is just an example,
They can be anything, as far as they are unique inside the bounded context
Student
Subscribed
to Course
Event
Subscribe
Student to
Course
Command
Decision based on the following business rules:
- A course cannot accept more than N students
- The student cannot join more than 10 courses
Course
Created
Student
Created
….
Course
Renamed
Course
Capacity
Changed
….
Course: jdsj4 Student:gfh3j ---
Course: jdsj4 Course: jdsj4
---
Pure Events
Tags
(Domain Identifiers)
Student
Subscribed
to Course
Course: jdsj4
Student: gfh3j
Student
Subscribed
to Course
Event
Subscribe
Student to
Course
Command
Decision based on the following business rules:
- A course cannot accept more than N students
- The student cannot join more than 10 courses
Course
Created
Student
Created
….
Course
Renamed
Course
Capacity
Changed
….
Course: jdsj4 Student:gfh3j ---
Course: jdsj4 Course: jdsj4
---
Pure Events
Tags
(Domain Identifiers)
Student
Subscribed
to Course
Course: jdsj4
Student: gfh3j
Course
Fully
Booked
Event
Course Fully
Booked
Course: jdsj4
append(DomainEvent[] events, StreamQuery query, EventIdentifier lastEvent)
append(DomainEvent[] events, StreamQuery query, EventIdentifier lastEvent)
[
Event event = Student subscribed to Course,
DomainIdentifiers[] identifiers = [{course: "jdsj4..."}, {student:"gfh3..."}],
Event event = Course Fully Booked,
DomainIdentifiers[] identifiers = [{course: "jdsj4..."}]
]
append(DomainEvent[] events, StreamQuery query, EventIdentifier lastEvent)
[
Event event = Student subscribed to Course,
DomainIdentifiers[] identifiers = [{course: "jdsj4..."}, {student:"gfh3..."}],
Event event = Course Fully Booked,
DomainIdentifiers[] identifiers = [{course: "jdsj4..."}]
]
DomainIdentifiers: [ {course: "jdsj4..."},
{student:"gfh3..."}],
Types: [ "Course Created", "Student Created", "Course Capacity Changed",
"Student Subscribed to Course", "Student Unsubscribed from Course"]}
append(DomainEvent[] events, StreamQuery query, EventIdentifier lastEvent)
[
Event event = Student subscribed to Course,
DomainIdentifiers[] identifiers = [{course: "jdsj4..."}, {student:"gfh3..."}],
Event event = Course Fully Booked,
DomainIdentifiers[] identifiers = [{course: "jdsj4..."}]
]
DomainIdentifiers: [ {course: "jdsj4..."},
{student:"gfh3..."}],
Types: [ "Course Created", "Student Created", "Course Capacity Changed",
"Student Subscribed to Course", "Student Unsubscribed from Course"]}
...593
Pure events
Pure events
An event does NOT belong to an aggregate
An event is just a description of a fact that is important for the business
An event can be related to one or multiple domain concepts, addressed by their
Domain Identifiers
Pure events
An event does NOT belong to an aggregate
An event is just a description of a fact that is important for the business
An event can be related to one or multiple domain concepts, addressed by their
Domain Identifiers
Pure events
An event does NOT belong to an aggregate
An event is just a description of a fact that is important for the business
An event can be related to one or multiple domain concepts
addressed by their Domain Identifiers
Less complexity
Less complexity
No owner of the event
The business decision can easily involve several domain concepts
The decision is taken in one place
Less complexity
No owner of the event
The business decision can easily involve several domain concepts
The decision is taken in one place
Less complexity
No owner of the event
The business decision can easily involve several domain concepts
The decision is taken in one place
Saga
Subscribe Student to
Course Command
Subscribe Student to
Course Command
Subscribe Student to
Course Command
Student Subscribed
Course Event
Student
Course
revert
Unsubscribe Student
to Course Command
Student Unsubscribed
Course Event
Student
1
1
2
3
More flexibility
Event sourcing provides a huge advantage because it decouples the persistence
from the model needed for taking the decision
Refactoring
● Change the StreamQuery
● Add/Remove Domain Identifiers
More flexibility
Event sourcing provides a huge advantage because it decouples the persistence
from the model needed for taking the decision
Refactoring
● Change the StreamQuery
More flexibility
Event sourcing provides a huge advantage because it decouples the persistence
from the model needed for taking the decision
Refactoring
● Change the StreamQuery
● Add/Remove Domain Identifiers
Dynamic Consistency Boundary - aka DCB
Dynamic Consistency Boundary - aka DCB
● Perfect match with story telling
Dynamic Consistency Boundary - aka DCB
● Perfect match with story telling
● Focus on behaviour instead of model
Dynamic Consistency Boundary - aka DCB
● Perfect match with story telling
● Focus on behaviour instead of model
● Less contention
Dynamic Consistency Boundary - aka DCB
● Perfect match with story telling
● Focus on behaviour instead of model
● Less contention
● Less complexity
Dynamic Consistency Boundary - aka DCB
● Perfect match with story telling
● Focus on behaviour instead of model
● Less contention
● Less complexity
● Simpler to refactor
The aggregate is dead
Long live the aggregate
There is no pattern that can replace common sense.
@_sara_p_
Sara Pellegrini
@MilanSavic14
Milan Savic

More Related Content

What's hot

.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven Design
.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven Design.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven Design
.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven DesignNETFest
 
Domain Driven Design(DDD) Presentation
Domain Driven Design(DDD) PresentationDomain Driven Design(DDD) Presentation
Domain Driven Design(DDD) PresentationOğuzhan Soykan
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven DesignRyan Riley
 
Hexagonal architecture for java applications
Hexagonal architecture for java applicationsHexagonal architecture for java applications
Hexagonal architecture for java applicationsFabricio Epaminondas
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven DesignNader Albert
 
Domain Driven Design (Ultra) Distilled
Domain Driven Design (Ultra) DistilledDomain Driven Design (Ultra) Distilled
Domain Driven Design (Ultra) DistilledNicola Costantino
 
From framework coupled code to #microservices through #DDD /by @codelytv
From framework coupled code to #microservices through #DDD /by @codelytvFrom framework coupled code to #microservices through #DDD /by @codelytv
From framework coupled code to #microservices through #DDD /by @codelytvCodelyTV
 
Evolving a Clean, Pragmatic Architecture - A Craftsman's Guide
Evolving a Clean, Pragmatic Architecture - A Craftsman's GuideEvolving a Clean, Pragmatic Architecture - A Craftsman's Guide
Evolving a Clean, Pragmatic Architecture - A Craftsman's GuideVictor Rentea
 
Kotlin vs Java | Edureka
Kotlin vs Java | EdurekaKotlin vs Java | Edureka
Kotlin vs Java | EdurekaEdureka!
 
Vertical Slicing Architectures
Vertical Slicing ArchitecturesVertical Slicing Architectures
Vertical Slicing ArchitecturesVictor Rentea
 
Hexagonal architecture - message-oriented software design
Hexagonal architecture  - message-oriented software designHexagonal architecture  - message-oriented software design
Hexagonal architecture - message-oriented software designMatthias Noback
 
Hexagonal Architecture.pdf
Hexagonal Architecture.pdfHexagonal Architecture.pdf
Hexagonal Architecture.pdfVladimirRadzivil
 
Clean Code I - Best Practices
Clean Code I - Best PracticesClean Code I - Best Practices
Clean Code I - Best PracticesTheo Jungeblut
 
Clean architecture
Clean architectureClean architecture
Clean architectureLieven Doclo
 
Clean architecture
Clean architectureClean architecture
Clean architecture.NET Crowd
 
Micro services Architecture
Micro services ArchitectureMicro services Architecture
Micro services ArchitectureAraf Karsh Hamid
 

What's hot (20)

.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven Design
.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven Design.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven Design
.NET Fest 2019. Halil Ibrahim Kalkan. Implementing Domain Driven Design
 
Domain Driven Design(DDD) Presentation
Domain Driven Design(DDD) PresentationDomain Driven Design(DDD) Presentation
Domain Driven Design(DDD) Presentation
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
 
Hexagonal architecture for java applications
Hexagonal architecture for java applicationsHexagonal architecture for java applications
Hexagonal architecture for java applications
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
 
Domain Driven Design (Ultra) Distilled
Domain Driven Design (Ultra) DistilledDomain Driven Design (Ultra) Distilled
Domain Driven Design (Ultra) Distilled
 
From framework coupled code to #microservices through #DDD /by @codelytv
From framework coupled code to #microservices through #DDD /by @codelytvFrom framework coupled code to #microservices through #DDD /by @codelytv
From framework coupled code to #microservices through #DDD /by @codelytv
 
Evolving a Clean, Pragmatic Architecture - A Craftsman's Guide
Evolving a Clean, Pragmatic Architecture - A Craftsman's GuideEvolving a Clean, Pragmatic Architecture - A Craftsman's Guide
Evolving a Clean, Pragmatic Architecture - A Craftsman's Guide
 
Kotlin vs Java | Edureka
Kotlin vs Java | EdurekaKotlin vs Java | Edureka
Kotlin vs Java | Edureka
 
Clean Architecture
Clean ArchitectureClean Architecture
Clean Architecture
 
Vertical Slicing Architectures
Vertical Slicing ArchitecturesVertical Slicing Architectures
Vertical Slicing Architectures
 
Hexagonal architecture - message-oriented software design
Hexagonal architecture  - message-oriented software designHexagonal architecture  - message-oriented software design
Hexagonal architecture - message-oriented software design
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
 
Hexagonal Architecture.pdf
Hexagonal Architecture.pdfHexagonal Architecture.pdf
Hexagonal Architecture.pdf
 
Clean Code I - Best Practices
Clean Code I - Best PracticesClean Code I - Best Practices
Clean Code I - Best Practices
 
Clean architecture
Clean architectureClean architecture
Clean architecture
 
Spring Core
Spring CoreSpring Core
Spring Core
 
Vault
VaultVault
Vault
 
Clean architecture
Clean architectureClean architecture
Clean architecture
 
Micro services Architecture
Micro services ArchitectureMicro services Architecture
Micro services Architecture
 

Similar to The aggregate is dead! Long live the aggregate! - SpringIO.pdf

OOP-Advanced Programming with c++
OOP-Advanced Programming with c++OOP-Advanced Programming with c++
OOP-Advanced Programming with c++Mohamed Essam
 
V Jornadas eMadrid sobre "Educación Digital". Cristina Conati, University of ...
V Jornadas eMadrid sobre "Educación Digital". Cristina Conati, University of ...V Jornadas eMadrid sobre "Educación Digital". Cristina Conati, University of ...
V Jornadas eMadrid sobre "Educación Digital". Cristina Conati, University of ...eMadrid network
 
Multi task learning stepping away from narrow expert models 7.11.18
Multi task learning stepping away from narrow expert models 7.11.18Multi task learning stepping away from narrow expert models 7.11.18
Multi task learning stepping away from narrow expert models 7.11.18Cloudera, Inc.
 
The Google Cloud Adoption Framework
The Google Cloud Adoption FrameworkThe Google Cloud Adoption Framework
The Google Cloud Adoption Frameworkrun_frictionless
 
OOP-Advanced_Programming.pptx
OOP-Advanced_Programming.pptxOOP-Advanced_Programming.pptx
OOP-Advanced_Programming.pptxMohamed Essam
 
Architecture for Flow w/ Wardley Mapping, Domain-Driven Design, and Team Topo...
Architecture for Flow w/ Wardley Mapping, Domain-Driven Design, and Team Topo...Architecture for Flow w/ Wardley Mapping, Domain-Driven Design, and Team Topo...
Architecture for Flow w/ Wardley Mapping, Domain-Driven Design, and Team Topo...Susanne Kaiser
 
Shivani Chouhan ,BCA ,2nd Year
Shivani Chouhan ,BCA ,2nd YearShivani Chouhan ,BCA ,2nd Year
Shivani Chouhan ,BCA ,2nd Yeardezyneecole
 
Bhanu Pratap Singh ,BCA
Bhanu Pratap Singh ,BCA Bhanu Pratap Singh ,BCA
Bhanu Pratap Singh ,BCA dezyneecole
 
Assignment 1. Coretta leases a workshop, in which she weaves rug.docx
Assignment 1. Coretta leases a workshop, in which she weaves rug.docxAssignment 1. Coretta leases a workshop, in which she weaves rug.docx
Assignment 1. Coretta leases a workshop, in which she weaves rug.docxtrippettjettie
 
Microservices Manchester: Microservices and Macro-Economics - A Shorty Histor...
Microservices Manchester: Microservices and Macro-Economics - A Shorty Histor...Microservices Manchester: Microservices and Macro-Economics - A Shorty Histor...
Microservices Manchester: Microservices and Macro-Economics - A Shorty Histor...OpenCredo
 
Nikita Totlani ,BCA 2nd year
Nikita Totlani ,BCA 2nd year Nikita Totlani ,BCA 2nd year
Nikita Totlani ,BCA 2nd year dezyneecole
 
Deepika Mittal,BCA ,2nd Year
Deepika Mittal,BCA ,2nd Year Deepika Mittal,BCA ,2nd Year
Deepika Mittal,BCA ,2nd Year dezyneecole
 
Design patterns - How much we understand and know ??
Design patterns - How much we understand and know ??Design patterns - How much we understand and know ??
Design patterns - How much we understand and know ??Vinay Raj
 

Similar to The aggregate is dead! Long live the aggregate! - SpringIO.pdf (20)

Kill Aggregate
Kill AggregateKill Aggregate
Kill Aggregate
 
OOP-Advanced Programming with c++
OOP-Advanced Programming with c++OOP-Advanced Programming with c++
OOP-Advanced Programming with c++
 
Lecce Presentation2008
Lecce Presentation2008Lecce Presentation2008
Lecce Presentation2008
 
V Jornadas eMadrid sobre "Educación Digital". Cristina Conati, University of ...
V Jornadas eMadrid sobre "Educación Digital". Cristina Conati, University of ...V Jornadas eMadrid sobre "Educación Digital". Cristina Conati, University of ...
V Jornadas eMadrid sobre "Educación Digital". Cristina Conati, University of ...
 
Multi task learning stepping away from narrow expert models 7.11.18
Multi task learning stepping away from narrow expert models 7.11.18Multi task learning stepping away from narrow expert models 7.11.18
Multi task learning stepping away from narrow expert models 7.11.18
 
The Google Cloud Adoption Framework
The Google Cloud Adoption FrameworkThe Google Cloud Adoption Framework
The Google Cloud Adoption Framework
 
OOP-Advanced_Programming.pptx
OOP-Advanced_Programming.pptxOOP-Advanced_Programming.pptx
OOP-Advanced_Programming.pptx
 
Architecture for Flow w/ Wardley Mapping, Domain-Driven Design, and Team Topo...
Architecture for Flow w/ Wardley Mapping, Domain-Driven Design, and Team Topo...Architecture for Flow w/ Wardley Mapping, Domain-Driven Design, and Team Topo...
Architecture for Flow w/ Wardley Mapping, Domain-Driven Design, and Team Topo...
 
Chounta@paws
Chounta@pawsChounta@paws
Chounta@paws
 
Shivani Chouhan ,BCA ,2nd Year
Shivani Chouhan ,BCA ,2nd YearShivani Chouhan ,BCA ,2nd Year
Shivani Chouhan ,BCA ,2nd Year
 
Bhanu Pratap Singh ,BCA
Bhanu Pratap Singh ,BCA Bhanu Pratap Singh ,BCA
Bhanu Pratap Singh ,BCA
 
Assignment 1. Coretta leases a workshop, in which she weaves rug.docx
Assignment 1. Coretta leases a workshop, in which she weaves rug.docxAssignment 1. Coretta leases a workshop, in which she weaves rug.docx
Assignment 1. Coretta leases a workshop, in which she weaves rug.docx
 
Microservices Manchester: Microservices and Macro-Economics - A Shorty Histor...
Microservices Manchester: Microservices and Macro-Economics - A Shorty Histor...Microservices Manchester: Microservices and Macro-Economics - A Shorty Histor...
Microservices Manchester: Microservices and Macro-Economics - A Shorty Histor...
 
Ooad
OoadOoad
Ooad
 
Ooad
OoadOoad
Ooad
 
Oos Short Q N
Oos Short Q NOos Short Q N
Oos Short Q N
 
"Paradigm Shifting" Presentation
"Paradigm Shifting" Presentation"Paradigm Shifting" Presentation
"Paradigm Shifting" Presentation
 
Nikita Totlani ,BCA 2nd year
Nikita Totlani ,BCA 2nd year Nikita Totlani ,BCA 2nd year
Nikita Totlani ,BCA 2nd year
 
Deepika Mittal,BCA ,2nd Year
Deepika Mittal,BCA ,2nd Year Deepika Mittal,BCA ,2nd Year
Deepika Mittal,BCA ,2nd Year
 
Design patterns - How much we understand and know ??
Design patterns - How much we understand and know ??Design patterns - How much we understand and know ??
Design patterns - How much we understand and know ??
 

Recently uploaded

办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptkotipi9215
 
What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....kzayra69
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfPower Karaoke
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsAhmed Mohamed
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEEVICTOR MAESTRE RAMIREZ
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...Christina Lin
 
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)jennyeacort
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
 

Recently uploaded (20)

办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.ppt
 
What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdf
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
 
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
 

The aggregate is dead! Long live the aggregate! - SpringIO.pdf