All we do is looking for some way to fulfill our needs.

środa, 29 czerwca 2011

Tagged under:

Naturalny porządek refaktoryzacji pod lupą cz. 4 Refaktoryzacja do wzorców

Stosując dotychczasowe kroki zaczynamy mieć coraz bardziej kształtne rozwiązanie, jednak głównie to co otrzymujemy to metody pogrupowane w klasy. Nadszedł czas na zastosowanie zasad obiektowych (np. zebranych w SOLID). Analizujemy kod pod kątem powtarzalności, potrzeby elastyczności, zapachów kodu i wprowadzamy wzorce projektowe. Często tam gdzie mamy wiele metod o zbliżonym schemacie będzie można zastosować Template Method lub Strategy. Tam gdzie tworzymy złożone struktury, tam stosujemy wzorzec Builder. Tam gdzie mamy do czynienia z nieskomplikowaną maszyną stanową wprowadzamy State. Tam gdzie potrzebujemy polimorficznego tworzenia obiektów używamy Abstract Factory lub jej zdegenerowanej postaci Simple Factory.
Jeśli przyjrzymy się klasie TextObfuscatorMethods z przykładu, możemy zauważyć, że większość metod przyjmuje jako parametr przetwarzany tekst. Jest to sygnał, że te metody powinny być w klasie, która ma pole zawierające przetwarzany tekst. W zasadzie możemy odwrócić sytuację i w klasie TextObfuscatorMethods umieścić pole typu przetwarzany tekst, wtedy metody staną się praktycznie bezparametrowe. Tym samym klasa nabiera charakteru wzorca Builder.
Inną opcją, pod warunkiem, że chcielibyśmy uzyskać możliwość dowolnego składania przekształceń zaciemniających tekst (stosować je wybiórczo, w dowolnej kolejności, o czym chcielibyśmy decydować w czasie wykonania), wtedy można by zastosować wzorzec Decorator.
Wersja z Budowniczym wyglądałaby jak poniżej.

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 textParts = new List();
    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);
            }
        }
    }
    // ...
}

0 komentarze: