SlideShare a Scribd company logo
1 of 44
Download to read offline
From ActiveRecord to
Events
Emanuele DelBono
@emadb
Customer
Address
Invoice
Items
Contacts
Role
Contract
Price
City
@emadb
I’m a software developer based
in Italy. I develop my apps in C#,
Javascript and some Ruby.
I’m a wannabe Ruby dev.
Lasagna architecture
View
Controller
Model (AR)
Database
O/RM
Active record
“An object that wraps a row in a database table or
view, encapsulates the database access, and adds
domain logic on that data.”
M. Fowler
Active record
1 table => 1 class
Too coupled with the database structure
No SRP
Database first
class User < ActiveRecord::Base
attr_accessible :email, :password
belongs_to :group
end
Get vs Post
def index
@products = Product.all
end
!
def create
@product = Product.new(product_params)
if @product.save
redirect_to @product
else
render action: 'new'
end
end
Active Record
A single model cannot be appropriate for
reporting, searching and transactional
behaviour.
Greg Young
Read vs Write
Reads and writes are two different concerns
Reads are simpler
Writes need logic
KEEP CALM
AND
STOP THINKING
IN CRUD
Command
Query
Responsibility
Segregation
CQRS
Presentation Layer
Handler
BL Repository
Write DB Read DB
Query Service
Denormalizer
CQRS
Fully normalized
Reads are easy
Writes became easier
SELECT fields FROM table (WHERE …)
Object state
id basket_id article_id quantity
1 4 8 1
2 3 8 3
3 3 6 1
4 4 5 1
Thinking in events
Every change is an event.
add_item
1
add_item
2
remove_item
1
add_item
3
time
Event Sourcing
Capture all changes to an application state as a
sequence of events.
M.Fowler
If the changes are stored in a database, we can rebuild the
state re-applying the events.
Event Sourcing
Presentation Layer
Bus
Handler
DMRepository
Event store Denormalizer
Query service
Read DB
Command
Events
Pros
• Encapsulation
• Separation of concern
• Simple storage
• Performance/Scaling
• Simple testing
• More information granularity
• Easy integration with other services
Cons
• Complex for simple scenarios
• Cost of infrastructure
• Long-living objects needs time to be reconstructed
• Tools needed (i.e. rebuild the state)
http://antwonlee.com/
Ingredients
• Rails app (no ActiveRecord)
• Redis (pub-sub)
• Sequel for querying data
• MongoDb (event store)
• Sqlite (Read db)
• Wisper (domain events)
Domain Model
Basket
BasketItem
Article
*
1
• Fully encapsulated (no accessors)
• Fully OOP
• Events for communication
• PORO
show_me_the_code.rb
include CommandExecutor
!
def add_to_basket
send_command AddToBasketCommand.new(
{"basket_id" => 42, "article_id" => params[:id].to_i})
redirect_to products_url
end
Controller
Bus
Command
POST /Products
add_to_basket
module CommandExecutor
!
def send_command (command)
class_name = command.class.name
channel = class_name.sub(/Command/, '')
@redis.publish channel, command.to_json
end
!
end
send_command
def consume(data)
basket = repository.get_basket(data["basket_id"])
article = repository.get_article(data["article_id"])
basket.add_item article
!
basket.commit
end
Bus
Handler
Command
handler
class Basket
include AggregateRootHelper
!
def add_item (item)
raise_event :item_added, {
basket_id: id,
item_code: item.code,
item_price: item.price
}
end
# ...
!
end
add_item
def raise_event(event, args)
@uncommited_events << {name: event, args: args}
send "on_#{event}", args
end
raise_event
DM (Basket)
Events
def get_item (item_code)
@items.select{|i| i.item_code == item_code}.try :first
end
!
def on_item_added (item)
get_item(item[:item_code]).try(:increase_quantity) ||
@items << BasketItem.new(item)
end
on_item_added
DM (Basket)
Events
def commit
while event = uncommited_events.shift
events_repository.store(id, event)
send_event event
end
end
commit
DM (Basket)
Event store
Event Store
def item_added(data)
db = Sequel.sqlite(AppSettings.sql_connection)
article = db[:products_view].where(code:
data[:item_code]).first
basket = db[:basket_view].where('basket_id = ? AND
article_id = ?', data[:basket_id], article[:id].to_i).first
if basket.nil?
#insert
else
db[:basket_view].where(id:
basket[:id]).update(quantity: (basket[:quantity] + 1))
end
end
denormalizer
Denormalizer
Read-Db
def index
@products=db[:basket_view]
end
Controller
Read DB
Query
GET /Products
index
Conclusion
• Stop thinking in CRUD
• Read and Write are different
• Domain model should be based on PORO
• CQRS/ES is useful in complex scenario
• Ruby power helps a lot (less infrastructure code)
https://github.com/emadb/revents

More Related Content

What's hot

A Separation of Concerns: Clean Architecture on Android
A Separation of Concerns: Clean Architecture on AndroidA Separation of Concerns: Clean Architecture on Android
A Separation of Concerns: Clean Architecture on Android
Outware Mobile
 
Avoiding the domino effect in our [micro]services (SOLID at macro-design level)
Avoiding the domino effect in our [micro]services (SOLID at macro-design level)Avoiding the domino effect in our [micro]services (SOLID at macro-design level)
Avoiding the domino effect in our [micro]services (SOLID at macro-design level)
CodelyTV
 

What's hot (20)

Clean architecture with ddd layering in php
Clean architecture with ddd layering in phpClean architecture with ddd layering in php
Clean architecture with ddd layering in php
 
Domain driven design and model driven development
Domain driven design and model driven developmentDomain driven design and model driven development
Domain driven design and model driven development
 
A Separation of Concerns: Clean Architecture on Android
A Separation of Concerns: Clean Architecture on AndroidA Separation of Concerns: Clean Architecture on Android
A Separation of Concerns: Clean Architecture on Android
 
Domain Driven Design(DDD) Presentation
Domain Driven Design(DDD) PresentationDomain Driven Design(DDD) Presentation
Domain Driven Design(DDD) Presentation
 
Domain Driven Rails
Domain Driven RailsDomain Driven Rails
Domain Driven Rails
 
High Concurrency Architecture at TIKI
High Concurrency Architecture at TIKIHigh Concurrency Architecture at TIKI
High Concurrency Architecture at TIKI
 
Mvc, mvp, mvvm...
Mvc, mvp, mvvm...Mvc, mvp, mvvm...
Mvc, mvp, mvvm...
 
Clean Architecture
Clean ArchitectureClean Architecture
Clean Architecture
 
Avoiding the domino effect in our [micro]services (SOLID at macro-design level)
Avoiding the domino effect in our [micro]services (SOLID at macro-design level)Avoiding the domino effect in our [micro]services (SOLID at macro-design level)
Avoiding the domino effect in our [micro]services (SOLID at macro-design level)
 
Clean architecture
Clean architectureClean architecture
Clean architecture
 
우아한 모노리스
우아한 모노리스우아한 모노리스
우아한 모노리스
 
Hexagonal architecture with Spring Boot
Hexagonal architecture with Spring BootHexagonal architecture with Spring Boot
Hexagonal architecture with Spring Boot
 
Hexagonal Architecture.pdf
Hexagonal Architecture.pdfHexagonal Architecture.pdf
Hexagonal Architecture.pdf
 
Brownfield Domain Driven Design
Brownfield Domain Driven DesignBrownfield Domain Driven Design
Brownfield Domain Driven Design
 
Domain Driven Design
Domain Driven Design Domain Driven Design
Domain Driven Design
 
Domain Driven Design Quickly
Domain Driven Design QuicklyDomain Driven Design Quickly
Domain Driven Design Quickly
 
CQRS and event sourcing
CQRS and event sourcingCQRS and event sourcing
CQRS and event sourcing
 
CQRS and Event Sourcing
CQRS and Event Sourcing CQRS and Event Sourcing
CQRS and Event Sourcing
 
Hexagonal architecture - message-oriented software design
Hexagonal architecture  - message-oriented software designHexagonal architecture  - message-oriented software design
Hexagonal architecture - message-oriented software design
 
Software architecture patterns
Software architecture patternsSoftware architecture patterns
Software architecture patterns
 

Similar to From ActiveRecord to EventSourcing

Ruby On Rails Tutorial
Ruby On Rails TutorialRuby On Rails Tutorial
Ruby On Rails Tutorial
sunniboy
 
Linq To The Enterprise
Linq To The EnterpriseLinq To The Enterprise
Linq To The Enterprise
Daniel Egan
 

Similar to From ActiveRecord to EventSourcing (20)

Ruby On Rails
Ruby On RailsRuby On Rails
Ruby On Rails
 
Ruby On Rails
Ruby On RailsRuby On Rails
Ruby On Rails
 
Ruby On Rails Tutorial
Ruby On Rails TutorialRuby On Rails Tutorial
Ruby On Rails Tutorial
 
Ruby On Rails
Ruby On RailsRuby On Rails
Ruby On Rails
 
Object- Relational Persistence in Smalltalk
Object- Relational Persistence in SmalltalkObject- Relational Persistence in Smalltalk
Object- Relational Persistence in Smalltalk
 
ISI work
ISI workISI work
ISI work
 
NDC Sydney 2019 - Microservices for building an IDE – The innards of JetBrain...
NDC Sydney 2019 - Microservices for building an IDE – The innards of JetBrain...NDC Sydney 2019 - Microservices for building an IDE – The innards of JetBrain...
NDC Sydney 2019 - Microservices for building an IDE – The innards of JetBrain...
 
React.js at Cortex
React.js at CortexReact.js at Cortex
React.js at Cortex
 
SQL in the Hybrid World
SQL in the Hybrid WorldSQL in the Hybrid World
SQL in the Hybrid World
 
Building Large Scale PHP Web Applications with Laravel 4
Building Large Scale PHP Web Applications with Laravel 4Building Large Scale PHP Web Applications with Laravel 4
Building Large Scale PHP Web Applications with Laravel 4
 
Ruby on rails for beginers
Ruby on rails for beginersRuby on rails for beginers
Ruby on rails for beginers
 
"Scala in Goozy", Alexey Zlobin
"Scala in Goozy", Alexey Zlobin "Scala in Goozy", Alexey Zlobin
"Scala in Goozy", Alexey Zlobin
 
Getting Started with Rails
Getting Started with RailsGetting Started with Rails
Getting Started with Rails
 
Linq To The Enterprise
Linq To The EnterpriseLinq To The Enterprise
Linq To The Enterprise
 
CouchDB
CouchDBCouchDB
CouchDB
 
Introduction To Ruby On Rails
Introduction To Ruby On RailsIntroduction To Ruby On Rails
Introduction To Ruby On Rails
 
Code decoupling from Symfony (and others frameworks) - PHP Conference Brasil ...
Code decoupling from Symfony (and others frameworks) - PHP Conference Brasil ...Code decoupling from Symfony (and others frameworks) - PHP Conference Brasil ...
Code decoupling from Symfony (and others frameworks) - PHP Conference Brasil ...
 
Overview of atg framework
Overview of atg frameworkOverview of atg framework
Overview of atg framework
 
Front Range PHP NoSQL Databases
Front Range PHP NoSQL DatabasesFront Range PHP NoSQL Databases
Front Range PHP NoSQL Databases
 
2007 SAPTech Ed
2007 SAPTech Ed2007 SAPTech Ed
2007 SAPTech Ed
 

More from Emanuele DelBono

More from Emanuele DelBono (13)

The simplest thing that could possibly work
The simplest thing that could possibly workThe simplest thing that could possibly work
The simplest thing that could possibly work
 
Una crescita armoniosa
Una crescita armoniosaUna crescita armoniosa
Una crescita armoniosa
 
A sip of Elixir
A sip of ElixirA sip of Elixir
A sip of Elixir
 
React.js in real world apps.
React.js in real world apps. React.js in real world apps.
React.js in real world apps.
 
An introduction to React.js
An introduction to React.jsAn introduction to React.js
An introduction to React.js
 
Ruby seen by a C# developer
Ruby seen by a C# developerRuby seen by a C# developer
Ruby seen by a C# developer
 
Ruby loves DDD
Ruby loves DDDRuby loves DDD
Ruby loves DDD
 
An introduction to knockout.js
An introduction to knockout.jsAn introduction to knockout.js
An introduction to knockout.js
 
Node azure
Node azureNode azure
Node azure
 
Da programmatore a CEO
Da programmatore a CEODa programmatore a CEO
Da programmatore a CEO
 
Sinatra for REST services
Sinatra for REST servicesSinatra for REST services
Sinatra for REST services
 
Test driving an MVVM App
Test driving an MVVM AppTest driving an MVVM App
Test driving an MVVM App
 
Mocking
MockingMocking
Mocking
 

Recently uploaded

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 

Recently uploaded (20)

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 

From ActiveRecord to EventSourcing