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

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

Cleaning Up Code: Not Just About Refactoring Part 2

Due to formatting problems with code on Blogspot, it is recommended to read this article in PDF format. You can download the PDF version of the article here.

Read More

Truth Does Not Exist (Proofs Neither)

Since my response to Sławek’s post has grown quite lengthy, I decided to also publish it here. Please read his post first, as my commentary only makes sense in its context.

Read More