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

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

https://azhidkov.pro
Download Telegram
Привет!

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

Но моя карьера его опровергает.
Первые 12 лет работы в найме, мне действительно приходилось довольно много работать с чужим кодом: я поработал над 8 "зрелыми" 4 "свежими" (до 2 лет жизни) проектами. И сделал с нуля 6 проектов.

А вот после перехода в независимые консультанты соотношение кардинально поменялось: 18 новых проектов (в некоторых я был только лидом и сам код практически не писал), против 4-ёх зрелых проектов (свежих не было).

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

Ну и, конечно же, по ходу дела будет много интересных приключений, о которых я буду писать:)
Первое приключение уже есть - я нашёл способ, как в тестах поднимать с нуля чистую БД на 300+ таблиц и с 8 годами liquibase xml-миграций, так чтобы в запуск тестрана из одного теста укладывался в 4 секунды
Думаю, на недельке расскажу подробности.

В общем стей тюнед, будет ещё интереснее:)

PS> а, да, если вы в основном работаете с легаси и вам это не нравится - задавшись целью, это можно изменить:)

PPS> в дальнейшем, оригинальный проект я буду называть "Project U", а новый сервис - "Project R"

#ergo_approach@ergonomic_code #project_u@ergonomic_code #project_r@ergonomic_code
👍65
Привет!

Недавно в комментах спрашивали про аргументы для бизнеса в пользу перехода на Котлин - они есть в этом докладе.

На мой взгляд их можно свести к паре слайдов

#talks@ergonomic_code #whykotlin@ergonomic_code
👍6👎1
Привет!

Я как всегда облажался с оценкой оверхеда на сетап проекта и сроки по Проекту Р начали подгорать.
Поэтому на этой недели не расскажу, как поднимаю БД на 300+ таблиц, собираемых из 8 лет миграций меньше чем за пару секунд.

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

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

spring:
datasource:
url: "jdbc:tc:postgresql:16.3:///bender?TC_REUSABLE=true&TC_TMPFS=/var:rw"


#tdd@ergonomic_code #integration_tests@ergonomic_code #project_r@ergonomic_code
👍3
Привет!

Сроки по Проекту Р уже полыхают синим пламенем но я, тем не менее, повыкраивал по чуть-чуть времени на микропост с описанием того, как я добился сетапа свежей БД на 300+ таблиц за 1.5 секунды.

#ergo_testing@ergonomic_code #tdd@ergonomic_code #integration_tests@ergonomic_code #project_r@ergonomic_code
👍5
Привет!

По совету подписчика начал читать Grokking Simplicity.

Пока прочитал 200 страниц из 600, но уже не могу удержать в себе восторг.

Это лучшая известная мне книга по функциональному стилю (или скорее data-oriented programming), с лучшим известным мне разбором двух основополагающих принципов проектирования:

1. разделение ввода-вывода и бизнес-логики
2. использование одного уровня абстракции в функции (анкл Бобовскя заметка на эту тему в чистом коде - даже близко не лежала с 1.5 главами об этом в книге).

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

#books@ergonomic_code #functional_architecture@ergonomic_code #fp@ergonomic_code #js@ergonomic_code
👍12
Эргономичный код
Привет! По совету подписчика начал читать Grokking Simplicity. Пока прочитал 200 страниц из 600, но уже не могу удержать в себе восторг. Это лучшая известная мне книга по функциональному стилю (или скорее data-oriented programming), с лучшим известным мне…
Привет!

Дочитал книгу. По традиции, тема разработки бэков поверх РСУБД практически не раскрыта (этому посвящено примерно 10 страниц про луковую архитектуру), но в остальном - чудесная книга, мой новый лидер среди книг по ФП.

И сейчас мой рекомендуемый трек по изучению разработки бэков в функциональном стиле выглядит так:
1. Grokking Simplicity
2. Принципы юнит тестирования
3. Domain Modeling Made Functional
4. Структура и интерпретация компьютерных программ
5. Functional Design: Principles, Patterns, and Practices
6. Structured Design

#books@ergonomic_code #functional_architecture@ergonomic_code #fp@ergonomic_code #js@ergonomic_code
👍10
Привет!

