Эх, не люблю писать бойлерплейты, ведь есть IntelliJ IDEA и Apache Velocity

Добрый день, Хабр!

Речь в этой статье пойдет о том, как частично сократить объем кода, который зачастую приходится набирать вручную или откуда-то копипастить (боже упаси), средствами IntelliJ IDEA, а конкретнее — шаблонами файлов и кода. Если вы не достаточно знакомы с расширенным использованием возможностей этой IDE, то добро пожаловать под кат.

Не секрет, что зачастую приходится писать бойлерплейты — от простого создания точки входа программы до надоедающих скобок в JSON-ах. Сообщество программистов постоянно оптимизирует этот процесс — выпускаются фреймворки, микролибы, шаблонизаторы… Также дело значительно облегчают фичи IDE, в которой вы работаете — сюда относятся, например, автоподстановка или вышеупомянутые шаблоны файлов и кода.

IntelliJ IDEA file and code templates


Допустим, что мы хотим создать в проекте какой-либо файл. Для этого мы открываем проект через нашу любимую IDE, нажимаем хот-кей Alt+1, после чего появляется панель с деревом проекта. Далее кликаем ПКМ по директории, в которой нужно создать новый файл. Открывается вот такое контекстное меню:

image

Здесь нас, естественно, интересует пункт «New».

image

Как видим, здесь есть различные варианты — файл с расширением .java (Java Class), файл с расширением .kt (Kotlin File/Class), пакет и так далее. Также здесь есть секция с более специфичными названиями — HTML File, JavaFXApplication, Singleton. Если вы нажмете на что-нибудь из этого, то создадите файл, в котором будет несколько строк кода, специфичного для некоторой технологии или паттерна. Вот это все и есть File and Code Templates, то есть шаблоны файлов и кода. А под всеми шаблонами есть кнопка «Edit File Templates...» Она-то нас и интересует. Нажимаем её и видим такое окно:

image

Для среднего программиста на Java набор доступных в IDEA шаблонов достаточно бедноват. Но ему предоставлена богатая возможность редактировать их с помощью шаблонизатора под названием Apache Velocity. Про него есть несколько статей на Хабре, для дополнительного чтения я оставлю ссылки внизу статьи.

Что же он может? Рассмотрим картинку выше. Слева есть список доступных шаблонов (он внушительный, но это фикция, он довольно беден на полезности), сверху — вкладки с категориями шаблонов, центр занимает текстовое поле, в котором написан HTML-код, а снизу большой объем текста, помеченный как Description. Допустим, что я не веб-разработчик и в HTML не разбираюсь, поэтому выберем другой шаблон — например, Class.

image

Сразу замечаем не похожий на Джаву код вперемешку с Джава-кодом. Это и есть конструкции Apache Velocity.

Apache Velocity: как делать


Не будем погружаться в глубины API и документации, а разберемся с основными моментами, которые помогут нам писать свои шаблоны.

Обычно конструкции шаблонизатора мешают с обычным текстом, поэтому процесс несколько специфичен.

Основное:

$variable_name — обращение к переменной. Имя должно начинаться с латинской буквы и содержать только латинские буквы, цифры, а также символы "-" и "_".

#set($variable_name = "value") — присвоение переменной значения для дальнейшего использования в тексте.

#if(condition) stub #else stub #end — условный оператор. Вместо стабов можно подставлять то, что должно появиться в тексте, если условие выполняется (или не выполняется).

#include("another_template.txt") — подставляет содержимое указанного файла. Файлы, доступные для использования, должны быть указаны во вкладке Includes.

#parse("another_template.txt") — делает то же самое, что и #includes, но если файл содержит VTL (Velocity Template Language — то же, что и Apache Velocity), то он также будет исполнен.

#evaluate(string) — подставляет параметр и исполняет содержащийся в нем VTL.

Теперь о типах данных. Переменные VTL могут иметь следующие типы:

  • Строка
  • Число
  • Массив
  • Мап

Также стоит отметить, что строка здесь соответствует String-у в Джаве, поэтому у нее можно вызывать методы contains(), matches() и так далее.

Также для написания шаблонов в Джаве есть несколько predefined-переменных. Самая важная — ${NAME}, содержащая имя файла; ${PACKAGE_NAME}, содержащая имя пакета; есть переменные для времени, например, ${DAY}, содержащая сегодняшний день; есть возможность объявлять свои переменные, значение которых вам предложат задать, когда вы будете создавать файл по написанному шаблону. Вот так: ${VARIABLE_NAME}. Полный список всех predefined-переменных есть в текстбоксе Description.

Примеры?


Для пояснения всего вышесказанного, напишем несколько собственных шаблонов. Нажимаем в нашем окошке зеленый плюсик над списком шаблонов.

Точка входа в приложение


Однажды я обнаружил, что у Идеи нет шаблонов классов, содержащих public static void main(). Совсем (ну, или я их не нашел). С этого и началось мое знакомство с шаблонами IntelliJ IDEA и с VTL — я решил написать себе свой шаблон, с комментариями и vararg-ами.

Получилось так:

public class ${NAME} {
    public static void main(String... args) {
        
    }
}

Здесь все просто. Из VTL-специфичных игрушек здесь только ${NAME}, predefined-переменная. Зато я могу, например, вставить комментарий, содержащий сегодняшний день и имя автора.

