Submit Search
Upload
DDD, Rails and persistence
•
0 likes
•
908 views
M
Michał Łomnicki
Follow
How to use Postgres JSON store to persist DDD aggregates
Read less
Read more
Software
Report
Share
Report
Share
1 of 22
Download now
Download to read offline
Recommended
RequireJS
RequireJS
Tim Doherty
Asset management with Zend Framework 2
Asset management with Zend Framework 2
Stefano Valle
Managing JavaScript Dependencies With RequireJS
Managing JavaScript Dependencies With RequireJS
Den Odell
Asynchronous Module Definition (AMD) used for Dependency Injection (DI) and MVVM
Asynchronous Module Definition (AMD) used for Dependency Injection (DI) and MVVM
Hugh Anderson
Oracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data Streaming
Oracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data Streaming
Michael Rainey
Prezentacja z Big Data Tech 2016: Machine Learning vs Big Data
Prezentacja z Big Data Tech 2016: Machine Learning vs Big Data
Bartlomiej Twardowski
Oracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data Streaming
Oracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data Streaming
Michael Rainey
Kafka for DBAs
Kafka for DBAs
Gwen (Chen) Shapira
Recommended
RequireJS
RequireJS
Tim Doherty
Asset management with Zend Framework 2
Asset management with Zend Framework 2
Stefano Valle
Managing JavaScript Dependencies With RequireJS
Managing JavaScript Dependencies With RequireJS
Den Odell
Asynchronous Module Definition (AMD) used for Dependency Injection (DI) and MVVM
Asynchronous Module Definition (AMD) used for Dependency Injection (DI) and MVVM
Hugh Anderson
Oracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data Streaming
Oracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data Streaming
Michael Rainey
Prezentacja z Big Data Tech 2016: Machine Learning vs Big Data
Prezentacja z Big Data Tech 2016: Machine Learning vs Big Data
Bartlomiej Twardowski
Oracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data Streaming
Oracle GoldenGate and Apache Kafka A Deep Dive Into Real-Time Data Streaming
Michael Rainey
Kafka for DBAs
Kafka for DBAs
Gwen (Chen) Shapira
Heroku pop-behind-the-sense
Heroku pop-behind-the-sense
Ben Lin
Kharkivpy#3: Javascript and Python backend
Kharkivpy#3: Javascript and Python backend
Max Klymyshyn
The new static resources framework
The new static resources framework
marcplmer
Modules and EmbedJS
Modules and EmbedJS
Jens Arps
Front End Development for Back End Java Developers - Jfokus 2020
Front End Development for Back End Java Developers - Jfokus 2020
Matt Raible
lecture5
lecture5
tutorialsruby
lecture5
lecture5
tutorialsruby
WP plugin - Lazar Dačić
WP plugin - Lazar Dačić
Stevan Pivnički
micro-frontends-with-vuejs
micro-frontends-with-vuejs
Oleksandr Tserkovnyi
SeedStack feature tour
SeedStack feature tour
SeedStack
Introduction to Grunt.js on Taiwan JavaScript Conference
Introduction to Grunt.js on Taiwan JavaScript Conference
Bo-Yi Wu
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...
Codemotion
Drupal tips 'n tricks
Drupal tips 'n tricks
John Tsevdos
Browserify
Browserify
davidchubbs
Take Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainers
Naresha K
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013
Joao Lucas Santana
Introduction to Django
Introduction to Django
Joaquim Rocha
Application Security from the Inside - OWASP
Application Security from the Inside - OWASP
Sqreen
Display Suite: A Themers Perspective
Display Suite: A Themers Perspective
Mediacurrent
Introduction to bdd
Introduction to bdd
antannatna
Forget Ruby. Forget CoffeeScript. Do SOA
Forget Ruby. Forget CoffeeScript. Do SOA
Michał Łomnicki
Having fun with legacy apps
Having fun with legacy apps
Michał Łomnicki
More Related Content
Similar to DDD, Rails and persistence
Heroku pop-behind-the-sense
Heroku pop-behind-the-sense
Ben Lin
Kharkivpy#3: Javascript and Python backend
Kharkivpy#3: Javascript and Python backend
Max Klymyshyn
The new static resources framework
The new static resources framework
marcplmer
Modules and EmbedJS
Modules and EmbedJS
Jens Arps
Front End Development for Back End Java Developers - Jfokus 2020
Front End Development for Back End Java Developers - Jfokus 2020
Matt Raible
lecture5
lecture5
tutorialsruby
lecture5
lecture5
tutorialsruby
WP plugin - Lazar Dačić
WP plugin - Lazar Dačić
Stevan Pivnički
micro-frontends-with-vuejs
micro-frontends-with-vuejs
Oleksandr Tserkovnyi
SeedStack feature tour
SeedStack feature tour
SeedStack
Introduction to Grunt.js on Taiwan JavaScript Conference
Introduction to Grunt.js on Taiwan JavaScript Conference
Bo-Yi Wu
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...
Codemotion
Drupal tips 'n tricks
Drupal tips 'n tricks
John Tsevdos
Browserify
Browserify
davidchubbs
Take Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainers
Naresha K
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013
Joao Lucas Santana
Introduction to Django
Introduction to Django
Joaquim Rocha
Application Security from the Inside - OWASP
Application Security from the Inside - OWASP
Sqreen
Display Suite: A Themers Perspective
Display Suite: A Themers Perspective
Mediacurrent
Introduction to bdd
Introduction to bdd
antannatna
Similar to DDD, Rails and persistence
(20)
Heroku pop-behind-the-sense
Heroku pop-behind-the-sense
Kharkivpy#3: Javascript and Python backend
Kharkivpy#3: Javascript and Python backend
The new static resources framework
The new static resources framework
Modules and EmbedJS
Modules and EmbedJS
Front End Development for Back End Java Developers - Jfokus 2020
Front End Development for Back End Java Developers - Jfokus 2020
lecture5
lecture5
lecture5
lecture5
WP plugin - Lazar Dačić
WP plugin - Lazar Dačić
micro-frontends-with-vuejs
micro-frontends-with-vuejs
SeedStack feature tour
SeedStack feature tour
Introduction to Grunt.js on Taiwan JavaScript Conference
Introduction to Grunt.js on Taiwan JavaScript Conference
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...
Universal JavaScript Web Applications with React - Luciano Mammino - Codemoti...
Drupal tips 'n tricks
Drupal tips 'n tricks
Browserify
Browserify
Take Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainers
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013
Um roadmap do Framework Ruby on Rails, do Rails 1 ao Rails 4 - DevDay 2013
Introduction to Django
Introduction to Django
Application Security from the Inside - OWASP
Application Security from the Inside - OWASP
Display Suite: A Themers Perspective
Display Suite: A Themers Perspective
Introduction to bdd
Introduction to bdd
More from Michał Łomnicki
Forget Ruby. Forget CoffeeScript. Do SOA
Forget Ruby. Forget CoffeeScript. Do SOA
Michał Łomnicki
Having fun with legacy apps
Having fun with legacy apps
Michał Łomnicki
Ruby tricks2
Ruby tricks2
Michał Łomnicki
Schema plus
Schema plus
Michał Łomnicki
Nodejs + Rails
Nodejs + Rails
Michał Łomnicki
ACID - Transakcje
ACID - Transakcje
Michał Łomnicki
Cap Theorem
Cap Theorem
Michał Łomnicki
More from Michał Łomnicki
(7)
Forget Ruby. Forget CoffeeScript. Do SOA
Forget Ruby. Forget CoffeeScript. Do SOA
Having fun with legacy apps
Having fun with legacy apps
Ruby tricks2
Ruby tricks2
Schema plus
Schema plus
Nodejs + Rails
Nodejs + Rails
ACID - Transakcje
ACID - Transakcje
Cap Theorem
Cap Theorem
Recently uploaded
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Christina Lin
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
ABDERRAOUF MEHENNI
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
OPEN KNOWLEDGE GmbH
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
kellynguyen01
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
bodapatigopi8531
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
MyIntelliSource, Inc.
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
VICTOR MAESTRE RAMIREZ
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
shikhaohhpro
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
soniya singh
Exploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the Process
Evangelist Apps https://twitter.com/EvangelistSW/
DNT_Corporate presentation know about us
DNT_Corporate presentation know about us
Dynamic Netsoft
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
SolGuruz
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
Andolasoft Inc
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
kalichargn70th171
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Call Girls In Delhi Whatsup 9873940964 Enjoy Unlimited Pleasure
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
Wave PLM
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Delhi Whatsup 9873940964 Enjoy Unlimited Pleasure
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
aagamshah0812
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
mohitmore19
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
joe51371421
Recently uploaded
(20)
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Exploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the Process
DNT_Corporate presentation know about us
DNT_Corporate presentation know about us
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
DDD, Rails and persistence
1.
DDD, Rails and
persistence Michał Łomnicki January, 2016 DRUG 1 / 21
2.
Inspiration Blog https://vaughnvernon.co Ideal DDD Aggregate Store Book 2 / 21
3.
Problem I want DDD in my Rails project I want fast and clean tests I want to build my application around domain objects not around database schema ...but I struggle with persistence and ActiveRecord gets into my way all the time 3 / 21
4.
Model classSquad includeVirtus.model#optional,canbePORO MAX_FIRST_SQUAD_PLAYERS=11 attribute:id, UUID attribute:match_id, UUID attribute:team_id,
UUID attribute:formation, Formation attribute:first_squad,Set[Player] attribute:bench, Set[Player] 4 / 21
5.
Model defremove_from_first_squad(player) raiseSquadErrorif!first_squad.member?(player) first_squad.delete(player) bench.add(player) end defadd_to_first_squad(player) raiseSquadErrorif!bench.member?(player) raiseSquadErroriffirst_squad.size==MAX_FIRST_SQUAD_PLAYERS bench.remove(player) first_squad.add(player) end 5 / 21
6.
Model defsubstitute(player_off,player_on) remove_from_first_squad(player_off) add_to_first_squad(player_on) DomainEventPublisher.publish( PlayerSubstituted.new( squad_id: id, player_off_id:player_off.id, player_on_id: player_on.id ) ) end 6 / 21
7.
Service classSquadService includeTransactionSupport definitialize(squad_repository,player_repository) @squad_repository =squad_repository @player_repository=player_repository end defsubstitute(substitution_form) transactiondo DomainEventPublisher.subscribe(PlayerSubstituted,SomeHandler) player_off=player_repository.find(substitution_form.player_off_id) player_on =player_repository.find(substitution_form.player_on_id) squad
=squad_repository.find(substitution_form.squad_id) squad.substitute(player_off,player_on) squad_repository.save(squad) end end defchange_formation(formation_form) ... end end 7 / 21
8.
Repository classSquadRepository defsave(squad) ifsquad.id update(squad) else create(squad) end end defcreate(squad) SquadAR.create( match_id:squad.match_id, formation:squad.formation.to_s, squad_players: squad.first_squad.map{|player|PlayerAR.new(first_squad:true,...)} +squad.bench.map{|player|PlayerAR.new(first_squad:false,...)} ) end ... 8 / 21
9.
Repository / Naive
update defupdate(squad) record=SquadAR.find(squad.id) record.formation=squad.formation.to_s #deleteandre-createassociations record.squad_players= squad.first_squad.map{|player|PlayerAR.new(first_squad:true,...)} +squad.bench.map{|player|PlayerAR.new(first_squad:false,...)} record.save end 9 / 21
10.
Repository / Naive
update defupdate(squad) record=SquadAR.find(squad.id) record.formation=squad.formation.to_s #deleteandre-createassociations record.squad_players= squad.first_squad.map{|player|PlayerAR.new(first_squad:true,...)} +squad.bench.map{|player|PlayerAR.new(first_squad:false,...)} record.save end Hard to maintain Errorprone Poor performance 10 / 21
11.
Solution 1 Data Mapper No mature Data Mapper for Ruby ROM looks promising ...but is yet incomplete 11 / 21
12.
Solution 2 Events as
a storage mechanism Yes, that's a good solution Big mental model change 12 / 21
13.
Solution 3 Postgres +
JSON Ideal DDD Aggregate store? Aggregate data stored as JSON One database row one aggregate create_table"squads"do|t| t.jsonb:data,null:false end 13 / 21
14.
DB schema create_table"users"do|t| t.jsonb:data,null:false end create_table"matches"do|t| t.jsonb:data,null:false end create_table"teams"do|t| t.jsonb:data,null:false end create_table"squads"do|t| t.jsonb:data,null:false end 14 / 21
15.
JSON Repository classSquadRepository defsave(squad) ifsquad.id update(squad) else create(squad) end end deffind(squad_id) Domain::Squad.new(SquadAR.find(squad_id)) end private defcreate(squad) SquadAR.create(data:squad.as_json) end defupdate(squad) SquadAR.where(id:squad.id).update_all(data:squad.as_json) end end 15 / 21
16.
Why not Mongo?
This looks like NoSQL Mongo is not ACIDcompliant Transactions only at the document level 16 / 21
17.
Postgres + JSON JSON introduced in Postgres 9.3 JSONB introduced in Postgres 9.4 JSONB can be indexed Postgres = ACID No foreign keys and unique indexes Data consistency ensured at application level Introduce this approach in the existing database 17 / 21
18.
Postgres + JSON JSON introduced in Postgres 9.3 JSONB introduced in Postgres 9.4 JSONB can be indexed Postgres = ACID No foreign keys and unique indexes Data consistency ensured at application level Introduce this approach in the existing database CREATEINDEXONsquadsUSINGgin(data) SELECT*FROMsquadsWHERE(data->>'match_id')::INT=12 18 / 21
19.
Locking Some locking mechanism is required Optimisic locking is preferred a)Process1reads b)Process2reads c)Process1writes d)Process2overwritesc) SquadAR.where(id:squad.id,lock_version:current_version[squad]).update_all( data: squad.as_json, lock_version:current_version[squad]+1 ) 19 / 21
20.
Lessons learnt It works Changes are easy to introduce Fast and easy to store and load an entire aggregate Code explains the application, not the DB schema Migrations require more work Most probably you will build a read model Denormalized data needs synchronization Avoid big aggregates No help from the database (foreign keys, not null, etc) Can't really fiddle in railsconsole Squad.find(123).squad_players.update_all(...) 20 / 21
21.
Thank you Resources: https://vaughnvernon.co/?p=942 http://www.amazon.com/ImplementingDomainDrivenDesignVaughn Vernon/dp/0321834577 http://www.postgresql.org/docs/9.4/static/datatypejson.html 21 / 21
Download now