Эргономичный код
767 subscribers
75 photos
1 video
20 files
375 links
Канал о разработке поддерживаемых бакэндов - про классическую школу TDD, прагматичное функциональное программирование и архитектуру и немного DDD.

Группа: https://t.me/+QJRqaHI8YD

https://azhidkov.pro
Download Telegram
А вот и актуальный хэйтинг подоспел
Во всех бэках на спринге (со Spring Data Jpa), которые я видел, был репоз на каждую табличку (кроме свяазующей многое-ко-многому).

И не то, а чём думали авторы Spring Data: https://stackoverflow.com/questions/21265262/are-you-supposed-to-have-one-repository-per-table-in-jpa/21277087#21277087

А наткунлся я на это вот этой любопытной ссылке - https://spring.io/blog/2018/09/24/spring-data-jdbc-references-and-aggregates
походу, можно юзать спринг дату для бойлерплейтного кода, но не тащить при этом адовый проект.

а вот в эту ссылку я полез после того, как в своём петпроджекте на кторе и ебине проапгрейдил ктор 1.4.1 -> 1.4.2 (минор казалось бы), и у меня всё поотавливалось т.к. ебин юзает блокирующий jdbc, а ктор весь из себя на корутинах и не блокирующий и походу впилили туда проверку. И чёт я задумался, что мош спринг не так уж и плох:)

#posts@ergonomic_code #whynojpa@ergonomic_code #dd@ergonomic_code #spring_data_jdbc@ergonomic_code
Рад представить вам анонсированный разгромный пост о том почему JPA лучше не использовать в серьёзных проектах:)
Это новый рекордсмен моего блога по объёму - закрыл гештальт:)

Ну и если я вдруг налажал с технической точки зрения - пишите. Может я, наконец, 15 лет спустя открою страшную тайну как правильно готовить JPA:)

#posts@ergonomic_code #whynojpa@ergonomic_code #spring_data_jdbc@ergonomic_code
Ну и наконец, линко-пост о кэшировании в Spring Data JDBC.

Про кеширование там полезно тем, что подсвечивают ряд граблей, свойственных JDBC, но самое полезное - раздел Why Spring Data does no caching, в котром автор пинает JPA.

Подписываюсь под каждым словом этого раздела всеми ~8 годами своих мучений с JPA/Hibernate в проде.

#posts@ergonomic_code #spring_data_jdbc@ergonomic_code
Привет!

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

И одним из аспектов кризиса является разочарование в агрегатах и Spring Data JDBC. Я пока не понимаю где проблема - в самих идее и технологии или ДНК (моём) и у меня нет другой идеи как делать эргономичный персистанс, поэтому пока придерживаюсь старой схемы.

Так вот, накопал интересный доклад о Spring Data JDBC от его разработчика. Он там из первых рук объясняет мотивацию создания модуля (мало кто в мире понимает и может эффективно использовать JPA, за пределами туториалов и хелло воролдов) и даёт пачку рецептов решения не совсем тривиальных проблем.

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

Потенциально есть ещё вариант с package private методами для мутации некорневых сущностей, но:
1) В Котлин package private всё ещё не завезли:(
2) Это требует пакетирования по агрегатам
Однако главный аргумент против того, чтобы не искать способ соблюдать это правило в изменяемой модели - императивный код сложен в понимании и подвержен ошибкам

А вот если у модель неизменяемя - то по определению, любая мутация любой части агрегата должна будет пройти через его корень, чтобы собрать новое состояние корня, со ссылками на новые состояния некорней. При том сами некрони можно спокойно выставлять для "публичного чтения".

#ergo_approach@ergonomic_code #spring_data_jdbc@ergonomic_code #talks@ergonomic_code #whynojpa@ergonomic_code
Привет!

Продолжаю проверять гипотезу, что это у меня проблема в ДНК, а с агрегатами и Spring Data JDBC всё ок, смотрю очередной видос

Всё тот же автор Spring Data JDBC одновременно:
1) пинает JPA
2) восторгается агрегатами
3) предлагает декомпозировать систему на основе агрегатов
4) запрещает циклы в зависимостях
Смотрю как в своё зеркало 21ого года:)

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

Ну и наконец:
"it will feel painfull ... but people have to think where stuff belongs and this alone is I think a great benefit"
Со второй частью согласен полностью. Но хочется найти способ обойтись без боли

