How to Use Extract Class Refactoring to Create Amazing Code


If you’re a programmer, you’re probably familiar with the Extract Method technique.

This is a very helpful refactoring that can be used when you need to modularize a piece of code that’s getting too big and too complicated.

But what if you need to break up a huge class into smaller, more manageable pieces? That’s where the Extract Class refactoring comes in. It’s a powerful tool that can be used to simplify your code.

Extract Class is a refactoring technique in which you move functionality from one class to another, creating a new class in the process. This is often done to move functionality from a large, monolithic class to a smaller, more focused class.

It’s also a great way to remove messy code that’s difficult to maintain.

In this blog post, I’ll show you how to use the extract class refactoring to create amazing code in the blink of an eye.

Overview of the Extract Class code refactoring

When designing a system, it’s important to keep it as simple as possible to make it easy to change.

This is often accomplished by breaking down the system into components and applying the single responsibility principle to each component.

One powerful technique for achieving this is by extracting a class. Extract Class is a refactoring that moves a group of methods from one class to a new class.

When you extract a class, you pull the code outside of the original class to a new class. You create a new class and move methods and fields from the original class. Then you pass the instance of the new class into the original class. This is a great way to create code that’s more reusable since you can use the extracted class in other places in your code.

This refactoring can be helpful when a class has become too large or complex and is difficult to understand or maintain. You can also use it to improve code organization, making it easier to find and use the code you need.
You can use Extract Class to create a new class that is a more specialized version of an existing class.
For example, if you have a class representing a general shape, you could extract a new class representing only circles. This would be useful if you needed to add functionality specifically for circles, such as a method to calculate the circumference. By extracting a new class, you can keep the existing code for the general shapes class unchanged and add the new code for the circle class.

The other example of using this refactoring is if you have two classes that have the same methods and those methods have the same logic. What you can do is extract the methods into a new class and make the old classes call the new class.

How do you use the Extract Class?

Use the following refactoring process:

  1. Identify methods and properties in the existing class you want to move to another class.
  2. Create a new class and name it accordingly.
  3. Create a connection between the existing class and the new class. Usually, an instance of the new class is created or passed to the old class.
  4. One by one, move methods, fields, and properties using Move Method and Move Field refactorings.
  5. Test that the code still works correctly after every change.
  6. Optionally, you can create a new interface for the new class. And use that interface in the existing code.

After you are done, take a look at the original class. Maybe it needs to be renamed since you have taken away some responsibilities from it.

Extracting a class is an important refactoring.

Here’s a simple example.

Extract class – Example

We have the following Person class:

class Person
{
    internal string Name { get; set; }
    internal string TelephoneNumber { get; set; }
    internal string Email { get; set; }
    //Address Details
    internal string Street { get; set; }
    internal int HouseNumber { get; set; }
    internal string City { get; set; }
    internal string PostalNumber { get; set; }
    internal string Country { get; set; }

    internal string GetFullAddress()
    {
        return $"{Street} {HouseNumber}, {PostalNumber} {City}, {Country}";
    }

    internal bool FreeDelivery()
    {
        return int.Parse(PostalNumber) < 40000;
    }

    //Other person methods here...
}

The Person class has many methods and properties. Let’s focus on moving the address details properties to a new class. We want to move the following properties:

  • Street
  • HouseNumber
  • City
  • PostalNumber
  • Country

The first step is to create a new class called AddressDetails:

class AddressDetails 
{       
}

And instantiate this class in the Person class.

public Person()
{
    Address = new AddressDetails();
}

internal AddressDetails Address { get; set; }

I have also created a property called Address so I can use this instance through the code.

The next step is to move properties from the Person class to the new class. You can do that one by one property. I will show you the final result, once all 5 properties are moved.

class AddressDetails 
{
    internal string Street { get; set; }
    internal int HouseNumber { get; set; }
    internal string City { get; set; }
    internal string PostalNumber { get; set; }
    internal string Country { get; set; }
}

Now you can start using the properties of the AddressDetails class in the existing code.

internal string GetFullAddress()
{
    return $"{Address.Street} {Address.HouseNumber}, {Address.PostalNumber} {Address.City}, {Address.Country}";
}

Once you have removed all references from the address details properties of the Person class, you can remove those properties.

The end result, this is how the Person class looks now:

class Person
{
    public Person()
    {
        Address = new AddressDetails();
    }

    internal AddressDetails Address { get; set; }
    internal string Name { get; set; }
    internal string TelephoneNumber { get; set; }
    internal string Email { get; set; }

    internal string GetFullAddress()
    {
        return $"{Address.Street} {Address.HouseNumber}, {Address.PostalNumber} {Address.City}, {Address.Country}";
    }

    internal bool FreeDelivery()
    {
        return int.Parse(Address.PostalNumber) < 40000;
    }

    //Other person methods here...
}

The next refactoring is to move the GetFullAddress method to the AddressDetails class, but you can see how to do that in the Move Method refactoring post.

Benefits of using the Extract Class refactoring?

There are a lot of benefits to the extract class refactoring, but I’ll focus on the top 3:

  1. Separation of concerns – The first benefit is that it separates code into multiple classes. As a result, one class only contains methods related to one functionality.
  2. Reusability of the code – The next benefit of this refactoring is the reusability of the code. This refactoring allows you to extract the duplicate code blocks into a new class. So you can reuse the code blocks that you extracted in other places in your code.
  3. Code cohesion – Another benefit of this refactoring is that it allows you to keep related code together. This means that when you’re looking at the code, one class wraps all methods and properties related to one functionality. Everything else belongs to a separate class.

Drawbacks of the Extract Class refactoring

Extracting classes, in general, is a good idea. It can remove a lot of duplicate code from your project and improves the readability of your code. But, sometimes, you have to be careful about what classes you extract.

When your code is not in good shape, you should extract the new classes. But don’t overuse this refactoring and extract every single method into a separate class. This will result in having too many classes. Navigation through the project will be too complicated, and every class will likely have a dozen of injected dependencies.

If you realize that Extract Class wasn’t the right approach for your codebase, you can use the Inline Class refactoring to bring the two classes together.

Conclusion

It’s not enough to just write good code. You want to write great code. To do that, you need to refactor your code to make it better. 

But how?

The Extract Class refactoring is a powerful one that can help you make your code cleaner and more readable. This is a great way to simplify and organize your code, as you can use the new class easier in other places in your existing project. Or the other projects. The sky is the limit.

FAQ

When would you decide to extract a class?

You might extract a class if the existing code becomes too complicated and you can’t figure out how to simplify it any further. Extracting a class is also a good idea when you don’t need to change the implementation of a code, but the same code is being duplicated in more than one place.

Does Visual Studio have a built-in refactoring command for this refactoring?

No, Visual Studio 2022 has many built-in refactoring tools, but it doesn’t support Extract Class.

How much code to extract?

A good rule of thumb is to perform this refactoring if you have identified at least two methods that you could extract. But ultimately, the decision depends on the type of class you’re refactoring and the goal of the refactoring.

Recent Posts