Quando utilizzare l'ereditarietà, quando utilizzare 'solo un campo booleano'?

18

Nella nostra applicazione Rails, stiamo aggiungendo notifiche. Alcuni di questi sono blocking : interrompono l'avanzamento di qualsiasi risorsa su cui sono aggiunti, poiché mancano alcune informazioni su tale risorsa.

Altre notifiche sono notifiche semplici e forniscono solo informazioni.

Oggi ho avuto una discussione con un altro programmatore sul nostro team. Ho creato la struttura di ereditarietà come questa:

Tuttavia, preferirebbe che aggiungessi blocking come metodo di ritorno booleano su ogni notifica e specificasse un elenco di sottoclassi che bloccano la classe genitore di notifica.

La differenza tra questi approcci non è molto ampia; nel mio approccio non è necessario specificare questo elenco, mantenendo pulita la classe radice. D'altra parte, la logica speciale che si verifica in Notification::Blocking adesso non è neanche molto grande.

Che tipo di astrazione è più adatta a questo problema?

    
posta Qqwy 23.05.2016 - 16:55
fonte

5 risposte

36

Vuoi evitare che le classi base conoscano le classi derivate. Introduce un accoppiamento stretto ed è un problema di manutenzione perché devi ricordarti di aggiungere all'elenco ogni volta che crei una nuova classe derivata.

Vi impedirà inoltre di essere in grado di inserire la classe di notifica in un pacchetto / assembly riutilizzabile se si desidera utilizzare questa classe in più progetti.

Se vuoi davvero usare una singola classe base, un altro modo per risolverlo è aggiungere una proprietà virtuale o un metodo IsBlocking sulla classe di base Notification. Le classi derivate potrebbero quindi sovrascriverle per restituire true o false. Avresti una soluzione a una sola classe senza che la classe base conosca le classi derivate.

    
risposta data 23.05.2016 - 17:06
fonte
14

and specify a list of subclasses that are blocking inside the Notification parent class.

Questo sembra molto particolare ed è un particolare odore di codice.

Fornire sottoclassi se si hanno differenze di comportamento tra le classi e si desidera trattare tutte queste notifiche nello stesso modo (cioè utilizzando polimorfismo ).

    
risposta data 23.05.2016 - 16:59
fonte
7

Come alternativa alle risposte esistenti, suggerirei che la proprietà booleana è l'opzione migliore se la modalità da utilizzare deve essere modificata dinamicamente (ad esempio tramite un file di configurazione che fornisce un elenco di quali tipi sono da bloccare e quali no).

Detto questo, un design migliore anche in questa situazione potrebbe essere l'uso di un oggetto Decorator.

    
risposta data 23.05.2016 - 20:09
fonte
1

Direi che dipende da quanto altro è speciale su una notifica di blocco, anche se il mio primo pensiero è di andare con "entrambi":

class Notification
 virtual Boolean Blocking{get return false;}

class BlockingNotification inherits Notification
 virtual overrides Boolean Blocking{get return true;}

In questo modo, puoi utilizzare n.Blocking o n is BlockingNotification (tutto in pseudo-codice), sebbene, se intendi consentire a una classe di implementare un valore Blocking sensibile al contesto, visto come te ' d devo controllare quel valore ogni volta, la classe BlockingNotification diventa meno utile.

In ogni caso, sono d'accordo con le altre risposte che non vuoi che l'implementazione della classe base di Blocking debba conoscere le classi derivate.

    
risposta data 28.05.2016 - 09:46
fonte
0

Invece di creare due classi base e più istanze di ciascuna, crea una classe di notifica con un bool per indicare se la notifica sta bloccando e qualsiasi altra informazione necessaria per comunicare la notifica all'utente.

Ciò ti consente di utilizzare un set di codice per l'elaborazione e la presentazione delle notifiche e riduce la complessità del tuo codice.

    
risposta data 25.05.2016 - 01:01
fonte

Leggi altre domande sui tag