/**
 *  Today is ${DATE}
 *  ${USER} is #if(${MINUTE}%1==0) the best #else not the best #end
*/
public class ${NAME} {
    public static void main(String... args) {
        
    }
}

Введем имя шаблона и сохраним его. После этого нажмем ПКМ где-нибудь у себя в проекте (советую создать тестовый проект, но можно поиграться и на продакшене) -> New -> Ваш шаблон. Вводим имя файла и видим:

image

Великолепно!

Шаблон для JUnit4-тестов


Более практичный и красивый пример. По соглашению об оформлении кода, тест-классы должны иметь в названии слово Test. Позаботимся о своей памяти и напишем вот такой шаблон:

import junit.framework.TestCase;

public class ${NAME}#if(!$NAME.contains("Test"))Test #end extends TestCase {
    @Override 
    public void setUp() {
        
    }
}

Теперь, если мы забудем при создании тест-кейса дописать в названии слово «Test», шаблон сделает это за нас!

Обратите внимание: здесь мы вызывали у строки метод contains. Чтобы вызывать методы строк, необходимо обращаться к переменной, опуская фигурные скобки. То же самое касается обращения к полям массивов и мап — никаких фигурных скобок!

Теперь сохраним шаблон и попробуем создать себе тест. Снова кликаем ПКМ на какой-нибудь директории -> New -> Ваш шаблон теста. Введем имя (без слова «Test»), создается вот такой файл:

image

Но это еще не все. Давайте удалим его и создадим заново с тем же именем, но на этот раз добавим в конце имени слово «Test». Что мы получаем? Абсолютно точно, никаких двух подряд идущих «Test»-ов.

image

Скрытый текст
На самом деле я просто вставил две одинаковые картинки, но это неважно. Оно работает!

Немного про схемы


В самом верху окна «File And Code Templates» есть выпадающий список, в котором есть два пункта — «Default» и «Project». Что это значит?

Это значит, что вы можете создавать шаблоны для всех проектов («Default»), либо только для текущего («Project»). Это называется схемы (Schemes) и конкретно в File and Code Templates их доступно только две, хотя в общих настройках их больше и можно создавать свои. Ну, неважно.

Что почитать


Упомянутые мною хабра-статьи, посвященные VTL

Да, она всего одна, потому что в процессе написания вторая куда-то потерялась.

Также есть английское руководство от IntelliJ

Но оно не раскрывает всех возможностей шаблонизации кода, хотя дает более полную характеристику юзабилити шаблонов.

И Getting Started с офф. сайта Apache Velocity

Заключение


File and Code Templates — весьма мощное средство IntelliJ IDEA, которое по какой-то причине мало освещено. Есть вещи, на которые сразу натыкаешься, начиная изучать предметную область, но шаблоны явно не относятся сюда — и зря. Срочно поделитесь этой информацией со своими друзьями и коллегами и посадите их писать шаблоны на VTL! Уговорите своего босса или владельца любимого open-source посадить человека оформлять contribution-гайды, вставляя в них шаблоны. Это — удобно!
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 8

    0
    Фича достаточно прикольная, но ее настроить отнимет много времени. Именно поэтому, мне, наверное, будет лень это сделать. Было бы достаточно неплохо, если б кто-то создал реп на гитхабе и добавлял бы туда самые разные шаблоны. Если такое уже есть, скиньте ссылку.
      +2
      у Идеи нет шаблонов классов, содержащих public static void main()

      Мне кажется, если создавать новый шаблон под каждое "классы, содержащие...", то в них можно будет заблудиться.
      Да и мне лично чаще всего надо добавить метод main() в уже существующий класс (чтобы быстро "на коленке" что-то проверить). Поэтому классы я создаю самые обычные. А метод добавляю с помощью Live Template: psvm + Tab

        +2
        import junit.framework.TestCase;

        Пакет junit.framework является deprecated уже больше 3 лет. Исправьте свой код. И другим такого больше не советуйте.

          +1

          Спасибо за замечание, но все же посчитаю его несколько неуместным. Статья — про VTL, а не юнит-тестирование, и пример — это пример, я не призываю неуклонно следовать ему. Вы же не станете копировать аннотации неизвестного ORM-инструмента из статьи про, например, Даггер, верно?

          +1
          Зато я могу, например, вставить комментарий, содержащий сегодняшний день и имя автора.

          В примере встроенного шаблона, который вы приводили выше, есть более удачный вариант:
          #parse("File Header.java")


          Это гарантирует, что у всех ваших новых классов будет одинаковая "шапка". И отредактировать её можно будет в одном месте, а не в каждом из десятка шаблонов для классов.

            +1
            Лично я создаю тесты так:
            1) Находясь в нужном мне классе (который нужно покрыть тестами), нажимаю Ctrl+Shift+T
            2) Create New Test
            3) Выбираю TestNG/JUnit/etc
            4) Ставлю при необходимости галки для setUp/tearDown
            5) Выбираю методы, которые нужно протестировать
            6) Нажимаю OK и шаблон для теста сгенерирован, остается «всего лишь» написать тесты.
              +1
              Зато я могу, например, вставить комментарий, содержащий сегодняшний день и имя автора.
              Совершенно бесполезная вещь, с тех пор как придумали системы контроля версий.
                0
                Соседи по цеху давно научились в кодогенерацию. Представляю вам yeoman.io

                Only users with full accounts can post comments. Log in, please.