SlideShare a Scribd company logo
1 of 19
Refactoring
for Rails
Using deodorant to prevent code smells
and a shower from time to time to
eliminate the most persistent ones
Rodrigo Urubatan Ferreira Jardim
rodrigo@urubatan.com
http://urubatan.dev
http://github.com/urubatan
http://twitter.com/urubatan
There is no magic trick, to fix most
smells we use simple refactoring
• Change Function Declaration
• Collapse Hierarchy
• Extract Module (Combine Functions into…)
• Extract Class (Combine Functions into…)
• Decompose Conditional
• Inline Variable
• Extract Variable
• Extract Method
• Inline Method
• Extract Superclass
• Move Field
• Move Function
• Remove Dead Code
• Rename Field/Variable/Method/Class
• Replace Constructor With Factory Function (here I usually use constantize, …)
• Replace TypeCode with subclasses
When you feel
adventurous
• Case statement without else
• Old or new code without tests
Refactoring good practices/rules
• After you complete the refactoring, the tests should still
work
• Refactoring should not change behavior
• In noncritical scenarios refactoring should not change
external API
• Refactoring is about code quality; you should separate time
for it
• Time saved to improve code quality will save your vacation
time and reduce the number of bugs
• Golden rule: big refactoring should be in it’s own PR not in a
random feature PR
• Exception: always leave the code you touch better than
when you found it, always do small refactorings
Smells like it’ll
explode
• Broken chain of nil safe calls (&.)
• Nested ternary operators
When something
smells different
• camel case variables…
• conditional expression with parenthesis
• incorrect parenthesis in method definition
• whitespace before parenthesis in method call
• negative condition in control flow statement
• Attribution sign in comparison
• Type Checking
• That ruby code that looks like your other
language
Rubocop for
the help
• Add to your Gemfile
• gem 'rubocop', require: false
• Run before every commit
• rubocop –a
• Abort commit if exit code isn’t zero
• I use husky+lint-staged for this
module.exports = {
'*.js': ['npx prettier --write', 'npx
eslint', 'git update-index --again'],
'!(*schema).rb': ['rubocop -a --fail-level
e', 'git update-index --again']
}
Lint-staged.config.js
The old and good
spaghetti code
• Class with too many responsibilities
• Method with too many responsibilities
• Incomplete library class
• Circular dependencies
• Change one piece another blows up
• Methods with many exit points
Whale class/huge
class
Sometimes a domain has too many things going
around
Big methods
• Sometimes the method is big and the only
thing you can do is to make it clear what is it
about
The first shower to fix
big classes and methods
• Extract super class
• Collapse hierarchy
• Extract module
• Move function
• Extract method
• Extract variable
• Inline variable
• Rename Class/Method/Variable
Fruit salad
• Too many instance variables
• Too many methods
• Methods with too many arguments
Some things just
smells like nothing
• Many return statements
• Unneeded comments
• If Boolean true than false
• Value objects?
That thing that
smells like prison
• To change one class or method safely you need
to touch many other methods or classes
• when you need to change 5 different projects
because you removed one field of a table
Fat smell?
• Fat controller thin models
• Models too fat? (missing domain class?)
Smells like the wrong
way
• Using models in migrations
• Migrations without down method
• Migrations that change model and update
data
Smells like help
is needed
• Views with query logic
• Views with repeated code
• Views with really complex bits
Refactoring Summary
Rucobop and similar
tools are your friend
Refactoring should be
separated from feature
implementation, use
separated PRs
Organize class
hierarchies with Extract
Superclass, extract
Module, extract class,
move function
Organize method body
with extract method,
extract variable, inline
variable
Remove dead code,
and have only one exit
point per method
whenever possible
Kill anything that
indicate a circular
dependency
Controllers should be
thin, models strong but
not fat
Pay attention to your
migrations
Use view helpers wisely
Don’t add query code
in your views
Cleaner code has less
bugs, and increase your
vacation/free time
Contact
Information

More Related Content

Similar to Ruby code smells

Clean code presentation
Clean code presentationClean code presentation
Clean code presentationBhavin Gandhi
 
Android Deobfuscation: Tools and Techniques
Android Deobfuscation: Tools and TechniquesAndroid Deobfuscation: Tools and Techniques
Android Deobfuscation: Tools and Techniquescaleb194331
 
TDD and the Legacy Code Black Hole
TDD and the Legacy Code Black HoleTDD and the Legacy Code Black Hole
TDD and the Legacy Code Black HoleNoam Kfir
 
2CPP11 - Method Overloading
2CPP11 - Method Overloading2CPP11 - Method Overloading
2CPP11 - Method OverloadingMichael Heron
 
Working With Concurrency In Java 8
Working With Concurrency In Java 8Working With Concurrency In Java 8
Working With Concurrency In Java 8Heartin Jacob
 
20140406 loa days-tdd-with_puppet_tutorial
20140406 loa days-tdd-with_puppet_tutorial20140406 loa days-tdd-with_puppet_tutorial
20140406 loa days-tdd-with_puppet_tutorialgarrett honeycutt
 
Principled And Clean Coding
Principled And Clean CodingPrincipled And Clean Coding
Principled And Clean CodingMetin Ogurlu
 
Code reviews
Code reviewsCode reviews
Code reviewsRoger Xia
 
Few minutes To better Code - Refactoring
Few minutes To better Code - RefactoringFew minutes To better Code - Refactoring
Few minutes To better Code - RefactoringDiaa Al-Salehi
 
Advanced debugging
Advanced debuggingAdvanced debugging
Advanced debuggingAli Akhtar
 
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
 
Metric driven refactoring
Metric driven refactoringMetric driven refactoring
Metric driven refactoringNick Harrison
 
Aki Salmi - Refactoring legacy code: a true story @ I T.A.K.E. Unconference 2...
Aki Salmi - Refactoring legacy code: a true story @ I T.A.K.E. Unconference 2...Aki Salmi - Refactoring legacy code: a true story @ I T.A.K.E. Unconference 2...
Aki Salmi - Refactoring legacy code: a true story @ I T.A.K.E. Unconference 2...Mozaic Works
 
CakePHP 2.0 - PHP Matsuri 2011
CakePHP 2.0 - PHP Matsuri 2011CakePHP 2.0 - PHP Matsuri 2011
CakePHP 2.0 - PHP Matsuri 2011Graham Weldon
 

Similar to Ruby code smells (20)

Clean code presentation
Clean code presentationClean code presentation
Clean code presentation
 
Android Deobfuscation: Tools and Techniques
Android Deobfuscation: Tools and TechniquesAndroid Deobfuscation: Tools and Techniques
Android Deobfuscation: Tools and Techniques
 
Eurosport's Kodakademi #2
Eurosport's Kodakademi #2Eurosport's Kodakademi #2
Eurosport's Kodakademi #2
 
TDD and the Legacy Code Black Hole
TDD and the Legacy Code Black HoleTDD and the Legacy Code Black Hole
TDD and the Legacy Code Black Hole
 
2CPP11 - Method Overloading
2CPP11 - Method Overloading2CPP11 - Method Overloading
2CPP11 - Method Overloading
 
Working With Concurrency In Java 8
Working With Concurrency In Java 8Working With Concurrency In Java 8
Working With Concurrency In Java 8
 
20140406 loa days-tdd-with_puppet_tutorial
20140406 loa days-tdd-with_puppet_tutorial20140406 loa days-tdd-with_puppet_tutorial
20140406 loa days-tdd-with_puppet_tutorial
 
Php traits
Php traitsPhp traits
Php traits
 
Principled And Clean Coding
Principled And Clean CodingPrincipled And Clean Coding
Principled And Clean Coding
 
Code reviews
Code reviewsCode reviews
Code reviews
 
Testing gone-right
Testing gone-rightTesting gone-right
Testing gone-right
 
Clean Code
Clean CodeClean Code
Clean Code
 
Few minutes To better Code - Refactoring
Few minutes To better Code - RefactoringFew minutes To better Code - Refactoring
Few minutes To better Code - Refactoring
 
Advanced debugging
Advanced debuggingAdvanced debugging
Advanced debugging
 
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)
 
Metric driven refactoring
Metric driven refactoringMetric driven refactoring
Metric driven refactoring
 
CPAN Curation
CPAN CurationCPAN Curation
CPAN Curation
 
Aki Salmi - Refactoring legacy code: a true story @ I T.A.K.E. Unconference 2...
Aki Salmi - Refactoring legacy code: a true story @ I T.A.K.E. Unconference 2...Aki Salmi - Refactoring legacy code: a true story @ I T.A.K.E. Unconference 2...
Aki Salmi - Refactoring legacy code: a true story @ I T.A.K.E. Unconference 2...
 
Lambdas in Java 8
Lambdas in Java 8Lambdas in Java 8
Lambdas in Java 8
 
CakePHP 2.0 - PHP Matsuri 2011
CakePHP 2.0 - PHP Matsuri 2011CakePHP 2.0 - PHP Matsuri 2011
CakePHP 2.0 - PHP Matsuri 2011
 

More from Rodrigo Urubatan

Data science in ruby is it possible? is it fast? should we use it?
Data science in ruby is it possible? is it fast? should we use it?Data science in ruby is it possible? is it fast? should we use it?
Data science in ruby is it possible? is it fast? should we use it?Rodrigo Urubatan
 
Data science in ruby, is it possible? is it fast? should we use it?
Data science in ruby, is it possible? is it fast? should we use it?Data science in ruby, is it possible? is it fast? should we use it?
Data science in ruby, is it possible? is it fast? should we use it?Rodrigo Urubatan
 
2018 the conf put git to work - increase the quality of your rails project...
2018 the conf   put git to work -  increase the quality of your rails project...2018 the conf   put git to work -  increase the quality of your rails project...
2018 the conf put git to work - increase the quality of your rails project...Rodrigo Urubatan
 
2018 RubyHACK: put git to work - increase the quality of your rails project...
2018 RubyHACK:  put git to work -  increase the quality of your rails project...2018 RubyHACK:  put git to work -  increase the quality of your rails project...
2018 RubyHACK: put git to work - increase the quality of your rails project...Rodrigo Urubatan
 
TDC2017 - POA - Aprendendo a usar Xamarin para desenvolver aplicações moveis ...
TDC2017 - POA - Aprendendo a usar Xamarin para desenvolver aplicações moveis ...TDC2017 - POA - Aprendendo a usar Xamarin para desenvolver aplicações moveis ...
TDC2017 - POA - Aprendendo a usar Xamarin para desenvolver aplicações moveis ...Rodrigo Urubatan
 
Your first game with unity3d framework
Your first game with unity3d frameworkYour first game with unity3d framework
Your first game with unity3d frameworkRodrigo Urubatan
 
Tdc Floripa 2017 - 8 falácias da programação distribuída
Tdc Floripa 2017 -  8 falácias da programação distribuídaTdc Floripa 2017 -  8 falácias da programação distribuída
Tdc Floripa 2017 - 8 falácias da programação distribuídaRodrigo Urubatan
 
Rubyconf2016 - Solving communication problems in distributed teams with BDD
Rubyconf2016 - Solving communication problems in distributed teams with BDDRubyconf2016 - Solving communication problems in distributed teams with BDD
Rubyconf2016 - Solving communication problems in distributed teams with BDDRodrigo Urubatan
 
resolvendo problemas de comunicação em equipes distribuídas com bdd
resolvendo problemas de comunicação em equipes distribuídas com bddresolvendo problemas de comunicação em equipes distribuídas com bdd
resolvendo problemas de comunicação em equipes distribuídas com bddRodrigo Urubatan
 
vantagens e desvantagens de trabalhar remoto
vantagens e desvantagens de trabalhar remotovantagens e desvantagens de trabalhar remoto
vantagens e desvantagens de trabalhar remotoRodrigo Urubatan
 
Using BDD to Solve communication problems
Using BDD to Solve communication problemsUsing BDD to Solve communication problems
Using BDD to Solve communication problemsRodrigo Urubatan
 
TDC2015 Porto Alegre - Interfaces ricas com Rails e React.JS
TDC2015  Porto Alegre - Interfaces ricas com Rails e React.JSTDC2015  Porto Alegre - Interfaces ricas com Rails e React.JS
TDC2015 Porto Alegre - Interfaces ricas com Rails e React.JSRodrigo Urubatan
 
Interfaces ricas com Rails e React.JS @ Rubyconf 2015
Interfaces ricas com Rails e React.JS @ Rubyconf 2015Interfaces ricas com Rails e React.JS @ Rubyconf 2015
Interfaces ricas com Rails e React.JS @ Rubyconf 2015Rodrigo Urubatan
 
TDC São Paulo 2015 - Interfaces Ricas com Rails e React.JS
TDC São Paulo 2015  - Interfaces Ricas com Rails e React.JSTDC São Paulo 2015  - Interfaces Ricas com Rails e React.JS
TDC São Paulo 2015 - Interfaces Ricas com Rails e React.JSRodrigo Urubatan
 
Full Text Search com Solr, MySQL Full text e PostgreSQL Full Text
Full Text Search com Solr, MySQL Full text e PostgreSQL Full TextFull Text Search com Solr, MySQL Full text e PostgreSQL Full Text
Full Text Search com Solr, MySQL Full text e PostgreSQL Full TextRodrigo Urubatan
 
Ruby para programadores java
Ruby para programadores javaRuby para programadores java
Ruby para programadores javaRodrigo Urubatan
 
Treinamento html5, css e java script apresentado na HP
Treinamento html5, css e java script apresentado na HPTreinamento html5, css e java script apresentado na HP
Treinamento html5, css e java script apresentado na HPRodrigo Urubatan
 
Ruby on rails impressione a você mesmo, seu chefe e seu cliente
Ruby on rails  impressione a você mesmo, seu chefe e seu clienteRuby on rails  impressione a você mesmo, seu chefe e seu cliente
Ruby on rails impressione a você mesmo, seu chefe e seu clienteRodrigo Urubatan
 
Aplicações Hibridas com Phonegap e HTML5
Aplicações Hibridas com Phonegap e HTML5Aplicações Hibridas com Phonegap e HTML5
Aplicações Hibridas com Phonegap e HTML5Rodrigo Urubatan
 

More from Rodrigo Urubatan (20)

Data science in ruby is it possible? is it fast? should we use it?
Data science in ruby is it possible? is it fast? should we use it?Data science in ruby is it possible? is it fast? should we use it?
Data science in ruby is it possible? is it fast? should we use it?
 
Data science in ruby, is it possible? is it fast? should we use it?
Data science in ruby, is it possible? is it fast? should we use it?Data science in ruby, is it possible? is it fast? should we use it?
Data science in ruby, is it possible? is it fast? should we use it?
 
2018 the conf put git to work - increase the quality of your rails project...
2018 the conf   put git to work -  increase the quality of your rails project...2018 the conf   put git to work -  increase the quality of your rails project...
2018 the conf put git to work - increase the quality of your rails project...
 
2018 RubyHACK: put git to work - increase the quality of your rails project...
2018 RubyHACK:  put git to work -  increase the quality of your rails project...2018 RubyHACK:  put git to work -  increase the quality of your rails project...
2018 RubyHACK: put git to work - increase the quality of your rails project...
 
TDC2017 - POA - Aprendendo a usar Xamarin para desenvolver aplicações moveis ...
TDC2017 - POA - Aprendendo a usar Xamarin para desenvolver aplicações moveis ...TDC2017 - POA - Aprendendo a usar Xamarin para desenvolver aplicações moveis ...
TDC2017 - POA - Aprendendo a usar Xamarin para desenvolver aplicações moveis ...
 
Your first game with unity3d framework
Your first game with unity3d frameworkYour first game with unity3d framework
Your first game with unity3d framework
 
Tdc Floripa 2017 - 8 falácias da programação distribuída
Tdc Floripa 2017 -  8 falácias da programação distribuídaTdc Floripa 2017 -  8 falácias da programação distribuída
Tdc Floripa 2017 - 8 falácias da programação distribuída
 
Rubyconf2016 - Solving communication problems in distributed teams with BDD
Rubyconf2016 - Solving communication problems in distributed teams with BDDRubyconf2016 - Solving communication problems in distributed teams with BDD
Rubyconf2016 - Solving communication problems in distributed teams with BDD
 
resolvendo problemas de comunicação em equipes distribuídas com bdd
resolvendo problemas de comunicação em equipes distribuídas com bddresolvendo problemas de comunicação em equipes distribuídas com bdd
resolvendo problemas de comunicação em equipes distribuídas com bdd
 
vantagens e desvantagens de trabalhar remoto
vantagens e desvantagens de trabalhar remotovantagens e desvantagens de trabalhar remoto
vantagens e desvantagens de trabalhar remoto
 
Using BDD to Solve communication problems
Using BDD to Solve communication problemsUsing BDD to Solve communication problems
Using BDD to Solve communication problems
 
TDC2015 Porto Alegre - Interfaces ricas com Rails e React.JS
TDC2015  Porto Alegre - Interfaces ricas com Rails e React.JSTDC2015  Porto Alegre - Interfaces ricas com Rails e React.JS
TDC2015 Porto Alegre - Interfaces ricas com Rails e React.JS
 
Interfaces ricas com Rails e React.JS @ Rubyconf 2015
Interfaces ricas com Rails e React.JS @ Rubyconf 2015Interfaces ricas com Rails e React.JS @ Rubyconf 2015
Interfaces ricas com Rails e React.JS @ Rubyconf 2015
 
TDC São Paulo 2015 - Interfaces Ricas com Rails e React.JS
TDC São Paulo 2015  - Interfaces Ricas com Rails e React.JSTDC São Paulo 2015  - Interfaces Ricas com Rails e React.JS
TDC São Paulo 2015 - Interfaces Ricas com Rails e React.JS
 
Full Text Search com Solr, MySQL Full text e PostgreSQL Full Text
Full Text Search com Solr, MySQL Full text e PostgreSQL Full TextFull Text Search com Solr, MySQL Full text e PostgreSQL Full Text
Full Text Search com Solr, MySQL Full text e PostgreSQL Full Text
 
Ruby para programadores java
Ruby para programadores javaRuby para programadores java
Ruby para programadores java
 
Treinamento html5, css e java script apresentado na HP
Treinamento html5, css e java script apresentado na HPTreinamento html5, css e java script apresentado na HP
Treinamento html5, css e java script apresentado na HP
 
Ruby on rails impressione a você mesmo, seu chefe e seu cliente
Ruby on rails  impressione a você mesmo, seu chefe e seu clienteRuby on rails  impressione a você mesmo, seu chefe e seu cliente
Ruby on rails impressione a você mesmo, seu chefe e seu cliente
 
Mini curso rails 3
Mini curso rails 3Mini curso rails 3
Mini curso rails 3
 
Aplicações Hibridas com Phonegap e HTML5
Aplicações Hibridas com Phonegap e HTML5Aplicações Hibridas com Phonegap e HTML5
Aplicações Hibridas com Phonegap e HTML5
 

Recently uploaded

Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Unlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsUnlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsPrecisely
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptxLBM Solutions
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraDeakin University
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
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
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDGMarianaLemus7
 

Recently uploaded (20)

Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Unlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsUnlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power Systems
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
The transition to renewables in India.pdf
The transition to renewables in India.pdfThe transition to renewables in India.pdf
The transition to renewables in India.pdf
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptx
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
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
 
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptxVulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning era
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
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
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDG
 

Ruby code smells

  • 1. Refactoring for Rails Using deodorant to prevent code smells and a shower from time to time to eliminate the most persistent ones Rodrigo Urubatan Ferreira Jardim rodrigo@urubatan.com http://urubatan.dev http://github.com/urubatan http://twitter.com/urubatan
  • 2. There is no magic trick, to fix most smells we use simple refactoring • Change Function Declaration • Collapse Hierarchy • Extract Module (Combine Functions into…) • Extract Class (Combine Functions into…) • Decompose Conditional • Inline Variable • Extract Variable • Extract Method • Inline Method • Extract Superclass • Move Field • Move Function • Remove Dead Code • Rename Field/Variable/Method/Class • Replace Constructor With Factory Function (here I usually use constantize, …) • Replace TypeCode with subclasses
  • 3. When you feel adventurous • Case statement without else • Old or new code without tests
  • 4. Refactoring good practices/rules • After you complete the refactoring, the tests should still work • Refactoring should not change behavior • In noncritical scenarios refactoring should not change external API • Refactoring is about code quality; you should separate time for it • Time saved to improve code quality will save your vacation time and reduce the number of bugs • Golden rule: big refactoring should be in it’s own PR not in a random feature PR • Exception: always leave the code you touch better than when you found it, always do small refactorings
  • 5. Smells like it’ll explode • Broken chain of nil safe calls (&.) • Nested ternary operators
  • 6. When something smells different • camel case variables… • conditional expression with parenthesis • incorrect parenthesis in method definition • whitespace before parenthesis in method call • negative condition in control flow statement • Attribution sign in comparison • Type Checking • That ruby code that looks like your other language
  • 7. Rubocop for the help • Add to your Gemfile • gem 'rubocop', require: false • Run before every commit • rubocop –a • Abort commit if exit code isn’t zero • I use husky+lint-staged for this module.exports = { '*.js': ['npx prettier --write', 'npx eslint', 'git update-index --again'], '!(*schema).rb': ['rubocop -a --fail-level e', 'git update-index --again'] } Lint-staged.config.js
  • 8. The old and good spaghetti code • Class with too many responsibilities • Method with too many responsibilities • Incomplete library class • Circular dependencies • Change one piece another blows up • Methods with many exit points
  • 9. Whale class/huge class Sometimes a domain has too many things going around
  • 10. Big methods • Sometimes the method is big and the only thing you can do is to make it clear what is it about
  • 11. The first shower to fix big classes and methods • Extract super class • Collapse hierarchy • Extract module • Move function • Extract method • Extract variable • Inline variable • Rename Class/Method/Variable
  • 12. Fruit salad • Too many instance variables • Too many methods • Methods with too many arguments
  • 13. Some things just smells like nothing • Many return statements • Unneeded comments • If Boolean true than false • Value objects?
  • 14. That thing that smells like prison • To change one class or method safely you need to touch many other methods or classes • when you need to change 5 different projects because you removed one field of a table
  • 15. Fat smell? • Fat controller thin models • Models too fat? (missing domain class?)
  • 16. Smells like the wrong way • Using models in migrations • Migrations without down method • Migrations that change model and update data
  • 17. Smells like help is needed • Views with query logic • Views with repeated code • Views with really complex bits
  • 18. Refactoring Summary Rucobop and similar tools are your friend Refactoring should be separated from feature implementation, use separated PRs Organize class hierarchies with Extract Superclass, extract Module, extract class, move function Organize method body with extract method, extract variable, inline variable Remove dead code, and have only one exit point per method whenever possible Kill anything that indicate a circular dependency Controllers should be thin, models strong but not fat Pay attention to your migrations Use view helpers wisely Don’t add query code in your views Cleaner code has less bugs, and increase your vacation/free time

Editor's Notes

  1. Code smells are a really cool way to describe and remember things that in some situations might cause issues in our code, flags to parts of the code that need refactoring. And there are many different names for common refactoring techniques, some language specific, but after researching most of what I saw was already described in the refactoring holly book. This presentation will not be code intensive; I’ll hardly show any code but I’ll try to help everyone identify some red flags and will comment how to improve them, most of the time using techniques name from this book.
  2. Adventure is good when we arrive in a marvelous country like Thailand, but for our code it isn’t always good… I know that sometimes the case without else covers all the possibilities of an enumeration, but in the future we might add another item to that enumeration and break the code And for code without tests that is always a big risk of everything breaking down with any change We have all been there, I use an enum to identify tag types in a system, and that enum has a case to display a user friendly name in one or two screens in the system, after a few years the system was running fine, the editors asked for a new tag type, that we promptly added to the enumeration, and a “Undefined method for NilClass” started appearing in the system logs and this is a sample of both scenarios because we also didn’t add the new enum value to the test case before that bug… And of course, those two situations aren’t even in the refactoring list, maybe in Clean Code, but it is better to avoid both scenarios when possible And add new tests for any code you touch
  3. There are other scenarios that can explode your code and are easy to find and fix, the easiest way to find these simpler cases is to use a tool like rubocop
  4. Rubocop will also help your ruby code look and feel like Ruby code, and not like the juice stand in a comedy show from Latin America in the show a homeless boy opened a juice stand, and whenever you asked for one of the juices he would say: this one is lemon juice, it tastes like gooseberry and looks like tamarind.. Rubocop standard configuration will warn you before your code looks like one of those juices
  5. I think it is a good practice to add rubocop for all your projects Gemfile, that will prevent versioning issues and make sure you always have it installed. And with a little help of husky and lint-staged JS modules, we can make sure it is executed before every commit reducing the risk of human error/forgetting to run it I think of rubocop as your everyday deodorant, it’ll keep out most mildly smells but won’t prevent you from needing a shower
  6. This is one of the best smells on an Italian restaurant and one of the worst smiles on your code, if you think of spaghetti while looking at the code it means there are many other smaller smells, like a wale class, dolphin method, you might smell something missing, or you might smell like you’ve been there already. One of the most common consequences of this smell is that when you change one part of the code, another or many other parts will blow due to circular dependencies or simply poor organization. There isn’t one single path to fix this big mess, so I’ll break it into a few different smells to help with the refactoring.
  7. When you find a whale class, it is probably not alone, because whales travel in pod, and they are usually composed of big methods
  8. Dolphin methods are usually a big part of whale classes, most of the time these big methods are doing more than they should, but even if they aren’t doing more then what they should, they will make your life debugging or understanding the code a less fun and a lor harder.
  9. In case the pod of whales has duplicated code what is really common, we can start the refactoring with an extract super class, sometimes the pod has nothing in common, in this case we collapse hierarchy, and when the whale is trying to fly, walk or do something that it shouldn’t we can extract module or extract class to move the weird behavior outside and use composition. Since in our code whales and dolphins usually are part of the same pod, we’ll also use a lot of extract method, that is one of the hardest refactoring in my opinion, because it involves passing parameters to the new method, using a good name and returning everything the old method needs to continue and if this is correctly done the new method might remove duplicated code from other parts of our big class hierarchy. Many times we combine extract method with move function to move methods to the new parent class or the newly created module. Extract variable also usually helps in extracting methods, and sometimes inline variable will make the extracted method include code duplicated code from more whales. This also means that we usually use extract/inline variable to create code duplication in many places to solve that duplication with extract method. An last but not less important, an spaghetti rarely has a good naming convention, so use rename with abundance.
  10. Some classes remember a fruit salad, because they contain a lot of instance variables, a huge number of methods and methods with too many attributes. Sometimes this is hidden, like an activerecord class that points to a table with a huge number of fields. To improve this scenarios, to initialize a class with too many instance variables and to fix methods with too many arguments we usually accept a parameter object, what in ruby is usually replaces by a more flexible hash. For an API method it is usually better to receive an object with the specific arguments instead of having one method with many arguments in-line, it is easier to document. The refactoring for that would be a Combine Variables into Value Object, and combine arguments into Value Object
  11. There is also code that just doesn’t smell like anything, actually it smells like it shouldn’t be there, for these we use Remove Dead Code And with a lot of dead code removed, and sometimes not dead but simply useless like return statements, our code will look a lot more like ruby and will look cleaner. Also using returns when the code isn’t really useless, we should probably rearrange the logic of that method because too many exist points is a really bad code smell that will start turning your code into an Italian pasta
  12. There are other scenarios where your code is making your life a lot harder, for example when a change in one method reflects in many different places, or worse yet to change one field or method you need to apply the same change in various other places. This is usually a lack of encapsulation To solve this, we should use Encapsulate Variable or work on the class hierarchies with Extract Superclass or Collapse Hierarchy, usually the former is better. There is also no perfect path for something that is depended on a lot of places, but it is a good idea to have clear paths of dependencies through the application and libraries, and avoid circular dependencies with all your forces.
  13. Those are the two most common rails anti patterns, of course there is no magic number but if your controller is doing much more than preparing data to send to the model and preparing the result to send to the view probably most of that logic should be extracted to a method and then the method moved to the model. And if the models are too fat it is very possible they are doing too many things that aren’t really related, or they become a domain dumpster Like a music model, that starts with music name, id, file name, and suddenly starts to convert the music file to wav, mp3, ogg, created a clip for that music, counts downloads, … the convert methods should be their own commands, the download counter should probably be another model, that would also help to save more information about who and when the music was downloaded, … In summary a fat model is usually doing things that should be elsewhere and a fat controller is probably doing things the model should do.
  14. Migrations are those things that when you have multiple environments or take too long to move a feature to production will break during every deploy, not all migrations of course, but one of them will… And it is usually because a model that was used in a migration changed after the migration was created The migration doesn’t have a down method so you can’t go back to where you were before to work on the other feature and your database becomes a mess of migrated code from different branches And migrations that change models and update data at the same time are also a good source for errors and regrets. For these situations I could not apply the refactoring names from martin fowler book, but just avoid these cases that in my experience are the most common error sources in migrations.
  15. When you are using erb views the most common anti patterns are adding model query logic in the views, that should be in the controllers, in the best case scenario the data needed for that view should get to the view in instance variables. Also views with repeated code or some really complex parts, those two scenarios have the same solution, use extract method for the complex or repeated part, and move the method to a ViewHelper This also has the side effect of allowing that bit of code to be easily tested