12 Hours To Rate A Rails Application

  • 3,191 views
Uploaded on

In some situations, it's useful to be able to evaluate a Rails application quickly. …

In some situations, it's useful to be able to evaluate a Rails application quickly.
I talk about how I work to get the most data as possible to get a good picture of whether an application is well-maintained, and will be easy to maintain later.

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

Actions

Shares
Downloads
35
Comments
0
Likes
7

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

  • a big company wants to acquire a startup that has a rails application.
    before the sale goes through, they want to be sure they get value for money.
    they call in an expert to have a look.
    you are the expert.

  • You go to the startup, you sign an NDA, and you get access to the code.
    You usually have full cooperation of the team, who would be eager for you to give a good report.
  • sit down with the team
    they will make an introduction
    and you can observe them:
    looking at people you can already form an idea
  • you have experience which will allow you to tell whether you have a team that will produce good to great software.
  • One guy: usually bad sign - easier to slack off when you’re alone
    commit everything
    maintainable test
    broken windows
    automation: manual scripts/hacks a person is not even consciously aware of
    simple peer pressure in everything
  • I’m sure there are many learned articles about group dynamics, about personality types in a team, etc ...
    the innovator: keeps up with what’s out there, wants to be on top of the next great thing
    the automator: more a sysadmin profile maybe - someone who likes scripting and making everything run smoothly
    the ant: obsessive-compulsive types who want to have every detail perfect.
  • You’ll notice I don’t include him ...

    Bottom line, after you’ve worked a while, you get a feel for what constitutes a good team. Getting to know a team can already tell you something about the application you’re about to look at ...

    On a less pleasant note, some of those people will be employed by the buyer. key players in the team


  • tools I think you cannot do without. Even if the bug tracker is a text file.

  • so you sat down with the team, you discussed the application, their philosophy, the deployment, other aspects ...

  • it’s time to dive in, and see what we have here.
  • does it work ?
    does the application match the vision ?
    Is it clear at all ? ‘don’t make me think’
    do you manage to get pesky 500s and 404 ?
  • that shouldn’t take too long.
  • then you can start inventorizing what you’ve got.
    First off, what version of rails are they using ?
    I think it’s a good sign when it’s a reasonably recent version.
  • Same for plugins.
    what gems, what plugins are they using ?
    Is it the last version ?
  • I’m a firm believer in the natural selection of open source
    Are they popular ?
    Are they maintained ?
  • are the plugins and gems easily updatable ?
  • another aspect you might not think of, but will interest the acquirer: what license is the code under ?
    Obviously, for commercial code, the freer the better - MIT or BSD license over GPL
  • I think I look out for, is the Not Invented Here syndrom.
    some people will not trust plugins they have not written themselves.
    That’s fine, but
    - reinventing the wheel
    - maintaining the wheel
    - by releasing it, you express your confidence that it is good code.
    - adoption and maintenance by others

  • OK, plugins and gems are inventorized.
  • you often have a sizeable code base to look at ... where to start ?

    Where would you start ?
  • what’s the action in the application ?

  • clearly named ?
    may not be clear to you - domain-dependent
    ideally googleable
    sometimes internal jargon for the firm
    ask someone in the same business what a term means
    ask a developer what it means
  • we now have a very high level view of the application.

    Now, before continuing, there is one priority

  • One way to start analyzing a large amount of code, is by using metrics.
  • I’m going to go a little bit more in-depth about the metric tools.
    There have been many presentations and blog posts about the subject, I’m going to try to go a little bit further, to give you an idea of what’s under the hood
  • the first code metric in history are lines of code.
    Unfortunately, they don’t tell you very much: imagine you add a few lines of comment, you break up an expression into several lines - for the same code you can double the number of lines.
    They give you an idea of the approximate size.

  • Most of the metrics tool rest on ruby parsing.
    RubyParser and ParseTree are both tools developed by Kevin Clarke and Ryan Biggs
    Also known as the Ruby Sadists

    The idea is to navigate the abstract syntax tree =
    code represented as a tree
    symbolic expressions are a good way to represent this tree
    list-based data structures that represent semi-structured data.
    . Lisp, Scheme
    the output of ruby parser and parsetree is a symbolic expression.
  • Flog is one of the tools made by Rian Bigg
    It gives a measure of code complexity.

    For every tool I try to give first a description,
    then some implementation details
    and finally what is expected for good code
  • How flog works:
    the AST is recursively accessed, and a calculation is made
    the calculation happens with ABC
    Assignment Branch Conditions - a traditional measure of code complexity.
  • The result is a series of number - per class and per method.
  • Per method, you expect something like this



  • guess where the name ‘saikuro’ comes from
    Japanese people have this habit of taking over words that indicate new concepts
    bi-ru co-hee
    it’s cyclo as used by japanese people
    number of linearly independent paths through a program's source code.
    it’s also a measure of code complexity
  • lexer: step before parsing -
    split program = characters - into tokens


  • we come to the less quantitative tools - roodi and reek find design issues for you.
  • abc metric like flog
    assignment in conditional
    missing else in a case
    class variables




  • Control couple: the execution of a method depends on one of the parameters (conditional on parameter). Also when one of parameters is defaulted to true or false
    Data clump: variables appearing together all the time - suggesting missing abstraction
    feature envy: when code fragment references other object more than it references itself, or when several objects do the same kind of manipulation on a particular kind of object
    Simulated polymorphism: case statements, several ifs, is_a_kind_of?






  • The tool we all know to check our test coverage


  • Now, code coverage doesn’t say much.
    For a good test set, you need 100%, but that’s a minimum requirement.
    You can have 100% coverage without
  • Heckle is really interesting in theory, difficult to apply in practice.

  • in the next mutation, it changed this to nil
    the one after that, ti change the symbol to something else



  • So I looked at the metrics, and I read some of the code that was flagged. time flies, and we have only 7 hours to go
  • and it’s time for lunch

  • revigorated, it’s time to continue

    with metrics, you got to see their worst. the monster methods, the antipatterns ...
    now you could also apply some normal codereading
    ask them what the core is, what their best code is
  • code should be readable. Ideally like a book

    At the very least it shouldn’t take too much effort to understand what’s going on.
  • rails is not slow, developers make bad use of the data base
    it’s not because we use an ORM that we can drop all knowledge
  • this is a plugin I’d rather not see. It means that you can go several levels of has_many_through
    in this case, it might be a good idea to reconsider. either using sql, or views at db level, or denormalize
  • We’ve looked at models, views
    in fact maybe we need a metric tool for views, too

    divitis
    javascript in the body
    unindented
    too much logic in view

  • it’s time to have a closer look at the tests.
    first off, it makes sense to run them

  • automated test suites fail when they expect not to have any maintenance
    tests take maintenance
    tests are software
    changes will occur, and they can be of 2 natures
  • does that remind you of something ?

  • deployment is important, but not that critical
    if you’ve got a well-structured, well-written, modular application, you can change deployment fairly easily
  • one thing to add in your description of the application: a schematic of the deployment
    they should be able to provide that, if only on a paper napkin





  • those were for me the important points
    if what we saw up to now is ok, they will get a good report.
    the following slides will get them a glowing report, with exclamation points




  • It’s time to go home with your notes and write a report

    Are there any questions ?
  • I hope you enjoyed the talk, and that you got something out of it.

