-

Jakie są najlepsze praktyki, aby pracować skutecznie z legacy code?

Praca z kodem legacy może spędzać sen z powiek nawet najlepszym programistom. Wiąże się ona często z mozolnym debugowaniem pojedynczych metod i odkrywaniem nielogicznych - choć czasem tylko na pierwszy rzut oka - zależności. Z tego artykułu dowiesz się, jak powstaje legacy code oraz jakich technik i narzędzi warto używać, aby pracować z nim skutecznie, zwiększając jednocześnie swoją wydajność i unikając niepotrzebnego stresu.

Co to jest legacy code?

Legacy code to termin odnoszący się do istniejącego kodu źródłowego, który powstał w przeszłości i pozostaje w użyciu. Na początku projektu mógł być on zrozumiały i czytelny. Z upływem czasu jednak wszystkie odstępstwa od dobrych praktyk programowania i pierwotnych założeń popełniane przez dewelopera lub zespół przerodziły się w końcu w duży problem. W rezultacie taki kod może być trudny do zrozumienia, utrzymania i rozwijania z powodu braku dokumentacji lub złej struktury.

Programiści miewają różne opinie na temat legacy code – niektórzy mogą go postrzegać jako wyzwanie, inni jako obciążenie. Ważne jest znalezienie skutecznych strategii pracy z nim, aby zapewnić kontynuację rozwoju aplikacji czy strony internetowej. Po czym rozpoznać kod legacy? 

Sygnały wskazujące, że masz do czynienia z legacy code

Istnieje kilka wyraźnych wskaźników, które pozwolą Ci ocenić, że kod ma charakter legacy. Oto przykłady niektórych z nich, wytypowane przez doświadczonych deweloperów z Droptica:  

Legacy code może przyjmować formę kodu nieobiektowego, źle sformatowanego lub bez dokumentacji. 

 

  1. Kod w innym języku niż angielski - używanie jednolitego języka programowania pozwala zadbać o klarowność kodu, ułatwiając jego zrozumienie i utrzymanie przez innych programistów w przyszłości. Widząc zmienną isPremiumUser, każdy deweloper rozpozna cel jej użycia. Natomiast zastosowanie zmiennej jestUzytkownikiemPremium może być mylące lub zupełnie niezrozumiałe dla osób nieznających języka polskiego.
     
  2. Źle sformatowany kod - czytelność kodu ma kluczowy wpływ na efektywność pracy. Stosując niestandardowe formatowanie, programista sprawia, że kod będzie czytelny wyłącznie dla niego (przynajmniej dopóki sam nie zapomni, do czego miał służyć) i już przy pierwszych zmianach lub debugowaniu, taki kod będzie stwarzał problemy.
     
  3. Kod nieobiektowy - często uznawany za legacy code ze względu na to, że programowanie obiektowe jest obecnie dominującym paradygmatem. Kod nieobiektowy może charakteryzować się brakiem struktury obiektowej, globalnymi zmiennymi, złożonością proceduralną i przestarzałymi wzorcami projektowymi, co utrudnia jego utrzymanie i rozwijanie.
     
  4. Kod bez możliwości testowania - brak automatycznych testów w przypadku kodu nie pozwala na skuteczne zweryfikowanie jego poprawności i działania. W efekcie jest on bardziej podatny na błędy, trudny w utrzymaniu i rozwijaniu. Nietestowanie kodu może również prowadzić do wprowadzania takich zmian, które niosą za sobą ryzyko niechcianych efektów ubocznych lub regresji. Na przykład, naprawiając jeden element, programista może przy okazji niepostrzeżenie zepsuć kilka innych i nawet tego nie zauważyć. 
     
  5. Kod bez dokumentacji - bywa traktowany jako forma kodu legacy ze względu na trudności, jakie stwarza w zrozumieniu jego działania, celów i zależności. Brak odpowiedniej dokumentacji utrudnia wprowadzanie zmian, utrzymanie i rozwijanie kodu przez inne osoby. Może też prowadzić do konieczności podejmowania działań detektywistycznych, co zwiększa ryzyko błędów i wpływa na efektywność pracy programistów.
     
  6. Niewspierane oprogramowanie - wsparcie dla oprogramowania (języka programowania, frameworku, jego modułów i dodatkowych bibliotek) obejmuje regularne aktualizacje, łatki bezpieczeństwa i support techniczny ze strony twórców. Brak aktywnego wsparcia oznacza, że oprogramowanie może być przestarzałe, może zawierać luki bezpieczeństwa i nie współgrać z nowymi środowiskami. W przypadku takiego oprogramowania, utrzymanie i rozwój kodu staje się trudniejsze.

