11 июля 2017

Проверка стиля оформления кода в крупном проекте на GRAILS

Наш Java-разработчик Константин продолжает делиться с нами своими находками, делающими разработку качественнее и проще.

Соблюдать единый стиль оформления кода в крупном многолетнем проекте — всегда проблематично, особенно если над проектом работали несколько разработчиков, да и изначальное качество кода так себе. Тем не менее, я убежден, что даже в таком случае необходимо следить за качеством кода и улучшать как минимум некоторые части проекта, преимущественно новый код. Основная идея состоит в том, что каждый разработчик должен писать хороший код, даже если качество соседнего кода оставляет желать лучшего. Здесь я хотел бы рассказать о системе, помогающей улучшить стиль оформления кода в огромном проекте, и поделиться некоторыми наблюдениями о CodeNarc и его плагине для  Grails.

Я решил использовать плагин Grails от CodeNarc для проверки стиля кода (не то, чтобы у меня был выбор для проекта на Grails). Плагин генерирует хорошо оформленный html-отчет, где нарушения стиля разбиты по приоритетам (важные, средние, мелкие). Когда я запустил его на проекте, он вернул мне десятки тысяч ошибок. Это полезная информация, когда вы хотите получить статистику обо всем проекте целиком, но совершенно выбивает из колеи одного-единственного разработчика, который просто хочет удостовериться перед коммитом, что с его собственным кодом все в порядке. Конечно, можно найти измененные  классы в html-отчете с помощью поиска в браузере, но это очень неудобно — к сожалению, коммиты иногда затрагивают большое количество файлов.

Справиться с этой проблемой позволяет утилита CodeNarc Command-Line. Она делает то же самое, что и плагин для Grails, но использует для этого командную строку. Смысл в том, чтобы получить список измененных файлов из гита, проверить их с помощью CodeNarc и в качестве результата сгенерировать простой небольшой отчет только для тех файлов, которые были изменены разработчиком. Ожидается, что при прочтении этого отчета разработчик исправит ошибки, которые можно исправить без дополнительных рисков.

Как использовать CODENARC COMMAND-LINE

Описание использования приложения Command-Line на официальном сайте умещается на одной небольшой страничке, хотя вообще-то все немного сложнее. Моя конфигурация codenarc.xml выглядит следующим образом:

<ruleset xmlns="http://codenarc.org/ruleset/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://codenarc.org/ruleset/1.0 http://codenarc.org/ruleset-schema.xsd"
         xsi:noNamespaceSchemaLocation="http://codenarc.org/ruleset-schema.xsd">
    <ruleset-ref path='rulesets/basic.xml'>

    </ruleset-ref>
    <ruleset-ref path='rulesets/braces.xml'/>
    <ruleset-ref path='rulesets/grails.xml'>
        <rule-config name="GrailsStatelessService">
            <property name="ignoreFieldNames" value="grailsApplication, mailService"/>
        </rule-config>
    </ruleset-ref>
    <ruleset-ref path='rulesets/logging.xml'/>
    <ruleset-ref path='rulesets/size.xml'/>
    <ruleset-ref path='rulesets/unnecessary.xml'>
        <exclude name="UnnecessaryGetter"/>
    </ruleset-ref>
    <ruleset-ref path='rulesets/unused.xml'/>

    <ruleset-ref path='rulesets/formatting.xml'>
        <exclude name="SpaceAroundMapEntryColon"/>
        <exclude name="ClassJavadoc"/>
    </ruleset-ref>
    <ruleset-ref path='rulesets/imports.xml'>
        <exclude name="MisorderedStaticImports"/>
        <exclude name="NoWildcardImports"/>
    </ruleset-ref>
    <ruleset-ref path='rulesets/naming.xml'>
        <rule-config name='ClassName'>
            <property name='regex' value='^[A-Z][\$a-zA-Z0-9]*$'/>
        </rule-config>
        <rule-config name='FieldName'>
            <property name='finalRegex' value='^[a-z][a-zA-Z0-9]*$'/>
            <property name='staticFinalRegex' value='^logger$|^[A-Z][A-Z_0-9]*$|^serialVersionUID$'/>
        </rule-config>
        <rule-config name='MethodName'>
            <property name='regex' value='^[a-z][\$_a-zA-Z0-9]*$|^.*\s.*$'/>
        </rule-config>
        <rule-config name='VariableName'>
            <property name='finalRegex' value='^[a-z][a-zA-Z0-9]*$'/>
        </rule-config>
        <exclude name="FactoryMethodName"/>
    </ruleset-ref>
