Action
Break the candidate
class into multiple smaller classes.
Inspiration
Single Responsibility Principle from SOLID. Deals with God Class anti-pattern.
Identifying
To identify the candidates for this kind of refactoring, while reviewing a class
you need to ask yourself what are the responsibilities of the class? If the answer is something like "What responsibilities? My class has only one responsibility, it does only this.", wonderful. But if the answer is "My class does this and that?", we have a problem. We need to separate "this" from "that" in two different class.
How
Let's consider that we have a AreaCalculator
class and its responsibility is to calculate the area of the shape passed as argument. Pretty simple, huh? Okay, now for the sake of simplicity, let's say there are only two kinds of shapes:
- Squares
- Circles
public class AreaCalculator
{
private int sideOrRadius;
private string shapeType;
public AreaCalculator(int sideOrRadius, string shapeType)
{
this.sideOrRadius = sideOrRadius;
this.shapeType = shapeType;
}
public double GetArea()
{
if (shapeType == "circle")
{
return 3.14 * sideOrRadius * sideOrRadius;
}
else if (shapeType == "square")
{
return sideOrRadius * sideOrRadius;
}
return 0;
}
}
Now, ask yourself what your class is truly doing. It is calculating the area of the shapes. What are shapes? Squares and circles.
So, your class is calculating area of squares and calculating area of circles which is too many things to do for a class. We need to break functionality for circles and squares apart. Consider the classes below.
public class Square
{
private int side;
public Square(int side)
{
this.side = side;
}
public int GetArea()
{
return side * side;
}
}
public class Circle
{
private int radius;
public Circle(int radius)
{
this.radius = radius;
}
public double GetArea()
{
return 3.14 * radius * radius;
}
}
Now, that we have two classes, their responsibilities are also divided in two parts. Now we don't have any God Class which needs to know the existence of every shapes existing on the face of the earth and how to calculate their area.
Opportunity
Breaking class practice opens up the opportunity to implement the Open-Close principle. Previously, if we need to add a new shape, we had to modify the existing AreaCalculator
class. Now, we can just implement a new class without even touching the Square
and Circle
class.