Monolith
Service
Service
Service
Service
Service
Early 2013 - Startup / Proof of Concept
Slide 18
Slide 18 text
Monolith
Service
Service
Service
Service
Service
2014 - Growth Phase
Slide 19
Slide 19 text
@skwp @reverbdotcom #wcr14
http://martinfowler.com/articles/distributed-objects-
microservices.html
“I'm wary of distribution and
my default inclination is to prefer
a monolithic design”
“While small microservices are certainly simpler to reason
about, I worry that this pushes complexity into the
interconnections between services”
“Refactoring becomes much harder when you have to do it
across remote boundaries.”
Slide 20
Slide 20 text
@skwp @reverbdotcom #wcr14
Quick Iterations
Low Operational
Complexity
May lead to a BBOM
Slide 21
Slide 21 text
@skwp @reverbdotcom #wcr14
Maintainable
Monoliths
Can Be
Achieved
Slide 22
Slide 22 text
@skwp @reverbdotcom #wcr14
Slide 23
Slide 23 text
@skwp @reverbdotcom #wcr14
Slide 24
Slide 24 text
@skwp @reverbdotcom #wcr14
Product
400 LOC
~150 LOC non-ActiveRecord
Churn: 49 changes this year"
Order
333 LOC
~200 LOC non-ActiveRecord
Churn: 36 changes this year
User
338 LOC
~200 LOC non-ActiveRecord
Churn: 29 changes this year
Slide 25
Slide 25 text
CHURN
Product
Order
User
Slide 26
Slide 26 text
@skwp @reverbdotcom #wcr14
Commonly used
classes are hard
to refactor
Slide 27
Slide 27 text
@skwp @reverbdotcom #wcr14
Stop
modifying
code!
Slide 28
Slide 28 text
@skwp @reverbdotcom #wcr14
Don’t put
different rates
of change
together"
Kent Beck - Smalltalk Best Practice Patterns
Slide 29
Slide 29 text
@skwp @reverbdotcom #wcr14
Don’t put
different rates
of change
together"
Kent Beck - Smalltalk Best Practice Patterns
Data Model
Business Logic
Slide 30
Slide 30 text
@skwp @reverbdotcom #wcr14
Separate
what the system is "
from what the
system does"
James Copelien & Trygve Reenskaug
(Data, Context, Interaction)
Slide 31
Slide 31 text
@skwp @reverbdotcom #wcr14
Where does business
logic go?
Slide 32
Slide 32 text
@skwp @reverbdotcom #wcr14
Controller
2005
ActiveRecord
Mailers
Services
User
Slide 33
Slide 33 text
@skwp @reverbdotcom #wcr14
Console?"
Rake task?"
Background jobs?"
API layer?"
Testing?
What about…
Slide 34
Slide 34 text
@skwp @reverbdotcom #wcr14
Order
Fat models?
Slide 35
Slide 35 text
@skwp @reverbdotcom #wcr14
Order
Refund
Slide 36
Slide 36 text
@skwp @reverbdotcom #wcr14
Order
Refund
Ship
Slide 37
Slide 37 text
@skwp @reverbdotcom #wcr14
Order
Refund
Ship
Check Fraud Risk
Slide 38
Slide 38 text
@skwp @reverbdotcom #wcr14
“Active Record is a good choice
for domain logic that isn't too
complex, such as creates, reads,
updates, and deletes”
Martin Fowler
Slide 39
Slide 39 text
@skwp @reverbdotcom #wcr14
If Controller and Model
are all you have then
one has to be skinny and
one has to be fat
Slide 40
Slide 40 text
@skwp @reverbdotcom #wcr14
Domain Layer
skinny framework,
healthy business logic,"
no fat anywhere
http://joncairns.com/2013/04/fat-model-
skinny-controller-is-a-load-of-rubbish/
Slide 41
Slide 41 text
Model
Controller
View
The Rails Way
The
Way
Active
Record
Use Cases
Grape
API
Controllers
Cron
Redis
Rake
HTTP
Services
Workers
R
Entities
Roles
DB
Listeners
Events
Slide 42
Slide 42 text
@skwp @reverbdotcom #wcr14
app/reverb
for app specific
Slide 43
Slide 43 text
@skwp @reverbdotcom #wcr14
lib/reverb
for Open Source / Generic
Slide 44
Slide 44 text
@skwp @reverbdotcom #wcr14
Reverb::
Namespace to avoid
collisions with gems
Slide 45
Slide 45 text
@skwp @reverbdotcom #wcr14
Slide 46
Slide 46 text
@skwp @reverbdotcom #wcr14
This is a
marketplace!
http://blog.
8thlight.com/uncle-
bob/2011/09/30/
Screaming-
Architecture.html
@skwp @reverbdotcom #wcr14
http://blog.8thlight.com/mike-ebert/2013/03/23/the-
repository-pattern.html
(but you should still read this)
Slide 53
Slide 53 text
@skwp @reverbdotcom #wcr14
User.where(…)
User.active
User.find(1)
This is easy to replace with
something other than AR.
Repository not required.
Don’t leak SQL outside of AR
Slide 54
Slide 54 text
@skwp @reverbdotcom #wcr14
Domain Logic in
ActiveRecord and
Controllers
leads to Churn
Slide 55
Slide 55 text
@skwp @reverbdotcom #wcr14
Use Cases
Reify complex business logic
into classes
Slide 56
Slide 56 text
@skwp @reverbdotcom #wcr14
Slide 57
Slide 57 text
@skwp @reverbdotcom #wcr14
This is not"
Rails
Slide 58
Slide 58 text
@skwp @reverbdotcom #wcr14
Slide 59
Slide 59 text
@skwp @reverbdotcom #wcr14
Explicitly Require Dependency
http://myronmars.to/n/dev-blog/2012/12/5-reasons-to-avoid-
bundler-require
Invoke It
Slide 60
Slide 60 text
@skwp @reverbdotcom #wcr14
Code Reuse!
Thin Shell
Slide 61
Slide 61 text
@skwp @reverbdotcom #wcr14
Stubby
Happy Path
Slide 62
Slide 62 text
@skwp @reverbdotcom #wcr14
Testing conditionals and side
effects has nothing to do with Rails
Slide 63
Slide 63 text
@skwp @reverbdotcom #wcr14
Naming
The hardest problem in computer science
Slide 64
Slide 64 text
@skwp @reverbdotcom #wcr14
OrderService
Slide 65
Slide 65 text
@skwp @reverbdotcom #wcr14
Order
Service
Slide 66
Slide 66 text
@skwp @reverbdotcom #wcr14
Order
Service
NounService Grows Unbounded
Slide 67
Slide 67 text
@skwp @reverbdotcom #wcr14
Use verbs to
narrow your scope
Slide 68
Slide 68 text
@skwp @reverbdotcom #wcr14
Order
Slide 69
Slide 69 text
@skwp @reverbdotcom #wcr14
Order
ShipOrder
Slide 70
Slide 70 text
@skwp @reverbdotcom #wcr14
Order
ShipOrder
Cancel
Order
Slide 71
Slide 71 text
@skwp @reverbdotcom #wcr14
Order
ShipOrder
Cancel
Order
Refund
Order
Slide 72
Slide 72 text
@skwp @reverbdotcom #wcr14
Order
ShipOrder
Cancel
Order
Refund
Order
Does not
grow over time
Slide 73
Slide 73 text
@skwp @reverbdotcom #wcr14
ShipOrder
Cancel
Order
Refund
Order
Don’t change"
once you write them
Slide 74
Slide 74 text
@skwp @reverbdotcom #wcr14
Ubiquitous Language
Slide 75
Slide 75 text
@skwp @reverbdotcom #wcr14
Slide 76
Slide 76 text
@skwp @reverbdotcom #wcr14
What is this?
Slide 77
Slide 77 text
@skwp @reverbdotcom #wcr14
Roles
Add methods to objects on demand
in the context of a Use Case
Slide 78
Slide 78 text
@skwp @reverbdotcom #wcr14
Decorator
Slide 79
Slide 79 text
@skwp @reverbdotcom #wcr14
We added these methods
Slide 80
Slide 80 text
@skwp @reverbdotcom #wcr14
Slide 81
Slide 81 text
@skwp @reverbdotcom #wcr14
Methods related to each"
other but loosely related"
to the parent concept"
and used only in a few"
Use Cases
Slide 82
Slide 82 text
@skwp @reverbdotcom #wcr14
Slide 83
Slide 83 text
@skwp @reverbdotcom #wcr14
Events
Add behavior with listeners
without modifying code
Slide 84
Slide 84 text
@skwp @reverbdotcom #wcr14
Order
ActiveRecord Callbacks
Send Email
Slide 85
Slide 85 text
@skwp @reverbdotcom #wcr14
Order
ActiveRecord Callbacks
Send Email
Call External Service
Slide 86
Slide 86 text
@skwp @reverbdotcom #wcr14
Order
ActiveRecord Callbacks
Send Email
Call External Service
Conditional
Callbacks
Slide 87
Slide 87 text
@skwp @reverbdotcom #wcr14
AR callbacks become
more complex as the
system supports more
use cases
Slide 88
Slide 88 text
@skwp @reverbdotcom #wcr14
Different use cases may
trigger different events
even when working with
the same model
Instead
Slide 89
Slide 89 text
@skwp @reverbdotcom #wcr14
Slide 90
Slide 90 text
@skwp @reverbdotcom #wcr14
Slide 91
Slide 91 text
@skwp @reverbdotcom #wcr14
Add another listener to add behavior
The core class doesn’t change
Slide 92
Slide 92 text
@skwp @reverbdotcom #wcr14
Global listeners for cross-cutting concerns
without littering code
Wisper::GlobalListeners.add(Reverb::Listeners::AnalyticsListener.new)"
Slide 93
Slide 93 text
@skwp @reverbdotcom #wcr14
Controller is a listener too
Slide 94
Slide 94 text
@skwp @reverbdotcom #wcr14
Policy Objects
Reify complex business rules
into objects
Slide 95
Slide 95 text
@skwp @reverbdotcom #wcr14
Likely to change
Unlikely to change
Slide 96
Slide 96 text
@skwp @reverbdotcom #wcr14
refactored for readability
Slide 97
Slide 97 text
@skwp @reverbdotcom #wcr14
Injectable, but has a default
Simple code, only need to test one path
for the imperative side effect"
(sending an email)
Slide 98
Slide 98 text
@skwp @reverbdotcom #wcr14
Distillation Time
Slide 99
Slide 99 text
@skwp @reverbdotcom #wcr14
Language of codebase
reflects language of business
Slide 100
Slide 100 text
@skwp @reverbdotcom #wcr14
Separate behaviors (what the system
does) from models (what the system is)
Slide 101
Slide 101 text
@skwp @reverbdotcom #wcr14
Rates of Change
Slide 102
Slide 102 text
@skwp @reverbdotcom #wcr14
Is this all Unicorns
and Rainbows?
@skwp @reverbdotcom #wcr14
Active
Record
Use Cases
Grape
API
Controllers
Cron
Redis
Rake
HTTP
Services
Workers
R
Entities
Roles
DB
Listeners
Events
Active
Record
Use Cases
Grape
API
Controllers
Cron
Redis
Rake
HTTP
Services
Workers
R
Entities
Roles
DB
Listeners
Events