Principio di inversione delle dipendenze - No derivante da classi concrete?

2

Non sono sicuro di aver capito bene. Per osservare i principi SOLID corretti, sono vietato ereditare da classi concrete ? Significa che ogni classe concreta che ho più o meno è sealed (o almeno considerata sealed )?

Questo mi confonde perché ho incontrato questo codice dal nostro repository:

class FontList : ObservableCollection<string> 
{ 
    public FontList() 
    {
        foreach (FontFamily f in Fonts.SystemFontFamilies)
        {                
            this.Add(f.ToString());                
        }  
    }   
}

Che eredita da ObservableCollection<string> , una classe concreta (corretta?). Comunque guardando ObservableCollection:

[Serializable]
public class ObservableCollection<T> : Collection<T>, INotifyCollectionChanged, INotifyPropertyChanged 

Sta ereditando da Collection<T> , che è anche una classe concreta. Qualcuno può spiegare la corretta interpretazione del DIP, specialmente per quanto riguarda l'ereditarietà della classe concreta?

    
posta Tyress 02.02.2016 - 10:52
fonte

3 risposte

2

L'applicazione di DIP dovrebbe essere selettiva. Ciò significa che scegli quali dipendenze vuoi invertite. L'applicazione di DIP aumenta la complessità. Quindi, dovresti impiegare la tua esperienza nella progettazione del software per scegliere dove questo aumento di complessità ripaga e dove no.

Inoltre, il libro di queste regole viene da sé stesso dice che quelle non sono regole dure e possono essere violate:

A somewhat more naïve, yet still powerful interpretation of DIP is the simple heuristic :

(l'elenco delle regole citate su Wikipedia segue)

... Moreover, there seems no reason to follow this heuristic for classes, that are concrete but nonvolatile. if concrete class is not going to change very much, and no other similar derivatives are going to be created, it does very little harm to depend on it.

Nel tuo caso sia ObservableCollection che Collection sono altamente non volatili. Fanno parte del framework .NET e si prevede che non cambieranno in un modo che richiederà la modifica da parte dell'utente.

Un'altra cosa è che la classe che mostri non è buona, non perché violerebbe DIP, ma perché è stupido creare una nuova classe solo per creare una raccolta pre-compilata. Invece, solo fare un metodo factory dovrebbe essere sufficiente.

public static class FontList
{ 
    public static ObservableCollection<string> Create() 
    {
        ObservableCollection<string> fonts = new ObservableCollection<string>();
        foreach (FontFamily f in Fonts.SystemFontFamilies)
        {                
            fonts.Add(f.ToString());                
        }
        return fonts;
    }   
}
    
risposta data 02.02.2016 - 11:12
fonte
0

Non ti è proibito ereditare da classi concrete, e certamente non dovresti rendere tutte le classi sealed , così facendo probabilmente porterai a violazioni del Open-Close Principle (OCP) in fondo alla strada quando ti rendi conto che hai bisogno di ereditare da una classe.

Finché la gerarchia dell'ereditarietà concreta non viola il Principio di sostituzione di Liskov (LSP), e che tutti i riferimenti a questa gerarchia dipende dalla classe base di livello superiore (si spera abstract ), probabilmente sei in buona forma.

    
risposta data 02.02.2016 - 11:26
fonte
0

In Principio di inversione delle dipendenze dovresti separare l'interfaccia (per il consumatore) dall'implementazione concreta.

Quindi la tua implementazione di FontList : ObservableCollection<string> è perfettamente a posto. (è solo un dettaglio di implementazione)

Dall'altro lato il consumatore della tua classe dovrebbe solo conoscere (o dipendere) un'interfaccia (cioè ICollection<string> ).

  • seguente DiP DoSomethingWithFontList(ICollection<string> fonts)
  • non seguendo DiP DoSomethingWithFontList(FontList fonts)
  • dipendenza non necessaria DoSomethingWithFontList(ObservableCollection<string> fonts)

Ad esempio, NHibernate sostituisce ICollection<string> con una raccolta speciale che carica la raccolta non appena un codice chiama un metodo nella raccolta. Il tuo programma di consumo non ha bisogno di sapere che esiste un'implementazione di raccolta speciale.

    
risposta data 02.02.2016 - 11:20
fonte

Leggi altre domande sui tag