Pull to refresh

Comments 61

PC-Lint я смотрел, а в PVS и Klocwork метрики кода поддерживаются? есть ли соотв. стандарту MISRA?
В Klocwork — поддерживаются, в PVS — нет. Про MISRA, увы, сказать ничего не могу.
Хотел немного обсудить метрики и MISRA. А вот нужны ли они в действительности? Поясню мысль.

Есть метрики, можно смотреть разные графики, сделать симпатичный слайд в презентации с цифрами и диаграммами. А вот какой толк от всего этого? Именно практический толк, а не абстрактный показ начальнику успехов и т.п. Вот посчитал я цикломатическую сложность всех функций, знаю самые сложные. Что дальше? Сражаться с ними? Если проект в состоянии «пипец» то смотри, не смотри на графики, лучше он не станет. А на глобальный рефакторинг всё равно время выделено не будет. Так вот вопрос, кто здесь из присутствующих получил реальную пользу от метрик? Как и зачем Вы их используете? Мне действительно интересно услышать успешные истории применения метрик.

Теперь MISRA. Мы прочитали диагностические правила, входящие в этот стандарт и решили, что не будем делать эту лабуду. Конечно, там много важного и полезного. Но столько же бесполезного и устаревшего. И реализовывать целиком поддержу — это только «испортить отчёт», в смысле добавить невероятное количество ложных срабатываний. Я понимаю, что это отраслевой стандарт. Но вот по ощущению, он уже сгнил. Вопрос. Кто имеет полезный опыт использования MISRA и реально рад его применению? Мешает этот стандарт или нет? Интересны отзывы о практическом использовании в своих проектах.
Метрики — как инструмент для ПМ быстро увидеть, есть ли потенциальные проблемные места в проекте, и если есть, то передать их на разруливание ответственным.

Или, как вариант, быстро среагировать на коммит «потока сознания».

А цикломатическая сложность — полезная, но далеко не самая интересная метрика. Я бы, например, очень хотел увидеть на доставшихся мне на сопровождение проектах метрики fan-in и fan-out по каждому классу… Именно с целью диагностики наиболее нестабильных мест в системе.
> очень хотел увидеть
Т.е. нет под рукой подходящего инструмента или есть?
Не-а, нет. Не нашел. NDepend и SourceMonitor такого не расчитывают.
А кто рассчитывает из платных анализаторов? Или тоже неизвестность?
> Сражаться с ними?
Угу, цикломатика в 10 единиц явно требует пересмотра функции :)
Вы серьезно? Что же тогда делать с функциями сложностью >800? Например, большой switch-case…
Большой switch-case меняйте на словарик.
В C# я в таких случаях часто использую Dictionary<string, Action>
Некорректно написал: под «словариком» я имел в виду коллекцию ключей и значений.
Тогда уж напишу подробней:
Вместо большого switch можно использовать коллекцию ключей и значений.
Ключи — то, что сравниваем в switch
Значения — делегат (метод), который надо выполнить в случае нахождения искомого ключа в коллекции.
Про метрики: в рамках CI мы обложились метриками от и до — у нас и CCCC и SLOCCount.
Как только прикрутили — посмотрели все, возможно начальник поглядывает на них и до сих пор.
Количество строк кода и цикломатическая сложность не информативны (а в неумелых руках и противоречивы), так, например: один разработчки за день добавил кода на 10N строк и 10К сложности, а другой за три дня на N строк и К сложности — далеко не факт, что первый эффективнее второго, но так же не факт и обратное. А на степень связности и прочие полезные отчеты, как то особо никто не смотрит, ибо как всегда торопимся и на «вылизование» времени нет — ведь работает же…
Ага. Вот нашелся подходящий человек. Дальше вас немного помучаю. :)

Начальник посматривает — это хорошо. Но что дальше? Какие и как рычаги воздействия он применяет и на основании чего именно?
На сколько мне известно, то воздействие не применяется (во всяком случае с явной ссылкой на результаты метрик).

