SlideShare a Scribd company logo
1 of 33
Download to read offline
Restructuring Rails
Eric Marthinsen
CTO and Founder, Agile Commerce
A Refactoring Story
Overview
•CTO and Founder of Agile
Commerce.
•Part of team that bought Sortfolio
from 37signals in 2012.
•Have been enhancing it for about a
year.
How was
their code?
Rule
Stable code running a
profitable company is
always successful code.
However
•Sortfolio was a successful MVP.
•37signals’ testing philosophy differs
from my own.
•Rails 2.3.8
•Needed some work to prepare for
new features.
Refactoring Result
•Improved from a CodeClimate
score of 2.78 to 3.51.
•Drastically improved test coverage,
while decreasing test run time.
•Doubled, roughly, our development
velocity.
Today’s Objective
Share the principles I used to
improve the Sortfolio codebase in a
way that you can apply these
principles to your own projects.
Reduce callbacks
Embrace CSS3
Inline concerns
Add decorators
STI
Create services
Create gateways
Custom presenters
DRY
Config to ENV
ElasticSearch
Method extraction
Fewer static methods
Extract class
Extract Class
Benefits
•Better domain model
•Easier comprehension
•More granular tests
•Faster tests
•More hooks for mocking
•Overall, better software
My Thesis
I believe that having classes with too
many responsibilities is the primary
cause of poor object-oriented code.
This is true of any object-oriented
platform, but doubly true of Rails.
Why Doubly True?
•ActiveRecord combines data and
business layers.
•View code often leaks into models
and controllers.
•Helpers are dumping grounds for
procedural code.
•Rails conventions support
overburdened objects.
“Fat model,
skinny controller”
Wrong - everything
should be skinny.
Example: Search
Step 0: Start
class Listing < ActiveRecord::Base
# associations
# validations
def self.get_pro_listings(location_id, budget_id, start, offset)
# lots of code
end
def self.get_free_listings(location_id, budget_id, start, offset)
# lots of similar code
end
end
Object-Orientation
•An object is data and the methods
that operate on that data.
•An object should represent a single
thing.
•A class defines the type of the
object.
Problems
•Why does a listing know how to
find its peers?
•We’re attaching collection methods
to a type declaration.
•A domain concept is being hidden.
Step 1
class Listing < ActiveRecord::Base
# associations
# validations
end
class ListingIndex
def self.get_pro_listings(location_id, budget_id, start, offset)
# lots of code
end
def self.get_free_listings(location_id, budget_id, start, offset)
# lots of similar code
end
end
Progress
•Now expressing the collection of
Listings in the domain model.
•Creating a “preferred” interface.
•But, not DRY, and two domain
concepts remain unexpressed.
Step 2
class Listing < ActiveRecord::Base
# associations
# validations
end
class ListingIndex
def self.get_listings(is_pro, location_id, budget_id, start, offset)
# lots of code
end
end
Progress
•ListingIndex is now DRY
•Still a couple domain concepts
hidden in there.
•Adding arguments is not scalable.
Step 3
class Listing < ActiveRecord::Base
# associations
# validations
end
class ListingIndex
def self.search(query)
# less code
end
end
class ListingQuery
def initialize(options)
# set properties
end
end
Progress
•We’ve teased out another domain
concept.
•Queries are now scalable and easy
to augment.
•ListingIndex has an intuitive
#search method.
•Still one domain concept hiding in
there.
Step 4
class ListingIndex
def self.search(query)
# less code
end
end
class ListingQuery
def initialize(options)
# set properties
end
end
class ListingResults
# mostly attrs
end
Progress
•Results are now expressed in the
domain model.
•Big improvements to other areas of
the code.
•Set up for success and making big
changes behind a stable interface.
Step 5: Final
class ListingIndex
def self.search(query)
# less code
end
def self.add_listing(listing)
# trivial
end
def self.remove_listing(listing)
# trivial
end
end
class ListingQuery
# no change
end
class ListingResults
# mostly attrs
end
Results
•Listing was split into Listing,
ListingIndex, ListingQuery, and
ListingResults.
•Better design allowed for trivial
introduction of ElasticSearch.
•Much easier and faster to test.
Takeaways
Your app probably
has fewer classes
than it should.
It’s easier to
combine classes
than to separate
them.
Models don’t need
to inherit from
ActiveRecord::Base
Conventions don’t
always apply.
More Info
Eric Marthinsen
emarthinsen@agilecommerce.com
www.agilecommerce.com/blog
@agilecommerce
@ericmarthinsen
THANKS!

