2013-01-17 25 views
31

In che modo differisce il "principio di segregazione dell'interfaccia" SOLID da "principio di responsabilità singola"?In SOLIDO, qual è la distinzione tra SRP e ISP? (Principio della singola responsabilità e principio di segregazione dell'interfaccia)

La Wikipedia entry for SOLID says che

ISP divide interfacce che sono molto grandi a quelli più piccoli e più specifiche in modo che i clienti dovranno solo conoscere i metodi che sono di loro interesse

Tuttavia, a me sembra che sia sufficiente applicare l'SRP alle interfacce e alle classi. Dopotutto, se un'interfaccia è responsabile solo di una cosa concettuale, allora non saresti in grado di scomporla ulteriormente.

Mi manca qualcosa o l'ISP è ridondante con SRP? Se no, allora cosa ISP implica che SRP non lo fa?

+0

duplicato possibile per http://stackoverflow.com/questions/8099010/is-interface-segregation-principle-only-a-substitue-for-single-responsibility- pr –

+0

Suppongo tecnicamente, ma questa domanda è meglio scritta da IMHO e le risposte sono più dettagliate. – ArtB

risposta

25

SRP ci dice che dovresti avere una sola responsabilità in un modulo.

ISP ci dice che non si dovrebbe essere costretti a confrontarsi con più di quanto effettivamente necessario. Se si desidera utilizzare un metodo print() dall'interfaccia I, non è necessario creare un'istanza di una classe SwimmingPool o DriveThru per quello.

Più concretamente, e andando dritti al punto, sono opinioni diverse sulla stessa idea: SRP è più focalizzato sul punto di vista del progettista, mentre l'ISP è più focalizzato sul punto di vista del cliente -di-view. Quindi hai praticamente ragione.

che provenivano tutti dalla

L'ISP è stato utilizzato per la prima e formulata da Robert C. Martin quando facendo qualche consulenza per Xerox. Xerox aveva creato un nuovo sistema di stampante che poteva eseguire una serie di attività come la graffatura di un set di documenti stampati e fax. Il software per questo sistema è stato creato da terra e ha eseguito correttamente i suoi compiti. Con la crescita del software, la modifica di è diventata sempre più difficile, cosicché anche il più piccolo cambiamento di avrebbe richiesto un ciclo di ridistribuzione a un'ora. Questo rendeva lo quasi impossibile da continuare lo sviluppo. Il problema di progettazione era che la classe di lavoro principale era stata utilizzata da quasi tutte le attività nella classe . Ogni volta che è stato necessario un lavoro di stampa o un lavoro di pinzatura, è stata effettuata una chiamata al metodo nella classe Lavoro. Ciò ha comportato una classe enorme o "grossa" con una moltitudine di metodi specifici per una varietà di client diversi. A causa di questo progetto, un lavoro di pinzatura avrebbe saputo di tutti i metodi del lavoro di stampa, anche se per loro non era possibile utilizzarli.

così

La soluzione suggerita da Martin è quello che viene chiamato l'interfaccia segregazione Principio oggi. Applicato al software Xerox, è stato aggiunto uno strato di interfacce tra la classe Job e tutti i relativi client utilizzando il principio di inversione dipendenza.Invece di avere una grande classe di lavoro , è stata creata un'interfaccia di lavoro pinzatura o un'interfaccia di lavoro di stampa che verrebbe utilizzata dalle classi pinzatura o stampa, rispettivamente, metodi di chiamata della classe di lavoro. Pertanto, è stata creata un'interfaccia per ciascun lavoro, che sono stati tutti implementati dalla classe Lavoro.

@http://en.wikipedia.org/wiki/Interface_segregation_principle#Origin

+1

Hmm, l'unica distinzione che vedo dal tuo post è "" Se vuoi usare un metodo print() dall'interfaccia I, non dovresti istanziare una classe SwimmingPool o DriveThru per quello. "" Che francamente suona molto simile a "[Volevi una banana ma quello che hai ottenuto era un gorilla con in mano la banana e l'intera giungla.] (http://www.johndcook.com/blog/2011/07/19/you-wanted-banana/) ". Stai dicendo che il commento sulla banana è una parafrasi dell'ISP? – ArtB

+0

Questo è corretto. –

+0

Spesso si vede codice mal progettato in cui per fare uso di alcune funzionalità, è necessario prima attivare la registrazione, quindi attivare i servizi A, B e C, mentre tutto ciò che si voleva fare era calcolare l'area di un'ellissi che è qualcosa che ti aspetteresti di non richiedere tutto questo. –

5

SRP si occupa di ciò che un modulo fa, e come è fatto, vietando qualsiasi combinazione di livelli di astrazione. Fondamentalmente, finché un componente può essere ampiamente definito con una singola frase, non si romperà SRP.

D'altra parte ISP è interessato a come un modulo dovrebbe essere consumato, se ha senso consumare solo una parte del modulo, ignorando alcuni aspetti.

Come esempio di un codice che mantiene lo spirito o SRP, ma può rompere ISP è il modello di facciata. Ha una sola responsabilità, "fornire un accesso semplificato a un sottosistema più grande", ma se il sottosistema sotteso ha bisogno di esporre in modo molto diverso i concetti, questo rompe l'ISP.

Detto questo, di solito quando un pezzo di codice rompe un principio SOLID, spesso si rompe tutto. Esempi concreti che infrangono un principio specifico, pur preservando il resto, sono rari in natura.

4

SRP e ISP si riducono infine alle stesse cose. L'implementazione, uno di essi, richiede una serie di classi o interfacce.

Tuttavia ci sono differenze su altri fronti.

  1. La violazione di SRP può avere effetti di vasta portata sull'intera struttura del progetto, dando luogo a scarsa manutenibilità, riutilizzo e, naturalmente, bassa coesione e accoppiamento.
  2. SRP ha un impatto su entrambi i componenti comportamentali e strutturali di una struttura di oggetti.
  3. Per la progettazione della violazione SRP è necessaria un'analisi molto più approfondita, è necessario esaminare i diversi componenti del design in modo olistico.

La violazione dell'ISP riguarda principalmente una scarsa leggibilità (e in una certa misura una bassa coesione). Ma l'impatto sulla manutenzione e sul riutilizzo del codice è molto meno sinistro rispetto all'SRP.

Inoltre, il codice di refactoring per la conformità ISP, sembra essere solo un cambiamento strutturale.

veda anche il mio blog per SRP e ISP

+0

Il punto che sono venuto a prendere è che SRP è una responsabilità nel dominio, mentre ISP è un singolo comportamento. Quindi in una biblioteca che ha una classe per 'Book's e una per' Movie's è un SRP, ma poi 'getDueDate()' e 'getMexRenewal()' sono la loro interfaccia (ad esempio 'Rentable') da' getId() '(eg' Identifiable') è ISP, anche se tutte le classi 'Affittabili 'saranno' Identificabili'. È quasi come se la definizione di "atomico" o "separato" fosse diversa per le interfacce di quanto non lo sia per le classi. – ArtB

+0

Non esiste una definizione formale per "atomico" o "separato". A tale riguardo, le considerazioni sulla progettazione per la creazione di una classe sono le stesse dell'interfaccia. – aknon

+0

Sarebbe sbagliato dire che i metodi di interfaccia definiscono una responsabilità per la classe di implementazione? Deve essere, altrimenti ci sono alcuni metodi di interfaccia scavalcati con un'implementazione 'NIL' nella classe implementata. Per inserire le tue parole, i metodi di interfaccia (messi insieme) definiscono un comportamento "atomico" di un tipo. Il comportamento "atomico" delle classi, o la cosiddetta "responsabilità", è un aggregato di molti di questi comportamenti. (E naturalmente, per una classe non definitiva, tutti i metodi pubblici devono essere sostituibili con diverse implementazioni) – aknon