L'ereditarietà multipla viola il principio di responsabilità singola?

18

Se hai una classe che eredita da due classi distinte, questo non significa che la sottoclasse fa automaticamente (almeno) 2 cose, una per ogni superclasse?

Credo che non ci siano differenze se si ha ereditarietà di interfacce multiple.

Modifica: per essere chiari, credo che se la sottoclasse di più classi violi SRP, quindi l'implementazione di interfacce multiple (non marcatore o interfaccia di base (ad esempio comparabile) viola anche SRP.

    
posta m3th0dman 07.08.2012 - 18:21
fonte

6 risposte

17

In un senso molto ristretto, la risposta è "Sì": partendo dal presupposto che le tue classi base o interfacce sono progettate per un singolo scopo, ereditandole entrambe crea una classe con più responsabilità. Tuttavia, indipendentemente dal fatto che sia o meno una "cosa negativa", dipende dalla natura delle classi o delle interfacce che stai ereditando.

Puoi suddividere le tue classi e le tue interfacce in due gruppi principali: quelli che affrontano la complessità essenziale del tuo sistema e quelli che affrontano la sua accidentale complessità. Se ereditato da più di una classe di "complessità essenziale", è cattivo; se si eredita da una "essenziale" e una o più classi "accidentali", è OK.

Ad esempio, in un sistema di fatturazione potresti avere classi per rappresentare fatture e cicli di fatturazione (affrontano la complessità essenziale) e classi per oggetti persistenti (affrontano la complessità accidentale). Se erediti in questo modo

class BillingCycleInvoice : public BillingCycle, public Invoice {
};

non è positivo: il tuo BillingCycleInvoice ha una responsabilità mista in relazione alla complessità essenziale del sistema.

D'altra parte, se erediti in questo modo

class PersistentInvoice : public Invoice, public PersistentObject {
};

la tua classe è OK: tecnicamente, offre due problemi contemporaneamente, ma dal momento che solo uno di essi è essenziale, puoi cancellare ereditando quello accidentale come il "costo di fare affari".

    
risposta data 07.08.2012 - 18:51
fonte
9

L'SRP è una linea guida per evitare le divinità, che sono cattive, ma può anche essere presa alla lettera e un progetto inizia a gonfiarsi con tonnellate di classi che non possono davvero fare nulla senza una combinazione di poche persone. L'ereditarietà multipla o le interfacce multiple possono essere un segno che una classe sta diventando troppo grande, ma potrebbe anche essere un segnale che il tuo obiettivo è troppo granulare per l'attività in corso e la tua soluzione è troppo ingegnerizzata, o potrebbe semplicemente essere perfettamente caso d'uso valido per ereditarietà multipla e le tue preoccupazioni sono infondate.

Il design del software è tanto l'arte quanto la scienza, è un atto di bilanciamento di molti interessi in competizione. Abbiamo regole per aiutare ad evitare cose che sappiamo essere di gran lunga in una direzione che causano problemi, ma quelle regole possono altrettanto facilmente portarci in un posto che è altrettanto cattivo o peggiore di quello che stavamo cercando di evitare in primo luogo.

    
risposta data 07.08.2012 - 19:39
fonte
4

Un po '. Concentriamoci sul principio principale per SRP:

A class should only have one reason to change.

L'ereditarietà multipla non la forza, ma tende a portarla ad essa. Se la classe esegue l'override o implementa le sue classi di base, questo tende a essere più motivi per cambiare. In questo modo, l'ereditarietà multipla dell'interfaccia tende ad essere più problematica dell'ereditarietà di classe. Se due classi sono ereditate ma non sovrascritte, i motivi per cambiare esistono nelle classi base e non nella nuova classe.

I luoghi in cui l'ereditarietà multipla non viola SRP è quando tutti tranne uno dei tipi di base non sono qualcosa che la classe sta implementando, ma agiscono come un tratto che la classe capita di avere. Considera IDisposable in C #. Le cose che sono usa e getta non hanno due responsabilità, l'interfaccia agisce semplicemente come una vista in classi che condividono il tratto ma hanno responsabilità decisamente diverse.

    
risposta data 07.08.2012 - 18:32
fonte
2

Non secondo me. Per me, una singola responsabilità è "modella un utente della mia applicazione". Potrebbe essere necessario fornire tali dati tramite un servizio Web e archiviarli in un database relazionale. Potrei fornire quella funzionalità ereditando un paio di classi mix-in.

Questo non significa che la classe abbia tre responsabilità. Significa che parte della responsabilità di modellare un utente richiede il supporto della serializzazione e della persistenza.

    
risposta data 07.08.2012 - 18:32
fonte
2

Assolutamente no. In Java, puoi avere un'interfaccia che rappresenta una sorta di oggetto di dominio - un Foo, per esempio. Potrebbe essere necessario confrontarlo con altri oggetti Foo e quindi implementare Comparable (con la logica di confronto esternalizzata in una classe Comparator); può essere che questo oggetto abbia anche bisogno di essere serializzabile, in modo che possa essere trasportato attraverso la rete; e potrebbe aver bisogno di essere Clonabile. Quindi la classe implementa tre interfacce ma non ha alcuna logica interna per supportarle oltre quella supportata da Foo.

Detto questo, è sciocco portare lo SRP agli estremi. Se una classe definisce più di un metodo, sta violando l'SRP? Tutti gli oggetti Java hanno un metodo toString () e un metodo equals (Object), che significa che OGNI oggetto in Java è responsabile sia dell'uguaglianza che dell'auto-rappresentazione. È una brutta cosa?

    
risposta data 07.08.2012 - 23:55
fonte
1

Penso che dipenda da come si definisce la responsabilità. Nell'esempio classico di iostream non viola l'SRP. L'IOstream è responsabile della gestione di un flusso bidirezionale.

Dopo aver esaurito le responsabilità primitive, passerai a responsabilità più generiche di alto livello, dopotutto come definisci la responsabilità del tuo punto di ingresso principale? La sua responsabilità deve essere "essere il punto di ingresso principale" e non "tutto ciò che fa la mia app", altrimenti è impossibile non violare l'SRP e produrre un'applicazione.

    
risposta data 07.08.2012 - 20:47
fonte