Почти всю свою сознательную карьеру разработчика, руководителя проектов, консультанта по процессам разработки я оставался в плену очень распространенного и простого заблуждения. Если программа выполняет требуемые функции, претензий к стабильности и производительности нет, то это «нормальная» программа. Прошу прощения за несколько утрированную формулировку, но так оно и есть, если разобраться.

За определениями термина «качество программного обеспечения» не грех обратиться к стандартам. Несколько определений из разных стандартов удобно приведены на одной странице wiki. И что же?! В фокусе способности программы удовлетворять потребностям Заказчика.

Итак, основной акцент делался и делается именно на функциональности. Заказчик формулирует свои функциональные требования и принимает программу тоже по «списку фич». Тестирование в большинстве случаев сводится к функциональному. Многочисленные инструменты автоматизированного тестирования решают именно этот класс задач. Да, иногда формулируются требования по отказоустойчивости или максимального приемлемого времени отклика пользовательского интерфейса, или исполнения отчета. Да, особо разборчивые могут провести даже нагрузочное тестирование. Но программа принимается на опытную эксплуатацию (а бывает, что и сразу в промышленную) при отсутствии дефектов в функциях определенного уровня, например, без критических багов. Я наблюдал этот процесс приемки многократно в проектах разного размера и у разных заказчиков, и в собственных отделах разработки, и в проектах с аутсорсингом, на разных технологиях и различной степени критичности — везде главное функциональность.

Что же, наверное, это правильно. Но достаточно ли этого на самом деле, чтобы спокойно утверждать, что мы сделали (или нам изготовили на заказ) «качественный» продукт? Что же это такое «качественное приложение»? Можно ли измерить качество, от каких факторов оно зависит, как его совершенствовать?

Понятно что, конечные пользователи, заказчики или бизнес, как принято сейчас говорить, почти никогда не знают, КАК на самом деле устроен программный продукт, который они используют: насколько хорошо написан код, насколько сложна компоновка программа и много ли в ней зависимостей от внешних библиотек, безопасна для хранимой в ней информации, сопровождается ли нормальной документацией и многое другое. Но пользователь отлично замечает другое — ошибки исправляются медленно, новых функций от версии к версии прибавляется мало, интервал выхода версий постоянно растет, появляются проблемы со стабильностью работы, наконец, продукт начинает невыгодно отличаться аналогов.

Даже при поверхностном исследовании темы выясняется, что сегодня все же необходимо учитывать больше факторов качества, например, безопасность, сопровождаемость, эффективность, портируемость, надежность и т.д. Понятно, что для разных приложений и различных условий использования критичными факторами качества будут совершенно определенные характеристики или уязвимости, если хотите. Можно ли как-то формализовать, что такое, например, «сопровождаемое» приложение? Или «безопасное»? Да, оказывается можно, и такая работа была проведена, и более того ведется постоянно. В ISO 25000 определена эталонная модель качества, состоящая из 8 характеристик качества.

Ниже вы найдете несколько полезных ресурсов на эту тему:

  • OWASP — The Open Web Application Security Project. Эта организация занимается вопросами безопасности web приложений. Посмотрите, например, их ролик, посвященный одной из наиболее распространенных уязвимостей — SQL инъекциям (SQL Injections)


  • CWE — Common Weakness Enumeration. Развивает реестр и классфикатор уязвимостей в пограммном обеспечении.

  • WASC — Web Application Security Consortium.

  • MISRA — Motor Industry Software Reliability Association. Развивает стандарт разработки на языке C, а также С++.

  • ISO 25000 Ну, а как же без ISO/IEE. Это серия стандартов оценки и требований к качеству программного обеспечения.

Как же теперь эту информацию можно использовать на практике? Модели, стандарты, рекомендации, лучшие практики — это всё замечательно, но требует массы времени на «усвоение».

Заранее прошу прощения за примитивность примеров на PHP. Я знаю, что использование $this в статических методах приведет к ошибке. Необходимо найти все вхождения примерно такого кода:

<?php
class MyClass {
     public $message = "A message";
     static function printMessage(){echo $this->$message;
//VIOLATION
           return;
           }
     }
?>

Или, например, не рекомендуется использовать exit() or die(), потому что будет сложно потом понять истинную причину ошибки.


<?php
$filename = '/path/to/datafile';
$f = fopen($filename, 'r') or die("Cannot open file ($filename)"); // VIOLATION
... operations on file ...
?>

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

И здесь многие скажут, что эти задачи уже давно и успешно решаются анализаторами исходного кода программ. В общем и целом, использовать какие-либо программные инструменты вовсе не обязательно. Есть такая хорошая и полезная инженерная практика, известная как «пересмотр или просмотр кода» или code review. Однако, в реальной жизни надо учитывать ряд сложностей:

  • человеческий фактор — уровень квалификации, мотивации, частных обстоятельств может сильно повлиять на результат.

  • слабый контроль изменений — выявленные недостатки и уязвимости нужно аккуратно фиксировать и ставить в план на исправление, а потом заново пересматривать код. Это весьма дорогая практика.

  • слабая измеримость — без использования каких-либо инструментов для проведения code review практически невозможно измерять метрики качества, а следовательно, видеть процесс в динамике — помогает нам практика или нет, что можно улучшить и т.д.

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

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

