Programmazione dei principi SOLIDI


43

Nel tempo ho capito due parti di SOLID : la "S" e la "O".

"O" - Ho imparato Open Closed Principle con l'aiuto di Ereditarietà e modello strategico.

"S": ho appreso il principio della responsabilità singola durante l'apprendimento dell'ORM (la logica di persistenza è tolta dagli oggetti del dominio).

In modo simile, quali sono le migliori regioni / attività per apprendere altre parti di SOLID (la "L", "I" e "D")?

Riferimenti

  1. msdn - I pericoli della violazione dei principi SOLIDI in C #
  2. channel9 - Applicazione dei principi SOLID in .NET / C #
  3. Principi OOPS (principi SOLIDI)

25
prendi nota che tutte queste idee sono buone idee e insieme sono molto buone. ma se li applichi dogmaticamente , causeranno più fallimenti che successi.

3
Gli OR-Mapper sono utili per la separazione delle preoccupazioni, non per il principio di responsabilità singola. Vedi questo post programmers.stackexchange.com/questions/155628/… per una discussione delle differenze.
Doc Brown,

Esempi dal mondo reale blog.gauffin.org/2012/05/…
LCJ

1
@JarrodRoberson Sì, è per questo che vengono attentamente definiti come linee guida . Inoltre, non dimenticare il resto dei principi: adamjamesnaylor.com/2012/11/12/… (11 in totale)
Adam Naylor,

2
Il link di @AdamNaylor ora è 404ing, è stato spostato su adamjamesnaylor.com/post/…
mattumotu

Risposte:


54

Ero nei tuoi panni un paio di mesi fa fino a quando non ho trovato un articolo molto utile.

Ogni principio è ben spiegato con situazioni del mondo reale che ogni sviluppatore di software può affrontare nei loro progetti. Sto tagliando qui e indicando il riferimento: SOLID Software Development, One Step at the Time .

Come sottolineato nei commenti, c'è un'altra ottima lettura in pdf: lo sviluppo di software SOLID di Pablo .

Inoltre, ci sono alcuni buoni libri che descrivono i principi SOLID in modo più dettagliato: Good Book on SOLID Software Development .

Modifica e commenti di un breve riassunto per ciascun principio:

  • "S" - Il principio di responsabilità singola è guidato dalle esigenze dell'azienda per consentire il cambiamento. "Un unico motivo per cambiare" ti aiuta a capire quali concetti logicamente separati dovrebbero essere raggruppati considerando il concetto e il contesto di business, anziché il solo concetto tecnico. In another words, ho imparato che ogni classe dovrebbe avere un'unica responsabilità. La responsabilità è semplicemente svolgere l'attività assegnata

  • "O" - ho imparato Open Closed Principle e ho iniziato a "preferire la composizione rispetto all'ereditarietà" e come tale, preferendo le classi che non hanno metodi virtuali e che possono essere sigillate, ma dipendono dalle astrazioni per la loro estensione.

  • "L" - Ho imparato il principio di sostituzione di Liskov con l'aiuto del modello di deposito per la gestione dell'accesso ai dati.

  • "Io" - Ho imparato a conoscere il principio di segregazione dell'interfaccia apprendendo che i client non dovrebbero essere costretti a implementare interfacce che non usano (come nel provider di appartenenze in ASP.NET 2.0). Quindi l'interfaccia non dovrebbe avere "molte responsabilità"
  • "D" - Ho imparato a conoscere il principio di inversione di dipendenza e ho iniziato a scrivere codice che è facile da modificare . Più facile da cambiare significa un costo totale di proprietà inferiore e una maggiore manutenibilità.

Dato che nei commenti è stata menzionata una risorsa utile di CodePlex, l'esempio fa riferimento a SOLID

inserisci qui la descrizione dell'immagine


3
Ho trovato molto utile la seguente raccolta di articoli: lostechies.com/wp-content/uploads/2011/03/…
Scroog1

