SlideShare una empresa de Scribd logo
1 de 46
Descargar para leer sin conexión
1. Embrace complexity
2. Know where you’re going
3. Be more than just a
“Rails Developer”
app
├── assets
├── controllers
├── helpers
├── mailers
├── models
└── views
V
CM
V
CM
def pricing_range_fold_and_save(new_range)
pos = 0
pricings = self.product_pricings
other_range = ProductPricing.new
if pricings.length == 0
pricings.push(new_range)
else
pricings.each_with_index do |e, i|
if i == 0 && new_range.start_date < e.start_date
pricings.unshift(new_range)
if new_range.end_date <= e.end_date
e.start_date = new_range.end_date + 1.day
break
else
while pricings[1].present? && new_range.end_date >= pricings[1].end_date
pricings[1].destroy
pricings.delete pricings[1]
end
if pricings[1].present?
pricings[1].start_date = new_range.end_date + 1.day
end
break
end
elsif new_range.start_date <= e.end_date && new_range.start_date >= e.start_date
!
if new_range.end_date < e.end_date
other_range = e.dup
other_range.start_date = new_range.end_date + 1.day
if new_range.start_date == e.start_date
e.destroy
pricings.delete e
i -= 1
else
e.end_date = new_range.start_date - 1.day
end
pricings.insert(i+1, new_range)
pos = i+1
pricings.insert(i+2, other_range)
break
else
if new_range.start_date == e.start_date
e.destroy
pricings.delete e
i -= 1
else
e.end_date = new_range.start_date - 1.day
end
pricings.insert(i+1, new_range)
pos = i+1
while pricings[i+2].present? && new_range.end_date >= pricings[i+2].end_date
pricings[i+2].destroy
pricings.delete pricings[i+2]
end
if pricings[i+2].present?
pricings[i+2].start_date = new_range.end_date + 1.day
end
break
end
!
elsif i == pricings.size-1
pricings[i].end_date = new_range.start_date-1.day
pricings.push(new_range)
break
end
end
end
!
pricings.each_with_index do |pricing, i|
if i != pricings.size-1 && pricing.price ==pricings[i+1].price
pricing.end_date = pricings[i+1].end_date
end
if i != 0 && pricing.end_date == pricings[i-1].end_date
pricing.destroy
pricings.delete pricing
end
if pricing.end_date < pricing.start_date
pricing.destroy
pricings.delete pricing
end
end
!
pricings.each do |pricing|
if pricing != pricings[pos]
pricing.currency = pricings[pos].currency
pricing.save
end
end
pricings[pos].save
return pricings
!
end
Pencil Sharpener
!
C V
M
E
E
S
S
C
V
M
R
Application
Domain
S
Complexity
The critical complexity of
most software projects is in
understanding the domain
itself.
!
Eric Evans
Ubiquitous Language
Domain Driven Design
Hexagonal Architecture
http://blog.mattwynne.net/2012/05/31/hexagonal-rails-objects-values-and-hexagons/
Matt Wynne
Form Object
FOworld C
Form Object
FOworld C
class TicketForm!
include ActiveModel::Model!
!
validates :trip, :price, :passengers, presence: true!
!
def passengers!
@passengers ||= [Passenger.new]!
end!
!
def tickets!
@tickets ||= self.passengers.map do |passenger|!
Ticket.new(...)!
end!
end!
end!
class TicketsController < ApplicationController!
!
def create!
@ticket_form = TicketForm.new(params)!
tickets = @ticket_form.tickets!
!
if @ticket_form.valid? && TicketCharger.new(tickets).charge!!
redirect_to success_url!
else!
render 'new'!
end!
end!
!
end
Request Object
ROCworld
Request Object
RO Cworld
class CreateOrderRequest
!
include Virtus.value_object
include ActiveModel::Validations
!
attribute :customer, Customer
validates :customer, nested: true, presence: true
!
attribute :billing, Billing
validates :billing, nested: true, presence: true
!
attribute :shipping, Shipping
validates :shipping, nested: true, presence: true
!
end
class ApplicationController < ActionController::Base
before_filter :validate_request
!
def validate_request
handle_error(request_object) unless request_object.valid?
end
!
def request_object
@request_object ||= request_class.new(request_parameters)
end
!
def request_class
"#{action_name}#{resource_name}Request".constantize
end
!
def handle_error(request_object)
[...]
end
end
Service Object
SOworld C
Service Object
SOworld C
class OrderService
!
def create(order)
authorize!(order)
!
repository.save!(order)
!
purchase(order) do |transaction|
repository.save!(order)
end
end
!
def purchase(order, &block)
PaymentService.new.purchase(order, &block)
end
!
end
class OrdersController < ApiController
!
def create
order = request_object.to_order
transaction = OrderService.new.create(order)
!
if transaction.success?
order_created(order)
else
payment_failed(transaction)
end
end
!
end
OK, so now what?
“I’m right there in the room, and no
one even acknowledges me.”
E
E
S
S
C
V
M
R
Application
Domain
S
Repository
MS R
E
class Repository!
!
class << self!
!
attr_accessor :mapper!
!
def save!(domain)!
record = mapper.export(domain, record)!
response = record.save!!
domain.id = record.id!
response!
end!
!
end!
!
def self.method_missing(method_name, *args, &block)!
Scope.new(mapper).send(method_name, *args, &block)!
end!
!
end
class Scope!
!
attr_accessor :mapper, :scope!
!
def initialize(mapper)!
@mapper = mapper!
@scope = mapper.export_class!
end!
!
def method_missing(method_name, *args, &block)!
@scope = scope.send(method_name, *args, &_map_block(block))!
!
scope.is_a?(ActiveRecord::Relation) ? self : _map(scope)!
end!
!
def _map_block(block)!
Proc.new { |*args| block.call(_map(*args)) } if block!
end!
!
def _map(object)!
if object.is_a?(mapper.export_class)!
mapper.map(object)!
elsif object.is_a?(Enumerable)!
object.map { |e| e.is_a?(mapper.export_class) ? mapper.map(e) : e }!
else!
object!
end!
end!
!
def respond_to?(method_name, include_private = false)!
scope.respond_to?(method_name, include_private) || super!
end!
end
class Mapper!
class << self!
!
attr_reader :base_class, :export_class!
!
def maps(mapping)!
@base_class, @export_class = mapping.first!
end!
!
def map(object)!
if object.is_a? base_class!
export(object)!
else!
import(object)!
end!
end!
!
def export(base, record=nil)!
return unless base!
!
if record!
record.assign_attributes(base.attributes)!
else!
record = export_class.new(base.attributes)!
end!
!
record!
end!
!
def import(record)!
base_class.new(record.attributes) if record!
end!
end!
end!
class Repository!
!
class << self!
!
attr_accessor :mapper!
!
def save!(domain)!
record = IdentityMap.get(mapper.export_class, domain.id)!
record = mapper.export(domain, record)!
response = record.save!!
IdentityMap.add(record)!
domain.id = record.id!
response!
end!
!
end!
!
def self.method_missing(method_name, *args, &block)!
Scope.new(mapper).send(method_name, *args, &block)!
end!
!
end
class IdentityMap!
!
class << self!
def add(record)!
raise ArgumentError.new('Record cannot be added with a nil id') unless record.id!
repository[key(record.class)][record.id] = record!
end!
!
def remove(record)!
repository[key(record.class)].delete(record.id)!
end!
!
def get(klass, id)!
repository[key(klass)][id]!
end!
!
def clear!
repository.clear!
end!
!
def repository!
Thread.current[:identity_map] ||= Hash.new { |h,k| h[k] = {} }!
end!
!
def key(klass)!
klass!
end!
!
end!
end!
So, what’s the point again?
1. Embrace complexity
!
2. Know where you’re going
!
3. Be more than just a “Rails Developer”
https://github.com/dwhelan/hex-ddd
Continue the discussion
Reading
Patterns of Enterprise Application Architecture

