Like many other things in life, our code needs some discipline too. I’m pretty sure no developer in the world wants to write unclean code. However, unclean code still does exist. It can arise due to various reasons - may be due to business pressure, lack of documentation, lack of interaction among team members or incompetence of the developer. Due action needs to be taken to make the code cleaner and to avoid problems that may come up in the future because of this. Fortunately, we can tackle these issues with a disciplined technique to restructure the code called as Refactoring.
Refactoring is a technique to improve the internal structure of the existing program source code and maintaining its external behavior. It is a step-by-step procedure to improve the code, which will otherwise cost us a lot of time and effort.
Disadvantages of Unclean Code
Expanding the source code size by adding new programs to it without refactoring for a long time makes the code messy and unclean. It makes the maintenance and further development on the project very difficult. Unclean code comes with tons of disadvantages:
- It increases the maintenance cost of the project.
- Adding new feature takes a lot of time and sometimes it become impossible to add.
- It slows down the introduction of new people to the project.
- It contains duplicate code.
- It does not pass all tests.
There are many other disadvantages, but these problems cost a lot of money and time to the organization.
Advantages of Clean Code
Clean and disciplined code has its own advantages:
- It does not contain duplicate code.
- It passes all tests.
- Makes the code more readable and easier to comprehend.
- It makes the code easier to maintain and less expensive.
Advantages of clean code are many. The process of turning a messy unclean code into a more maintainable clean code is called Refactoring process.
Refactoring Process
Refactoring should be done as a series of small changes, each of which slightly improves the existing code and allows the program to continue to run without breaking it. After refactoring, code should become cleaner than before. If it remains unclean, then there is no point of refactoring. It is just a loss of time and effort. No new code should be added during refactoring to create new functionality. It should pass all the tests after refactoring.
When to Refactor
Refactoring should be performed when:
- Adding duplicate code to the project. Because duplicate code is hard to maintain and changes in one place may require updates in many other places.
- Adding a feature. Refactoring makes it easier to add new functionality.
- When fixing a bug, you should refactor because it will make the bug discovered automatically.
- Code review is the last stage of refactoring the code before changes are deployed to production.
Dealing with Code Smells
Problems on the code are sometimes referred to as code smells. These are the problems addressed during the refactoring. They are easier to find and fix.
For example:
- Large methods and classes which are very hard to work with.
- Incomplete or incorrect usage of object-oriented programming concept.
- Code that makes it hard to add any changes.
- Duplicate and deprecated code in the project.
- Highly coupled code.
Refactoring Techniques
Refactoring techniques are the steps taken to refactor the code. Some of the refactoring techniques are:
1. The Extract Method
// Problem
function printInvoice() {
$this->printHeader();
// Print details.
print("name: " . $this->name);
print("amount " . $this->getPrice());
}
// Solution
function printInvoice() {
$this->printBanner();
$this->printDetails($this->getPrice());
}
function printDetails($price) {
print("name: " . $this->name);
print("amount " . $outstanding);
}
If you have a code fragment that can be grouped, add a new method for that part of code and replace the old code. It makes the code more isolated and removes duplication.
2. Extract Variable
// Problem
if (($student->getMarksinMath() > 60) &&
($student->getMarksInPhysics() > 60) &&
($student->getMarksinChemistry() > 60) && $this->pass)
{
// do something
}
// Solution
$mathResult = $student->getMarksinMath() > 60;
$physicsResult = $student->getMarksinPhysics() > 60;
$chemistryResult = $student->getMarksinChemistry() > 60;
$hasPassed = $this->pass;
if ($mathResult && $physicsResult && $chemistryResult && $hasPassed) {
// do something
}
For large expressions like the one displayed in the problem, which is very hard to understand, different variables can be created for each expression. It makes the code more readable. But this method should be applied with caution. However, it has its own disadvantages. The code will execute even if the condition is false which is not the case in the problem.
3. The Inline Method
// Problem
function printResult() {
return ($this->getResult()) ? “Pass” : “Fail”;
}
function getResult() {
return $this->totalMarks > 300;
}
// Solution
function getRating() {
return ($this->totalMarks > 300) ? “Pass” : “Fail”;
}
When the method body is more obvious, use this technique. Replace the method with method content and delete the method. It minimizes the number of unwanted methods.
4. Inline Temp
// Problem
$mathMark = $student->getMathResult();
return $mathMark > 60;
// Solution
return $student->getMathResult() > 60;
If there is an unwanted temporary variable which just holds the expression result, remove the variable with the expression itself. It helps in getting rid of unnecessary variables.
5. Replace array with object
// Problem
$row = [];
$row[0] = "Virat Kohli";
$row[1] = 70;
// Solution
$row = new Player();
$row->setName("Virat Kohli");
$row->setNumberofCentury(70);
If there is an array with various types of data, replace that with an object. Because fields of a class are easier to document and maintain than arrays with various types of data.
6. Parameterized Method
// Problem
function fivePercentRaise() {
}
function tenPercentRaise() {
}
// Solution
function raise(percent) {
}
If multiple methods perform similar action on data, then replace all the methods with one method and pass the data as argument(s). It removes duplicate and redundant methods.
7. Separate query from modifier
// Problem
function getInterest() {
$this->interestAmount = $this->principal * 10 / 100;
return $this->interestAmount;
}
// Solution
function setInterest() {
$this->interestAmount = $this->principal * 10 / 100;
}
function getInterest() {
return $this->interestAmount;
}
If a method is returning value and changing the object, split the two methods. One for modification and another to return the result. It removes the chance of unintentional modification of an object.
Unclean and chaotic code leads to technical debt that keeps adding up if not tackled right. And a debt always means a loss. Refactoring the code is a technique that can help fight issues that leads to bad and smelly code. Need help or more information on refactoring your code? Contact Specbee’s specialists today!