Общаясь с людьми на конференциях и в комментариях к статьям, мы сталкиваемся со следующим возражением: статический анализ сокращает время на нахождение ошибок, но отнимает время у программистов, что нивелирует пользу от его использования и даже наоборот тормозит процесс разработки. Давайте разберём это возражение и покажем, что оно беспочвенно.
Утверждение «статический анализ будет отнимать часть рабочего времени» в отрыве от контекста является верным. Регулярный просмотр предупреждений статического анализатора, выдаваемых на новый или изменённый код, действительно отнимает время. Однако следует продолжить мысль: но затрачиваемое на это время гораздо меньше, чем потраченное на выявление ошибок другими методами. Ещё хуже — узнавать об ошибках от клиентов.
Здесь очень хорошей аналогией могут являться юнит-тесты. Юнит-тесты точно также отнимают время разработчиков, однако это не является причиной их не использовать. Польза от написания более качественного и проверенного кода при использовании юнит-тестов превосходит затраты на их написание.
Ещё одна аналогия: предупреждения компилятора. Это вообще очень близкая тема, так как предупреждения инструментов статического анализа в первом приближении можно рассматривать как расширение предупреждений компиляторов. Естественно, когда программист видит предупреждение компилятора, он тратит на него время. Он должен или изменить код, или явно потратить время на подавление предупреждения, например, с помощью #pragma. Однако эти затраты времени не являются причиной отключить предупреждения компилятора. А если кто-то так сделает, это будет однозначно интерпретироваться другими как профессиональная непригодность.
Тем не менее, откуда же берёт начало испуг перед необходимостью тратить время на предупреждения статических анализаторов кода?
Всё очень просто. Программисты, ещё мало знакомые с этой методологией, путают пробные запуски и регулярное использование. При первых запусках любые анализаторы выдают огромный список предупреждений, на который даже страшно смотреть. Причина в том, что анализатор ещё не настроен. Настроенный же анализатор выдаёт при регулярных запусках малое число ложных срабатываний. Другими словами, большинство предупреждений выявляют реальные дефекты или код с запахом. Важно только сделать эту настройку. В этом и есть весь фокус, который превращает статический анализатор из зла, отнимающего время, в друга и помощника.
Любой статический анализатор вначале выдаст много ложных срабатываний. Причин тому много, и эта тема заслуживает отдельной статьи. Естественно, и мы, и разработчики других анализаторов борются с ложными срабатываниями. Но срабатываний всё равно будет много, если без подготовки вдруг взять и запустить анализатор на каком-то проекте. Такая же картина, кстати, и с предупреждениями компилятора. Пусть у вас есть большой проект, который вы всегда собирали, например, с помощью компилятора Visual C++. Предположим, проект чудесным образом получился переносимым и скомпилировался с помощью GCC. Даже в этом случае вы получите гору предупреждений от GCC. Кто переживал смену компиляторов в большом проекте, тот понимает, о чём речь.
Однако никто не заставляет постоянно копаться в горах мусора из предупреждений после смены компилятора или после запуска анализатора. Естественным следующим шагом будет настройка компилятора или анализатора. Те, кто говорит «анализ предупреждений отнимает много времени», оценивает сложность внедрения инструмента, думая только об всех этих предупреждениях, которые нужно побороть вначале, но не думает о спокойном регулярном использовании.
Настройка анализаторов, как и компиляторов, не так сложна и трудозатрата, как любят пугать программисты. Если вы — менеджер, не слушайте их. Они просто ленятся. Программист с гордостью может рассказывать, как он 3 дня искал баг, найденный тестировщиком/клиентом. И это для него нормально. Однако с его точки зрения неприемлемо потратить один день на настройку инструмента, после чего подобная ошибка будет выявляться, ещё не попав в систему контроля версий.
Да, ложные срабатывания будут присутствовать и после настройки. Но их количество преувеличивается. Вполне можно настроить анализатор, чтобы процент ложных срабатываний составлял 10%-15%. Т.е. на 9 найденных дефектов только 1 предупреждение потребует подавления как ложное. Так где же здесь «трата времени»? При этом 15% — это вполне реальное значение, о чём подробнее можно прочитать в этой статье.
Остаётся ещё один момент. Программист может возразить:
Хорошо, предположим, регулярные запуски статического анализа действительно эффективны. Но что делать с первоначальным шумом? На нашем большом проекте мы не сможем настроить инструмент за 1 обещанный день. Только одна перекомпиляция, чтобы проверить очередную порцию настроек, занимает несколько часов. Мы не готовы потратить пару недель на всё это.
И это не проблема, а попытка найти повод не внедрять что-то новое. Конечно, в большом проекте всегда всё непросто. Но, во-первых, мы оказываем поддержку и помогаем интегрировать PVS-Studio в процесс разработки. А во-вторых, вовсе не обязательно начинать разбирать все предупреждения.
Раз ваше приложение работает, значит существующие там ошибки не так уж критичны и скорее всего живут в редко используемом коде. Серьёзные явные ошибки уже найдены и исправлены с помощью более медленных и дорогих методов. Но про это ниже в примечании. Сейчас нам важно другое. Нет смысла заниматься массовыми правками в коде, исправляя множество малозначимых ошибок. При таком большом рефакторинге легко что-то сломать и вреда будет больше, чем пользы.
Лучше считать существующие предупреждения техническим долгом. К долгу можно будет вернуться позже и работать со старыми предупреждениями постепенно. Используя механизм массового подавления предупреждений, вы можете начать быстро использовать PVS-Studio в большом проекте. Совсем кратко это происходит так:
Кстати, система хранения неинтересных предупреждений достаточно умная. Хранятся хеши для строки с потенциальной ошибкой, а также для предыдущей и следующей. Благодаря этому, если в начало одного из файлов добавить строчку, то ничего «не разъедется» и анализатор по-прежнему будет молчать на код, считающийся техническим долгом.
Надеюсь, нам удалось развеять одно из предубеждений относительно статического анализа. Приходите, скачивайте и пробуйте наш статический анализатор кода PVS-Studio. Он будет выявлять множество ошибок на ранних этапах и сделает ваш код в целом более надёжным и качественным.
Примечание
При разработке любого проекта постоянно появляются и исправляются новые ошибки. Ненайденные ошибки «оседают» в коде надолго, и затем многие из них могут быть выявлены при запуске статического анализа кода. Из-за этого иногда возникает ложное ощущение, что статические анализаторы находят только какие-то малоинтересные ошибки в редко используемых участках кода. Конечно, так оно и есть, если использовать анализатор неправильно и запускать его только время от времени, например, незадолго до выпуска релиза. Подробнее эта тема разбирается здесь. Да, мы сами при написании статей выполняем разовые проверки открытых проектов. Но у нас другая цель. Мы хотим продемонстрировать возможности анализатора кода по выявлению дефектов. Эта задача имеет мало общего с повышением качества кода проекта в целом и сокращением издержек, связанных с правкой ошибок.
Дополнительные ссылки:
Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Andrey Karpov. Handling Objections: Static Analysis Will Take up Part of Working Time.
Утверждение «статический анализ будет отнимать часть рабочего времени» в отрыве от контекста является верным. Регулярный просмотр предупреждений статического анализатора, выдаваемых на новый или изменённый код, действительно отнимает время. Однако следует продолжить мысль: но затрачиваемое на это время гораздо меньше, чем потраченное на выявление ошибок другими методами. Ещё хуже — узнавать об ошибках от клиентов.
Здесь очень хорошей аналогией могут являться юнит-тесты. Юнит-тесты точно также отнимают время разработчиков, однако это не является причиной их не использовать. Польза от написания более качественного и проверенного кода при использовании юнит-тестов превосходит затраты на их написание.
Ещё одна аналогия: предупреждения компилятора. Это вообще очень близкая тема, так как предупреждения инструментов статического анализа в первом приближении можно рассматривать как расширение предупреждений компиляторов. Естественно, когда программист видит предупреждение компилятора, он тратит на него время. Он должен или изменить код, или явно потратить время на подавление предупреждения, например, с помощью #pragma. Однако эти затраты времени не являются причиной отключить предупреждения компилятора. А если кто-то так сделает, это будет однозначно интерпретироваться другими как профессиональная непригодность.
Тем не менее, откуда же берёт начало испуг перед необходимостью тратить время на предупреждения статических анализаторов кода?
Всё очень просто. Программисты, ещё мало знакомые с этой методологией, путают пробные запуски и регулярное использование. При первых запусках любые анализаторы выдают огромный список предупреждений, на который даже страшно смотреть. Причина в том, что анализатор ещё не настроен. Настроенный же анализатор выдаёт при регулярных запусках малое число ложных срабатываний. Другими словами, большинство предупреждений выявляют реальные дефекты или код с запахом. Важно только сделать эту настройку. В этом и есть весь фокус, который превращает статический анализатор из зла, отнимающего время, в друга и помощника.
Любой статический анализатор вначале выдаст много ложных срабатываний. Причин тому много, и эта тема заслуживает отдельной статьи. Естественно, и мы, и разработчики других анализаторов борются с ложными срабатываниями. Но срабатываний всё равно будет много, если без подготовки вдруг взять и запустить анализатор на каком-то проекте. Такая же картина, кстати, и с предупреждениями компилятора. Пусть у вас есть большой проект, который вы всегда собирали, например, с помощью компилятора Visual C++. Предположим, проект чудесным образом получился переносимым и скомпилировался с помощью GCC. Даже в этом случае вы получите гору предупреждений от GCC. Кто переживал смену компиляторов в большом проекте, тот понимает, о чём речь.
Однако никто не заставляет постоянно копаться в горах мусора из предупреждений после смены компилятора или после запуска анализатора. Естественным следующим шагом будет настройка компилятора или анализатора. Те, кто говорит «анализ предупреждений отнимает много времени», оценивает сложность внедрения инструмента, думая только об всех этих предупреждениях, которые нужно побороть вначале, но не думает о спокойном регулярном использовании.
Настройка анализаторов, как и компиляторов, не так сложна и трудозатрата, как любят пугать программисты. Если вы — менеджер, не слушайте их. Они просто ленятся. Программист с гордостью может рассказывать, как он 3 дня искал баг, найденный тестировщиком/клиентом. И это для него нормально. Однако с его точки зрения неприемлемо потратить один день на настройку инструмента, после чего подобная ошибка будет выявляться, ещё не попав в систему контроля версий.
Да, ложные срабатывания будут присутствовать и после настройки. Но их количество преувеличивается. Вполне можно настроить анализатор, чтобы процент ложных срабатываний составлял 10%-15%. Т.е. на 9 найденных дефектов только 1 предупреждение потребует подавления как ложное. Так где же здесь «трата времени»? При этом 15% — это вполне реальное значение, о чём подробнее можно прочитать в этой статье.
Остаётся ещё один момент. Программист может возразить:
Хорошо, предположим, регулярные запуски статического анализа действительно эффективны. Но что делать с первоначальным шумом? На нашем большом проекте мы не сможем настроить инструмент за 1 обещанный день. Только одна перекомпиляция, чтобы проверить очередную порцию настроек, занимает несколько часов. Мы не готовы потратить пару недель на всё это.
И это не проблема, а попытка найти повод не внедрять что-то новое. Конечно, в большом проекте всегда всё непросто. Но, во-первых, мы оказываем поддержку и помогаем интегрировать PVS-Studio в процесс разработки. А во-вторых, вовсе не обязательно начинать разбирать все предупреждения.
Раз ваше приложение работает, значит существующие там ошибки не так уж критичны и скорее всего живут в редко используемом коде. Серьёзные явные ошибки уже найдены и исправлены с помощью более медленных и дорогих методов. Но про это ниже в примечании. Сейчас нам важно другое. Нет смысла заниматься массовыми правками в коде, исправляя множество малозначимых ошибок. При таком большом рефакторинге легко что-то сломать и вреда будет больше, чем пользы.
Лучше считать существующие предупреждения техническим долгом. К долгу можно будет вернуться позже и работать со старыми предупреждениями постепенно. Используя механизм массового подавления предупреждений, вы можете начать быстро использовать PVS-Studio в большом проекте. Совсем кратко это происходит так:
- Вы исключаете из анализа явно лишние директории (сторонние библиотеки). Эту настройку лучше в любом случае делать в самом начале, чтобы сократить время анализа.
- Вы пробуете PVS-Studio и изучаете самые интересные предупреждения. Вам нравятся результаты, и вы показываете инструмент коллегам и начальству. Команда решает начать его регулярное использование.
- Проверяется проект. Все найденные предупреждения отключаются с помощью механизма массового подавления. Другими словами, все имеющиеся на данный момент предупреждения теперь считаются техническим долгом, к которому можно вернуться позже.
- Получившийся файл с подавленными предупреждениями закладывается в систему контроля версий. Этот файл большой, но это не страшно. Вы делаете эту операцию один раз (или, по крайней мере, будете делать крайне редко). И теперь этот файл появится у всех разработчиков.
- Теперь все разработчики видят предупреждения, относящиеся только к новому или изменённому коду. С этого момента команда начинает получать пользу от статического анализа. Постепенно настраиваете анализатор и занимаетесь техническим долгом.
Кстати, система хранения неинтересных предупреждений достаточно умная. Хранятся хеши для строки с потенциальной ошибкой, а также для предыдущей и следующей. Благодаря этому, если в начало одного из файлов добавить строчку, то ничего «не разъедется» и анализатор по-прежнему будет молчать на код, считающийся техническим долгом.
Надеюсь, нам удалось развеять одно из предубеждений относительно статического анализа. Приходите, скачивайте и пробуйте наш статический анализатор кода PVS-Studio. Он будет выявлять множество ошибок на ранних этапах и сделает ваш код в целом более надёжным и качественным.
Примечание
При разработке любого проекта постоянно появляются и исправляются новые ошибки. Ненайденные ошибки «оседают» в коде надолго, и затем многие из них могут быть выявлены при запуске статического анализа кода. Из-за этого иногда возникает ложное ощущение, что статические анализаторы находят только какие-то малоинтересные ошибки в редко используемых участках кода. Конечно, так оно и есть, если использовать анализатор неправильно и запускать его только время от времени, например, незадолго до выпуска релиза. Подробнее эта тема разбирается здесь. Да, мы сами при написании статей выполняем разовые проверки открытых проектов. Но у нас другая цель. Мы хотим продемонстрировать возможности анализатора кода по выявлению дефектов. Эта задача имеет мало общего с повышением качества кода проекта в целом и сокращением издержек, связанных с правкой ошибок.
Дополнительные ссылки:
- PVS-Studio ROI.
- Статический анализ улучшит кодовую базу сложных C++ проектов.
- Heisenbug 2019. Доклад Ивана Пономарёва "Непрерывный статический анализ кода".
- Иван Пономарев. Внедряйте статический анализ в процесс, а не ищите с его помощью баги.
Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Andrey Karpov. Handling Objections: Static Analysis Will Take up Part of Working Time.