Всем привет!
Меня зовут Михаил. Я Android-разработчик в продуктовой команде Циан.
При разработке новой фичи приходится тратить время на создание однотипных файлов, в которых мы будем писать логику. Такие файлы очень похожи друг на друга, зачастую различие только в названии. Будь то создание presentation-слоя c Fragment -> ViewModel -> ComposeWidget (с типовыми State) или data-слоя c интерфейсами, Repository и их реализацией или создание компонента для DI.
Когда сталкиваешься с рутиной, есть желание от неё избавиться. Очень хочется, чтобы всё рутинное создавалось за пару кликов, и ты после этого мог создавать новую функциональность.
В моём представлении в этом могут помочь шаблоны. Вбиваю нужные параметры, и магическим образом всё готово, и всё на своих местах.
Размышляя, в каком виде я хочу видеть этот процесс, я пришёл к таким критериям:
-
Максимальная комфортность и простота генерации файлов, чтобы, буквально за пару кликов.
-
Шаблон должен легко модифицироваться всей командой разработки.
-
Шаблоны не надо искать или скачивать. При свежем develop – свежие шаблоны.
-
Это точно не скрипт, так как сложно поддерживать его актуальность.
-
Все должно работать в IDE и легко устанавливаться.
В далёком 2020-м году, Google удалили из AS поддержку кастомных Freemarker-ных шаблонов, альтернатив которым особо не было. А то, что имелось, не подходило моим критериям.
Совместив все критерии, я пришел к выводу, что мне нужен мой собственный plugin для IDE, который полностью удовлетворит все мои потребности.
И я его, знаете-ли, сделал..
Group File Template (GFT) — это плагин для создания классов из подготовленных заранее шаблонов. Настолько гибко, что подойдёт не только Android-разработчику.
Где его найти? В Marketplace IDEA или Android Studio. Просто вбиваем в поиск «GFT». Он там такой один.

Как работает плагин?
Шаблоны для использования должны находиться в корне вашего проекта в каталоге templates.

