Jakiś czas temu brałem udział w rekrutacji na stanowisko WordPress Developer, rozmawiałem z przedstawicielami firmy o moich umiejętnościach – miękkich jak i twardych.

Rekrutacja była podzielona na trzy części. Pierwsza część to zaprogramowanie pluginu do WordPressa – zadanie rekrutacyjne. Druga i trzecia część polegała na rozmowie i odbywała się na kamerkach w aplikacji Google Meet. W drugiej części zostały poruszone tematy dotyczące między innymi: czy pracowałem w sprintach, jakie mam doświadczenie w pracy z zespołem, jak sobie radzę z presją czasu i nadmiarem obowiązków – klasyczne pytania. Ostatnim etapem było code review z deweloperem oraz.. przeprowadzenie testu znajomości skrótów (?).

Tak, sprawdzali czy potrafię rozwinąć skróty. Poczułem się znowu jakbym chodził do szkoły i nauczyciel programowania uczył mnie suchych definicji zamiast pokazać jak napisać kod! Przerażające.

Muszę jednak przyznać, że nie znałem wszystkich rozwinięć skrótów typu DRY, SOLID, AGILE. Nie znałem, natomiast stosowałem te praktyki przez ostatnie 3 lata swojej pracy. Zaskakujące? Troszkę tak. Część zasad stosowałem intuicyjnie, część zasad widziałem w kodzie od starszych kolegów. Podczas rekrutacji, kiedy byłem odpytywany ze znajomości definicji, zdałem sobie sprawę, że wiedza (ta teoretyczna) musi być istotna na równi z wiedzą praktyczną – przynajmniej w oczach rekrutującego.

W momencie gdy nie potrafiłem rozwinąć skrótu DRY, prowadzący rekrutację wytłumaczył mi na czym polega ta zasada – Don’t Repeat Yourself. Powiedziałem wtedy:
– hah, stosuję tą zasadę tak często jak to możliwe – Dla mnie to było naturalne, dla innych jest to złota zasada, której muszą się nauczyć. Takich zasad jest więcej.

Poniżej przygotowałem listę pojęć, które powinieneś znać aby stać się lepszym, bardziej świadomym programistą.

  1. DRY
  2. Agile
  3. SOLID
  4. SoC
  5. Wzorce i antywzorce projektowe – refactoring.guru
  6. Hermetyzacja, polimorfizm, dziedziczenie, przeciążanie
  7. Mów, nie pytaj
    https://bulldogjob.pl/readme/czym-sa-zapachy-kodu-w-php-czysty-kod-z-podejsciem-oop
  8. Git – repozytorium, branch, pull request, commit,

*lista będzie stale rozszerzana i aktualizowana

SOLID

Skrót SOLID powinieneś kojarzyć z terminem programowania obiektowego, składa się z 5 zasad, które każdy programista POWINIEN znać, wdrażać i respektować – nieważne czy programujesz obiektowo czy strukturalnie.
Wiem, na początku będzie trudno. Wiem, znajomość teorii nie zawsze przekłada się na praktykę. Wiem, czasami poprawniej będzie złamać jedną z zasad aby spełnić zalożenia projektu – ale wiesz co? Wiem też, że na początku drogi samuraja programisty spotyka nas chaos. Chaos ten dobrze uporządkować a najlepszym sposobem jest zastosowanie się do wzorców i zasad. Może i na początku Twój kod nie będzie idealny ale będzie przynajmniej SOLIDnie POPRAWNY. A to już coś 😉

S jak Single Responsibility Principle (SRP) – zasada pojedynczej odpowiedzialności. W dużej mierze chodzi o to aby klasa, funkcja lub moduł X wykonywała zadania, które wykonywać powinna. Przykładowo, tworząc klasę Product, oczekujemy od klasy że będzie przechowywała takie dane jak: nazwa produktu, typ produktu, cena, zdjęcie. Jeżeli oczekujemy, że klasa Product zwróci informację o koszcie wysyłki, wówczas nasze oczekiwania są niezgodne z zasadą SRP. Informacje o produkcie przechowujmy w klasie Product, informacje o wysyłce w klasie Shipping. Keep it simple, sully!

O jak Open/Closed Principle (OCP) – Otwierajmy głowy, zamykajmy hejterów… żartuję.. chociaż nie.
Zasada ta prawi, abyśmy tworzyli moduły łatwe do rozszerzania ale zamknięte na modyfikację.
IMO ta zasada dotyczy zarówno etapu kiedy tworzymy nowy kod jak i kiedy musimy dodać nową funkcjonalność do istniejącego już rozwiązania. Starajmy się zamiast edytować istniejący kod – rozszerzać go o nowe funkcjonalności.

L jak Liskov umiała w programowanie (LSP) – Liskov Substition Principle – Zasada podstawiania. Jest to bardzo abstrakcyjna zasada, dlatego postaram się przy niej dłużej zatrzymać aby ją prawidłowo przedstawić.


Basia Liskov mówi:

