Devo usare una proprietà di raccolta se richiedo solo un oggetto al momento?

2

Vedi la classe qui sotto:

public class Customer
    {
        private readonly IList<Order> _orders = new List<Order>();

        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Province { get; set; }
        public IEnumerable<Order> Orders { get { return _orders; } } //This line

        internal void AddOrder(Order order)
        {
            _orders.Add(order);
        }
}

Così com'è; una persona può avere solo un ordine a loro assegnato (c'è una buona ragione per questo così com'è - se la stessa persona crea un altro ordine allora viene creato un altro ordine). Tuttavia, questo potrebbe cambiare in futuro.

Mi è stato chiesto di recente perché utilizzo un elenco nel modello di dominio per rappresentare gli ordini. Ci sono due opzioni:

1) Usa un elenco sulla base del fatto che in futuro il piano è di avere una persona con più ordini.

2) Usa un oggetto per ora e modificalo in un elenco in futuro, se necessario.

Mi rendo conto che questo è un po 'pedante. Tuttavia, sto lavorando per un'organizzazione a cui piace usare il principio del minimo stupore. Quale opzione dovrei andare con; per quanto riguarda quanto sopra. C'è un principio in gioco qui?

    
posta w0051977 19.02.2018 - 14:44
fonte

6 risposte

4

Se dovessi seguire YAGNI su questo, dovresti rimandare l'implementazione di qualsiasi cosa nella classe cliente relativa agli ordini. Quando inizi ad aggiungere qualcosa agli ordini, introduci qualcosa che si interrompe se lo cambi in seguito.

Quindi devi prendere una decisione adesso è solo un oggetto o è qualcosa che sarà una lista quando viene usato il sistema.

La decisione è in questo caso molto facile. Anche se un cliente può avere al massimo un unico ordine, esiste ancora il caso in cui il cliente non abbia ordini.

Una lista vuota è sempre più pulita di NULL.

E anche se tutti i clienti hanno sempre un solo ordine, se i requisiti / le storie degli utenti ti dicono che cambierà.

    
risposta data 20.02.2018 - 10:47
fonte
3

Sebbene David Arno abbia menzionato un buon punto (evitando la complessità non necessaria), non sono completamente d'accordo.

Ci sono molti fattori che dovrebbero essere considerati prima di prendere quella decisione, e per me uno dei più importanti è:

Quanto lavoro significherà cambiare in seguito da un oggetto all'altro?

  • Quante classi si baseranno sul fatto che esiste un solo ordine per cliente? Queste classi dovranno essere rivisitate con quel cambiamento.
  • Esiste una struttura del database che deve essere modificata, che richiede la migrazione dei dati esistenti? Sono solo i dati della tua azienda o devi ripetere la migrazione del database per più siti o produrre uno script affidabile che eseguirà una migrazione automatica?

E (anche se ovviamente non conosco il tuo caso di domanda) mi interrogherei sul fatto che un cliente ha un solo ordine. La maggior parte delle aziende preferisce che i propri clienti tornino con nuovi ordini abbastanza spesso e che consentano loro di elaborare più ordini in parallelo.

Quindi dovresti stimare:

  • la complessità aggiunta di un elenco su un singolo oggetto
  • il carico di lavoro prodotto cambiando successivamente da oggetto a elenco
  • la probabilità che una lista sia necessaria in seguito.
risposta data 19.02.2018 - 15:07
fonte
3

Sebbene sia opportuno prevedere i possibili requisiti futuri, è necessario considerare la complessità extra che si sta aggiungendo al software. Complessità che al momento attuale non è necessaria. Invece di aggiungere inutili complessità al tuo software nella speranza che un giorno possa dare i suoi frutti, preferirei mantenere il codice il più semplice e pulito possibile e implementare solo ciò che è necessario. Se ogni decisione di progettazione che fai è basata su "ciò che cambia il futuro POTREBBE portare", ti ritroverai con un pezzo di software sovradimensionato, che è inutilmente difficile da leggere e comprendere e ironicamente difficile da mantenere ed espandere.

    
risposta data 19.02.2018 - 15:43
fonte
2