Jak eliminować legacy code z projektu?

Eliminowanie legacy code w trakcie pracy nad projektem jest kluczowe dla utrzymania jakości kodu i ułatwienia przyszłego rozwoju oprogramowania. Istnieje kilka skutecznych praktyk, które można wdrożyć już na etapie pisania kodu, aby w przyszłości nie był postrzegany jako legacy.

1. Pisanie kodu zgodnie ze standardami

Tworzenie kodu zgodnie ze standardami jest ważnym czynnikiem zapobiegającym powstawaniu legacy code. Zastosowanie jednolitych standardów kodowania, takich jak nazewnictwo, struktura plików, formatowanie i komentarze, ułatwia zrozumienie kodu przez innych programistów. Dzięki temu kod staje się bardziej przejrzysty, łatwiejszy do utrzymania i modyfikacji, co minimalizuje ryzyko, że zostanie uznany za legacy code w przyszłości.

Ponadto, korzystanie z dobrych praktyk projektowych, takich jak podział na moduły, odpowiednie zarządzanie zależnościami i unikanie nadmiernego skomplikowania, pomaga w tworzeniu bardziej elastycznego i skalowalnego kodu, który ma większe szanse na długotrwały rozwój.

2. Stosowanie zasad dobrego programowania

Istotne w ograniczaniu legacy code jest wcielenie w życie zasad dobrego programowania. Należą do nich np. podejścia SOLID i KISS:

  • SOLID to zestaw zasad projektowania oprogramowania, które promują elastyczność, skalowalność i łatwość utrzymania kodu poprzez zastosowanie 5 reguł. Więcej na ten temat przeczytasz w artykule: Najlepsze praktyki dotyczące refaktoringu kodu.
     
  • KISS, czyli “Keep it simple, stupid”, to zasada, którą można w prosty sposób objaśnić hasłem: zapobiegaj niepotrzebnej komplikacji działań. Jeśli możesz coś ułatwić, po prostu to zrób.

Stosowanie tych zasad oraz innych sprawdzonych wzorców projektowych pomaga w utrzymaniu kodu czytelnego, modułowego i łatwo rozszerzalnego. Dodatkowo, dbanie o czystość kodu poprzez eliminację nadmiernego skomplikowania, redundancji i niepotrzebnych zależności również wpływa na zmniejszenie ryzyka, że kod stanie się legacy code.

Praktyki takie jak regularne przeglądy kodu, dokumentowanie i używanie opisowych nazw zmiennych i funkcji również przyczyniają się do utrzymania kodu w dobrej kondycji i minimalizują ryzyko powstawania legacy code.

3. Współpraca z tech leadem kontrolującym rozwój aplikacji

Kolejną dobrą praktyką w pracy z kodem legacy jest zaangażowanie w proces lidera technicznego, czyli tech leada. Ten specjalista powinien kontrolować rozwój aplikacji i jej architekturę w celu uniknięcia powstawania legacy code z kilku istotnych powodów.

