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

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

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

Ещё немного вас поспамалю на волне JPoint-а:)

Я там познакомился лично с Максом Моревым - моим братом-близнецом по подходу к разработке:)

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

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

Так же у Макса есть канал codemonsters.log - пока он не очень активный, но думаю новые подписчики замотивируют Макса писать больше:) А ему, совершенно точно, есть что написать:) В общем подписывайтесь:)
1👍1
Привет!

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

Список того, над чем ещё предстоит поработать выглядит так:
* Ретро Проекта Э
* Эргономичная структура програм
* Функциональная архитектура
* Классический подход к ТДД
- Фокус на тестировании требований
* Обработка ошибок
* ПЕРСИСТАНС!
- Посмотреть на Exposed + отказ от агрегатов и слоя сущностей
- iArm
* В целом описать процесс разработки от "Хочу зюзюку" до "Вот ваша зюзюка в проде"
* Чеклисты/критерии качества процесса и кодовой базы
* Матрица компетенций разработчика по Эргономичному подходу

Чуть подробнее расписал эти пункты в микропосте

Моими темпами, тут без персистанса мне работы ещё лет на 5 минимум, а с персистансом - на все 10. Так что стей тюнед, будет интересно:)

#ergo_approach@ergonomic_code
👍6🔥2❤‍🔥1
Привет!

Не спрашивайте как, но я тут наткнулся на очередную любопытную статью - Analyzing Error-Prone System Structure.

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

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

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

#papers@ergonomic_code #coupling@ergonomic_code #effects_diagram@ergonomic_code
🔥5👍1
Привет!

Провёл небольшой опрос среди 23 студентов 3его курса ФИТ НГУ - думаю, вам результаты тоже могут быть интересны и полезны:)

ТЛДР - 80% разработчиков без опыта желающих найти работу её находят уже на 3-ем курсе.

Вопрос: вы трудоустроены?

Результаты:
- Да, разработчиком, с зп >= 300 р/час* - ~8% (2 человека)
- Да, разработчиком, с зп < 300 р/час - 26% (6)
- Да, неразработчиком - 13% (3)
- Пытался (рассылал резюме), но пока не взяли - 8% (2)
- Нет, пока не искал работу - 47% (11)

* зп считать как <сумма зп за 6 мес.> / <кол-во часов работы за 6 мес. по вашей оценке>

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

Посмотрел очередной доклад Кевлина Хенни - Non-Functional Coding - Kevlin Henney.
Вообще он даже относительно своих предыдущих докладов ничего нового не сказал, но если вы раньше не видели его докладов и интересуетесь темой ФП (да и Тру(TM) ООП) - рекомендую. У него и подача прикольная, и много любопытных исторических фактов и задуматься заставляет о многом.

А следом - очень крутой доклад о профессии разработчика от анкл Боба
Рекомендую вдумчиво посмотреть. И там тоже есть прикольная историческая часть, с упоминанием Тюринга:)

А в части, когда он говорит о том как мы (программисты) убиваем людей - вспомните про все эти хайповые истории, как люди делают приложения на чатгпт:)

#talks@ergonomic_code
👍7
Привет!

Ретро проекта Э идёт прям тяжело (тупо прокрастинирую его), поэтому решил написать микроретро очередного релиза.

В этом релизе, мы среди прочего сделали две большие штуки:

. Реализовали поддержку множества сессий пользователей - 73 файла, ~1200 строк изменений (ввели понятие сессии и привязали рефреш-токен к ней, а не пользователям. Плюс сделали бесшовную миграцию токенов);
. Серьёзно отрефакторили модуль наблюдения, поправив логические и технические ошибки в изначальной модели - 129 файлов, ~2300 строк изменений.

Ещё хочу напомнить, что месяц назад у нас в проекте всего было 23,944 строк кода и 730 классов.
То есть в этом релизе релизе мы потрогали процентов 15 всей кодов базы.

При этом:

. Багов, найденных командой QA за 3 дня тестирования релиз-кандидата - 0 (ноль);
. Багов, найденных заказчиком и пользователями за 5 дней использования релиза - 0 (ноль);
. Багов, найденных разработчиком по коду после мёржа в мастер - 1 (один);

