Jak wdrożyć statyczny analizator kodu w starszym projekcie bez demotywowania zespołu

Jak wdrożyć statyczny analizator kodu w starszym projekcie bez demotywowania zespołu
Wypróbowanie statycznego analizatora kodu jest łatwe. Ale wdrożenie go, zwłaszcza przy opracowywaniu dużego, starego projektu, wymaga umiejętności. Jeśli zostanie wykonany nieprawidłowo, analityk może dodać pracy, spowolnić rozwój i zdemotywować zespół. Porozmawiajmy krótko o tym, jak właściwie podejść do integracji analizy statycznej z procesem rozwoju i zacząć ją wykorzystywać w ramach CI/CD.

Wprowadzenie

Ostatnio moją uwagę przykuła publikacja „Rozpoczęcie pracy z analizą statyczną bez przytłaczania zespołuZ jednej strony jest to dobry artykuł, z którym warto się zapoznać. Z drugiej strony wydaje mi się, że nadal nie daje pełnej odpowiedzi jak bezboleśnie wdrożyć analizę statyczną w projekcie z dużą ilością starszego kodu Artykuł mówi, że można zaakceptować dług techniczny i pracować tylko nad nowym kodem, ale nie ma odpowiedzi na pytanie, co później zrobić z tym długiem technicznym.

Nasz zespół PVS-Studio przedstawia swoje zdanie na ten temat. Przyjrzyjmy się, jak w pierwszej kolejności powstaje problem wdrożenia statycznego analizatora kodu, jak go pokonać i jak bezboleśnie stopniowo eliminować dług techniczny.

Problemy

Uruchomienie i sprawdzenie, jak działa analizator statyczny, zwykle nie jest trudne [1] Możesz zobaczyć interesujące błędy, a nawet przerażające potencjalne luki w kodzie. Można nawet coś naprawić, ale wtedy wielu programistów się poddaje.

Wszystkie analizatory statyczne dają fałszywe wyniki pozytywne. Jest to cecha metodologii analizy kodu statycznego i nic nie można z tym zrobić. W ogólnym przypadku jest to problem nierozwiązywalny, co potwierdza twierdzenie Rice’a [2] Algorytmy uczenia maszynowego też nie pomogą [3] Nawet jeśli dana osoba nie zawsze potrafi stwierdzić, czy ten, czy inny kod jest błędny, nie należy tego oczekiwać od programu :).

Fałszywe alarmy nie stanowią problemu, jeśli analizator statyczny jest już skonfigurowany:

  • Wyłączono nieistotne zestawy reguł;
  • Niektóre nieistotne funkcje diagnostyczne zostały wyłączone;
  • Jeśli mówimy o C lub C++, to zaznaczane są makra zawierające określone konstrukcje, które powodują pojawianie się bezużytecznych ostrzeżeń w każdym miejscu, w którym takie makra są używane;
  • Zaznaczono funkcje własne, które wykonują działania podobne do funkcji systemowych (własny odpowiednik memcpy lub printf) [4];
  • Fałszywe alarmy są specjalnie wyłączane za pomocą komentarzy;
  • I tak dalej.

W tym przypadku możemy spodziewać się niskiego odsetka wyników fałszywie dodatnich na poziomie około 10-15% [5] Innymi słowy, 9 na 10 ostrzeżeń analizatora będzie wskazywać na prawdziwy problem w kodzie lub przynajmniej na „silnie pachnący kod”. Zgadzam się, ten scenariusz jest niezwykle przyjemny, a analizator jest prawdziwym przyjacielem programisty.

Jak wdrożyć statyczny analizator kodu w starszym projekcie bez demotywowania zespołu
W rzeczywistości w dużym projekcie początkowy obraz będzie zupełnie inny. Analizator generuje setki lub tysiące ostrzeżeń dla starszego kodu. Niemożliwe jest szybkie zrozumienie, które z tych ostrzeżeń są istotne, a które nie. Nieracjonalne jest usiąść i zająć się wszystkimi tymi ostrzeżeniami, ponieważ w tym przypadku główna praca zostanie zatrzymana na kilka dni lub tygodni. Zazwyczaj drużyny nie stać na taki scenariusz. Pojawi się także ogromna liczba różnic, które psują historię zmian. A szybka, masowa edycja tak wielu fragmentów kodu nieuchronnie spowoduje nowe literówki i błędy.

