Skip to content
This repository has been archived by the owner on Jul 23, 2024. It is now read-only.

Commit

Permalink
Add example for dealing with side effects
Browse files Browse the repository at this point in the history
  • Loading branch information
johanneswseitz committed Dec 17, 2013
1 parent ed7f2d0 commit 7b56f37
Show file tree
Hide file tree
Showing 14 changed files with 106 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package event_sourcing

case class BankAccount(owner:String, private var postings :Seq[MonetaryAmount] = Seq.empty) {

def balance = {
var balance = MonetaryAmount(0)
for (posting <- postings){
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package event_sourcing

import java.util.UUID

trait BankAccountRepository {
def getAccount(id:UUID) : BankAccount
def saveAccount(account:BankAccount)
}
12 changes: 9 additions & 3 deletions code-samples/src/main/scala/event_sourcing/ChangeOwner.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package event_sourcing

import java.util.UUID

// changeOwnerCommand
class ChangeOwner(newOwner:String) extends Command[BankAccount] {
def execute(bankAccount:BankAccount): BankAccount = {
bankAccount.changeOwner(newOwner)
class BankAccountCommandHandler(bankAccountRepo:BankAccountRepository) {
def handle(changeOwner:ChangeOwner) {
val account = bankAccountRepo.getAccount(changeOwner.accountID)
val modifiedAccount = account.changeOwner(changeOwner.newOwner)
bankAccountRepo.saveAccount(modifiedAccount)
}
}

case class ChangeOwner(accountID: UUID, newOwner:String) extends Command
// changeOwnerCommand
4 changes: 1 addition & 3 deletions code-samples/src/main/scala/event_sourcing/Command.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
package event_sourcing

trait Command[T] {
def execute(someObject:T) : T
}
trait Command
12 changes: 12 additions & 0 deletions code-samples/src/main/scala/event_sourcing/EventBus.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package event_sourcing

import event_sourcing.events.DomainEvent

object EventBus {
var eventStream = Seq.empty[DomainEvent]

def publishEvent(event:DomainEvent) : Unit = {
eventStream :+= event
print(event + " published")
}
}
54 changes: 54 additions & 0 deletions code-samples/src/main/scala/event_sourcing/OrderExample.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package event_sourcing

import java.util.UUID
import event_sourcing.events.DomainEvent

abstract class Order
case class BuyOrder(amount:MonetaryAmount, isin:String) extends Order
case class PerformBuyOrder(orderBookId:UUID, order:BuyOrder) extends Command
case class OrderConfirmation(orderId:UUID, order:BuyOrder)
case class OrderSentToBank(orderId:UUID, order:BuyOrder) extends DomainEvent
object OrderSentToBank {
def from(orderConfirmation:OrderConfirmation) = {
OrderSentToBank(orderConfirmation.orderId, orderConfirmation.order)
}
}

// dealingWithSideEffects

class BrokerCommandHandler (bankInterface:BankInterface,
orderBookRepository:OrderBookRepository) {
def handle(buyCommand:PerformBuyOrder) = {
var orderBook = orderBookRepository.load(buyCommand.orderBookId)
val validationResult = bankInterface.validate(buyCommand.order)
if (!validationResult.succeeded)
throw new InvalidOrderException(validationResult)
val orderConfirmation = bankInterface.perform(buyCommand.order)
val orderPerformedEvent = OrderSentToBank.from(orderConfirmation)
orderBook = orderBook.handle(orderPerformedEvent)
orderBookRepository.save(orderBook)
}
}

case class OrderBook(orders:Seq[Order] = Seq.empty) {
def handle(orderSentToBank:OrderSentToBank) : OrderBook = {
this.copy(orders :+ orderSentToBank.order)
}
}

// dealingWithSideEffects

trait BankInterface {
def validate(order:BuyOrder) : ValidationResult
def perform(order:BuyOrder) : OrderConfirmation
}

class InvalidOrderException(validationResult:ValidationResult) extends RuntimeException(validationResult.toString)

case class ValidationResult(succeeded:Boolean)
case class OrderFailedEvent(validationResult:ValidationResult) extends DomainEvent

trait OrderBookRepository {
def load(orderBookID:UUID) : OrderBook
def save(orderBook:OrderBook)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package event_sourcing
package event_sourcing.events

import java.util.UUID
import event_sourcing.MonetaryAmount

// depositEvent
case class DepositPerformed(account:UUID, amount:MonetaryAmount)
case class DepositPerformed(account:UUID, amount:MonetaryAmount) extends DomainEvent
// depositEvent
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package event_sourcing.events

trait DomainEvent
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@

### Contra {.cons}

-
- Replaying may inflict unexpected side effects
8 changes: 8 additions & 0 deletions pages/slides/06-how-eventsourcing-works/10-side-effects.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
## Dealing with side effects

How do we deal with side effects?

- Leave side effect to the command handler
{.slide}
- Record result as domain event, if necessary
{.slide}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@(dealingWithSideEffects)[../../../code-samples/src/main/scala/event_sourcing/OrderExample.scala]
3 changes: 3 additions & 0 deletions static/custom.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
div.codehilite {
line-height: 1;
}
Empty file removed static/themes/custom.css
Empty file.
5 changes: 3 additions & 2 deletions templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@

<!-- Required stylesheet -->
<link rel="stylesheet" href="{{ STATIC_URL }}/core/deck.core.css">
<link rel="stylesheet" href="{{ STATIC_URL }}/custom.css">

<!-- Extension CSS files go here. Remove or add as needed. -->
<link rel="stylesheet" media="screen" href="{{ STATIC_URL }}/960.css">
<link rel="stylesheet" media="screen" href="{{ STATIC_URL }}/pygments-colorful.css">
<link rel="stylesheet" media="screen" href="{{ STATIC_URL }}/960.css">
<link rel="stylesheet" media="screen" href="{{ STATIC_URL }}/pygments-colorful.css">
<link rel="stylesheet" media="screen" href="{{ STATIC_URL }}/extensions/goto/deck.goto.css">
<link rel="stylesheet" media="screen" href="{{ STATIC_URL }}/extensions/menu/deck.menu.css">
<link rel="stylesheet" media="screen" href="{{ STATIC_URL }}/extensions/navigation/deck.navigation.css">
Expand Down

0 comments on commit 7b56f37

Please sign in to comment.