Martin Fowler
Domain Driven Design

Tackling Complexity in the Heart of Software

Eric Evans
Practical Object Oriented Design in Ruby

An Agile Primer

Sandi Metz
Reading
Clean Code

A Handbook of Agile Software Craftsmanship

Robert C. Martin
Implementing Domain Driven Design

Vaughn Vern
Photo/Video Credits
https://www.youtube.com/watch?v=-JLbAePwoHQ
http://www.docstoc.com/docs/47342986/Rube-Goldberg-Project-Rube
https://sitespecific2013awe.blogs.lincoln.ac.uk/tag/tower-of-babel/
http://collabcubed.com/2012/01/17/roskilde-festival-plywood-dome/
http://mitchjackson.com/white-elephants/

Más contenido relacionado

La actualidad más candente

Mucon 2019: OOps I DDD it again and again
Mucon 2019: OOps I DDD it again and againMucon 2019: OOps I DDD it again and again
Mucon 2019: OOps I DDD it again and againOra Egozi-Barzilai
 
Hexagonal architecture with Spring Boot
Hexagonal architecture with Spring BootHexagonal architecture with Spring Boot
Hexagonal architecture with Spring BootMikalai Alimenkou
 
Spring @Transactional Explained
Spring @Transactional ExplainedSpring @Transactional Explained
Spring @Transactional ExplainedVictor Rentea
 
TypeScript: coding JavaScript without the pain
TypeScript: coding JavaScript without the painTypeScript: coding JavaScript without the pain
TypeScript: coding JavaScript without the painSander Mak (@Sander_Mak)
 
Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023
Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023
Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023Steve Pember
 
The Art of Unit Testing - Towards a Testable Design
The Art of Unit Testing - Towards a Testable DesignThe Art of Unit Testing - Towards a Testable Design
The Art of Unit Testing - Towards a Testable DesignVictor Rentea
 
Domain Driven Design Introduction
Domain Driven Design IntroductionDomain Driven Design Introduction
Domain Driven Design Introductionwojtek_s
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven DesignRyan Riley
 
Stability Patterns for Microservices
Stability Patterns for MicroservicesStability Patterns for Microservices
Stability Patterns for Microservicespflueras
 
Hexagonal Architecture
Hexagonal ArchitectureHexagonal Architecture
Hexagonal ArchitectureMarcelo Cure
 
Clean Architecture Applications in Python
Clean Architecture Applications in PythonClean Architecture Applications in Python
Clean Architecture Applications in PythonSubhash Bhushan
 
Asynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFutureAsynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFutureJosé Paumard
 
Clean architecture
Clean architectureClean architecture
Clean architectureLieven Doclo
 
Functional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayFunctional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayDebasish Ghosh
 

La actualidad más candente (20)

Domain Driven Design 101
Domain Driven Design 101Domain Driven Design 101
Domain Driven Design 101
 
Mucon 2019: OOps I DDD it again and again
Mucon 2019: OOps I DDD it again and againMucon 2019: OOps I DDD it again and again
Mucon 2019: OOps I DDD it again and again
 
Clean Architecture
Clean ArchitectureClean Architecture
Clean Architecture
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
 
Hexagonal architecture with Spring Boot
Hexagonal architecture with Spring BootHexagonal architecture with Spring Boot
Hexagonal architecture with Spring Boot
 
Clean Architecture
Clean ArchitectureClean Architecture
Clean Architecture
 
Spring @Transactional Explained
Spring @Transactional ExplainedSpring @Transactional Explained
Spring @Transactional Explained
 
TypeScript: coding JavaScript without the pain
TypeScript: coding JavaScript without the painTypeScript: coding JavaScript without the pain
TypeScript: coding JavaScript without the pain
 
Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023
Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023
Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023
 
The Art of Unit Testing - Towards a Testable Design
The Art of Unit Testing - Towards a Testable DesignThe Art of Unit Testing - Towards a Testable Design
The Art of Unit Testing - Towards a Testable Design
 
Domain Driven Design Introduction
Domain Driven Design IntroductionDomain Driven Design Introduction
Domain Driven Design Introduction
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
 
JPA and Hibernate
JPA and HibernateJPA and Hibernate
JPA and Hibernate
 
Stability Patterns for Microservices
Stability Patterns for MicroservicesStability Patterns for Microservices
Stability Patterns for Microservices
 
Hexagonal Architecture
Hexagonal ArchitectureHexagonal Architecture
Hexagonal Architecture
 
Clean Architecture Applications in Python
Clean Architecture Applications in PythonClean Architecture Applications in Python
Clean Architecture Applications in Python
 
Asynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFutureAsynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFuture
 
TypeScript - An Introduction
TypeScript - An IntroductionTypeScript - An Introduction
TypeScript - An Introduction
 
Clean architecture
Clean architectureClean architecture
Clean architecture
 
Functional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayFunctional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 Way
 

Destacado

Refactoring for Domain Driven Design
Refactoring for Domain Driven DesignRefactoring for Domain Driven Design
Refactoring for Domain Driven DesignDavid Berliner
 
Why Domain-Driven Design Matters
Why Domain-Driven Design MattersWhy Domain-Driven Design Matters
Why Domain-Driven Design MattersMathias Verraes
 
