Design In Ruby
Presented By- Swapnil Abnave
Kiprosh, 5 December 2013
Fact: your application is going to
change. How will your application
handle that change?
Your App may be o
Rigid: Making a change somewhere will
break something somewhere else.
Fragile: You can’t predict where that break
Immobile: It’s hard to change/re-use your
Viscous: It’s easier to do the wrong thing
than to fix things.
Design is all about
• If you refer to something, you depend
• When the things you depend on
change, you must change.
There should never be more than
one reason for a class to change
A module should be open for
extension but closed for
Depend upon abstractions.
Do not depend upon concretions
SOLID principles we can ignore in
Really only a problem for staticallytyped, compiled languages.
“Because we’re in Ruby, we don’t have
this problem! Win!”
“Dynamic languages obey this rule
in the most extreme way possible:
• What is it ? - “Many client
specific interfaces are better
than one general purpose
When you design, don’t break the
contract of the superclass in the
DESIGN MIGHT SAVE YOU
To avoid dependencies, your design
Loosely coupled – D – Inject
Highly cohesive – SRP
Easily composable – Can be changed
Context independent – Can be
Resistance is a resource => Listen to what
the pain is telling you.
Listen to what the code smells are telling
Embrace the friction.
Fix the problem.
If testing seems hard – examine your
Your Checkpoint for Design
When you get to the refactor stage of
red-green-refactor, ask yourself …
Is it DRY?
Does it have just one responsibility?
Does everything change at the same
Does it depend on things that change
"Triangle of Responsibility"
Extract - Pull functionality out
Inject - Inject that new
dependency into place from which
it was extracted
Act like an idiot
What if I don't know where I want
this refactoring to take me?
That's OK. In fact, that's typical.
"Refactor, not because you know
the abstraction, but because you
want to find it."
Act like an idiot
"You don't have to know where
you're going to successfully
When you see someone's code
and think it's beautiful and you
wonder how they thought of
it, they didn't. They evolved it to
When injecting dependencies into a
class, do so only via arguments to
@downloader = downloader
When you need to inject a few
dependencies, you can use an options
hash to remove the dependency on the
order of the arguments
@env = opts[:env] || Rails.env
filename = opts[:filename]
Dependency is unavoidable
How to assess: "Does each object
depend on things that change less
than it does?”
Line up the objects from left to right
Left = lower likelihood of change
Right = higher likelihood of change
Only depend on things on your left
Conclude to begin with design
TDD is not enough
DRY is not enough
Design because you expect your
application to succeed(and to
change in the future to come)