The Natural Order of Refactoring Under the Microscope Part 3: Extract Method

Table of Contents

Analyzing Class and Method Responsibilities

In the next step, we examine the responsibilities of individual classes and methods, checking if they align with the intended responsibility of the class. It is best to analyze all methods and group them based on performing similar operations. We look for a place for these in other classes or a new class. Remember: if there is a significant private method in a class (longer than 3-4 lines), it should be moved to another class.

Example: Extracting Methods for Clarity

In our example, the methods mainly revolve around discrete operations aimed at obfuscating text and ensuring operations are performed with a certain probability. We can extract classes corresponding to these operations: TextObfuscatorMethods and Probability.

Refactored Code Example

The code after this change might look like this:

public class TextObfuscator
{
    // ...
    public string Obfuscate(string text)
    {
        List<TextPart> parts = methods.ParseTextForWordsAndNonWords(text);
        methods.ChangeWordsOrderRandomly(parts);
        methods.AddMeaninglessWordsRandomly(parts);
        methods.RemoveSeparators(parts);
        methods.AddSeparatorsRandomly(parts);
        methods.RemoveSpaces(parts);
        // ...
    }
}

public class TextObfuscatorMethods
{
    // ...
    public virtual void RemoveSpaces(List<TextPart> parts)
    {
        for (int i = 0; i < parts.Count; i++)
        {
            RemoveSpacesFromTextPart(parts, i);
            RemoveTextPartIfEmpty(parts, i);
        }
    }

    private static void RemoveSpacesFromTextPart(List<TextPart> parts, int i)
    {
        parts[i] = parts[i].ReplaceContents(" ", "");
    }

    public virtual void RemoveSeparators(List<TextPart> parts)
    {
        for (int i = 0; i < parts.Count; i++)
        {
            RemoveSeparatorsFromTextPart(parts, i);
            RemoveTextPartIfEmpty(parts, i);
        }
    }

    public virtual void AddSeparatorsRandomly(List<TextPart> parts)
    {
        for (int i = 0; i < parts.Count; i++)
        {
            if (ShouldAddSeparator())
            {
                parts.Insert(i, TextPart.NewSeparator(DrawSeparator())); i++;
            }
        }
    }

    private bool ShouldAddSeparator()
    {
        return probability.ShouldBeDone(ADDING_SEPARATOR_PROBABILITY);
    }
    // ...
}

public class Probability
{
    private Random random = new Random();

    public bool ShouldBeDone(double probability)
    {
        if (probability < 0.0 || probability > 1.0)
        {
            throw new ProbabilityException("Probability should be in range [0.0, 0.1]");
        }

        return random.NextDouble() < probability;
    }
}

This refactoring approach helps to maintain a clean codebase by ensuring that each class has a single responsibility and methods are organized according to their functionalities.

(Text translated and moved from original old blog automatically by AI. May contain inaccuracies.)

Related Posts

Don't Let Conflicts Overwhelm You

Introduction

During a job interview, a candidate for a team leader position once mentioned that he managed to fulfill his role without conflicts. This statement raises suspicions. A lack of conflicts is a symptom that requires special attention. Project life is full of conflicts, and it is crucial to let them occur so that solutions satisfying both parties can be found.

Read More
Deconstructing LLM Agents for software engineers - Beyond the Hype

Deconstructing LLM Agents for software engineers - Beyond the Hype

Introduction

Agents, agents, agents everywhere. To be clear: AI agents. Oh, sorry—to be precise, LLM agents. A lot of buzz surrounds these agents. They were called the most important AI innovation of 2024, and now they’re touted as the hottest topic of 2025. But is this something we truly need? What exactly are they? Are all agents the same? Let’s dive deeper into the subject.

Read More

Make Room for Progress...

From the collection Poetry for Project Enthusiasts

Make Room for Progress

There is never a good time for the first child,
There is never a good time for the second child,
There is never a good time to build a house,
There is never a good time for renovations,
There is never a good time for a wedding,
There is never a good time to introduce refactoring,
And there is never a good time to start writing unit tests.
In each of these cases, you simply need to make a decision,
Start doing it, and time and resources will appear,
Because they will have to…

Read More