Как было бы замечательно, если бы практика просмотра кода была лишена этих недостатков. Хочешь «перетрясти» все мегабайты накопленного кода на разных языках программирования с уверенностью и знаниями эксперта — пожалуйста. Хочешь проверять качество и отлеживать улучшения на каждом чекине — отличная идея. Хочешь видеть нормальные отчеты и графики по результатам анализа, а не только длинные списки найденных дефектов — ну, а кто не хочет? А еще бы оценить трудоемкость исправлений обнаруженных недостатков и уязвимостей, хотя бы приблизительно. И автоматически назначить задачи программистам в Jira, чтоб не отвертелись. А хорошо было бы еще…

Выходит, что в программных анализаторах исходного кода действительно есть определенная потребность. Почему же этот класс инструментов управления качеством оставался и остается у нас практически невостребованным. Я вижу здесь несколько основных причин. Во-первых, считается, это только инструмент для программиста. Например, Microsoft Visual Studio включает в свой пакет инструментов именно такой анализатор. Т.е. результаты анализа кода являются настолько техническими, что мало понятны тем, кто заинтересован в повышении качества продукта, но не готов вникать в детали. Во-вторых, относительно понятия «качества» программного продукта все еще распространено слишком узкое понимание вопроса. В-третьих, есть совершенно определенный конфликт интересов. Программист может быть вовсе не заинтересован в том, чтобы узнать о своем коде «всю правду». Руководитель разработки и так находится в постоянном цейтноте, планируя сроки выхода версий и формируя состав изменений будущих версий. Про технический долг он и так знает. Ну, выявит, анализатор еще тонну уязвимостей и недостатков — поставит в очередь. В лучшем случае. Тестировщики заняты и мотивированы выявлением ошибок в функциональности, а их руководители не видят общей картины того, как хорошо/плохо программа на самом деле сделана.

И все же. Красота же должна спасти мир, или нет?! Чистый и правильный код — это тоже красота! И мы нашли то, что искали — современный облачный статический анализатор кода — Kiuwan. Хотя бы из любопытства посмотрите на их сайт. Проверьте свои программы — это не займет больше нескольких минут времени. Испанцы сделали классный продукт!

Поддерживается целый рой технологий и языков программирования:


Objective-C, Java, JSP, Javascript, PHP, C/C++, ABAP IV, Cobol, JCL, C#, PL/SQL, Transact-SQL, SQL, SQL Forms, RPG, VB6, VB.Net, Android, Hibernate, Natural, Informix SQL

Увы, Pascal/Delphi/RAD не поддерживается. ReactJS тоже. Метрики, индикаторы, отчеты, графики — всё на самом современном уровне. Применяемую модель качества можно настраивать, а можно расширять — добавлять свои правила для своих уязвимостей. Об этом будет отдельная статья в нашем блоге.

Может интегрироваться с другими анализаторами кода — например, он может «переварить» результаты анализа кода Ruby из другого анализатора Brakeman. Постараемся сделать статью об этом в ближайшее время.

Интегрируется с Jira, SBM. Поддерживает разные системы контроля версий.

Что может не понравиться:
1) Если в вашей программе «очень много букв», то попросят денег.
2) Да, это облачный сервис. есть программа для локального анализа кода, но результаты разбора кода будут все равно отправлены в ваш личный кабинет в облако.
3) На английском

Начать можно отсюда