Po pierwsze, na tech leadzie spoczywa odpowiedzialność za zapewnienie spójności i zgodności architektonicznej w projekcie. Poprzez czuwanie nad pracą zespołu, lider techniczny może monitorować, czy są przestrzegane dobre praktyki programistyczne, zasady projektowe i standardy kodowania, co pomaga utrzymać wysoką jakość kodu i uniknąć tworzenia potencjalnego legacy code.

Po drugie, kontrola nad rozwojem aplikacji pozwala tech leadowi na śledzenie ewentualnych zmian w wymaganiach i technologiach. W miarę jak aplikacja się zmienia, tech lead może dostosowywać jej architekturę, aby sprostać nowym wymaganiom i wykorzystać najnowsze techniki i narzędzia programistyczne. Dzięki temu można uniknąć sytuacji, w której aplikacja staje się przestarzała i trudna do utrzymania.

Wreszcie, tech lead powinien zarządzać długiem technologicznym. Ten specjalista może identyfikować obszary wymagające refaktoryzacji kodu, wprowadzenia poprawek i optymalizacji, aby utrzymać kod w dobrej kondycji. Dzięki temu zapobiega tworzeniu się legacy code, które może prowadzić do trudności we wprowadzaniu zmian.

4. Tworzenie kodu bez komentarzy

Pisanie kodu zgodnie z zasadą “dobry kod nie potrzebuje komentarza” pomaga unikać tworzenia legacy code z prostego powodu. Gdy kod jest czytelny sam w sobie, to znaczy, że jest dobrze zorganizowany, ma odpowiednie nazwy zmiennych i funkcji oraz jest napisany w prosty i intuicyjny sposób. Nie wymaga dodatkowych opisów, ponieważ jego intencje i działanie są zrozumiałe dla innych programistów. 

Powyższa zasada pozwala nieco zmienić podejście deweloperów. Warto obiektywnie spojrzeć na pisany kod i zastanowić się, czy ktoś inny będzie w stanie rozszyfrować  go już na pierwszy rzut oka, bez dodatkowych wskazówek w komentarzach.

5. Korzystanie z automatycznych narzędzi 

Używanie narzędzi, które czuwają nad przestrzeganiem zasad dobrego programowania, również ograniczają legacy code. Dzięki narzędziom do analizy kodu i linterom, otrzymujesz informację zwrotną dotyczącą zgodności z zasadami programowania, co pomaga uniknąć pomyłek i złych praktyk. 

Narzędzia do automatycznego testowania pozwalają także wykrywać błędy i niezgodności, co minimalizuje ryzyko degradacji kodu do statusu legacy code. W rezultacie ich używanie pomaga tworzyć bardziej jakościowy i trwały kod.

W przypadku przejęcia projektu z legacy code, warto jest poświęcić na początku czas na analizę kodu jednym z wielu dostępnych narzędzi (jego dobór należy dostosować do języka i rodzaju projektu). Często oferują one automatyczną poprawę podstawowych błędów, takich jak złe formatowanie czy źle dobrany przypadek zmiennych.

Narzędzia ułatwiające pracę z legacy code

Pracę z legacy code może ułatwić Ci szereg narzędzi, które pomogą go wykryć, automatycznie poprawią formatowanie, a także zasugerują, jakiej funkcji należy użyć w miejscu jej przestarzałej (deprecated) poprzedniczki. Należy je oczywiście dobrać do używanego języka programowania i środowiska. Tutaj znajdziesz przykłady narzędzi przeznaczonych dla PHP i JavaScriptu.

Narzędzia do weryfikacji legacy code

Poza wymienionymi wcześniej sygnałami wskazującymi na pracę z legacy code, możesz również skorzystać z pomocy IDE (ang. Integrated Development Environment, czyli środowisko dla pisanego kodu) . Większość programów w większym lub mniejszym stopniu (może to być również zależne od ich ustawień, z którymi warto się zapoznać) będzie zwracało uwagę na zduplikowane fragmenty kodu, nieprawidłowe formatowanie czy odstępstwa od wybranego standardu kodowania. Możesz także często zainstalować do nich rozszerzenia skupiające się na pracy z konkretnym frameworkiem, takim jak Drupal, Symfony czy Laravel.

