[Перевод] Кодогенерация в Dart
Известно, что для программиста очень хорошо быть ленивым, потому что делать больше с меньшими затратами — ключ к прогрессу. Никто не любит делать одно и то же снова и снова. Это утомительно, скучно, да и совсем не креативно. Повторяя одно и то же действие мы часто делаем ошибки, но, к счастью, есть те, кто действительно хорош и эффективен в выполнении однотипных задач. И это КОМПЬЮТЕРЫ!
На сегодняшний день кодогенерация это возможность сделать работу за наименьший промежуток времени. Основная идея проста: найти закономерность в однотипных и утомительных участках кода, которые приходится писать снова и снова, создать инструмент для генерации, запустить его и увидеть, как происходит волшебство!
В мире Android разработки такие инструменты хорошо известны каждому разработчику. Это и Retrofit, и Dagger, и Room. А как насчет Dart? И не менее важный вопрос: что нам нужно, чтобы создавать собственные инструменты для кодогенерации?
Чтобы создать инструмент для кодогенерации, нам потребуются следующие два пакета:
source_gen
Этот пакет предоставляет удобный API для генерации кода. Это абстракция над некоторыми низкоуровневыми Dart-пакетами, такими как analyzer и build. Несмотря на то, что использование этого пакета не является обязательным, он может избавить вас от многих трудностей.
source_gen предоставляет два абстрактных класса-генератора, которые следуют паттерну Посетитель:
Generator
: при наследовании этого класса будет посещаться каждый элемент вашего кода. Таким образом у вас есть полный контроль над тем, что сделать с каждым посещенным узлом или элементом.GeneratorForAnnotation
: этот класс похож на простой Generator, но при наследовании этого класса вы также указываете «аннотацию». Таким образом, посещаться будут только те узлы, которые аннотированы данной аннотацией. Остальные участки кода будут проигнорированы.
Также необходимо сконфигурировать Builder
, который будет оберткой над генератором. Есть три варианта:
- Если вы хотите написать
partial
участок кода, то следует выбратьSharedPartBuilder
. «part» позволяет вам разделить библиотеку на несколько Dart-файлов.SharedPartBuilder
создает файл с расширением.g.dart
. - Вы также можете использовать
PartBuilder
, если хотите использовать «part» подход, но вам требуется больший контроль над расширением сгенерированного файла, например,.my_file.dart
. - Если вы хотите написать самостоятельную библиотеку, которая может быть импортирована, используйте
LibraryBuilder
.
build_runner
Этот инструмент позволяет запустить генератор на этапе разработки. Он может быть вызван из конандной строки:
pub run build_runner
На месте
может быть:
build
: запускает генерацию один раз.watch
: запускает демона, который отслеживает изменения в файлах и запускает генерацию, когда потребуется.serve
: похож на watch, но запускается также как сервер разработки.test
: запускает генерацию один раз, создает общую выходную директорию и затем запускаетpub run test --precompiled
.
Чтобы source_gen
заработал, нужно также создать файл buil.yaml
, в котором указываются детали конфигурации кодогенератора.
Кодогенерация используется во многих известных библиотеках для Dart:
Во второй части будет показано как использовать аннотации и кодогенерацию для отслеживания всех TODO
в приложении.