SlideShare a Scribd company logo
Fighting Code Smells

 ruby code analysis tools
        Dennis Ushakov
Pareto Principle

         •   20%
             Write new code

         • 80%
             Modify existing code
Does This Smell?

a = something.valid?

if (a.to_s == "true")
  # code here
end
Does This Smell?

def has_currency_rate?
  val = false
  if currency.id == company.currency.id or rate.blank?
  else
    val = true
  end
  val
end
Does This Smell?
class FinancialEventObserver < ActiveRecord::Observer
  observe Payment, Invoice
  def before_save(model)
    event = nil
    if model.class == Payment
      if model.new_record?
        event = FinancialEvent.new(:event => FinancialEvent::Event::PAYMENT_INVOICE,
        :arguments => {:client_name => model.invoice.client.short_name, :invoice_number =>
model.invoice.invoice_number},
          :company_id=>model.invoice.client.company.id)
      end
    elsif model.class == Invoice
      i = Invoice.find_by_id model.id
      if model.new_record? or i.status != model.status
        if model.status == Invoice::Status::ESTIMATE
          event = FinancialEvent.new(:event => FinancialEvent::Event::ESTIMATE_SEND,
        :arguments => {:client_name => model.client.short_name, :invoice_number => model.invoice_number},
            :company_id=>model.client.company.id)
        elsif model.status == Invoice::Status::APPROVED
          event = FinancialEvent.new(:event => FinancialEvent::Event::ESTIMATE_APPROVED,
        :arguments => {:client_name => model.client.short_name, :invoice_number => model.invoice_number},
            :company_id=>model.client.company.id)
        elsif model.status == Invoice::Status::REJECTED
          event = FinancialEvent.new(:event => FinancialEvent::Event::ESTIMATE_REJECTED,
        :arguments => {:client_name => model.client.short_name, :invoice_number => model.invoice_number},
            :company_id=>model.client.company.id)
        elsif model.status == Invoice::Status::SEND
          event = FinancialEvent.new(:event => FinancialEvent::Event::INVOICE_SEND,
        :arguments => {:client_name => model.client.short_name, :invoice_number => model.invoice_number},
            :company_id=>model.client.company.id)
        end
      elsif !model.new_record? and i.state != model.state
        if model.state == Invoice::State::DELETED
          event = FinancialEvent.new(:event => FinancialEvent::Event::INVOICE_DELETED,
        :arguments => {:invoice_number => model.invoice_number},
            :company_id=>model.client.company.id)
        end
      end
    end
    event.eventable = model.requester unless event.blank?
    event.save unless event.blank?
Code That Smells
• Runtime errors
• Runtime warnings
• Dead code
• Copy/paste
• Complex method bodies
• Code style violations
• Framework pattern violations
Code Quality Tools
         Static                     Runtime

   flay          roodi                     rspec
metrics_fu                      rcov
                 dust                        simplecov
      heckle            reek   autotest
             pelusa                       cucumber
flog
Static Tools

• Inspect your code without launching it
• 100% side effects free
• Challenging to implement
• Rails DSL magic kills ‘em
Reek

• Class, module, method, identifier names
• Using is_a?, kind_of? instead of duck typing
• Code duplicates
• Large classes and methods
• Nested iterators
Flog
• Uses ABC metrics system
    •   Assignment

    •   Branches

    •   Conditions

    •   |ABC| = √(A²+B²+C²)

• Consider revising most
  painful methods
Flay

   • Analyzes code duplicates
   • Ignores identifier/
       constants names

   • Consider refactoring
       code that’s reported
Roodi

• Assignments in conditions
• Case blocks without else
• Large classes, modules and methods
• Naming conventions
• Cyclomatic complexity
metrics_fu/metrical

Provides aggregate results for
• Flay
• Flog
• Reek
• Roodi
Runtime Tools

• Inspect your code by launching it
• 100% follow the way Ruby works
• Cope well with DSL magic
• May have side effects
• Works until the very first failure
Runtime Tools
• Code testing
   •   Test::Unit/MiniTest

   •   RSpec/Cucumber

   •   Autotest/CI

• Code coverage
   •   RCov/SimpleCov

   •   Heckle
Heckle
• Changes code
    • if → unless
    • Calls are changed
    • Numbers are changed
• Runs tests
• At least one test should
  fail after change
RubyMine
•   Static analysis
     •   On-the-fly inspections with quickfixes

     •   Understands Rails DSLs

     •   Code duplication

•   Dynamic analysis tools integration
     •   Graphical representation

     •   Autotest simulation

     •   Stacktrace navigation
Refactorings

• Rename
• Extract
   •   Method

   •   Class/Module

   •   Variable/Parameter
Morale

• Use static analysis
  tools

• Don’t forget to test
• Try RubyMine
  http://jetbrains.com/
  ruby
dennis.ushakov@jetbrains.com
          en_Dal
          denofevil

More Related Content

