Заметки по докладам со Spring IO 2022

November 3, 2022

На той неделе я был в полуотпуске и посмотрел 3 миллиона видео со Spring IO 2022 и SpringOne 2021. На удивление, из докладов SpringOne (вроде как главной конфы по Spring) - меня вообще ничего не заинтересовало. Большую часть я даже открывать не стал, а то что посмотрел - зря время потратил, хоть и на x1.5 и многое просто перематывая.

А вот на Spring IO было много прям крутых докладов и я собрал микропост (пост, написанный за один проход без редактуры) из своих заметок по этим видео.

Серия про модульные приложения

Modular Applications

https://www.youtube.com/watch?v=DlQ6Ht9Cf5s&list=PLe6FX2SlkJdTVSt4D3bBCOkVeXB0qGdEY&index=25

Тут мужики всё правильно говорят. Но есть нюанс. В качестве ответа на вопрос "как находить границы модулей" они предлагают DDD. И если вы можете себе это позволить - круто, делайте так. Если же вы (как и я) не можете себе этого позволить - попробуйте более простую методику на базе эффектов. У меня есть пост с подводкой и кратким описанием этой методики, но полноценный пост я ещё не осилил. Он у меня первый в очереди, но пока что у меня львиную долю сил и внимания отнимает Проект Э.

Молния!!! Spring ведёт R&D проект "Modulith", по поддержке модульных монолитов!

Лет 5-6 назад я ненавидел Спринг и считал его корнем всех бед в архитектуре (пакетирование по слоям, инъекция на филдах, глобальный компонент скан, анемичная модель, связный двунаправленный граф JPA-сущностей). А сейчас вижу, что у нас (теперь) общие ценности - начиная с рекомендации инъекции через конструктор, продолжая рекомендуемой структурой пакетов (Locating the Main Application Class) и рекомендацией делать репозы на агрегаты, а не сущности (Are you supposed to have one repository per table in JPA?) вместе с Spring Data JDBC, который, кажется, они сейчас активно продвигают вместо JPA и вот заканчивая "Modulith-ом".

Getting modules right with Domain-driven Design

https://www.youtube.com/watch?v=Q_0XW46IlHY&list=PLe6FX2SlkJdTVSt4D3bBCOkVeXB0qGdEY&index=49

Тут мужик расказывает как искать границы по DDD. И лишь подтверждает мой тезис, что это не для всех - сначала надо собрать всю команду включая доменных экспертов в большой комнате с длинной стеной и провести сессию "эвент шторминга" (не путать с "сорсингом") - я не представляю, как мне это проделывать на моих проектах.

Ещё интересная мысль - ООАД фокусируется на существительных, а ДДД - на глаголах. А ЭП/ОД, судя по всему (раньше не думал в этом ключе), на их связях

Spring for the architecturally curious developer

https://www.youtube.com/watch?v=zrqupmaIsto&list=PLe6FX2SlkJdTVSt4D3bBCOkVeXB0qGdEY&index=31).

В этом докладе один из содокладчиков первого показывает Modulith в действии. И это очень круто - в тестах я сейчас примерно тош самое пытаюсь делать на коленке с переменным успехом.

А генерация доков - это вообще бомба.

Let’s build components, not layers

https://www.youtube.com/watch?v=-VmhytwBZVs&list=PLe6FX2SlkJdTVSt4D3bBCOkVeXB0qGdEY&index=38

Увидев докладчика, я начал относиться к докладу со скепсисом, т.к. недавно читал его книгу, где он топил за чистую архитектуру. Но в то же время, я вполне успешно использую его идеи по созданию модулей в Spring-приложениях, поэтому всё-таки продолжил смотреть. И не зря.

Как и я, сейчас он пришёл к выводу, что ЧА не должна быть выбором по умолчанию. А выбором по умолчанию должна быть компонентная архитектура.

Однако, как и все прочие подобные доклады, он не говорит как компоненты находить - в своём примере он их просто дал свыше. А я - говорю:)

