Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Прикладная кодогенерация для Java разработчика

Прикладная кодогенерация для Java разработчика

Андрей Когунь (http://deeprefactoring.ru/speakers/andrey-kogun)

Java разработчики, особенно те, кто заняты в заказной разработке, находятся в постоянной борьбе за то, чтобы писать меньше бойлерплейт кода, будь то тривиальные геттеры-сеттеры, конструкторы и т.п. или CRUD репозитории и контроллеры и часто ответом является кодогенерация в разных видах: поддержка генерации в IDE, генерация байткода при помощи Lombok, процессоры аннотаций порождающие новый код, фреймворки, позволяющие по описанию модели получить готовое (почти) приложение и много чего еще, не исключая новые и не очень JVM языки, которые позволют писать более лаконичный код и реализовывать DSL-и для решения прикладных задач.

В докладе мы сделаем ретроспективу наиболее часто применяемых подходов, поговорим об их сильных сторонах, ограничениях и практической применимости, а главное, попробуем взять ситуацию с кодогенерацией под контроль, чтобы она стала реально полезным инструментом эффективного разработчика.

Видео: https://youtu.be/GFnqbPIAPrg

========================
"Глубокий Рефакторинг" - открытый клуб разработчиков и профессионалов IT-индустрии Воронежа, организующий доклады на профильные темы - http://deeprefactoring.ru/

Открытый чат: https://t.me/deeprefactoring
Новостной канал: https://t.me/deeprefactoring_news
Видео всех докладов - https://www.youtube.com/c/deeprefactoring
Слайды выступлений: https://speakerdeck.com/deeprefactoring

Группа FB - https://www.facebook.com/groups/deeprefactoring
Группа ВК - https://vk.com/deeprefactoring
===========================

Deep Refactoring

June 26, 2019
Tweet

More Decks by Deep Refactoring

Other Decks in Programming

Transcript

  1. 2 # ЧТО ХОТИМ • Делать микросервисы (и монолиты) на

    Spring-e • Spring Framework • Spring Boot • Spring Data (JPA)
  2. 3 # Хотя, все происходит автомагически, не обойтись, без того,

    чтобы не написать немного кода: • Configuration • Entity • Repository • Service • Controller SPRING BOOT: МИНИМАЛЬНОЕ ПРИЛОЖЕНИЕ http://foxminded.com.ua/news/55-sravnenie-stekov-java-ee-i-spring-vozmozhnosti-i-ogranicheniya/
  3. 4 # А КАК ЭТО ОБЫЧНО ВЫГЛЯДИТ? @Entity public class

    User { @Id @GeneratedValue private Long id; @Transient private transient boolean isNew; @Column(nullable = false) private String name; }
  4. 5 # А КАК МЫ ХОТИМ? @Entity public class User

    { @Column(nullable = false) private String name; }
  5. 6 # А КАК МЫ ХОТИМ? @Entity class User {

    @Column(nullable = false) String name; }
  6. 7 # А КАК МЫ ХОТИМ? @Entity class User {

    @Column(nullable = false) String name @ManyToOne @Column(nullable = false) Country country }
  7. 8 # А КАК МЫ ХОТИМ? @Entity class User {

    @Column(nullable = false) String name @ManyToOne @Column(nullable = false) Country country }
  8. 9 # А КАК МЫ ХОТИМ? @Entity class User {

    @Column(nullable = false) String name @ManyToOne @JoinColumn(nullable = false) Country country }
  9. 12 # Когунь Андрей — программист • Работаю в компании

    КРОК • Провожу встречи Московского JUG @mskjug, #jugmsk • Преподаю Java О СЕБЕ
  10. 13 # Департамент разработки программного обеспечения • Заказная (в основном)

    разработка • Для “быстрой” разработки учетных систем реализован собственный фреймворк - jXFW О КРОК ДРПО
  11. 14 # О ЧЕМ ПОГОВОРИМ • Кодогенерация в IDE •

    Java Annotation Processing (apt) • Lombok • JavaPoet • Kotlin • Xtend
  12. 15 # КОДОГЕНЕРАЦИЯ В IDE • Итеративный (и не самый

    быстрый) процесс • Генерировать можно исходный java код, любые другие ресурсы https://youtu.be/EEAiyRuaUXU
  13. 16 # КАК РАБОТАЕТ ANNOTATION PROCESSING • Генерировать можно исходный

    java код, любые другие ресурсы • Процессор должен располагаться в отдельном от прикладного кода модуле • Процессор не может менять код, только создавать новый
  14. 17 # КАК РАБОТАЕТ ANNOTATION PROCESSING • Генерировать можно исходный

    java код, любые другие ресурсы • Процессор должен располагаться в отдельном от прикладного кода модуле • Процессор не может менять код, только создавать новый • Итеративный (и не самый быстрый) процесс
  15. 19 # ДЕЛАЕМ СВОЙ PROCESSOR ДЛЯ ENTITY @AutoService(Processor.class) public class

    EntityProcessor extends AbstractProcessor { @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); // processingEnv.getFiler(); // processingEnv.getMessager(); } @Override public Set<String> getSupportedAnnotationTypes() { Set<String> set = new HashSet<>(); set.add(Entity.class.getCanonicalName()); return set; } @Override public SourceVersion getSupportedSourceVersion() { return SourceVersion.latestSupported(); } }
  16. 20 # ДЕЛАЕМ СВОЙ PROCESSOR ДЛЯ ENTITY @AutoService(Processor.class) public class

    EntityProcessor extends AbstractProcessor { … @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { for (TypeElement annotation : annotations) { Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(annotation); // … } return true; } }
  17. 21 # ДЕЛАЕМ СВОЙ PROCESSOR ДЛЯ ENTITY … @Override public

    boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { … JavaFileObject repositoryFile = filer.createSourceFile(repositoryClassName); try (PrintWriter out = new PrintWriter(repositoryFile.openWriter())) { if (packageName != null) { out.print("package "); out.print(packageName); out.println(";"); out.println(); } out.print("public class "); out.print(repositorySimpleClassName); out.println(" {"); out.println(); … } }
  18. 23 # УЛУЧШАЕМ ПОДДЕРЖКУ ГЕНЕРАЦИИ ИСХОДНОГО JAVA КОДА • JavaPoet

    - https://github.com/square/javapoet MethodSpec setQueryParamsBuilderFactory = MethodSpec .methodBuilder("setQueryParamsBuilderFactory") .addModifiers(Modifier.PUBLIC) .addParameter(QueryParamsBuilderFactory.class, "queryParamsBuilderFactory") .addStatement("this.queryParamsBuilderFactory = queryParamsBuilderFactory") .addAnnotation(Autowired.class) .build();
  19. 24 # ДЕЛАЕМ СВОЙ PROCESSOR ДЛЯ ENTITY C JAVAPOET …

    @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { … JavaFile.builder(repository, typeSpec) .build() .writeTo(filer); }
  20. 26 # APT + LOMBOK? • Можно пользоваться готовыми аннотациями

    • А можно сделать свою: @MetaInfServices(JavacAnnotationHandler.class) public class EntityJavacHandler extends JavacAnnotationHandler<Entity> { }
  21. 27 # APT + LOMBOK? • Удачи с JCTree This

    is NOT part of any supported API. If you write code that depends on this, you do so at your own risk. This code and its internal interfaces are subject to change or deletion without notice. public void handle(AnnotationValues<Entity> annotation, JCTree.JCAnnotation ast, JavacNode annotationNode) { Context context = annotationNode.getContext(); Javac8BasedLombokOptions options = Javac8BasedLombokOptions.replaceWithDelombokOptions(context); options.deleteLombokAnnotations(); JavacHandlerUtil.deleteAnnotationIfNeccessary(annotationNode, Entity.class); …
  22. 28 # APT + LOMBOK? • JCTree • С этим

    разбирается Шерлок зато, с вашим кодом будет разбираться Шерлок Это больно и неприятно,
  23. 29 # МОЖЕТ, НАПИШЕМ СВОЙ ЯЗЫК? • Описываем доменную модель

    на собственном диалекте • Реализуем maven (gradle) плагин • Генерацию запускаем из IDE
  24. 30 # МОЖЕТ, НАПИШЕМ СВОЙ ЯЗЫК? • Описываем доменную модель

    на собственном диалекте • Реализуем maven (gradle) плагин • Генерацию запускаем из IDE • Иван Пономарев, КУРС – JavaCC + JavaPoet
  25. 31 # МОЖЕТ, НАПИШЕМ СВОЙ ЯЗЫК? • Описываем доменную модель

    на собственном диалекте • Реализуем maven (gradle) плагин • Генерацию запускаем из IDE • Иван Пономарев, КУРС – JavaCC + JavaPoet
  26. 34 # А ЧТО KOTLIN KAPT? @Entity data class User

    { val name: String } • kotlin-metadata • KotlinPoet
  27. 36 # Xtend (http://xtend-lang.org) — это статически типизированный язык программирования,

    приемник Xpand, построенный с использованием Xtext и компилирующийся в Java исходный код. • Начало разработки – 2011 год • Текущая версия – 2.17.0 О XTEND https://jaxenter.com/pirates-of-the-jvm-the-infographic-132524.html
  28. 37 # • Как в Java – • Классы, методы,

    поля • Лямбда-выражения • var (val) О XTEND • Не как в Java – • Active annotations • Template Expressions • Switch Expression • Нет continue, break
  29. 38 # • Как в Java – • Классы, методы,

    поля • Лямбда-выражения • var (val) О XTEND • Не как в Java – • Active annotations • Template Expressions • Switch Expression • Нет continue, break
  30. 39 # Возможность повлиять на результат компиляции Xtend Java @Active(EntityProcessor.class)

    public @interface Entity { … } АКТИВНЫЕ АННОТАЦИИ Xtend @Active(EntityProcessor) annotation Entity { … }
  31. 40 # Возможность повлиять на результат компиляции Xtend, из коробки:

    Xtend @Accessors(PUBLIC_GETTER, PUBLIC_SETTER) @ToString @EqualsHashCode @FinalFieldsConstructor … АКТИВНЫЕ АННОТАЦИИ
  32. 42 # üПодключить зависимости Xtend в Maven проект üДобавить собственную

    аннотацию @Entity, модифицировать код генерации сеттера üДобавить интерфейс Repository и класс Service, сгенерировать необходимые методы üПровалидировать модель üСформировать тест на генератор АКТИВНЫЕ АННОТАЦИИ XTEND И СОБСТВЕННЫЙ ПРОЦЕССОР АННОТАЦИЙ
  33. 43 # • Был еще плагин для IntelliJ IDEA, но…

    https://github.com/eclipse/xtext-idea • Сейчас вся надежда на LSP ТОЛЬКО В ECLIPSE IDE?
  34. 44 # НАГЕНЕРИРОВАЛИ КОД, А ЧТО ДАЛЬШЕ? • Перенести в

    src и дальше править там, или • Модифицировать генератор под новые задачи • Переопределить бины в Spring-е при помощи аннотации @Primary • Добавить точки расширения, например как в Spring Data Rest, при помощи событий
  35. 48 # • Наиболее актуальная группа с обсуждениями вопросов https://groups.google.com/forum/#!forum/xtend-lang

    • Официальная страница проекта https://www.eclipse.org/xtend • Основной репозиторий проекта https://github.com/eclipse/xtext-xtend/ • Тут будет опубликован код демо https://github.com/kogun ПОЛЕЗНЫЕ ССЫЛКИ
  36. 49 # ВЫВОДЫ • Технологии идеальны, …. • Не обязательно

    переводить проект на Xtend целиком • Лучше потратить время на разработку “интересного” кода, будь то генератор или бизнес-логика и не писать “скучный” код • Меньше кода написано – меньше ошибок