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

Table of Contents

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.

In cases where we have many methods with similar patterns, we can potentially use the Template Method or Strategy pattern. When constructing complex structures, the Builder pattern is appropriate. For dealing with simple state machines, the State pattern is beneficial. When polymorphic object creation is necessary, you might use the Abstract Factory or its degenerated form, the Simple Factory.

Example: Refactoring Text Obfuscation Methods

If we observe the TextObfuscatorMethods class from our example, we notice that most methods take the processed text as a parameter. This is an indication that these methods should reside in a class containing a field for the processed text. Essentially, we can invert the situation by placing a field for the processed text within the TextObfuscatorMethods class, thereby making the methods practically parameterless. This gives the class the characteristics of a Builder pattern.

An alternative approach, under the condition that we want the flexibility to compose obfuscating transformations selectively and in any order during execution, would be to apply the Decorator pattern.

Builder Pattern Example:

public class TextObfuscator
{
    private ObfuscatedTextBuilder builder = null;
    // ...
    public string Obfuscate(string text)
    {
        builder.NewText(text);

        builder.ChangeWordsOrderRandomly();
        builder.AddMeaninglessWordsRandomly();
        builder.RemoveSeparators();
        builder.AddSeparatorsRandomly();
        builder.RemoveSpaces();
        builder.ReplacePolishCharactersWithNonPolish();
        builder.ReplaceUpperAndLowercase();

        return builder.ToString();
    }
}

public class ObfuscatedTextBuilder
{
    // ...
    private List<string> textParts = new List<string>();

    public virtual void NewText(string text)
    {
        this.textParts = ParseTextForWordsAndNonWords(text);
    }

    // ...
    public virtual void RemoveSpaces()
    {
        for (int i = 0; i < textParts.Count; i++)
        {
            RemoveSpacesFromTextPart(textParts, i);
            RemoveTextPartIfEmpty(textParts, i);
        }
    }

    public virtual void AddMeaninglessWordsRandomly()
    {
        for (int i = 0; i < textParts.Count; i++)
        {
            if (ShouldAddMeaninglessWords())
            {
                textParts.Insert(i, TextPart.SpaceSeparator); i++;
                textParts.Insert(i, new TextPart(DrawMeaninglessWord(), TextPartType.WORD)); i++;
                textParts.Insert(i, TextPart.SpaceSeparator);
            }
        }
    }
    // ...
}

By employing these design patterns, we enable greater flexibility in our code, helping to achieve cleaner, more maintainable solutions.

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

Related Posts

Code Cleanup: Not Just About Refactoring

Introduction

Blogspot unfortunately disappoints me when it comes to publishing source code, which is especially important for topics concerning coding style. Perhaps some of you have experience or ideas on this matter. I use the tool http://formatmysourcecode.blogspot.com/2006/02/paste-your-text-here.html, but still, Blogspot occasionally distorts the post.

Read More

Technical Leader Worries: To Be a Tech Expert or Not to Be

The majority of IT leaders are promoted IT specialists. Many times, this happens surprisingly, and we are usually not well prepared for this change. We love our tech job—programming—and suddenly someone wants to take it from us. Of course, we are free people and can say “NO,” but it doesn’t happen too often. Becoming a leader may be the next real step in our career, a new opportunity to learn something completely different.

Read More

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

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.

Read More