#talks@ergonomic_code #spring_data_jdbc@ergonomic_code #whynojpa@ergonomic_code #ergo_approach@ergonomic_code
Привет!

Посмотрел доклад "Меняем Spring Data JPA на Spring Data JDBC!". Хотя докладчик в начале сказал, что не призывает использовать JPA, мне что-то захотелось написать микропост в защиту Spring Data JDBC.

#talks@ergonomic_code #spring_data_jdbc@ergonomic_code
Привет!

Посмотрел Keynote SpringIO 23, резюме:
1) Вышел Spring Boot 3.1
1.1) Автоматический запуск докер-композа (!) О_О - теперь реально можно запускать проекты буквально в один клик после клона репоза
1.2) Я думаю в ближайшее время переедем на него - расскажу о впечатлениях

2) Поддержка Project CRaC в Spring Framework 6.1 (осень 23) - сохранение снапошота памяти запущенного приложения при сборке, чтобы потом в проде запустить его за пару сотен миллисекунд

3) В обеих демках мелькала Spring Data JDBC (а не JPA) - у меня всё больше складывается ощущение, что Спринг пушит JDBC в качестве замены JPA

#talks@ergonomic_code #spring@ergonomic_code #spring_data_jdbc@ergonomic_code
👍2
Привет!

Для меня работа с БД - это самая большая боль Эргономичного подхода.
Возможно, после публикации второго тома ретро (ориентировачно в четверг) - я напишу пост о том, почему мне не подходит хибер и почему подходит Spring Data JDBC.

Но SDJ хоть и подходит концептуально, в повседневной жизни бывает довольно болючь (о чём я тоже когда-нибудь напишу).

Поэтому я, стараясь не привлекать внимание санитаров, подумываю о собственном ОРМе (у меня уже даже есть небольшой прототип АПИ, работающий поверх Мап).

И в ОРМе самой большой проблемой видится загрузка развесистых агрегатов - агрегатов с несколькими вложенными коллекциями. И если оставаться в широко поддерживаемом подмножестве SQL, то у этой задачи (как казалось) нет эффективного решения - либо куча отдельных запросов, либо декартово произведение. Либо какой-то умный планировщик, который комбинирует эти подходы, и на котором если не докторскую, то кандидатскую точно можно защитить.

В качестве потенциально решения этой проблемы на "продвинутом SQL" мне виделся SQL MULTISET или его эмуляция на json-е.

А сегодня наткнулся на статью с амбициозным названием "This is the Beginning of the End of the N+1 Problem" от основного разработчика SDJ, где он описывает решение на оконных функциях. И самое чудесное, что это решение в минимальном виде уже работает в мейлстоуне SDJ 3.2.0.

Возможно, мне всё-таки не придётся писать ОРМ и SDJ станет тем инструментом работы с БД, который не только подходит мне идеологически, но и зубную боль не вызывает.

P.S.
Но не спешите переезжать на SDJ ради решения проблемы Н+1. Если вы сейчас на хибере, то у вас совершенно точно изменяемая модель данных и, скорее всего, не функциональная архитектура. И если вы не смените подход к проектированию на неизменяемую модель данных и функциональную архитектуру, то получите все те ужасы, баги и боли, которых говорит Андрей в Меняем Spring Data JPA на Spring Data JDBC!. И очень мало получите взамен.

#posts@ergonomic_code #spring_data_jdbc@ergonomic_code #ergo_approach@ergonomic_code
4🤔1
Привет!

Я посмотрел Migrating from (Spring Data) JPA to Spring Data JDBC.
И пересмотрел Меняем Spring Data JPA на Spring Data JDBC! (на который уже писал своё фи).

Удивительно, насколько эти доклады об одном и том же разные:
1. Дженс начинает с тестов и выделяет для них целый слайд. Андрей между делом упоминает их в конце доклада
2. Дженс топит за то, чтобы делать это очень аккуратно и постепенно и рассказывает про любопытную методику больших рефакторингов. А Андрей шарашит с распахнутым забралом и даже без тестов
3. Дженс практически ~50% доклада (~20 минут из ~40) посвящает перепроектированию модели данных. Андрей посвящает этому ~3% (~2 минуты из ~60)
4. Естественно, Дженс чморит JPA, а Андей - SDJ