Файлы с расширением .tm — это абстрактный шаблон класса. На их основе и будут генерироваться классы. За генерацию по этим шаблонам отвечает «main.json».
В шаблон можно добавлять свои параметры, которые будут заполняться из IDE.
Main поддерживает 2 типа параметров:
-
поле для заполнения, в которое можно ввести любой текст;
-
выпадающий список, в котором надо будет выбрать один из вариантов.
Плагин создаёт файлы в той папке, из которой было вызвано создание.
Поближе рассмотрим main.json. Он имеет следующую структуру:
{ "name": "TestTemplate", // Название Шаблона "description": "Example for documentation", // Описание шаблона "path": "/templates/TestTemplate", // Путь к файлу main шаблона (Заполняется автоматически при создании шаблона из IDE) "param": [ // Список параметров, которые надо будет ввести при создании файлов из шаблона "name" ], "selectParam": [ // Список параметров, которые надо будет выбрать при создании файлов из шаблона { "paramName": "ide", // Имя параметра "paramValue": [ // Список вариантов выбора "Android Studio", "Pycharm", "intellij" ] }, ], "addFile": [ // Список файлов абстрактных шаблонов класса { "name": "{name}[-C]ViewModel.kt", // Имя, с каким создастся файл "path": "{ide}/viewModels/{name}[-c]", // Путь, по которому будет создан файл "fileTemplatePath": "example.tm" // Путь до абстрактного шаблона класса в каталоге с шаблоном } ] }
Опции
Можно заметить, что рядом с параметрами присутствуют какие-то загадочные символы в квадратных скобках. Например, «[-C]». Всё дело в том, что параметры имеют опции, которые могут поменять значение, вставленное из параметра:
-
[-s] — snake_case
-
[-C] — CamelCase
-
[-c] — camelCase
-
[-p] — point.between.words
-
[-sl] — slash/between/word
-
[-d] — dash-between-word
Например, написав «{«NewFeature»}[-s]», мы получим «new_feature».
Стандартные параметры
Помимо параметров, которые мы указываем в «main.json» файле, существуют стандартные параметры, которые можно применять в шаблоне.
-
{package} — пакет места, в которое вы делаете создание файла (если создать от каталога внутри модуля /ui/screen, то package будет выглядеть как ru.package.module.ui.screen).
-
{time} = Текущее время в 12-ти часовом формате —
15:56«03:56». -
{day} = Текущий день «04».
-
{month} = Текущий месяц «06».
-
{year} = Текущий год «2023».
Имена файлов и каталогов
Теперь давайте рассмотрим несколько особенностей и фишек плагина при работе с именами файлов и каталогов.
Если имя файла пустое, плагин создаст только цепочку каталогов, не создавая файл.
{ "name": "", "path": "path/{name}[-sl]/catalog", "fileTemplatePath": "" }
Для добавления файлов в Android-ресурсы пропишите «res/» в параметре «path». Плагин сам найдёт папку res в вашем модуле
{ "name": "{name}[-s]_main.xml", "path": "res/layout", "fileTemplatePath": "layout.tm" }
Чтобы добавить Unit-тест напишите «test/» в параметр «path». Плагин сам найдёт папку test в вашем модуле.
{ "name": "{name}[-C]ViewModelTest.kt", "path": "test/viewModels/{name}[-c]", "fileTemplatePath": "example.tm" }
Бывают случаи, что нам надо создать файлы не только там, где мы вызвали, но и в корне проекта.
Чтобы создать файл в корне проекта, напишите «~/» в «path».
{ "name": "{name}[-C].txt", "path": "~", "fileTemplatePath": "example.tm" }
Актуальные примеры шаблона можно посмотреть тут.
Что писать в .tm файле?
В tm файле находится ваш шаблон. Размечаем его параметрами, которые создали в main.json -> (param или selectParam)
К параметрам применяем нужные нам опции и собственно всё.
package {package}.analytics import ru.cian.presentation.analytics.base.sender.AnalyticsSender import {package}.analytics.builder.{name}[-C]Builder import javax.inject.Inject class {name}[-C]Analytics @Inject constructor( private val analyticsSender: AnalyticsSender ) { fun {name}[-c]() { val builder = {name}[-C]Builder() analyticsSender.sendEvent(builder) } }
Если вы добавили .tm файл в шаблон не через IDE, а руками, то не забудьте прописать его в «main.json» как показано выше.
Как создать шаблон?
-
Вводим название вашего будущего шаблона в диалоговом окне.

-
Чтобы создать новый шаблон, нажмите на пункт меню «Tools» -> «Create New Template».

-
Готово. В вашей папке с проектом в подпапке «templates» появился новый шаблон.

Как добавить файл в свой шаблон?
-
Чтобы добавить файл в шаблон, щёлкните по этому файлу правой кнопкой мыши и выберите «Add File in Template».

-
Плагин попросит вас выбрать, в какой шаблон вы хотите добавить файл (если у вас их несколько).

-
Переименовываем файл так, как он будет назван в шаблоне.

-
Готово, файл появился в выбранном шаблоне и виден в main.json.
"addFile": [ { "name": "build.gradle.kts", "path": "", "fileTemplatePath": "buildTemp.tm" }, ]
Как использовать созданный шаблон?
-
Кликаем правой кнопкой мыши по папке, в которой хотим создать файлы, и выбираем из списка нужный нам шаблон..

-
Заполняем параметры в диалоговом окне и нажимаем «OK».

-
Готово, создалась целая структура из шаблона!
Итого!
Что плагин умеет делать, мы разобрались, но чего он пока не умеет делать?
Пока что, не умеет вставлять куски кода в уже существующие файлы (фича на будущее), и чтобы подключить новые модули к app я создаю helpFile.md файл, в котором я прописываю путь до файла, и что в него надо вставить.
В main.json
{ "name": "helpFile.md", "path": "~", "fileTemplatePath": "helpFile.tm" }
и сам шаблон файла
[Добавить в](app/build.gradle.kts) implementation(project(":kmm_{name}[-s]_api")) runtimeOnly(project(":kmm_{name}[-s]_impl")) runtimeOnly(project(":{name}[-s]_compose")) [Добавить в](settings.gradle.kts) includeKmmFeatureModule("{name}[-s]")
Плагин помогает мне создавать большие модули, например, для использования kmm нам надо создать 3 модуля, в которых 8 каталогов.
-
api
-
androidMain
-
commonMain
-
-
impl
-
androidMain
-
androidTest
-
commonMain
-
commonTest
-
iosMain
-
-
ui module
-
androidMain
-
Он значительно сокращает время от старта фичи в работу до начала написания бизнес логики.
Использую даже для мелких задач, например, нам нужно создать из endPoint дерево каталогов.
Из — /getData/point/v2/map-search
Преобразует в дерево каталогов

Если у вас остались вопросы, пишите мне, всем с радостью отвечу!
Надеюсь, мой плагин облегчит вашу рутинную разработку!
Ccылка на Github
Ссылка на Marketplace
ссылка на оригинал статьи https://habr.com/ru/articles/740928/
Добавить комментарий