Programowanie zasad SOLID

43

Z czasem mogłem zrozumieć dwie części SOLID - „S” i „O”.

„O” - nauczyłem się otwartej zasady zamkniętej za pomocą wzoru dziedziczenia i strategii.

„S” - nauczyłem się zasady pojedynczej odpowiedzialności podczas uczenia się ORM (logika trwałości jest odbierana obiektom domeny).

W podobny sposób, jakie są najlepsze regiony / zadania do nauki innych części SOLID („L”, „I” i „D”)?

Bibliografia

  1. msdn - Niebezpieczeństwa związane z naruszaniem zasad SOLID w C #
  2. channel9 - Stosowanie zasad SOLID w .NET / C #
  3. Zasady OOPS (zasady SOLID)
LCJ
źródło
25
zauważ, że wszystkie te pomysły są dobrymi pomysłami i razem są bardzo dobre. ale jeśli zastosujesz je dogmatycznie , spowodują więcej porażek niż sukcesów.
3
OR-maperzy są dobrzy do rozdzielania problemów, a nie do zasady pojedynczej odpowiedzialności. Zobacz ten post programmers.stackexchange.com/questions/155628/..., aby uzyskać omówienie różnic.
Dok. Brown
Przykłady ze świata rzeczywistego blog.gauffin.org/2012/05/…
LCJ
1
@JarrodRoberson Tak, dlatego są one uważane za wytyczne . Nie zapomnij także o pozostałych zasadach: adamjamesnaylor.com/2012/11/12/… (łącznie 11)
Adam Naylor
2
Link @AdamNaylor ma teraz 404ing, został przeniesiony na adamjamesnaylor.com/post/…
mattumotu,

Odpowiedzi:

54

Byłem w twoich butach kilka miesięcy temu, aż znalazłem bardzo pomocny artykuł.

Każda zasada jest ładnie wyjaśniona rzeczywistymi sytuacjami, z którymi każdy programista może się spotkać w swoich projektach. Skracam się tutaj i wskazuję na odniesienie - SOLID Software Development, krok po kroku .

Jak wskazano w komentarzach, istnieje jeszcze jedna bardzo dobra lektura pdf - SOLID Software Development firmy Pablo .

Ponadto istnieje kilka dobrych książek, które bardziej szczegółowo opisują zasady SOLID - Dobra książka o rozwoju oprogramowania SOLID .

Edytuj i komentuj krótkie podsumowanie każdej zasady:

  • „S” - zasada pojedynczej odpowiedzialności wynika z potrzeb firmy, aby pozwolić na zmiany. „Pojedynczy powód do zmiany” pomaga zrozumieć, które logicznie odrębne koncepcje należy zgrupować, biorąc pod uwagę koncepcję biznesową i kontekst, a nie samą koncepcję techniczną. In another words, dowiedziałem się, że każda klasa powinna ponosić jedną odpowiedzialność. Obowiązkiem jest po prostu wykonanie przydzielonego zadania

  • „O” - nauczyłem się otwartej zasady zamkniętej i zacząłem „preferować kompozycję nad dziedziczeniem” i jako takie, preferując klasy, które nie mają metod wirtualnych i są prawdopodobnie zapieczętowane, ale ich rozszerzenie wymaga abstrakcji.

  • „L” - nauczyłem się zasady podstawiania Liskowa za pomocą wzorca repozytorium do zarządzania dostępem do danych.

  • „Ja” - poznałem zasadę segregacji interfejsów, dowiadując się, że klienci nie powinni być zmuszani do implementowania interfejsów, których nie używają (jak w programie Membership Provider w ASP.NET 2.0). Interfejs nie powinien więc mieć „wielu obowiązków”
  • „D” - poznałem zasadę inwersji zależności i zacząłem pisać kod, który można łatwo zmienić . Łatwiejsza zmiana oznacza niższy całkowity koszt posiadania i większą łatwość konserwacji.

Ponieważ w komentarzach wspomniano o przydatnym zasobie z CodePlex, w przykładach podano odniesienie do SOLID

wprowadź opis zdjęcia tutaj

EL Yusubov
źródło
3
Uważam, że następujący zbiór artykułów jest bardzo przydatny: lostechies.com/wp-content/uploads/2011/03/…
Scroog1
Przeczytałem cały ten artykuł i nie jestem sprzedawany na wzorach ani na SOLID. Przykład jest zbyt uproszczony, ale kiedy się komplikuje, złożoność jest sztuczna. Mam jeszcze do czynienia z SOLID OOP w świecie rzeczywistym bez lepszych alternatyw.
Job
3
ponieważ wspomniano tutaj o artykułach Lostechies, istnieje również ten solidexamples.codeplex.com (oparty na lostechies)
ciemny suwak
2
Byłem jednym z autorów ebooka Pablos. Cieszę się, że ludzie nadal uważają to za przydatne. :)
Sean Chambers
1
+1000000 gdybym mógł za podsumowanie zasady otwartego zamknięcia - wszyscy mylą się i myślą, że chodzi o dziedziczenie
AlexFoxGill
11

(I) nterface Segregacja i (D) Odwrócenie zależności można nauczyć się poprzez testowanie jednostkowe i kpiny. Jeśli klasy tworzą własne zależności, nie można tworzyć dobrych testów jednostkowych. Jeśli zależą od zbyt szerokiego interfejsu (lub w ogóle nie ma interfejsu), nie jest bardzo oczywiste, co należy kpić, aby wykonać testy jednostkowe.

StriplingWarrior
źródło
2
+1 to jest bardzo prawdą. Nie musisz nawet przestrzegać (imo) czasami zbyt surowej zasady „test jednostkowy powinien testować tylko jedną rzecz”: jeśli nie możesz wymyślić przyzwoitego zestawu testów dla klasy w ciągu kilku minut, to narusza I i D, a prawdopodobnie także resztę
alfabetu
8

Zasada podstawienia Liskowa zasadniczo nie pozwala na nadużywanie dziedziczenia implementacji: nigdy nie należy używać dziedziczenia tylko do ponownego użycia kodu (jest na to skład)! Stosując się do LSP, możesz być całkiem pewien, że faktycznie istnieje „relacja” między twoją nadklasą a twoją podklasą.

Mówi się, że podklasy muszą implementować wszystkie metody podklasy w podobny sposób, jak implementacja metod w podklasie. Nigdy nie należy zastępować metody z implementacją NOP ani zwracać wartości null, gdy nadtyp generuje wyjątek; zgodnie z warunkami Projektu według umowy, podczas nadpisywania metody należy przestrzegać umowy metody z nadklasy. Sposobem obrony przed złamaniem tej zasady jest nigdy nie zastępowanie zaimplementowanej metody; zamiast tego wyodrębnij interfejs i zaimplementuj ten interfejs w obu klasach.

Zasada segregacji interfejsu, zasada pojedynczej odpowiedzialności i zasada wysokiego współdziałania z GRASP są w jakiś sposób powiązane; odnoszą się one do faktu, że jednostka powinna być odpowiedzialna za tylko jedną rzecz, tak aby istniał tylko jeden powód zmiany, aby zmiana była dokonywana bardzo łatwo.

W rzeczywistości mówi, że jeśli klasa implementuje interfejs, musi zaimplementować i zastosować wszystkie metody interfejsu. Jeśli istnieją metody, które nie są potrzebne w tej konkretnej klasie, interfejs nie jest dobry i musi zostać podzielony na dwa interfejsy, który ma tylko metody wymagane przez klasę oryginalną. Można to rozpatrywać z POV, który odnosi się do poprzedniej zasady, ponieważ nie pozwala na tworzenie dużych interfejsów, aby ich implementacja mogła złamać LSP.

Odwrócenie zależności można zobaczyć we wzorcu fabrycznym; tutaj zarówno komponent wysokiego poziomu (klient), jak i komponent niskiego poziomu (indywidualna instancja do utworzenia) zależą od abstrakcji(Interfejs). Sposób zastosowania go w architekturze warstwowej: nie należy definiować interfejsu do warstwy w zaimplementowanej warstwie, ale w wywoływanym module. Na przykład interfejs API do warstwy źródła danych nie powinien być zapisywany w warstwie źródła danych, ale w warstwie logicznej dla biznesu, gdzie należy ją wywołać. W ten sposób warstwa źródła danych dziedziczy / zależy od zachowania zdefiniowanego w logice biznesowej (a więc inwersji), a nie odwrotnie (jak w normalny sposób). Zapewnia to elastyczność w projektowaniu, umożliwiając logice biznesowej pracę bez zmiany kodu, z innym całkowicie innym źródłem danych.

m3th0dman
źródło
1
Świetne wyjaśnienie na temat Liskowa. :)
John Korsnes