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];
  • Точечно с помощью комментариев отключены ложные срабатывания;
  • 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.

По-своему, они правы. Они считают, что для начала они должны как-то избавиться от всех этих предупреждений. И только тогда они смогут получать пользу от регулярного использования анализатора кода. В противном случае, новые предупреждения будут просто тонуть в старых, и на них никто не будет обращать внимание.

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
Самое худшее в этой истории, если кто-то сверху в этот момент заставит использовать статический анализ кода. Это только демотивирует команду, так как с их точки зрения появится дополнительная бюрократическая сложность, которая только мешает. Отчёты анализатора никто не будет смотреть, и всё использование будет только «на бумаге». Т.е. формально анализ встроен в DevOps процесс, но на практике от этого никому никакой пользы нет. Мы слышали подробные истории при общении на стендах от посетителей конференций. Подобный опыт может надолго, если не на всегда, отбить желание у программистов связываться с инструментами статического анализа.

Внедрение и устранение технического долга

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;

Анализатор PVS-Studio выдаст здесь предупреждение 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. Использование машинного обучения в статическом анализе исходного кода программ.
  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