SlideShare a Scribd company logo
1 of 173
Download to read offline
Code Quality
                               What is this s**t?




                          Steve Hayes - Cogent Consulting Pty Ltd
                            http://www.cogentconsulting.com.au
                           steve.hayes@cogentconsulting.com.au



Friday, 28 August 2009                                              1
In 1990 there were 120 billion lines of code




Friday, 28 August 2009                                                  2
In 2000 there were 250 billion lines of code




Friday, 28 August 2009                                                  3
In 2010 there will be 500 billion lines of code




Friday, 28 August 2009                                                 4
Printed in a font 1mm high
               the code listing would stretch
               from the Earth to the Moon
               and beyond




Friday, 28 August 2009                          5
Code Quality



Friday, 28 August 2009                  6
Code quality is subjective - it requires human
                                       judgment




Friday, 28 August 2009                                                7
There have been, and always will be, arguments
                               about code quality




Friday, 28 August 2009                                             8
Friday, 28 August 2009   9
WTF implies lack of clarity




Friday, 28 August 2009                                 10
“Simplicity, clarity, singleness: These are the
               attributes that give our lives power and vividness
                and joy as they are also the marks of great art.
                  The seem to be the purpose of God for his
                                 whole creation.”

                                               Richard Holloway




Friday, 28 August 2009                                              11
Clear code is easier to understand, easier to
                                maintain, and easier to extend




Friday, 28 August 2009                                                   12
There are many things that can reduce the clarity
                             of code, including:

                         •   inconsistent style
                         •   long methods
                         •   lots of methods in a single class
                         •   repeated code
                         •   methods with many alternative paths



Friday, 28 August 2009                                             13
Your particular bugbears may be different




Friday, 28 August 2009                                               14
Why metrics?




Friday, 28 August 2009                  15
We substitute metrics for human judgement




Friday, 28 August 2009                                               16
Friday, 28 August 2009   17
People are expensive, CPU time is cheap




Friday, 28 August 2009                                             18
Use automation to detect clarity problems, such
             as:

                         •   inconsistent style
                         •   long methods
                         •   lots of methods in a single class
                         •   repeated code
                         •   methods with many alternative paths



Friday, 28 August 2009                                             19
Use exception based reporting so that people can
                            focus their energy




Friday, 28 August 2009                                          20
on the quality exceptions




Friday, 28 August 2009                               21
or on completely different things




Friday, 28 August 2009                                       22
Friday, 28 August 2009   23
Code Analysis



Friday, 28 August 2009                   24
Let’s start with some Ruby

                         Formtastic by Justin French




Friday, 28 August 2009                                 25
Then we’ll move on to some Java




Friday, 28 August 2009                                     26
Duplication



Friday, 28 August 2009                 27
Friday, 28 August 2009   28
Duplication makes everything else worse




Friday, 28 August 2009                                         29
Friday, 28 August 2009   30
Initial analysis of Formtastic




Friday, 28 August 2009                                    31
37 Roodi problems

                         95 Flog problems




Friday, 28 August 2009                       32
Simian
                         http://www.redhillconsulting.com.au/products/simian/




Friday, 28 August 2009                                                          33
Simian - Similarity Analyser | Duplicate Code Detection for the Enterprise                          14/08/09 3:41 AM




                                                         Simian - Similarity Analyser
           Purpose
           Simian (Similarity Analyser) identifies duplication in Java, C#, C, C++, COBOL, Ruby, JSP, ASP,
           HTML, XML, Visual Basic, Groovy source code and even plain text files. In fact, simian can be used on
           any human readable files such as ini files, deployment descriptors, you name it.

           Especially on large enterprise projects, it can be difficult for any one developer to keep track of all the
           features (classes, methods, etc.) of the system.

           Simian runs natively in any .NET 1.1 or higher supported environment and on any Java 1.4 or higher
           virtual machine, meaning Simian can be run on just about any hardware and any operating system you
           can hope for. Both the Java and .NET runtimes are included as part of the distribution.

           Simian can be used as part of the build process during development or as a guide when re-factoring.
           Think of Simian as an independent pair of eyes that will assist in raising the quality of your software.

           Within minutes, Simian can save you literally thousands of dollars in time spent performing maintenence,
           debugging and re-factoring.

           With licensing available to suite personal, project and enterprise use, simian is ideally suited for use on
           your project.

           Why do I need Simian?
           Imagine for example that a bug is discovered in a method somewhere in a project. The developer duly
           writes a test case, makes the necessary code changes, ensures the test passes, checks the code in and
           considers the job finished!

           Right?
Friday, 28 August 2009                                                                                                          34
Simian highlights obvious duplication




Friday, 28 August 2009                                           35
Similarity Analyser 2.2.24 - http://www.redhillconsulting.com.au/products/simian/index.html
                     Copyright (c) 2003-08 RedHill Consulting Pty. Ltd. All rights reserved.
                     Simian is not free unless used solely for non-commercial or evaluation purposes.
                     {failOnDuplication=true, ignoreCharacterCase=true, ignoreCurlyBraces=true, ignoreIdentifierCase=true,
                     ignoreModifiers=true, ignoreStringCase=true, threshold=6}
                     Found 7 duplicate lines in the following files:
                      Between lines 949 and 962 in /Users/stevehayes/projects/third-party/formtastic/spec/formtastic_spec.rb
                      Between lines 969 and 982 in /Users/stevehayes/projects/third-party/formtastic/spec/formtastic_spec.rb
                     Found 7 duplicate lines in the following files:
                      Between lines 2552 and 2562 in /Users/stevehayes/projects/third-party/formtastic/spec/formtastic_spec.rb
                      Between lines 2752 and 2762 in /Users/stevehayes/projects/third-party/formtastic/spec/formtastic_spec.rb
                     Found 11 duplicate lines in the following files:
                      Between lines 1429 and 1446 in /Users/stevehayes/projects/third-party/formtastic/spec/formtastic_spec.rb
                      Between lines 1758 and 1775 in /Users/stevehayes/projects/third-party/formtastic/spec/formtastic_spec.rb
                     Found 50 duplicate lines in 6 blocks in 1 files
                     Processed a total of 2066 significant (4341 raw) lines in 6 files
                     Processing time: 0.144sec




Friday, 28 August 2009                                                                                                           36
Flay
                         http://ruby.sadi.st/Flay.html




Friday, 28 August 2009                                   37
Confessions of a Ruby Sadist sudo gem install flay                                               14/08/09 3:46 AM




                                                       Ruby Sadist            Flog   Flay   Heckle   Kittens   About Us




                                     Confessions of a Ruby Sadist
                                                                     sudo gem install flay

                         Flay analyzes ruby code for
                         structural similarities. Differences
                         in literal values, names,
                         whitespace, and programming
                         style are all ignored.

                         Code that flay reports as similar
                         is a good candidate for
                         refactoring.

                         Try this:

                         % sudo gem install
                         flay
                         % flay lib/*.rb

                         and see what you find.




Friday, 28 August 2009                                                                                                                       38
Flay detects more subtle duplication




Friday, 28 August 2009                                          39
Total score (lower is better) = 2637              8) Similar code found in :iter (mass = 96)
                                                                       spec/formtastic_spec.rb:1825
                                                                       spec/formtastic_spec.rb:1831
                    1) Similar code found in :iter (mass = 342)        spec/formtastic_spec.rb:1844
                     spec/formtastic_spec.rb:1570                      spec/formtastic_spec.rb:1877
                     spec/formtastic_spec.rb:1616                      spec/formtastic_spec.rb:1895
                                                                       spec/formtastic_spec.rb:1914
                    2) Similar code found in :iter (mass = 136)
                     spec/formtastic_spec.rb:1183                     9) Similar code found in :iter (mass = 92)
                     spec/formtastic_spec.rb:2147                      spec/formtastic_spec.rb:2235
                     spec/formtastic_spec.rb:2313                      spec/formtastic_spec.rb:2245
                     spec/formtastic_spec.rb:2368
                                                                      10) Similar code found in :block (mass = 84)
                    3) IDENTICAL code found in :iter (mass*2 = 136)    spec/formtastic_spec.rb:1900
                     spec/formtastic_spec.rb:1458                      spec/formtastic_spec.rb:1919
                     spec/formtastic_spec.rb:1787
                                                                      11) IDENTICAL code found in :block (mass*2 = 84)
                    4) IDENTICAL code found in :iter (mass*2 = 120)    spec/formtastic_spec.rb:187
                     spec/formtastic_spec.rb:1069                      spec/formtastic_spec.rb:194
                     spec/formtastic_spec.rb:1133
                                                                      12) Similar code found in :iter (mass = 84)
                    5) IDENTICAL code found in :iter (mass*2 = 104)    spec/formtastic_spec.rb:774
                     spec/formtastic_spec.rb:232                       spec/formtastic_spec.rb:830
                     spec/formtastic_spec.rb:392
                                                                      13) Similar code found in :iter (mass = 78)
                    6) Similar code found in :iter (mass = 100)        spec/formtastic_spec.rb:1208
                     spec/formtastic_spec.rb:2572                      spec/formtastic_spec.rb:1239
                     spec/formtastic_spec.rb:2771                      spec/formtastic_spec.rb:1265

                    7) Similar code found in :iter (mass = 98)        14) Similar code found in :iter (mass = 75)
                     spec/formtastic_spec.rb:408                       spec/formtastic_spec.rb:596
                     spec/formtastic_spec.rb:419                       spec/formtastic_spec.rb:602
                                                                       spec/formtastic_spec.rb:608




Friday, 28 August 2009                                                                                                   40
So what did I do?




Friday, 28 August 2009                       41
move lines around

                         change similar code to be the same

                         changed in-line constants to variables




Friday, 28 August 2009                                            42
these are often non-trivial changes




Friday, 28 August 2009                                         43
very little change in overall file length

                                 (3013 => 2897 lines)




Friday, 28 August 2009                                              44
How did that change complexity?




Friday, 28 August 2009                                     45
37 => 37 Roodi problems

                         95 => 38 Flog problems




Friday, 28 August 2009                             46
Flog change indicates that methods have
                                     become simpler




Friday, 28 August 2009                                             47
Exacerbation




Friday, 28 August 2009                  48
Friday, 28 August 2009   49
What else exacerbates problems?




Friday, 28 August 2009                                     50
Long classes and methods




Friday, 28 August 2009                              51
http://farm4.static.flickr.com/3060/2426522019_7e696fb9af.jpg




Friday, 28 August 2009                                                                  52
Tools that detect long classes and methods are
                                        simple but useful




Friday, 28 August 2009                                                    53
Roodi
                              Ruby Object Oriented Design Inferometer
                         http://github.com/martinjandrews/roodi/tree/master




Friday, 28 August 2009                                                        54
General Purpose Code Quality




Friday, 28 August 2009                                  55
Roodi checks

       AssignmentInConditionalCheck      Check for an assignment inside a conditional. It‘s probably a mistaken equality comparison.

       CaseMissingElseCheck              Check that case statements have an else statement so that all cases are covered.

       ClassLineCountCheck               Check that the number of lines in a class is below the threshold.

       ClassNameCheck                    Check that class names match convention.

       CyclomaticComplexityBlockCheck    Check that the cyclomatic complexity of all blocks is below the threshold.

       CyclomaticComplexityMethodCheck   Check that the cyclomatic complexity of all methods is below the threshold.

       EmptyRescueBodyCheck              Check that there are no empty rescue blocks.

       ForLoopCheck                      Check that for loops aren‘t used (Use Enumerable.each instead)

       MethodLineCountCheck              Check that the number of lines in a method is below the threshold.

       MethodNameCheck                   Check that method names match convention.

       ModuleLineCountCheck              Check that the number of lines in a module is below the threshold.

       ModuleNameCheck                   Check that module names match convention.

       ParameterNumberCheck              Check that the number of parameters on a method is below the threshold.




Friday, 28 August 2009                                                                                                                 56
Roodi parameters

           AssignmentInConditionalCheck

           CaseMissingElseCheck

           ClassLineCountCheck               300

           ClassNameCheck                    pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/

           CyclomaticComplexityBlockCheck    4

           CyclomaticComplexityMethodCheck   8

           EmptyRescueBodyCheck

           ForLoopCheck

           MethodLineCountCheck              20

           MethodNameCheck                   pattern: !ruby/regexp /^[_a-z<>=[]|+-/*`]+[_a-z0-9_<>=~@[]]*[=!?]?$/

           ModuleLineCountCheck              300

           ModuleNameCheck                   pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/

           ParameterNumberCheck              5




Friday, 28 August 2009                                                                                                     57
lib/formtastic.rb:8      -   Module "Formtastic" has 1272 lines. It should have 300 or less.
          lib/formtastic.rb:10     -   Class "SemanticFormBuilder" has 1196 lines. It should have 300 or less.
          lib/formtastic.rb:742    -   Method "date_or_datetime_input" has 33 lines. It should have 20 or less.
          lib/formtastic.rb:835    -   Method "check_boxes_input" has 24 lines. It should have 20 or less.
          lib/formtastic.rb:1008   -   Method "default_input_type" has 24 lines. It should have 20 or less.
          lib/formtastic.rb:1046   -   Method "find_collection_for_column" has 27 lines. It should have 20 or less.
          lib/formtastic.rb:1180   -   Method "localized_attribute_string" has 24 lines. It should have 20 or less.
          lib/formtastic.rb:742    -   Method name "date_or_datetime_input" cyclomatic complexity is 10. It should be 8 or less.
          lib/formtastic.rb:1008   -   Method name "default_input_type" cyclomatic complexity is 19. It should be 8 or less.
          lib/formtastic.rb:1046   -   Method name "find_collection_for_column" cyclomatic complexity is 10. It should be 8 or less.
          lib/formtastic.rb:756    -   Block cyclomatic complexity is 5. It should be 4 or less.
          lib/formtastic.rb:1027   -   Found = in conditional. It should probably be an ==
          lib/formtastic.rb:1103   -   Found = in conditional. It should probably be an ==
          lib/formtastic.rb:1188   -   Rescue block should not be empty.
          lib/formtastic.rb:103    -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:378    -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:381    -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:427    -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:455    -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:883    -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:948    -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:950    -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:1027   -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:1080   -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:1128   -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:1130   -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:1176   -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:1184   -   Don't use class variables. You might want to try a different design.




Friday, 28 August 2009                                                                                                                 58
spec/formtastic_spec.rb:38 - Block cyclomatic complexity is 5. It should be 4 or less.
                         spec/formtastic_spec.rb:1728 - Block cyclomatic complexity is 5. It should be 4 or less.
                         spec/formtastic_spec.rb:1899 - Block cyclomatic complexity is 5. It should be 4 or less.
                         spec/formtastic_spec.rb:1900 - Block cyclomatic complexity is 5. It should be 4 or less.
                         spec/formtastic_spec.rb:2006 - Block cyclomatic complexity is 6. It should be 4 or less.
                         spec/formtastic_spec.rb:2300 - Block cyclomatic complexity is 9. It should be 4 or less.
                         spec/formtastic_spec.rb:2895 - Block cyclomatic complexity is 9. It should be 4 or less.
                         spec/formtastic_spec.rb:2897 - Block cyclomatic complexity is 14. It should be 4 or less.
                         spec/formtastic_spec.rb:109 - Case statement is missing an else clause.




Friday, 28 August 2009                                                                                               59
Let’s work through the spec first




Friday, 28 August 2009                                      60
spec/formtastic_spec.rb:38 - Block cyclomatic
                    complexity is 5. It should be 4 or less.




Friday, 28 August 2009                                              61
spec/formtastic_spec.rb:109 - Case statement
                    is missing an else clause.




Friday, 28 August 2009                                             62
Existing code



                         Post.stub!(:reflect_on_association).and_return do |column_name|
                           case column_name
                           when :author, :author_status
                             mock('reflection', :options => {},
                                                :klass => Author,
                                                :macro => :belongs_to)
                           when :authors
                             mock('reflection', :options => {},
                                                :klass => Author,
                                                :macro => :has_and_belongs_to_many)
                           end
                         end




Friday, 28 August 2009                                                                     63
New code

         def mock_post_association(column_name)
           return mock_association(Author, :belongs_to) if column_name.is_post_belongs_to?
           return mock_association(Author, :has_and_belongs_to_many) if
       column_name.is_post_habtm?
         end

          def mock_association(klass, multiplicity)
            mock('reflection', :options => {},
                               :klass => klass,
                               :macro => multiplicity)
          end
    ...
    Post.stub!(:reflect_on_association).and_return
                            { |column_name|mock_post_association(column_name) }




Friday, 28 August 2009                                                                       64
spec/formtastic_spec.rb:1744   -   Block   cyclomatic   complexity   is   5.    It should be 4 or less.
                         spec/formtastic_spec.rb:1915   -   Block   cyclomatic   complexity   is   5.    It should be 4 or less.
                         spec/formtastic_spec.rb:1916   -   Block   cyclomatic   complexity   is   5.    It should be 4 or less.
                         spec/formtastic_spec.rb:2022   -   Block   cyclomatic   complexity   is   6.    It should be 4 or less.
                         spec/formtastic_spec.rb:2316   -   Block   cyclomatic   complexity   is   9.    It should be 4 or less.
                         spec/formtastic_spec.rb:2911   -   Block   cyclomatic   complexity   is   9.    It should be 4 or less.
                         spec/formtastic_spec.rb:2913   -   Block   cyclomatic   complexity   is   14.    It should be 4 or less.




Friday, 28 August 2009                                                                                                              65
Not worth addressing these




Friday, 28 August 2009                                66
Back to the non-test code




Friday, 28 August 2009                               67
lib/formtastic.rb:8      -   Module "Formtastic" has 1272 lines. It should have 300 or less.
          lib/formtastic.rb:10     -   Class "SemanticFormBuilder" has 1196 lines. It should have 300 or less.
          lib/formtastic.rb:742    -   Method "date_or_datetime_input" has 33 lines. It should have 20 or less.
          lib/formtastic.rb:835    -   Method "check_boxes_input" has 24 lines. It should have 20 or less.
          lib/formtastic.rb:1008   -   Method "default_input_type" has 24 lines. It should have 20 or less.
          lib/formtastic.rb:1046   -   Method "find_collection_for_column" has 27 lines. It should have 20 or less.
          lib/formtastic.rb:1180   -   Method "localized_attribute_string" has 24 lines. It should have 20 or less.
          lib/formtastic.rb:742    -   Method name "date_or_datetime_input" cyclomatic complexity is 10. It should be 8 or less.
          lib/formtastic.rb:1008   -   Method name "default_input_type" cyclomatic complexity is 19. It should be 8 or less.
          lib/formtastic.rb:1046   -   Method name "find_collection_for_column" cyclomatic complexity is 10. It should be 8 or less.
          lib/formtastic.rb:756    -   Block cyclomatic complexity is 5. It should be 4 or less.
          lib/formtastic.rb:1027   -   Found = in conditional. It should probably be an ==
          lib/formtastic.rb:1103   -   Found = in conditional. It should probably be an ==
          lib/formtastic.rb:1188   -   Rescue block should not be empty.
          lib/formtastic.rb:103    -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:378    -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:381    -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:427    -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:455    -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:883    -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:948    -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:950    -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:1027   -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:1080   -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:1128   -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:1130   -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:1176   -   Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:1184   -   Don't use class variables. You might want to try a different design.




Friday, 28 August 2009                                                                                                                 68
(and now I make lots of code changes)




Friday, 28 August 2009                                           69
lib/formtastic.rb:115 - Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:390 - Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:393 - Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:439 - Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:467 - Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:926 - Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:991 - Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:993 - Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:1045 - Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:1126 - Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:1175 - Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:1177 - Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:1223 - Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:1240 - Don't use class variables. You might want to try a different design.
          lib/formtastic.rb:20 - Module "Formtastic" has 1311 lines. It should have 300 or less.
          lib/formtastic.rb:22 - Class "SemanticFormBuilder" has 1235 lines. It should have 300 or less.
          lib/formtastic.rb:1244 - Rescue block should not be empty.




Friday, 28 August 2009                                                                                     70
and I decide that’s enough for now




Friday, 28 August 2009                                        71
How does this change flog?




Friday, 28 August 2009                               72
Old and new flog warnings

          >88.1: SemanticFormBuilder#date_or_datetime_input         60.4: SemanticFormBuilder#inputs
           60.4: SemanticFormBuilder#inputs                         58.4: SemanticFormBuilder#input
           58.4: SemanticFormBuilder#input                          45.3: SemanticFormBuilder#database_column_input_type
          >57.7: SemanticFormBuilder#find_collection_for_column      43.3: SemanticFormBuilder#field_set_and_list_wrapping
          -56.9: SemanticFormBuilder#default_input_type             40.2: SemanticFormBuilder#radio_input
          >48.3: SemanticFormBuilder#localized_attribute_string     38.4: SemanticFormBuilder#localized_attribute_string
          -44.3: SemanticFormBuilder#check_boxes_input              31.4:
           43.3: SemanticFormBuilder#field_set_and_list_wrapping     SemanticFormBuilder#find_collection_for_column_explicit_or_asso
           40.2: SemanticFormBuilder#radio_input                    ciation_or_boolean
           31.2: SemanticFormBuilder#inputs_for_nested_attributes   31.2: SemanticFormBuilder#inputs_for_nested_attributes
           24.0: SemanticFormBuilder#label                          29.5: SemanticFormBuilder#datetime_content_tag
           22.7: SemanticFormBuilder#method_required?               28.1: SemanticFormBuilder#find_collection_for_column
           20.0: SemanticFormBuilder#none                           26.0: SemanticFormBuilder#single_list_item_content_from
                                                                    24.0: SemanticFormBuilder#label
                                                                    22.7: SemanticFormBuilder#method_required?
                                                                    20.2: SemanticFormBuilder#date_or_datetime_input
                                                                    20.0: SemanticFormBuilder#none




Friday, 28 August 2009                                                                                                               73
Changes

          >88.1: SemanticFormBuilder#date_or_datetime_input        45.3: SemanticFormBuilder#database_column_input_type
          >57.7: SemanticFormBuilder#find_collection_for_column     38.4: SemanticFormBuilder#localized_attribute_string
          -56.9: SemanticFormBuilder#default_input_type            31.4:
          >48.3: SemanticFormBuilder#localized_attribute_string   SemanticFormBuilder#find_collection_for_column_explicit_
          -44.3: SemanticFormBuilder#check_boxes_input            or_association_or_boolean
                                                                   29.5: SemanticFormBuilder#datetime_content_tag
                                                                   28.1: SemanticFormBuilder#find_collection_for_column
                                                                   26.0: SemanticFormBuilder#single_list_item_content_from
                                                                   20.2: SemanticFormBuilder#date_or_datetime_input




Friday, 28 August 2009                                                                                                       74
So what’s Flog?




Friday, 28 August 2009                     75
Confessions of a Ruby Sadist sudo gem install flog                                                14/08/09 3:34 AM




                                                       Ruby Sadist             Flog   Flay   Heckle   Kittens   About Us




                                     Confessions of a Ruby Sadist
                                                                     sudo gem install flog

                         Flog shows you the most
                         torturous code you wrote.
                         The more painful the code,
                         the higher the score. The
                         higher the score, the
                         harder it is to test.

                         Run it against your best
                         stuff. I double-dog dare you.
                                                                              So what’s Flog?
                         Flog essentially scores an
                         ABC metric: Assignments,
                         Branches, Calls, with
                         particular attention placed
                         on calls.

                         Run flog on all your code.
                         Try this:

                          find lib -name *.rb | xargs flog


                         Whatever is at the top of the
                         report is worth looking at.

                         This is how it works:



Friday, 28 August 2009                                                                                                                        76
Confessions of a Ruby Sadist sudo gem install flog                                                 14/08/09 3:34 AM




                                                                                           class Test
                          class Test
                                                                                             def blah           # 11.2 =
                            def blah
                                                                                               a = eval "1+1"   # 1.2 + 6.0 +
                              a = eval "1+1"
                                                                                               if a == 2 then   # 1.2 + 1.2 +
                              if a == 2 then                                  Is seen by
                                                                                           0.4 +
                                puts "yay"                                      flog as:         puts "yay"     # 1.2
                              end
                                                                                               end
                            end
                                                                                             end
                          end
                                                                                           end

                                                                                           Test#blah: (11.2)
                                                                                                6.0: eval
                                                                                                1.2: branch
                                                                          and reported          1.2: ==
                                                                              as:               1.2: puts
                                                                                                1.2: assignment
                                                                                                0.4: lit_fixnum




Friday, 28 August 2009                                                                                                                         77
Flog weights
       THRESHOLD = 0.60
       SCORES = Hash.new 1                                 # various "magic" usually used for "clever code"
       BRANCHING =                                         SCORES.merge!(:alias_method               => 2,
     [ :and, :case, :else, :if, :or, :rescue, :until,                    :extend                     => 2,
     :when, :while ]                                                     :include                    => 2,
                                                                         :instance_method            => 2,
        # various non-call constructs                                    :instance_methods           => 2,
        OTHER_SCORES = {                                                 :method_added               => 2,
          :alias          => 2,                                          :method_defined?            => 2,
          :assignment     => 1,                                          :method_removed             => 2,
          :block          => 1,                                          :method_undefined           => 2,
          :block_pass     => 1,                                          :private_class_method       => 2,
          :branch         => 1,                                          :private_instance_methods   => 2,
          :lit_fixnum     => 0.25,                                       :private_method_defined?    => 2,
          :sclass         => 5,                                          :protected_instance_methods => 2,
          :super          => 1,                                          :protected_method_defined? => 2,
          :to_proc_icky! => 10,                                          :public_class_method        => 2,
          :to_proc_normal => 5,                                          :public_instance_methods    => 2,
          :yield          => 1,                                          :public_method_defined?     => 2,
        }                                                                :remove_method              => 2,
                                                                         :send                       => 3,
        # eval forms                                                     :undef_method               => 2)
        SCORES.merge!(:define_method    =>   5,
                      :eval             =>   5,            # calls I don't like and usually see being
                      :module_eval      =>   5,          abused
                      :class_eval       =>   5,
                      :instance_eval    =>   5)            SCORES.merge!(:inject => 2)




Friday, 28 August 2009                                                                                        78
flog -d lib/formtastic.rb




Friday, 28 August 2009                              79
Flog details for worst method
                          60.4: SemanticFormBuilder#inputs
                              16.6: assignment
                              11.9: branch
                              11.5: to_proc_normal
                               5.8: block_pass
                               5.7: map
                               4.8: class
                               3.3: field_set_and_list_wrapping
                               2.3: content_columns
                               2.2: macro
                               2.1: reflections
                               2.0: ==
                               2.0: to_sym
                               1.9: compact!
                               1.9: +
                               1.9: -
                               1.8: empty?
                               1.8: input
                               1.5: block_given?
                               1.5: inputs_for_nested_attributes
                               1.4: extract_options!
                               1.4: []




Friday, 28 August 2009                                             80
Original code

           def inputs(*args, &block)
             html_options = args.extract_options!
             html_options[:class] ||= "inputs"

              if html_options[:for]
                inputs_for_nested_attributes(args, html_options, &block)
              elsif block_given?
                field_set_and_list_wrapping(html_options, &block)
              else
                if @object && args.empty?
                  args = @object.class.reflections.map { |n,_| n if _.macro == :belongs_to }
                  args += @object.class.content_columns.map(&:name)
                  args -= %w[created_at updated_at created_on updated_on lock_version]
                  args.compact!
                end
                contents = args.map { |method| input(method.to_sym) }

               field_set_and_list_wrapping(html_options, contents)
             end
           end




Friday, 28 August 2009                                                                         81
First change
           def inputs(*args, &block)
             html_options = args.extract_options!
             html_options[:class] ||= "inputs"

              if html_options[:for]
                inputs_for_nested_attributes(args, html_options, &block)
              elsif block_given?
                field_set_and_list_wrapping(html_options, &block)
              else
                if @object && args.empty?
                 args = build_default_inputs_args
               end
               contents = args.map { |method| input(method.to_sym) }
               field_set_and_list_wrapping(html_options, contents)
             end
           end


           def build_default_inputs_args()
             args = @object.class.reflections.map { |n,_| n if _.macro == :belongs_to }
             args += @object.class.content_columns.map(&:name)
             args -= %w[created_at updated_at created_on updated_on lock_version]
             args.compact!
           end



Friday, 28 August 2009                                                                    82
Flog details
                         29.8: SemanticFormBuilder#build_default_inputs_args
                              9.0: to_proc_normal
                              8.7: assignment
                              3.8: class
                              3.0: map
                              2.9: branch
                              1.8: block_pass
                              1.8: content_columns
                              1.7: macro
                              1.6: reflections
                              1.5: ==
                              1.4: compact!
                              1.4: -
                              1.4: +

                         24.1: SemanticFormBuilder#inputs
                              8.0: branch
                              6.7: assignment
                              3.5: block_pass
                              3.3: field_set_and_list_wrapping
                              2.0: to_sym
                              1.8: empty?
                              1.8: build_default_inputs_args
                              1.8: input
                              1.7: map
                              1.5: inputs_for_nested_attributes
                              1.5: block_given?
                              1.4: extract_options!
                              1.4: []


Friday, 28 August 2009                                                         83
Next change
           def inputs(*args, &block)
             html_options = args.extract_options!
             html_options[:class] ||= "inputs"

              if html_options[:for]
                inputs_for_nested_attributes(args, html_options, &block)
              elsif block_given?
                field_set_and_list_wrapping(html_options, &block)
              else
               contents = inputs_contents(args)
               field_set_and_list_wrapping(html_options, contents)
             end
           end


           def inputs_contents(args)
             if @object && args.empty?
               args = build_default_inputs_args
             end
             return args.map { |method| input(method.to_sym) }
           end

           def build_default_inputs_args()
             args = @object.class.reflections.map { |n,_| n if _.macro == :belongs_to }
             args += @object.class.content_columns.map(&:name)
             args -= %w[created_at updated_at created_on updated_on lock_version]
             args.compact!
           end

Friday, 28 August 2009                                                                    84
Flog details - only one significant method


                            29.8: SemanticFormBuilder#build_default_inputs_args
                                 9.0: to_proc_normal
                                 8.7: assignment
                                 3.8: class
                                 3.0: map
                                 2.9: branch
                                 1.8: block_pass
                                 1.8: content_columns
                                 1.7: macro
                                 1.6: reflections
                                 1.5: ==
                                 1.4: compact!
                                 1.4: -
                                 1.4: +




Friday, 28 August 2009                                                            85
Inline to_proc




           def build_default_inputs_args()
             args = @object.class.reflections.map { |n,_| n if _.macro == :belongs_to }
             args += @object.class.content_columns.map {|c| c.name}
             args -= %w[created_at updated_at created_on updated_on lock_version]
             args.compact!
           end




Friday, 28 August 2009                                                                    86
Flog details


                         22.4: SemanticFormBuilder#build_default_inputs_args
                             10.4: assignment
                              4.5: branch
                              3.8: class
                              3.0: map
                              1.8: content_columns
                              1.7: name
                              1.7: macro
                              1.6: reflections
                              1.5: ==
                              1.4: compact!
                              1.4: -




Friday, 28 August 2009                                                         87
Extract method


           def build_default_inputs_args()
             args = @object.class.reflections.map { |n,_| n if _.macro == :belongs_to }
             args += content_column_names
             args -= %w[created_at updated_at created_on updated_on lock_version]
             args.compact!
           end


           def content_column_names
             return @object.class.content_columns.map {|c| c.name}
           end




Friday, 28 August 2009                                                                    88
Flog details


                         16.6: SemanticFormBuilder#build_default_inputs_args
                              8.7: assignment
                              2.9: branch
                              1.8: class
                              1.7: macro
                              1.6: content_column_names
                              1.6: reflections
                              1.5: ==
                              1.4: compact!
                              1.4: map
                              1.4: -
                              1.4: +




Friday, 28 August 2009                                                         89
and so forth...




Friday, 28 August 2009                     90
Other Ruby code quality tools




Friday, 28 August 2009                                   91
Code churn metric




Friday, 28 August 2009                       92
Saikuro : A Cyclomatic Complexity Analyzer                                                        14/08/09 5:05 AM




                         Saikuro
                         A Cyclomatic Complexity Analyzer
                                                                                                                   Download Saikuro




                                           Saikuro is a Ruby cyclomatic complexity analyzer. When given
                                           Ruby source code Saikuro will generate a report listing the
                                           cyclomatic complexity of each method found. In addition,
                                           Saikuro counts the number of lines per method and can
                                           generate a listing of the number of tokens on each line of code.

                                           Version:
                                              0.2


                                           License
                                              Saikuro uses the BSD license.


                                           Example Output
                                              Here are examples of the output generated by Saikuro.
                                                  Cyclomatic complexity summary page
                                                  Token count summary page


                                           Installation
                                              As root run:
                                               # ruby setup.rb all


                                           Usage
                                              Saikuro is a command line program. Running "saikuro.rb -h" will
                                              output a usage statement describing all the various arguments
                                              you can pass to it.
                                               "saikuro -c -p tests/samples.rb"
                                              The above command is a simple example that generates a
                                              cyclomatic complexity report on the samples.rb file, using the
                                              default filter, warning and error settings. The report is saved in
                                              the current directory.
                                              A more detailed example is :
Friday, 28 August 2009                         "saikuro -c -t -i tests -y 0 -w 11 -e 16 -o out/"                                              93
reek, a code smells detector for ruby « silk and spinach                                              14/08/09 5:06 AM




                          silk and spinach
                          development, by example

                          reek, a code smells detector for ruby
                          with 23 comments

                          To complement the imminent (ie. sometime next year) publication of the Ruby Refactoring Workbook
                          I’ve been working on a little software tool called ‘reek’. Reek scans ruby code — either source files or
                          in-memory Class objects — looking for some of the code smells discussed in the book. Right now it can
                          detect (certain forms of):

                                   Long Method
                                   Large Class
                                   Feature Envy
                                   Uncommunicative Name
                                   Long Parameter List
                                   Utility Function
                                   Nested Iterators

                          As time goes by I’ll be adding checks for more smells, and I hope to make the current checks a bit more
                          sophisticated. But in the agile spirit of going ugly early, the current very early version is available for
                          you to experiment with. To get the tool:
                          gem install reek

                          To run it:
                          reek file1.rb file2.rb ...

                          If you try it, please let me know what you think and what you’d like the next version to do!

                          You can browse the reek project’s code repository at http://github.com/kevinrutherford/reek/tree/master
                          or http://rubyforge.org/projects/reek/, both of which are clones of the same Git repository.
Friday, 28 August 2009                                                                                                                            94
RCov - Ruby C0 Code Coverage                                       15/08/09 12:11 PM




                          RCov
                          RCov - Ruby C0 Code Coverage

                                  Source

                          Install
                          $ gem install relevance-rcov


                          Usage
                          See the README on GitHub for the most-up to date usage of RCov.

                          Maintained by Relevance




Friday, 28 August 2009                                                                                          95
metric fu




Friday, 28 August 2009               96
rake metrics:all




Friday, 28 August 2009                      97
results at
                         file:///Users/stevehayes/projects/third-party/
                         formtastic/tmp/metric_fu/output/index.html




Friday, 28 August 2009                                                   98
Java time




Friday, 28 August 2009               99
Example code is from Apache
                          Commons Collections 3.2.1




Friday, 28 August 2009                                 100
Simian for duplication detection




Friday, 28 August 2009                                      101
java -jar simian-2.2.24.jar src/**/*.java




