SlideShare a Scribd company logo
How to rate a
               Rails application

           Elise Huard @elise_huard
           http://jabberwocky.eu


Sunday 30 May 2010
Acquisition
Sunday 30 May 2010
Maintenance


Sunday 30 May 2010
Where to Start ?




Sunday 30 May 2010
Try the app




                             Björn Söderqvist on Flickr

Sunday 30 May 2010
Rails version




Sunday 30 May 2010
plugins and
                    gems




                               Photo Lex on Flickr

Sunday 30 May 2010
Sunday 30 May 2010
Run Tests




Sunday 30 May 2010
Lots of code
Sunday 30 May 2010
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'
models
                railroad -M | dot Tpng > models.png
                        rubymine ctrl-alt-D
Sunday 30 May 2010
names


                     “There are only two hard things in
                     Computer Science: cache
                     invalidation and naming things”
                                             Phil Karlton




Sunday 30 May 2010
Metrics:
                     Know thine Tools


                                 docman on flickr
Sunday 30 May 2010
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
RubyParser and
                           Parsetree



                     Ryan Davis and Eric Hodel
                          (‘Ruby Sadists’)




Sunday 30 May 2010
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
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
RubyParser

                        pure ruby

                       Parsetree
                     ruby and inline c
                          < 1.9



Sunday 30 May 2010
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
flog
                     ‘the pain your code
                             is in’




Sunday 30 May 2010
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
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
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
FLOG


                        Methods
                     Very good: < 20
                     All Right: < 50




Sunday 30 May 2010
FLAY
                     code similarities




Sunday 30 May 2010
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
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
Saikuro

                     cyclomatic
                     complexity
Sunday 30 May 2010
Saikuro




Sunday 30 May 2010
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
Saikuro




                        Good:
                     methods < 5




Sunday 30 May 2010
Roodi
           ‘Ruby Object Oriented Design Inferometer’




                                            nutmeg66 on flickr
Sunday 30 May 2010
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
Roodi


                     RubyParser
                     visitor pattern
                      visitor: checker (Configuration)
                      visitable: parsed nodes
                     = extensible




Sunday 30 May 2010
Reek




Sunday 30 May 2010
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
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
Reek



                              RubyParser
                         extends parsed nodes
                            traverses nodes
                     returns code after Ruby2Ruby




Sunday 30 May 2010
rails_best_practices




                                   kamoda on Flickr

Sunday 30 May 2010
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
rails_best_practices


                           Visitor pattern
                     visitor : checking_visitor
                      visitable: visitable sexp




Sunday 30 May 2010
Churn




Sunday 30 May 2010
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
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
Churn



                              common sense ...
                     mostly useful in maintenance phase




Sunday 30 May 2010
Rcov
Sunday 30 May 2010
Rcov




               Total coverage: comments included




Sunday 30 May 2010
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
Rcov



                     good: 100% coverage




Sunday 30 May 2010
Heckle




Sunday 30 May 2010
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
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
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
metric_fu




Sunday 30 May 2010
check out the good stuff




                                           OrbitalJoe on flickr
Sunday 30 May 2010
what these metrics don’t
                             tell you



                              Bugs




Sunday 30 May 2010
what these metrics don’t
                             tell you



                         code performance
                          Ruby Profiling




Sunday 30 May 2010
Reads like a book

Sunday 30 May 2010
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

More Related Content

KEY
Minicurso Ruby e Rails
KEY
Objective-C & iPhone for .NET Developers
PDF
Ruby hollywood nordic
PDF
Ireland Travel Driving Guide
PDF
Building Community Gardens Manual
ODP
I N C O M E T A X L A W O F I N D I A
PDF
PDF
Cyber [crime|war deepsec
Minicurso Ruby e Rails
Objective-C & iPhone for .NET Developers
Ruby hollywood nordic
Ireland Travel Driving Guide
Building Community Gardens Manual
I N C O M E T A X L A W O F I N D I A
Cyber [crime|war deepsec

Similar to how to rate a Rails application (20)

PDF
12 hours to rate a rails application
PDF
12 Hours To Rate A Rails Application
PDF
Paul Querna - libcloud
PDF
How to Begin Developing Ruby Core
PDF
Python for Chemistry
PDF
Python for Chemistry
PPTX
APOC Pearls - Whirlwind Tour Through the Neo4j APOC Procedures Library
PPTX
Code for Startup MVP (Ruby on Rails) Session 2
PDF
Python utan-stodhjul-motorsag
PPTX
A Workshop on R
PDF
How to Begin to Develop Ruby Core
PDF
A Recovering Java Developer Learns to Go
PPTX
Clojure And Swing
PDF
Rejectkaigi 2010
PDF
Couchdbkit & Dango
PDF
Couchdbkit djangocong-20100425
PDF
Webinar: What's New in Solr 7
PDF
30 Days to Elixir and Crystal and Back to Ruby
PDF
ScaleCamp 2009 - Last.fm vs Xbox
PDF
Spock: Test Well and Prosper
12 hours to rate a rails application
12 Hours To Rate A Rails Application
Paul Querna - libcloud
How to Begin Developing Ruby Core
Python for Chemistry
Python for Chemistry
APOC Pearls - Whirlwind Tour Through the Neo4j APOC Procedures Library
Code for Startup MVP (Ruby on Rails) Session 2
Python utan-stodhjul-motorsag
A Workshop on R
How to Begin to Develop Ruby Core
A Recovering Java Developer Learns to Go
Clojure And Swing
Rejectkaigi 2010
Couchdbkit & Dango
Couchdbkit djangocong-20100425
Webinar: What's New in Solr 7
30 Days to Elixir and Crystal and Back to Ruby
ScaleCamp 2009 - Last.fm vs Xbox
Spock: Test Well and Prosper
Ad

More from ehuard (12)

PDF
Euroclojure 2017
PDF
Ruby goes to Hollywood
PDF
Ruby goes to hollywood
PDF
Ruby hollywood
PDF
Concurrency: Rubies, plural
PDF
Concurrency
PDF
Concurrency
KEY
Barcamp Ghent2009
ODP
Tokyo Cabinet
ODP
The real-time web
KEY
Rails and the internet of things
ODP
Oauth
Euroclojure 2017
Ruby goes to Hollywood
Ruby goes to hollywood
Ruby hollywood
Concurrency: Rubies, plural
Concurrency
Concurrency
Barcamp Ghent2009
Tokyo Cabinet
The real-time web
Rails and the internet of things
Oauth
Ad

Recently uploaded (20)

DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
Encapsulation theory and applications.pdf
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PPTX
Cloud computing and distributed systems.
PDF
Approach and Philosophy of On baking technology
PDF
NewMind AI Weekly Chronicles - August'25 Week I
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PPTX
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PPT
Teaching material agriculture food technology
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PPTX
A Presentation on Artificial Intelligence
The AUB Centre for AI in Media Proposal.docx
Chapter 3 Spatial Domain Image Processing.pdf
Understanding_Digital_Forensics_Presentation.pptx
Diabetes mellitus diagnosis method based random forest with bat algorithm
Encapsulation theory and applications.pdf
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Cloud computing and distributed systems.
Approach and Philosophy of On baking technology
NewMind AI Weekly Chronicles - August'25 Week I
“AI and Expert System Decision Support & Business Intelligence Systems”
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Building Integrated photovoltaic BIPV_UPV.pdf
Teaching material agriculture food technology
Network Security Unit 5.pdf for BCA BBA.
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
Reach Out and Touch Someone: Haptics and Empathic Computing
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
A Presentation on Artificial Intelligence

how to rate a Rails application

  • 1. How to rate a Rails application Elise Huard @elise_huard http://jabberwocky.eu 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
  • 7. plugins and gems Photo Lex on Flickr 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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