Зато, оба доклада раскрывают тему генерации id 🤷‍♂️ И я до сих пор не понимаю, чем default nextval('seq') плох, раз уж generated always as identity не подходит

И эта разница навела меня на новый аргумент против jpa за sdj.

При разработке приложения на базе JPA основными сложностями будут изучить саму JPA, потом накастовать аннотаций, чтобы она делала то, что надо, а через полгода угадывать как это всё будет работать. Это всё - привнесённая сложность (Accidental complexity), которую можно и не привносить.

А при разработке приложения на базе SDJ основной сложностью будет декомпозиция модели на агрегаты. И вот это уже сложность, присущая задаче.

И хотя, теоретически, JPA позволяет так же выполнить декомпозицию модели, она не обязывает это делать.
В результате в приложениях на JPA на декомпозицию предметной области забивают и в ответ получают Big Ball of Mud. Так произошло в 100% проектах на JPA, которые я видел.

Проектирование агрегатов - действительно сложная тема и по ней написано много хороших книг. Но с ними со всеми есть одна проблема - они полагаются на экспертов предметной области.

И хотя это лучший способ выполнить декомпозицию предметной области, у него есть недостатки:
1. Эксперты предметной области зачастую недоступны в принципе.
2. А когда доступны - извлечение формальной модели из головы другого человека средствами естественного (неформализованного) языка - это в целом задача на уровне "мишшн импоссбл", а для многих технических специалистов просто за гранью понимания.

Из-за этого проектирование агрегатов зачастую хромает на обе ноги.

Поэтому я сейчас использую более технический подход к проектированию агрегатов. Об этом подходе надо написать отдельный пост, но если вкратце, он выглядит так:
1. Спроектировать ЕР модель, особое внимание уделить слабым сущностям
1.1 Признаки слабой сущности:
1.1.1 её жизненный цикл ограничен жизненным циклом другой сущности - позиция заказа не может существовать без заказа, номер не может существовать без отеля
1.1.2 она упоминается всегда в контексте другой сущности - вторая строчка заказа такого-то, номер 215 отеля такого-то
2. Все стержневые сущности (со слабыми и без них) считаются корнями агрегатов
3. Провести транзакционный анализ - в идеале в рамках одной транзакции должен меняться один агрегат и меняться целиком. Если это не так - что-то надо объединить, а что-то разделить.

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

Ещё ссылки по теме:
1. Нотация описания неизменяемой модели данных (+ Ответы на вопросы по Эргономичной нотации ER-модели)
2. Агрегаты
3. Рациональный подход к декомпозиции систем на модули или микросервисы

В общем, инвестируйте свой интеллект в решение присущей сложности задачи, а не привнесённой:)

#why_sdj@ergonomic_code #whynojpa@ergonomic_code #ddd@ergonomic_code #spring_data_jdbc@ergonomic_code #jpa@ergonomic_code
👍76
Привет!

Обещанные демо-проекты.

Project Moby - демо того, как я выкручиваюсь на Spring Data JDCB с энергичной загрузкой, когда она нужна.

Project Sherlok - демо того, как я выкручиваюсь с динамиеческими запросами.

Обе техники используются в Trainer Advisor.

#spring_data_jdbc@ergonomic_code #trainer_advisor@ergonomic_code #demo_projects@ergonomic_code
🔥10
Ещё пункт забыл

Неожиданная встреча
Случайно встретил бывшего студента.

Он рассказал, что следующему поколению советовал идти ко мне на курс по БД. А я не пришел - взял "декрет".
Но все равно приятно - снова задумался вернутся в следующем году.

А ещё (к вопросу про JPA в комментах) рассказал, что у них в большой корпорации пришел СТО, сказал что они не умеют в JPA и теперь они то ли все новое пишут, то ли старое переписывают на SDJ.

#spring_data_jdbc@ergonomic_code
👍2
Привет!

Периодически гипотезы, лежащие в основе ЭП, рушатся о жестокую реальность промышленной разработки, что приводит к кризисам ЭП, которых уже было три штуки: раз по мотивам проекта Barcoder (решение), два (решение) и три (решение - нафик ООД, ДДД и private внутри одного репоза😀) - по мотивам #project_e.

