Domanda

Come rifattorizzeresti queste due classi per astrarre le somiglianze?Una classe astratta?Eredità semplice?Come sarebbero le classi sottoposte a refactoring?

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;
        }
    }
}
È stato utile?

Soluzione

A meno che tu non abbia una forte ragione per il refactoring (perché aggiungerai più classi come quelle nel prossimo futuro), la penalità di modificare il design per un esempio così piccolo e artificioso supererebbe il guadagno in manutenzione o spese generali in questo scenario.Comunque ecco un possibile progetto basato su espressioni generiche e 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));
    }
}

Altri suggerimenti

Dipende, se non hanno intenzione di fare molto di più, probabilmente li lascerei così come sono: IMHO, in questo caso, è probabile che la fattorizzazione delle cose sia più complessa.

Questa è una domanda piuttosto semplice e per me sa terribilmente di un compito a casa.

Ovviamente puoi vedere le parti comuni nel codice e sono abbastanza sicuro che puoi fare un tentativo tu stesso inserendo queste cose in una superclasse.

Potresti forse combinarli in un file Locale class, che memorizza sia il codice lingua che quello regionale, ha funzioni di accesso per regione e lingua più una funzione di analisi che consente anche stringhe come "en_gb"...

È così che ho visto gestire le impostazioni locali in vari framework.

Questi due, così come sono, non eseguiranno bene il refactoring a causa dei metodi statici.

O ti ritroveresti con una sorta di metodo factory su una classe base che restituisce un tipo di quella classe base (che successivamente richiederebbe il casting) o avresti bisogno di una sorta di classe helper aggiuntiva.

Data la quantità di codice extra e il successivo casting nel tipo appropriato, non ne vale la pena.

  1. Creare una classe base generica (es AbstractCode<T>)
  2. aggiungi metodi astratti come

    protected T GetConstructor(string code);
    
  3. sovrascrivere nelle classi base come

    protected override RegionCode GetConstructor(string code)
    {
        return new RegionCode(code);
    }
    
  4. Infine, fai lo stesso con string GetIsoName(string code), per esempio

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

Ciò effettuerà il refactoring di entrambi.Chris Kimpton solleva l'importante questione se ne valga la pena.

Sono sicuro che esista una soluzione migliore basata sui farmaci generici.Ma ci ho comunque provato.

MODIFICARE:Come dice il commento, i metodi statici non possono essere sovrascritti, quindi un'opzione sarebbe mantenerli e utilizzare oggetti TwoLetterCode in giro e lanciarli, ma, come ha già sottolineato qualche altra persona, è piuttosto inutile.

Cosa ne pensi di questo?

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);
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top