Friday, 28 August 2009                                           102
Found 11527 duplicate lines in 871 blocks in 239 files

                     Processed a total of 41324 significant (109875 raw)
                     lines in 467 files

                     Processing time: 2.404sec




Friday, 28 August 2009                                                       103
27.9% of the code is duplicated




Friday, 28 August 2009                                     104
Simian can also be language
                                  sensitive




Friday, 28 August 2009                                 105
java -jar simian-2.2.24.jar
                             -language=java src/**/*.java




Friday, 28 August 2009                                      106
PMD for duplication detection




Friday, 28 August 2009                                   107
Android Rules: These rules deal with the Android SDK, mostly related to best practices. To get better results, make sure
                    that the auxclasspath is defined for type resolution to work.
               •    Basic JSF rules: Rules concerning basic JSF guidelines.
               •    Basic JSP rules: Rules concerning basic JSP guidelines.
               •    Basic Rules: The Basic Ruleset contains a collection of good practices which everyone should follow.
               •    Braces Rules: The Braces Ruleset contains a collection of braces rules.
               •    Clone Implementation Rules: The Clone Implementation ruleset contains a collection of rules that find questionable usages
                    of the clone() method.
               •    Code Size Rules: The Code Size Ruleset contains a collection of rules that find code size related problems.
               •    Controversial Rules: The Controversial Ruleset contains rules that, for whatever reason, are considered controversial. They
                    are separated out here to allow people to include as they see fit via custom rulesets. This ruleset was initially created in
                    response to discussions over UnnecessaryConstructorRule which Tom likes but most people really dislike :-)
               •    Coupling Rules: These are rules which find instances of high or inappropriate coupling between objects and packages.
               •    Design Rules: The Design Ruleset contains a collection of rules that find questionable designs.
               •    Finalizer Rules: These rules deal with different problems that can occur with finalizers.
               •    Import Statement Rules: These rules deal with different problems that can occur with a class' import statements.
               •    J2EE Rules: These are rules for J2EE
               •    JavaBean Rules: The JavaBeans Ruleset catches instances of bean rules not being followed.
               •    JUnit Rules: These rules deal with different problems that can occur with JUnit tests.
               •    Jakarta Commons Logging Rules: The Jakarta Commons Logging ruleset contains a collection of rules that find questionable
                    usages of that framework.
               •    Java Logging Rules: The Java Logging ruleset contains a collection of rules that find questionable usages of the logger.
               •    Migration Rules: Contains rules about migrating from one JDK version to another. Don't use these rules directly, rather, use
                    a wrapper ruleset such as migrating_to_13.xml.
               •    Migration13: Contains rules for migrating to JDK 1.3
               •    Migration14: Contains rules for migrating to JDK 1.4
               •    Migration15: Contains rules for migrating to JDK 1.5
               •    MigratingToJava4: Contains rules for migrating to JDK 1.5
               •    Naming Rules: The Naming Ruleset contains a collection of rules about names - too long, too short, and so forth.
               •    Optimization Rules: These rules deal with different optimizations that generally apply to performance best practices.
               •    Strict Exception Rules: These rules provide some strict guidelines about throwing and catching exceptions.
               •    String and StringBuffer Rules: These rules deal with different problems that can occur with manipulation of the class String
                    or StringBuffer.
               •    Security Code Guidelines: These rules check the security guidelines from Sun, published at http://java.sun.com/security/
                    seccodeguide.html#gcg
               •    Type Resolution Rules: These are rules which resolve java Class files for comparisson, as opposed to a String




Friday, 28 August 2009                                                                                                                             108
Basic Rules: The Basic Ruleset contains a collection of good practices which everyone should follow.
               •    Braces Rules: The Braces Ruleset contains a collection of braces rules.
               •    Clone Implementation Rules: The Clone Implementation ruleset contains a collection of rules that find questionable usages
                    of the clone() method.
               •    Code Size Rules: The Code Size Ruleset contains a collection of rules that find code size related problems.
               •    Coupling Rules: These are rules which find instances of high or inappropriate coupling between objects and packages.
               •    Design Rules: The Design Ruleset contains a collection of rules that find questionable designs.
               •    Import Statement Rules: These rules deal with different problems that can occur with a class' import statements.
               •    JUnit Rules: These rules deal with different problems that can occur with JUnit tests.
               •    Naming Rules: The Naming Ruleset contains a collection of rules about names - too long, too short, and so forth.
               •    Optimization Rules: These rules deal with different optimizations that generally apply to performance best practices.
               •    Strict Exception Rules: These rules provide some strict guidelines about throwing and catching exceptions.
               •    String and StringBuffer Rules: These rules deal with different problems that can occur with manipulation of the class String
                    or StringBuffer.
               •    Type Resolution Rules: These are rules which resolve java Class files for comparisson, as opposed to a String
               •    Unused Code Rules: The Unused Code Ruleset contains a collection of rules that find unused code.




Friday, 28 August 2009                                                                                                                             109
Basic Rules
             •       Empty catch block                   •   Unnecessary final modifier
             •       Empty if Statement                  •   Collapsible if statements
             •       Empty while statement               •   Useless overriding method
             •       Empty try block                     •   Class cast exception with toArray
             •       Empty finally block                  •   Avoid decimal literals in BigDecimal
             •       Empty switch statements                 constructor
             •       Jumbled incrementer                 •   Useless operation on immutable
             •       For loop should be while loop       •   Misplaced null check
             •       Unnecessary conversion temporary    •   Unused null check in equals
             •       Override both equals and hashcode   •   Avoid thread group
             •       Double checked locking              •   Broken null check
             •       Return from finally block            •   BigInteger instantiation
             •       Empty synchronized block            •   Avoid using octal values
             •       Unnecessary return                  •   Avoid using hardcoded IP
             •       Empty static initializer            •   Check result set
             •       Unconditional if statement          •   Avoid multiple unary operators
             •       Empty statement not in loop         •   Empty initializer
             •       Boolean instantiation



Friday, 28 August 2009                                                                              110
Basic Rules - 725
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BeanMap.java:308
        Overriding method merely calls super
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ExtendedProperties.java:410
 Overriding method merely calls super
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ExtendedProperties.java:476
 Avoid empty catch blocks
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ExtendedProperties.java:536
 Avoid empty catch blocks
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ExtendedProperties.java:616
 These nested if statements could be combined
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ExtendedProperties.java:1157
 Avoid instantiating Boolean objects; reference
    Boolean.TRUE or Boolean.FALSE or call Boolean.valueOf() instead.
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ExtendedProperties.java:1179
 Avoid instantiating Boolean objects; reference
    Boolean.TRUE or Boolean.FALSE or call Boolean.valueOf() instead.
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/IteratorUtils.java:907
 Avoid empty catch blocks
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/LRUMap.java:120
         These nested if statements could be combined
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/MapUtils.java:170
       Avoid instantiating Boolean objects; reference Boolean.TRUE or
    Boolean.FALSE or call Boolean.valueOf() instead.
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/MultiHashMap.java:138
             Avoid empty catch blocks
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:598
             Avoid empty while statements
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:936
             Ensure you override both equals() and hashCode()
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:952
             Ensure you override both equals() and hashCode()
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/StaticBucketMap.java:159
          Unnecessary final modifier in final class
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/StaticBucketMap.java:393
          Unnecessary final modifier in final class
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/StaticBucketMap.java:401
          Unnecessary final modifier in final class
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/StaticBucketMap.java:416
          Unnecessary final modifier in final class
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/StaticBucketMap.java:431
          Unnecessary final modifier in final class
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/functors/PrototypeFactory.java:195
        Avoid empty catch blocks
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/functors/PrototypeFactory.java:202
        Avoid empty catch blocks
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/iterators/FilterIterator.java:108
These nested if statements could be combined
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/iterators/FilterListIterator.java:140
     These nested if statements could be combined
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/iterators/FilterListIterator.java:156
     These nested if statements could be combined
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/iterators/ObjectGraphIterator.java:141
 Avoid empty if statements
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/iterators/ObjectGraphIterator.java:193
 Avoid empty if statements
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/iterators/ObjectGraphIterator.java:195
 Avoid empty if statements
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/list/CursorableLinkedList.java:428
        Avoid empty if statements
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/AbstractReferenceMap.java:278
 Avoid empty while statements
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/AbstractReferenceMap.java:889
 Ensure you override both equals() and hashCode()
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/AbstractReferenceMap.java:906
 Ensure you override both equals() and hashCode()
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/CaseInsensitiveMap.java:133
           Overriding method merely calls super
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/HashedMap.java:96
             Overriding method merely calls super
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/IdentityMap.java:175
          Overriding method merely calls super
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/LRUMap.java:395
Overriding method merely calls super
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/LinkedMap.java:117
            Overriding method merely calls super
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/StaticBucketMap.java:160
 Unnecessary final modifier in final class



Friday, 28 August 2009                                                                                                                                                                111
Braces Rules


                         •   If statements must use braces
                         •   While loops must use braces
                         •   If else statements must use braces
                         •   For loops must use braces




Friday, 28 August 2009                                            112
Braces Rules - 210
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BeanMap.java:268
      Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BeanMap.java:600
      Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BinaryHeap.java:476
 Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BoundedFifoBuffer.java:272
 Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BoundedFifoBuffer.java:280
 Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:370
Avoid using if...else statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:371
Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:382
Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:393
Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:876
Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:894
Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:912
Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:987
Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:1012
       Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:1029
       Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:1063
       Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastHashMap.java:592
Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastTreeMap.java:700
 Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/LRUMap.java:92
        Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:289
         Avoid using while statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:378
         Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:464
         Avoid using if...else statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:465
         Avoid using if...else statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:506
         Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:520
         Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:537
         Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:538
         Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:541
         Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:571
         Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:579
         Avoid using if...else statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:580
         Avoid using if...else statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:598
         Avoid using while statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:621
         Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:622
         Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:665
         Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:711
         Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:771
         Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:778
         Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:779
         Avoid using if statements without curly braces
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:780
         Avoid using if statements without curly braces



Friday, 28 August 2009                                                                                                                                                             113
Clone Rules

             • Proper clone implementation (should include super.clone())
             • Clone throws CloneNotSupportedException
             • Clone method must implement cloneable




Friday, 28 August 2009                                                      114
Clone Rules - 25
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:281
Object clone() should be implemented with super.clone()
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:281
clone() method should be implemented only if implementing
    Cloneable interface
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:281
clone() method should throw CloneNotSupportedException
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastHashMap.java:419
Object clone() should be implemented with super.clone()
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastHashMap.java:419
clone() method should be implemented only if implementing
    Cloneable interface
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastHashMap.java:419
clone() method should throw CloneNotSupportedException
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastTreeMap.java:470
 Object clone() should be implemented with super.clone()
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastTreeMap.java:470
 clone() method should be implemented only if implementing
    Cloneable interface
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastTreeMap.java:470
 clone() method should throw CloneNotSupportedException
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/MultiHashMap.java:464
          clone() method should be implemented only if implementing
    Cloneable interface
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/MultiHashMap.java:464
          clone() method should throw
    CloneNotSupportedException
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/AbstractHashedMap.java:1227
         clone() method should be implemented only if
    implementing Cloneable interface
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/AbstractHashedMap.java:1227
         clone() method should throw
    CloneNotSupportedException
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/CaseInsensitiveMap.java:133
         clone() method should throw
    CloneNotSupportedException
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/Flat3Map.java:1014
         clone() method should throw
    CloneNotSupportedException
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/HashedMap.java:96
          clone() method should throw
    CloneNotSupportedException
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/IdentityMap.java:175
       clone() method should throw
    CloneNotSupportedException
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/LRUMap.java:395
clone() method should throw CloneNotSupportedException
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/LinkedMap.java:117
         clone() method should throw
    CloneNotSupportedException
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/MultiKeyMap.java:818
       Object clone() should be implemented with super.clone()
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/MultiKeyMap.java:818
       clone() method should be implemented only if implementing
    Cloneable interface
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/MultiKeyMap.java:818
       clone() method should throw
    CloneNotSupportedException
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/SingletonMap.java:538
      clone() method should throw
    CloneNotSupportedException
    /Users/stevehayes/commons-collections-3.2.1-src/src/test/org/apache/commons/collections/BulkTest.java:177
     clone() method should throw CloneNotSupportedException




Friday, 28 August 2009                                                                                                                                                                  115
Code Size Rules

                         •   NPath complexity (200)
                         •   Excessive method length (100)
                         •   Excessive parameter list (10)
                         •   Excessive class length (1000)
                         •   Cyclomatic complexity (10)
                         •   Excessive public count (45)
                         •   Too many fields (15)
                         •   NCSS method count (100)
                         •   NCSS type count (1500)
                         •   NCSS constructor count (100)
                         •   Too many methods (10)


Friday, 28 August 2009                                       116
Code Size Rules - 338
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BeanMap.java:55
       This class has too many methods, consider refactoring it.
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BinaryHeap.java:63
 The class 'BinaryHeap' has a Cyclomatic Complexity of 2 (Highest =
    14).
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BinaryHeap.java:64
 This class has too many methods, consider refactoring it.
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BinaryHeap.java:465
 The method 'iterator' has a Cyclomatic Complexity of 14.
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BinaryHeap.java:482
 The method 'remove' has a Cyclomatic Complexity of 10.
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BoundedFifoBuffer.java:56
       This class has too many methods, consider refactoring it.
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ClosureUtils.java:57
 This class has too many methods, consider refactoring it.
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CollectionUtils.java:17
 his class has a bunch of public methods and attributes
                                                                                                                   T
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CollectionUtils.java:58
 void really long classes.
                                                                                                                   A
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CollectionUtils.java:58
 he class 'CollectionUtils' has a Cyclomatic Complexity of 3
                                                                                                                   T
    (Highest = 14).
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CollectionUtils.java:58
 his class has too many methods, consider refactoring it.
                                                                                                                   T
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CollectionUtils.java:741
        The method 'index' has a Cyclomatic Complexity of 13.
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CollectionUtils.java:829
        The method 'get' has a Cyclomatic Complexity of 14.
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CollectionUtils.java:894
        The method 'size' has a Cyclomatic Complexity of 10.
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ComparatorUtils.java:44
         This class has too many methods, consider refactoring it.
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CursorableLinkedList.java:17
 This class has a bunch of public methods and attributes
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CursorableLinkedList.java:55
 Avoid really long classes.
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CursorableLinkedList.java:55
 This class has too many methods, consider refactoring it.
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CursorableLinkedList.java:1202
 his class has too many methods, consider refactoring it.
                                                                                                                             T
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CursorableLinkedList.java:1405
 he method insertListable() has an NPath complexity of
                                                                                                                             T
    200
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/DefaultMapBag.java:48
 his class has too many methods, consider refactoring it.
                                                                                                                   T
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/DoubleOrderedMap.java:17
 This class has a bunch of public methods and attributes
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/DoubleOrderedMap.java:107
 Avoid really long classes.
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/DoubleOrderedMap.java:107
 The class 'DoubleOrderedMap' has a Cyclomatic
    Complexity of 4 (Highest = 15).
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/DoubleOrderedMap.java:107
 This class has too many methods, consider refactoring it.
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/DoubleOrderedMap.java:202
 The method 'entrySetByValue' has a Cyclomatic Complexity
    of 12.
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/DoubleOrderedMap.java:341
 The method 'valuesByValue' has a Cyclomatic Complexity
    of 11.
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/DoubleOrderedMap.java:804
 The method 'doRedBlackInsert' has a Cyclomatic
    Complexity of 11.
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/DoubleOrderedMap.java:875
 The method 'doRedBlackDelete' has a Cyclomatic
    Complexity of 13.
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/DoubleOrderedMap.java:952
 The method 'doRedBlackDeleteFixup' has a Cyclomatic
    Complexity of 12.
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/DoubleOrderedMap.java:1044
 The method 'swapPosition' has a Cyclomatic Complexity of



Friday, 28 August 2009                                                                                                                                                                   117
Coupling Rules


             • Coupling between objects (attributes, local variables,
                     return types) (20)
             •       Excessive imports (30)
             •       Loose coupling (avoid using implementation types, use
                     interface instead)




Friday, 28 August 2009                                                       118
Coupling Rules - 63
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BeanMap.java:59
        Avoid using implementation types like 'HashMap'; use the interface
    instead
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BeanMap.java:60
        Avoid using implementation types like 'HashMap'; use the interface
    instead
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BeanMap.java:61
        Avoid using implementation types like 'HashMap'; use the interface
    instead
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BeanMap.java:72
        Avoid using implementation types like 'HashMap'; use the interface
    instead
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ExtendedProperties.java:187
 Avoid using implementation types like 'ArrayList'; use the
    interface instead
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ExtendedProperties.java:1037
 Avoid using implementation types like 'Vector'; use the
    interface instead
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ExtendedProperties.java:1053
 Avoid using implementation types like 'Vector'; use the
    interface instead
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ExtendedProperties.java:1053
 Avoid using implementation types like 'Vector'; use the
    interface instead
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:117
Avoid using implementation types like 'ArrayList'; use the interface
    instead
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastHashMap.java:71
 Avoid using implementation types like 'HashMap'; use the interface
    instead
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastTreeMap.java:73
 Avoid using implementation types like 'TreeMap'; use the interface
    instead
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/IteratorUtils.java:17
 A high number of imports can indicate a high degree of coupling
    within an object.
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/SequencedHashMap.java:154
 Avoid using implementation types like 'HashMap'; use the
    interface instead
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/StaticBucketMap.java:508
        Avoid using implementation types like 'ArrayList'; use the
    interface instead
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/iterators/CollatingIterator.java:49
     Avoid using implementation types like 'ArrayList';
    use the interface instead
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/iterators/CollatingIterator.java:52
     Avoid using implementation types like 'ArrayList';
    use the interface instead
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/iterators/CollatingIterator.java:361
    Avoid using implementation types like 'ArrayList';
    use the interface instead
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/MultiValueMap.java:78
       Avoid using implementation types like 'ArrayList'; use the
    interface instead
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/MultiValueMap.java:109
 Avoid using implementation types like 'ArrayList'; use the
    interface instead
    /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/StaticBucketMap.java:499
 Avoid using implementation types like 'ArrayList'; use the
    interface instead



Friday, 28 August 2009                                                                                                                                                                    119
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java
Code Quality in Ruby and Java

More Related Content

What's hot

Chapter 4 - Performance Testing Tasks
Chapter 4 - Performance Testing TasksChapter 4 - Performance Testing Tasks
Chapter 4 - Performance Testing TasksNeeraj Kumar Singh
 
Introduction to Robot Framework (external)
Introduction to Robot Framework (external)Introduction to Robot Framework (external)
Introduction to Robot Framework (external)Zhe Li
 
Introducing Playwright's New Test Runner
Introducing Playwright's New Test RunnerIntroducing Playwright's New Test Runner
Introducing Playwright's New Test RunnerApplitools
 
The story of SonarQube told to a DevOps Engineer
The story of SonarQube told to a DevOps EngineerThe story of SonarQube told to a DevOps Engineer
The story of SonarQube told to a DevOps EngineerManu Pk
 
Code Review Best Practices
Code Review Best PracticesCode Review Best Practices
Code Review Best PracticesTrisha Gee
 
Automated Testing with Agile
Automated Testing with AgileAutomated Testing with Agile
Automated Testing with AgileKen McCorkell
 
Test-Driven Development
Test-Driven DevelopmentTest-Driven Development
Test-Driven DevelopmentJohn Blum
 
What is Jenkins | Jenkins Tutorial for Beginners | Edureka
What is Jenkins | Jenkins Tutorial for Beginners | EdurekaWhat is Jenkins | Jenkins Tutorial for Beginners | Edureka
What is Jenkins | Jenkins Tutorial for Beginners | EdurekaEdureka!
 
API Testing: The heart of functional testing" with Bj Rollison
API Testing: The heart of functional testing" with Bj RollisonAPI Testing: The heart of functional testing" with Bj Rollison
API Testing: The heart of functional testing" with Bj RollisonTEST Huddle
 
Introduction to K6
Introduction to K6Introduction to K6
Introduction to K6Knoldus Inc.
 
An introduction to unit testing
An introduction to unit testingAn introduction to unit testing
An introduction to unit testingAdam Stephensen
 
An Introduction To Jenkins
An Introduction To JenkinsAn Introduction To Jenkins
An Introduction To JenkinsKnoldus Inc.
 

What's hot (20)

Api testing
Api testingApi testing
Api testing
 
Chapter 4 - Performance Testing Tasks
Chapter 4 - Performance Testing TasksChapter 4 - Performance Testing Tasks
Chapter 4 - Performance Testing Tasks
 
Introduction to Robot Framework (external)
Introduction to Robot Framework (external)Introduction to Robot Framework (external)
Introduction to Robot Framework (external)
 