PDF
Fighting Ruby code smell
PPT
RubyMotion #jbday
PPTX
Day 8 - jRuby
PPT
Web development basics (Part-5)
PDF
What's new in PHP 7.1
PDF
Node.js Patterns and Opinions
PPT
Web development basics (Part-3)
PDF
Ruby and Rails by Example (GeekCamp edition)
Fighting Ruby code smell
RubyMotion #jbday
Day 8 - jRuby
Web development basics (Part-5)
What's new in PHP 7.1
Node.js Patterns and Opinions
Web development basics (Part-3)
Ruby and Rails by Example (GeekCamp edition)

What's hot (20)

PDF
Spring I/O 2012: Natural Templating in Spring MVC with Thymeleaf
PDF
Ruby onrails cucumber-rspec-capybara
PDF
Gtg12
PDF
Shootout! Template engines for the JVM
PDF
Model with actors and implement with Akka
KEY
Intro to Ruby on Rails
PPT
Web development basics (Part-6)
PDF
RoR (Ruby on Rails)
ODP
How to start using Scala
PPT
Web development basics (Part-2)
PPT
Ruby On Rails Presentation
PPTX
Day 1 - Intro to Ruby
PDF
遇見 Ruby on Rails
PDF
Thymeleaf, will it blend?
PPTX
Automating Your Daily Tasks with Scripting - RubyConf 2015 Taiwan
PDF
Back to the future: Isomorphic javascript applications
PDF
PDF
GraphQL-PHP: Dos and don'ts
PDF
Ruby performance - The low hanging fruit
PDF
Spring I/O 2012: Natural Templating in Spring MVC with Thymeleaf
Ruby onrails cucumber-rspec-capybara
Gtg12
Shootout! Template engines for the JVM
Model with actors and implement with Akka
Intro to Ruby on Rails
Web development basics (Part-6)
RoR (Ruby on Rails)
How to start using Scala
Web development basics (Part-2)
Ruby On Rails Presentation
Day 1 - Intro to Ruby
遇見 Ruby on Rails
Thymeleaf, will it blend?
Automating Your Daily Tasks with Scripting - RubyConf 2015 Taiwan
Back to the future: Isomorphic javascript applications
GraphQL-PHP: Dos and don'ts
Ruby performance - The low hanging fruit
Ad

Similar to Frozen rails 2012 - Fighting Code Smells (20)

PDF
Rails antipattern-public
PDF
Rails antipatterns
PPTX
Random Ruby Tips - Ruby Meetup 27 Jun 2018
PDF
2011-02-03 LA RubyConf Rails3 TDD Workshop
KEY
Developer testing 101: Become a Testing Fanatic
PDF
Rails Tips and Best Practices
PDF
QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...
PPT
KEY
Tdd for BT E2E test community
PDF
Working Effectively With Legacy Perl Code
PDF
Pragmatic Patterns of Ruby on Rails - Ruby Kaigi2009
PDF
Refactoring
ZIP
Continuous Integration For Rails Project
PDF
Refactoring @ Mindvalley: Smells, Techniques and Patterns
PPTX
Coding Naked 2023
PPTX
How to practice TDD without shooting yourself in the foot
PDF
Where Does the Fat Goes? Utilizando Form Objects Para Simplificar seu Código
PDF
Into The Box 2018 - CBT
PPTX
DDD, CQRS and testing with ASP.Net MVC
PPTX
PVS-Studio and static code analysis technique
Rails antipattern-public
Rails antipatterns
Random Ruby Tips - Ruby Meetup 27 Jun 2018
2011-02-03 LA RubyConf Rails3 TDD Workshop
Developer testing 101: Become a Testing Fanatic
Rails Tips and Best Practices
QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...
Tdd for BT E2E test community
Working Effectively With Legacy Perl Code
Pragmatic Patterns of Ruby on Rails - Ruby Kaigi2009
Refactoring
Continuous Integration For Rails Project
Refactoring @ Mindvalley: Smells, Techniques and Patterns
Coding Naked 2023
How to practice TDD without shooting yourself in the foot
Where Does the Fat Goes? Utilizando Form Objects Para Simplificar seu Código
Into The Box 2018 - CBT
DDD, CQRS and testing with ASP.Net MVC
PVS-Studio and static code analysis technique
Ad

Recently uploaded (20)

PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PPT
Teaching material agriculture food technology
PPTX
breach-and-attack-simulation-cybersecurity-india-chennai-defenderrabbit-2025....
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
KodekX | Application Modernization Development
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
GamePlan Trading System Review: Professional Trader's Honest Take
PPTX
Cloud computing and distributed systems.
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Empathic Computing: Creating Shared Understanding
PDF
Advanced IT Governance
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
Machine learning based COVID-19 study performance prediction
Diabetes mellitus diagnosis method based random forest with bat algorithm
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
The Rise and Fall of 3GPP – Time for a Sabbatical?
Teaching material agriculture food technology
breach-and-attack-simulation-cybersecurity-india-chennai-defenderrabbit-2025....
“AI and Expert System Decision Support & Business Intelligence Systems”
KodekX | Application Modernization Development
20250228 LYD VKU AI Blended-Learning.pptx
Chapter 3 Spatial Domain Image Processing.pdf
Mobile App Security Testing_ A Comprehensive Guide.pdf
Spectral efficient network and resource selection model in 5G networks
GamePlan Trading System Review: Professional Trader's Honest Take
Cloud computing and distributed systems.
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
MYSQL Presentation for SQL database connectivity
Empathic Computing: Creating Shared Understanding
Advanced IT Governance
Review of recent advances in non-invasive hemoglobin estimation
Dropbox Q2 2025 Financial Results & Investor Presentation
Machine learning based COVID-19 study performance prediction