A Practical Guide to Domain Driven Design: Presentation Slides
A Practical Guide to Domain Driven Design: Presentation SlidesA Practical Guide to Domain Driven Design: Presentation Slides
A Practical Guide to Domain Driven Design: Presentation Slidesthinkddd
 
Domain Driven Design in Rails
Domain Driven Design in RailsDomain Driven Design in Rails
Domain Driven Design in RailsHans Yu
 
ZendCon 2011 UnCon Domain-Driven Design
ZendCon 2011 UnCon Domain-Driven DesignZendCon 2011 UnCon Domain-Driven Design
ZendCon 2011 UnCon Domain-Driven DesignBradley Holt
 
Introduction to Domain Driven Design
Introduction to Domain Driven DesignIntroduction to Domain Driven Design
Introduction to Domain Driven DesignChristos Tsakostas
 
Code & Cannoli - Domain Driven Design
Code & Cannoli - Domain Driven DesignCode & Cannoli - Domain Driven Design
Code & Cannoli - Domain Driven DesignFrank Levering
 
Domain-driven design
Domain-driven designDomain-driven design
Domain-driven designKnoldus Inc.
 
Domain Driven Design Introduction
Domain Driven Design IntroductionDomain Driven Design Introduction
Domain Driven Design IntroductionTung Nguyen Thanh
 
Domain-Driven Design with ASP.NET MVC
Domain-Driven Design with ASP.NET MVCDomain-Driven Design with ASP.NET MVC
Domain-Driven Design with ASP.NET MVCSteven Smith
 
Implementing DDD with C#
Implementing DDD with C#Implementing DDD with C#
Implementing DDD with C#Pascal Laurin
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven DesignYoung-Ho Cho
 
От Rails-way к модульной архитектуре
От Rails-way к модульной архитектуреОт Rails-way к модульной архитектуре
От Rails-way к модульной архитектуреIvan Nemytchenko
 
Refactoring Rails applications with RubyMine
Refactoring Rails applications with RubyMineRefactoring Rails applications with RubyMine
Refactoring Rails applications with RubyMineAndrzej Krzywda
 
Hexagonal architecture for the web
Hexagonal architecture for the webHexagonal architecture for the web
Hexagonal architecture for the webJesús Espejo
 
Domain-Driven Design at ZendCon 2012
Domain-Driven Design at ZendCon 2012Domain-Driven Design at ZendCon 2012
Domain-Driven Design at ZendCon 2012Bradley Holt
 
Domain-Driven Design: The "What" and the "Why"
Domain-Driven Design: The "What" and the "Why"Domain-Driven Design: The "What" and the "Why"
Domain-Driven Design: The "What" and the "Why"bincangteknologi
 
Scaling Wanelo.com 100x in Six Months
Scaling Wanelo.com 100x in Six MonthsScaling Wanelo.com 100x in Six Months
Scaling Wanelo.com 100x in Six MonthsKonstantin Gredeskoul
 

Destacado (20)

Ruby loves DDD
Ruby loves DDDRuby loves DDD
Ruby loves DDD
 
Refactoring for Domain Driven Design
Refactoring for Domain Driven DesignRefactoring for Domain Driven Design
Refactoring for Domain Driven Design
 
Why Domain-Driven Design Matters
Why Domain-Driven Design MattersWhy Domain-Driven Design Matters
Why Domain-Driven Design Matters
 
A Practical Guide to Domain Driven Design: Presentation Slides
A Practical Guide to Domain Driven Design: Presentation SlidesA Practical Guide to Domain Driven Design: Presentation Slides
A Practical Guide to Domain Driven Design: Presentation Slides
 
Domain Driven Design in Rails
Domain Driven Design in RailsDomain Driven Design in Rails
Domain Driven Design in Rails
 
ZendCon 2011 UnCon Domain-Driven Design
ZendCon 2011 UnCon Domain-Driven DesignZendCon 2011 UnCon Domain-Driven Design
ZendCon 2011 UnCon Domain-Driven Design
 
Introduction to Domain Driven Design
Introduction to Domain Driven DesignIntroduction to Domain Driven Design
Introduction to Domain Driven Design
 
Code & Cannoli - Domain Driven Design
Code & Cannoli - Domain Driven DesignCode & Cannoli - Domain Driven Design
Code & Cannoli - Domain Driven Design
 
Domain-driven design
Domain-driven designDomain-driven design
Domain-driven design
 
Domain Driven Design Introduction
Domain Driven Design IntroductionDomain Driven Design Introduction
Domain Driven Design Introduction
 