К предыдущему моему сообщению: Как только прикрутили — посмотрели все, ..., но теперь основная масса на них и не смотрит.
Т.е. все-таки это оказалось не более чем игрушкой? И начальник смотрит тоже просто на пузомерки тоже просто так?
Я хочу для себя лучше уяснить, актуальны метрики для практики или нет. Поэтому и задаю эти вопросы.
Ну начальнику в голову я не загляну, поэтому, что он думает я не знаю.
После ввода метрик провёл оценку и в достаточно неформальной форме дал поверхностную оценку деятельности лиц задействованных в различных проектах (в цедом объективно, но это было видно и без метрик). Более к подобным вопросам не возвращался. Но я не могу сказать, что он их игнорирует теперь — я не знаю…

Что касается разработчиков, то написал выше: вначале из любопытства с результатами метрики ознакомились, а в дальнейшем интерес пропал. На CI-сервере у нас бьют по рукам только за ошибки статических анализаторов — результаты метрик на статус сборки не влияют.

Т.о. для разработчиков, да, метрики это не более чем игрушка, а для начальника — не знаю (но думаю, что если и актуальный инструмент, то далеко не самый приоритетный, т.к. «воздействий» по результатам метрик не следует).

P.S. Чувствую, я тут сейчас договрюсь…
А какие статические анализаторы используете?
cppcheck — приоритетный, rats, cpplint — второстепенные, clang — только на машинах некоторых разработчиков, т.к. лицо занимающееся настройкой CIS не может его прикрутить (но очень хотим и его), splint формально работает, но настроен не корректно, кроме того парсим warning'и компилятора (gcc), т.о. в сухом остатке имеем cppcheck.
А под Windows что-то собираете? Мог бы предложить ключ для пробы PVS-Studio.
Пока нет. Но вот если бы можно было под Windows проверить gcc'шный код, то с большим удовольствием.
Что дальше?


Дальше настроить CI-сервер так, чтобы билд падал при нарушении метрик. Все остальное сделают разработчики.
У вас так и заведено, или это теоретическое предложение? Если так на практике, то прошу рассказать поподробнее. Какие метрики считаете и что является критической чертой.
Так заведено. Вообще у нас проект на Java, для проверки используется PMD, включены практически все метрики, в code-base сейчас ни одного нарушения. Как только возникает нарушение, билд фейлится — это и есть критическая черта.

Проект довольно большой, одно время над ним работало больше 30 разработчиков.
Пола не понял. Метрика — это грубо говоря, некоторые числа. Не очень понятно, что значит возникает нарушение? Было одно число, стало другое… Или всё же речь идет о каких-то диагностических правилах, а не о метриках?
Речь идет именно о метриках — Cyclomatic Complexity, количество строк в методе(максимум 12 строк), количество методов в классе, связность классов, куча стилевых правил вроде избегания более одного цикла в методе, вложенных if, вложенных циклов, большого количества точек выхода и т.д. и т.д. Если вам уж очень интересно, то я могу посмотреть конфиги и сказать конкретные пороги по конкретным правилам.
Так как практику внедрили не с самого старта проекта, то правила вводились постепенно — каждый разработчик вместе с коммитом новых фич добавлял исправления нарушений существующих метрик.
Хороший подход. По крайней мере, со стороны. А как бы вы оценили это, реально поработав с таким подходом? Отлично, так себе или вообще не стоило делать?
Отлично, потому что это заставляет разработчиков писать нормальный код. Кроме того, у нас 80%-е покрытие кода тестами и разработчики обязаны писать тесты на свой код.
Во-первых, например, ты уже не будешь писать колбасу на 100 строк, потому что тебе потом надо будет написать на нее тест, а тесты на большие методы писать довольно накладно, во-вторых, даже если ты осилишь тест, система все равно заставит тебя пересмотреть решение и разбить код на логичные части.

Вкупе это дает кумулятивный эффект — разработчик уже не может наговнокодить просто так, он обязан выдавать качественный по меркам анализатора код, который конечно же не идеален и не всегда является действительно качественным с точки зрения хорошего разрабочика но по крайней мере уже не откровенный говнокод.

