Эргономичный код
831 subscribers
96 photos
3 videos
24 files
442 links
Канал о разработке поддерживаемых бакэндов - про классическую школу TDD, прагматичное функциональное программирование и архитектуру и немного DDD.

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

Канал в Max: https://max.ru/id544512614458_biz

https://azhidkov.pro
Download Telegram
В данном случае это не плохо, а с учётом того, что публикация должна быть сделана через Transactional Outbox - неизбежно. Но если у функции появляется 2 и более подобных смежных ответственностей - это уже хороший повод, чтобы их отцепить как раз через события. Это и упростит код реализации, и надёжность работы функции повысит, и тесты ускорит и упростит.

Или, если на самом деле в зависимости от параметров функция делает "(А и Б) либо (А и В)" - то её надо разбить на две отдельных функции, переиспользующие "А".

#ergo_approach@ergonomic_code #books@ergonomic_code #project_e@ergonomic_code
👍3🤔1
Привет!

ИИ похмелье...

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

Это ужас. Он там и найденные правила гайдлайна нарушил, и не нашёл нужные правила (но тут косяк фреймворка, наверное) и не реализовал требования, которые явно были в ТЗ.

Единственное, что он сделал так же хорошо как и я - пропустил несколько мест, которые тоже аффектились изменениями. Но, в отличие от меня, прикрыл их подорожником, когда наткнулся...

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

Когда-то слышал, что есть два типа гонищков:
1. первых находит предел сцепления машины с дорогой снизу - начинает ехать медленно и разгоняется пока не улетит
2. второй находит предел сцепления сверху - сразу топит на все деньги, а улетев превращается в первый тип

Вот я в этот раз был гонщиком второго типа. Теперь стал первого:)

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

И немного инсайтов:

1. используйте тайм блокинг между разработкой продукта и ии контекста агента. Когда пилите фичи - не допиливайте контекст сразу, если агент лажанул (как максимум - дополняйте туду). Когда пилите контекст - не пилите продукт по настоящему. Берёте одну задачу, один промпт и повторяете его до тех пор, пока результат не окажется нужным (или хотя бы заметно лучше, чем был).

2. Попробуйте добавить в системные инструкции "Chat answers must be at least 2x shorter than your natural default." - это заметно снижает объём ии слопа для ревью, а просадки в качестве я не заметил.

3. пишите файлы контекста своими руками, а потом отдавайте на ревью/перевод ИИ.

—

* примеры скиллов: "определить границы фичи", "составить список эндпоинтов, которые будут затронуты", "составить список критериев приёмки", "спроектировать рест апи", "закодировать приёмочный тест", "реализовать модель", "реализовать операцию"

#ai@ergonomic_code
👍4❤2
Привет!

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

1. d-r-q/dot-agents - мои личные предпочтения и скиллы для работы агентов.
2. ergonomic-code/dot-agents - актуальная версия фреймворка.
3. ergonomic-code/dot-ai - архив с первым подходом к фреймворку.

Ну и первый, на мой взгляд полезный кусочек нового фреймворка - скилл генерации человеко-читаемого описания REST API.

С ним можно написать Codex-5.3 low:
[$describing-rest-api](skills/describing-rest-api/SKILL.md)

Опиши апи [NewsAdminController.kt](NewsAdminController.kt) .createNews


И получить такую штуку.

Или можно попросить Codex-5.3 medium:

[$skills/describing-rest-api/SKILL.md)
Опиши как изменилось апи NewsAdminController.kt .createNews в коммитах 39b4bf9d, 1abf8b1e, 05f01a28, f4622e63, b60daa6d, 0f4e2031


И получить такую штуку.

Отказ от ответственности: как с любым сгенерированным контентом, в сгенерённых доках могут быть ошибки.

—

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