A co najważniejsze, taki wyczyn w walce z ostrzeżeniami nie ma większego sensu. Zgadzam się, że skoro projekt działa pomyślnie od wielu lat, większość zawartych w nim błędów krytycznych została już poprawiona. Tak, te poprawki były bardzo drogie, wymagały debugowania, otrzymywały negatywne opinie użytkowników na temat błędów i tak dalej. Analizator statyczny pomógłby szybko i tanio naprawić wiele z tych błędów na etapie kodowania. Ale w tej chwili w ten czy inny sposób błędy te zostały naprawione, a analizator wykrywa głównie błędy niekrytyczne w starym kodzie. Tego kodu nie można używać, można go używać bardzo rzadko, a błąd w nim może nie powodować zauważalnych konsekwencji. Być może gdzieś cień spod przycisku ma niewłaściwy kolor, ale nie przeszkadza to nikomu w korzystaniu z produktu.

Oczywiście nawet drobne błędy pozostają błędami. Czasami błąd może ukryć prawdziwą lukę. Jednak rezygnacja ze wszystkiego i spędzanie dni/tygodni na radzeniu sobie z defektami, które ledwo się ujawniają, wydaje się wątpliwym pomysłem.

Programiści patrzą, patrzą, patrzą na te wszystkie ostrzeżenia dotyczące starego, działającego kodu... I myślą: obejdziemy się bez analizy statycznej. Przejdźmy do napisania nowej przydatnej funkcjonalności.

Na swój sposób mają rację. Uważają, że najpierw muszą jakoś pozbyć się tych wszystkich ostrzeżeń. Tylko wtedy będą mogli czerpać korzyści z regularnego korzystania z analizatora kodu. W przeciwnym razie nowe ostrzeżenia po prostu utopią się w starych i nikt nie zwróci na nie uwagi.

Jest to ta sama analogia, co w przypadku ostrzeżeń kompilatora. Nie bez powodu zalecają utrzymanie liczby ostrzeżeń kompilatora na poziomie 0. Jeśli ostrzeżeń będzie 1000, to gdy będzie 1001, nikt nie zwróci na to uwagi i nie wiadomo, gdzie szukać tego najnowszego ostrzeżenia.

Jak wdrożyć statyczny analizator kodu w starszym projekcie bez demotywowania zespołu
Najgorsze w tej historii jest to, że ktoś z góry zmusza Cię w tym momencie do użycia statycznej analizy kodu. To tylko zdemotywuje zespół, ponieważ z ich punktu widzenia pojawi się dodatkowa złożoność biurokratyczna, która tylko będzie przeszkadzać. Nikt nie będzie zaglądał do raportów analizatora, a wszelkie wykorzystanie będzie tylko „na papierze”. Te. Formalnie analiza jest wbudowana w proces DevOps, jednak w praktyce nikomu nie przynosi to korzyści. Na stoiskach usłyszeliśmy szczegółowe historie od uczestników konferencji. Takie doświadczenie może zniechęcić programistów do korzystania z narzędzi do analizy statycznej na długi czas, jeśli nie na zawsze.

Wdrażanie i eliminowanie długu technicznego

Tak naprawdę nie ma nic trudnego ani strasznego we wprowadzeniu analizy statycznej nawet do dużego, starego projektu.

CI / CD

Co więcej, analizator można od razu włączyć do ciągłego procesu rozwoju. Na przykład dystrybucja PVS-Studio zawiera narzędzia umożliwiające wygodne przeglądanie raportów w potrzebnym formacie oraz powiadomienia dla programistów, którzy napisali problematyczne sekcje kodu. Tym, którzy są bardziej zainteresowani uruchomieniem PVS-Studio z systemów CI/CD, polecam zapoznać się z odpowiednim Sekcja dokumentacja oraz cykl artykułów:

Wróćmy jednak do kwestii dużej liczby fałszywych alarmów już na pierwszych etapach wdrażania narzędzi do analizy kodu.

Naprawianie istniejącego długu technicznego i radzenie sobie z nowymi ostrzeżeniami

Nowoczesne komercyjne analizatory statyczne pozwalają badać tylko nowe ostrzeżenia, które pojawiają się w nowym lub zmienionym kodzie. Implementacja tego mechanizmu jest różna, ale istota jest ta sama. W analizatorze statycznym PVS-Studio funkcjonalność ta jest realizowana w następujący sposób.

Aby szybko rozpocząć korzystanie z analizy statycznej, sugerujemy użytkownikom PVS-Studio skorzystanie z mechanizmu masowego tłumienia ostrzeżeń [6] Ogólna koncepcja jest następująca. Użytkownik uruchomił analizator i otrzymał wiele ostrzeżeń. Skoro projekt rozwijany od wielu lat żyje, rozwija się i zarabia, to najprawdopodobniej w raporcie nie będzie wielu ostrzeżeń wskazujących na wady krytyczne. Innymi słowy, krytyczne błędy zostały już w ten czy inny sposób naprawione przy użyciu droższych metod lub dzięki opiniom klientów. W związku z tym wszystko, co analizator aktualnie znajdzie, można uznać za dług techniczny, którego natychmiastowe wyeliminowanie jest niepraktyczne.