Funkcje, które używają wskaźników lub referencji do klas bazowych, muszą być w stanie używać również obiektów klas dziedziczących po klasach bazowych, bez dokładnej znajomości tych obiektów

Zasada ta jest spełniona, jeżeli klasa dziedzicząca po klasie bazowej zawiera wszystkie metody klasy bazowej. Słowo podstawianie odnosi się do sposobu testowania klas. Oprę to na przykładzie:

Tworzymy 2 klasy: Prostokąt i Kwadrat. Klasa Kwadrat dziedziczy metody po klasie Prostokąt, a wiec Kwadrat zawiera wszystkie metody klasy Prostokąt. Klasa Prostokąt posiada implementacje metod LiczObwód oraz LiczPoleKwadratowe.

Tworzymy obiekt klasy Prostokąt. Aby zasada podstawiania była spełniona, zamieńmy implementacje obiektu klasy Prostokat na Kwadrat.

Jeżeli nowy obiekt klasy Kwadrat pozwala na wykonanie tych samych metod jak w przypadku obiektów Prostokąt to wtedy mówimy że zasada L w akronimie SOLID jest spełniona.

I jak Interfejs Segregation Principle – zasada segregacji interfejsów. W dużym skrócie, zasada ta prawi: Kilka małych, dedykowanych interfejsów jest lepsze niż jeden olbrzymi i ogólny interfejs.

Interfejs jest abstrakcją, w której deklarujemy metody ale nie programujemy logiki tej metody. Logikę metody przygotowujemy w Klasie do której przypisaliśmy dany Interfejs. Jeżeli w Interfejsie mamy zdefiniowane 4 metody, to w Klasa która ma przypisany ten interfejs MUSI posiadać zaprogramowaną logikę dla wszystkich 4 metod, nawet jeżeli metody te nic by nie zwracały – innymi słowy, musisz wówczas zaimplementować puste metody – trochę bez sensu, prawda?

Prawda.

Pamiętaj! Do jednej Klasy możesz przypisać N Interfejsów!

Biorąc pod uwagę powyższą adnotacje, możemy podzielić Interfejs zawierający 4 metody, na 4 małe Interfejsy i przypisać je do Klas w zależności od potrzeb.

Przykład:

Posiadamy 2 klasy: Programista oraz Księgowy

Oraz 1 Interfejs: IObowiązki

Interfejs IObowiązki posiada 3 metody: generujRaportCzasuPracy(), programuj(), generujFV()

Jeżeli przypiszemy IObowiazki do klasy Programista, wówczas w klasie tej będziemy mieli jedną niepotrzebną metodę generujFV(), która nic nie będzie zwracać

W klasie Księgowy, również będziemy mieć jedną pustą metodę programuj();

Co więcej, jeżeli będziemy chcieli do Interfejsu dodać nową metodę oplacFV(); tylko dla Księgowego, to w Klasie Programista będziemy musieli również dodać nową metodę. Aby uniknąć generowania niepotrzebnych linii kodu, należałoby interfejs IObowiazki podzielić na 3 mniejsze interfejsy:

  • IObowiazkiKazdegoPracownika + metoda: generujRaportCzasuPracy();
  • IProgramista + metoda programuj();
  • IZarzadzanieFV + metody generujFV(); oraz oplacFV();

Dzieki temu, struktura będzie wyglądała tak:

Klasa Programista będzie miała przypisany IObowiazkiKazdegoPracownika oraz IProgramista. Łączna ilość metod wyniesie 2 (zamiast 4)

Klasa Księgowy będzie miała przypisany interfejs IObowiazkiKazdegoPracownika oraz IZarzadznieFV. Łączna ilość metod będzie równa 3 (zamiast 4).

Simple 😉

D – zasada odwróconej zależności – Dependency Inversion Principle

Ta zasada, podobnie jak w przypadku zasady Liskov jest jedną z trudniejszych do zrozumienia. Zacznę od podręcznikowej definicji a następnie krok po kroku będę wyjaśniał „o co w tym chodzi”

Moduły wysokopoziomowe nie powinny zależeć od modułów niskopoziomowych. Każdy komponent powinien zależeć od abstrakcji. Abstrakcja nie jest zależna od szczegółów – to szczegóły zależą od abstrakcji.

Moduły wysokopoziomowe nie powinny zależeć od modułów niskopoziomowych
Mówiąc moduły, mamy na myśli klasy. Klasy wyższego poziomu nie powinny być zależne od niższych klas.

Każdy komponent powinien zależeć od abstrakcji
Komponent jest funkcją! Abstrakcją jest na przykład Interfejs lub inna klasa! Każda funkcja powinna zależeć od Interfejsu lub Klasy. Innymi słowy, Klasa definiuje funkcję a nie funkcja klasę/


Abstrakcja nie jest zależna od szczegółów – to szczegóły zależą od abstrakcji.
Klasa nie powinna być uzależniona od pierdół używanych podczas implementacji klasy! To pierdołki trzeba odpowiednio dostosować do klasy.