Domain-Driven Design with ASP.NET MVC
Domain-Driven Design with ASP.NET MVCDomain-Driven Design with ASP.NET MVC
Domain-Driven Design with ASP.NET MVC
 
Implementing DDD with C#
Implementing DDD with C#Implementing DDD with C#
Implementing DDD with C#
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
 
От Rails-way к модульной архитектуре
От Rails-way к модульной архитектуреОт Rails-way к модульной архитектуре
От Rails-way к модульной архитектуре
 
DDD e Rails
DDD e RailsDDD e Rails
DDD e Rails
 
Refactoring Rails applications with RubyMine
Refactoring Rails applications with RubyMineRefactoring Rails applications with RubyMine
Refactoring Rails applications with RubyMine
 
Hexagonal architecture for the web
Hexagonal architecture for the webHexagonal architecture for the web
Hexagonal architecture for the web
 
Domain-Driven Design at ZendCon 2012
Domain-Driven Design at ZendCon 2012Domain-Driven Design at ZendCon 2012
Domain-Driven Design at ZendCon 2012
 
Domain-Driven Design: The "What" and the "Why"
Domain-Driven Design: The "What" and the "Why"Domain-Driven Design: The "What" and the "Why"
Domain-Driven Design: The "What" and the "Why"
 
Scaling Wanelo.com 100x in Six Months
Scaling Wanelo.com 100x in Six MonthsScaling Wanelo.com 100x in Six Months
Scaling Wanelo.com 100x in Six Months
 

Similar a Domain Driven Design and Hexagonal Architecture with Rails

Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...Coupa Software
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Railsrstankov
 
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and JasmineRails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and JasmineRaimonds Simanovskis
 
Intro to-rails-webperf
Intro to-rails-webperfIntro to-rails-webperf
Intro to-rails-webperfNew Relic
 
Random Ruby Tips - Ruby Meetup 27 Jun 2018
Random Ruby Tips - Ruby Meetup 27 Jun 2018Random Ruby Tips - Ruby Meetup 27 Jun 2018
Random Ruby Tips - Ruby Meetup 27 Jun 2018Kenneth Teh
 
A Small Talk on Getting Big
A Small Talk on Getting BigA Small Talk on Getting Big
A Small Talk on Getting Bigbritt
 
Crossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkCrossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkDaniel Spector
 
Micropatterns
MicropatternsMicropatterns
Micropatternscameronp
 
Beware: Sharp Tools
Beware: Sharp ToolsBeware: Sharp Tools
Beware: Sharp Toolschrismdp
 
The Art Of Readable Code
The Art Of Readable CodeThe Art Of Readable Code
The Art Of Readable CodeBaidu, Inc.
 
TDC2018SP | Trilha Ruby - Maior performance no seu sistema com o uso adequado...
TDC2018SP | Trilha Ruby - Maior performance no seu sistema com o uso adequado...TDC2018SP | Trilha Ruby - Maior performance no seu sistema com o uso adequado...
TDC2018SP | Trilha Ruby - Maior performance no seu sistema com o uso adequado...tdc-globalcode
 
Frozen rails 2012 - Fighting Code Smells
Frozen rails 2012 - Fighting Code SmellsFrozen rails 2012 - Fighting Code Smells
Frozen rails 2012 - Fighting Code SmellsDennis Ushakov
 
Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7Brian Hogan
 
Say Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick SuttererSay Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick SuttererRuby Meditation
 

Similar a Domain Driven Design and Hexagonal Architecture with Rails (20)

Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
 
Why ruby
Why rubyWhy ruby
Why ruby
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
 
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and JasmineRails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
 
Intro to-rails-webperf
Intro to-rails-webperfIntro to-rails-webperf
Intro to-rails-webperf
 
Random Ruby Tips - Ruby Meetup 27 Jun 2018
Random Ruby Tips - Ruby Meetup 27 Jun 2018Random Ruby Tips - Ruby Meetup 27 Jun 2018
Random Ruby Tips - Ruby Meetup 27 Jun 2018
 
A Small Talk on Getting Big
A Small Talk on Getting BigA Small Talk on Getting Big
A Small Talk on Getting Big
 
SOLID Ruby, SOLID Rails
SOLID Ruby, SOLID RailsSOLID Ruby, SOLID Rails
SOLID Ruby, SOLID Rails
 
Beware sharp tools
Beware sharp toolsBeware sharp tools
Beware sharp tools
 
Crossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkCrossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end Framework
 
