Prima di tutto, ogni elemento è responsabile di essa la propria stato (informazioni). In una buona progettazione OOP l'oggetto non può mai essere impostato in uno stato non valido. Dovresti almeno cercare di impedirlo.
Per fare ciò non è possibile avere pubblici setter se uno o più campi sono obbligatori in combinazione.
Nel tuo esempio un Item
non è valido se manca la orderId
o itemId
. Senza queste informazioni l'ordine non può essere completato.
Così si dovrebbe attuare tale classe come questa:
public class Item
{
public Item(int orderId, int itemId)
{
if (orderId <= 0) throw new ArgumentException("Order is required");
if (itemId <= 0) throw new ArgumentException("ItemId is required");
OrderId = orderId;
ItemId = itemId;
}
public int OrderID { get; private set; }
public int ItemID { get; private set; }
public string ItemName { get; set; }
}
vedere quello che ho fatto lì? Mi sono assicurato che l'oggetto fosse in uno stato valido fin dall'inizio forzando e convalidando le informazioni direttamente nel costruttore.
Il ItemName
è solo un bonus, non è necessario per poter elaborare un ordine.
Se i setter di proprietà sono pubblici, è facile dimenticare di specificare entrambi i campi richiesti, ottenendo uno o più bug in seguito quando tali informazioni vengono elaborate. Costringendolo a includere e convalidando le informazioni si catturano i bug molto prima.
Ordinare
L'oggetto ordine deve assicurare che si tratta di tutta la struttura è valido. Quindi è necessario avere control sulle informazioni che esso contiene, che includono anche gli articoli dell'ordine.
se avete qualcosa di simile:
public class Order
{
int OrderID;
string OrderName;
List<Items> OrderItems;
}
Si sono fondamentalmente dicendo: ho articoli di ordine, ma non mi interessa quanti o ciò che essi contengono. Questo è un invito ai bug più avanti nel processo di sviluppo.
Anche se si dice qualcosa di simile:
public class Order
{
int OrderID;
string OrderName;
List<Items> OrderItems;
public void AddItem(item);
public void ValidateItem(item);
}
si sta comunicando qualcosa di simile: Si prega di essere bello, convalidare la voce e poi inserirlo attraverso il metodo Add. Tuttavia, se hai un ordine con id 1, qualcuno potrebbe ancora fare order.AddItem(new Item{OrderId = 2, ItemId=1})
o order.Items.Add(new Item{OrderId = 2, ItemId=1})
, rendendo così l'ordine contenente informazioni non valide.
imho a ValidateItem
metodo non appartiene a Order
ma in Item
in quanto è sua responsabilità essere in uno stato valido.
Un design migliore sarebbe:
public class Order
{
private List<Item> _items = new List<Item>();
public Order(int orderId)
{
if (orderId <= 0) throw new ArgumentException("OrderId must be specified");
OrderId = orderId;
}
public int OrderId { get; private set; }
public string OrderName { get; set; }
public IReadOnlyList<Items> OrderItems { get { return _items; } }
public void Add(Item item)
{
if (item == null) throw new ArgumentNullException("item");
//make sure that the item is for us
if (item.OrderId != OrderId) throw new InvalidOperationException("Item belongs to another order");
_items.Add(item);
}
}
controllo Ora avete ottenuto oltre l'intero ordine, se devono essere apportate modifiche alla lista elemento, questo deve essere fatto direttamente nell'oggetto ordine.
Tuttavia, un articolo può ancora essere modificato senza che l'ordine lo conosca. Qualcuno potrebbe ad esempio a order.Items.First(x=>x.Id=3).ApplyDiscount(10.0);
che sarebbe fatale se l'ordine avesse un campo memorizzato nella cache Total
.
Tuttavia, un buon design non lo fa sempre correttamente al 100%, ma un compromesso tra codice con cui possiamo lavorare e codice che fa tutto correttamente secondo principi e schemi.
Una buona risposta, ma non è il cuore di Rich Data Model che le entità si convalidano? quindi perché dovresti convalidare l'oggetto nella classe 'Order'? Anche così, perché è il compito di "Ordine" per determinare se un "Articolo" è valido? Non dovrebbe _that_ essere su 'Item'? –
Questo è il punto cruciale della domanda. Dove vanno i comportamenti? Un oggetto può validarsi da solo? La convalida necessaria cambia nel contesto di un ordine? Ad esempio, un articolo di sconto può essere applicato solo quando alcuni altri articoli sono nell'ordine. Lo sconto stesso è valido, ma potrebbe non essere in alcuni ordini. – dbugger
Grazie per la risposta !! Sono d'accordo con la maggior parte di quello che hai detto tranne la convalida di un oggetto. Penso che dovrebbe essere fatto nella classe dell'oggetto. La classe ordine può chiamare quel metodo nella classe articolo prima che possa essere aggiunto. Da un lato, sto iniziando a sentire che il modello di servizio è più adatto per le applicazioni web .. solo un pensiero :) – user3587180