Я считаю, что использование CI и принуждение разработчиков поддерживать приемлемый уровень покрытия тестами и соблюдать правила статических анализаторов — обязательно для любого серьезного проекта.
может, совершенно случайно, вы можете подсказать публичные скрипты реализующие проверки описанные вами (или хотя бы часть)?
FindBugs, PMD, но это для Java а не для C/C++.
Самих чеков там миллион, смотрите оффициальную документацию, если чего не найдете — спрашивайте.
Практическое использование MISRA и метрик кода есть в реальном проекте в авиационной области. Собственно здесь MISRA и коэф. Маккейба (я еще изучаю данный вопрос может еще пару метрик предложу для использования в нашем проекте) прописаны в стандарте на кодирование, что конечно может вызвать некоторые неудобства для программиста, но если стараешься сделать надежное ПО, код которого детерминирован, повторяем и верифицируем, то данные вещи как правило уже де-факто являются стандартом.
Теперь MISRA. Мы прочитали диагностические правила, входящие в этот стандарт и решили, что не будем делать эту лабуду.
Всё изменилось :-)
До 2018 года анализатор PVS-Studio был ориентирован на проверку десктопных приложений, работающих под управлением Windows, Linux и macOS. Соответственно, поддержка MISRA имела мало практического смысла. Никто не будет внедрять в большой существующий десктопный проект этот стандарт. Всё изменилось, когда в 2018 году мы начали поддержку встраиваемых систем.
PVS-Studio: поддержка стандартов кодирования MISRA C и MISRA C++.
есть файлы правил для проверки кода на соответствие MISRA здесь.

AU-thor options files (author recommended)

au-misra1.lnt (MISRA C 1998 (TM) — 1/5/12)
au-misra2.lnt (MISRA C 2004 (TM) — 1/5/12)
au-misra-cpp.lnt (MISRA C++ 2008 (TM) — 1/6/12)

>>PC-Lint здесь видит неоднозначность прочтения: a / b* c – это (a / b) * c или a / (b * c)?
По мне это скорее занудство
Это еще не занудство, у PC-Lint есть гораздо более занудные замечания! И к сожалению, именно они составляют 90% всех срабатываний.
Это вы не работали на пределе разрядности, когда результат сильно отличается от порядка вычисления.
Даже не обязательно работать на пределе разрядности. Например, если сравнивать результат вычислений с другим числом, и в зависимости от того, больше он или меньше, выполнять разные действия. Тогда, например, в debug/release может получиться разное поведение, и потом отлавливать такое неприятно.
Если операнды — целые числа, то результат отличается даже не «на пределе разрядности».
А это и есть «предел разрядности» :) Когда нужна дробная часть, а ея нэма.
Так дело не в потере точности, а в читаемости.
А можно оригинальную цитату описания? Что дело в _читаемости_ а не _неоднозначности_ вычисления?
Речь таки о читаемости! Порядок вычислений в данном случае строго задан. Вот цитата из описания:

Operator ‘Name’ followed by operator ‘Name’ is confusing. Use parentheses. — Some combinations of operators seem to be confusing. For example:
a = b – c – d;
a = b – c + d;
a = b / c / d;
a = b / c * d;

tend to befuddle the reader. To reduce confusion we recommend using parentheses to make the
association of these operators explicit. For example:
a = (b – c) – d;
a = (b – c) + d;
a = (b / c) / d;
a = (b / c) * d;