Micropatterns
MicropatternsMicropatterns
Micropatterns
 
Beware: Sharp Tools
Beware: Sharp ToolsBeware: Sharp Tools
Beware: Sharp Tools
 
The Art Of Readable Code
The Art Of Readable CodeThe Art Of Readable Code
The Art Of Readable Code
 
TDC2018SP | Trilha Ruby - Maior performance no seu sistema com o uso adequado...
TDC2018SP | Trilha Ruby - Maior performance no seu sistema com o uso adequado...TDC2018SP | Trilha Ruby - Maior performance no seu sistema com o uso adequado...
TDC2018SP | Trilha Ruby - Maior performance no seu sistema com o uso adequado...
 
Frozen rails 2012 - Fighting Code Smells
Frozen rails 2012 - Fighting Code SmellsFrozen rails 2012 - Fighting Code Smells
Frozen rails 2012 - Fighting Code Smells
 
The Joy Of Ruby
The Joy Of RubyThe Joy Of Ruby
The Joy Of Ruby
 
Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7
 
Writing clean code
Writing clean codeWriting clean code
Writing clean code
 
Say Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick SuttererSay Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick Sutterer
 
Refactoring
RefactoringRefactoring
Refactoring
 

Más de Declan Whelan

Technical debt is a systemic problem - not a personal failing
Technical debt is a systemic problem - not a personal failingTechnical debt is a systemic problem - not a personal failing
Technical debt is a systemic problem - not a personal failingDeclan Whelan
 
From Technical Debt to Technical Health
From Technical Debt to Technical HealthFrom Technical Debt to Technical Health
From Technical Debt to Technical HealthDeclan Whelan
 
effective agile adoption
effective agile adoptioneffective agile adoption
effective agile adoptionDeclan Whelan
 
Navigating Organizational Change
Navigating Organizational ChangeNavigating Organizational Change
Navigating Organizational ChangeDeclan Whelan
 
Win Win Conversations
Win Win ConversationsWin Win Conversations
Win Win ConversationsDeclan Whelan
 
Agile 2012 Simple Design Applied
Agile 2012 Simple Design AppliedAgile 2012 Simple Design Applied
Agile 2012 Simple Design AppliedDeclan Whelan
 
Releasing your teams energy through 'pull' conversations
Releasing your teams energy through 'pull' conversationsReleasing your teams energy through 'pull' conversations
Releasing your teams energy through 'pull' conversationsDeclan Whelan
 
Specification by Example
Specification by ExampleSpecification by Example
Specification by ExampleDeclan Whelan
 
Learning is Key to Agile Success: Agile Vancouver 2010
Learning is Key to Agile Success: Agile Vancouver 2010Learning is Key to Agile Success: Agile Vancouver 2010
Learning is Key to Agile Success: Agile Vancouver 2010Declan Whelan
 
Agile learning agile 2010
Agile learning agile 2010Agile learning agile 2010
Agile learning agile 2010Declan Whelan
 
Agile Learning (60 minute version)
Agile Learning (60 minute version)Agile Learning (60 minute version)
Agile Learning (60 minute version)Declan Whelan
 
Agile Learning from Agile 2009
Agile Learning from Agile 2009Agile Learning from Agile 2009
Agile Learning from Agile 2009Declan Whelan
 
Agile Testing: The Role Of The Agile Tester
Agile Testing: The Role Of The Agile TesterAgile Testing: The Role Of The Agile Tester
Agile Testing: The Role Of The Agile TesterDeclan Whelan
 

Más de Declan Whelan (18)

Technical debt is a systemic problem - not a personal failing
Technical debt is a systemic problem - not a personal failingTechnical debt is a systemic problem - not a personal failing
Technical debt is a systemic problem - not a personal failing
 
From Technical Debt to Technical Health
From Technical Debt to Technical HealthFrom Technical Debt to Technical Health
From Technical Debt to Technical Health
 
effective agile adoption
effective agile adoptioneffective agile adoption
effective agile adoption
 
Big Balls of Mud
Big Balls of MudBig Balls of Mud
Big Balls of Mud
 
Navigating Organizational Change
Navigating Organizational ChangeNavigating Organizational Change
Navigating Organizational Change
 
Simple Design
Simple DesignSimple Design
Simple Design
 
Win Win Conversations
Win Win ConversationsWin Win Conversations
Win Win Conversations
 
Agile 2012 Simple Design Applied
Agile 2012 Simple Design AppliedAgile 2012 Simple Design Applied
Agile 2012 Simple Design Applied
 
Releasing your teams energy through 'pull' conversations
Releasing your teams energy through 'pull' conversationsReleasing your teams energy through 'pull' conversations
Releasing your teams energy through 'pull' conversations
 
Specification by Example
Specification by ExampleSpecification by Example
Specification by Example
 
Solid principles
Solid principlesSolid principles
Solid principles
 
Learning is Key to Agile Success: Agile Vancouver 2010
Learning is Key to Agile Success: Agile Vancouver 2010Learning is Key to Agile Success: Agile Vancouver 2010
Learning is Key to Agile Success: Agile Vancouver 2010
 
Agile learning agile 2010
Agile learning agile 2010Agile learning agile 2010
Agile learning agile 2010
 
Agile Learning (60 minute version)
Agile Learning (60 minute version)Agile Learning (60 minute version)
Agile Learning (60 minute version)
 
Cuke2Beer
Cuke2BeerCuke2Beer
Cuke2Beer
 
Agile Learning from Agile 2009
Agile Learning from Agile 2009Agile Learning from Agile 2009
Agile Learning from Agile 2009
 
Agile, Tdd And .Net
Agile, Tdd And .NetAgile, Tdd And .Net
Agile, Tdd And .Net
 
Agile Testing: The Role Of The Agile Tester
Agile Testing: The Role Of The Agile TesterAgile Testing: The Role Of The Agile Tester
Agile Testing: The Role Of The Agile Tester
 

Último

Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesZilliz
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 

Último (20)

Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector Databases
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 

