Автоматический контроль структуры класса

imageУ каждой компании есть свой стандарт оформления кода и важно придерживаться его. Встроенные в IDE форматеры кода решают это задачу частично, так как они в основном позволяют лишь добиться простого выравнивая кода. Помимо этого хочется еще и порядка в последовательности объявления как полей, методов, так и вложенных классов. Причин, по которым код-стандарт не соблюдается масса: программист перед отправкой кода в репозиторий может не заметить отклонение от стандарта; новый разработчик недостаточно внимательно прочитал документ; в погоне за хот фиксом о формате забыли; либо из-за банальной усталости или лени программиста; автоматического рефакторинга и так далее. Регулярный код-ревью не решает суть проблемы, так как занимает слишком много времени и тормозит разработку — нужна автоматизация проверки соответствия кода в момент его написания!

Частые проблемы:
  • конструктор неожиданно появляется в середине класса;
  • внутренний класс объявлен где-то в середине внешнего класса;
  • абстрактный метод объявлен где-то в середине большого абстрактного класса;
  • @Autowired метод тоже расположен где угодно но только не на самом видном месте;
  • статические билдер методы разбросаны по коду класса;
  • поле класса затерялось где-то между внутренним классом и методами.

Надоело такое терпеть в коде?

Многие из вас наверное уже знакомы с системой проверки стиля программирования CheckStyle, позволяющая автоматически проверять соответствие стиля Java кода к стандарту, определенным пользователем, а также с ее Eclipse плагином Eclipse-cs. CheckStyle используется консольно, реализовано множество плагинов и средств проверки на его основе и именно поэтому он был взят за основу. Вышеописанные проверки частично уже реализованы в модуле Declaration Order, работающему по стандарту, который был заявлен Sun. Но в нем нет возможности настроить стандарт под свои нужны и свой стиль. Наша группа разработчиков предложила и реализовала новый проверочный модуль, который бы удовлетворил любого за счет гибкости настроек в описании структуры класса.

Пользователю предлагается описать желаемый формат содержимого(структуры) класса с помощью кусочков регулярных выражений для полей(Field), методов(Method), конструкторов(Ctor), внутренних класов(InnerClass), разделитель между элементами класса — «###».
При задании структуры класса в регулярном выражении можно указывать модификаторы доступа, аннотации, типы, имена.

Примеры использования


Пример простейшего правила: в классе объявлены сначала поля, потом методы и потом внутренние классы:
Field(.*) ### Method(.*) ### InnerClass(.*)
Пример для полей: паблик статики, потом протектед, потом аннотирование @Autowired, потом приватные поля:
Field(public static final.*) ###
Field((private|protected) static final.*) ###
Field(@Autowired.* public) ###
Field(private.*)

Шаблон «.*» можно не указывать в конце правила — подставляется автоматически.

imageРезультат работы проверочного модуля виден сразу после сохранения файла, что позволяет разработчику мгновенно получать информацию о нарушении порядка. Разрешить это не составит и минуты, благо в Outline окне Eclipse методы и поля классов перетаскиваются мышкой и требуемый порядок легко восстанавливается. Каждое объявление расположенное в неправильном месте подсвечивается сообщением.

Пример правила из реальной жизни (формат нашего кода):
Field(private static final long serialVersionUID) ### Field((private|protected) final Log ([\w]*L|l)og|private static final Log [\w]*LOG) ### Field(public static final) ### Field((private|protected) static final) ### Field(@Autowired.* public) ### Field(public.*) ### Field(public) ### Field(private final) ### Field(private.*) ### Field(private) ### Field(.*) ### Method(public static void main.*) ### Method((public|protected)?\w*abstract) ### Method(public static .*(new|edit|create|open|clone).*) ### Ctor(public) ### Ctor(private) ### Method(@Autowired.* public) ### Method(.*) ### InnerClass(.*)

Необходима поддержка


К сожалению, данный модуль так и не попал в релиз CheckStyle 5.2 и 5.3. Переговоры с разработчиком проекта велись и он не дал объяснений чем не нравится подобное решение. Ссылка на патч обсуждение по новому чеку — тут.

