The Natural Order of Refactoring Under the Microscope Part 1

Table of Contents

Refactoring is an age-old problem—perhaps not the best word given the relatively short existence of software engineering as a discipline. Everyone knows refactoring should be done, but nobody seems to have the time for it.

Once you start refactoring, it’s often not enough to just refactor for the sake of it, as it’s easy to fall into a frenzy of refactoring everything at all costs. Here, I’ll present a refactoring strategy that allows for a systematic approach to this often thankless task, contributing to the evolutionary development of a project and architecture, while also suggesting how to tackle legacy code. Here are the magic points:

  1. Start Simple: Begin with a simple solution, following the principle of “Keep it simple stupid.” Don’t overthink patterns or introduce unnecessary flexibility.

  2. Extract Methods: Start extracting smaller components from large methods (refactoring known as Extract Method). Aim for the Compose Method pattern—let your main method consist of a series of smaller method calls.

  3. Analyze Class Responsibilities: When your classes consist of many small methods, start analyzing the responsibility of each class. Move methods that fulfill different responsibilities to more appropriate classes.

  4. Introduce Design Patterns: Over time, you may notice a need for flexibility in your solutions—start introducing design patterns where needed.

  5. Regularly Review Architecture: Occasionally (every few months for larger projects), analyze what’s happening with your project. Architecture requires regular refreshing and modifications to align with emerging requirements.

The idea was illustrated in a blog post here.

Let’s assume we have a class providing a method for obfuscating text, which is a parameter of the method. Here is a sample code snippet:

public class TextManager
{
    private TextManagerHelper _hlp = null;
    // ...
    public TextManager(TextManagerHelper helper)
    {
        this._hlp = helper;
    }

    private Random rnd = new Random();

    public string Convert(string text)
    {
        String result = "";
        List<TextPart> prts = _hlp.Convert(text);

        for (int i = 0; i < prts.Count; i++)
        {
            if (prts[i].Type.Equals(TextPartType.WORD) && rnd.NextDouble() < 0.2)
            {
                if (i + 2 < prts.Count)
                {
                    TextPart t = prts[i];
                    prts[i] = prts[i + 2];
                    prts[i + 2] = t;
                }
            }
        }

        for(int i1 = 0; i1 < prts.Count; i1++)
        {
            if (rnd.NextDouble() < 0.2)
            {
                prts.Insert(i1, new TextPart(" ", TextPartType.NONWORD)); i1++;
                String[] wds = new String[] { "i", "a", "aczkolwiek", "poniekąd" };
                int ind = rnd.Next(wds.Length);
                prts.Insert(i1, new TextPart(wds[ind], TextPartType.WORD)); i1++;
                prts.Insert(i1, new TextPart(" ", TextPartType.NONWORD));
            }
        }

        String result2 = "";

        foreach (TextPart part in prts)
        {
            result2 += part.Contents;
        }

        result = result2;
        result = Regex.Replace(result, @"[\?!-\.,:;'\(\)]", "", RegexOptions.CultureInvariant);

        String result1 = "";

        for ( int i2 = 0; i2 < result.Split(' ').Length - 1; i2++)
        {
            if (rnd.NextDouble() < 0.5)
            {
                char [] chs = new char[] { '.', ',', '!' };
                int j = rnd.Next(chs.Length);
                result1 += result.Split(' ')[i2] + chs[j];
            }
            else
            {
                result1 += result.Split(' ')[i2] + " ";
            }
        }
        result1 += result.Split(' ')[result.Split(' ').Length - 1];
        result = result1;

        result = result
            .Replace("ą", "a")
            .Replace("ł", "l")
            .Replace("ę", "e")
            .Replace("ń", "n")
            .Replace("ż", "z")
            .Replace("ź", "z")
            .Replace("ó", "o")
            .Replace("ś", "s")
            .Replace("ć", "c")
            .Replace("Ą", "A")
            .Replace("Ł", "L")
            .Replace("Ę", "E")
            .Replace("Ń", "N")
            .Replace("Ż", "Z")
            .Replace("Ź", "Z")
            .Replace("Ó", "O")
            .Replace("Ś", "S");

        String result3 = "";
        char[] tArray = result.ToCharArray();

        foreach (char ch in tArray) {
            if (rnd.NextDouble() < 0.3)
            {
                char? newCh = null;
                if (Char.IsLower(ch))
                {
                    newCh = Char.ToUpper(ch);
                } else
                {
                    newCh = Char.ToLower(ch);
                }

                result3 += newCh;
            }
            else
            {
                result3 += ch;
            }
        }

        result = result3.Replace(" ", "");

        return result;
    }
}

To be continued…

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

Related Posts

Master... Master...

The Role of the Scrum Master

In the real world, there are many variations of this role. Sometimes it’s a person from the team, sometimes a manager, sometimes someone from outside the team, sometimes a specialist in being a Scrum Master, and I’ve even seen it as a rotating role within the team. So, who is it really? What’s the purpose?

Read More

The Natural Order of Refactoring Examined Part 4: Refactoring to Patterns

The Natural Order of Refactoring Examined Part 4: Refactoring to Patterns

By following the steps outlined previously, we begin to see a more structured solution, predominantly consisting of methods grouped into classes. It’s now time to apply object-oriented principles, such as those encapsulated by the SOLID principles. We analyze the code for patterns of repetition, the need for flexibility, and code smells, and introduce design patterns where appropriate.

Read More

Don't Be Too Quick, Start Thinking!

Don’t Be Too Quick, Start Thinking!

Sometimes I feel like the world has become too fast. Everything happens so quickly that we switch to autopilot and stop thinking about why and for what purpose we are doing a task. Are we doing it in the way we imagined, or the way someone else suggested?

Read More