Смотрите этот доклад, берите на вооружение декомпозицию на базе эффектов для поиска компонентов и вы получите добрую половину Эргономичного подхода. Читайте и применяйте PPP of Unit Testing (включая функциональную архитектуру) и вы получите ЭП целиком:)

Плюс я прямо сейчас как раз думаю вести в гайдлайн Проекта Э пакеты api (с сервисами и тем, что у них в публичном интерфейсе светится) и impl (со всем остальным), но пока только думаю.

Ну и он там топит за заголовочные интерфейсы. Но у него есть хороший аргумент за них - у него на этом базируется ArchUnit-чек, который следит, за тем чтобы никто не лазил в кишки модуля. Я сам до ArchUnit ещё не добрался, но если доберусь и пойму, что подругому никак - тоже соглашусь на заголовочные интерфейсы.

Thoughts about layered architecture – Mapping efficiently with SQL

https://www.youtube.com/watch?v=glxS4Ffxtdw&list=PLe6FX2SlkJdTVSt4D3bBCOkVeXB0qGdEY&index=23

Как можно догадаться из названия, тут мужик топит за то, чтобы в случае простого чтения выкинуть нафиг сервисы и весь маппинг и стримить данные из БД напрямую в браузер. Хорошая идея, я об этом давно думаю и даже писал пару раз, но пока так и не решился. Он там говорит, что добавление поля в стандартной схеме потребует кучи изменений в куче разных файлов. Но если стримить напрямую из базы, то это всё равно будет куча изменений, хоть и в одном файле. Плюс мы потеряем красивое описание модели данных, по которому можно чудесным образом сваггер сгенерять.

Но что меня больше всего пугает: там где такой подход даст больше всего пользы - запросы где надо вытащить кучу данных из кучи таблиц - этот подход нанесёт больше всего вреда с точки зрения инкапсуляции. В моём мире за каждую таблицу отвечает один модуль, и если какой-то модуль начинает напрямую лазить в чужие таблицы, то это вопиющее нарушение инкапсуляции. Именно из-за этого я пока держусь в стороне от этого подхода.

Ну приводит один из моих любимых аргументов против JPA - показывает код маппера и спрашивает есть ли там побочные эффекты (обращения к БД). Ответ - it depends (c). Невозможно ответить на этот вопрос, т.к. ответ зависит от маппинга сущностей и что творилось в коде выше по стеку. Это и есть "нелокальность" рассуждений ака сложность кода, которую всегда тащит ленивая загрузка.

How fixing a broken window cut down our build time by 50%

https://www.youtube.com/watch?v=c-GV2PxymoY&list=PLe6FX2SlkJdTVSt4D3bBCOkVeXB0qGdEY&index=12

Хороший доклад, показывающий как правильно писать тесты на Spring, чтобы они работали настолько быстро, насколько это возможно. Спойлер - надо не использовать фичи, которые ломают кэш контекстов (DynamicPropertySource, MockBean, Spy и т.д.).

От себя добавлю ещё пару советов:

  1. Используйте переиспользуемые тест-контейнеры (https://rieckpil.de/reuse-containers-with-testcontainers-for-fast-integration-tests/)
  2. Базы храните на RAM-диске (.withTmpFs(mapOf("/var" to "rw")).withEnv("PGDATA", "/var/lib/postgresql/data-no-mounted"))

Modern frontends using Spring Boot and Thymeleaf with htmx

https://www.youtube.com/watch?v=okCdaBTQsik

Возможно вам не нужны фронтэндеры, React, Redux, nodejs, npm, webpack, javascript, jsx, REST API, боль и страдания. Возможно ваш фронт вполне можно сделать на Thymelead + HTML + htmx + Bootstrap + чуть-чуть Alpine.js.

Я сам за последние лет 7 ни разу так не делал, но в последнее время мне эта идея всё больше и больше нравится. Один внутренний проект с серверным рендерингом мы уже сделали очень успешно (в плане трудозатрат) и при первом удобном случае я попробую пропихнуть такой подход в коммерческий проект.

И ещё доклады про htmx: