2013-01-17 26 views
31

W jaki sposób "Zasada podziału na interfejsy" SOLID różni się od "Zasada pojedynczej odpowiedzialności"?W SOLID, jaka jest różnica między SRP i ISP? (Zasada pojedynczej odpowiedzialności i zasada podziału interfejsu)

Wikipedii entry for SOLID says że

ISP dzieli interfejsy, które są bardzo duże na mniejsze i bardziej szczegółowych nich tak, że klienci będą mieli tylko wiedzieć o sposobach, które są dla nich interesujące

Jednak dla mnie brzmi to jak zastosowanie SRP do interfejsów i klas. W końcu, jeśli interfejs jest odpowiedzialny tylko za jedną koncepcyjną rzecz, to nie byłbyś w stanie go rozbić dalej.

Czy brakuje mi czegoś lub czy ISP jest zbędny z SRP? Jeśli nie, to co ISP sugeruje, że SRP tego nie robi?

+0

Możliwy duplikat dla http://stackoverflow.com/questions/8099010/is-interface-segregation-principle-only-a-substitue-for-single-responsibility- pr –

+0

Podejrzewam, że technicznie, ale to jest IMHO lepiej napisane, a odpowiedzi bardziej rozwinięte. – ArtB

Odpowiedz

25

SRP mówi nam, że powinieneś mieć tylko jedną odpowiedzialność w module.

Usługodawca internetowy informuje, że nie należy zmuszać użytkownika do konfrontacji z więcej niż jest to konieczne. Jeśli chcesz użyć metody print() z interfejsu I, nie powinieneś już tworzyć instancji klasy SwimmingPool lub DriveThru.

Bardziej konkretnie, idąc od razu do punktu, są różne poglądy na ten sam pomysł - SRP jest bardziej skoncentrowany na punkcie widzenia strony projektanta, podczas gdy ISP jest bardziej skoncentrowany na punkcie po stronie klienta -of-view. Więc w zasadzie masz rację.

To wszystko pochodzi z

ISP został użyty po raz pierwszy sformułowane i Robert C. Martin, gdy robi niektóre konsultingową dla Xerox. Firma Xerox utworzyła nowy system drukowania, który umożliwia wykonanie różnych zadań, takich jak zszywanie zestawu wydruków i faksowanie. Oprogramowanie dla tego systemu zostało utworzone z poziomu gruntu i pomyślnie wykonało swoje zadania. Wraz z rozwojem oprogramowania modyfikacja stała się coraz trudniejsza, dzięki czemu nawet najmniejsza zmiana w modelu wymagałaby przesunięcia do godziny. To czyniło go prawie niemożliwym do dalszego rozwoju. Problem z projektowaniem polegał na tym, że jedna główna klasa zadań była używana przez prawie wszystkie zadania. Za każdym razem, gdy trzeba było wykonać zadanie drukowania lub zszywania, wykonano połączenie z pewną metodą w klasie Job. W rezultacie powstała ogromna lub "gruba" klasa z wieloma metodami specyficznymi dla różnych klientów. Z tego powodu zszywki będą wiedzieć o wszystkich metodach drukowania , nawet jeśli nie były dla nich przydatne.

tak

Rozwiązanie sugerowane przez Martin to, co nazywa się Interfejs Segregacja Zasada dzisiaj. W przypadku oprogramowania Xerox warstwa interfejsu między klasą Job i wszystkimi jej klientami została dodana przy użyciu zasady odwrócenia zależności.Zamiast jednej wielkiej klasy zadań Job, interfejs zszywania lub interfejs zadań drukowania został utworzony , który byłby używany odpowiednio przez metody Zszywania lub Drukowania, metody klasy Job. Dlatego utworzono jeden interfejs dla każdego zadania, który został zaimplementowany przez klasę Job.

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

+1

Hmm, jedyne wyróżnienie, jakie widzę ze swojego wpisu, to '" Jeśli chcesz użyć metody print() z interfejsu I, nie powinieneś tworzyć instancji klasy SwimmingPool lub DriveThru. "Co szczerze brzmi dużo jak "[Chciałeś banana, ale masz goryl trzymający banana i całą dżunglę.] (http://www.johndcook.com/blog/2011/07/19/you-wanted-banana/) ". Czy mówisz, że komentarz do banana jest parafrazą ISP? – ArtB