Лично я считаю это выдающимся достижением.

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

#why_ergo_approach@ergonomic_code #ergo_testing@ergonomic_code #project_e@ergonomic_code #case@ergonomic_code
👍2🔥2👌2
Привет!

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

С декомпозицией на базе эффектов в одном из модулей начала стрелять одна из проблем Труъ ООП. Он начал обрастать слишком большим количеством операций, предназначенных для разных ролей и юз кейсов.

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

Эту проблему можно попробовать решить вернувшись к версии Эргономичной структуры программ 1.5-летней давности с разбиением слоя домена (состояния) и приложения (операций). Однако этот пост заканчивается словами "Что значит "проектируйте слой ядра приложения"? Вот у вас есть требования, вам надо спроектировать ядро - как это сделать? Ответ в следующем посте.".

В итоге ответ появился через 1.5 года в виде объединения этих слоёв и тут же зашатался.
Я отказался от изначальной идеи разделения по двум причинам:
1. при таком подходе отсутствует сокрытие информации. Как следствие появляются все проблемы процедурного программирования - потенциальная возможность порчи состояния, и распространение изменений в структурах данных домена на слой приложения
2. я не смог найти вменяемого способа декомпозировать слой приложения.

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

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

В общем план как решить проблему отсутствия сокрытия информации у меня есть.

А вот как декомозировать слой приложения - я пока не знаю. Пойду курить мат часть со всех возможных сторон - перечитаю Structured Design, Object-Oriented Software Engineering, Applaying UML and Patterns, Domain Modelling Made Functional, дочитаю Functional Design and Architecture и Functional and Reactive Domain Modeling. Надеюсь что-нибудь придумаю.


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

А как ваша ночь прошла? 😂

#ergo_approach@ergonomic_code
👍32
Привет!

Пара ссылок, где анкл Боб рассказывает про ООП на чисто функциональном языке (Clojure).

https://blog.cleancoder.com/uncle-bob/2023/01/18/functional-classes.html
https://blog.cleancoder.com/uncle-bob/2023/01/19/functional-classes-clojure.html

Советую почитать, даже если вы не интересуетесь ФП. Но интересоваться хотя бы ООП - надо:)

А после прочтения этих статей я наткнулся на ещё более огненный пост - https://habr.com/ru/companies/domclick/articles/732876/
Который так же упоминает посты анкл Боба.

Совпадение? Не думаю 🤯🤔

#posts@ergonomic_code #clojure@ergonomic_code #oop@ergonomic_code
🔥5
Спамить так спамить.

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

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

Как в будущем избежать таких факапов я знаю, но решил что он является хорошим поводом синхронизироваться с реальностью:)

Соответственно опрос: какой режим публикаций вам был бы более комфортен?
1. Более-менее регулярно по вторникам и пятницам
2. По мере поступления. От нескольких постов в день, до нескольких недель тишины.

Сейчас запилю собственно опрос
👍2
Какой режим публикаций вам более комфортен
Anonymous Poll
28%
Регулярный (вторник, пятница)
72%
Хаотичный
Привет!

Шутник в маинтейнерах Spring Data JDBC детектед:)
😁14
Привет!

Вчера в Проекте Э пришлось подравить пару МРов своими собственными руками (редкое событие в последнее время, к сожалению), чтобы успеть заталкать в релиз.

И в обоих случаях ТДД спасло меня от внесения багов.

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

Во втором случае, я в оригинальном МРе убрал часть логики (обновление времени действия пользователя в одном из кейсов). А потом выяснилось что всё-таки обновлять время надо. На этот кейс теста не было, поэтому я опять же начал с него. Вернул оригинальный код и. Тест не прошёл. Там был баг. Который я благополучно починил.

В общем прям советую взять в практику разработку через тесты. А чтобы это не было мучитльно больно - писать тесты без моков и на максимально высоком уровне абстракции (с позиции пользователя)

#project_e@ergonomic_code #tdd@ergonomic_code #ergo_testing@ergonomic_code
👍4🤔1
Привет!

Потока сознания пост

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

Изначальный код был примерно такой:
scanner.startScan(filters, settings)
.filter { foundDevices->
foundDevices.map { address }
.contains(address)
}
.take(1)