Możesz powiedzieć PVS-Studio, aby na razie uznało te ostrzeżenia za nieistotne (zachowaj dług techniczny na później) i nie będzie już ich wyświetlać. Analizator tworzy specjalny plik, w którym zapisuje informacje o błędach, które nie są jeszcze interesujące. A teraz PVS-Studio będzie wyświetlać ostrzeżenia tylko w przypadku nowego lub zmienionego kodu. Co więcej, wszystko to zostało sprytnie zaimplementowane. Jeśli np. na początku pliku z kodem źródłowym zostanie dodana pusta linia, to analizator zrozumie, że tak naprawdę nic się nie zmieniło i nadal będzie milczał. Ten plik znaczników można umieścić w systemie kontroli wersji. Plik jest duży, ale nie stanowi to problemu, ponieważ nie ma sensu go często przechowywać.

Teraz wszyscy programiści zobaczą ostrzeżenia dotyczące tylko nowego lub zmienionego kodu. W ten sposób możesz zacząć korzystać z analizatora, jak mówią, od następnego dnia. A do długu technicznego można później wrócić i stopniowo poprawiać błędy oraz konfigurować analizator.

Zatem pierwszy problem z implementacją analizatora w dużym, starym projekcie został rozwiązany. Zastanówmy się teraz, co zrobić z długiem technicznym.

Poprawki błędów i refaktoryzacje

Najprostszą i najbardziej naturalną rzeczą jest poświęcenie czasu na analizę masowo tłumionych ostrzeżeń analizatora i stopniowe radzenie sobie z nimi. Gdzieś powinieneś naprawić błędy w kodzie, gdzieś powinieneś dokonać refaktoryzacji, aby poinformować analizator, że kod nie stwarza problemów. Prosty przykład:

if (a = b)

Większość kompilatorów i analizatorów C++ narzeka na taki kod, ponieważ istnieje duże prawdopodobieństwo, że faktycznie chcieli go napisać (a == b). Istnieje jednak niepisana umowa i zwykle jest to odnotowywane w dokumentacji, że jeśli są dodatkowe nawiasy, to uważa się, że programista celowo napisał taki kod i nie ma potrzeby przeklinać. Na przykład w dokumentacji PVS-Studio do diagnostyki V559 (CWE-481) jest wyraźnie napisane, że następujący wiersz zostanie uznany za poprawny i bezpieczny:

if ((a = b))

Inny przykład. Czy zostało to zapomniane w tym kodzie C++? złamać czy nie?

case A:
  foo();
case B:
  bar();
  break;

Analizator PVS-Studio wyświetli w tym miejscu ostrzeżenie V796 (CWE-484). Może to nie być błąd, w takim przypadku powinieneś dać parserowi wskazówkę, dodając atrybut [[przejście]] lub na przykład __attribute__((przejście)):

case A:
  foo();
  [[fallthrough]];
case B:
  bar();
  break;

Można powiedzieć, że takie zmiany w kodzie nie naprawiają błędu. Tak, to prawda, ale ma dwie przydatne rzeczy. Po pierwsze, raport analizatora eliminuje fałszywe alarmy. Po drugie, kod staje się bardziej zrozumiały dla osób zajmujących się jego utrzymaniem. A to jest bardzo ważne! Choćby po to warto przeprowadzić drobne refaktoryzacje, aby kod stał się bardziej przejrzysty i łatwiejszy w utrzymaniu. Ponieważ analizator nie rozumie, czy „przerwa” jest potrzebna, czy nie, będzie to również niejasne dla innych programistów.

Oprócz poprawek błędów i refaktoryzacji możesz w szczególności ukryć oczywiście fałszywe ostrzeżenia analizatora. Niektóre nieistotne funkcje diagnostyczne można wyłączyć. Na przykład ktoś uważa, że ​​ostrzeżenia są bezcelowe V550 o porównywaniu wartości float/double. A niektórzy klasyfikują je jako ważne i godne studiowania [7] O tym, które ostrzeżenia uważa się za istotne, a które nie, decyduje zespół programistów.

Istnieją inne sposoby tłumienia fałszywych alertów. Na przykład wspomniano wcześniej o znacznikach makro. Wszystko to opisano bardziej szczegółowo w dokumentacji. Najważniejsze jest, aby zrozumieć, że jeśli stopniowo i systematycznie będziesz podchodzić do pracy z fałszywymi alarmami, nie ma w nich nic złego. Zdecydowana większość nieciekawych ostrzeżeń znika po konfiguracji, a pozostają tylko miejsca, które naprawdę wymagają dokładnego przestudiowania i pewnych zmian w kodzie.