И вот с семантикой диффа, видимо, надо делать не один скилл/промпт, а многошаговый workflow:
1. собираем что вообще надо описать
2. с новым контекстом собираем ir что было и здесь и далее процедурно валидируем его
3. с новым контекстом собираем ir как стало
4. с новым контекстом, из что было, что стало, кодом и историей гита, собираем хинты диффов - какие эндпоинты поменяли пути, имена и структуру моделей, но продолжают выполнять ту же роль
5. с новым контекстом из данных пп 2-4 собираем ir с диффом
6. процедурно генеряем md

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

#ai@ergonomic_code #tools@ergonomic_code
👍9❤3
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Привет!

Саша Раковский наконец-то опубликовал обновленную версию своего ии-фреймворка /continue.

И меня этот фреймворк вверг в комплекс неполноценности.
Не столько размером и полнотой фреймворка, которые тоже впечатляют, сколько кристальной чёткостью процесса в Сашиной голове, которая стоит за этим фреймворком. Я сейчас буксую именно на процессной части, хотя мне казалось, что у меня процесс тоже хорошо отстроен и формализован. Но на деле - только лишь казалось.
👍4❤3
С другой стороны, я планирую вернуться в большой (очень большой) постинг и чутка отвлечься от ии-темы.

В рамках чего я продолжил писать серию постов про миграцию на Spring Boot 4 - на той неделе я выкатил в прод ядро Проекта Э на Spring Boot 4 - и не единого разрыва, если вы понимаете о чём я.

Так как материала получается реально много и прорабатывать его реально тяжело - буду публиковаться по частям. И в первой части расскажу о потенциальных проблемах с автоконфигурациями и Jackson-ом.
🔥7
Привет!

Пост про пробемы с Jackson-ом при миграции на Spring Boot 4 движется, но с трудом - я по каждой проблеме восстанавливаю исходное состояние, снимаю ошибки и в неочевыдных местах разбираюсь что именно поменялось и/или почему фикс работает. Довльно нудная и утомительная работа, поэтому решил развеяться и добавил на вики первое приближение статьи с шаблоном именования тесткейсов.

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

Реклама

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

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

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

В чём мой секрет?
В тестах.

Мой подход к тестам имеет одну очень крутую в текущих условиях особенность — его можно внедрить ретроспективно практически в любой проект. При наличии политической воли и ресурсов.

Поэтому, если вы хотите вайб-кодить, но не хотите вайб-дебажить — приходите ко мне. Я научу вас лично или вашу компанию:

1. Писать быстрые, показательные и устойчивые к рефакторингу тесты;
2. Работать в цикле TDD;
3. Учить ИИ работать в цикле TDD.

На консультациях/тренингах в зависимости от вашего запроса или запроса вашей компании, я могу:

1. Помочь разобраться с теорией: TDD, проектирование тест-кейсов, архитектура кода тестов;
2. Показать на практике, как это всё работает в реальном проекте;
3. Помочь найти решение ваших конкретных проблем (подпишу NDA);
4. Помочь спланировать проект по внедрению тестов в вашу кодовую базу и спроектировать требуемую для них тестовую инфраструктуру.

Стоимость разовой часовой индивидуальной консультации — 4000 р.
Стоимость пакета из 4+ консультаций — 3000 р. за консультацию.

Стоимость для организаций — по договорённости.

Задать вопрос и обсудить план обучения можно в личке в Телеграме: @d_r_q. Или по старинке по почте: biz@azhidkov.pro.
👍9🔥3
Привет!

Наконец-то осилил пост про миграцию на Spring Boot 4.
Ну как осилил - процентов 10-20 от того, что реально можно было написать.

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

При том что Spring Boot вообще не моя тема и эта работа никак не продвинула меня к финализации Эргономичного подхода.

Поэтому я решил, что описать только проблемы с наиболее распространёнными технологиями - автоконфигами и Jackson-ом - будет вполне себе "good enough" ™️.

А остальное - никогда-нибдуь потом, микропостом, если будут вопросы по моему опыту.

#spring@ergonomic_code
И для того, чтобы в будущем не врюхиваться в такие приключения, я решил написать для себя манифест блога, вики и этого канала.

