how to rate a Rails application

  • 3,936 views
Uploaded on

Talk given at Euruko 2010: the talk describes how to quickly evaluate the quality of a Rails codebase. Ruby metrics are explained in detail.

Talk given at Euruko 2010: the talk describes how to quickly evaluate the quality of a Rails codebase. Ruby metrics are explained in detail.

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
3,936
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
28
Comments
0
Likes
8

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

Transcript

  • 1. How to rate a Rails application Elise Huard @elise_huard http://jabberwocky.eu Sunday 30 May 2010
  • 2. Acquisition Sunday 30 May 2010
  • 3. Maintenance Sunday 30 May 2010
  • 4. Where to Start ? Sunday 30 May 2010
  • 5. Try the app Björn Söderqvist on Flickr Sunday 30 May 2010
  • 6. Rails version Sunday 30 May 2010
  • 7. plugins and gems Photo Lex on Flickr Sunday 30 May 2010
  • 8. Sunday 30 May 2010
  • 9. Run Tests Sunday 30 May 2010
  • 10. Lots of code Sunday 30 May 2010
  • 11. config/routes.rb match ‘/’, :to => ‘root#index’ match ‘root’, :to => ‘root#index’ namespace :admin do resources :grids do resources :nodes resources :edges do collection do post :all post :update_all end end resources :walkers end end resources :nodes, :only => [:show,:new,:create,:destroy] do put :directions, :on => :collection end resources :walkers, :only => [:show,:new,:create,:destroy] do get :select, :on => :collection end resources :itineraries, :only => [:show] Sunday 30 May 2010 map.four_oh_four '*path' , :controller => 'four_oh_fours'
  • 12. models railroad -M | dot Tpng > models.png rubymine ctrl-alt-D Sunday 30 May 2010
  • 13. names “There are only two hard things in Computer Science: cache invalidation and naming things” Phil Karlton Sunday 30 May 2010
  • 14. Metrics: Know thine Tools docman on flickr Sunday 30 May 2010
  • 15. LOC rake stats +----------------------+-------+-------+---------+---------+-----+-------+ | Name | Lines | LOC | Classes | Methods | M/C | LOC/M | +----------------------+-------+-------+---------+---------+-----+-------+ | Controllers | 2702 | 2150 | 36 | 158 | 4 | 11 | | Helpers | 358 | 303 | 0 | 22 | 0 | 11 | | Models | 1358 | 1104 | 30 | 117 | 3 | 7 | | Libraries | 2286 | 1655 | 38 | 152 | 4 | 8 | | Integration tests | 0 | 0 | 0 | 0 | 0 | 0 | | Functional tests | 1687 | 1322 | 31 | 195 | 6 | 4 | | Unit tests | 1356 | 1079 | 27 | 158 | 5 | 4 | +----------------------+-------+-------+---------+---------+-----+-------+ | Total | 9747 | 7613 | 162 | 802 | 4 | 7 | +----------------------+-------+-------+---------+---------+-----+-------+ Code LOC: 5212 Test LOC: 2401 Code to Test Ratio: 1:0.5 Sunday 30 May 2010
  • 16. RubyParser and Parsetree Ryan Davis and Eric Hodel (‘Ruby Sadists’) Sunday 30 May 2010
  • 17. RubyParser and Parsetree Abstract syntax tree RubyParser.new.parse(File.read(‘metrics.rb’),‘metric.rb’) class Metrics s(:class,:Metrics, nil, def probe s(:scope, s(:defn,:probe, puts "good" s(:args), end s(:scope, end s(:block, s(:call, nil, :puts, s(:arglist, s(:str, "good")))))))) Symbolic Expression (Sexp) Sunday 30 May 2010
  • 18. RubyParser and Parsetree Abstract syntax tree RubyParser.new.parse(File.read(‘metrics.rb’),‘metric.rb’) class Metrics s(:class,:Metrics, nil, def probe s(:scope, s(:defn,:probe, puts "good" s(:args), end s(:scope, end s(:block, s(:call, nil, :puts, s(:arglist, s(:str, "good")))))))) Symbolic Expression (Sexp) Ruby2Ruby Sunday 30 May 2010
  • 19. RubyParser pure ruby Parsetree ruby and inline c < 1.9 Sunday 30 May 2010
  • 20. rake stats size Flog Flay code complexity code similarities Roodi R_B_P Saikuro Reek cyclomatic antipatterns Rails complexity Heckle Rcov test coverage Sunday 30 May 2010
  • 21. flog ‘the pain your code is in’ Sunday 30 May 2010
  • 22. FLOG flog lib/flog.rb 647.8: flog total 13.8: flog/method average 87.5: Flog#output_details 58.8: Flog#process_iter 54.2: Flog#flog 48.8: Flog#parse_options 34.1: Flog#none 23.2: Flog#output_method_details 22.1: Flog#score_method 16.0: Flog#process_block_pass 15.6: Flog#report 15.2: Flog#expand_dirs_to_files 15.0: Flog#klass_name Sunday 30 May 2010
  • 23. FLOG Assignment Branch Condition (ABC) def score_method(tally) a, b, c = 0, 0, 0 tally.each do |cat, score| case cat when :assignment then a += score when :branch then b += score else c += score end end Math.sqrt(a*a + b*b + c*c) end Sunday 30 May 2010
  • 24. FLOG Weighing the AST with factors def process_if(exp) add_to_score :branch process exp.shift # cond penalize_by 0.1 do process exp.shift # true process exp.shift # false end s() end Sunday 30 May 2010
  • 25. FLOG Methods Very good: < 20 All Right: < 50 Sunday 30 May 2010
  • 26. FLAY code similarities Sunday 30 May 2010
  • 27. FLAY flay *.rb Total score (lower is better) = 621 1) IDENTICAL code found in :defn (mass*2 = 188) channel.rb:48 clip.rb:80 2) Similar code found in :defn (mass = 93) channel.rb:150 clip.rb:110 clip.rb:116 3) Similar code found in :defs (mass = 58) contact.rb:32 contact.rb:37 Sunday 30 May 2010
  • 28. FLAY RubyParser def mass @mass ||= self.structure.flatten.size end Hash of structure of nodes with mass > threshold self.hashes[node.structural_hash] << node analyze: if same hash = similar if same node = identical Sunday 30 May 2010
  • 29. Saikuro cyclomatic complexity Sunday 30 May 2010
  • 30. Saikuro Sunday 30 May 2010
  • 31. Saikuro ruby-lex every keyword is interpreted into ‘state’ state used to calculate if, unless, while, until, for, elsif, when, rescue (blocks) Recursively Sunday 30 May 2010
  • 32. Saikuro Good: methods < 5 Sunday 30 May 2010
  • 33. Roodi ‘Ruby Object Oriented Design Inferometer’ nutmeg66 on flickr Sunday 30 May 2010
  • 34. Roodi app/controllers/itineraries_controller.rb:4 - Method name "show" cyclomatic complexity is 14. It should be 8 or less. app/models/itinerary.rb:41 - Block cyclomatic complexity is 6. It should be 4 or less. app/controllers/itineraries_controller.rb:4 - Method "show" has 30 lines. It should have 20 or less. app/helpers/application_helper.rb:27 - Method "clippy" has 26 lines. It should have 20 or less. Sunday 30 May 2010
  • 35. Roodi RubyParser visitor pattern visitor: checker (Configuration) visitable: parsed nodes = extensible Sunday 30 May 2010
  • 36. Reek Sunday 30 May 2010
  • 37. Reek more OO-specific checks Control Couple Data Clump Feature Envy Large Class Long Method Long Parameter List Simulated Polymorphism Uncommunicative Name Sunday 30 May 2010
  • 38. Reek UserSessionsController has no descriptive comment (Irresponsible Module) UserSessionsController#destroy calls current_user_session twice (Duplication) app/controllers/users_controller.rb -- 5 warnings: UsersController has no descriptive comment (Irresponsible Module) UsersController tests @aid_app at least 4 times (Simulated Polymorphism) UsersController#create calls params 3 times (Duplication) UsersController#create calls params[:user] 3 times (Duplication) ... Sunday 30 May 2010
  • 39. Reek RubyParser extends parsed nodes traverses nodes returns code after Ruby2Ruby Sunday 30 May 2010
  • 40. rails_best_practices kamoda on Flickr Sunday 30 May 2010
  • 41. rails_best_practices ./app/controllers/ws/vmg/aid_user_accounts_controller.rb:160 - move model logic into model (@aid_user_account called_count > 4) ./app/controllers/ws/vmg/ipt_controller.rb:102 - move model logic into model (xml called_count > 4) ./app/controllers/ws/vmg/ipt_controller.rb:102 - move model logic into model (pf called_count > 4) ./config/routes.rb:3 - overuse route customizations (customize_count > 3) ./config/routes.rb:35 - overuse route customizations (customize_count > 3) ./app/models/vmg/scenario.rb:41 - keep finders on their own model Sunday 30 May 2010
  • 42. rails_best_practices Visitor pattern visitor : checking_visitor visitable: visitable sexp Sunday 30 May 2010
  • 43. Churn Sunday 30 May 2010
  • 44. Churn +-------------------------------------------------+---------------+ | file_path | times_changed | +-------------------------------------------------+---------------+ | db/schema.rb | 26 | | config/routes.rb | 24 | | app/controllers/application_controller.rb | 22 | | app/controllers/add_apps_controller.rb | 22 | | config/environment.rb | 20 | | app/views/layouts/application.html.erb | 20 | | app/models/ability.rb | 18 | ... Sunday 30 May 2010
  • 45. Churn Not only classes but also methods (RubyParser) Version control: git, Hg, svn Locates changes in source using logs (as in git log) Sunday 30 May 2010
  • 46. Churn common sense ... mostly useful in maintenance phase Sunday 30 May 2010
  • 47. Rcov Sunday 30 May 2010
  • 48. Rcov Total coverage: comments included Sunday 30 May 2010
  • 49. Rcov Executes test keeps track of the executed lines Using C extension when possible to hook into MRI (experimental for 1.9) Sunday 30 May 2010
  • 50. Rcov good: 100% coverage Sunday 30 May 2010
  • 51. Heckle Sunday 30 May 2010
  • 52. Heckle ParseTree + Ruby2Ruby mutate time-consuming: combinatorials more for small programs (gems, scripts) doesn’t work for ruby 1.9 (ParseTree) Sunday 30 May 2010
  • 53. Heckle Initial tests pass. Let's rumble. ********************************************************************** *** AidApp#property_names loaded with 4 possible mutations ********************************************************************** 4 mutations remaining... Replacing AidApp#property_names with: --- original +++ mutation def property_names - (meta_policy and meta_policy.property_names_for(:aid_app)) + (nil and meta_policy.property_names_for(:aid_app)) end Sunday 30 May 2010
  • 54. rake stats size Flog Flay code complexity code similarities Roodi Saikuro Reek cyclomatic antipatterns RAILS_BEST complexity _PRACTICES Heckle Rcov test coverage Sunday 30 May 2010
  • 55. metric_fu Sunday 30 May 2010
  • 56. check out the good stuff OrbitalJoe on flickr Sunday 30 May 2010
  • 57. what these metrics don’t tell you Bugs Sunday 30 May 2010
  • 58. what these metrics don’t tell you code performance Ruby Profiling Sunday 30 May 2010
  • 59. Reads like a book Sunday 30 May 2010
  • 60. http://railroad.rubyforge.org/ http://www.igvita.com/2008/12/11/ruby-ast-for-fun-and-profit/ http://ruby.sadi.st/Ruby_Sadist.html http://goruco2008.confreaks.com/04_davis.html http://cwd.dhemery.com/2009/11/wmaat/ http://c2.com/cgi/wiki?AbcMetric http://hissa.nist.gov/HHRFdata/Artifacts/ITLdoc/235/title.htm http://blog.rubybestpractices.com/posts/judofyr/sexp-for- rubyists.html Elise Huard @elise_huard elise@elisehuard.be http://jabberwocky.eu http://github.com/elisehuard Sunday 30 May 2010