Прочитал Java to Kotlin: A Refactoring Guidebook - мне понравилась.
Её с тем же успехом можно было назвать "Рефакторинг императивного стиля в функциональный" и она хорошо дополняет Grokking Simplicity - на мой вкус менее фундаментальная, но более бакэндерская и со статической типизацией. Хотя, опять же, тема персистанса практически не раскрыта.

И в качестве инструкции по переходу на Котлин она тоже хороша.
Рекомендую, в общем.

Ещё пару находок оттуда:
1. Идея "волокон" (grains) языков программирования. "Вдоль" которых работать проще, чем поперёк - как с деревом. И ФП укладывается вдоль волокон Котлина, но идёт поперёк волокон Джавы. С одной стороны. С другой стороны, монады - не укладываются в волокна Котлина.

2. У Фаулера есть статья про баги вызванные алиасингом

3. Один из соавторов этой книги - также соавтор и Growing Object-Oriented Software Guided by Tests - книги, которую я долгое время считал идеологически вредной. В Java to Kotlin же он пишет, что в GOOS моки не предполагалось использовать в качестве стабов - поставщиков данных через ридонли методы. Возможно, мне стоит перечитать GOOS и поменять своё мнение о ней.

#books@ergonomic_code #functional_architecture@ergonomic_code #kotlin@ergonomic_code #java@ergonomic_code
👍6
Привет!

Вышли результаты ежегодного опроса девелоперов от SO.

И там я нашёл новый аргумент за ФП - из топ-10 языков по ЗП 6 являются функциональными:)

А из оставшихся 4ёх только Руби не является ещё большей эзотерикой, чем ФП языки из топа:)

И ещё любопытное наблюдение - судя по всему, чем популярнее язык, тем меньше за него платят.
Вам ещё нужны аргументы в пользу функционального стиля?
Anonymous Poll
38%
Да, я чёт сомневаюсь
30%
Да, я сам не сомневаюсь, но команду ещё не убедил
33%
Горошчек не вари
Привет!

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

В ОО-модели сущность (якобы) инкапуслирована в объектах, а репозы/дао/объекты таблиц - это просто индексные указатели, которые используются для поиска объектов. И чтобы поменять объект, вам надо его найти, позвать пару сеттеров и (теоретически) готово.

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

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

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

Надеюсь, в течении пары месяцев напишу развёрнутый пост на эту тему. После поста "Почему ФП" - там у меня тоже появилась идея:)

#immutable_domain_model@ergonomic_code
👍6🤔1
Привет!

Наткнулся на любопытную штуку для фронта - Feature-Sliced Design, "Architectural methodology for frontend projects".

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

#guideline@ergonomic_code
Привет!

Вечная битва добра и зла продолжается. Ведущий разработчик Spring Data Relational пинает JPA за сложность предсказания его поведения

Подача/запись доклада паршивые, но сам доклад хорош тем, что:
1. Подсвечивает пачку граблей JPA, для тех кто его юзает
2. Чуть подробнее раскрывает мою мысль из предпредыдущего поста, почему сложно реализовать хранение императивной ОО-модели

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

Я тут такую штуку в Котлине откапал.
Для локальных и возвращаемых из приватных функций анонимных объектов можно обращаться к поля

    fun test() {
val tests = (1..2).map {
createTest(mapOf("id" to 10))
}

println(tests[0].id == 10L)
}

private fun createTest(map: Map<String, Any>) = object {
val id: Long = map["id"] as Long
}


Что тут просиходит:
1. У меня есть функция createTest, которая возвращает анонимный объект с полем id
2. Я генерирую список таких объектов и сохраняю его в tests
3. Я беру первый элемент из списка и беру у него поле id. И всё работает. Но если попытаться проставить тип для функции или коллекции - там можно вставить только Any (aka Object) и всё ломается.

У меня есть сомнения в целесообразоности использования такого трюка, но код ручного маппинга 1-N в дерево неизменяемых объектов он мне сделал чуть понагляднее

#kotlin@ergonomic_code
👍3
Привет!

У меня две новости. Обе хорошие и обе объясняют затишье в канале:)

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

Новость вторая - мой доклад "Spring Data JDBC. Четыре года в проде, полет отличный" взяли в программу Joker 2024.
Поэтому сейчас всё ЭП-время уходит на подготовку доклада и до октября в канале я буду постить только ссылки на видосы, которые смотрю, пока гуляю с ребёнком:)

Если собираетесь на Joker и ещё не купили билеты - не торопитесь, в прошлый раз мне чуть меньше чем за месяц до конфы дали промокод на скидку 20%

#talks@ergonomic_code
🔥172👍2
Ну и собственно очередной досмотренный видос - Test automation without a headache: Five key patterns.

Мне понравился, рекомендую.

Паттерны:
1. разделяйте ожидания, workflows и взаимодействия - эту штуку я с наскоку не понял, но кажется в ней что-то есть, буду разбираться.

2. Симулируйте только те штуки, которые вы полностью понимаете. Это классика из Growing Object-Oriented Software, что мокать можно только собственные классы.

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

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

5. Реорганизуйте тесты для discovery. Посыл вроде как "организуйте тесты не воркуг юзер стори/итераций, а вокруг функциональности". Но лично я ни разу не видел первый вариант.

Есть ещё версия на ютубе с субтитрами и короче на 25 минут

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

Прочитал Good to Great: Why Some Companies Make the Leap...And Others Don't

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

А потом попытались понять, чем 11 "good-to-great", контор похожи между собой и отличаются от остальных.

И вроде как поняли и описали что надо делать, чтобы забацать "great company".

И среди прочего, как это не удивительно, надо собрать правильных людей.
А правильные люди - это не те, которые прямо сейчас обладают нужными вам скиллами, а те, которые обладают характером, нужным для вашей организации.
Second, widen your definition of “right people” to focus more on the character attributes of the person and less on specialized knowledge. People can learn skills and acquire knowledge, but they cannot learn the essential character traits that make them right for your organization


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

#books@ergonomic_code #hr@ergonomic_code
🔥2
Привет!

Пошёл полистать Lean Architecture в поисках инфы как писать юзкейсы и вообще форматов описания требований.

И потихоньку переполз на DCI.

И в это прочтение у меня три новых мысли возникло.

Мысль первая

Тезис, что ООП - это то как мир представляют нормальные люди - фикция.

ООП, по определению объекта (состояние + поведение), предполагает активность объектов.

Например счёт может (сам) сделать перевод. Или напечатать себя.

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

Наверное поэтому, "полнокровная" доменная модель не вытеснила анемичную доменную модель в мейнстриме. Тупые сущности и умные сервисы - это то, как наши пользователи думают о наших информационных системах.

Мысль вторая

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

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

Это типовой пример Expression problem (aka Data/Object Anti-Symmetry из 6ой главы чистого кода).

И, наверное, ООП и правда стрельнуло только на волне GUI - там как раз чаще появлялись новые типы, чем новые методы.

Но на бэке информационной системы, намного чаще появляются новые операции, чем типы.

Поэтому "полнокровная" доменная модель ведёт не только к тому, что изменения приходится вносить в множество мест, но ещё и к огромным с десятками методов для совершенно разных контекстов объектов с низким cohesion и высоким coupling.

Мысль третья

DCI - это ещё одна попытка решить expression problem.
И если у вас её нет (а у меня нет - очень редко появляются иерархии типов сущностей) - то и DCI не надо.

#whynotoop@ergonomic_code #dci@ergonomic_code #lean_architecture@ergonomic_code
👍4
И в догонку накопал жёский наборос
It is high time to ‘kill’ Clean Architecture, the Hex, the Onion and the VSA and come up with something better

One of the most common ‘architectures’ among aspiring software designers is either the Clean Spaghetti Architecture or the Hexagonal Bubble Architecture. I don’t blame them for using these antipatterns. At least they are trying something new. They are going out of their comfort zone, ready to make mistakes. Here is a visual representation of both these architectures

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

Но вот чтобы так жёска и прям с порога - это надо иметь смелость:)

PS> сам пост ещё не прочитал

#clean_architecture@ergonomic_code