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

Conversation with the Client

First Conversation with the Client

Today marks the beginning of a new project. As always in such cases, there is a hint of excitement in the team, as well as attempts to guess what the project will be about. We have some information, but nothing is certain yet.

Read More

Building Knowledge in a Team: Main Mistakes and Strategies

Introduction

For IT leaders, the topic of knowledge management is often unexplored territory. There is a silent assumption that it happens on its own. While it’s true to some extent, as software developers, we constantly need to learn new things to stay relevant. However, it’s not enough if only some team members learn independently. For a team to work efficiently, they need consistent and up-to-date knowledge. Cutting-edge technology skills alone have limited value.

Read More

Time for Non-Violent Rebel

The Deficit of Humanity in Agile Practice

Agile thinking has been with us for several years. There is a lot of humanity behind Agile thinking, and this is what is great about it. But Agile, like every idea, is just that—an idea. It is not easily applicable in life and often distorted to be convenient, though not necessarily useful. People focus on practices and lose the spirit of the idea. Agile is just an example. All in all, the problem is the deficit of humanity in the business context.

Read More