Modellazione del dominio

3

Sto lavorando al modello di dominio di un'applicazione che memorizza le informazioni fornite dai venditori sui prodotti che vendono su una piattaforma. L'applicazione funge semplicemente da archivio dati per queste informazioni. Le informazioni sono chiamate "ProductFact" e possono essere diverse. Ogni esempio di seguito rappresenta un'istanza "ProductFact".

  1. il prezzo di vendita dell'articolo per il pubblico in generale.
  2. lo sconto che il venditore può offrire ad alcuni clienti specifici (a importo assoluto, o percentuale del prezzo di vendita).
  3. la quantità minima che un cliente deve acquistare per usufruire della spedizione gratuita.

Quanto sopra sono alcuni casi che sono noti al momento, ma potrebbero essercene altri in futuro, senza alcuna garanzia di condivisione di alcuna proprietà con i "ProductFact" già esistenti. Diversi client chiameranno questa applicazione, ognuno alla ricerca di un tipo specifico di "ProductFact".

Useremo un backend NoSQL, quindi lo schema db non è un problema. Il problema è con il livello dell'applicazione. Non sono sicuro di come modellare questo particolare oggetto. Ho provato a modellarlo come:

public class ProductFact {
    private ProductFactType productFactType; //enum for different types like SELLING_PRICE, DISCOUNTS, MIN_QUANT, etc.
    private ProductFactData productFactData; // for representing the actual data.
}

Sarebbe stato ideale se ProductFactData avesse un comportamento, quindi avrei potuto usarlo come interfaccia e creato implementazioni o ogni caso d'uso. Ma questo è solo dati, e l'ereditarietà sembra essere un approccio hacky.

Un altro approccio potrebbe essere:

public class ProductFact {
    private ProductFactType productFactType;

    private SellingPriceFactData sellingPriceFactData;
    private DiscountFactData discountFactData;
    .
    .
    .
    private SomeProductFactData someProductFactData;
}

Il client può verificare il valore di "productFactType" e quindi chiamare il getter per il tipo FactData appropriato.Ma anche questo approccio sembra hacky.

Quale sarebbe un buon modo di modellare questo scenario?

Modifica
Sembra che l'affermazione del problema potrebbe usare un po 'più di chiarezza. Sconto e prezzo sono due dei tanti pezzi "ProductFact" che l'applicazione potrebbe memorizzare. Ci potrebbero essere altri in futuro, tra cui:

  1. Informazioni sull'eleggibilità della consegna espressa del prodotto, ad esempio "ExpressDeliveryProductFact" - quali aree sono disponibile per, qual è la quantità minima richiesta.
  2. Informazioni sulla condizione del prodotto - è usato, nuovo?

Ci sarebbero diversi client che interrogano questa applicazione, ognuno dei quali cerca il tipo di ProductFact a cui è interessato. Ad esempio, un client DeliveryService sarebbe interessato a "ExperssDeliveryProductFact".
Come si può vedere, queste informazioni apparentemente non hanno nulla in comune, che pone problemi nel modello di dominio.

    
posta user3024475 14.04.2018 - 10:27
fonte

1 risposta

2

Per modellare correttamente in un modo orientato agli oggetti, sposta la tua mentalità verso modelli di progettazione orientati agli oggetti.

Ad esempio, puoi applicare il modello di strategia per applicare lo sconto al prezzo del prodotto per caso.

Definisci un'interfaccia per la tua strategia di sconti nel tuo modello:

public interface iDiscountStrategy
{
     decimal ApplyExtraDiscountTo(decimal originalSalePrice);
}

Aggiungi ogni tipo di sconto come implementazione della strategia di sconto. Ecco uno sconto percentuale e uno nessuno sconto implementazioni (definirli anche nel tuo modello):

public class TradeDiscountDiscountStrategy : IDiscountStrategy
{
    public decimal ApplyExtraDiscountTo(decimal originalSalePrice)
    {
        decimal price = originalSalePrice;
        price = price * 0.95M;
        return price;
    }
}

public class NullDiscountStrategy : IDiscountStrategy
{
    public decimal ApplyExtraDiscountTo(decimal originalSalePrice)
    {
        return originalSalePrice;
    }
}

La tua entità modello Price . Usa il sapore setter di DI per abilitare la strategia di sconto da applicare al prezzo del prodotto:

public class Price
{
    private IDiscountStrategy discountStrategy = new NullDiscountStrategy();

    private decimal sellingPrice;

    public Price(decimal sellingPrice)
    {
        this.sellingPrice = sellingPrice;
    }

    public void SetDiscountStrategyTo(IDiscountStrategy discountStrategy)
    {
        this.discountStrategy = discountStrategy;
    }

    public decimal SellingPrice
    {
        get
        {
            return this.discountStrategy.ApplyExtraDiscountsTo(this.sellingPrice);
        }
    }
}

Tieni presente che Price può contenere qualsiasi altra logica (ad esempio "comportamento") come il calcolo del risparmio ecc.

Il ProductFact diventa:

public class ProductFact
{
    public Price Price { get; set; }
    // ...
}

Per applicare lo sconto per tipo di cliente è necessario creare la seguente enumerazione:

public enum CustomerType
{
    Standard = 0,
    Trade = 1
}

Devi anche creare una classe factory la cui unica responsabilità sarà quella di restituire la strategia di sconto corrispondente per un dato CustomerType :

public static class DiscountFactory
{
    public static IDiscountStrategy GetDiscountStrategyFor(CustomerType customerType)
    {
        switch (customerType)
        {
            case CustomerType.Trade:
                return new TradeDiscountStrategy();
            default:
                return new NullDiscountStrategy();
        }
    }
}

E questo è tutto. Quindi, nel tuo livello di servizio puoi scrivere qualcosa come:

public class ProductFactService
{
    public IList<ProductFact> GetAllProducts(CustomerType customerType)
    {
        IDiscountStrategy discountStrategy = DiscountFactory.GetDiscountStrategyFor(customerType);

        IList<ProductFact> products = // get products from database

        foreach (ProductFact pf in products)
        {
            pf.Price.SetDiscountStrategyTo(discountStrategy);
        }

        retur products;
    }
}

Avere la stessa mentalità per il resto del dominio e la maggior parte dei problemi di modellazione andrà via.

    
risposta data 15.04.2018 - 09:36
fonte

Leggi altre domande sui tag