how to rate a rails application

Post on 17-May-2015

4.034 Views

Category:

Technology

2 Downloads

Preview:

Click to see full reader

DESCRIPTION

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

TRANSCRIPT

How to rate a Rails application

Elise Huard @elise_huardhttp://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 endend resources :nodes, :only => [:show,:new,:create,:destroy] do put :directions, :on => :collectionend

resources :walkers, :only => [:show,:new,:create,:destroy] do get :select, :on => :collectionendresources :itineraries, :only => [:show]

map.four_oh_four '*path' , :controller => 'four_oh_fours'Sunday 30 May 2010

modelsrailroad -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 treeRubyParser.new.parse(File.read(‘metrics.rb’),‘metric.rb’)

class Metrics def probe puts "good" end end

s(:class,:Metrics, nil, s(:scope, s(:defn,:probe, s(:args), s(:scope, s(:block, s(:call, nil, :puts, s(:arglist, s(:str, "good"))))))))

Symbolic Expression (Sexp)

Sunday 30 May 2010

RubyParser and Parsetree

Abstract syntax treeRubyParser.new.parse(File.read(‘metrics.rb’),‘metric.rb’)

class Metrics def probe puts "good" end end

s(:class,:Metrics, nil, s(:scope, s(:defn,:probe, s(:args), s(:scope, s(:block, s(:call, nil, :puts, s(:arglist, s(:str, "good"))))))))

Symbolic Expression (Sexp)

Ruby2Ruby

Sunday 30 May 2010

RubyParser

Parsetree

pure ruby

ruby and inline c< 1.9

Sunday 30 May 2010

cyclomatic complexity

size

code complexity code similarities

test coverage

antipatterns

rake stats

Flay

ReekRoodi

Flog

Saikuro

Heckle Rcov

Rails

R_B_P

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

MethodsVery good: < 20All Right: < 50

Sunday 30 May 2010

FLAYcode similarities

Sunday 30 May 2010

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

FLAY

Sunday 30 May 2010

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 = similarif same node = identical

FLAY

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 calculateif, 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

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

Sunday 30 May 2010

Reek

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

RubyParserextends parsed nodes

traverses nodesreturns code after Ruby2Ruby

Sunday 30 May 2010

rails_best_practices

kamoda on Flickr

Sunday 30 May 2010

./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

rails_best_practices

Sunday 30 May 2010

rails_best_practices

Visitor patternvisitor : checking_visitorvisitable: 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, svnLocates 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 testkeeps track of the executed linesUsing 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 + Ruby2Rubymutate

time-consuming: combinatorialsmore 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

cyclomatic complexity

size

code complexity code similarities

test coverage

antipatterns

rake stats

Flay

ReekRoodi

Flog

Saikuro

Heckle Rcov

RAILS_BEST_PRACTICES

Sunday 30 May 2010

metric_fu

Sunday 30 May 2010

OrbitalJoe on flickr

check out the good stuff

Sunday 30 May 2010

what these metrics don’t tell you

Bugs

Sunday 30 May 2010

what these metrics don’t tell you

code performanceRuby Profiling

Sunday 30 May 2010

Reads like a book

Sunday 30 May 2010

top related