И вот по мотивам #project_r за последние 5 дней у меня случился и благополучно разрешился очередной кризис ЭП:)

В связи с чем у меня пачка новостей.

Книга
Это уже новость второй свежести, но для контекста надо проговорить - я договорился с менеджером проектов издательства Питер начать с апреля плотную работу над книгой про ЭП. Так что надеюсь, на горизонте пары лет книга увидит свет.

Отказ от ФА
Номинально самая большая новость - я решил отказаться от ФА (которая когда-то была одним из трёх столпов ЭП).
Но по сути ничего не меняется - ЭП всё так же предполагает использование неизменяемых структур данных и максимально возможное разделение логики и ио.
Это просто признание реальности, что в ЭП, который начинался как сильно функциональный, я методично отказываюсь от отличительных черт ФА/ФП:
1. уже очень давно я отказался от монад и ROP-а в пользу защитных условий
2. затем я затащил операции в императивную оболочку
3. во многом по мотивам Проекта Р я вернул в милость выброс исключений вместо возвращения Result
4. по мотивам Проекта Р, я утащил сбалансированную форму системы с архитектурного уровня системы, на локальный уровень отдельных методов

Отказ от SDJ как дефолтной технологии работы с БД
А вот по сути самое больше изменение - я решил отказаться от SDJ в качестве дефолта для работы с БД.
Это всё ёще допустимый в рамках ЭП т.к. его всё ещё легче "продать" заказчикам и коллегам, но по умолчанию я теперь предлагаю использовать какой-то легковесный DSL - jooq или Exposed, ещё не решил что именно.

Это опять же обусловлено опытом Проекта Р - там у меня львиная доля запросов чтения рукописные, потому что SDJ не в состоянии эффективно доставать данные этого проекта, а после того, как мне пришлось ещё и два кастомных метода сохранения написать - стало понятно, что я борюсь с технологией. Этому решению так же поспособствовали пост из канала одного из участников нашей группы.
И решение перейти на UUID-ы, которое так же было обусловлено опытом разработки Проекта Р, где надо сетапать огромные графы объектов в тестах и с генераций ИДов на уровне БД это очень сложно.

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

1. проекция структуры данных (модель данных) - тут про агрегаты и связи между ними
2. проекция состояния (объектная модель) - тут про объекты в рантайме (порты, операции, ресурсы) и связи между ними
3. проекция структуры поведения (процедурная модель) - тут про методы и связи между ними

Плюс я туда сразу накидал кучу примеров (пока на словах😕), а так же процессы построения всех этих структур и итоговой архитектуры.

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

И возвращаясь к книге - эта статья по сути - четверть книги. Заполнить там пробелы, добавить примеры и теоретическая часть по ЭА готова. Вспоминая про бейзкамповский Hill Chart, у меня сейчас такое ощущение, что я достиг холма реализации ЭА и дальше только дело техники. Лишь бы очередной проект не зафейлил очередную гипотезу 😄

#the_book@ergonomic_code #functional_architecture@ergonomic_code #ergo_arch@ergonomic_code #ergo_persistance@ergonomic_code #spring_data_jdbc@ergonomic_code
Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥6👍42
Привет!

Ток что впервые за 4 года пришлось запилить руками dirty checking в SDJ...

Хотел написать я.
Но уже буквально коммитаясь я в последний момент одуплил, что я поломал основную идею ДДД, SDJ и эргономичного персистанса - у меня одна сущность оказалось частью двух агрегатов.

По бизнес процессу, она сначала появляется в одном агрегате, а потом перемещается во второй агрегат того же типа, но в другую связь (условно - из черновика в основные данные). Добавил удаление ссылки из первого агрегата при перемещении - и обошлось:)

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

5-ый кризис ЭП пролетел буквально за часик:)

Хотел написать я.
А потом упёрся в то, что есть ещё одна сущность, которую я сделал частью нескольких агрегатов одного типа...

А если учесть, что эта сущность в перспективе будет контрибьютить в инварианты этого типа агрегатов - Проект Р, кажись, не у ЭП, а у ДДД трубу зашатал...

#project_r@ergonomic_code #ddd@ergonomic_code #ergo_persistance@ergonomic_code #spring_data_jdbc@ergonomic_code
😱4👍1