Click here to Skip to main content
15,886,137 members
Articles / Programming Languages / C#
Tip/Trick

Refactor Like a Boss: Break the Classes

Rate me:
Please Sign up or sign in to vote.
4.71/5 (8 votes)
18 Apr 2016CPOL1 min read 10.1K   31   1   3
A tip for getting the most out of your refactoring practice

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:

  1. Squares
  2. Circles
C#
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.

C#
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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionInterfaces. Pin
mbb015-May-16 22:23
mbb015-May-16 22:23 
As well as discussing how inheritance comes into play, you might want to discuss how an interface can be used in the refactoring.

The GetArea() signatures are different as well, so at the moment you don't have a consistent contract for the action.
QuestionWhy cant we use Inheritance Pin
iamramt18-Apr-16 21:22
iamramt18-Apr-16 21:22 
AnswerRe: Why cant we use Inheritance Pin
debashishPaul19-Apr-16 1:12
professionaldebashishPaul19-Apr-16 1:12 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.