Jak znaleźć nieużywany / martwy kod w projektach Java [zamknięte]

306

Jakich narzędzi używasz do znajdowania nieużywanego / martwego kodu w dużych projektach Java? Nasz produkt jest rozwijany od kilku lat i bardzo trudno jest ręcznie wykryć nieużywany kod. Staramy się jednak usunąć jak najwięcej nieużywanego kodu.

Doceniane są również sugestie dotyczące ogólnych strategii / technik (innych niż określone narzędzia).

Edycja: Zauważ, że już używamy narzędzi do pokrywania kodu (Clover, IntelliJ), ale są one mało pomocne. Martwy kod nadal ma testy jednostkowe i pokazuje się jako objęty. Wydaje mi się, że idealne narzędzie identyfikuje klastry kodu, które mają bardzo mało innych kodów zależnych od niego, umożliwiając ręczną kontrolę dokumentów.

knatten
źródło
16
Zachowaj testy jednostkowe w osobnym drzewie źródeł (powinieneś i tak powinieneś) i uruchom narzędzia pokrycia tylko na żywym drzewie.
agnul
5
Zacznę od inspekcji IDEA „Nieużywana deklaracja” i odznacz Uwzględnij źródła testowe . Czy możesz wyjaśnić, co masz na myśli, mówiąc „niewielka pomoc” IDEA?
David Moles,
1
Sposoby znalezienia martwego kodu: 1) niepowiązane z niczym zewnętrznym. 2) nie był używany z zewnątrz, mimo że jest powiązany w czasie wykonywania. 3) Połączone i wywołane, ale nigdy nie używane jak martwa zmienna. 4) logicznie nieosiągalny stan. Więc łączenie, uzyskiwanie dostępu w czasie, oparte na logice, używanie po uzyskaniu dostępu.
Muhammad Umer,
Skorzystaj z Pomysłu IntelliJ i mojej odpowiedzi tutaj: stackoverflow.com/questions/22522013/... :)
BlondCode
Dodatek do odpowiedzi Davida Mole'a: zobacz tę odpowiedź stackoverflow.com/a/6587932/1579667
Benj

Odpowiedzi:

40

Instrumentowałbym działający system, aby przechowywać dzienniki użycia kodu, a następnie zacząłem sprawdzać kod, który nie jest używany przez miesiące lub lata.

Na przykład, jeśli jesteś zainteresowany nieużywanymi klasami, wszystkie klasy można oprzyrządować do rejestrowania podczas tworzenia instancji. A potem mały skrypt może porównać te dzienniki z pełną listą klas, aby znaleźć nieużywane klasy.

Oczywiście, jeśli wybierzesz metodę, powinieneś pamiętać o wydajności. Na przykład metody mogą rejestrować tylko ich pierwsze użycie. Nie wiem, jak najlepiej to zrobić w Javie. Zrobiliśmy to w Smalltalk, który jest językiem dynamicznym, a zatem umożliwia modyfikację kodu w czasie wykonywania. Instrumentujemy wszystkie metody za pomocą wywołania rejestrującego i odinstalowujemy kod rejestrujący po pierwszym logowaniu metody, więc po pewnym czasie nie występują już żadne ograniczenia wydajności. Być może podobną rzecz można zrobić w Javie ze statycznymi flagami logicznymi ...

akuhn
źródło
5
Podoba mi się ta odpowiedź, ale czy ktoś ma pomysł, jak to zrobić w Javie bez jawnego dodawania logowania w każdej klasie? Może jakaś magia „proxy”?
Outlaw Programmer
14
@Outlaw AOP wydaje się idealnym rozwiązaniem do tego celu.
Pascal Thivent,
6
Jeśli rozumiesz strukturę aplikacji ładującą klasy, możesz użyć AOP na module ładującym klasy, aby śledzić zdarzenia obciążenia klasą. Byłoby to mniej inwazyjne w systemie produkcyjnym niż porady przed wszystkimi konstruktorami.
ShabbyDoo,
5
Ta odpowiedź jest całkiem dobra dla języka dynamicznego, ale okropna dla języka statycznego, który mógłby zrobić DUŻO lepiej. Dzięki statycznie wpisanemu językowi (oprócz refleksji) możesz na pewno dokładnie wiedzieć, które metody są używane, a które nie, jest to jedna z największych zalet języka statycznego i powinieneś go używać zamiast metody niestabilnej opisanej tutaj .
Bill K
4
@BillK dzieje się więcej refleksji, niż myślisz. Np. Wiosna kryje w sobie sporo magii, w tym odbicie. Twoje narzędzie analityczne musi to naśladować.
Thorbjørn Ravn Andersen
220

