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 hereend
Does This Smell?def has_currency_rate?  val = false  if currency.id == company.currency.id or rate.blank?  else    val = t...
Does This Smell?class FinancialEventObserver < ActiveRecord::Observer  observe Payment, Invoice  def before_save(model)   ...
Code That Smells• Runtime errors• Runtime warnings• Dead code• Copy/paste• Complex method bodies• Code style violations• F...
Code Quality Tools         Static                     Runtime   flay          roodi                     rspecmetrics_fu    ...
Static Tools• Inspect your code without launching it• 100% side effects free• Challenging to implement• Rails DSL magic ki...
Reek• Class, module, method, identifier names• Using is_a?, kind_of? instead of duck typing• Code duplicates• Large classes...
Flog• Uses ABC metrics system    •   Assignment    •   Branches    •   Conditions    •   |ABC| = √(A²+B²+C²)• Consider rev...
Flay   • Analyzes code duplicates   • Ignores identifier/       constants names   • Consider refactoring       code that’s ...
Roodi• Assignments in conditions• Case blocks without else• Large classes, modules and methods• Naming conventions• Cyclom...
metrics_fu/metricalProvides 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 ...
Runtime Tools• Code testing   •   Test::Unit/MiniTest   •   RSpec/Cucumber   •   Autotest/CI• Code coverage   •   RCov/Sim...
Heckle• Changes code    • if → unless    • Calls are changed    • Numbers are changed• Runs tests• At least one test shoul...
RubyMine•   Static analysis     •   On-the-fly inspections with quickfixes     •   Understands Rails DSLs     •   Code dupli...
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
Upcoming SlideShare
Loading in...5
×

Frozen rails 2012 - Fighting Code Smells

1,380

Published on

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,380
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
8
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • Runtime warnings (like parens in calls, ineffective global variables)\nCode style violations (naming conventions, parentheses around conditional)\nFramework pattern violations - MVC pattern violations\n
  • Mention that\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Frozen rails 2012 - Fighting Code Smells

    1. 1. Fighting Code Smells ruby code analysis tools Dennis Ushakov
    2. 2. Pareto Principle • 20% Write new code • 80% Modify existing code
    3. 3. Does This Smell?a = something.valid?if (a.to_s == "true") # code hereend
    4. 4. Does This Smell?def has_currency_rate? val = false if currency.id == company.currency.id or rate.blank? else val = true end valend
    5. 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. 6. Code That Smells• Runtime errors• Runtime warnings• Dead code• Copy/paste• Complex method bodies• Code style violations• Framework pattern violations
    7. 7. Code Quality Tools Static Runtime flay roodi rspecmetrics_fu rcov dust simplecov heckle reek autotest pelusa cucumberflog
    8. 8. Static Tools• Inspect your code without launching it• 100% side effects free• Challenging to implement• Rails DSL magic kills ‘em
    9. 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. 10. Flog• Uses ABC metrics system • Assignment • Branches • Conditions • |ABC| = √(A²+B²+C²)• Consider revising most painful methods
    11. 11. Flay • Analyzes code duplicates • Ignores identifier/ constants names • Consider refactoring code that’s reported
    12. 12. Roodi• Assignments in conditions• Case blocks without else• Large classes, modules and methods• Naming conventions• Cyclomatic complexity
    13. 13. metrics_fu/metricalProvides aggregate results for• Flay• Flog• Reek• Roodi
    14. 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. 15. Runtime Tools• Code testing • Test::Unit/MiniTest • RSpec/Cucumber • Autotest/CI• Code coverage • RCov/SimpleCov • Heckle
    16. 16. Heckle• Changes code • if → unless • Calls are changed • Numbers are changed• Runs tests• At least one test should fail after change
    17. 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. 18. Refactorings• Rename• Extract • Method • Class/Module • Variable/Parameter
    19. 19. Morale• Use static analysis tools• Don’t forget to test• Try RubyMine http://jetbrains.com/ ruby
    20. 20. dennis.ushakov@jetbrains.com en_Dal denofevil
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×