Хотелось бы обратится к сообществу с просьбой поддержать CustomDeclarationOrderCheck в комментриях на SourceForge сайте, или написать в комментариях Хабрахабра возможные причины отказа и что стоит доработать, поделиться опытом продвижения своих наработок в открытые проекты.

Желающие проверить работоспособность модуля, могут воспользоваться нашими сборками:
  1. Eclipse-cs 5.3;
  2. Eclipse-cs 5.2;
  3. Eclipse-cs 5.1.

Для этого вам необходимо скачать архив для Eclipse-cs (update site) вашей версии и скопировать содержимое папки net.sf.eclipsecs.checkstyle_x.x.x.xxx...x из архива с заменой предлагаемых файлов в <Eclipse PATH>/plugins.

В предложенных сборках включены несколько патчей нашей команды, которые так и не были включены в релизы CheckStyle:
  1. Update for Maximum Line Length check;
  2. New check: CustomDeclarationOrderCheck;
  3. MultipleVariableDeclarations fixes.

После того, как вы установили себе плагин checkstyle и поставили на него патч с нашими дополнительными модулями, в
Window -> Preferences -> Checkstyle вы создаете, редактируете Check Configuration (New, Configure).
В появившемся окне конфигурации вам надо зайти в группу модулей Coding problems и создать из списка новый модуль Custom Declaration Order Check.

