Design di classe per oggetto internazionalizzato

2

Sto cercando alcuni suggerimenti sulla progettazione della classe per un'applicazione globale.

Diciamo che devo creare una struttura di classe per gestire i prodotti e che i prodotti sono venduti in paesi diversi. Alcuni dei campi per il prodotto avranno lo stesso valore in tutti i paesi (ad esempio codice prodotto, descrizione ERP). Chiamerò questi campi "internazionali" e alcuni campi saranno specifici per un singolo paese (ad esempio Descrizione locale), lascia chiamare questi campi "locali". Ovviamente, alcuni campi "locali" saranno uguali per gruppi di paesi (es: peso: 1 chilogrammo / 2 libbre). Inoltre, mi aspetto che non tutti i Paesi abbiano valori per tutti i campi.

Quali campi sono "internazionali" e quali campi "locali" possono cambiare da un'installazione all'altra e io sono riluttante a inserire questo aspetto nel design perché sono sicuro che mi morderà più tardi.

Quindi, sto cercando di capire come strutturare gli oggetti in modo da poter utilizzare un prodotto a livello internazionale e fare sempre riferimento allo stesso "prodotto", ma anche mantenere e utilizzare le informazioni locali quando necessario?

Per essere chiari, non sto parlando di impostazioni locali dell'utente, numero o data, ecc. I dati sorgente provengono da diversi schemi di database (uno per ogni paese). Il prodotto finale sarà scritto in C #.

Mi chiedo se qualcuno ha esperienza o può indicarmi un modello che potrebbe fornire una buona soluzione prima di andare a reinventare la ruota?

    
posta Nick B. 02.08.2012 - 11:51
fonte

4 risposte

1

Suppongo tu abbia un database di qualche tipo. Creo una classe factory che crea gli oggetti (ad esempio Product ) dai dati nel database.

Diciamo che stai progettando la classe Product . Ha alcuni dei tuoi campi internazionali:

public class Product
{
    private string ean;
}

Per cose internazionalizzate come i pesi, scriverei alcune strutture Weight che ti permettono di impostare l'unità (sterline, chilogrammi). Usa un'unità di peso coerente nel tuo database (ad esempio i chilogrammi) e usala per creare l'oggetto. Quindi codifica il tuo ToString per restituire il valore localizzato nell'unità specificata. Questo è simile al modo in cui DateTime può richiedere una data / ora in UTC e "localizzato" al fuso orario dell'utente.

Quando non c'è peso, usa ad esempio un peso di -1 e dichiara questo come static readonly Weight None = new Weight(-1) .

public class Product
{
    private string ean;
    private Weight weight;
    private DateTime availableFrom;
}

public struct Weight
{
    private static readonly Weight None = new Weight(-1);

    private int weightInKG;

    public Weight(int weightInKG)
    {
        this.weightInKG = weightInKG;
    }

    public WeightUnit Unit
    { get; set; }

    public string ToString()
    { /* Implement */ }
}

Quindi, se hai pezzi di testo che sono localizzati (tradotti), allora userei solo le stringhe. La classe factory dovrebbe ottenere la stringa localizzata appropriata dal database. Se non esiste una stringa di questo tipo, utilizza null .

public class Product
{
    private string ean;
    private Weight weight;
    private DateTime availableFrom;
    private string description;
}

Infine, se hai informazioni che vengono sempre utilizzate insieme localizzate (ad esempio, specifiche per il prodotto), crea una classe Specs (o una gerarchia SpecsBase MonitorSpecs HardDiskSpecs se ci sono più tipi) per questo. Quando non ce ne sono, usa null . Puoi condividere questi oggetti tra più prodotti se le informazioni sono le stesse. Ancora una volta, la fabbrica dovrebbe occuparsi di crearla.

Puoi anche usare questi oggetti per i campi che potrebbero essere internazionali o locali a seconda dell'installazione.

public class Product
{
    private string ean;
    private Weight weight;
    private DateTime availableFrom;
    private string description;
    private Specs specs;
}

Per tutti gli oggetti, sostituisci il metodo ToString per restituire le stringhe (localizzate) corrette.

    
risposta data 02.08.2012 - 14:36
fonte
0

Vorrei creare una classe con tutti i campi necessari, quindi delegare la creazione dell'istanza a una fabbrica. La factory creerà le istanze della classe in base ai criteri locali individuati che sono i migliori (se specifichi le impostazioni internazionali nel metodo create o specifichi una locale nel costruttore della fabbrica). La fabbrica manterrà tutta la logica per assemblare oggetti da qualunque tavolo tu abbia. È possibile avere diverse strategie per gestire valori mancanti o predefiniti (se questi variano in base alle impostazioni locali) e quali campi sono "localizzati". Questo concentra tutta la logica in un posto, ma ti dà una buona flessibilità.

    
risposta data 02.08.2012 - 14:11
fonte
0

Definisci una tabella per i prodotti che contiene
ProductCode, ERP Description e altri campi "costanti".

Definire una tabella per le proprietà che contiene solo 4 colonne:
PropertyId(long),
PropertyOwnerId(long),
PropertyType(int, predefined in C# code, enumeration for instance),
PropertyValue(nvarchar, will be parsed depending on PropertyType in C# code, Object in C# code) .

Questo è sufficiente per legare le proprietà con i loro proprietari. Successivamente, se le proprietà cambiano, tutto ciò che devi fare è inserire nuovi record nella seconda tabella.

Le classi dovrebbero avere la stessa struttura. Questo design è un po 'scomodo per il fatto che dovrai analizzare una proprietà letta da DB o lanciare una proprietà nel codice C #, ma è estremamente flessibile.

P.S se ritieni che alcuni dei campi "costanti" possano cambiare, inseriscili come proprietà nella seconda tabella.

    
risposta data 02.08.2012 - 12:01
fonte
0

Alla fine ho usato una classe Product con contenuto generico e una classe di dettaglio accessibile tramite gli indicizzatori per fornire la funzionalità ... ma non sono sicuro che sia il modo giusto per farlo.

Non ho trovato uno schema di progettazione specifico che definisca esplicitamente come farlo (come nella domanda originale). Tranne "Factory", ma sembra un po 'generico ...

Ecco come l'ho implementato (il codice è stato semplificato):

public class Product    
{   
    public string Code {get;set;}
    ....
    private Dictionary<string, ProductDetail> LocalProduct= new Dictionary<string, ProductDetail>();

    public LocalDetail this[string countryCode]
    {
        get
        {
            if (LocalProducts.ContainsKey(countryCode))
                return LocalProducts[countryCode];
            else
                throw new ApplicationException(String.Format("Local product detail does not exist for {0}", countryCode));
         }
         set
         {
            if (LocalProducts.ContainsKey(countryCode))
                throw new ApplicationException(String.Format("Local product detail already exists for {0}", countryCode));
            else
                LocalProducts.Add(countryCode, value);
        }
    }
}

public class LocalDetail 
{
    public string Description {get; set;}
    ....
}

Il codice chiamante è qualcosa del tipo:

        Product p = new Product("123456");

        LocalDetail UKDetail = new LocalDetail();
        UKDetail.Description = "Description in English";
        p["UK"] = UKDetail;            

        System.Console.WriteLine("Product {0} Description in UK Detail : {1}", p.Code, p["UK"].Description);

        LocalDetail ITDetail = new LocalDetail();
        ITDetail.Description = "Descrizione in Italiano";
        p["IT"] = ITDetail;
        System.Console.WriteLine("Product {0} Description in Italian Detail : {1}", p.Code, p["IT"].Description);
    
risposta data 09.08.2012 - 12:47
fonte

Leggi altre domande sui tag