Introducing Playwright's New Test Runner
Introducing Playwright's New Test RunnerIntroducing Playwright's New Test Runner
Introducing Playwright's New Test Runner
 
Test automation process
Test automation processTest automation process
Test automation process
 
Introduction to CI/CD
Introduction to CI/CDIntroduction to CI/CD
Introduction to CI/CD
 
The story of SonarQube told to a DevOps Engineer
The story of SonarQube told to a DevOps EngineerThe story of SonarQube told to a DevOps Engineer
The story of SonarQube told to a DevOps Engineer
 
Jenkins presentation
Jenkins presentationJenkins presentation
Jenkins presentation
 
Cypress Automation
Cypress  AutomationCypress  Automation
Cypress Automation
 
Selenium Automation Framework
Selenium Automation  FrameworkSelenium Automation  Framework
Selenium Automation Framework
 
Code Review Best Practices
Code Review Best PracticesCode Review Best Practices
Code Review Best Practices
 
Automated Testing with Agile
Automated Testing with AgileAutomated Testing with Agile
Automated Testing with Agile
 
"DevOps > CI+CD "
"DevOps > CI+CD ""DevOps > CI+CD "
"DevOps > CI+CD "
 
Test-Driven Development
Test-Driven DevelopmentTest-Driven Development
Test-Driven Development
 
API Testing
API TestingAPI Testing
API Testing
 
What is Jenkins | Jenkins Tutorial for Beginners | Edureka
What is Jenkins | Jenkins Tutorial for Beginners | EdurekaWhat is Jenkins | Jenkins Tutorial for Beginners | Edureka
What is Jenkins | Jenkins Tutorial for Beginners | Edureka
 
API Testing: The heart of functional testing" with Bj Rollison
API Testing: The heart of functional testing" with Bj RollisonAPI Testing: The heart of functional testing" with Bj Rollison
API Testing: The heart of functional testing" with Bj Rollison
 
Introduction to K6
Introduction to K6Introduction to K6
Introduction to K6
 
An introduction to unit testing
An introduction to unit testingAn introduction to unit testing
An introduction to unit testing
 
An Introduction To Jenkins
An Introduction To JenkinsAn Introduction To Jenkins
An Introduction To Jenkins
 

Similar to Code Quality in Ruby and Java

iPhone Development Overview
iPhone Development OverviewiPhone Development Overview
iPhone Development OverviewTom Adams
 
Content Management Selection and Strategy
Content Management Selection and StrategyContent Management Selection and Strategy
Content Management Selection and StrategyIvo Jansch
 
Ibuildings Cms Talk
Ibuildings Cms TalkIbuildings Cms Talk
Ibuildings Cms Talkdean1985
 
Holistic slides lightning_testing_bof
Holistic slides lightning_testing_bofHolistic slides lightning_testing_bof
Holistic slides lightning_testing_bofTerry Peppers
 
Artromick Choosing And Implementing A Mobile Hospital Cart Solution
Artromick Choosing And Implementing A Mobile Hospital Cart SolutionArtromick Choosing And Implementing A Mobile Hospital Cart Solution
Artromick Choosing And Implementing A Mobile Hospital Cart SolutionArtromick
 
Aegis Global Media Seville09 Final
Aegis Global Media Seville09 FinalAegis Global Media Seville09 Final
Aegis Global Media Seville09 FinalRicardo Salema
 
It's the Customer, Not the Container
It's the Customer, Not the ContainerIt's the Customer, Not the Container
It's the Customer, Not the Containerjohn wilbanks
 
Accelerate Your Rails Site with Automatic Generation-Based Action Caching
Accelerate Your Rails Site with Automatic Generation-Based Action CachingAccelerate Your Rails Site with Automatic Generation-Based Action Caching
Accelerate Your Rails Site with Automatic Generation-Based Action Cachingelliando dias
 
Rhouse - Home automation is ruby ?
Rhouse - Home automation is ruby ?Rhouse - Home automation is ruby ?
Rhouse - Home automation is ruby ?Fernand Galiana
 
IT Depends: Custom vs Packaged Software
IT Depends: Custom vs Packaged SoftwareIT Depends: Custom vs Packaged Software
IT Depends: Custom vs Packaged Software★ Selcuk Atli
 
Wave Presentation
Wave PresentationWave Presentation
Wave Presentationbedney
 
intl me this, intl me that
intl me this, intl me thatintl me this, intl me that
intl me this, intl me thatAndrei Zmievski
 
MATI 2009 Conference: CAT Tools
MATI 2009 Conference: CAT ToolsMATI 2009 Conference: CAT Tools
MATI 2009 Conference: CAT ToolsDierk Seeburg
 
Smalltalk Metaprogramming supports Probabilistic Program Analysis
Smalltalk Metaprogramming supports Probabilistic Program AnalysisSmalltalk Metaprogramming supports Probabilistic Program Analysis
Smalltalk Metaprogramming supports Probabilistic Program AnalysisESUG
 
eZ critical architectures
eZ critical architectureseZ critical architectures
eZ critical architecturesDamien Seguy
 
Measuring Online Influence: The Art of Making Noise Without Being Noisy
Measuring Online Influence: The Art of Making Noise Without Being NoisyMeasuring Online Influence: The Art of Making Noise Without Being Noisy
Measuring Online Influence: The Art of Making Noise Without Being NoisyMicah Baldwin
 
Testing Android
Testing AndroidTesting Android
Testing AndroidMarc Chung
 

Similar to Code Quality in Ruby and Java (20)

iPhone Development Overview
iPhone Development OverviewiPhone Development Overview
iPhone Development Overview
 
Content Management Selection and Strategy
Content Management Selection and StrategyContent Management Selection and Strategy
Content Management Selection and Strategy
 
Ibuildings Cms Talk
Ibuildings Cms TalkIbuildings Cms Talk
Ibuildings Cms Talk
 
Holistic slides lightning_testing_bof
Holistic slides lightning_testing_bofHolistic slides lightning_testing_bof
Holistic slides lightning_testing_bof
 
Artromick Choosing And Implementing A Mobile Hospital Cart Solution
Artromick Choosing And Implementing A Mobile Hospital Cart SolutionArtromick Choosing And Implementing A Mobile Hospital Cart Solution
Artromick Choosing And Implementing A Mobile Hospital Cart Solution
 
Orchestra
OrchestraOrchestra
Orchestra
 
Aegis Global Media Seville09 Final
Aegis Global Media Seville09 FinalAegis Global Media Seville09 Final
Aegis Global Media Seville09 Final
 
It's the Customer, Not the Container
It's the Customer, Not the ContainerIt's the Customer, Not the Container
It's the Customer, Not the Container
 
Accelerate Your Rails Site with Automatic Generation-Based Action Caching
Accelerate Your Rails Site with Automatic Generation-Based Action CachingAccelerate Your Rails Site with Automatic Generation-Based Action Caching
Accelerate Your Rails Site with Automatic Generation-Based Action Caching
 
Rhouse - Home automation is ruby ?
Rhouse - Home automation is ruby ?Rhouse - Home automation is ruby ?
Rhouse - Home automation is ruby ?
 
IT Depends: Custom vs Packaged Software
IT Depends: Custom vs Packaged SoftwareIT Depends: Custom vs Packaged Software
IT Depends: Custom vs Packaged Software
 
Wave Presentation
Wave PresentationWave Presentation
Wave Presentation
 
intl me this, intl me that
intl me this, intl me thatintl me this, intl me that
intl me this, intl me that
 
Professionalism
ProfessionalismProfessionalism
Professionalism
 
MATI 2009 Conference: CAT Tools
MATI 2009 Conference: CAT ToolsMATI 2009 Conference: CAT Tools
MATI 2009 Conference: CAT Tools
 
Goboogo 2004
Goboogo 2004Goboogo 2004
Goboogo 2004
 
Smalltalk Metaprogramming supports Probabilistic Program Analysis
Smalltalk Metaprogramming supports Probabilistic Program AnalysisSmalltalk Metaprogramming supports Probabilistic Program Analysis
Smalltalk Metaprogramming supports Probabilistic Program Analysis
 
eZ critical architectures
eZ critical architectureseZ critical architectures
eZ critical architectures
 
Measuring Online Influence: The Art of Making Noise Without Being Noisy
Measuring Online Influence: The Art of Making Noise Without Being NoisyMeasuring Online Influence: The Art of Making Noise Without Being Noisy
Measuring Online Influence: The Art of Making Noise Without Being Noisy
 
Testing Android
Testing AndroidTesting Android
Testing Android
 

Recently uploaded

Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 

Recently uploaded (20)

Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 