Wtyczka Eclipse, która działa dość dobrze, to nieużywany detektor kodu .

Przetwarza cały projekt lub określony plik i pokazuje różne nieużywane / martwe kody, a także sugeruje zmiany widoczności (tj. Metodę publiczną, która może być chroniona lub prywatna).

Mikezx6r
źródło
Wygląda ładnie, ale nie udało mi się go uruchomić - akcja „Wykryj kod ...” jest wyłączona i nie znalazłem sposobu, aby ją włączyć.
Ondra Žižka
1
Naprawdę znajdź nieużywane metody, ALE też znajdź, że moje EJB są nieużywane (gdy są), ponieważ używam projektu wzorca dla delegatów biznesowych
Eildosa
Czy nadal działa na Kepler? komunikaty mówią o Eclipse 3.8: ucdetector.org/releases.html
Mr_and_Mrs_D
Wydaje się być w idealnym stanie technicznym na Kepler.
Erik Kaplun
4
Czy chcesz dodać link do marketplace marketplace.eclipse.org/content/unnecessary-code-detector ? Ułatwia to instalację i odpowiada na pytanie, czy jest obsługiwane w nowszych wersjach Eclipse.
Thomas Weller,
64

CodePro został niedawno wydany przez Google z projektem Eclipse. Jest darmowy i bardzo skuteczny. Wtyczka ma funkcję „ Znajdź martwy kod ” z jednym / wieloma punktami wejścia. Działa całkiem dobrze.

Berlin Brown
źródło
1
Nie będzie już działać z zaćmieniem Keplera. Po pomyślnym zainstalowaniu za pośrednictwem strony aktualizacji powoduje za każdym razem awarię zaćmienia.
txulu
Niestety wygląda na to, że to narzędzie nie zdaje sobie sprawy z istnienia Springa, dlatego oznaczy wszystkie moje @Components jako nieużywane, błędnie
Clint Eastwood
Stań się bardzo stary Już nie działa Last updated this plugin March 27, 2012 developers.google.com/java-dev-tools/download-codepro
mumair
2
Wszystkie linki są nieaktualne.
zygimantus
3
Niestety wygląda na to, że Google zrzucił kod z projektu Eclipse i zapomniał o tym wszystkim.
Thorbjørn Ravn Andersen
30

Jestem zaskoczony, że ProGuard nie został tutaj wymieniony. To jeden z najbardziej dojrzałych produktów na rynku.

ProGuard to darmowy program do zmniejszania plików klasy Java, optymalizator, obfuscator i preverifier. Wykrywa i usuwa nieużywane klasy, pola, metody i atrybuty. Optymalizuje kod bajtowy i usuwa nieużywane instrukcje. Zmienia nazwy pozostałych klas, pól i metod, używając krótkich, pozbawionych znaczenia nazw. Na koniec weryfikuje przetworzony kod dla Java 6 lub Java Micro Edition.

Niektóre zastosowania ProGuard to:

  • Tworzenie bardziej zwartego kodu dla mniejszych archiwów kodów, szybszy transfer między sieciami, szybsze ładowanie i mniejsze zużycie pamięci.
  • Utrudnianie inżynierii wstecznej programów i bibliotek.
  • Wyświetlanie martwego kodu, dzięki czemu można go usunąć z kodu źródłowego.
  • Retargeting i preweryfikacja istniejących plików klas dla Java 6 lub wyższej, aby w pełni wykorzystać ich szybsze ładowanie klas.