</ruleset>

Важно опубликовать это, потому что разные правила требуют разных зависимостей, и вы ответственны за то, чтобы предоставить их в classpath. На странице проекта указано, что classpath должен содержать следующие ресурсы:

  1. Groovy jar;
  2. CodeNarc jar;
  3. Log4J jar;
  4. Папки, содержащие конфигурационные файлы CodeNarc, такие как “codenarc.properties” или файлы с набором правил.

Не исключено, что вас попросят добавить больше ресурсов, чтобы не было ClassNotFoundException. Я дополнительно добавил GMetrics-0.3.jar и… еще один groovy :) Вероятно, разные правила используют разные версии groovy. Отдельно с первым или со вторым groovy вылетает ClassNotFoundException. К счастью, добавление двух groovy jars решило эту проблему, хотя это довольно рискованный шаг и мне повезло, что он сработал без сбоев (конечно, такой подход применим к ограниченному набору ситуаций, обычно мы не рискуем, если что-то идет не так с проверкой оформления стиля). Я пока не нашел решение получше, но не тратил много времени на это.

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

GROOVY1_JAR="lib/groovy-all-1.7.10.jar"
GROOVY2_JAR="lib/groovy-all-2.1.0.jar"
CODENARC_JAR="lib/CodeNarc-0.27.0.jar"
LOG4J_JAR="lib/log4j-1.2.17.jar"
GMETRICS_JAR="lib/GMetrics-0.3.jar"
BASEDIR="project/"
CONFIG_DIR="project/config/codenarc"

java -classpath $GROOVY2_JAR:$CODENARC_JAR:$LOG4J_JAR:$CONFIG_DIR:$GMETRICS_JAR:$GROOVY1_JAR org.codenarc.CodeNarc -basedir=$BASEDIR -rulesetfiles="codenarc.xml"

Интеграция с гитом

Скрипт ниже собирает все файлы в строке, а потом проверяет их, используя опцию “includes” приложения Codenarc Command-Line:

cd project
output=$(git ls-files -m | grep .groovy)
PATHS=""
while read -r line; do
    PATHS=$PATHS"**/$line,"
done <<< "$output"
PATHS=${PATHS::-1}

cd ..

GROOVY1_JAR="libs/groovy-all-1.7.10.jar"
GROOVY2_JAR="libs/groovy-all-2.1.0.jar"
CODENARC_JAR="libs/CodeNarc-0.27.0.jar"
LOG4J_JAR="libs/log4j-1.2.17.jar"
GMETRICS_JAR="libs/GMetrics-0.3.jar"
BASEDIR="project/"
CONFIG_DIR="project/config/codenarc"

java -classpath $GROOVY2_JAR:$CODENARC_JAR:$LOG4J_JAR:$CONFIG_DIR:$GMETRICS_JAR:$GROOVY1_JAR org.codenarc.CodeNarc -basedir=$BASEDIR -includes=$PATHS -rulesetfiles="codenarc.xml"

Предполагается следующая структура файлов (проект — корневая папка проекта Grails):

check.sh
libs
  groovy-all-1.7.10.jar
  groovy-all-2.1.0.jar
  CodeNarc-0.27.0.jar
  log4j-1.2.17.jar
  GMetrics-0.3.jar
project
  config
     codenarc
        codenarc.xml

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

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

Оригинал: https://kosbr.github.io/2017/05/12/codenarc.html

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Читайте в нашем блоге

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: