Question

Comment refactoriez-vous ces deux classes pour en extraire les similitudes? Une classe abstraite? Un héritage simple? À quoi ressemblerait la ou les classes refactorées?

public class LanguageCode
{
    /// <summary>
    /// Get the lowercase two-character ISO 639-1 language code.
    /// </summary>
    public readonly string Value;

    public LanguageCode(string language)
    {
        this.Value = new CultureInfo(language).TwoLetterISOLanguageName;
    }

    public static LanguageCode TryParse(string language)
    {
        if (language == null)
        {
            return null;
        }

        if (language.Length > 2)
        {
            language = language.Substring(0, 2);
        }

        try
        {
            return new LanguageCode(language);
        }
        catch (ArgumentException)
        {
            return null;
        }
    }
}

public class RegionCode
{
    /// <summary>
    /// Get the uppercase two-character ISO 3166 region/country code.
    /// </summary>
    public readonly string Value;

    public RegionCode(string region)
    {
        this.Value = new RegionInfo(region).TwoLetterISORegionName;
    }

    public static RegionCode TryParse(string region)
    {
        if (region == null)
        {
            return null;
        }

        if (region.Length > 2)
        {
            region = region.Substring(0, 2);
        }

        try
        {
            return new RegionCode(region);
        }
        catch (ArgumentException)
        {
            return null;
        }
    }
}
Était-ce utile?

La solution

Sauf si vous avez une bonne raison de refactoriser (parce que vous allez ajouter plus de classes que dans un futur proche), la pénalité de changer la conception pour un exemple aussi petit et artificiel permettrait de surmonter le gain de maintenance ou de frais généraux de ce scénario. . Quoi qu’il en soit, voici un modèle possible basé sur des expressions génériques et lambda.

public class TwoLetterCode<T>
{
    private readonly string value;

    public TwoLetterCode(string value, Func<string, string> predicate)
    {
        this.value = predicate(value);
    }

    public static T TryParse(string value, Func<string, T> predicate)
    {
        if (value == null)
        {
            return default(T);
        }

        if (value.Length > 2)
        {
            value = value.Substring(0, 2);
        }

        try
        {
            return predicate(value);
        }
        catch (ArgumentException)
        {
            return default(T);
        }
    }

    public string Value { get { return this.value; } }
}

public class LanguageCode : TwoLetterCode<LanguageCode>  {
    public LanguageCode(string language)
        : base(language, v => new CultureInfo(v).TwoLetterISOLanguageName)
    {
    }

    public static LanguageCode TryParse(string language)
    {
        return TwoLetterCode<LanguageCode>.TryParse(language, v => new LanguageCode(v));
    }
}

public class RegionCode : TwoLetterCode<RegionCode>
{
    public RegionCode(string language)
        : base(language, v => new CultureInfo(v).TwoLetterISORegionName)
    {
    }

    public static RegionCode TryParse(string language)
    {
        return TwoLetterCode<RegionCode>.TryParse(language, v => new RegionCode(v));
    }
}

Autres conseils

Cela dépend, s'ils ne vont pas faire beaucoup plus, je les laisserais probablement tels quels - IMHO factoriser des choses est susceptible d'être plus complexe, dans ce cas.

C'est une question assez simple et pour moi, ça sent terriblement comme un devoir.

Vous pouvez évidemment voir les éléments communs du code et je suis sûr que vous pouvez le tenter vous-même en plaçant ces éléments dans une super-classe.

Vous pourriez peut-être les combiner dans une classe Locale, qui stocke à la fois le code de langue et le code de région, a des accesseurs pour Région et langue plus une fonction d'analyse qui permet également des chaînes comme & "; en_gb &" ; ...

C'est comme ça que j'ai vu les paramètres régionaux être gérés dans différents cadres.

Ces deux éléments, dans leur état actuel, ne vont pas bien se reformer à cause des méthodes statiques.

Vous pourriez vous retrouver avec une sorte de méthode d'usine sur une classe de base qui retourne un type de cette classe de base (qui aurait par la suite besoin d'être transtypé) ou bien une sorte de classe d'assistance supplémentaire.

Compte tenu de la quantité de code supplémentaire et de la conversion ultérieure vers le type approprié, cela ne vaut pas la peine.

  1. Créer une classe de base générique (par exemple AbstractCode<T>)
  2. ajouter des méthodes abstraites comme

    protected T GetConstructor(string code);
    
  3. remplacer dans les classes de base comme

    protected override RegionCode GetConstructor(string code)
    {
        return new RegionCode(code);
    }
    
  4. Enfin, faites de même avec string GetIsoName(string code), par exemple

    protected override GetIsoName(string code)
    {
        return new RegionCode(code).TowLetterISORegionName;
    }
    

Cela va refactoriser les deux. Chris Kimpton pose la question importante de savoir si l'effort en vaut la peine.

Je suis sûr qu'il existe une meilleure solution basée sur les génériques. Mais toujours donné un coup de feu.

EDIT: Comme le commentaire le dit, les méthodes statiques ne peuvent pas être remplacées. Une option consiste donc à les conserver et à utiliser les objets TwoLetterCode pour les lancer, mais comme une autre personne l’a déjà fait remarquer, cela est plutôt inutile.

Comment ça?

public class TwoLetterCode {
    public readonly string Value;
    public static TwoLetterCode TryParseSt(string tlc) {
        if (tlc == null)
        {
            return null;
        }

        if (tlc.Length > 2)
        {
            tlc = tlc.Substring(0, 2);
        }

        try
        {
            return new TwoLetterCode(tlc);
        }
        catch (ArgumentException)
        {
            return null;
        }
    }
}
//Likewise for Region
public class LanguageCode : TwoLetterCode {
    public LanguageCode(string language)
    {
        this.Value = new CultureInfo(language).TwoLetterISOLanguageName;
    }
    public static LanguageCode TryParse(string language) {
        return (LanguageCode)TwoLetterCode.TryParseSt(language);
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top