Oto przykład martwego kodu listy: https://www.guardsquare.com/en/products/proguard/manual/examples#deadcode

David d C e Freitas
źródło
8
Podanie przykładowego użycia byłoby lepszą odpowiedzią.
rds
1
Czytając dokumentację, widzę, że zmniejsza ona nieużywany kod, ale nie mogę znaleźć nigdzie, gdzie jest wymieniony - uzgodniony, przykład lub link do odpowiedniej sekcji dokumentacji byłby bardzo pomocny!
orbfish
26

Jedną rzeczą, o której wiem, że robię w Eclipse, na jednej klasie, jest zmiana wszystkich jej metod na prywatne, a następnie sprawdzenie, jakie mam skargi. W przypadku metod, które zostaną użyte, spowoduje to błędy i przywrócę je do najniższego poziomu dostępu, jaki mogę. W przypadku nieużywanych metod spowoduje to wyświetlenie ostrzeżeń o nieużywanych metodach, które można następnie usunąć. Jako bonus często można znaleźć metody publiczne, które mogą i powinny być prywatne.

Ale to bardzo ręczne.

skiphoppy
źródło
4
Może nie jest to idealna odpowiedź, ale to naprawdę sprytne.
Erik Reppen
8
Jest to sprytne ... dopóki nie otrzymasz wywołania z nieużywanego kodu z innej klasy.
Danosaure,
Iteracja po tej metodzie może usunąć ogromne obszary kodu, ponieważ jedna z używanych metod tworzy inne po usunięciu.
4myle
15

Użyj narzędzia pokrycia testowego, aby instrumentować bazę kodu, a następnie uruchom samą aplikację, a nie testy.

Emma i Eclemma podadzą Ci miłe raporty na temat tego, jaki procent klas jest uruchamiany dla danego przebiegu kodu.

jamesh
źródło
1
+1, ponieważ jest to dobry punkt wyjścia, ale należy pamiętać, że np. Niewykorzystane (jeszcze zadeklarowane) zmienne również pojawią się na zielono.
DerMike
13

Zaczęliśmy używać funkcji Znajdź błędy, aby zidentyfikować funk w bogatym w cele środowisku naszej bazy kodów do refaktoryzacji. Rozważę również Strukturę 101, aby zidentyfikować miejsca w architekturze bazy kodu, które są zbyt skomplikowane, abyś wiedział, gdzie są prawdziwe bagna.

Alan
źródło
4
FindBugs nie może wykryć martwego i nieużywanego kodu, tylko nieużywane pola. Zobacz tę odpowiedź .
Stefan Mücke
12

Teoretycznie nie można deterministycznie znaleźć nieużywanego kodu. Istnieje matematyczny dowód na to (cóż, jest to szczególny przypadek bardziej ogólnego twierdzenia). Jeśli jesteś ciekawy, poszukaj problemu zatrzymania.

Może to objawiać się w kodzie Java na wiele sposobów:

  • Ładowanie klas na podstawie danych wprowadzanych przez użytkownika, plików konfiguracyjnych, wpisów w bazie danych itp .;
  • Ładowanie kodu zewnętrznego;
  • Przekazywanie drzew obiektów do bibliotek stron trzecich;
  • itp.

Biorąc to pod uwagę, używam IDEA IntelliJ jako mojego wybranego IDE i ma rozbudowane narzędzia analityczne do znajdowania zależności między modułami, nieużywanych metod, nieużywanych elementów, nieużywanych klas itp. Jego dość inteligentna metoda prywatna, która nie jest wywoływana, to oznaczone jako nieużywane, ale metoda publiczna wymaga szerszej analizy.

