Le altre due risposte e il collegamento "possibile domanda duplicata" risolvono in modo adeguato i problemi dell'utilizzo delle classi base, piuttosto che delle interfacce. Ma mi piacerebbe indirizzare il codice nella domanda stessa.
La prima cosa da notare è la riga return customer.IsBirthday() ? 0.10m : 0;
.
Questo codice rivela il fatto che il metodo IsBirthday()
è probabilmente strettamente accoppiato a DateTime.Now
. Ciò rende i test più difficili di quanto sia necessario, ad esempio senza modificare il tempo di sistema (o solo eseguendo il test una volta ogni quattro anni), non c'è un modo semplice per verificare che gestisca correttamente un cliente nato il 29 febbraio. La data corrente deve essere passata a IsBirthday()
.
In secondo luogo, se la data corrente gli viene passata, CalculateCustomerDiscount
diventa una pura funzione, quindi può essere reso statico:
public static decimal CalculateBirthdayDiscount(Customer customer, DateTime date) =>
customer.IsBirthday(date) ? 0.10m : 0;
E può essere referenziato tramite un Func<Customer, DateTime, decimal>
delegato in tutto il codice. Ciò elimina la necessità di definire l'interfaccia IDiscountRule
.
Non solo semplifichiamo il codice rimuovendo un'interfaccia inutilizzata, ma eliminiamo la necessità di dover creare simulazioni di quell'interfaccia nel codice di test. È possibile invece utilizzare un semplice metodo di simulazione, che semplifica ancora una volta le cose, eliminando potenzialmente la necessità di utilizzare un framework di simulazione.