Ho letto l'intero articolo e non sono venduto su modelli o su SOLID. L'esempio è troppo semplicistico, ma quando diventa complesso quella complessità è artificiale. Devo ancora incontrare SOLID OOP nel mondo reale senza alternative migliori.
Giobbe

3
da quando gli articoli di Lostechies sono stati menzionati qui c'è anche questo solidexamples.codeplex.com (basato su lostechies)
dark fader

2
Sono stato uno dei collaboratori dell'eBook Pablos. Sono contento che le persone lo trovino ancora utile. :)
Sean Chambers,

1
+1000000 se potessi per il tuo riassunto del principio Open-Closed - tutti sbagliano e pensano che si
tratti

11

(I) nterface Segregation e (D) ependency Inversion possono essere appresi tramite unit testing e beffardo. Se le classi creano le proprie dipendenze, non è possibile creare buoni test unitari. Se dipendono da un'interfaccia troppo ampia (o nessuna interfaccia), non è molto ovvio cosa debba essere deriso per effettuare i test delle unità.


2
+1 questo è molto vero. Non devi nemmeno aderire alla regola (imo) a volte troppo rigida "un test unitario dovrebbe testare solo una cosa": se non riesci a trovare una suite di test decente per una classe in un paio di minuti, viola I e D e probabilmente anche il resto dell'alfabet
stijn

8

Il Principio di sostituzione di Liskov in sostanza non ti consente di abusare dell'ereditarietà dell'implementazione: non dovresti mai usare l'ereditarietà solo per il riutilizzo del codice (c'è una composizione per questo)! Aderendo a LSP, puoi essere abbastanza sicuro che esiste effettivamente una "relazione is-a" tra la tua superclasse e la tua sottoclasse.

Ciò che dice è che le sottoclassi devono implementare tutti i metodi della sottoclasse in modo simile all'implementazione dei metodi nella sottoclasse. Non si dovrebbe mai sostituire un metodo con l'implementazione di NOP o restituire null quando il supertipo genera un'eccezione; indicato in termini di Design by Contract, è necessario rispettare il contratto del metodo dalla superclasse quando si ignora un metodo. Un modo per difendersi dalla violazione di questo principio non è mai scavalcare un metodo implementato; estrarre invece un'interfaccia e implementare tale interfaccia in entrambe le classi.

Il principio di segregazione dell'interfaccia , il principio di responsabilità singola e il principio di alta coesione di GRASP sono in qualche modo correlati; si riferiscono al fatto che un'entità dovrebbe essere responsabile di una sola cosa, in modo che vi sia una sola ragione per il cambiamento, in modo che il cambiamento sia fatto molto facilmente.

In realtà dice che se una classe implementa un'interfaccia, allora deve implementare e usare tutti quei metodi dell'interfaccia. Se ci sono metodi che non sono necessari in quella particolare classe, allora l'interfaccia non è buona e deve essere suddivisa in due interfacce una che ha solo i metodi necessari per la classe originale. Può essere considerato da un POV, che si riferisce al principio precedente dal fatto che non consente di creare interfacce di grandi dimensioni in modo che la loro implementazione possa interrompere LSP.

È possibile vedere Inversion di dipendenza nel modello di fabbrica; qui sia il componente di alto livello (il client) che il componente di basso livello (istanza individuale da creare) dipendono dall'astrazione(l'interfaccia). Un modo per applicarlo in un'architettura a più livelli: non è necessario definire un'interfaccia per un livello nel livello implementato ma nel modulo chiamato. Ad esempio, l'API nel livello dell'origine dati non deve essere scritta nel livello dell'origine dati ma nel livello logico aziendale, dove deve essere chiamato. In questo modo, il livello dell'origine dati eredita / dipende dal comportamento definito nella logica aziendale (quindi l'inversione) e non viceversa (come sarebbe in modo normale). Ciò fornisce flessibilità nella progettazione, consentendo alla logica di business di funzionare senza alcuna modifica del codice, con un'altra fonte di dati completamente diversa.


1
Grande spiegazione su Liskov. :)
John Korsnes
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.