in place of the above.
Понятно. В общем-то, насколько помню, /* имеют один приоритет, и вычисляются слева-направо, однако точно помню, что кто-то из оптимизирующих оптимизировал порядок для сохранения точности, что давало весёлые эффекты, когда release работал, а debug нет.
Помню как-то сидел пару дней исправлял ошибки, которые нашел анализатор в проекте. Проект писался очень долго и не понятно кем. Исправил только те ошибки, в которых был уверен, например char separator == "|"; а после пришлось все откатить, так как эти ошибки были запатчены в совершенно неведомых местах и программа стала работать непредсказуемо )
Сочувствую! С таким проектом работать — врагу не пожелаешь.
Кстати, я ради интереса делал такое. Взял маленькую программу в духе «Hello world». Кажется сортировка одномерного массива и вывод результата на экран. Включил диагностику в PC-Lint на максимум и пытался сделать программу идеальной. Чтобы ни одного предупреждения не было. Долго сидел. Часа 2 наверное. Но так и не смог. :)
О, хорошая мысль, надо будет попробовать, если время найдется! Правда, на максимуме — это все же слишком для PC-Lint :)
Ну, да, там начинается паранойя в духе:

У вас используется переменная типа int. Это подозрительно. Нужно завести свой тип, отражающий смысл данных значений.

Пишешь typedef int MyCounter;

Тогда PC-Lint говорит, что подозрительно, что используется typedef! Это может запутать программиста.

Замкнутый круг. :)
Так эти проверки можно просто отключить, видимо просто по умолчанию всякая фигня включена. Я вот работаю над проектом, где оно настроено как надо — никаких сообщений такого рода нет, только нужные.
Не, ну если включать на максимум не глядя, то конечно :) А пример с typedef забавный.
PC-Lint весьма полезен для embedded software, когда код пишется под сертификацию и изначально используются стандарты вроде MISRA-C (с ограничениями естественно).
Похожую ситуацию я наблюдал с инструментом FxCop для дотнета. Тоже огромное количество сообщений, но классы варнингов собраны в группы и можно отключать как отдельные классы варнингов, так и группы целиком, плюс можно отдельное срабатывание отметить как неважное.

На практике же с любым средством статического анализа — его использование нужно встраивать в рабочий процесс, если один человек будет использовать анализатор а другие 49 не будут — пользы практически нет.
На практике же с любым средством статического анализа — его использование нужно встраивать в рабочий процесс

Очень согласен! А ещё, на мой взгляд, важно настроить под себя адекватный уровень «тревожности». Например, если например мы убежденно используем табы, вместо пробелов, то соответствующее сообщение (правда это не про FxCop, а про StyleCop) лучше отключить, дабы в 25000 неважных (в данном случа) сообщениях не затерялись те, ради которых и используется статический анализ.
Проверить-то результат можно, а дальше что? Куда его потом девать, если он сигнализирует о неудаче, а вызывающая функция не имеет механизма обработки исключительных ситуаций?
It depends.

Если неудача возникла в функциональности, необходимой для корректного продолжения работы — надо громко кричать и падать. Как вариант, перед падением можно попробовать автоматически восстановиться после ошибки прямо здесь же (например повторив эту операцию пару раз с задержками). Иначе могут быть (и будут) странные и абсолютно непредсказуемые глюки в других местах приложения, которые во-первых придётся очень долго отлаживать, и во-вторых которые могут привести к полной катастрофе (вроде порчи/искажения критических данных). Такая ситуация называется «поведение приложения не определено» и не делать ничего уговаривая себя что «и так сойдёт, и вообще вряд ли это настолько критично» — означает заниматься самообманом.

Если же неудача возникла в не столь критичной функциональности, то надо подумать, может стоит вообще выкинуть эту функциональность нафиг — если приложение может продолжать абсолютно корректно работать без этой функциональности, то зачем она там нужна?
Ну на самом деле что делать — понятно. Просто в данном конкретном случае речь шла о том, что чтобы сделать нормально, пришлось бы менять архитектуру, для чего не было ни ресурсов, ни желания. И чтобы сделать хоть что-то с минимумом усилий, я сделал то, что сделал — убрал иллюзию того, что статус обрабатывается.
>возможности отметить одно конкретное сообщение как ложно-положительное нет никакой

посмотрите получше, были ЕМНИП какие-то хитрые комментарии, которые отключали ложно-положительный warning в заданном куске кода
В коде при помощи комментариев специальных да, можно. Но… как бы так сказать, это не совсем тот вариант, который хотелось бы использовать. Мне не нравится идея менять код (пусть даже комментариями) для того, чтобы настраивать анализатор. Мне гораздо больше нравится идея кликнуть правой кнопкой на конкретном варнинге и выбрать из меню пункт «False-positive». Как по удобству, так и по скорости.
Sign up to leave a comment.

Articles