Ponadto zawsze pomagamy naszym klientom w skonfigurowaniu PVS-Studio, jeśli pojawią się jakiekolwiek trudności. Ponadto zdarzały się przypadki, gdy sami eliminowaliśmy fałszywe ostrzeżenia i poprawialiśmy błędy [8] Na wszelki wypadek postanowiłem wspomnieć, że taka opcja rozszerzonej współpracy również jest możliwa :).

Metoda ratchetowa

Istnieje inne interesujące podejście do stopniowej poprawy jakości kodu poprzez wyeliminowanie ostrzeżeń analizatora statycznego. Konkluzja jest taka, że ​​liczba ostrzeżeń może się jedynie zmniejszyć.

Jak wdrożyć statyczny analizator kodu w starszym projekcie bez demotywowania zespołu

Rejestrowana jest liczba ostrzeżeń wydanych przez analizator statyczny. Bramka jakości jest skonfigurowana w taki sposób, że teraz można wprowadzić tylko kod, który nie zwiększa liczby operacji. W rezultacie proces stopniowego zmniejszania liczby alarmów rozpoczyna się od dostosowania analizatora i skorygowania błędów.

Nawet jeśli ktoś chce trochę oszukać i zdecyduje się przejść bramkę jakości nie poprzez wyeliminowanie ostrzeżeń w swoim nowym kodzie, ale poprzez ulepszenie starego kodu strony trzeciej, nie jest to przerażające. Mimo to zapadka obraca się w jednym kierunku i stopniowo liczba defektów będzie się zmniejszać. Nawet jeśli ktoś nie chce naprawiać swoich nowych defektów, nadal będzie musiał coś poprawić w sąsiednim kodzie. W pewnym momencie kończą się proste sposoby na zmniejszenie liczby ostrzeżeń i przychodzi moment, w którym rzeczywiste błędy zostaną naprawione.

Metodologię tę opisano bardziej szczegółowo w bardzo interesującym artykule Iwana Ponomariewa „Zaimplementuj analizę statyczną w procesie, zamiast szukać w niej błędów", który polecam przeczytać każdemu zainteresowanemu poprawą jakości kodu.

Autor artykułu ma również raport na ten temat: „Ciągła analiza statyczna".

wniosek

Mam nadzieję, że po tym artykule czytelnicy będą bardziej akceptować narzędzia analizy statycznej i będą chcieli wdrożyć je w procesie rozwoju. Jeśli masz jakieś pytania, jesteśmy zawsze gotowi konsultować użytkownikom naszego analizatora statycznego PVS-Studio i pomoc przy jego wdrożeniu.

Istnieją inne typowe wątpliwości, czy analiza statyczna może być naprawdę wygodna i użyteczna. Większość tych wątpliwości starałem się rozwiać w publikacji „Powody wprowadzenia do procesu deweloperskiego analizatora kodu statycznego PVS-Studio” [9].

Dziękuję za uwagę i przychodzę pobranie i wypróbuj analizator PVS-Studio.

Dodatkowe linki

  1. Andriej Karpow. Jak mogę szybko zobaczyć interesujące ostrzeżenia, które analizator PVS-Studio generuje dla kodu C i C++?
  2. Wikipedia. Twierdzenie Rice'a.
  3. Andriej Karpow, Wiktoria Chaniewa. Wykorzystanie uczenia maszynowego w analizie statycznej kodu źródłowego programu.
  4. Studio PVS. Dokumentacja. Dodatkowe ustawienia diagnostyczne.
  5. Andriej Karpow. Charakterystyka analizatora PVS-Studio na przykładzie bibliotek EFL Core Libraries, 10-15% wyników fałszywie dodatnich.
  6. Studio PVS. Dokumentacja. Masowe tłumienie komunikatów analizatora.
  7. Iwan Andryaszin. O tym, jak testowaliśmy analizę statyczną w naszym projekcie edukacyjnego symulatora endowaskularnej chirurgii rentgenowskiej.
  8. Paweł Jeremiejew, Światosław Razmysłow. Jak zespół PVS-Studio ulepszył kod Unreal Engine.
  9. Andriej Karpow. Powody wprowadzenia statycznego analizatora kodu PVS-Studio do procesu rozwoju.

Jak wdrożyć statyczny analizator kodu w starszym projekcie bez demotywowania zespołu

Jeśli chcesz udostępnić ten artykuł anglojęzycznej publiczności, skorzystaj z linku do tłumaczenia: Andrey Karpov. Jak wprowadzić statyczny analizator kodu do starszego projektu i nie zniechęcić zespołu.

Źródło: www.habr.com

Dodaj komentarz