by Daniel Westheide / @kaffeecoder
@ flatMap(Oslo), 14.05.2013
https://github.com/dwestheide/eventhub-flatmap2013
git clone git://github.com/dwestheide/eventhub-flatmap2013.git
cd eventhub-flatmap2013
git checkout step-0
mongod
sbt run
case class Meeting(
id: MeetingId,
name: String,
time: DateTime,
venue: Venue)
def moveToVenue(meeting: Meeting, newVenue: Venue): Meeting =
meeting.copy(venue = newVenue)
meetingRepo.fromIdentity(meetingId).foreach { meeting =>
meetingRepo.save(moveToVenue(meeting))
}
Wait, so our application state is effectively mutable? Doh!
In my domain, it is not important to know the previous states of an entity.
If my domain requires a history of what happened, of course I explicitly make that part of my domain model.
def moveToVenue(
meeting: Meeting,
venue: Venue): Validation[String, (MeetingEvent, Meeting)] =
if (canMoveToVenue(meeting, venue)) {
val event = MovedToVenue(new DateTime(), meeting.id, venue)
(event, this(meeting, event)).success
} else s"Cannot move $meeting to $venue".fail
(Aggregate, DomainEvent) => Aggregate
def apply(meeting: Meeting, event: MeetingEvent): Meeting =
event match {
case VenueChanged(_, _, aVenue) =>
meeting.copy(venue = aVenue)
}
def currentState(meetingId: MeetingId): Meeting =
eventStream(meetingId).foldLeft(Meeting())(apply)
Command-Query Responsibility Segregation
Only a single service can process commands on an aggregate
See Single Writer Principle by Martin Thompson