Манифест блога
У меня есть определённое представление о том, как надо писать код, чтобы он был поддерживаемым:

1. Код должен быть покрыт тестами (ATDD);
* Потому что это развязывает руки команде рефакторить код и поддерживать его в хорошем состоянии

2. Эти тесты должны быть преимущественно приёмочными/клиентскими/граничными (ATDD);
* Потому что такие тесты являются наиболее показательными и устойчивыми к рефакторингу и их надо наименьшее количество для того, чтобы убедиться в работоспособности системы. А современные инструменты и оборудование практически снимают их проблемы со скоростью (легко можно добиться времени выполнения 5 секунд на старт тестов плюс 20-50мс на тест) и стабильностью (сброс состояния инфраструктуры перед каждым тестом);

3. Тесты должны писаться преимущественно до кода (ATDD);
* Потому что это:
- гарантирует вообще наличие тестов и то, что тесты вообще что-то проверяют;
- задаёт ритм разработки небольшими шагами, которые легко делать, отлаживать и ревьювить.

4. Модель должна быть разбита на небольшие слабосвязанные агрегаты (DDD);
* Потому что это помогает поддерживать высокую связанность (cohesion) элементов модели;

5. Модель должна образовывать направленный ацикличный граф (DDD, FA);
* Потому что это задаёт "начало" (важные и фундаментальные части) и "конец" (вторичные, вспомогательные и периферийные части) модели и тем самым упрощает её понимание;

6. Модель должна состоять из неизменяемых классов (FP, FA);
* Потому что это:
- Способствует исключению циклов;
- Упрощает понимание кода, работающего с ними;

7. Модель должна явно кодировать свои допустимые состояния (FP, OOP);
* Потому что это повышает наглядность/упрощает понимание модели и предотвращает ошибки;

8. Сложные алгоритмы и бизнес-правила должны быть оформлены в виде чистых функций (FP);
* Потому что это упрощает их понимание, тестирование и отладку;

9. Операции должны стремиться к сбалансированной форме (ака Recawr Sandwich) (SD, FA)
* Потому что это упрощает их понимание и, как следствие, предотвращение, поиск и устранение ошибок и проблем производительности;

10. Операции должны должны иметь высокую (функциональной, последовательной или коммуникационной) связанность (cohesion) (SD);
* Потому что это упрощает их понимание, тестирование, изменение и переиспользование;

11. Компоненты должны иметь высокую связность (cohesion) (OOD);
* Потому что это упрощает их понимание, тестирование, изменение и переиспользование;

И есть мой базовый стек - Kotlin, Spring, Spring Data JDBC, PostgreSQL.

И в блоге я пишу о том, как на этом стеке писать поддерживаемый код:

1. Как писать быстрые клиентские тесты на Kotlin, Spring, WebTestClient, JUnit, Kotest, Testcontainers, PostgreSQL;
2. Как проектировать тест-кейсы;
3. Как начинать разработку с тестов;
4. Как проектировать агрегаты. Без доступа к экспертам;
5. Как кодировать агрегаты с помощью Spring Data Jdbc и мапить их на таблицы PostgreSQL;
6. Как писать код, работающий с неизменяемой моделью на Kotlin;
7. Как проектировать точные модели, исключающие недопустимые состояния на Kotlin;
8. Как разделять бизнес-логику и ввод-вывод на Kotlin;
9. Как группировать ввод и как группировать вывод на Kotlin, Spring и Spring Data Jdbc;
10. Как проектировать операции с высокой связанностью;
11. Как проектировать Spring beans с высокой связанностью;
12. Как все эти правила затолкать в ИИ-агента;
13. Разбор конкретных кейсов из моей практики по темам выше.

Манифест вики

Вики содержит статьи на темы №1-11 из блога.

Разница в том, что в блоге эти темы раскрываются как туториалы и кейсы, а на вики - как абстрактный справочный материал.

