Code Bloats or Code Bloaters are probably the most common signs of code smells you can see in any branch of code. In fact, eradicating bloaters act as the first step towards refactoring your code. Bloaters are nothing but classes or methods that have grown excessively over a long time marking it difficult to work with. Typically, bloaters doesn’t happen right away, but is accumulate long term as your code base grows.
In this blog post, we will be discussing two of the most common bloaters, Long Method and Long Class
It is recommended that any method which is longer than 10 lines of code is a good candidate for refactoring. One could Extract Code Fragments (that does a specific task and relates to each other than any other piece of code in the method) that can be grouped together to a new Method (Extract Method), even if the new method is hardly couple of lines. It could also help in reducing code duplication and isolating independent parts of code.
Another refactoring technique that could be applied for Long Methods is Separating Query from Modifiers . It would be better to segregate the code fetching data from that modifies/mutates a state. The crux of this technique is based on the Command Query Seperation (CQS) Principle. CQS recommends dividing an object’s method into two broad categories, Queries (Returns a result, but doesn’t change any observable state) and Commands (changes observable state but doesn’t return a value). An observable state of an object is a state which can be accessed by the client code. However, care should be taken to avoid race condition that comes along the CQS approach in a multi-threaded application.
There might be certain scenario’s as well where the local variables are so intertwined with the code that it becomes difficult to extract method. In such scenarios, it might be a good idea to Replace Method with a Method Object, or in other words separate the Long Method into a Separate class, where the local variables of the class becomes Fields variables of the new class. Then it becomes much easier to split the method to smaller chunks of code.
Conditional Operators such as If-else or Switch Cases is another place where you could cut down the Method. You could either opt for refactoring techniques such as Decompose Conditional or use Strategy Pattern. Usage of Strategy Pattern also helps in bringing down the Cyclomatic Complexity of the Method.
Large Class, similar to Long Methods are another undesired quality accumulated over time. Developers find it more convenient to add methods to existing classes than creating a new one. This results in Classes which cluttered with large number of methods and fields.
It is always better to split up a large class (Extract Class), especially if it has more than one responsibility. This ensures the class aligns with Single Responsibility Principle. There might be other cases where , there might be a class which utilizes a subset of its feature only in certain special scenarios. For Example consider the following code.
public class Person
if(PersonType == PersonType.Student)
// Do Something
if(PersonType == PersonType.Faculty)
// Do Something
In the above class, despite being related to the Person Class and sharing many other features with it, methods PublishMarks and PublishSalary are used only when the PersonType is Student or Faculty respectively. In this scenario, separating an entirely new Class for Student and Faculty isn’t quite recommended. Instead, we could take advantages of Inheritence and creates subclasses of Person Class, separating the Student and Faculty functionalities to SubClass. This technique is refactoring is known as Extracting SubClass.
Another scenario that is worth mentioning is cases when Domain (Business) Logic and Data gets embedded in the UI (Presentation) class. Problem with this approach is that you might end up with lot of duplicate code as the same domain objects might be required at other places in Presentation Classes. The refactoring technique, Duplicate Observed Data, recommends to remove Domain Data to separate classes and use an Observer pattern to synchronize the classes.
In the next of this series, we will look into few more Bloaters, including Primitive Obsession, Long Parameter List and Data Clumps.