Cletus
źródło
1
Dziękuję za Twój wkład. Korzystamy z IntelliJ i otrzymujemy pomoc. Jeśli chodzi o problem zatrzymania i nierozstrzygalność, znam teorię, ale niekoniecznie potrzebujemy deterministycznego rozwiązania.
knatten
12
Zdanie otwierające jest zbyt mocne. Podobnie jak w przypadku problemu zatrzymania (również często błędnie cytowanego / nadużywanego), nie ma kompletnych ogólnych rozwiązań, ale istnieje wiele specjalnych przypadków, które można wykryć.
joel.neely
9
Chociaż nie ma ogólnego rozwiązania dla języków z eval i / lub refleksją, istnieje wiele przypadków, w których kod jest nieosiągalny.
pjc50
1
Bez refleksji i przy pełnym kodzie źródłowym każdy statycznie wpisany język powinien ułatwić deterministycznie znalezienie całego nieużywanego kodu.
Bill K,
Nie możesz znaleźć tego, co da się udowodnić, że jest nieosiągalne przez refleksję lub przez zewnętrznych rozmówców, ale możesz znaleźć kod, który jest możliwy do udowodnienia, nieosiągalny statycznie z danego punktu wejścia lub zestawu punktów wejścia
nafg
8

W Eclipse Goto Windows> Preferencje> Java> Kompilator> Błędy / Ostrzeżenia
i zmień je wszystkie na błędy. Napraw wszystkie błędy. To jest najprostszy sposób. Piękno polega na tym, że pozwoli ci to wyczyścić kod podczas pisania.

Kod Eclipse zrzutu ekranu:

wprowadź opis zdjęcia tutaj

smileprem
źródło
5

IntelliJ ma narzędzia do analizy kodu do wykrywania nieużywanego kodu. Powinieneś spróbować stworzyć jak najwięcej niepublicznych pól / metod / klas, a to pokaże więcej nieużywanych metod / pól / klas

Spróbowałbym również zlokalizować zduplikowany kod jako sposób na zmniejszenie objętości kodu.

Moją ostatnią propozycją jest próba znalezienia kodu open source, który, jeśli zostanie użyty, uprości kod.

Peter Lawrey
źródło
Jakieś przykłady tego, czym są te narzędzia?
orbfish
@orbfish Możesz uruchomić Analyse=> Run inspection by name=>unused
Peter Lawrey
5

Perspektywa plasterka Structure101 wyświetli listę (i wykres zależności) dowolnych „sierot” lub „ grup osieroconych ” klas lub pakietów, które nie są zależne od lub od klastra „głównego”.

Chris Chedgey - Struktura101
źródło
Czy to działa na przykład dla zmiennych / metod w klasie?
Joeblackdev
Skąd mam wiedzieć, czy to ma działać np. W Eclipse 4.3?
Erik Kaplun
3

DCD nie jest wtyczką dla niektórych IDE, ale może być uruchamiany z ant lub standalone. Wygląda jak narzędzie statyczne i może robić to, czego nie potrafią PMD i FindBugs . Spróbuję.

PS Jak wspomniano w komentarzu poniżej, Projekt mieszka teraz w GitHub .

Heiner
źródło
To powinno zniknąć jako komentarz, a nie odpowiedź
hrabia
Zaktualizuj swoją odpowiedź, aby usunąć stwierdzenie, że DCD „wygląda teraz martwy”. Wersja 2.1 została wydana 12 dni temu . Link w Twojej odpowiedzi nie działa.
skomisa
2

Istnieją narzędzia, które profilują kod i zapewniają dane dotyczące pokrycia kodu. Pozwala to zobaczyć (w trakcie działania kodu), jak wiele z nich jest wywoływanych. Możesz uzyskać dowolne z tych narzędzi, aby dowiedzieć się, ile masz kodu osieroconego.

Vaibhav
źródło
2
  • FindBugs doskonale nadaje się do tego typu rzeczy.
  • PMD (Project Mess Detector) to kolejne narzędzie, którego można użyć.

Jednak żadne z nich nie może znaleźć publicznych metod statycznych, które nie są używane w obszarze roboczym. Jeśli ktoś wie o takim narzędziu, daj mi znać.

graveca
źródło
1

Narzędzia pokrycia użytkowników, takie jak EMMA. Ale to nie jest narzędzie statyczne (tzn. Wymaga faktycznego uruchomienia aplikacji poprzez testy regresji i wszystkie możliwe przypadki błędów, co jest, cóż, niemożliwe :))

