Parametri di funzione e polimorfismo non utilizzati

5

Ho avuto una discussione con un collega di lavoro sui membri dell'interfaccia con parametri che alcune implementazioni non usano.

Dire che ho un'interfaccia

interface IDoctor
{
    string GetMedicalOpinion(Age age, Weight weight, SleepSchedule sleepSchedule, Symptom symptom)
}

Le implementazioni di IDoctor non utilizzano necessariamente tutti i parametri del metodo:

class BadDoctor : IDoctor
{
    string GetMedicalOpinion(Age age, Weight weight, SleepSchedule sleepSchedule, Symptom symptom)
    {
        if (Symptom == Symptoms.Fatigue)
            return "You're sick!";
        return "You're okay."
    }
}

Il mio collega pensa che l'interfaccia sia mal definita perché ci sono implementazioni che non usano tutti i parametri del metodo.

Penso che vada bene. Avere un metodo con tutti i parametri ci dà il polimorfismo - possiamo scambiare gli IDoctor di varia competenza senza modificare il codice circostante. Inoltre, i parametri sono dati immutabili, quindi i consumatori non dovrebbero avere alcuna aspettativa che la funzione faccia qualcosa di diverso dal restituire una stringa. Infine, i parametri sono tutte cose che i consumatori dovrebbero avere naturalmente, quindi fornire le informazioni non è un onere per i consumatori.

Questo viola i principi del design contemporaneo? C'è davvero un problema con i membri dell'interfaccia che hanno parametri usati da alcune implementazioni, ma ignorati da altri?

    
posta theguy 14.05.2016 - 16:41
fonte

2 risposte

8

Penso che il problema principale sia in realtà causato da una ragione che è stata ampiamente discussa di recente su questa scheda esatta, Dovremmo evitare oggetti personalizzati come parametri?

Per chiamare il metodo che hai definito, hai bisogno di decostruire l'oggetto a cui appartengono gli attributi.

Modificando la firma del metodo su quella dell'esempio seguente, elimini la necessità di passare parametri inutilizzati.

interface IDoctor
{
    string DetermineMedicalState(IPatient patient);
}

Sembra davvero che tutte le proprietà che stai passando appartengono ad un paziente, quindi tienile insieme in un oggetto. Ecco a cosa servono anche gli oggetti, per ridurre il numero di parametri.

Con questo approccio sai che il metodo accetta una variabile IPatient e non potrebbe importare di meno quale tipo di medico estrae le informazioni da esso.

Per rispondere alle domande che hai posto, non penso che il progetto iniziale violi le regole, purché rispetti il contratto dato dall'interfaccia. Ma non è nemmeno un design elegante e forse nemmeno quello giusto.

Passando un oggetto IPatient hai ancora il polimorfismo a portata di mano, quindi non hai perso nulla.

    
risposta data 14.05.2016 - 18:36
fonte
5

Does this violate contemporary design principles?

No.

Is there really a problem with interface members having parameters that are used by some implementations, but ignored by others?

Non per il solo fatto. Ma se hai 10 diverse implementazioni di interfaccia e 9 di loro usano solo i parametri 1 e 2, e l'implementazione numero 10 è l'unica usando i parametri 3 e 4, che potrebbe essere un'indicazione che le responsabilità sono non tagliato in modo ottimale. Se vedi un disegno del genere, puoi chiederti se l'astrazione definita dall'interfaccia va bene. Forse puoi spostare i parametri 3 e 4 al costruttore della classe 10, come suggerito da @Ewan. Dovresti anche verificare se le implementazioni sono conformi al Listino di Sottoscrizione Liskov. Ma in entrambi i casi, potresti arrivare alla risposta "sì" e lasciare che l'interfaccia sia esattamente così com'è.

Questo nulla che può essere semplicemente deciso contando l'uso dei parametri - devi guardare il codice reale, i nomi delle funzioni e delle classi e prendere una decisione basata su tali informazioni.

    
risposta data 14.05.2016 - 16:59
fonte

Leggi altre domande sui tag