Domain Driven Design and Hexagonal Architecture with Rails

  • 1.
  • 3. 2. Know where you’re going
  • 4. 3. Be more than just a “Rails Developer”
  • 5. app ├── assets ├── controllers ├── helpers ├── mailers ├── models └── views
  • 8. def pricing_range_fold_and_save(new_range) pos = 0 pricings = self.product_pricings other_range = ProductPricing.new if pricings.length == 0 pricings.push(new_range) else pricings.each_with_index do |e, i| if i == 0 && new_range.start_date < e.start_date pricings.unshift(new_range) if new_range.end_date <= e.end_date e.start_date = new_range.end_date + 1.day break else while pricings[1].present? && new_range.end_date >= pricings[1].end_date pricings[1].destroy pricings.delete pricings[1] end if pricings[1].present? pricings[1].start_date = new_range.end_date + 1.day end break end elsif new_range.start_date <= e.end_date && new_range.start_date >= e.start_date ! if new_range.end_date < e.end_date other_range = e.dup other_range.start_date = new_range.end_date + 1.day if new_range.start_date == e.start_date e.destroy pricings.delete e i -= 1 else e.end_date = new_range.start_date - 1.day end pricings.insert(i+1, new_range) pos = i+1 pricings.insert(i+2, other_range) break else if new_range.start_date == e.start_date e.destroy pricings.delete e i -= 1 else e.end_date = new_range.start_date - 1.day end pricings.insert(i+1, new_range) pos = i+1 while pricings[i+2].present? && new_range.end_date >= pricings[i+2].end_date pricings[i+2].destroy pricings.delete pricings[i+2] end if pricings[i+2].present? pricings[i+2].start_date = new_range.end_date + 1.day end break end ! elsif i == pricings.size-1 pricings[i].end_date = new_range.start_date-1.day pricings.push(new_range) break end end end ! pricings.each_with_index do |pricing, i| if i != pricings.size-1 && pricing.price ==pricings[i+1].price pricing.end_date = pricings[i+1].end_date end if i != 0 && pricing.end_date == pricings[i-1].end_date pricing.destroy pricings.delete pricing end if pricing.end_date < pricing.start_date pricing.destroy pricings.delete pricing end end ! pricings.each do |pricing| if pricing != pricings[pos] pricing.currency = pricings[pos].currency pricing.save end end pricings[pos].save return pricings ! end
  • 10.
  • 13.
  • 14. Complexity The critical complexity of most software projects is in understanding the domain itself. ! Eric Evans
  • 21.
  • 22. class TicketForm! include ActiveModel::Model! ! validates :trip, :price, :passengers, presence: true! ! def passengers! @passengers ||= [Passenger.new]! end! ! def tickets! @tickets ||= self.passengers.map do |passenger|! Ticket.new(...)! end! end! end!
  • 23. class TicketsController < ApplicationController! ! def create! @ticket_form = TicketForm.new(params)! tickets = @ticket_form.tickets! ! if @ticket_form.valid? && TicketCharger.new(tickets).charge!! redirect_to success_url! else! render 'new'! end! end! ! end
  • 26. class CreateOrderRequest ! include Virtus.value_object include ActiveModel::Validations ! attribute :customer, Customer validates :customer, nested: true, presence: true ! attribute :billing, Billing validates :billing, nested: true, presence: true ! attribute :shipping, Shipping validates :shipping, nested: true, presence: true ! end
  • 27. class ApplicationController < ActionController::Base before_filter :validate_request ! def validate_request handle_error(request_object) unless request_object.valid? end ! def request_object @request_object ||= request_class.new(request_parameters) end ! def request_class "#{action_name}#{resource_name}Request".constantize end ! def handle_error(request_object) [...] end end
  • 30. class OrderService ! def create(order) authorize!(order) ! repository.save!(order) ! purchase(order) do |transaction| repository.save!(order) end end ! def purchase(order, &block) PaymentService.new.purchase(order, &block) end ! end
  • 31. class OrdersController < ApiController ! def create order = request_object.to_order transaction = OrderService.new.create(order) ! if transaction.success? order_created(order) else payment_failed(transaction) end end ! end
  • 32. OK, so now what?
  • 33. “I’m right there in the room, and no one even acknowledges me.”
  • 36. class Repository! ! class << self! ! attr_accessor :mapper! ! def save!(domain)! record = mapper.export(domain, record)! response = record.save!! domain.id = record.id! response! end! ! end! ! def self.method_missing(method_name, *args, &block)! Scope.new(mapper).send(method_name, *args, &block)! end! ! end
  • 37. class Scope! ! attr_accessor :mapper, :scope! ! def initialize(mapper)! @mapper = mapper! @scope = mapper.export_class! end! ! def method_missing(method_name, *args, &block)! @scope = scope.send(method_name, *args, &_map_block(block))! ! scope.is_a?(ActiveRecord::Relation) ? self : _map(scope)! end! ! def _map_block(block)! Proc.new { |*args| block.call(_map(*args)) } if block! end! ! def _map(object)! if object.is_a?(mapper.export_class)! mapper.map(object)! elsif object.is_a?(Enumerable)! object.map { |e| e.is_a?(mapper.export_class) ? mapper.map(e) : e }! else! object! end! end! ! def respond_to?(method_name, include_private = false)! scope.respond_to?(method_name, include_private) || super! end! end
  • 38. class Mapper! class << self! ! attr_reader :base_class, :export_class! ! def maps(mapping)! @base_class, @export_class = mapping.first! end! ! def map(object)! if object.is_a? base_class! export(object)! else! import(object)! end! end! ! def export(base, record=nil)! return unless base! ! if record! record.assign_attributes(base.attributes)! else! record = export_class.new(base.attributes)! end! ! record! end! ! def import(record)! base_class.new(record.attributes) if record! end! end! end!
  • 39. class Repository! ! class << self! ! attr_accessor :mapper! ! def save!(domain)! record = IdentityMap.get(mapper.export_class, domain.id)! record = mapper.export(domain, record)! response = record.save!! IdentityMap.add(record)! domain.id = record.id! response! end! ! end! ! def self.method_missing(method_name, *args, &block)! Scope.new(mapper).send(method_name, *args, &block)! end! ! end
  • 40. class IdentityMap! ! class << self! def add(record)! raise ArgumentError.new('Record cannot be added with a nil id') unless record.id! repository[key(record.class)][record.id] = record! end! ! def remove(record)! repository[key(record.class)].delete(record.id)! end! ! def get(klass, id)! repository[key(klass)][id]! end! ! def clear! repository.clear! end! ! def repository! Thread.current[:identity_map] ||= Hash.new { |h,k| h[k] = {} }! end! ! def key(klass)! klass! end! ! end! end!
  • 41. So, what’s the point again?
  • 42. 1. Embrace complexity ! 2. Know where you’re going ! 3. Be more than just a “Rails Developer”
  • 44. Reading Patterns of Enterprise Application Architecture
 Martin Fowler Domain Driven Design
 Tackling Complexity in the Heart of Software
 Eric Evans Practical Object Oriented Design in Ruby
 An Agile Primer
 Sandi Metz
  • 45. Reading Clean Code
 A Handbook of Agile Software Craftsmanship
 Robert C. Martin Implementing Domain Driven Design
 Vaughn Vern