Blog

Odkryj moc czystego kodu budowanie solidnego i efektywnego oprogramowania

Odkryj moc czystego kodu budowanie solidnego i efektywnego oprogramowania

Czysty kod — czyli jaki? Choć powstało już na ten temat wiele książek, w praktyce trudno jest trzymać się wszystkich zaleceń. W tym artykule poruszę aspekty, o które sam dbam i na które zwracam uwagę podczas code review.

Czym jest code review?

Zacznijmy od wyjaśnienia, czym jest code review. Jak sama nazwa wskazuje, jest to proces przeglądania kodu przez członków zespołu. Robi się to, aby wyłapać ewentualne błędy w kodzie i przetransferować wiedzę między programistami.

Ten drugi aspekt jest dla mnie nawet ważniejszy, bo każdy członek zespołu developerskiego powinien mieć równą wiedzę na temat powstającego oprogramowania. Nie chcemy przecież dopuścić do sytuacji, gdy z powodu urlopu lub choroby jednego z programistów praca stoi, bo nikt inny nie jest w stanie naprawić błędu.

O czysty kod należy jednak dbać już na etapie jego powstawania. Do code review powinien trafiać jak najlepszy kod, a sam proces powinien być jedynie formalnością i okazją do zapoznania się z wprowadzonymi zmianami przez resztę zespołu. Inaczej odbijanie piłeczki między twórcą kodu i pozostałymi programistami mogłoby trwać tygodniami.

Co oznacza „jak najlepszy kod”?

Każdy projekt powinien posiadać jasno zdefiniowany standard, do którego stosują się wszyscy członkowie zespołu. Mowa tu o zbiorze reguł dotyczących m.in. Wielkości wcięć, stawiania (bądź nie) średników na końcu wiersza, konwencji zapisu nazw zmiennych, funkcji, klas itd.

W wielu kwestiach istnieją odgórnie przyjęte zasady i najlepiej się ich po prostu trzymać, jednak w każdym projekcie zasady te mogą się od siebie mniej lub bardziej różnić. Na szczęście istnieją narzędzia, które ułatwiają pilnowanie trzymania się ustalonych zasad. W przypadku JavaScript każdy powinien znać Prettier1 oraz ESLint2. Oba pozwalają na sprawdzenie poprawności składniowej i stylistycznej kodu źródłowego, jednak jest pomiędzy nimi kilka istotnych różnic.

Przydatne narzędzia

Prettier jest narzędziem pozwalającym na automatyczne formatowanie kodu, na podstawie ściśle określonych zasad. Działa z różnymi językami programowania, w tym JavaScript, HTML, CSS, SCSS i JSON. Umożliwia automatyczną edycję spacji i wcięć, a także formatowanie ciągów tekstu, liczb, zmiennych oraz innych elementów kodu. Jedną z jego największych zalet jest łatwość użycia. Wymaga on jedynie odpowiedniego ustawienia w edytorze kodu.

ESLint umożliwia dokonanie analizy kodu, w celu zidentyfikowania potencjalnych błędów i złych praktyk, a także pozwala na wskazanie w konfiguracji zasad, jakich program ma się trzymać. Współpracuje z JavaScript i umożliwia wykrywanie błędów w postaci niezadeklarowanych zmiennych, nieprawidłowych wcięć czy nieprzestrzegania zasad stylu kodu. ESLint jest łatwy w użyciu i działa z wieloma popularnymi edytorami kodu.

Dwa powyższe narzędzia powinny w pewnym stopniu zadbać za nas o kod. Wiele jednak zależy od tego, jak zostaną skonfigurowane.

SOLID

Kwestie związane ze specyfiką języka mamy załatwione, jednak nie jest to koniec dbania o nasz kod. Przy wytwarzaniu oprogramowania należy się kierować określonymi zasadami. Jednym z najpopularniejszych podejść jest SOLID, czyli akronim zawierający w sobie pięć głównych zasad zapewniających elastyczność, rozszerzalność i utrzymanie kodu w przyszłości. Oto co oznaczają poszczególne litery:

S - Single Responsibility Principle (zasada pojedynczej odpowiedzialności).

Zasada mówi o tym, że każdy obiekt w programie powinien mieć tylko jedną odpowiedzialność. Innymi słowy, klasa powinna być odpowiedzialna tylko za jedną rzecz. Gdy każda klasa ma jasno określony cel, łatwiej jest utrzymywać i modyfikować kod.

O - Open-Closed Principle (zasada otwarte-zamknięte)

Zasada ta sprowadza się do tego, że kod powinien być otwarty na rozszerzenie, ale zamknięty na modyfikację. Istniejące klasy lub moduły powinno się modyfikować jedynie wtedy, kiedy jest to konieczne. Minimalizuje to niebezpieczeństwo przypadkowego wprowadzania błędów w kodzie.

L - Liskov Substitution Principle (zasada podstawienia Liskov)

Trzecia z zasad mówi, że obiekt klasy dziedziczącej powinien dać się zastąpić przez obiekt klasy bazowej. Czyli klasa dziedzicząca powinna działać tak samo, jak klasa bazowa. Pomaga to uniknąć błędów w kodzie, gdy korzystamy z obiektów klasy dziedziczącej.

I - Interface Segregation Principle (zasada segregacji interfejsów)

Zakłada ona, że interfejsy powinny być rozbite na mniejsze, bardziej specyficzne i związane tylko z konkretną funkcjonalnością.

D - Dependency Inversion Principle (zasada odwracania zależności)

