W większości projektów z czasem pojawiają się drobne problemy i niedociągnięcia — czasem wynikające z pośpiechu, czasem z nieuwagi. W przeszłości opisywaliśmy już Checkstyle — narzędzie, które pomoże Ci utrzymać standardy formatowania na wysokim poziomie, a także SonarQube — pakiet do śledzenia długu technicznego w projekcie. Dzisiaj zajmiemy się ostatnim przedstawicielem ‘wielkiej trójki’ — FindBugs, który szuka potencjalnych problemów w kodzie!
FindBugs to oprogramowanie opracowane na uniwersytecie w Maryland, którego celem jest — podobnie jak w przypadku pozostałych wymienionych — statyczna analiza kodu. Zasada działania jest jednak inna — sprawdza nie tyle zgodność z ustalonym wcześniej stylem, co potencjalne problemy i błędy w aplikacji (np. modyfikowanie zmiennych, które są argumentami metody itp). O ile integracja z projektem rozwijanym przez lata może przyprawić o ból głowy pod kątem ilości zalezionych problemów, często zgłaszane problemy są warte poprawienia, a przynajmniej sprawdzenia.
Z użyciem linii komend / GUI
FindBugs oferuje graficzny interfejs użytkownika, za pomocą którego możemy dokonać analizy wybranych klas czy projektu. Aby uruchomić interfejs graficzny, wystarczy uruchomić plik JAR z projektem — dwukrotnie na niego klikając lub uruchamiając z linii komend, np. poleceniem java ‑jar findbugs.jar ‑gui . Po skonfigurowaniu projektu za pomocą GUI możliwe jest uruchamianie sprawdzania za pomocą linii komend (co może być przydatne w przypadku automatyzacji). Szczegółowe informacje na temat używania graficznego interfejsu, linii komend oraz dostępnych opcji można znaleźć w dokumentacji projektu.
W praktyce ten sposób używania jest najmniej wygodny i o ile jest to możliwe, zachęcamy do korzystania z integracji z Mavenem oraz środowiskiem IDE. Możliwość konfiguracji z linii komend jest nadal przydatna w starszych projektach, które korzystają z archaicznych lub niestandardowych systemów budowania.
Wtyczka do Eclipse
W przypadku Eclipse, wtyczka ta jest dostępna w Marketplace. Zwróć uwagę, że dla najnowszych wersji Eclipse nazywa się ona SpotBugs, not FindBugs! Instalacja sprowadza się do kliknięcia w ‘Install’:
Po instalacji plugin powinien być gotowy do działania. Aby uruchomić analizę, z menu kontekstowego (projektu, pakietu lub klasy) wybieramy opcję ‘SpotBugs’:
W efekcie plugin oznaczy znalezione błędy w następujący sposób:
Odnośniki:
Jako element buildu Mavenowego
Poza konfiguracją IDE warto także dodać FindBugs do konfiguracji Mavena w projekcie. Dzięki temu sprawdzenie będzie się odbywało także podczas budowania projektu — dodatkowy stopień ‘ochrony’ naszego projektu przed niepożądanymi problemami.
Konfiguracja sprowadza się do dodania pluginu do naszego pliku pom.xml — szczegóły opisane są oczywiście w dokumentacji. Podstawowa konfiguracja może wyglądać następująco:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>3.0.6-SNAPSHOT</version>
<configuration>
<effort>Max</effort>
<threshold>Low</threshold>
<xmlOutput>true</xmlOutput>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>
Domyślnie sprawdzenie uruchomi się w fazie verify, co możemy oczywiście zmienić w konfiguracji pluginu. Dostępne opcje oraz ich znaczenie standardowo znajdują się w dokumentacji. W przypadku znalezienia błędów w projekcie, Maven zatrzyma proces budowania z błędem i informacją o lokalizacji raportu FindBugs.
Znajdywane problemy
FindBugs wyszukuje różnego rodzaju problemów, które grupuje w kategorie. Wszystkie problemy, wraz z konkretnym plikiem i numerem linii, są zawarte w raporcie generowanym podczas sprawdzenia — raport generowany jest zarówno jako plik HTML (do standardowego wglądu przez programistę) — jak i w formacie XML (możliwym do wykorzystania przy automatyzacji).
Listę wyszukiwanych problemów wraz z opisami można znaleźć na stronie projektu. Opisy te są także zawarte w raporcie generowanym podczas sprawdzenia.
Własne (lub po prostu dodatkowe) sprawdzenia
W niektórych projektach konieczne jest sprawdzenie specyficznych aspektów lub konwencji, które wynikają ze środowiska projektu lub praktyk przyjętych w firmie. FindBugs pozwala nam na to umożliwiając pisanie własnych detektorów (ang. Detectors). Ponieważ stworzenie własnego detektora jest dość skomplikowane i konieczna jest wiedza na temat statycznej analizy kodu oraz parsowania, ograniczymy się jedynie do odesłania do zewnętrznych materiałów:
Ignorowanie problemów
FindBugs jest jednak tylko narzędziem do statycznej analizy kodu — czasem znajdywane ‘błędy’ nie są faktycznymi problemami, a celowym działaniem programisty. W takiej sytuacji FindBugs pozwala nam ignorować określone problemy (wraz z podaniem uzasadnienia). Pierwotnie wymagało to dodania odpowiedniej konfiguracji w XML (opis można nadal znaleźć w dokumentacji), my jednak skorzystamy z wygodniejszego rozwiązania — adnotacji. Aby móc je wykorzystać, przede wszystkim konieczne jest dodanie zależności do projektu:
<dependency>
<groupId>net.sourceforge.findbugs</groupId>
<artifactId>annotations</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
Zwróć uwagę na scope — adnotacje te potrzebne są tylko podczas budowania projektu, w przypadku działającej aplikacji nie mają znaczenia. Dodanie <scope>provided</scope> powoduje, że zależność ta nie będzie dołączona do zbudowanego pliku jar (lub war). Więcej o różnych wartościach scope znajdziesz w dokumentacji Mavena, w tym wpisie poprzestaniemy na ich użyciu :)
Mając dodaną zależność, kolejnym krokiem jest oznaczenie problematycznych miejsc adnotacją @SupressFBWarning, np:
@SuppressFBWarnings(value="HE_EQUALS_USE_HASHCODE", justification="Ja wiem lepiej!!")
public void someOffensiveMethod() {
//...
}
W ten sposób określony rodzaj błędu będzie ignorowany w wybranej metodzie. Pamiętaj jednak, że jest to ostateczność, używaj tej możliwości z dużym umiarem i tylko kiedy jest absolutnie konieczna!
Podsumowanie
FindBugs jest jednym z tych projektów, które warto zawsze mieć ‘pod ręką’ — jeśli nie zintegrowane z systemem budowania, to na pewno ze środowiskiem. FindBugs oferuje znacznie bogatszą i bardziej kontekstową analizę kodu niż inne, podobne rozwiązania. Pomimo dość długiego cyklu rozwojowego (kolejne wersje wypuszczane są co kilka miesięcy czy nawet lat — głównie w celu zapewnienia zgodności z najnowszą wersją Javy), rozwiązanie to nie traci na aktualności.
Niestety problemem bywa współpraca z narzędziami typu Lombok — często potrzebna jest dodatkowa konfiguracja lub raportowane są błędy, które nie są faktycznymi błędami. Mimo wszystko jest to narzędzie zdecydowanie warte uwagi i dodania do swojego ‘przybornika’.
Na podstawie FindBugs powstaje także sporo ciekawych projektów pobocznych, np w formie pluginów. Jednym z nich wartym uwagi jest find-sec-bugs — plugin, który wyszukuje błędy w kodzie związane z bezpieczeństwem aplikacji.
Nazwa oraz logo FindBugs są własnością Uniwersytetu w Maryland.
FindBugs vs SpotBugs
W ostatnim czasie można znaleźć informacje na temat innego produktu — SpotBugs. Projekt ten jest forkiem FindBugs — innymi słowy ktoś wziął dostępny kod i rozwija go niezależnie od pierwotnego projektu. Powodów było zapewne wiele, na pewno nie pomagało to, że ‘marka’ FindBugs była własnością uniwersytetu oraz sprawował on kuratelę nad projektem. O ile nam wiadomo, społeczność zgromadzona wokół FindBugs raczej entuzjastycznie odnosi się do zmiany — można więc mieć nadzieję, że projekt będzie rozwijany pod tą marką. Na ten moment sposób działania, UI i właściwie wszystkie inne elementy są kompatybilne pomiędzy tymi projektami i nie ma za wiele różnic. Częściej spotykana jest jednak nazwa FindBugs, dlatego zdecydowaliśmy się jej używać w tym artykule. Niemniej, zachęcamy do obserwowania repozytorium SpotBugs — najprawdopodobniej to tam będzie się odbywał dalszy rozwój projektu.