Frozen rails 2012 - Fighting Code Smells

  • 1,233 views
Uploaded on

 

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
1,233
On Slideshare
0
From Embeds
0
Number of Embeds
1

Actions

Shares
Downloads
6
Comments
0
Likes
2

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    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

Transcript

  • 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 hereend
  • 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. 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 rspecmetrics_fu rcov dust simplecov heckle reek autotest pelusa cucumberflog
  • 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/metricalProvides 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