Clean code: smells

We continue series of articles about Clean Code conceptions, that are based on a famous book of R.Martin Clean Code: A Handbook of Agile Software Craftsmanship, classification of Urs Enzler from BBV and our experience.
We would write about code smells and code metrics: indicators, that help to analyze code in our software solution.

Code metrics

The following list shows the code metrics results that Visual Studio calculates:

  • Maintainability Index – Calculates an index value between 0 and 100 that represents the relative ease of maintaining the code. A high value means better maintainability. Color coded ratings can be used to quickly identify trouble spots in your code. A green rating is between 20 and 100 and indicates that the code has good maintainability. A yellow rating is between 10 and 19 and indicates that the code is moderately maintainable. A red rating is a rating between 0 and 9 and indicates low maintainability.
  • Cyclomatic Complexity – Measures the structural complexity of the code. It is created by calculating the number of different code paths in the flow of the program. A program that has complex control flow will require more tests to achieve good code coverage and will be less maintainable.
  • Depth of Inheritance – Indicates the number of class definitions that extend to the root of the class hierarchy. The deeper the hierarchy the more difficult it might be to understand where particular methods and fields are defined or/and redefined.
  • Class Coupling – Measures the coupling to unique classes through parameters, local variables, return types, method calls, generic or template instantiations, base classes, interface implementations, fields defined on external types, and attribute decoration. Good software design dictates that types and methods should have high cohesion and low coupling. High coupling indicates a design that is difficult to reuse and maintain because of its many interdependencies on other types.
  • Lines of Code – Indicates the approximate number of lines in the code. The count is based on the IL code and is therefore not the exact number of lines in the source code file. A very high count might indicate that a type or method is trying to do too much work and should be split up. It might also indicate that the type or method might be hard to maintain.
  • Tests code coverage – To determine what proportion of your project’s code is actually being tested by coded tests such as unit, functional and other type of tests.

− Rigidity

The software is difficult to change. A small change causes a cascade of subsequent changes.
Precise indicators: Depth of Inheritance, Class Coupling.
Fix approach: to refactor code over Loose coupling, High Cohesion principles, redesign Class structure.

− Fragility

The software breaks in many places due to a single change.
Precise indicators: Depth of Inheritance, Class Coupling, Unit tests coverage.
Fix approach: Unit tests covering, Change is Local principle, to refactor code over Loose coupling, High Cohesion, Single Responsibility Principles

Comment: Refactor, refactor, refactor

− Immobility

You cannot reuse parts of the code in other projects because of involved risks and high effort.
Precise indicators: Depth of Inheritance, Class Coupling, Unit tests coverage.
Fix approach: Unit tests covering, to refactor code over Loose coupling.

− Viscosity of Design

Taking a shortcut and introducing technical debt requires less effort than doing it right.
Precise indicators: Maintainability Index, Cyclomatic Complexity, Class Coupling.
Fix approach: Unit tests covering, improve Maintainability Index and Cyclomatic Complexity over dividing to sub-methods

Comment: Sometimes appear time critical tasks, that need to implement ASAP ‘somehow’. Such practice should be as exception.

− Viscosity of Environment

Building, testing and other tasks take a long time. Therefore, these activities are not executed properly by everyone and technical debt is introduced.
Precise indicators: Building, deploying, executing unit testing time.
Fix approach: setup Continuous Integration with automatic execution all required steps.

Comment: Bulding, deploying time with tests execution should be no more than 5 minutes during regular team work.

− Needless Complexity

The design contains elements that are currently not useful. The added complexity makes the code harder to comprehend. Therefore, extending and changing the code results in higher effort than necessary.
Precise indicators: Difficult to add simple feature, large needless flexebility.
Fix approach: KISS principle, analyzying and decrease when it’s possible business rules

Comment: sometimes need to forget about flexibility and try to understand business value of product

− Needless Repetition

Code contains exact code duplications or design duplicates (doing the same thing in a different way). Making a change to a duplicated piece of code is more expensive and more error-prone because the change has to be made in several places with the risk that one place is not changed accordingly.
Precise indicators: in VS -> Anaylze Solution for Code clones
Fix approach: to refactor code over extract similar functionality to general code place

− Bad opacity

The code is hard to understand. Therefore, any change takes additional time to first reengineer the code and is more likely to result in defects due to not understanding the side effects.
Precise indicators: Maintainability Index, Cyclomatic Complexity, Lines of Code.
Fix approach: follow Code conventions, KISS principle, dividing to sub-methods

Comment: Here is one of main Clean code goal: Code is clean if it can be understood easily – by everyone on the team

Next article will be about Class design principles: Single Responsibility Principle, Open Closed Principle, Liskov Substitution Principle, Dependency Inversion Principle, Interface Segregation Principle, Class size, Class responsibility.

R.Martin Clean Code: A Handbook of Agile Software Craftsmanship