As software developers, we can write a lot of code each day. Each piece of code has its story, the code could be:
- Inspired by a web resource ( forum, tutorial, blog post,…)
- Inspired by an open source project from Github, Sourceforge or other.
- Copy/Pasted from the project itself.
- developed from scratch.
And for each piece of code, the developer does an analysis of the current problem to resolve, its background and the opinions of his team could influence a lot its choices, and the way how the code is developed.
After writing a code and committing it. be sure that it will introduce a debt that the project maintainer and developers have to pay sooner or later. To minimize the debt and make the task easy for all the project developers, it’s better to acquire some basic good habits to make the code clean from the beginning.
Sometimes we spent a lot of times just to understand the utility of a variable or a function because it’s named a,b or x. And if from the beginning it was named with a clear and significant name, its meaning will become obvious.
Good a significant naming that follows a naming convention help:
- To reduce the effort needed to read and understand source code;
- To enable code reviews to focus on more important issues than arguing over syntax and naming standards.
- To enable code quality review tools to focus their reporting mainly on significant issues other than syntax and style preferences.
Narrowing visibility is a good practice because doing so promotes encapsulation. Reduce the scope to a minimum, will help the user of your code. Indeed he will know which code could be used from outside a class.
Making all the class methods public will confuse the user, and it will hide the class contract. And in this case, we need a documentation to know which methods could be used.
A function that takes more than five parameters indicates one of two problems:
- The function is doing too much. It should be split into several smaller functions, each which have a smaller parameter set.
- There is another object hiding in there. You may need to create another object or data structure that includes these parameters.
There are some good gains to be had by doing this:
- It makes your code easier to read.
- It’s more unit testable.
Methods too big are not easy to maintain and understand. Here’s some advice about the length of functions from the linux coding style web page:
Functions should be short and sweet, and do just one thing. They should fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24, as we all know), and do one thing and do that well. The maximum length of a function is inversely proportional to the complexity and indentation level of that function. So, if you have a conceptually simple function that is just one long (but simple) case-statement, where you have to do lots of small things for a lot of different cases, it's OK to have a longer function.
5 Number of local variables
Methods, where NbVariables is higher than 8, are hard to understand and maintain. Methods, where NbVariables is higher than 15, are extremely complex and should be split into smaller methods (unless they are automatically generated by a tool).
6 Avoid defining complex functions
Many metrics exist to detect complex functions, NBLinesOfCode, Number of parameters and number of local variables are the basic ones.
There are other interesting metrics to detect complex functions:
- Cyclomatic complexity is a popular procedural software metric where the result is equal to the number of decisions that can be taken in a procedure.
- Nesting Depth is a metric defined on methods that is relative to the maximum depth of the more nested scope in a method body.
- Max Nested loop is equal to the maximum level of loop nesting in a function.
The max value tolerated for these metrics depends more on the team choices, as there are no standard values.
Let’s search for possible functions to be refactored:
Programming style and indentation can be defined as the way you follow to organize and document your source code. Code indentation is a part of style and it is more of aesthetic interest. If we follow a proper style guide and indentation then a program can be just like a POEM. And the reader will be comfortable enough to SAIL through it and understand the meaning. As we know a proper code indentation will make it:
- Easier to read
- Easier to understand
- Easier to modify
- Easier to maintain
- Easier to enhance
The purpose of code indentation and style is to make the program more readable and understandable. It saves lots of time while we revisit the code and use it. A style guide provides a road map which the developer should follow and implement in coding. So in a group of developers, all the code generated will be of consistent in nature and reusable by any coder/developer.
Sometimes the code is not all commented and for other cases, it’s over-commented. Maybe you have already read this phrase: Good code is self-documenting.
Yes, it’s a good practice to let the code clean to talk for himself and avoid the comments. but in the real world, it’s the not an easy task. In some cases, you need to clarify what the code does.
Low coupling is desirable because a change in one area of an application will require fewer changes throughout the entire application. In the long run, this could alleviate a lot of time, effort, and cost associated with modifying and adding new features to an application.
Functions using many other functions are very difficult to understand and maintain. It’s recommended to minimize the efferent coupling of your functions.
The single responsibility principle states that a class should not have more than one reason to change. Such a class is said to be cohesive. A high LCOM value generally pinpoints a poorly cohesive class. There are several LCOM metrics. The LCOM takes its values in the range [0-1]. The LCOM HS (HS stands for Henderson-Sellers) takes its values in the range [0-2]. A LCOM HS value highest than 1 should be considered alarming. Here are to compute LCOM metrics:
LCOM = 1 – (sum(MF)/M*F)
LCOM HS = (M – sum(MF)/F)(M-1)
- M is the number of methods in class (both static and instance methods are counted, it includes also constructors, properties getters/setters, events add/remove methods).
- F is the number of instance fields in the class.
- MF is the number of methods of the class accessing a particular instance field.
- Sum(MF) is the sum of MF over all instance fields of the class.
The underlying idea behind these formulas can be stated as follow: a class is utterly cohesive if all its methods use all its methods use all its instance fields, which means that sum(MF)=M*F and then LCOM = 0 and LCOMHS = 0.
LCOMHS value higher than 1 should be considered alarming.
There are some basic habits that could make your code clean from the beginning, don’t wait for the refactoring to make your code clean. try to do it from the beginning.