Transcript

  • 1. hours to rate a Rails application Elise Huard @elise_huard http://jabberwocky.eu Wednesday 31 March 2010
  • 2. Acquisition Wednesday 31 March 2010
  • 3. Maintenance Wednesday 31 March 2010
  • 4. 12 hours To Rate a Rails Application 12:00 Wednesday 31 March 2010
  • 5. Team Wednesday 31 March 2010
  • 6. Team: use your gut Wednesday 31 March 2010
  • 7. One man’s application Wednesday 31 March 2010
  • 8. innovator automator Control Freak Wednesday 31 March 2010
  • 9. ... Wednesday 31 March 2010
  • 10. Vision Wednesday 31 March 2010
  • 11. Methodology Wednesday 31 March 2010
  • 12. Bug Tracker Version control Wednesday 31 March 2010
  • 13. Back seat driver Wednesday 31 March 2010
  • 14. 12 hours To Rate a Rails Application 10:00 Wednesday 31 March 2010
  • 15. Try the app Wednesday 31 March 2010
  • 16. does it work ? Wednesday 31 March 2010
  • 17. 12 hours To Rate a Rails Application 09:45 Wednesday 31 March 2010
  • 18. Rails version Wednesday 31 March 2010
  • 19. plugins and gems Wednesday 31 March 2010
  • 20. Wednesday 31 March 2010
  • 21. managing updates piston git submodules (svn externals) Wednesday 31 March 2010
  • 22. Licenses Wednesday 31 March 2010
  • 23. NIH syndrom Wednesday 31 March 2010
  • 24. 12 hours To Rate a Rails Application 09:00 Wednesday 31 March 2010
  • 25. All that code Wednesday 31 March 2010
  • 26. config/routes.rb map.root :controller => 'root', :action => 'index' map.namespace :admin do |admin| admin.resources :grids do |grid| grid.resources :nodes grid.resources :edges, :collection => {:all => :post, :update_all => :post} grid.resources :walkers end end map.resources :nodes, :only => [:new,:create,:show,:destroy], :collection => {:directions => :put} map.resources :walkers, :only => [:show,:new,:create,:destroy], :collection => {:select => :get} map.resources :itineraries, :only => [:show] map.four_oh_four '*path' , :controller => 'four_oh_fours' Wednesday 31 March 2010
  • 27. models railroad -M | dot Tpng > models.png rubymine ctrl-alt-D uml dumper (needs maintenance) Wednesday 31 March 2010
  • 28. names “There are only two hard things in Computer Science: cache invalidation and naming things” Phil Karlton Wednesday 31 March 2010
  • 29. 12 hours To Rate a Rails Application 08:30 Wednesday 31 March 2010
  • 30. Coffee Wednesday 31 March 2010
  • 31. metrics Wednesday 31 March 2010
  • 32. Know thine tools Wednesday 31 March 2010
  • 33. 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 Wednesday 31 March 2010
  • 34. RubyParser and Parsetree Ryan Davis and Eric Hodel (‘Ruby Sadists’) Wednesday 31 March 2010
  • 35. 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 Wednesday 31 March 2010
  • 36. flog ‘the pain your code is in’ Wednesday 31 March 2010
  • 37. FLOG Weighing the AST with factors Assignment Branch Condition (ABC) 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 Wednesday 31 March 2010
  • 38. 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 Wednesday 31 March 2010
  • 39. FLOG Very good: < 20 All Right: < 50 Wednesday 31 March 2010
  • 40. FLAY code similarities Wednesday 31 March 2010
  • 41. 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 Wednesday 31 March 2010
  • 42. 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 Wednesday 31 March 2010
  • 43. Saikuro cyclomatic complexity Wednesday 31 March 2010
  • 44. Saikuro ruby-lex every keyword is interpreted into ‘state’ state used to calculate if, unless, while, until, for, elsif, when, rescue (blocks) Recursively Wednesday 31 March 2010
  • 45. Saikuro Wednesday 31 March 2010
  • 46. Saikuro Good: methods < 5 Wednesday 31 March 2010
  • 47. Roodi Ruby Object Oriented Design Inferometer (what ?) “design issues” Wednesday 31 March 2010
  • 48. Roodi RubyParser visitor pattern visitor: checker (Configurable) visitable: parsed nodes = extensible Wednesday 31 March 2010
  • 49. 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. Wednesday 31 March 2010
  • 50. Reek Control Couple Data Clump Feature Envy Large Class Long Method Long Parameter List Simulated Polymorphism Uncommunicative Name Wednesday 31 March 2010
  • 51. Reek RubyParser extends parsed nodes traverses nodes returns code after Ruby2Ruby Wednesday 31 March 2010
  • 52. 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) ... Wednesday 31 March 2010
  • 53. Churn Frequent changes may indicate issue Wednesday 31 March 2010
  • 54. Churn Not only classes but also methods (RubyParser) Version control: git, Hg, svn Locates changes in source using logs (as in git log) Wednesday 31 March 2010
  • 55. 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 | ... Wednesday 31 March 2010
  • 56. Churn common sense ... mostly useful in maintenance phase Wednesday 31 March 2010
  • 57. Rcov Wednesday 31 March 2010
  • 58. Rcov Executes test keeps track of the executed lines Using C extension when possible to hook into MRI (experimental for 1.9) Wednesday 31 March 2010
  • 59. Rcov Total coverage: comments included Wednesday 31 March 2010
  • 60. Rcov good: 100% coverage Wednesday 31 March 2010
  • 61. Heckle Wednesday 31 March 2010
  • 62. Heckle ParseTree + Ruby2Ruby mutate doesn’t work for ruby 1.9 (ParseTree) time-consuming: combinatorials more for small programs (gems, scripts) Wednesday 31 March 2010
  • 63. 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 Wednesday 31 March 2010
  • 64. rake stats size Flog Flay code complexity code similarities Roodi Saikuro Reek cyclomatic antipatterns complexity Heckle Rcov test coverage Wednesday 31 March 2010
  • 65. metric_fu Wednesday 31 March 2010
  • 66. 12 hours To Rate a Rails Application 06:30 Wednesday 31 March 2010
  • 67. Lunch Wednesday 31 March 2010
  • 68. and more Coffee Wednesday 31 March 2010
  • 69. read some code Wednesday 31 March 2010
  • 70. Expressive code Wednesday 31 March 2010
  • 71. Database db/schema.rb seed data everything in migrations ? Wednesday 31 March 2010
  • 72. Nested_has_many_through Wednesday 31 March 2010
  • 73. views Bad: unindented divitis javascript in the body too much logic in viewiew Wednesday 31 March 2010
  • 74. 12 hours To Rate a Rails Application 04:30 Wednesday 31 March 2010
  • 75. run tests Wednesday 31 March 2010
  • 76. Time for tests (or autotest/ci) Wednesday 31 March 2010
  • 77. maintainable test suite tests = software changes in implementation changes in requirements Wednesday 31 March 2010
  • 78. maintainable test suite express code responsibility hide incident detail DRY Wednesday 31 March 2010
  • 79. 12 hours To Rate a Rails Application 02:30 Wednesday 31 March 2010
  • 80. Deployment Wednesday 31 March 2010
  • 81. Deployment Wednesday 31 March 2010
  • 82. Deployment Automation, automation, automation Wednesday 31 March 2010
  • 83. Deployment deployment = software same rules apply Wednesday 31 March 2010
  • 84. Traffic Wednesday 31 March 2010
  • 85. Performance tests Bottlenecks Wednesday 31 March 2010
  • 86. 12 hours To Rate a Rails Application 01:00 Wednesday 31 March 2010
  • 87. Brownie Points Wednesday 31 March 2010
  • 88. Continuous integration ... and they’re using it Wednesday 31 March 2010
  • 89. Documentation of any kind ... and it’s up to date Wednesday 31 March 2010
  • 90. monitoring exception notification Log analyzers Wednesday 31 March 2010
  • 91. testing javascripts Continuous performance testing Wednesday 31 March 2010
  • 92. 12 hours To Rate a Rails Application 00:00 Wednesday 31 March 2010
  • 93. 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 Wednesday 31 March 2010