Mówi o tym, że moduły i klasy powinny opierać się na abstrakcjach, a nie na szczegółach implementacyjnych. Chodzi tu o wykorzystywanie interfejsów zamiast konkretnych klas. Ułatwia to wprowadzanie zmian i zwiększa elastyczność.

Moim zdaniem, powyższe zasady stanowią fundament wytwarzania oprogramowania. Bez stosowania się do nich, ciężko mówić o czystym kodzie, który zrozumieją inni, a także my sami, wracając do niego w przyszłości.

Trzymaj się zasad, ale z głową

Próbując trzymać się zasad, warto zachować zdrowy rozsądek, bo czasami może to prowadzić do nadmiernych komplikacji. W takich sytuacjach przychodzi nam z pomocą zasada KISS (Keep It Simple, Stupid!). Ma ona na celu ograniczenie poziomu skomplikowania sytuacji i oznacza, że w sytuacjach problemowych preferowane są proste rozwiązania. Skomplikowany kod, mający wiele elementów, może prowadzić do powstawania nieskoordynowanych i niestabilnych systemów.

Nie należy także zapominać o zasadzie DRY (Don't Repeat Yourself). Jak sama nazwa wskazuje, chodzi w niej o unikanie powtórzeń w kilku miejscach w kodzie. Powtarzanie wiele razy tej samej informacji nie tylko zwiększa czasochłonność pisania kodu, ale także potęguje ryzyko występowania błędów i niepotrzebnie komplikuje proces utrzymania.

Zasada DRY nie oznacza, że programista ma napisać dany kod tylko raz, bo często zdarza się, że dana funkcja wymaga skopiowania i zastosowania w różnych miejscach w kodzie. Jednak w przypadku powtarzającego się fragmentu, należy wydzielić go do osobnej funkcji, która może być użyta w wielu miejscach.

Należy pamiętać, że zasada ta nie dotyczy jedynie kodu, ale także informacji, takich jak nazwy zmiennych, stałe i opisy funkcji. Podsumowując, zasada ta jest istotna dla każdego programisty, który chce stworzyć łatwy w utrzymaniu i rozwoju, a także skalowalny kod.

Czy pisać komentarze?

Chciałbym jeszcze na koniec poruszyć kontrowersyjny temat, który dzieli programistów na dwa obozy. Pisać komentarze, czy ich nie pisać? Oto jest pytanie.

Jednym z głównych argumentów za pisaniem komentarzy, jest ułatwienie zrozumienia kodu przez innych programistów. Przy skomplikowanych projektach, zawierających wiele plików i funkcji, brak komentarzy może utrudniać zrozumienie zasadności konkretnego fragmentu kodu.

Zwolennicy pisania komentarzy uważają też, że pozwalają one szybciej i bardziej precyzyjnie odnajdywać konkretne części kodu, jak i łatwiej utrzymywać i rozwijać kod. Brak jasnego i klarownego opisu kodu może według nich skutkować trudnymi do poprawienia błędami. Ostatnią z zalet pisania komentarzy jest odświeżanie pamięci, gdy do kodu trzeba wrócić po dłuższym czasie.

Po drugiej stronie barykady są osoby twierdzące, że dobry kod powinien być samoopisujący się, a nawyk pisania komentarzy może skutkować kiepskim nazewnictwem zmiennych i funkcji. Skoro mamy komentarz, to po co mamy się do tego przykładać, prawda? Ponadto, używanie komentarzy skutkuje tym, że w plikach mamy dużą ilością tekstu, która nie jest kodem.

Osobiście zaliczam się do tej drugiej grupy. Czasami rzeczywiście zdarzają się bardziej złożone funkcjonalności, które powodują, że sam kod może być niewystarczający, szczególnie dla testerów czy też nowych członków projektu. W takich przypadkach preferuję jednak utworzenie osobnego dokumentu i dodanie go do README zamiast dodawania komentarzy.

Jedynym wyjątkiem, gdy piszę komentarze, jest przypadek, gdy robię coś niezgodnego z zasadami, albo gdy jest to obsługa przypadku brzegowego. Wtedy każdy, kto spojrzy w kod w przyszłości, będzie wiedział, dlaczego powstał taki dziwny twór.

Podsumowanie

Istnieje wiele zasad i narzędzi, które pomagają tworzyć czysty i czytelny kod. Umiejętne wykorzystywanie narzędzi, takich jak opisywane wyżej Prettier i ESLint bardzo pomaga w utrzymywaniu spójności i odpowiedniej jakości kodu.

Najważniejsze są jednak zasady projektowania, zapewniające elastyczność, rozszerzalność i utrzymanie kodu w przyszłości. Akronimy SOLID, KISS i DRY to zbiór podstawowych zasad, które powinien mieć na uwadze każdy programista.

Co do pisania komentarzy, jest to kwestia mocno indywidualna, choć ja stoję na stanowisku, że dobry kod, powinien być samoopisujący się.

1 https://prettier.io/

2 https://eslint.org/

Grzegorz Kielar

Grzegorz Kielar

Architekt możliwości

W Kielni Kodu dbam o to, żeby proponowane rozwiązania i technologie były dobrane do potrzeb i budżetu klienta. Poza zarządzaniem firmą i kontaktem z klientami odpowiadam za backend oprogramowania, kwestie związane z serwerami i usługami chmurowymi. Innymi słowy, robię wszystko to, czego nikt nie widzi i nie wie, dlaczego działa, ale działa :)

Prywatnie fotograf amator, mąż i właściciel psa Eliota.