#ergo_approach@ergonomic_code
👍8❤5🔥3
Манифест канала

В канале я пишу:

1. Анонсы постов в блоге и статей на вики;
2. Микропосты по тем же темам, что и в блоге;
3. Микропосты по прочей связанной тематике - индустриальные новости, управление проектами и организация разработки, разработка фронта, книги, посты, выступления, ИИ, технологии и т. п.;
👍2
Привет!

Если вы как и я:

1. любите текстовые редакторы
2. с поддержкой вим-режима
3. и при этом красивые
4. и быстрые
5. и не глюкавые

- попробуйте посмотреть Zed.

Меня в последнее время VS Code задолбал тем, что периодически выжирал на 100% одно ядро. В этом, почти, наверняка виноваты Kotlin LSP или Codex, но это подтолкнуло меня снова глянуть на Zed. Который по счастливой случайности зарелизал версию 1.0 пару недель назад.

И я приятно удивился - на мой вкус и субъективный взгляд, он симпатичнее и быстрее ВС Кода.
Экосистема у него беднее - нет JB-шного Kotlin LSP и официального плагина Codex - но оно и к лучшему, судя по всему:)
Ещё нет превью для asciidoc и mermaid (отдельного, в markdown превью mmd-вставки рендярятся).

Но, тем не менее, я уже неделю в нём пишу тексты и ИИ фреймворк, пока доволен и поставил его дефолтным текстовым редактором в системе. Посмотрим как пойдёт.

#tools@ergonomic_code
👍3👀3❤2
Привет!

Навеяно интернетом.

Многие думают, что тесты нужны для того, чтобы проверить код, который программист написал только что.
Некоторые из них вспоминают, что Дейкстра писал:

Program testing can be a very effective way to show the presence of bugs, but it is hopelessly inadequate for showing their absence.

—

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


И говорят: «Тесты не нужны» (c).

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

Но, несмотря на это, у меня другое мнение по вопросу "нужны ли тесты?" (вот это каминг аут у меня тут вышел 🤦‍♂️).
Тесты нужны. Но не для того, чтобы продемонстрировать отсутствие ошибок в коде, который я только что написал. А для того, чтобы продемонстрировать отсутствие ошибок в коде, который я только что изменил. И во всех его зависимостях.

И с учётом этого, тесты начинают играть новыми красками.

Если вы только что сделали новую фичу и все тесты зелёные — то действительно, в ней всё ещё могут быть баги.

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

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

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

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

—

Теоретически адекватных тестов можно можно добиться и без TDD.

Но дисциплина работы по TDD даёт простым смертным:

1. Гарантию того, что вы действительно напишете тесты (а не спишите их написание в техдолг).
2. Гарантию того, что эти тесты будут проверять все требования о которых вы и постановщик задачи подумали (а не только те, о которых вы вспомнили и на которые хватило времени).
3. Гарантию того, что эти тесты действительно что-то проверяют, а не зелёные всегда (вы же не пишете тесты на тесты?).

В общем: Пишите тесты. Сначала. Не так много. В основном интеграционные.

#ergo_testing@ergonomic_code
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9💯3
Привет!

Вести с полей Spring Data Jdbc.

Я года 2 назад запилил небольшой DSL для SDJ, который позволяет писать запросы так:

jdbcAggregateOperations.findAll(
query(CountryCode::code isEqualIfNotNull countryCode.code),
Country::class.java
)


Но в котором есть гора дублей с типизацией и без:

infix fun String.isEqualIfNotNull(value: String?): Criteria {
return if (value != null) {
this.isEqual(value)
} else {
Criteria.empty()
}
}

infix fun <T, V> KProperty1<T, V>.isEqualIfNotNull(value: String?): Criteria {
return this.columnName().isEqualIfNotNull(value)
}


--

А недавно запилил фрагмент, который позволяет делать merge/upsert с кастомным SQL-ем:

interface DomainEventsRepo :
CrudRepository<DomainEvent, UUID>,
MergeExecutor<DomainEvent> {

fun mergeIgnoringNew(entity: DomainEvent): DomainEvent? {
return mergeIgnoringNew(
insertSql = """
INSERT INTO domain_event_inbox ( id, event_id, domain_event, created_at, updated_at, processed, version )
VALUES ( :id, :event_id, :diary_domain_event, :created_at, :updated_at, :processed, :version )
ON CONFLICT (id) DO NOTHING
RETURNING *
""",
entity = entity
)
}


И вот, в SDJ 4.1 завозят типизированные пути в Criteria API и merge из коробоки. Мелочь, а приятно.

В целом эти пара плюшек и RestTestClient (и ускорение тестов процентов на 10% за счёт перехода на него с WebTestClient) - вполне окупают заморочки на миграцию на Spring Boot 4, имхо.

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

Посмотрел кейнот КотлинКонф 26

Из любопытного (для меня):

1. Kotlin LSP перешёл в альфу
2. Гугл переписал "web serving stack" страницы поиска на Котлин (с корутинами). Любопытно, почему слезли (или не залезли на) с Go?
3. И в гугле сейчас на Котлине пишут больше бакендеры, чем андроидщики
4. Гуглодоки на Web/iOS переписали на Kotlin Multiplatform
5. Гопатыч лучше клода в андроид (Kotlin?) разработке
6. А вот чувак из антрофика говорит, что клод пишет на Kotlin лучше "неуказанного соперника"
7. ~10 лет спустя Exposed вышел в 1.0
8. Без пруфов - использование Котлин ускоряет разработку до 15-20%
9. У JB есть некий плагин для Lambok-а и он недавно вышел в Альфу
10. Только 5% ИИ продуктов дошли до прода
11. По какому-то бенчу MCP Java 30 раз быстрее Python-а, в 10 раз быстрее NodeJs и практически 1 в 1 как Go. Хз в чём, Лонг супер быстро и супер кратко говорит.
12. Compose на web-е пошёл в бету

#kotlin@ergonomic_code #talks@ergonomic_code
1❤3🔥2💯2
И я тут 5 лет спустя прикрутил анонимную аналитику к блогу и узнал, что у меня на блог есть ссылки в:
1. конфе ВК на диаграмму эффектов
2. явно каком-то корпарате с MS Teams-ом на пост про структурный дизайн
3. конфе НСПК на пост про декомпозицию на базе эффектов

Запишу себе это в ачивки:)

#ergo_approach@ergonomic_code
👍3⚡2❤2
Привет!

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

Мысль первая: а что если "ум" ИИ растёт не по экспоненте, а по логарифму?

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

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

Затем, в августе вышел GPT-5 и это был ещё один качественный скачёк, который меня изрядно шокировал и напугал - теперь гопатыч стал лучше меня раскапывать всякую дичь со спрингом.

Но вот с тех пор прошёл уже почти год, у гопатыча вышло пять поинт-релизов, а новых качественных скачков я так и не увидел. Гопатыча 5.5/xhigh всё ещё надо водить за ручку маленькими шажками с постоянным ревью. А если дать ему даже средней руки задачу для решения "под ключ" - он в целом выдаст решение, и оно, скорее всего функционально будет ок. Но если заглянуть внутрь - правый глаз вытечет, а левый задёргается.

Бизнес, попервости, это решение может и устроит. Но через год такой работы в реализации будет такая свалка, что вонь от неё в виде стоимости оборудования, количества багов и времени простоя дойдёт и до бизнеса.

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

Это, конечно, может быть наивная надежда на чудо, свойственная кожаным мешкам, но что уж тут поделаешь:)

#ai@ergonomic_code
❤4
Мысль вторая: компиляторщики всё ещё не вымерли

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

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

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

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

Если, конечно, ИИ растёт по логарифму или линейно.
Потому как если по экспоненте, то... я не берусь даже пытаться предсказывать, что будет.

#ai@ergonomic_code