Frozen rails 2012 - Fighting Code Smells

  • 1. Fighting Code Smells ruby code analysis tools Dennis Ushakov
  • 2. Pareto Principle • 20% Write new code • 80% Modify existing code
  • 3. Does This Smell? a = something.valid? if (a.to_s == "true") # code here end
  • 4. Does This Smell? def has_currency_rate? val = false if currency.id == company.currency.id or rate.blank? else val = true end val end
  • 5. Does This Smell? class FinancialEventObserver < ActiveRecord::Observer observe Payment, Invoice def before_save(model) event = nil if model.class == Payment if model.new_record? event = FinancialEvent.new(:event => FinancialEvent::Event::PAYMENT_INVOICE, :arguments => {:client_name => model.invoice.client.short_name, :invoice_number => model.invoice.invoice_number}, :company_id=>model.invoice.client.company.id) end elsif model.class == Invoice i = Invoice.find_by_id model.id if model.new_record? or i.status != model.status if model.status == Invoice::Status::ESTIMATE event = FinancialEvent.new(:event => FinancialEvent::Event::ESTIMATE_SEND, :arguments => {:client_name => model.client.short_name, :invoice_number => model.invoice_number}, :company_id=>model.client.company.id) elsif model.status == Invoice::Status::APPROVED event = FinancialEvent.new(:event => FinancialEvent::Event::ESTIMATE_APPROVED, :arguments => {:client_name => model.client.short_name, :invoice_number => model.invoice_number}, :company_id=>model.client.company.id) elsif model.status == Invoice::Status::REJECTED event = FinancialEvent.new(:event => FinancialEvent::Event::ESTIMATE_REJECTED, :arguments => {:client_name => model.client.short_name, :invoice_number => model.invoice_number}, :company_id=>model.client.company.id) elsif model.status == Invoice::Status::SEND event = FinancialEvent.new(:event => FinancialEvent::Event::INVOICE_SEND, :arguments => {:client_name => model.client.short_name, :invoice_number => model.invoice_number}, :company_id=>model.client.company.id) end elsif !model.new_record? and i.state != model.state if model.state == Invoice::State::DELETED event = FinancialEvent.new(:event => FinancialEvent::Event::INVOICE_DELETED, :arguments => {:invoice_number => model.invoice_number}, :company_id=>model.client.company.id) end end end event.eventable = model.requester unless event.blank? event.save unless event.blank?
  • 6. Code That Smells • Runtime errors • Runtime warnings • Dead code • Copy/paste • Complex method bodies • Code style violations • Framework pattern violations
  • 7. Code Quality Tools Static Runtime flay roodi rspec metrics_fu rcov dust simplecov heckle reek autotest pelusa cucumber flog
  • 8. Static Tools • Inspect your code without launching it • 100% side effects free • Challenging to implement • Rails DSL magic kills ‘em
  • 9. Reek • Class, module, method, identifier names • Using is_a?, kind_of? instead of duck typing • Code duplicates • Large classes and methods • Nested iterators
  • 10. Flog • Uses ABC metrics system • Assignment • Branches • Conditions • |ABC| = √(A²+B²+C²) • Consider revising most painful methods
  • 11. Flay • Analyzes code duplicates • Ignores identifier/ constants names • Consider refactoring code that’s reported
  • 12. Roodi • Assignments in conditions • Case blocks without else • Large classes, modules and methods • Naming conventions • Cyclomatic complexity
  • 13. metrics_fu/metrical Provides aggregate results for • Flay • Flog • Reek • Roodi
  • 14. Runtime Tools • Inspect your code by launching it • 100% follow the way Ruby works • Cope well with DSL magic • May have side effects • Works until the very first failure
  • 15. Runtime Tools • Code testing • Test::Unit/MiniTest • RSpec/Cucumber • Autotest/CI • Code coverage • RCov/SimpleCov • Heckle
  • 16. Heckle • Changes code • if → unless • Calls are changed • Numbers are changed • Runs tests • At least one test should fail after change
  • 17. RubyMine • Static analysis • On-the-fly inspections with quickfixes • Understands Rails DSLs • Code duplication • Dynamic analysis tools integration • Graphical representation • Autotest simulation • Stacktrace navigation
  • 18. Refactorings • Rename • Extract • Method • Class/Module • Variable/Parameter
  • 19. Morale • Use static analysis tools • Don’t forget to test • Try RubyMine http://jetbrains.com/ ruby
  • 20. dennis.ushakov@jetbrains.com en_Dal denofevil

Editor's Notes