Mimo to EMMA jest bardzo przydatna.

Vladimir Dyuzhev
źródło
1

Narzędzia do pokrycia kodu, takie jak Emma, ​​Cobertura i Clover, będą instrumentować Twój kod i rejestrować, które jego części są wywoływane przez uruchomienie zestawu testów. Jest to bardzo przydatne i powinno stanowić integralną część procesu rozwoju. Pomoże Ci to określić, jak dobrze Twój zestaw testów obejmuje Twój kod.

Nie jest to jednak to samo, co identyfikacja rzeczywistego martwego kodu. Identyfikuje tylko kod objęty (lub nie objęty) testami. Może to dać fałszywe alarmy (jeśli twoje testy nie obejmują wszystkich scenariuszy), a także fałszywe negatywy (jeśli kod dostępu do testów nigdy nie jest używany w scenariuszu z prawdziwego świata).

Wyobrażam sobie, że najlepszym sposobem na rzeczywistą identyfikację martwego kodu byłoby oprzyrządowanie kodu za pomocą narzędzia pokrycia w środowisku działającym na żywo i analiza pokrycia kodu przez dłuższy okres czasu.

Jeśli pracujesz w środowisku redundantnym z równoważeniem obciążenia (a jeśli nie, dlaczego nie?), Przypuszczam, że sensowne byłoby instrumentowanie tylko jednego wystąpienia aplikacji i skonfigurowanie modułu równoważenia obciążenia w taki sposób, aby losowa, ale niewielka część Twoi użytkownicy działają w Twojej instancji instrumentalnej. Jeśli robisz to przez dłuższy czas (aby upewnić się, że obejrzałeś wszystkie scenariusze użytkowania w świecie rzeczywistym - takie sezonowe odmiany), powinieneś być w stanie dokładnie zobaczyć, które obszary twojego kodu są dostępne w rzeczywistym użyciu i które części tak naprawdę nigdy nie są dostępne, a zatem martwy kod.

Nigdy nie widziałem tego osobiście i nie wiem, jak wspomniane narzędzia można wykorzystać do instrumentowania i analizowania kodu, który nie jest wywoływany za pomocą zestawu testów - ale jestem pewien, że mogą.

Vihung
źródło
1

Istnieje projekt Java - Dead Code Detector (DCD). W przypadku kodu źródłowego wydaje się, że nie działa dobrze, ale w przypadku pliku .jar jest naprawdę dobry. Dodatkowo możesz filtrować według klasy i metody.

Łukasz Czerwiński
źródło
0

Zaćmienie może pokazywać / wyróżniać kod, którego nie można osiągnąć. JUnit może pokazać zasięg kodu, ale potrzebujesz testów i musisz zdecydować, czy odpowiedniego testu brakuje, czy kod jest naprawdę nieużywany.

Matthias Winkelmann
źródło
3
Eclipse powie ci tylko, czy zakres metody jest lokalny (tzn. Prywatny); i nawet wtedy nie możesz być w 100% pewien ... z odbiciem prywatna metoda może być wywołana z zewnątrz.
p3t0r
0

Znalazłem narzędzie pokrycia Clover, które instrumenty kodują i podświetla kod, który jest używany, a który nie jest używany. W przeciwieństwie do Google CodePro Analytics, działa również dla aplikacji internetowych (zgodnie z moim doświadczeniem i mogę się mylić co do Google CodePro).

Jedyną wadą, którą zauważyłem, jest to, że nie bierze pod uwagę interfejsów Java.

Kashif Nazar
źródło
Afaict, to niewolne narzędzie CI po stronie serwera.
Erik Kaplun
0

Używam Doxygen do opracowania mapy wywołań metod w celu zlokalizowania metod, które nigdy nie są wywoływane. Na wykresie znajdziesz wyspy klastrów metod bez wywołujących. To nie działa w przypadku bibliotek, ponieważ zawsze musisz zacząć od jakiegoś głównego punktu wejścia.

jbruni
źródło