W trakcie sprawdzania aktualności oprogramowania projektu warto pamiętać, że wiele informacji na temat używanych wersji oprogramowania jest dostępnych w panelu administracyjnym strony. Zwykle można tam znaleźć listę modułów, które wymagają aktualizacji. Natomiast po stronie frontendu z pomocą przyjdą Ci wtyczki do przeglądarki, takie jak Wappalyzer. Wykrywają one, jakie technologie są użyte w witrynie internetowej i analizują jej działanie.

W wykryciu kodu legacy może pomóc narzędzie Wappalyzer, czyli wtyczka do przeglądarki internetowej.


Skan strony internetowej Droptica.com wykonany z użyciem wtyczki Wappalyzer (źródło)

Narzędzia do porządkowania legacy code

Wiele mniejszych błędów związanych z legacy code możesz poprawić, korzystając z narzędzi przeznaczonych dla konkretnych języków i frameworków. Po analizie kodu przedstawią one listę wykrytych błędów, zwykle informując o możliwości automatycznej poprawy części z nich. Oto przykłady tego rodzaju narzędzi: 

  • Code Sniffer - popularne narzędzie wśród deweloperów PHP i Drupala. Po ustawieniu odpowiedniego standardu kodowania, oferuje dogłębną analizę kodu.
     
  • CS Fixer - niezawodne rozwiązanie dla programistów korzystających z frameworka Symfony, które automatycznie naprawia i dostosowuje formatowanie kodu do ustalonych standardów, poprawiając czytelność i spójność projektu.
     
  • ESlint/JSlint - popularne narzędzia do statycznej analizy kodu JavaScript, które pomagają deweloperom w utrzymaniu czystego i spójnego kodu poprzez identyfikację i zgłaszanie potencjalnych błędów oraz niezgodności z zasadami kodowania.
W utrzymaniu czystego i spójnego kodu w technologii JavaScript może pomóc narzędzie online ESlint.

Źródło: eslint.org

  • PHPStan - potężne narzędzie statycznej analizy kodu dla języka PHP, które pozwala programistom wykrywać błędy, niezgodności typów i potencjalne problemy w czasie kompilacji, poprawiając jakość i niezawodność kodu.
     
  • Larastan - rozszerzenie dla PHPStan, które dostarcza statyczną analizę kodu dla aplikacji opartych na frameworku Laravel, umożliwiając programistom wykrywanie błędów i poprawianie jakości kodu w czasie kompilacji.
     
  • Rector - narzędzie dla języka PHP, które umożliwia automatyczne przekształcenie kodu źródłowego w celu dostosowania go do nowych standardów, najlepszych praktyk i konwencji. Ułatwia aktualizację projektu do najnowszych wersji PHP oraz poprawia czytelność i jakość kodu.

Praktyki w zapobieganiu legacy code - podsumowanie

Legacy code to określenie na istniejący już kod, który pozostaje w użyciu. Wielu programistów uważa, że trudno się z nim pracuje i jest ciężki do zrozumienia ze względu na to, że np. nie przestrzega standardów kodowania w danym języku lub framework’u czy też korzysta z przestarzałych technologii. 

Pracę z kodem legacy może ułatwić wcielenie w życie wyżej wymienionych strategii oraz używanie narzędzi stworzonych do utrzymywania czystego kodu. Pomagają one w analizie i automatycznie poprawią mniejsze błędy. Dobrze jest też pamiętać i postarać się o wdrożenie testów jednostkowych, dzięki którym upewnisz się, że wprowadzane zmiany odnoszą zamierzone skutki. Jeśli potrzebujesz dodatkowego wsparcia przy legacy code, nasz doświadczony zespół programistów Drupala, PHP czy Symfony pomoże Ci dobrać właściwą strategię.

3. Najlepsze praktyki zespołów programistycznych