Видите баг? Фильтр мапит список на переменную, а потом проверяет что он содержит эту переменную. Очевидно он срабатывал для любого не пустого списка. Добавили в маппинг it.device.address и всё заработало. Я до сих пор не понимаю как - если есть эксперты по андроиду/бле - напишите, пожалуйста:)

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

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

Соответственно мысль №1 - хорошие тесты должны проверять предположения разработчика относительно кода. Например, сохранение сущности значит, что её потом можно достать по иду - вот это и надо проверять. А не то что ид обновился, или что был вызван метод репоза.

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

Я не думаю что возможно (и экономически целесообразно) жить и кодить вообще без предположений и вообще все предположения проверять. Но рефлексировать на эту тему - точно хорошее упражнение.

#case@ergonomic_code #project_e@ergonomic_code #ergo_testing@ergonomic_code
👍3
Эргономичный код
Привет! Кажется у меня по мотивам Проекта Э на горизонте замаячил очередной кризис Эргономичного подхода. При том зашатались одновременно два столпа - декомпозиция на базе эффектов и функциональная архитектура. С декомпозицией на базе эффектов в одном из…
Привет!

Начал таки читать OOSE - исчерпывающего ответа пока не нашёл, но пару примечательных штук заметил.

Штука №1
На 136 странице наткнулся на такой параграф:
> Thus the actual problem here was that too much specific functionality had been incorporated in the blocks (entity object in OOSE). Instead we should model this specific functionality in the control object so that, firstly the (operations of the) entity object will be more reusable in several different use cases, and secondly the specific functionality should be local and not distributed so that it is easier to introduce changes in this functionality

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

Штука №2
В книге нашёл картинку (см скрин), которая для меня полностью аналогична той картинке, с которой я начал работу над ЭП в далёком феврале 20-ого года. И на тот момент книгу я ещё не прочитал:)

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

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

Было бы мне актуально - сам бы пошёл к Максу:)
Forwarded from codemonsters.log (Maxim Morev)
Ищу в команду Цифровой Рубль ТехЛида
Пишите в личку @maxology

отправляйте репост своим друзьям.
50% процессы, люди
50% код, дизайн системы
Гибрид | Удаленка | Офис
💩4👍1👎1🤡1
Привет!

В Проекте Э, мы интегрируемся с внешней системой, отправляя туда часть записей дневника пользователя по протоколу MQTT.
И коллеги попросили делать это ровно один раз.
Что невозможно в нашей вселенной.

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

Вариант, что кто-то придёт в комменты и натыкает меня носом в то, как это сделать за 5 минут - мне тоже подходит :)

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

Прошёл Spring IO 23
И там дикая пачка любопытных по названию докладов:
- Spring is bootiful but so is your domain
- Tactical Domain-Driven Design with Spring Boot [Workshop]
- Anatomy of a Spring Boot App with Clean Architecture
- Things I Wish I Knew When I Started Testing Spring Boot Applications
- Rapid server-side full stack web development with ViewComponents and htmx
- The Aggregate is dead. Long live the Aggregate!
- Preparing web applications for Loom
- Server-side rendering (SSR) with Spring [BoF]
- Integration Testing for everyone with Testcontainers [Workshop]
- Architecturally evident Spring applications with jMolecules
- Spring Boot 3 is here: Where are you? [Workshop]
- Avoid the Distributed Monolith - Moving Towards Mature Scalable Microservice Applications with Spring
- Bootiful Spring Boot 3
- Do you really need Hibernate?
- REST next level : Crafting domain-driven web APIs
- Automating away bugs with Error Prone in practice
- Why you don't need to worry about scaling your Spring webapp

Доступны пока только 16 штук, но если не упарываться - как раз что-то ещё появится, пока то что есть посмотришь
👍5
Привет!

Листаю Designing object-oriented software и наткнулся на такой же тест как и у меня тест на разумность декомпозиции:)

За одно ещё раз попиарю - https://archive.org. Там после бесплатной регистрации можно легально откопать редкие и интересные книги:)

Единственное не удобство - читать только на сайте и раз в час надо заново "занимать" книгу.

#books@ergonomic_code #oop@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