+0

To prawda. –

+0

Często widzisz źle zaprojektowany kod, w którym do korzystania z niektórych funkcji, musisz najpierw włączyć rejestrowanie, a następnie włączyć usługi A, B i C, podczas gdy wszystko, co chcesz zrobić, to obliczyć obszar wielokropka, który jest czymś, czego oczekuje się, że nie będzie wymagać tego wszystkiego. –

5

SRP jest zaniepokojony tym, co robi moduł, i jak to jest zrobione, wykluczający jakąkolwiek mieszankę poziomach abstrakcji. Zasadniczo, dopóki komponent może być szeroko zdefiniowany za pomocą jednego zdania, nie zepsuje SRP.

Z drugiej strony dostawca usług internetowych jest zainteresowany tym, jak należy zużywać moduł, czy warto spożywać tylko część modułu, ignorując pewien aspekt.

Jako przykład kodu, który zachowuje ducha lub SRP, ale może przerwać ISP jest wzór Fasady Ma jedną odpowiedzialność, "zapewniając uproszczony dostęp do większego podsystemu", ale jeśli bazowy podsystem musi eksponować szalenie różne myśli, to łamie ISP.

To powiedziawszy, zazwyczaj, gdy fragment kodu łamie zasadę SOLID, często psuje całą partię. Konkretne przykłady, które łamią określoną zasadę, a jednocześnie zachowują resztę, są rzadkością na wolności.

4

SRP i ISP ostatecznie sprowadzają się do tych samych rzeczy. Implementacja jednego z nich wymaga podziału klas lub interfejsów.

Istnieją jednak różnice na innych frontach.

  1. Naruszenie SRP może mieć daleko idący wpływ na całą strukturę projektu, powodując słabą łatwość konserwacji, ponowne użycie i oczywiście niską spójność i sprzężenie.
  2. SRP ma wpływ zarówno na behawioralne, jak i strukturalne elementy struktury obiektu.
  3. Ponowne projektowanie w przypadku naruszeń SRP wymaga znacznie głębszej analizy, wymaga spojrzenia na różne elementy projektu w sposób holistyczny.

Naruszenie dostawcy usług internetowych dotyczy głównie słabej czytelności (i do pewnego stopnia niskiej spójności). Jednak wpływ na utrzymanie i ponowne użycie kodu jest znacznie mniej groźny niż SRP.

Co więcej, kod refaktoryzacji konformacji ISP wydaje się być tylko zmianą strukturalną.

Zobacz także mój blog dla SRP i ISP

+0

Punktem, do którego doszedłem, jest to, że SRP jest jednym z obowiązków w domenie, podczas gdy ISP jest pojedynczym zachowaniem. Zatem w bibliotece posiadającej jedną klasę dla 'Book's i jedną dla' Movie's jest SRP, ale wtedy 'getDueDate()' i 'getMexRenewal()' są ich własnym interfejsem (np. 'Rentable') z' getId() '(np.' Identableable') to dostawca usług internetowych, nawet jeśli wszystkie klasy "do wynajęcia" będą również "identyfikowalne". To prawie tak samo, jak definicja "atomowej" lub "oddzielnej" jest inna dla interfejsów niż dla klas. – ArtB

+0

Nie ma formalnej definicji "atomowej" lub "oddzielnej". W tym względzie rozważania projektowe dotyczące budowy klasy są takie same, jak w przypadku interfejsu. – aknon

+0

Czy błędem będzie twierdzenie, że metody interfejsu definiują odpowiedzialność za klasę wykonawczą? Musi tak być, w przeciwnym razie istnieją pewne przesłonięte metody interfejsu mające implementację "NIL" w zaimplementowanej klasie. Aby wyrazić swoje słowa, metody interfejsu (złożone) definiują "atomowe" zachowanie typu. "Atomowe" klasy, lub tzw. "Odpowiedzialność", jest zbiorem wielu takich zachowań. (Oczywiście, dla nie końcowej klasy, wszystkie publiczne metody muszą być zastępowalne różnymi implementacjami) – aknon