Code Quality in Ruby and Java

  • 1. Code Quality What is this s**t? Steve Hayes - Cogent Consulting Pty Ltd http://www.cogentconsulting.com.au steve.hayes@cogentconsulting.com.au Friday, 28 August 2009 1
  • 2. In 1990 there were 120 billion lines of code Friday, 28 August 2009 2
  • 3. In 2000 there were 250 billion lines of code Friday, 28 August 2009 3
  • 4. In 2010 there will be 500 billion lines of code Friday, 28 August 2009 4
  • 5. Printed in a font 1mm high the code listing would stretch from the Earth to the Moon and beyond Friday, 28 August 2009 5
  • 6. Code Quality Friday, 28 August 2009 6
  • 7. Code quality is subjective - it requires human judgment Friday, 28 August 2009 7
  • 8. There have been, and always will be, arguments about code quality Friday, 28 August 2009 8
  • 10. WTF implies lack of clarity Friday, 28 August 2009 10
  • 11. “Simplicity, clarity, singleness: These are the attributes that give our lives power and vividness and joy as they are also the marks of great art. The seem to be the purpose of God for his whole creation.” Richard Holloway Friday, 28 August 2009 11
  • 12. Clear code is easier to understand, easier to maintain, and easier to extend Friday, 28 August 2009 12
  • 13. There are many things that can reduce the clarity of code, including: • inconsistent style • long methods • lots of methods in a single class • repeated code • methods with many alternative paths Friday, 28 August 2009 13
  • 14. Your particular bugbears may be different Friday, 28 August 2009 14
  • 15. Why metrics? Friday, 28 August 2009 15
  • 16. We substitute metrics for human judgement Friday, 28 August 2009 16
  • 17. Friday, 28 August 2009 17
  • 18. People are expensive, CPU time is cheap Friday, 28 August 2009 18
  • 19. Use automation to detect clarity problems, such as: • inconsistent style • long methods • lots of methods in a single class • repeated code • methods with many alternative paths Friday, 28 August 2009 19
  • 20. Use exception based reporting so that people can focus their energy Friday, 28 August 2009 20
  • 21. on the quality exceptions Friday, 28 August 2009 21
  • 22. or on completely different things Friday, 28 August 2009 22
  • 23. Friday, 28 August 2009 23
  • 24. Code Analysis Friday, 28 August 2009 24
  • 25. Let’s start with some Ruby Formtastic by Justin French Friday, 28 August 2009 25
  • 26. Then we’ll move on to some Java Friday, 28 August 2009 26
  • 28. Friday, 28 August 2009 28
  • 29. Duplication makes everything else worse Friday, 28 August 2009 29
  • 30. Friday, 28 August 2009 30
  • 31. Initial analysis of Formtastic Friday, 28 August 2009 31
  • 32. 37 Roodi problems 95 Flog problems Friday, 28 August 2009 32
  • 33. Simian http://www.redhillconsulting.com.au/products/simian/ Friday, 28 August 2009 33
  • 34. Simian - Similarity Analyser | Duplicate Code Detection for the Enterprise 14/08/09 3:41 AM Simian - Similarity Analyser Purpose Simian (Similarity Analyser) identifies duplication in Java, C#, C, C++, COBOL, Ruby, JSP, ASP, HTML, XML, Visual Basic, Groovy source code and even plain text files. In fact, simian can be used on any human readable files such as ini files, deployment descriptors, you name it. Especially on large enterprise projects, it can be difficult for any one developer to keep track of all the features (classes, methods, etc.) of the system. Simian runs natively in any .NET 1.1 or higher supported environment and on any Java 1.4 or higher virtual machine, meaning Simian can be run on just about any hardware and any operating system you can hope for. Both the Java and .NET runtimes are included as part of the distribution. Simian can be used as part of the build process during development or as a guide when re-factoring. Think of Simian as an independent pair of eyes that will assist in raising the quality of your software. Within minutes, Simian can save you literally thousands of dollars in time spent performing maintenence, debugging and re-factoring. With licensing available to suite personal, project and enterprise use, simian is ideally suited for use on your project. Why do I need Simian? Imagine for example that a bug is discovered in a method somewhere in a project. The developer duly writes a test case, makes the necessary code changes, ensures the test passes, checks the code in and considers the job finished! Right? Friday, 28 August 2009 34
  • 35. Simian highlights obvious duplication Friday, 28 August 2009 35
  • 36. Similarity Analyser 2.2.24 - http://www.redhillconsulting.com.au/products/simian/index.html Copyright (c) 2003-08 RedHill Consulting Pty. Ltd. All rights reserved. Simian is not free unless used solely for non-commercial or evaluation purposes. {failOnDuplication=true, ignoreCharacterCase=true, ignoreCurlyBraces=true, ignoreIdentifierCase=true, ignoreModifiers=true, ignoreStringCase=true, threshold=6} Found 7 duplicate lines in the following files: Between lines 949 and 962 in /Users/stevehayes/projects/third-party/formtastic/spec/formtastic_spec.rb Between lines 969 and 982 in /Users/stevehayes/projects/third-party/formtastic/spec/formtastic_spec.rb Found 7 duplicate lines in the following files: Between lines 2552 and 2562 in /Users/stevehayes/projects/third-party/formtastic/spec/formtastic_spec.rb Between lines 2752 and 2762 in /Users/stevehayes/projects/third-party/formtastic/spec/formtastic_spec.rb Found 11 duplicate lines in the following files: Between lines 1429 and 1446 in /Users/stevehayes/projects/third-party/formtastic/spec/formtastic_spec.rb Between lines 1758 and 1775 in /Users/stevehayes/projects/third-party/formtastic/spec/formtastic_spec.rb Found 50 duplicate lines in 6 blocks in 1 files Processed a total of 2066 significant (4341 raw) lines in 6 files Processing time: 0.144sec Friday, 28 August 2009 36
  • 37. Flay http://ruby.sadi.st/Flay.html Friday, 28 August 2009 37
  • 38. Confessions of a Ruby Sadist sudo gem install flay 14/08/09 3:46 AM Ruby Sadist Flog Flay Heckle Kittens About Us Confessions of a Ruby Sadist sudo gem install flay Flay analyzes ruby code for structural similarities. Differences in literal values, names, whitespace, and programming style are all ignored. Code that flay reports as similar is a good candidate for refactoring. Try this: % sudo gem install flay % flay lib/*.rb and see what you find. Friday, 28 August 2009 38
  • 39. Flay detects more subtle duplication Friday, 28 August 2009 39
  • 40. Total score (lower is better) = 2637 8) Similar code found in :iter (mass = 96) spec/formtastic_spec.rb:1825 spec/formtastic_spec.rb:1831 1) Similar code found in :iter (mass = 342) spec/formtastic_spec.rb:1844 spec/formtastic_spec.rb:1570 spec/formtastic_spec.rb:1877 spec/formtastic_spec.rb:1616 spec/formtastic_spec.rb:1895 spec/formtastic_spec.rb:1914 2) Similar code found in :iter (mass = 136) spec/formtastic_spec.rb:1183 9) Similar code found in :iter (mass = 92) spec/formtastic_spec.rb:2147 spec/formtastic_spec.rb:2235 spec/formtastic_spec.rb:2313 spec/formtastic_spec.rb:2245 spec/formtastic_spec.rb:2368 10) Similar code found in :block (mass = 84) 3) IDENTICAL code found in :iter (mass*2 = 136) spec/formtastic_spec.rb:1900 spec/formtastic_spec.rb:1458 spec/formtastic_spec.rb:1919 spec/formtastic_spec.rb:1787 11) IDENTICAL code found in :block (mass*2 = 84) 4) IDENTICAL code found in :iter (mass*2 = 120) spec/formtastic_spec.rb:187 spec/formtastic_spec.rb:1069 spec/formtastic_spec.rb:194 spec/formtastic_spec.rb:1133 12) Similar code found in :iter (mass = 84) 5) IDENTICAL code found in :iter (mass*2 = 104) spec/formtastic_spec.rb:774 spec/formtastic_spec.rb:232 spec/formtastic_spec.rb:830 spec/formtastic_spec.rb:392 13) Similar code found in :iter (mass = 78) 6) Similar code found in :iter (mass = 100) spec/formtastic_spec.rb:1208 spec/formtastic_spec.rb:2572 spec/formtastic_spec.rb:1239 spec/formtastic_spec.rb:2771 spec/formtastic_spec.rb:1265 7) Similar code found in :iter (mass = 98) 14) Similar code found in :iter (mass = 75) spec/formtastic_spec.rb:408 spec/formtastic_spec.rb:596 spec/formtastic_spec.rb:419 spec/formtastic_spec.rb:602 spec/formtastic_spec.rb:608 Friday, 28 August 2009 40
  • 41. So what did I do? Friday, 28 August 2009 41
  • 42. move lines around change similar code to be the same changed in-line constants to variables Friday, 28 August 2009 42
  • 43. these are often non-trivial changes Friday, 28 August 2009 43
  • 44. very little change in overall file length (3013 => 2897 lines) Friday, 28 August 2009 44
  • 45. How did that change complexity? Friday, 28 August 2009 45
  • 46. 37 => 37 Roodi problems 95 => 38 Flog problems Friday, 28 August 2009 46
  • 47. Flog change indicates that methods have become simpler Friday, 28 August 2009 47
  • 49. Friday, 28 August 2009 49
  • 50. What else exacerbates problems? Friday, 28 August 2009 50
  • 51. Long classes and methods Friday, 28 August 2009 51
  • 53. Tools that detect long classes and methods are simple but useful Friday, 28 August 2009 53
  • 54. Roodi Ruby Object Oriented Design Inferometer http://github.com/martinjandrews/roodi/tree/master Friday, 28 August 2009 54
  • 55. General Purpose Code Quality Friday, 28 August 2009 55
  • 56. Roodi checks AssignmentInConditionalCheck Check for an assignment inside a conditional. It‘s probably a mistaken equality comparison. CaseMissingElseCheck Check that case statements have an else statement so that all cases are covered. ClassLineCountCheck Check that the number of lines in a class is below the threshold. ClassNameCheck Check that class names match convention. CyclomaticComplexityBlockCheck Check that the cyclomatic complexity of all blocks is below the threshold. CyclomaticComplexityMethodCheck Check that the cyclomatic complexity of all methods is below the threshold. EmptyRescueBodyCheck Check that there are no empty rescue blocks. ForLoopCheck Check that for loops aren‘t used (Use Enumerable.each instead) MethodLineCountCheck Check that the number of lines in a method is below the threshold. MethodNameCheck Check that method names match convention. ModuleLineCountCheck Check that the number of lines in a module is below the threshold. ModuleNameCheck Check that module names match convention. ParameterNumberCheck Check that the number of parameters on a method is below the threshold. Friday, 28 August 2009 56
  • 57. Roodi parameters AssignmentInConditionalCheck CaseMissingElseCheck ClassLineCountCheck 300 ClassNameCheck pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/ CyclomaticComplexityBlockCheck 4 CyclomaticComplexityMethodCheck 8 EmptyRescueBodyCheck ForLoopCheck MethodLineCountCheck 20 MethodNameCheck pattern: !ruby/regexp /^[_a-z<>=[]|+-/*`]+[_a-z0-9_<>=~@[]]*[=!?]?$/ ModuleLineCountCheck 300 ModuleNameCheck pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/ ParameterNumberCheck 5 Friday, 28 August 2009 57
  • 58. lib/formtastic.rb:8 - Module "Formtastic" has 1272 lines. It should have 300 or less. lib/formtastic.rb:10 - Class "SemanticFormBuilder" has 1196 lines. It should have 300 or less. lib/formtastic.rb:742 - Method "date_or_datetime_input" has 33 lines. It should have 20 or less. lib/formtastic.rb:835 - Method "check_boxes_input" has 24 lines. It should have 20 or less. lib/formtastic.rb:1008 - Method "default_input_type" has 24 lines. It should have 20 or less. lib/formtastic.rb:1046 - Method "find_collection_for_column" has 27 lines. It should have 20 or less. lib/formtastic.rb:1180 - Method "localized_attribute_string" has 24 lines. It should have 20 or less. lib/formtastic.rb:742 - Method name "date_or_datetime_input" cyclomatic complexity is 10. It should be 8 or less. lib/formtastic.rb:1008 - Method name "default_input_type" cyclomatic complexity is 19. It should be 8 or less. lib/formtastic.rb:1046 - Method name "find_collection_for_column" cyclomatic complexity is 10. It should be 8 or less. lib/formtastic.rb:756 - Block cyclomatic complexity is 5. It should be 4 or less. lib/formtastic.rb:1027 - Found = in conditional. It should probably be an == lib/formtastic.rb:1103 - Found = in conditional. It should probably be an == lib/formtastic.rb:1188 - Rescue block should not be empty. lib/formtastic.rb:103 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:378 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:381 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:427 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:455 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:883 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:948 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:950 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:1027 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:1080 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:1128 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:1130 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:1176 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:1184 - Don't use class variables. You might want to try a different design. Friday, 28 August 2009 58
  • 59. spec/formtastic_spec.rb:38 - Block cyclomatic complexity is 5. It should be 4 or less. spec/formtastic_spec.rb:1728 - Block cyclomatic complexity is 5. It should be 4 or less. spec/formtastic_spec.rb:1899 - Block cyclomatic complexity is 5. It should be 4 or less. spec/formtastic_spec.rb:1900 - Block cyclomatic complexity is 5. It should be 4 or less. spec/formtastic_spec.rb:2006 - Block cyclomatic complexity is 6. It should be 4 or less. spec/formtastic_spec.rb:2300 - Block cyclomatic complexity is 9. It should be 4 or less. spec/formtastic_spec.rb:2895 - Block cyclomatic complexity is 9. It should be 4 or less. spec/formtastic_spec.rb:2897 - Block cyclomatic complexity is 14. It should be 4 or less. spec/formtastic_spec.rb:109 - Case statement is missing an else clause. Friday, 28 August 2009 59
  • 60. Let’s work through the spec first Friday, 28 August 2009 60
  • 61. spec/formtastic_spec.rb:38 - Block cyclomatic complexity is 5. It should be 4 or less. Friday, 28 August 2009 61
  • 62. spec/formtastic_spec.rb:109 - Case statement is missing an else clause. Friday, 28 August 2009 62
  • 63. Existing code Post.stub!(:reflect_on_association).and_return do |column_name| case column_name when :author, :author_status mock('reflection', :options => {}, :klass => Author, :macro => :belongs_to) when :authors mock('reflection', :options => {}, :klass => Author, :macro => :has_and_belongs_to_many) end end Friday, 28 August 2009 63
  • 64. New code def mock_post_association(column_name) return mock_association(Author, :belongs_to) if column_name.is_post_belongs_to? return mock_association(Author, :has_and_belongs_to_many) if column_name.is_post_habtm? end def mock_association(klass, multiplicity) mock('reflection', :options => {}, :klass => klass, :macro => multiplicity) end ... Post.stub!(:reflect_on_association).and_return { |column_name|mock_post_association(column_name) } Friday, 28 August 2009 64
  • 65. spec/formtastic_spec.rb:1744 - Block cyclomatic complexity is 5. It should be 4 or less. spec/formtastic_spec.rb:1915 - Block cyclomatic complexity is 5. It should be 4 or less. spec/formtastic_spec.rb:1916 - Block cyclomatic complexity is 5. It should be 4 or less. spec/formtastic_spec.rb:2022 - Block cyclomatic complexity is 6. It should be 4 or less. spec/formtastic_spec.rb:2316 - Block cyclomatic complexity is 9. It should be 4 or less. spec/formtastic_spec.rb:2911 - Block cyclomatic complexity is 9. It should be 4 or less. spec/formtastic_spec.rb:2913 - Block cyclomatic complexity is 14. It should be 4 or less. Friday, 28 August 2009 65
  • 66. Not worth addressing these Friday, 28 August 2009 66
  • 67. Back to the non-test code Friday, 28 August 2009 67
  • 68. lib/formtastic.rb:8 - Module "Formtastic" has 1272 lines. It should have 300 or less. lib/formtastic.rb:10 - Class "SemanticFormBuilder" has 1196 lines. It should have 300 or less. lib/formtastic.rb:742 - Method "date_or_datetime_input" has 33 lines. It should have 20 or less. lib/formtastic.rb:835 - Method "check_boxes_input" has 24 lines. It should have 20 or less. lib/formtastic.rb:1008 - Method "default_input_type" has 24 lines. It should have 20 or less. lib/formtastic.rb:1046 - Method "find_collection_for_column" has 27 lines. It should have 20 or less. lib/formtastic.rb:1180 - Method "localized_attribute_string" has 24 lines. It should have 20 or less. lib/formtastic.rb:742 - Method name "date_or_datetime_input" cyclomatic complexity is 10. It should be 8 or less. lib/formtastic.rb:1008 - Method name "default_input_type" cyclomatic complexity is 19. It should be 8 or less. lib/formtastic.rb:1046 - Method name "find_collection_for_column" cyclomatic complexity is 10. It should be 8 or less. lib/formtastic.rb:756 - Block cyclomatic complexity is 5. It should be 4 or less. lib/formtastic.rb:1027 - Found = in conditional. It should probably be an == lib/formtastic.rb:1103 - Found = in conditional. It should probably be an == lib/formtastic.rb:1188 - Rescue block should not be empty. lib/formtastic.rb:103 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:378 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:381 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:427 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:455 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:883 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:948 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:950 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:1027 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:1080 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:1128 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:1130 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:1176 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:1184 - Don't use class variables. You might want to try a different design. Friday, 28 August 2009 68
  • 69. (and now I make lots of code changes) Friday, 28 August 2009 69
  • 70. lib/formtastic.rb:115 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:390 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:393 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:439 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:467 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:926 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:991 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:993 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:1045 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:1126 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:1175 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:1177 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:1223 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:1240 - Don't use class variables. You might want to try a different design. lib/formtastic.rb:20 - Module "Formtastic" has 1311 lines. It should have 300 or less. lib/formtastic.rb:22 - Class "SemanticFormBuilder" has 1235 lines. It should have 300 or less. lib/formtastic.rb:1244 - Rescue block should not be empty. Friday, 28 August 2009 70
  • 71. and I decide that’s enough for now Friday, 28 August 2009 71
  • 72. How does this change flog? Friday, 28 August 2009 72
  • 73. Old and new flog warnings >88.1: SemanticFormBuilder#date_or_datetime_input 60.4: SemanticFormBuilder#inputs 60.4: SemanticFormBuilder#inputs 58.4: SemanticFormBuilder#input 58.4: SemanticFormBuilder#input 45.3: SemanticFormBuilder#database_column_input_type >57.7: SemanticFormBuilder#find_collection_for_column 43.3: SemanticFormBuilder#field_set_and_list_wrapping -56.9: SemanticFormBuilder#default_input_type 40.2: SemanticFormBuilder#radio_input >48.3: SemanticFormBuilder#localized_attribute_string 38.4: SemanticFormBuilder#localized_attribute_string -44.3: SemanticFormBuilder#check_boxes_input 31.4: 43.3: SemanticFormBuilder#field_set_and_list_wrapping SemanticFormBuilder#find_collection_for_column_explicit_or_asso 40.2: SemanticFormBuilder#radio_input ciation_or_boolean 31.2: SemanticFormBuilder#inputs_for_nested_attributes 31.2: SemanticFormBuilder#inputs_for_nested_attributes 24.0: SemanticFormBuilder#label 29.5: SemanticFormBuilder#datetime_content_tag 22.7: SemanticFormBuilder#method_required? 28.1: SemanticFormBuilder#find_collection_for_column 20.0: SemanticFormBuilder#none 26.0: SemanticFormBuilder#single_list_item_content_from 24.0: SemanticFormBuilder#label 22.7: SemanticFormBuilder#method_required? 20.2: SemanticFormBuilder#date_or_datetime_input 20.0: SemanticFormBuilder#none Friday, 28 August 2009 73
  • 74. Changes >88.1: SemanticFormBuilder#date_or_datetime_input 45.3: SemanticFormBuilder#database_column_input_type >57.7: SemanticFormBuilder#find_collection_for_column 38.4: SemanticFormBuilder#localized_attribute_string -56.9: SemanticFormBuilder#default_input_type 31.4: >48.3: SemanticFormBuilder#localized_attribute_string SemanticFormBuilder#find_collection_for_column_explicit_ -44.3: SemanticFormBuilder#check_boxes_input or_association_or_boolean 29.5: SemanticFormBuilder#datetime_content_tag 28.1: SemanticFormBuilder#find_collection_for_column 26.0: SemanticFormBuilder#single_list_item_content_from 20.2: SemanticFormBuilder#date_or_datetime_input Friday, 28 August 2009 74
  • 75. So what’s Flog? Friday, 28 August 2009 75
  • 76. Confessions of a Ruby Sadist sudo gem install flog 14/08/09 3:34 AM Ruby Sadist Flog Flay Heckle Kittens About Us Confessions of a Ruby Sadist sudo gem install flog Flog shows you the most torturous code you wrote. The more painful the code, the higher the score. The higher the score, the harder it is to test. Run it against your best stuff. I double-dog dare you. So what’s Flog? Flog essentially scores an ABC metric: Assignments, Branches, Calls, with particular attention placed on calls. Run flog on all your code. Try this: find lib -name *.rb | xargs flog Whatever is at the top of the report is worth looking at. This is how it works: Friday, 28 August 2009 76
  • 77. Confessions of a Ruby Sadist sudo gem install flog 14/08/09 3:34 AM class Test class Test def blah # 11.2 = def blah a = eval "1+1" # 1.2 + 6.0 + a = eval "1+1" if a == 2 then # 1.2 + 1.2 + if a == 2 then Is seen by 0.4 + puts "yay" flog as: puts "yay" # 1.2 end end end end end end Test#blah: (11.2) 6.0: eval 1.2: branch and reported 1.2: == as: 1.2: puts 1.2: assignment 0.4: lit_fixnum Friday, 28 August 2009 77
  • 78. Flog weights THRESHOLD = 0.60 SCORES = Hash.new 1 # various "magic" usually used for "clever code" BRANCHING = SCORES.merge!(:alias_method => 2, [ :and, :case, :else, :if, :or, :rescue, :until, :extend => 2, :when, :while ] :include => 2, :instance_method => 2, # various non-call constructs :instance_methods => 2, OTHER_SCORES = { :method_added => 2, :alias => 2, :method_defined? => 2, :assignment => 1, :method_removed => 2, :block => 1, :method_undefined => 2, :block_pass => 1, :private_class_method => 2, :branch => 1, :private_instance_methods => 2, :lit_fixnum => 0.25, :private_method_defined? => 2, :sclass => 5, :protected_instance_methods => 2, :super => 1, :protected_method_defined? => 2, :to_proc_icky! => 10, :public_class_method => 2, :to_proc_normal => 5, :public_instance_methods => 2, :yield => 1, :public_method_defined? => 2, } :remove_method => 2, :send => 3, # eval forms :undef_method => 2) SCORES.merge!(:define_method => 5, :eval => 5, # calls I don't like and usually see being :module_eval => 5, abused :class_eval => 5, :instance_eval => 5) SCORES.merge!(:inject => 2) Friday, 28 August 2009 78
  • 80. Flog details for worst method 60.4: SemanticFormBuilder#inputs 16.6: assignment 11.9: branch 11.5: to_proc_normal 5.8: block_pass 5.7: map 4.8: class 3.3: field_set_and_list_wrapping 2.3: content_columns 2.2: macro 2.1: reflections 2.0: == 2.0: to_sym 1.9: compact! 1.9: + 1.9: - 1.8: empty? 1.8: input 1.5: block_given? 1.5: inputs_for_nested_attributes 1.4: extract_options! 1.4: [] Friday, 28 August 2009 80
  • 81. Original code def inputs(*args, &block) html_options = args.extract_options! html_options[:class] ||= "inputs" if html_options[:for] inputs_for_nested_attributes(args, html_options, &block) elsif block_given? field_set_and_list_wrapping(html_options, &block) else if @object && args.empty? args = @object.class.reflections.map { |n,_| n if _.macro == :belongs_to } args += @object.class.content_columns.map(&:name) args -= %w[created_at updated_at created_on updated_on lock_version] args.compact! end contents = args.map { |method| input(method.to_sym) } field_set_and_list_wrapping(html_options, contents) end end Friday, 28 August 2009 81
  • 82. First change def inputs(*args, &block) html_options = args.extract_options! html_options[:class] ||= "inputs" if html_options[:for] inputs_for_nested_attributes(args, html_options, &block) elsif block_given? field_set_and_list_wrapping(html_options, &block) else if @object && args.empty? args = build_default_inputs_args end contents = args.map { |method| input(method.to_sym) } field_set_and_list_wrapping(html_options, contents) end end def build_default_inputs_args() args = @object.class.reflections.map { |n,_| n if _.macro == :belongs_to } args += @object.class.content_columns.map(&:name) args -= %w[created_at updated_at created_on updated_on lock_version] args.compact! end Friday, 28 August 2009 82
  • 83. Flog details 29.8: SemanticFormBuilder#build_default_inputs_args 9.0: to_proc_normal 8.7: assignment 3.8: class 3.0: map 2.9: branch 1.8: block_pass 1.8: content_columns 1.7: macro 1.6: reflections 1.5: == 1.4: compact! 1.4: - 1.4: + 24.1: SemanticFormBuilder#inputs 8.0: branch 6.7: assignment 3.5: block_pass 3.3: field_set_and_list_wrapping 2.0: to_sym 1.8: empty? 1.8: build_default_inputs_args 1.8: input 1.7: map 1.5: inputs_for_nested_attributes 1.5: block_given? 1.4: extract_options! 1.4: [] Friday, 28 August 2009 83
  • 84. Next change def inputs(*args, &block) html_options = args.extract_options! html_options[:class] ||= "inputs" if html_options[:for] inputs_for_nested_attributes(args, html_options, &block) elsif block_given? field_set_and_list_wrapping(html_options, &block) else contents = inputs_contents(args) field_set_and_list_wrapping(html_options, contents) end end def inputs_contents(args) if @object && args.empty? args = build_default_inputs_args end return args.map { |method| input(method.to_sym) } end def build_default_inputs_args() args = @object.class.reflections.map { |n,_| n if _.macro == :belongs_to } args += @object.class.content_columns.map(&:name) args -= %w[created_at updated_at created_on updated_on lock_version] args.compact! end Friday, 28 August 2009 84
  • 85. Flog details - only one significant method 29.8: SemanticFormBuilder#build_default_inputs_args 9.0: to_proc_normal 8.7: assignment 3.8: class 3.0: map 2.9: branch 1.8: block_pass 1.8: content_columns 1.7: macro 1.6: reflections 1.5: == 1.4: compact! 1.4: - 1.4: + Friday, 28 August 2009 85
  • 86. Inline to_proc def build_default_inputs_args() args = @object.class.reflections.map { |n,_| n if _.macro == :belongs_to } args += @object.class.content_columns.map {|c| c.name} args -= %w[created_at updated_at created_on updated_on lock_version] args.compact! end Friday, 28 August 2009 86
  • 87. Flog details 22.4: SemanticFormBuilder#build_default_inputs_args 10.4: assignment 4.5: branch 3.8: class 3.0: map 1.8: content_columns 1.7: name 1.7: macro 1.6: reflections 1.5: == 1.4: compact! 1.4: - Friday, 28 August 2009 87
  • 88. Extract method def build_default_inputs_args() args = @object.class.reflections.map { |n,_| n if _.macro == :belongs_to } args += content_column_names args -= %w[created_at updated_at created_on updated_on lock_version] args.compact! end def content_column_names return @object.class.content_columns.map {|c| c.name} end Friday, 28 August 2009 88
  • 89. Flog details 16.6: SemanticFormBuilder#build_default_inputs_args 8.7: assignment 2.9: branch 1.8: class 1.7: macro 1.6: content_column_names 1.6: reflections 1.5: == 1.4: compact! 1.4: map 1.4: - 1.4: + Friday, 28 August 2009 89
  • 90. and so forth... Friday, 28 August 2009 90
  • 91. Other Ruby code quality tools Friday, 28 August 2009 91
  • 92. Code churn metric Friday, 28 August 2009 92
  • 93. Saikuro : A Cyclomatic Complexity Analyzer 14/08/09 5:05 AM Saikuro A Cyclomatic Complexity Analyzer Download Saikuro Saikuro is a Ruby cyclomatic complexity analyzer. When given Ruby source code Saikuro will generate a report listing the cyclomatic complexity of each method found. In addition, Saikuro counts the number of lines per method and can generate a listing of the number of tokens on each line of code. Version: 0.2 License Saikuro uses the BSD license. Example Output Here are examples of the output generated by Saikuro. Cyclomatic complexity summary page Token count summary page Installation As root run: # ruby setup.rb all Usage Saikuro is a command line program. Running "saikuro.rb -h" will output a usage statement describing all the various arguments you can pass to it. "saikuro -c -p tests/samples.rb" The above command is a simple example that generates a cyclomatic complexity report on the samples.rb file, using the default filter, warning and error settings. The report is saved in the current directory. A more detailed example is : Friday, 28 August 2009 "saikuro -c -t -i tests -y 0 -w 11 -e 16 -o out/" 93
  • 94. reek, a code smells detector for ruby « silk and spinach 14/08/09 5:06 AM silk and spinach development, by example reek, a code smells detector for ruby with 23 comments To complement the imminent (ie. sometime next year) publication of the Ruby Refactoring Workbook I’ve been working on a little software tool called ‘reek’. Reek scans ruby code — either source files or in-memory Class objects — looking for some of the code smells discussed in the book. Right now it can detect (certain forms of): Long Method Large Class Feature Envy Uncommunicative Name Long Parameter List Utility Function Nested Iterators As time goes by I’ll be adding checks for more smells, and I hope to make the current checks a bit more sophisticated. But in the agile spirit of going ugly early, the current very early version is available for you to experiment with. To get the tool: gem install reek To run it: reek file1.rb file2.rb ... If you try it, please let me know what you think and what you’d like the next version to do! You can browse the reek project’s code repository at http://github.com/kevinrutherford/reek/tree/master or http://rubyforge.org/projects/reek/, both of which are clones of the same Git repository. Friday, 28 August 2009 94
  • 95. RCov - Ruby C0 Code Coverage 15/08/09 12:11 PM RCov RCov - Ruby C0 Code Coverage Source Install $ gem install relevance-rcov Usage See the README on GitHub for the most-up to date usage of RCov. Maintained by Relevance Friday, 28 August 2009 95
  • 96. metric fu Friday, 28 August 2009 96
  • 97. rake metrics:all Friday, 28 August 2009 97
  • 98. results at file:///Users/stevehayes/projects/third-party/ formtastic/tmp/metric_fu/output/index.html Friday, 28 August 2009 98
  • 99. Java time Friday, 28 August 2009 99
  • 100. Example code is from Apache Commons Collections 3.2.1 Friday, 28 August 2009 100
  • 101. Simian for duplication detection Friday, 28 August 2009 101
  • 102. java -jar simian-2.2.24.jar src/**/*.java Friday, 28 August 2009 102
  • 103. Found 11527 duplicate lines in 871 blocks in 239 files Processed a total of 41324 significant (109875 raw) lines in 467 files Processing time: 2.404sec Friday, 28 August 2009 103
  • 104. 27.9% of the code is duplicated Friday, 28 August 2009 104
  • 105. Simian can also be language sensitive Friday, 28 August 2009 105
  • 106. java -jar simian-2.2.24.jar -language=java src/**/*.java Friday, 28 August 2009 106
  • 107. PMD for duplication detection Friday, 28 August 2009 107
  • 108. Android Rules: These rules deal with the Android SDK, mostly related to best practices. To get better results, make sure that the auxclasspath is defined for type resolution to work. • Basic JSF rules: Rules concerning basic JSF guidelines. • Basic JSP rules: Rules concerning basic JSP guidelines. • Basic Rules: The Basic Ruleset contains a collection of good practices which everyone should follow. • Braces Rules: The Braces Ruleset contains a collection of braces rules. • Clone Implementation Rules: The Clone Implementation ruleset contains a collection of rules that find questionable usages of the clone() method. • Code Size Rules: The Code Size Ruleset contains a collection of rules that find code size related problems. • Controversial Rules: The Controversial Ruleset contains rules that, for whatever reason, are considered controversial. They are separated out here to allow people to include as they see fit via custom rulesets. This ruleset was initially created in response to discussions over UnnecessaryConstructorRule which Tom likes but most people really dislike :-) • Coupling Rules: These are rules which find instances of high or inappropriate coupling between objects and packages. • Design Rules: The Design Ruleset contains a collection of rules that find questionable designs. • Finalizer Rules: These rules deal with different problems that can occur with finalizers. • Import Statement Rules: These rules deal with different problems that can occur with a class' import statements. • J2EE Rules: These are rules for J2EE • JavaBean Rules: The JavaBeans Ruleset catches instances of bean rules not being followed. • JUnit Rules: These rules deal with different problems that can occur with JUnit tests. • Jakarta Commons Logging Rules: The Jakarta Commons Logging ruleset contains a collection of rules that find questionable usages of that framework. • Java Logging Rules: The Java Logging ruleset contains a collection of rules that find questionable usages of the logger. • Migration Rules: Contains rules about migrating from one JDK version to another. Don't use these rules directly, rather, use a wrapper ruleset such as migrating_to_13.xml. • Migration13: Contains rules for migrating to JDK 1.3 • Migration14: Contains rules for migrating to JDK 1.4 • Migration15: Contains rules for migrating to JDK 1.5 • MigratingToJava4: Contains rules for migrating to JDK 1.5 • Naming Rules: The Naming Ruleset contains a collection of rules about names - too long, too short, and so forth. • Optimization Rules: These rules deal with different optimizations that generally apply to performance best practices. • Strict Exception Rules: These rules provide some strict guidelines about throwing and catching exceptions. • String and StringBuffer Rules: These rules deal with different problems that can occur with manipulation of the class String or StringBuffer. • Security Code Guidelines: These rules check the security guidelines from Sun, published at http://java.sun.com/security/ seccodeguide.html#gcg • Type Resolution Rules: These are rules which resolve java Class files for comparisson, as opposed to a String Friday, 28 August 2009 108
  • 109. Basic Rules: The Basic Ruleset contains a collection of good practices which everyone should follow. • Braces Rules: The Braces Ruleset contains a collection of braces rules. • Clone Implementation Rules: The Clone Implementation ruleset contains a collection of rules that find questionable usages of the clone() method. • Code Size Rules: The Code Size Ruleset contains a collection of rules that find code size related problems. • Coupling Rules: These are rules which find instances of high or inappropriate coupling between objects and packages. • Design Rules: The Design Ruleset contains a collection of rules that find questionable designs. • Import Statement Rules: These rules deal with different problems that can occur with a class' import statements. • JUnit Rules: These rules deal with different problems that can occur with JUnit tests. • Naming Rules: The Naming Ruleset contains a collection of rules about names - too long, too short, and so forth. • Optimization Rules: These rules deal with different optimizations that generally apply to performance best practices. • Strict Exception Rules: These rules provide some strict guidelines about throwing and catching exceptions. • String and StringBuffer Rules: These rules deal with different problems that can occur with manipulation of the class String or StringBuffer. • Type Resolution Rules: These are rules which resolve java Class files for comparisson, as opposed to a String • Unused Code Rules: The Unused Code Ruleset contains a collection of rules that find unused code. Friday, 28 August 2009 109
  • 110. Basic Rules • Empty catch block • Unnecessary final modifier • Empty if Statement • Collapsible if statements • Empty while statement • Useless overriding method • Empty try block • Class cast exception with toArray • Empty finally block • Avoid decimal literals in BigDecimal • Empty switch statements constructor • Jumbled incrementer • Useless operation on immutable • For loop should be while loop • Misplaced null check • Unnecessary conversion temporary • Unused null check in equals • Override both equals and hashcode • Avoid thread group • Double checked locking • Broken null check • Return from finally block • BigInteger instantiation • Empty synchronized block • Avoid using octal values • Unnecessary return • Avoid using hardcoded IP • Empty static initializer • Check result set • Unconditional if statement • Avoid multiple unary operators • Empty statement not in loop • Empty initializer • Boolean instantiation Friday, 28 August 2009 110
  • 111. Basic Rules - 725 /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BeanMap.java:308 Overriding method merely calls super /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ExtendedProperties.java:410 Overriding method merely calls super /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ExtendedProperties.java:476 Avoid empty catch blocks /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ExtendedProperties.java:536 Avoid empty catch blocks /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ExtendedProperties.java:616 These nested if statements could be combined /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ExtendedProperties.java:1157 Avoid instantiating Boolean objects; reference Boolean.TRUE or Boolean.FALSE or call Boolean.valueOf() instead. /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ExtendedProperties.java:1179 Avoid instantiating Boolean objects; reference Boolean.TRUE or Boolean.FALSE or call Boolean.valueOf() instead. /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/IteratorUtils.java:907 Avoid empty catch blocks /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/LRUMap.java:120 These nested if statements could be combined /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/MapUtils.java:170 Avoid instantiating Boolean objects; reference Boolean.TRUE or Boolean.FALSE or call Boolean.valueOf() instead. /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/MultiHashMap.java:138 Avoid empty catch blocks /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:598 Avoid empty while statements /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:936 Ensure you override both equals() and hashCode() /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:952 Ensure you override both equals() and hashCode() /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/StaticBucketMap.java:159 Unnecessary final modifier in final class /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/StaticBucketMap.java:393 Unnecessary final modifier in final class /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/StaticBucketMap.java:401 Unnecessary final modifier in final class /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/StaticBucketMap.java:416 Unnecessary final modifier in final class /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/StaticBucketMap.java:431 Unnecessary final modifier in final class /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/functors/PrototypeFactory.java:195 Avoid empty catch blocks /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/functors/PrototypeFactory.java:202 Avoid empty catch blocks /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/iterators/FilterIterator.java:108 These nested if statements could be combined /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/iterators/FilterListIterator.java:140 These nested if statements could be combined /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/iterators/FilterListIterator.java:156 These nested if statements could be combined /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/iterators/ObjectGraphIterator.java:141 Avoid empty if statements /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/iterators/ObjectGraphIterator.java:193 Avoid empty if statements /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/iterators/ObjectGraphIterator.java:195 Avoid empty if statements /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/list/CursorableLinkedList.java:428 Avoid empty if statements /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/AbstractReferenceMap.java:278 Avoid empty while statements /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/AbstractReferenceMap.java:889 Ensure you override both equals() and hashCode() /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/AbstractReferenceMap.java:906 Ensure you override both equals() and hashCode() /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/CaseInsensitiveMap.java:133 Overriding method merely calls super /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/HashedMap.java:96 Overriding method merely calls super /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/IdentityMap.java:175 Overriding method merely calls super /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/LRUMap.java:395 Overriding method merely calls super /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/LinkedMap.java:117 Overriding method merely calls super /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/StaticBucketMap.java:160 Unnecessary final modifier in final class Friday, 28 August 2009 111
  • 112. Braces Rules • If statements must use braces • While loops must use braces • If else statements must use braces • For loops must use braces Friday, 28 August 2009 112
  • 113. Braces Rules - 210 /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BeanMap.java:268 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BeanMap.java:600 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BinaryHeap.java:476 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BoundedFifoBuffer.java:272 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BoundedFifoBuffer.java:280 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:370 Avoid using if...else statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:371 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:382 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:393 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:876 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:894 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:912 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:987 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:1012 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:1029 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:1063 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastHashMap.java:592 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastTreeMap.java:700 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/LRUMap.java:92 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:289 Avoid using while statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:378 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:464 Avoid using if...else statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:465 Avoid using if...else statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:506 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:520 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:537 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:538 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:541 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:571 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:579 Avoid using if...else statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:580 Avoid using if...else statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:598 Avoid using while statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:621 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:622 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:665 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:711 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:771 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:778 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:779 Avoid using if statements without curly braces /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ReferenceMap.java:780 Avoid using if statements without curly braces Friday, 28 August 2009 113
  • 114. Clone Rules • Proper clone implementation (should include super.clone()) • Clone throws CloneNotSupportedException • Clone method must implement cloneable Friday, 28 August 2009 114
  • 115. Clone Rules - 25 /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:281 Object clone() should be implemented with super.clone() /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:281 clone() method should be implemented only if implementing Cloneable interface /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:281 clone() method should throw CloneNotSupportedException /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastHashMap.java:419 Object clone() should be implemented with super.clone() /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastHashMap.java:419 clone() method should be implemented only if implementing Cloneable interface /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastHashMap.java:419 clone() method should throw CloneNotSupportedException /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastTreeMap.java:470 Object clone() should be implemented with super.clone() /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastTreeMap.java:470 clone() method should be implemented only if implementing Cloneable interface /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastTreeMap.java:470 clone() method should throw CloneNotSupportedException /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/MultiHashMap.java:464 clone() method should be implemented only if implementing Cloneable interface /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/MultiHashMap.java:464 clone() method should throw CloneNotSupportedException /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/AbstractHashedMap.java:1227 clone() method should be implemented only if implementing Cloneable interface /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/AbstractHashedMap.java:1227 clone() method should throw CloneNotSupportedException /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/CaseInsensitiveMap.java:133 clone() method should throw CloneNotSupportedException /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/Flat3Map.java:1014 clone() method should throw CloneNotSupportedException /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/HashedMap.java:96 clone() method should throw CloneNotSupportedException /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/IdentityMap.java:175 clone() method should throw CloneNotSupportedException /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/LRUMap.java:395 clone() method should throw CloneNotSupportedException /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/LinkedMap.java:117 clone() method should throw CloneNotSupportedException /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/MultiKeyMap.java:818 Object clone() should be implemented with super.clone() /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/MultiKeyMap.java:818 clone() method should be implemented only if implementing Cloneable interface /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/MultiKeyMap.java:818 clone() method should throw CloneNotSupportedException /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/SingletonMap.java:538 clone() method should throw CloneNotSupportedException /Users/stevehayes/commons-collections-3.2.1-src/src/test/org/apache/commons/collections/BulkTest.java:177 clone() method should throw CloneNotSupportedException Friday, 28 August 2009 115
  • 116. Code Size Rules • NPath complexity (200) • Excessive method length (100) • Excessive parameter list (10) • Excessive class length (1000) • Cyclomatic complexity (10) • Excessive public count (45) • Too many fields (15) • NCSS method count (100) • NCSS type count (1500) • NCSS constructor count (100) • Too many methods (10) Friday, 28 August 2009 116
  • 117. Code Size Rules - 338 /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BeanMap.java:55 This class has too many methods, consider refactoring it. /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BinaryHeap.java:63 The class 'BinaryHeap' has a Cyclomatic Complexity of 2 (Highest = 14). /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BinaryHeap.java:64 This class has too many methods, consider refactoring it. /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BinaryHeap.java:465 The method 'iterator' has a Cyclomatic Complexity of 14. /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BinaryHeap.java:482 The method 'remove' has a Cyclomatic Complexity of 10. /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BoundedFifoBuffer.java:56 This class has too many methods, consider refactoring it. /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ClosureUtils.java:57 This class has too many methods, consider refactoring it. /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CollectionUtils.java:17 his class has a bunch of public methods and attributes T /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CollectionUtils.java:58 void really long classes. A /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CollectionUtils.java:58 he class 'CollectionUtils' has a Cyclomatic Complexity of 3 T (Highest = 14). /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CollectionUtils.java:58 his class has too many methods, consider refactoring it. T /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CollectionUtils.java:741 The method 'index' has a Cyclomatic Complexity of 13. /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CollectionUtils.java:829 The method 'get' has a Cyclomatic Complexity of 14. /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CollectionUtils.java:894 The method 'size' has a Cyclomatic Complexity of 10. /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ComparatorUtils.java:44 This class has too many methods, consider refactoring it. /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CursorableLinkedList.java:17 This class has a bunch of public methods and attributes /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CursorableLinkedList.java:55 Avoid really long classes. /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CursorableLinkedList.java:55 This class has too many methods, consider refactoring it. /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CursorableLinkedList.java:1202 his class has too many methods, consider refactoring it. T /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/CursorableLinkedList.java:1405 he method insertListable() has an NPath complexity of T 200 /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/DefaultMapBag.java:48 his class has too many methods, consider refactoring it. T /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/DoubleOrderedMap.java:17 This class has a bunch of public methods and attributes /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/DoubleOrderedMap.java:107 Avoid really long classes. /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/DoubleOrderedMap.java:107 The class 'DoubleOrderedMap' has a Cyclomatic Complexity of 4 (Highest = 15). /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/DoubleOrderedMap.java:107 This class has too many methods, consider refactoring it. /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/DoubleOrderedMap.java:202 The method 'entrySetByValue' has a Cyclomatic Complexity of 12. /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/DoubleOrderedMap.java:341 The method 'valuesByValue' has a Cyclomatic Complexity of 11. /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/DoubleOrderedMap.java:804 The method 'doRedBlackInsert' has a Cyclomatic Complexity of 11. /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/DoubleOrderedMap.java:875 The method 'doRedBlackDelete' has a Cyclomatic Complexity of 13. /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/DoubleOrderedMap.java:952 The method 'doRedBlackDeleteFixup' has a Cyclomatic Complexity of 12. /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/DoubleOrderedMap.java:1044 The method 'swapPosition' has a Cyclomatic Complexity of Friday, 28 August 2009 117
  • 118. Coupling Rules • Coupling between objects (attributes, local variables, return types) (20) • Excessive imports (30) • Loose coupling (avoid using implementation types, use interface instead) Friday, 28 August 2009 118
  • 119. Coupling Rules - 63 /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BeanMap.java:59 Avoid using implementation types like 'HashMap'; use the interface instead /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BeanMap.java:60 Avoid using implementation types like 'HashMap'; use the interface instead /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BeanMap.java:61 Avoid using implementation types like 'HashMap'; use the interface instead /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/BeanMap.java:72 Avoid using implementation types like 'HashMap'; use the interface instead /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ExtendedProperties.java:187 Avoid using implementation types like 'ArrayList'; use the interface instead /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ExtendedProperties.java:1037 Avoid using implementation types like 'Vector'; use the interface instead /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ExtendedProperties.java:1053 Avoid using implementation types like 'Vector'; use the interface instead /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/ExtendedProperties.java:1053 Avoid using implementation types like 'Vector'; use the interface instead /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastArrayList.java:117 Avoid using implementation types like 'ArrayList'; use the interface instead /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastHashMap.java:71 Avoid using implementation types like 'HashMap'; use the interface instead /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/FastTreeMap.java:73 Avoid using implementation types like 'TreeMap'; use the interface instead /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/IteratorUtils.java:17 A high number of imports can indicate a high degree of coupling within an object. /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/SequencedHashMap.java:154 Avoid using implementation types like 'HashMap'; use the interface instead /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/StaticBucketMap.java:508 Avoid using implementation types like 'ArrayList'; use the interface instead /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/iterators/CollatingIterator.java:49 Avoid using implementation types like 'ArrayList'; use the interface instead /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/iterators/CollatingIterator.java:52 Avoid using implementation types like 'ArrayList'; use the interface instead /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/iterators/CollatingIterator.java:361 Avoid using implementation types like 'ArrayList'; use the interface instead /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/MultiValueMap.java:78 Avoid using implementation types like 'ArrayList'; use the interface instead /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/MultiValueMap.java:109 Avoid using implementation types like 'ArrayList'; use the interface instead /Users/stevehayes/commons-collections-3.2.1-src/src/java/org/apache/commons/collections/map/StaticBucketMap.java:499 Avoid using implementation types like 'ArrayList'; use the interface instead Friday, 28 August 2009 119