Комментарии (2)


  1. Alekseeva
    18.01.2016 12:34

    Спасибо за полезную в целом статью и ссылки в ней.

    А можно попридираться? Привычка тестировщика.

    1. На мой взгляд, статья начинается с некоторой подмены понятий: утверждается, что в определении качества основной упор сделан на функциональности, хотя в цитируемых определениях речь идет о фокусе на потребностях заказчика. Потребности же — это не только функциональность, но и те самые безопасность, сопровождаемость, эффективность, портируемость, надежность. В любом нормальном ТЗ этим потребностям отведен раздел нефункциональных требований.

    2. Возникает впечатление, что в статье противопоставлен статический анализ кода и code review и производится попытка показать, что статический анализ лучше. На самом деле они дополняют друг друга, поскольку никакой автоматический анализатор на самом деле, по крайней мере пока, не сможет помочь вам сделать код архитектурно красивым и повысить уровень владения кодом большим количеством программистов.

    3. Из статьи не понятно каким образом анализатор становится не чисто техническим инструментом. Ведь свои сообщения он все равно пишет чисто техническим языком. Эта тема как-то не слишком раскрыта.

    4. Сомнительно звучит, что программист не хочет знать о своем коде всю правду. Хочет. И хочет сделать код лучше, причем, чем раньше, тем лучше. И чтобы никто первоначальных недостатков не увидел. В этом-то анализатор и может ему наилучшим способом помочь: его можно использовать и поправить дефекты на самой ранней стадии.

    5. Совсем ничего не сказано о возможных ложных срабатываниях анализаторов.


  1. aionin
    18.01.2016 14:54

    Спасибо за хорошие вопросы.
    1. Это, конечно, так. Термин «Потребности» нужно понимать действительно в широком смысле. Однако на практике, функциональные требования настолько доминируют над сознанием и отношениями, что прочие «смыслы» зачастую остаются на бумаге. Более того, не функциональные требования часто проверяются только в первой версии, а для последующих уже нет. Вот, например, классическая заглушка для ФТР одного из наших проектов
    8. Обеспечение доступности
    Функционально-технические решения по обеспечению доступности не изменяются и соответствуют описанию в соответствующем разделе ФТР предыдущей версии N.N


    2. Нет, не противопоставление. Скорее я хотел донести идею, что использование автоматических средств анализа исходного кода — это своеобразный недорогой «code review». Разумеется, просмотр кода опытными разработчиками или архитекторами может помочь выявить серьезные ошибки проектирования, например. Однако, использовать такой ресурс для более простых задач анализа текста программы, которые гораздо эффективнее и быстрее решает соответствующий инструмент — это расточительство времени и сил. Опять же я привёл примеры, когда альтернативы анализаторам кода просто нет.
    Что касается использование анализатора кода в качестве средства обучения хорошим правилам программирования, то здесь я бы поспорил. Когда анализатор выдаст исчерпывающую справку о найденной уязвимости с подробным описанием возможных последствий, предоставит примеры того, как код исправить, укажет на строки кода, где эта уязвимость обнаружена — то это уже вполне можно считать элементом обучения.

    Например, для C# из Kiuwan

    Overload Equals method on value types
    Description
    For the value type «structure', default implementation of the method that determines the equality of two objects (Equals) habitually it will have a performance lower than a personalized implementation and because of this it recommends to personalize this method and Violation will appear when it is not like that.
    Code
    OPT.CSHARP.Csharp.OverloadingEqualsValueTypes
    Reference
    msdn.microsoft.com/en-us/library/7h9bszxx(VS.80).aspx
    Violation code

    public struct A {     //VIOLATION
          int x;
         }
    


    Fixed code

    public struct A {
             int x;
    
             public override bool Equals(object o)  //OK
             {
                 A obj = (A)o;
                 return (this.x == obj.x);
             }
        }
    


    3. Базовым результатом работы любого анализатора кода будет список найденных уязвимостей, ошибок, замечаний. Всё самое интересно начинается потом. Как работать с этим списком? Классификация, сортировка, группировка, приоритизация. Над этим слоем можно построить более общие отчеты по обнаруженным проблемам.

    Выше — общая статистика по приложению

    Выше — статистика по портфелю приложений, командам разработки или внешним исполнителям и многое другое.
    Пример общего отчета анализа С# приложения.
    И это только срез отчетов после одной проверки. А если процедуру производить регулярно, то появится возможность посмотреть на информацию в динамике — кто улучшает качественные характеристики, кто ухудшает, по каким показателям и т.д.
    Еще на один момент я обращал внимание в статье — насколько важно обнаруженные уязвимости преобразовать в задачи. Здесь два аспекта — оценка сложность исправления и доставка задачи исполнителю. И то и другое, например, есть в Kiuwan — система помогает примерно оценить в часах, днях сколько нужно времен на исправление. Есть выгрузка в Excel. Есть интеграция с Jira / SBM. Наверное можно и с другими трекерами установить „рабочие отношения“.
    Вот теперь это уже не только инструмент самообразования программиста, а полноценный инструмент контроля качества серьезной организации, как мне представляется.

    4. Как известно, есть две парадигмы в отношении управления людьми. Или нужно исходить из того, что все сотрудники лентяи, бездари, халтурщики и т.д. или наоборот, что они все молодцы, болеют за дело, как за свое, пожертвуют своим временем и здоровьем ради проекта и т.д. Я обычно исхожу из „второй“, а получается как в „первой“. :)

    5. Я даже скажу больше. Важно не только отбрасывать ложные срабатывания, но и „отключать“ целые типы уязвимостей, которые для ваших обстоятельств использования приложения, например, значения не имеют.
    В Kiuwan пользователь может отключить отдельные найденные ошибки — »Mute" — и они больше не попадут в отчет даже при повторном анализе. Либо настроить свою модель качества приложений, повысив приоритет одних характеристик и снизив для других, что отражается и для расчета метрик и для поиска уязвимостей. Либо загрузить свои правила обнаружения дефектов.

    Как-то так. Надеюсь, что ответил на ваши вопросы.