More Related Content

Similar to Restructuring rails

Improving the Quality of Existing Software
Improving the Quality of Existing SoftwareImproving the Quality of Existing Software
Improving the Quality of Existing SoftwareSteven Smith
 
Art of refactoring - Code Smells and Microservices Antipatterns
Art of refactoring - Code Smells and Microservices AntipatternsArt of refactoring - Code Smells and Microservices Antipatterns
Art of refactoring - Code Smells and Microservices AntipatternsEl Mahdi Benzekri
 
Improving the Quality of Existing Software - DevIntersection April 2016
Improving the Quality of Existing Software - DevIntersection April 2016Improving the Quality of Existing Software - DevIntersection April 2016
Improving the Quality of Existing Software - DevIntersection April 2016Steven Smith
 
Refactoring to SOLID Code
Refactoring to SOLID CodeRefactoring to SOLID Code
Refactoring to SOLID CodeAdil Mughal
 
Using Compass to Diagnose Performance Problems in Your Cluster
Using Compass to Diagnose Performance Problems in Your ClusterUsing Compass to Diagnose Performance Problems in Your Cluster
Using Compass to Diagnose Performance Problems in Your ClusterMongoDB
 
Using Compass to Diagnose Performance Problems
Using Compass to Diagnose Performance Problems Using Compass to Diagnose Performance Problems
Using Compass to Diagnose Performance Problems MongoDB
 
Improving the Quality of Existing Software
Improving the Quality of Existing SoftwareImproving the Quality of Existing Software
Improving the Quality of Existing SoftwareSteven Smith
 
Writing Clean Code (Recommendations by Robert Martin)
Writing Clean Code (Recommendations by Robert Martin)Writing Clean Code (Recommendations by Robert Martin)
Writing Clean Code (Recommendations by Robert Martin)Shirish Bari
 
Improving the Quality of Existing Software
Improving the Quality of Existing SoftwareImproving the Quality of Existing Software
Improving the Quality of Existing SoftwareSteven Smith
 
Improving The Quality of Existing Software
Improving The Quality of Existing SoftwareImproving The Quality of Existing Software
Improving The Quality of Existing SoftwareSteven Smith
 
Application Architecture April 2014
Application Architecture April 2014Application Architecture April 2014
Application Architecture April 2014Lars-Erik Kindblad
 
Building rich domain models with ddd and tdd ivan paulovich - betsson
Building rich domain models with ddd and tdd   ivan paulovich - betssonBuilding rich domain models with ddd and tdd   ivan paulovich - betsson
Building rich domain models with ddd and tdd ivan paulovich - betssonIvan Paulovich
 
Episode 3 – Classes, Inheritance, Abstract Class, and Interfaces
Episode 3 – Classes, Inheritance, Abstract Class, and InterfacesEpisode 3 – Classes, Inheritance, Abstract Class, and Interfaces
Episode 3 – Classes, Inheritance, Abstract Class, and InterfacesJitendra Zaa
 
Prashant technical practices-tdd for xebia event
Prashant   technical practices-tdd for xebia eventPrashant   technical practices-tdd for xebia event
Prashant technical practices-tdd for xebia eventXebia India
 
Migration strategies 4
Migration strategies 4Migration strategies 4
Migration strategies 4Wenhua Wang
 
