Dżank (junk code) to kod i zależności, które nie przynoszą korzyści projektowi, ale zwiększają jego objętość, czas budowania i obciążenie poznawcze zespołu. W przeciwieństwie do martwego kodu, który nigdy się nie wykonuje, dżank może działać, ale robi to nieefektywnie lub nadmiarowo: dublujące się biblioteki, nieużywane importy, zakomentowane bloki, przestarzałe polyfill-e i dekoracyjne abstrakcje. Według raportu CodeScene Code Health Report (2025), średnio 15 procent zależności w projektach mobilnych nie jest używanych bezpośrednio, a jedynie ciągną pakiety przechodnie. Junk-kod to „zbędna waga” projektu: sprawia, że kod jest grubszy, ale nie silniejszy. Regularny audyt zależności i usuwanie nadmiarowych abstrakcji bezpośrednio poprawiają szybkość budowania i jakość kodu.
Najważniejsze
Dżank (junk code) — zbiorcze określenie dla kodu, konfiguracji i zależności, które występują w projekcie, ale nie niosą wartości funkcjonalnej. Dżank niekoniecznie jest zepsuty lub nieużywany — problem polega na tym, że jego obecność pogarsza metryki projektu bez odpowiedniego uzasadnienia.
Dżank dzieli się na cztery kategorie. Pierwsza — nadmiarowe zależności: biblioteki podłączone dla jednej funkcji, którą można zrealizować standardowymi środkami. Druga — martwy ciężar: zakomentowane bloki, TODO bez ticketów, puste metody i klasy-zastawki. Trzecia — dublujące rozwiązania: dwie biblioteki robiące to samo (na przykład Gson i Kotlin Serialization w jednym projekcie). Czwarta — over-engineering: warstwy architektoniczne, które nie są używane, ale są utrzymywane „na przyszłość”.
Według badań Stripe Engineering Productivity (2025), usunięcie 10 procent dżanku z typowego projektu skraca czas pełnego budowania średnio o 22 procent. Przyczyna: każda zbędna zależność zwiększa graf budowania, każda pusta abstrakcja wymaga czasu na zrozumienie, każdy zakomentowany blok odwraca uwagę.
Główna trudność w walce z dżankiem to brak natychmiastowych konsekwencji. Projekt z junk-kodem kompiluje się i działa. Problemy narastają stopniowo: budowanie zwalnia, liczba transitive dependencies rośnie, a za rok dodanie nowej funkcji zajmuje dwa razy więcej czasu niż powinno.
Zależności junk — to biblioteki i pakiety, które są podłączone do projektu, ale nie są używane bezpośrednio w kodzie, albo są używane tylko w jednej funkcji, którą łatwiej zrealizować na standardowych API.
Typowe przykłady: biblioteka do pracy z JSON, gdy projekt już używa Kotlin Serialization (dwa parsery — to dżank); biblioteka Apache Commons Lang dla jednej metody StringUtils.isEmpty, którą zastępuje Kotlin extension isNullOrBlank; biblioteka do DI, która jest używana w jednym module z dziesięciu, a pozostałe otrzymują zależności przez konstruktor ręcznie.
Każda zbędna zależność to nie tylko dodatkowy kod w binarnce. To zwiększenie powierzchni ataku na podatności: według GitHub Advisory Database (2025), 40 procent krytycznych CVE w projektach mobilnych pochodzi z zależności przechodnich, których programiści nie kontrolują. Im mniej zależności — tym mniejsza powierzchnia ataku.
// Wyświetl drzewo zależności Gradle
./gradlew app:dependencies --configuration releaseRuntimeClasspath
// Znajdź nieużywane zależności (wtyczka Gradle)
plugins {
id "com.autonomousapps.dependency-analysis" version "2.0.0"
}
// Wygeneruj raport nieużywanych bibliotek
./gradlew buildHealth
Dla iOS użyj polecenia swift package show-dependencies, które wyświetla pełne drzewo zależności. Narzędzie Xcode Build Timeline pokazuje, ile czasu każda biblioteka dodaje do budowania. Jeśli biblioteka zajmuje 30 procent czasu kompilacji, ale jest używana w jednym ekranie — to kandydat do usunięcia lub zastąpienia.
Dla Node.js (React Native) użyj depcheck — narzędzia, które znajduje nieużywane zależności w package.json, oraz npm-check, które dodatkowo pokazuje przestarzałe wersje. Wdróż zasadę: każda nowa zależność przechodzi code review z uzasadnieniem „dlaczego nie można standardowymi środkami”.
Martwe importy — najczęstszy rodzaj dżanku. Nie wpływają na runtime, ale zwiększają czas kompilacji: kompilator przetwarza każdy import, nawet jeśli nie jest używany. W dużych projektach usunięcie nieużywanych importów skraca czas budowania o 5–10 procent.
Nowoczesne IDE automatycznie podświetlają nieużywane importy na szaro. Skonfiguruj automatyczne czyszczenie przy zapisie pliku: w IntelliJ IDEA — Optimize Imports on the fly, w Xcode — Editor > Remove Unused Imports. W CI dodaj sprawdzanie: linter powinien blokować commity z nieużywanymi importami.
Zakomentowany kod — kolejny rodzaj dżanku. Programiści komentują bloki, aby „nie stracić” funkcjonalności przy refaktoryzacji. Jednak git przechowuje pełną historię zmian: każdy usunięty kod można przywrócić jednym poleceniem git revert lub git log -S
Zasada: w repozytorium nie ma zakomentowanego kodu. Jeśli kod nie jest potrzebny — usuń go na zawsze. Jeśli kod jest potrzebny, ale tymczasowo wyłączony — użyj feature toggle z ticketem i terminem. Komentarze typu // TODO: remove after migration — nie zostawiaj bez deadline'u. Ustaw datę i przypnij w kalendarzu.
Over-engineering — tworzenie warstw architektonicznych, które nie rozwiązują bieżących problemów, ale wymagają utrzymania. To jeden z najtrudniejszych rodzajów dżanku, ponieważ formalnie kod jest „prawidłowy”: spełnia SOLID, jest pokryty testami i zgodny z architekturą. Problem w tym, że nie jest potrzebny.
Klasyczny przykład — abstrakcyjna klasa UseCase z jedną metodą invoke, która po prostu wywołuje repozytorium. Jeśli UseCase nie dodaje logiki (cache'owanie, retry, transformacja), a tylko przekazuje wywołanie dalej — to zbędny byt. Zwiększa nawigację po projekcie: programista otwiera UseCase, patrzy, że invoke → repository — i zamyka. Czas stracony, korzyść żadna.
Inny przykład — nadmiarowa parametryzacja. Generic-interfejs z sześcioma type parameters, używany w jednym miejscu. Każdy type parameter to obciążenie poznawcze: podczas czytania kodu trzeba trzymać w głowie sześć typów, choć realnie używane są tylko dwa. Jeśli abstrakcja nie jest współużywana — jest nadmiarowa.
Kryterium odcięcia: jeśli abstrakcja nie jest współużywana w trzech różnych kontekstach — usuń ją. Abstrakcja jest uzasadniona, gdy realnie rozwiązuje problem dublowania, a nie prognozuje hipotetyczne scenariusze przyszłości. YAGNI (You Ain't Gonna Need It) — najlepsza zasada profilaktyki over-engineeringu.
Audyt dżanku wymaga kombinacji analizy statycznej, analizy zależności i ręcznego sprawdzania. Całkowicie zautomatyzować wyszukiwanie nadmiarowych abstrakcji się nie da, ale techniczny dżank (martwe importy, nieużywane biblioteki, zakomentowany kod) znajduje się narzędziami.
| Kategoria | Narzędzie | Co sprawdza |
|---|---|---|
| Nieużywane zależności | dependency-analysis (Gradle) | Biblioteki, które nie są używane w kodzie |
| Nieużywane zależności | depcheck (Node.js) | Pakiety z package.json bez importów |
| Nieużywane zależności | swift package --show-dependencies | Drzewo zależności SwiftPM |
| Martwe importy | IDE (Optimize Imports) | Nieużywane wyrażenia import |
| Zakomentowany kod | grep -r "//" / rg "^\s*//" | Bloki komentarzy z kodem |
| Puste metody/klasy | SonarQube / CodeClimate | Metody bez ciała lub z pustym ciałem |
| Dublujące biblioteki | Gradle lint (duplicate classes) | Konflikty klas z różnych bibliotek |
Do pełnego audytu uruchamiaj buildHealth (Android) lub depcheck (Node.js) raz na sprint. Stwórz dashboard w CI, który pokazuje dynamikę liczby zależności w sprintach. Jeśli liczba rośnie, a funkcjonalność nie rośnie proporcjonalnie — zespół gromadzi dżank.
Zwróć uwagę na duplicate classes — błąd, gdy dwie biblioteki zawierają tę samą klasę. To nie tylko dżank, ale także bezpośrednie źródło konfliktów budowania. W Gradle takie konflikty rozwiązuje się przez force lub exclude, ale każde takie rozwiązanie to sygnał, że jedna z bibliotek jest zbędna.
Czyszczenie dżanku to nie jednorazowa akcja, ale regularny proces. Bez reguł dżank wraca w ciągu dwóch–trzech sprintów. Najlepsza praktyka — przeznaczać 10–15 procent pojemności każdego sprintu na czyszczenie techniczne, w tym audyt dżanku.
Proces składa się z czterech kroków. Pierwszy — diagnostyka: uruchomienie narzędzi, uzyskanie raportu, priorytetyzacja. Wysoki priorytet — zależności ze znanymi CVE i dublujące biblioteki. Średni — martwe importy i zakomentowany kod. Niski — nadmiarowe abstrakcje (wymagają ręcznej analizy).
Drugi — czyszczenie: usunięcie martwych zależności, zastąpienie dublujących bibliotek jedną, usunięcie zakomentowanego kodu. Każda zmiana to osobny commit z czytelnym komunikatem: „remove unused dependency: gson (replaced by kotlinx.serialization)”, „delete commented code in LoginViewModel”.
Trzeci — weryfikacja: budowanie projektu, uruchomienie testów, sprawdzenie UI. Jeśli po usunięciu zależności testy przechodzą — zależność rzeczywiście nie była potrzebna. Jeśli testy padają — znaczy, że gdzieś została ukryta referencja, której nie wykrył analizator statyczny.
Czwarty — profilaktyka: aktualizacja checklisty code review, dodanie zasady „żadnej nowej zależności bez uzasadnienia” do Definition of Done, skonfigurowanie automatycznego sprawdzania w CI. Profilaktyka to jedyny sposób, aby nie dopuścić do ponownego gromadzenia dżanku.
Często zadawane pytania
Dług techniczny to świadome kompromisowe rozwiązanie (szybko, ale niskiej jakości), które planuje się naprawić. Dżank to nie świadome rozwiązanie, a nagromadzone śmieci: zbędne zależności, zakomentowany kod, puste abstrakcje, których nikt nie planował i nie chce utrzymywać.
Optymalny rytm — każdy sprint przeznaczać 10 procent czasu na czyszczenie techniczne. Pozwala to utrzymać dżank pod kontrolą, nie gromadząc krytycznej masy. Jeśli w projekcie jest dużo dżanku — zacznij od jednego dużego sprintu czyszczenia, a potem przejdź na regularny rytm.
Zmierz i pokaż liczby: zmierz czas budowania przed i po usunięciu 3–5 zbędnych zależności. Skrócenie o 15–30 sekund na jedno budowanie mnoży się przez liczbę budowań dziennie i daje godziny zaoszczędzonego czasu zespołu. Liczby przekonują lepiej niż abstrakcyjne apele o czystość.
Tak, szczególnie jeśli zależność ma CVE. Nawet jeśli projekt jest stabilny, podatność w zależności przechodniej to ryzyko bezpieczeństwa. Ponadto przy aktualizacji SDK lub języka stara zależność może przestać być kompatybilna, a jej usunięcie przed aktualizacją zaoszczędzi godziny migracji.
Każde TODO bez ticketa to dżank. Ustal zasadę: TODO pisze się tylko w formacie // TODO(PROJECT-1234): fix z przypisaniem do zadania w trackerze. Regularnie sprawdzaj TODO i zamykaj te, które straciły aktualność. Przeterminowane TODO usuwaj — jeśli problem nie wypłynął przez pół roku, nie jest krytyczny.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również