Наша команда не прекращает работу по развитию CheckStyle. Готовые патчи были предоставлены пользователями solid90, rusya7, daniilyar, romanivanov. Всем перечисленным было бы особо приятно присоединится к сообществу хабраюзеров.
Продолжение темы тут.
Метки:
Поделиться публикацией
Похожие публикации
Комментарии 29
  • 0
    Все чаще сталкиваюсь с проблемой чёткого разделения полей класса на свойства (то, что непосредственно характеризует объект) и зависимости (то, что нужно для работы объекта и будет инжектится). А ведь есть еще и константы! Но с ними проще, public static final обычно сразу «выделяются из толпы». Короче, хотелось бы сгруппировать поля по назначению. Приходится писать так (пример взят от балды):

    public class BadRobot {

    public static final int MAX_HEALTH = 60;
    public static final int MAX_SPEED = 15;
    // ^ Constants ^
    private FuelSupplySystem fuelSupply;
    private BulletSupplySystem bulletSupply;
    // ^ Dependencies ^
    private int currentHealth;
    private int currentSpeed;

    // Constructors and methods…

    }

    Можно ли каким-либо образом автоматически отслеживать, чтобы такое разделение всегда соблюдалось?
    • 0
      Если у вас все имена полей начинаются с «current», то вот такое регулярное выражение поможет вам:
      Field(public static final) ### Field(private.*current.*) ### Field(private .*)

      Тогда в данном случае порядок будет такой: константы, поля, dependencies.
      Либо надо придумать как описать dependencies одним регулярным выражением (например делать опору на имена, типы или аннотации)
      • 0
        см мой коммент ниже
      • 0
        по-моему, смахивает на фашизм. Чекстайла, PMD, Findbugs я думаю в большинстве случае достаточно.

        А вот если бы был плагин, который код форматировал в соответствии с чекстайлом — это было бы хорошо. Конечно, не все ошибки чекстайла можно исправить (остутствие комментария например), но стилевые вещи можно. А так приходится два конфига иметь — чекстайл и code formatting
        • +1
          Что подразумевается под фашизмом?
          Это и есть модуль к чекстайлу и его можно настроить под свои нужды.
          У чекстайла есть данная опция, может она поможет.
          • –2
            под фашизмом подразумевается проверка структуры класса на соответствие нормам. В принципе, это не такой уж фашизм, но, например, фэйлить сборку по такой проверке я рассматриваю как перебор
            • +1
              чекстайл позволяет настраивать уровень ошибки: error, warning, info, что позволяет выбрать необходимый уровень, для того чтоб не фейлилась сборка.
              + у нас более 4000 классов проекта описаны правилами, описанными в статье и читабельность кода значительно улучшилась.
        • +3
          в intellij idea можно задавать порядок размещения элементов класса
          • 0
            предложенное решение c помощью checkstyle позволяет сосуществовать программистам, использующим разные IDE. Более того проверка осуществляется и на уровне билд машины (continius integration system), Sonar и…
            • 0
              Не подскажете, как?
            • 0
              А есть способ спрятать пачку однострочных геттеров и сеттеров?
              • 0
                да
                • 0
                  это вопрос к idea ide или к модулю чекстайла?
                  • 0
                    Это вопрос из серии «наболело».
                • +1
                  Вообще, Jalopy прекрасно умеет добавлять комментарии к разным блокам кода, сортировать их по смыслу и алфавиту, добавлять модификаторы, если надо…

                  Оно прекрасно интегрируется в нетбинс, и, вероятно, в eclipse не хуже…
                  • 0
                    jindent пробовали?
                    • 0
                      jalopy круче, насколько я помню. Рулит автоматическая сортировка блоков кода
                      • 0
                        jindent тоже сортирует блоки кода, чем круче то?
                        • 0
                          Видимо был неправ. Исправлюсь
                          • 0
                            Да какая разница кто тут прав, просто интересно чем он лучше. В свое время сравнивал их и jindent более цивильно код сортировал и оформлял. Проблема только в том, что jindent платный :) Но он стоит своих денег.
                            • 0
                              А, может поэтому я не стал им пользоваться
                              А вы вообще следите за ними? Они развиваются?
                              • 0
                                Развиваются, вот С++ уже обозначен, но еще не зарелизен. Вроде ява тоже двигатся вперед.
                                • 0
                                  Это про индент?
                                  А что с джалопи?
                              • 0
                                Неделю назад на него наткнулся. Проблему платности решил (последняя статья на краклабе про это), если кому интересно будет.
                    • 0
                      Недавно была статья про svn-hook для агрессивной проверки форматирования кода на C# (режект коммита если проверка не прошла). Мне кажется, лишним реализовать поддержку «из коробки» такой проверки для CheckStyle не будет.
                      • 0
                        Если считаете что лишним не будет, то оставте пожалуйста комент на станичке с патчем для автора проекта Checkstyle что бы показать ему заинтересованость в этом чеке и других разработчиков. Зарание спасибо.
                      • 0
                        Объясните, пожалуйста, куда вставлять строку «Пример правила из реальной жизни...». По настройкам checkstyle потыкался — не нашёл.
                        • 0
                          После того, как вы установили себе плагин checkstyle и поставили на него патч с нашими дополнительными модулями, в
                          Window -> Preferences -> Checkstyle вы создаете, редактируете Check Configuration (New, Configure).
                          В появившемся окне конфигурации вам надо зайти в группу модулей Coding problems и создать из списка новый модуль Custom Declaration Order Check.
                          К сожалению, разработчики плагина на checkstyle для Eclipse не предусмотрели multi-line поле для текста, приходится все заполнять в одну строку…
                        • –1
                          Все эти ваши «конструктор неожиданно появляется в середине класса» и «внутренний класс объявлен где-то в середине внешнего класса» — это все мышиная возня.

                          Мне вот интересно, что, реально есть люди, которые при открытии класса прокручивают файл, выискивают методы, конструкторы, атрибуты?

                          А не используют навигаторы струкур классов, которые выдают перед глазами всю логическую структуру, правильно все группируя (гетеры-сетеры с атрибутами; расширения/перепределения в дочерних классах; реализации интерфейсов) и сортируя, если требуется.

                          А не используют иерархию пакетов, дабы наблюдать (читай — представлять в голове) вложенность пакетов и агрегацию классов.

                          А не используют иерархию типов, дабы наблюдать зависимости наследований.

                          Вас реально волнует отсортированы ли методы по названию, рядом ли расположены атрибут и его методы доступа?

                          Люди, опомнитесь! (с)
                          Не спускайте время на мышиную возню — пусть всей рутиной занимается компьютер (IDE), а вы — используйте свою жизненную энергию как подобает homo sapiens — реализуйте свой потенциал, добиваясь сдачи интересных проектов в срок, без багов и с изящной архитектурой, которую не прийдется долго и затратно рефакторить.

                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.