Tworzenie kodu według najlepszych praktyk
2 godz. 45 min · Full-stack i Programowanie
Rafał PiekaraSoftware KomandosNie zrozumiesz SOLIDa bez teoretycznych podstaw. Przejdziemy przez założenia stojące za każdą z nich. Przeanalizujemy problemy, które możesz spotkać oraz dowiesz się dlaczego ciągle jeszcze tak wielu programistów nie stosuje się do tych zasad.
Ruby i Typescript to technologie, które świetnie odzwierciedlają uniwersalizm SOLIDa. Te złote zasady działają w językach dynamicznie typowanych i interpretowanych jak Ruby oraz przy statycznym typowaniu na przykładzie Typescript.
Zanim zabierzesz się za programowanie warto poćwiczyć SOLIDny sposób myślenia. Zmierzysz się z zadaniami, w ramach których będziesz projektować kod tak, aby wszystkie zasady SOLID znalazły w nim swoje zastosowanie.
Prawda jest taka, że kod, z którym w większości pracujemy ma swoją historię. Czasami historia ta jest tak bolesna, że klasy i metody są zagmatwane, poplątane i trudne w utrzymaniu. Gdy dotrzesz do tego miejsca będziesz mieć w arsenale wszystkie potrzebne narzędzia, żeby zmierzyć się z zadaniami praktycznymi, które przekształcą kod legacy w SOLIDne arcydzieło.
Tak ważny temat, jak testowanie nie może zostać pominięty. Między innymi po to też stosujemy zasady SOLID, żeby nasz kod praktycznie sam się testował. Napiszesz więc testy, których wzorce możesz wykorzystać w dowolnym projekcie, dowolnej technologii, jeśli tylko kod, który testujesz będzie spełniał wymagania zasad SOLID.
Nie ma znaczenia, czy dopiero zaczynasz przygodę z programowaniem, czy też jesteś starym wyjadaczem, który klasami i interfejsami myśli przy zagryzaniu tosta na śniadanie. Ten kurs jest właśnie dla Ciebie. Technologia ani język programowania też nie mają znaczenia. Zasady SOLID to uniwersalny zbiór. Ich znajomość sprawi, że Twój kod będzie lepszy, łatwiejszy w utrzymaniu i odporny na perturbacje i zmiany.
Ostatnia zasada The Dependency Invasion Principle,
czyli zasada odwracania zależności.
Ta zasada mówi nam o tym, że chcemy mieć elastyczny system,
a najbardziej elastyczny system jest taki, kiedy zależności w tym systemie, w kodzie
tego systemu odnoszą się wyłącznie do abstrakcji, a nie
do konkretnych elementów, czyli odnoszą się do reguł, a nie odnoszą
się do infrastruktury.
I te zależności nie powinny się odnosić do modułów z konkretną implementacją.
Więc jeśli mamy jakieś zależności, one powinny być możliwie jak
najbardziej abstrakcyjne.
I tutaj przychodzą nam z pomocą właśnie statycznie typowane języki z interfejsami.
Mówimy cały czas o interfejsach.
Zależnością powinien być interfejs, a nie konkretna implementacja.
Jako moduły z konkretną implementacją będziemy rozumieć te moduły, w których
zaimplementowane są już konkretne funkcje, czyli mamy zaimplementowane funkcje
zdefiniowane w interfejsach.
Uwaga Statyczne, statycznie typowane języki dynamiczne
typowane języki mogą tutaj nie obrazować tego do
końca tak, jak potrzeba.
Posłużmy się cytatem Roberta Martina.
W tworzonym systemie musimy natomiast unikać zależności od konkretnych, ale
ulotnych elementów, czyli implementacja.
Takimi elementami są moduły, nad którymi aktywnie pracujemy, a przez to poddawane
są one częstym modyfikacjom, częstym modyfikacją.
Czyli po prostu implementujemy jakiś kod i on żyje, on się zmienia.
Natomiast interfejs kiedy definiujemy tylko interfejs.
Typ interfejsu, Typ metody w interfejsie parametrów on będzie w miarę stabilny,
bo logika zależy od implementacji.
Definicja jest gdzie indziej, kontrakt jest gdzie indziej, więc będziemy mieć
tutaj stabilną implementację i taką stabilną architekturę.
Bo stabilna architektura jest architekturą, w której unika się
zależności od ulotnych implementacji, czyli od konkretnych funkcji, od
konkretów, a faworyzowane jest wykorzystywanie stabilnych,
abstrakcyjnych interfejsów.
Czyli często mówimy o tym np.
w językach statycznie typowanych typu Java czyste Sharp.
Tam bardzo duży nacisk kładzie się na definiowanie interfejsów.
W skrypcie też będziemy mieć definiowanie interfejsów.
W dynamicznie typowanych językach typu Python, Ruby to pojęcie.
Ta zasada będzie bardziej rozmyta.
Trzeba z większą subtelnością, z większą dokładnością skupiać się na
definiowaniu interfejsów.
Ten cognitive load niestety jest zdjęty z interpretera czy z kompilatora?
Jak to jest w językach kompilowane na programistę?
Niestety.
A co to są te stabilne abstrakcje w ogóle?
Bo stabilne abstrakcje to takie abstrakcje, które nie odnoszą się w żaden
sposób do konkretnych, ulotnych klas.
Definiują tylko kontrakt.
Stabilne abstrakcje nie dziedziczą po konkretnych, ulotnych klasach.
One są często abstrakcyjnymi klasami.
To nie one wykorzystują, ale je się wykorzystuje do budowania konkretnej
implementacji i nie pokrywają tych ulotnych funkcji.
Ulotnych, czyli tych, które są już konkretną implementacją.
Jak to wygląda w kodzie, zobaczysz w następnym materiale.