Should I use a collection property if I only require an object at the moment?

Probabilmente no; dato che ora non hai bisogno della flessibilità extra, stai scommettendo che

  • hai indovinato correttamente quale sarà il futuro requisito
  • il costo di cambiare l'API in seguito supera il costo aggiuntivo che la flessibilità impone ora
  • che questa implementazione sopravviverà abbastanza a lungo perché le scommesse lente paghino

Hai ragione a pensare in anticipo ai cambiamenti futuri, ma potresti mancare un'idea chiave: che vuoi cambiamenti futuri che estendono la funzionalità corrente, piuttosto che modifiche che lo distruggono.

L'attuale ipotesi è che alla fine vorrai una funzione Orders , quindi nel pensare all'API corrente, vuoi lasciare un buco in modo che tu possa facilmente aggiungere quel metodo più tardi.

interface V1 {
    Order Order();
}

interface V2  : V1 {
    IEnumerable<Order> Orders();
}

Ora, quando vengono visualizzati i requisiti per la restituzione di più ordini, dovrai capire quali di quegli ordini che l'interfaccia V1 dovrebbe restituire. Potresti provare a fare questa ipotesi oggi e organizzare l'interfaccia V1 in modo che corrisponda

interface V1 {
    Order LatestOrder();
}

Oppure (consigliato) puoi aspettare che la situazione sia più chiara

interface V1 {
    Order Order(); // delegates to V2.LatestOrder
}

interface V2  : V1 {
    Order LatestOrder();
    IEnumerable<Order> Orders();
}

Il punto è che i client possono continuare a utilizzare l'interfaccia V1 con l'implementazione V2 - le modifiche sono retrocompatibili.

    
risposta data 19.02.2018 - 16:27
fonte
0

Evita di aggiungere complessità ora in previsione di un requisito futuro. Il futuro ha l'abitudine fastidiosa di rivelarsi in modo diverso rispetto alle nostre previsioni.

Se si codifica il supporto per più ordini e tale caratteristica non è mai necessaria, il codice sarà più complesso di quanto non sia necessario, per tutto il tempo (anche per la sua durata almeno). Avrai sprecato tempo di sviluppo per implementare quella funzionalità inutilizzata e avrai infranto il principio del minimo stupore avendo uno strano, più complesso di quanto dovrebbe essere, funzionalità del codice che potenzialmente rallenterebbe la manutenzione man mano che le persone si allenano è lì "nel caso in cui", non perché è necessario.

Invece, assicurati che il tuo codice sia semplice (implementa solo ciò che è necessario ora) e che sia ben supportato dai test unitari. In questo modo, se in futuro saranno necessari più ordini, diventa un compito relativamente semplice per il refactoring del codice per supportare tale funzione.

    
risposta data 19.02.2018 - 14:51
fonte
0

Ecco un grosso svantaggio: se ho bisogno di scrivere codice che gestisce l'ordine o gli ordini associati a un cliente, vedo che stai restituendo un elenco, quindi presumo che ci possano essere 0, 1 o 100 ordini. E scriverò codice in grado di gestire 0, 1 o 100 ordini, e questo sarà più complicato rispetto alla gestione di solo 1. Ad esempio, devo supporre che le cose non si adattino a una pagina dello schermo e debbano gestire lo scrolling su e giù. Devo ordinare l'elenco in questo modo e in quel modo e scrivere un'interfaccia utente per questo. C'è molto lavoro extra.

E poi mi viene detto che c'è sempre un solo ordine ... Non sarò felice.

Risparmierai pochissimo lavoro se cambi mai da un oggetto a uno multiplo, ma potresti perdere un sacco di lavoro se non lo fai mai.

    
risposta data 20.02.2018 - 16:19
fonte

Leggi altre domande sui tag