Boosting the Performance of your Rails Apps
Boosting the Performance of your Rails AppsBoosting the Performance of your Rails Apps
Boosting the Performance of your Rails AppsMatt Kuklinski
 

Similar to Restructuring rails (20)

Improving the Quality of Existing Software
Improving the Quality of Existing SoftwareImproving the Quality of Existing Software
Improving the Quality of Existing Software
 
Art of refactoring - Code Smells and Microservices Antipatterns
Art of refactoring - Code Smells and Microservices AntipatternsArt of refactoring - Code Smells and Microservices Antipatterns
Art of refactoring - Code Smells and Microservices Antipatterns
 
Improving the Quality of Existing Software - DevIntersection April 2016
Improving the Quality of Existing Software - DevIntersection April 2016Improving the Quality of Existing Software - DevIntersection April 2016
Improving the Quality of Existing Software - DevIntersection April 2016
 
Refactoring to SOLID Code
Refactoring to SOLID CodeRefactoring to SOLID Code
Refactoring to SOLID Code
 
Using Compass to Diagnose Performance Problems in Your Cluster
Using Compass to Diagnose Performance Problems in Your ClusterUsing Compass to Diagnose Performance Problems in Your Cluster
Using Compass to Diagnose Performance Problems in Your Cluster
 
Using Compass to Diagnose Performance Problems
Using Compass to Diagnose Performance Problems Using Compass to Diagnose Performance Problems
Using Compass to Diagnose Performance Problems
 
Improving the Quality of Existing Software
Improving the Quality of Existing SoftwareImproving the Quality of Existing Software
Improving the Quality of Existing Software
 
Application Architecture
Application ArchitectureApplication Architecture
Application Architecture
 
Writing Clean Code (Recommendations by Robert Martin)
Writing Clean Code (Recommendations by Robert Martin)Writing Clean Code (Recommendations by Robert Martin)
Writing Clean Code (Recommendations by Robert Martin)
 
Improving the Quality of Existing Software
Improving the Quality of Existing SoftwareImproving the Quality of Existing Software
Improving the Quality of Existing Software
 
Improving The Quality of Existing Software
Improving The Quality of Existing SoftwareImproving The Quality of Existing Software
Improving The Quality of Existing Software
 
Application Architecture April 2014
Application Architecture April 2014Application Architecture April 2014
Application Architecture April 2014
 
Building rich domain models with ddd and tdd ivan paulovich - betsson
Building rich domain models with ddd and tdd   ivan paulovich - betssonBuilding rich domain models with ddd and tdd   ivan paulovich - betsson
Building rich domain models with ddd and tdd ivan paulovich - betsson
 
Design p atterns
Design p atternsDesign p atterns
Design p atterns
 
Bdd with m spec
Bdd with m specBdd with m spec
Bdd with m spec
 
Episode 3 – Classes, Inheritance, Abstract Class, and Interfaces
Episode 3 – Classes, Inheritance, Abstract Class, and InterfacesEpisode 3 – Classes, Inheritance, Abstract Class, and Interfaces
Episode 3 – Classes, Inheritance, Abstract Class, and Interfaces
 
SDWest2005Goetsch
SDWest2005GoetschSDWest2005Goetsch
SDWest2005Goetsch
 
Prashant technical practices-tdd for xebia event
Prashant   technical practices-tdd for xebia eventPrashant   technical practices-tdd for xebia event
Prashant technical practices-tdd for xebia event
 
Migration strategies 4
Migration strategies 4Migration strategies 4
Migration strategies 4
 
Boosting the Performance of your Rails Apps
Boosting the Performance of your Rails AppsBoosting the Performance of your Rails Apps
Boosting the Performance of your Rails Apps
 

Recently uploaded

Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
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 educationjfdjdjcjdnsjd
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdfChristopherTHyatt
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
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 productivityPrincipled Technologies
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
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...Miguel Araújo
 

Recently uploaded (20)

Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
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
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdf
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
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
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
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...
 

Restructuring rails