Привет!
Ну всё, сходил к @javaswag - минут 5 возились с микрофоном, чтобы был анонсированный боХатый голос 🤣
Походу подкаста, кажись осознал свою фишку - у меня есть ссылка на все случае жизни - я, наверное, их штук 20 наобещать успел:)
PS>
Картинка в тему - из свежего рабочего чата
Ну всё, сходил к @javaswag - минут 5 возились с микрофоном, чтобы был анонсированный боХатый голос 🤣
Походу подкаста, кажись осознал свою фишку - у меня есть ссылка на все случае жизни - я, наверное, их штук 20 наобещать успел:)
PS>
Картинка в тему - из свежего рабочего чата
🔥6👍2
Продолжая топик ссылок на любой случай жизни, может кому-то пригодится как я читаю книги:
Юниор
Как-то техническую литературу еще плотно не приходилось читать.
Ты как ее читал? По выходным в охотку? Когда возникали конкретные запросы и нужно было найти что-то в книгах? Делал ли заметки и как долго переваривал прочитанное? Или это должно просто где-то отложиться и выстрелить в нужный момент?
Я
Ох. мне кажется это всё строго индивидуально. Конкретно я:
1. По выходным в охотку? - В разные периоды и разные книги по разному. В среднем можно считать, что ежедневно полчаса-час перед сном, либо с утра до работы
2. Когда возникали конкретные... - обычно, выбирая книгу, я беру то, что сейчас охота прочитать. Но обычно охота - то что сейчас актуально. Потом, когда возникает конкретный вопрос у меня сами вспоминаются книги, где был ответ и их иду перечитываю. Несколько раз ещё была отдельная штука тематических статей, типа агрегатов - вот тут уже читал конкретные главы конкретных книг в "рабочее на себя время"
3. Делал ли заметки - не считая тематических постов, я никогда не делаю заметки. Иногда делаю закладки (в электронной книге). Ещё реже пишу минипосты с рецензией по ним.
4. как долго переваривал прочитанное - смотря что ты имеешь ввиду. Систематических перерывов в чтении между книгами у меня не бывает - закончил одну, начал вторую. К прочитанным книгам периодически возвращаюсь, когда возникают вопросы.
5. Или это должно просто где-то отложиться и выстрелить в нужный момент? - ну с одной стороны, наверное да. Но конкретно у меня чтение подкрепляется перманентной практикой применения идей из книг в пет проектах
Алексей Жидков
Агрегаты - Алексей Жидков
В основе поддерживаемых информационных систем лежат агрегаты. В этом посте я расскажу что такое агрегат, как его проектировать и какие ошибки проектирования агрегатов встречаются чаще всего
👍2
Привет!
JB прислали напоминалку, что заканчивается лицензия, решил приобщиться к импортозамещению и попробовать посидеть на gigaide, gigacode и amplicode.
Пока выглядит так, что мне не хватает только HTTP Client-а.
Через недельку напишу как впечатления
#tools@ergonomic_code
JB прислали напоминалку, что заканчивается лицензия, решил приобщиться к импортозамещению и попробовать посидеть на gigaide, gigacode и amplicode.
Пока выглядит так, что мне не хватает только HTTP Client-а.
Через недельку напишу как впечатления
#tools@ergonomic_code
gitverse.ru
GitVerse — Платформа для работы с исходным кодом, Git-репозиторий
✅ GitVerse — платформа для разработчиков. ✅ Создавайте и развивайте проекты с открытым и закрытым исходным кодом. ✅ Загрузка репозиториев, импорт и зеркалирование из других git-сервисов.
👍8
GitHub
GitHub - ergonomic-code/Trainer-Advisor: Информационная система йогатерапевта и демонстрационный проект Эргономичного подхода
Информационная система йогатерапевта и демонстрационный проект Эргономичного подхода - ergonomic-code/Trainer-Advisor
Привет!
На выходных спинным мозгом чутка подвигал Trainer Advisor
Переезд на Kotlin 2.0.20
Начал с того, что с третьей попытки наконец осилил переехать с Kotlin 1.9.20 на 2.0.20.
Летом при переезде на 2.0.0 (и, возможно, 2.0.10 - не помню уже точно) было какое-то совершенно невнятное сообщение об ошибке компиляции, которое ставило меня в тупик.
В этот раз было даже не сообщение об ошибке компиляции, а вообще какая-то кровавая жесть из кишёк компилятора, но победить её удалось. Случайно.
Я начал пытаться локализовать строчку, на которой компилятор взрывается (он писал файл). И долокализовался до того, что файл вообще удалил, а компилятор продолжил взрываться 🤯
Потом каким-то чудом я обнаружил, что у меня есть одноимённый файл в Gradle Test Fixtures source set. И вот когда я туда залез - там у меня ужеIDEA GigaIDE начала взрываться, что не найдены Spring-овые классы. Пошёл гуглить WTF и по первой же ссылке выяснил, что во 2-ой версии, impl-зависимости продового кода не перекидываются в testFixture - прокинул, завелось.
Мораль - чёрт его знает. Проект на 13К нетривиального кода (люблю я знаете ли проверять компиляторы на прочность) перевести мне удалось. Но чудом. Если ждали знака, чтобы попробовать перевести свой проект - вот он. Но будьте готовы к приключениям.
Переезд на HTMX 2.0.3
Следующим шагом переехал на новую мажорную версию HTMX. Просто обновил и всё заработало. Вряд ли это кому-то ещё интересно, но если вдруг - на HTMX 2 можно достаточно смело ехать.
Greenmail для локальной работы в докере
Но кое-какой нюанс с переездом всё таки был - если покрытие серверного кода, включая рендеринг HTML у меня близок к 100%, то динамика UI (у меня там ещё и alpine.js немного есть) у меня очень слабо покрыта e2e тестами - есть только тесты на критичные сценарии - регистрация и логин и создание карточки клиента и приёма.
Поэтому я на всякий случай после переезда на HTMX 2 решил руками прогнать полный регресс.
И упёрся в небольшую шероховатость DevX-а проекта.
Наполовину по историческим причинам и наполовину во имя простоты бэка, сейчас при регистрации пароль отправляется письмом на почту юзера.
Примерно по тем же причинам, в проде для отправки почты у меня используется бесплатный ящик на Яндексе. И креды от него, по понятным причинам, куда-то заныканы.
Соответственно, при локальной разработке, после чекаута проекта зарегаться нельзя - надо сначала как-то настроить отправку писем.
Об это я и споткнулся, когда начал делать регресс в новом проекте - обычно я 99% работы делаю через тесты и ещё для 0.99% работы мне достаточно юзера, который добавляется в демо-данных при локальной разработке.
А вот регистрация из коробки не работала.
Вот это я и залечил, добавив Greenmail в проект компоуза локальной инфры.
И написав shell-однострочник для выковыривания пароля оттуда:
PS>
Напоминаю, что мне в ТА можно поконтрибьютить.
Если вы опытный разработчик и вам не комфортно работать в том стиле, в котором пишете сейчас - это хороший способ пощупать ЭП руками и понять нравится ли вам такой DevX.
Если вы молодой разработчик - это хороший способ получить мой менторинг на реальном проекте в замен за работу. Я очень тщательно провожу ревью и в целом стараюсь давать максимум полезной обратной связи.
Код двух подписчиков уже есть в TA - так что это вполне реально:)
Отзыв одного из них:
Если интересно - пишите в личку, договоримся о звонке для онбоардинга
#trainer_advisor@ergonomic_code #tools@ergonomic_code #kotlin@ergonomic_code #devx@ergonomic_code
На выходных спинным мозгом чутка подвигал Trainer Advisor
Переезд на Kotlin 2.0.20
Начал с того, что с третьей попытки наконец осилил переехать с Kotlin 1.9.20 на 2.0.20.
Летом при переезде на 2.0.0 (и, возможно, 2.0.10 - не помню уже точно) было какое-то совершенно невнятное сообщение об ошибке компиляции, которое ставило меня в тупик.
В этот раз было даже не сообщение об ошибке компиляции, а вообще какая-то кровавая жесть из кишёк компилятора, но победить её удалось. Случайно.
Я начал пытаться локализовать строчку, на которой компилятор взрывается (он писал файл). И долокализовался до того, что файл вообще удалил, а компилятор продолжил взрываться 🤯
Потом каким-то чудом я обнаружил, что у меня есть одноимённый файл в Gradle Test Fixtures source set. И вот когда я туда залез - там у меня уже
Мораль - чёрт его знает. Проект на 13К нетривиального кода (люблю я знаете ли проверять компиляторы на прочность) перевести мне удалось. Но чудом. Если ждали знака, чтобы попробовать перевести свой проект - вот он. Но будьте готовы к приключениям.
Переезд на HTMX 2.0.3
Следующим шагом переехал на новую мажорную версию HTMX. Просто обновил и всё заработало. Вряд ли это кому-то ещё интересно, но если вдруг - на HTMX 2 можно достаточно смело ехать.
Greenmail для локальной работы в докере
Но кое-какой нюанс с переездом всё таки был - если покрытие серверного кода, включая рендеринг HTML у меня близок к 100%, то динамика UI (у меня там ещё и alpine.js немного есть) у меня очень слабо покрыта e2e тестами - есть только тесты на критичные сценарии - регистрация и логин и создание карточки клиента и приёма.
Поэтому я на всякий случай после переезда на HTMX 2 решил руками прогнать полный регресс.
И упёрся в небольшую шероховатость DevX-а проекта.
Наполовину по историческим причинам и наполовину во имя простоты бэка, сейчас при регистрации пароль отправляется письмом на почту юзера.
Примерно по тем же причинам, в проде для отправки почты у меня используется бесплатный ящик на Яндексе. И креды от него, по понятным причинам, куда-то заныканы.
Соответственно, при локальной разработке, после чекаута проекта зарегаться нельзя - надо сначала как-то настроить отправку писем.
Об это я и споткнулся, когда начал делать регресс в новом проекте - обычно я 99% работы делаю через тесты и ещё для 0.99% работы мне достаточно юзера, который добавляется в демо-данных при локальной разработке.
А вот регистрация из коробки не работала.
Вот это я и залечил, добавив Greenmail в проект компоуза локальной инфры.
И написав shell-однострочник для выковыривания пароля оттуда:
curl -X GET "http://localhost:58080/api/user/test%40ya.ru/messages/" \
-H 'accept: application/json' | jq -r '.[] | .mimeMessage ' | grep -A7 0JfQ | python3 -m base64 -d | grep 'Пароль'
PS>
Напоминаю, что мне в ТА можно поконтрибьютить.
Если вы опытный разработчик и вам не комфортно работать в том стиле, в котором пишете сейчас - это хороший способ пощупать ЭП руками и понять нравится ли вам такой DevX.
Если вы молодой разработчик - это хороший способ получить мой менторинг на реальном проекте в замен за работу. Я очень тщательно провожу ревью и в целом стараюсь давать максимум полезной обратной связи.
Код двух подписчиков уже есть в TA - так что это вполне реально:)
Отзыв одного из них:
В целом, мне понравилось делать изменения у тебя. Не могу сказать, что согласен со всем. Мне пока кажется почти идеальным вот этот layout https://github.com/gushakov/cargo-clean
Если интересно - пишите в личку, договоримся о звонке для онбоардинга
#trainer_advisor@ergonomic_code #tools@ergonomic_code #kotlin@ergonomic_code #devx@ergonomic_code
🔥6👍2🥰2
Привет!
Ползеняшка
В Идее есть такая штука, как структурный поиск. С её помощью можно найти, например, все классы в которых есть поля id и name, в независимости от их типа и форматирования в коде (в каком порядке, с какими аннотациями, комментами и т.д.)
Ещё пример использования этой штуки - удаление модификтора suspend у всех методов всех классов репозиториев
Я вообще искал класс, в котором есть только эти поля, но сходу не осилил как это сделать - если кто-то знает как - научите в комментах, пожалуйста.
#tools@ergonomic_code
Ползеняшка
В Идее есть такая штука, как структурный поиск. С её помощью можно найти, например, все классы в которых есть поля id и name, в независимости от их типа и форматирования в коде (в каком порядке, с какими аннотациями, комментами и т.д.)
Ещё пример использования этой штуки - удаление модификтора suspend у всех методов всех классов репозиториев
Я вообще искал класс, в котором есть только эти поля, но сходу не осилил как это сделать - если кто-то знает как - научите в комментах, пожалуйста.
#tools@ergonomic_code
2❤5
Привет!
Немного размышлений о чистоте модели предметной области по мотивам рассылки On domain model purity от Хорикова.
Он там пишет:
То есть Хориков полагает, что наличие БД влияет на дизайн системы.
И когда-то я думал так же. В частности, qbit был попыткой сделать такую систему хранения, которая позволила бы писать программы так, как будто все данные живут в памяти.
А сейчас я думаю, что с точки зрения дизайна у меня ничего не поменяется.
Я всё равно буду моделировать состояние системы как набор изменяемых Map неизменяемых структур данных (ака Spring Data JDBC Repository).
Возможно, у меня будет меньше специализированных под юз кейсы ДТОшек.
Совершенно точно я начну спокойно ходить по ссылкам между сущностями внутри бизнес-логики (а-ля Datomic Pull API)..
Но совершенно точно не перейду на модель огромного графа изменяемых объектов (которую, судя по всему Хориков считает идеально чистой).
При том у Хорикова в самом примере есть противоречие:
С одной стороны, он пишет:
Но с другой стороны, в примере он использует репоз для того, чтобы обеспечить уникльность емейла студента. И вот куда он засунет поиск студента по емейлу? В
Кажется, единственное разумное место, куда можно эту проверку засунуть - StudentsRepository. Где бы он не хранил свои данные - в памяти или БД.
В общем, функциональная модель не только лучше отражает модель в голове конечного пользователя, но и лучше отражает природу информационных систем.
#functional_architecture@ergonomic_code #ddd@ergonomic_code
Немного размышлений о чистоте модели предметной области по мотивам рассылки On domain model purity от Хорикова.
Он там пишет:
To see how pure your domain model is, you need to imagine how you would design it if you didn’t have to persist any data to the database, and all you had to do is keep that data in the application memory. Then you need to compare this design to what you ended up with in your project. The difference would be the dent in domain model purity
Чтобы увидеть, насколько чиста ваша модель предметной области, вам нужно представить, как бы вы ее спроектировали, если бы вам не нужно было сохранять какие-либо данные в базе данных, а все, что вам нужно было сделать, это сохранить эти данные в памяти приложения. Затем вам нужно сравнить этот дизайн с тем, что в итоге получилось в вашем проекте. Разница между ними и будет дырой в чистоте вашей модели.
То есть Хориков полагает, что наличие БД влияет на дизайн системы.
И когда-то я думал так же. В частности, qbit был попыткой сделать такую систему хранения, которая позволила бы писать программы так, как будто все данные живут в памяти.
А сейчас я думаю, что с точки зрения дизайна у меня ничего не поменяется.
Я всё равно буду моделировать состояние системы как набор изменяемых Map неизменяемых структур данных (ака Spring Data JDBC Repository).
Возможно, у меня будет меньше специализированных под юз кейсы ДТОшек.
Совершенно точно я начну спокойно ходить по ссылкам между сущностями внутри бизнес-логики (а-ля Datomic Pull API)..
Но совершенно точно не перейду на модель огромного графа изменяемых объектов (которую, судя по всему Хориков считает идеально чистой).
При том у Хорикова в самом примере есть противоречие:
С одной стороны, он пишет:
And the difference here is the IStudentRepository interface. The domain class simply wouldn’t need to work with this interface in a setting with no database.
Но с другой стороны, в примере он использует репоз для того, чтобы обеспечить уникльность емейла студента. И вот куда он засунет поиск студента по емейлу? В
class Domain(val students: Set<Student>)
?Кажется, единственное разумное место, куда можно эту проверку засунуть - StudentsRepository. Где бы он не хранил свои данные - в памяти или БД.
В общем, функциональная модель не только лучше отражает модель в голове конечного пользователя, но и лучше отражает природу информационных систем.
#functional_architecture@ergonomic_code #ddd@ergonomic_code
GitHub
GitHub - d-r-q/qbit: qbit is a kotlin-multiplatform embeddable decentralized DBMS with object-relational information model
qbit is a kotlin-multiplatform embeddable decentralized DBMS with object-relational information model - d-r-q/qbit
❤4👍3
Привет!
И снова мне попалась дичь в переводе английской книги, которую я рекомендую к прочтению.
В книге по большому счёту ни слова об Андроиде. Но переводчики, то ли от собственной некомпетентности, то ли по злому маркетинговому умыслу написали, что книга про Андроид разработку.
Не слушайте их - книгу можно и нужно читать и бакэндерам тоже.
И читайте книги только в оригиналах. Пусть это будет одна, а не 12 книг в год, но вы хотя бы что-то полезное усвоите, а не глюки ИИ, который занимался переводом под редакторством дилетантов, которые код в глаза не видели
#books@ergonomic_code
И снова мне попалась дичь в переводе английской книги, которую я рекомендую к прочтению.
В книге по большому счёту ни слова об Андроиде. Но переводчики, то ли от собственной некомпетентности, то ли по злому маркетинговому умыслу написали, что книга про Андроид разработку.
Не слушайте их - книгу можно и нужно читать и бакэндерам тоже.
И читайте книги только в оригиналах. Пусть это будет одна, а не 12 книг в год, но вы хотя бы что-то полезное усвоите, а не глюки ИИ, который занимался переводом под редакторством дилетантов, которые код в глаза не видели
#books@ergonomic_code
😢6👍4
Привет!
Полезняшка
Представьте, что у вас есть json-файл с массивом на 500 объектов.
И вам надо добавить в эти 500 объектов по ключу externalId с разными UUID-ами.
Есть вариант влоб - написать скриптик.
А есть вариант попроще.
Зайти в neovim и написать:
1. qq - запустить запись макроса
2. /lastExistingKey - найти следующую строку, в которой содержится подстрока с именем последнего существующего ключа
3. A - переместить курсор в конец строки и войти в режим печати
4.
5. <esc> - вернуться в командный режим
5. :read!uuidgen<enter> - запустить программу uuidgen и вставить её вывод в новой строке файла после курсора
6. I - перейти в начало строки и войти в режим печати
7.
8. <esc> - вернуться в командный режим
9. A - перейти в конец строки и войти в режим печати
10.
11. <esc> - вернуться в командный режим
12. q - завершить запись макроса
13. 499@q - 499 раз исполнить макрос
Вопрос примерно 2 минут вместе с гуглением uuidgen и задача решена.
Быстрее, наверное, только на sed/awk - но с ними у меня проблема, что такие задачи у меня раз в месяц появляются и за этот месяц у меня этот клингонский из головы выветривается. А вимом я пользуюсь каждый день и он у меня уже на подкорке.
Поддержка vim-режима есть во всех популярных ИДЕ/редакторов включая Emacs (😄 - если вы понимаете о чём я)
#tools@ergonomic_code
Полезняшка
Представьте, что у вас есть json-файл с массивом на 500 объектов.
И вам надо добавить в эти 500 объектов по ключу externalId с разными UUID-ами.
Есть вариант влоб - написать скриптик.
А есть вариант попроще.
Зайти в neovim и написать:
1. qq - запустить запись макроса
2. /lastExistingKey - найти следующую строку, в которой содержится подстрока с именем последнего существующего ключа
3. A - переместить курсор в конец строки и войти в режим печати
4.
,
- добавить запятую в конце строки5. <esc> - вернуться в командный режим
5. :read!uuidgen<enter> - запустить программу uuidgen и вставить её вывод в новой строке файла после курсора
6. I - перейти в начало строки и войти в режим печати
7.
"externalId": "
- добавить в начале стоки отступ, имя ключа и кавычку перед значением8. <esc> - вернуться в командный режим
9. A - перейти в конец строки и войти в режим печати
10.
"
- добавить в конце строки кавычки11. <esc> - вернуться в командный режим
12. q - завершить запись макроса
13. 499@q - 499 раз исполнить макрос
Вопрос примерно 2 минут вместе с гуглением uuidgen и задача решена.
Быстрее, наверное, только на sed/awk - но с ними у меня проблема, что такие задачи у меня раз в месяц появляются и за этот месяц у меня этот клингонский из головы выветривается. А вимом я пользуюсь каждый день и он у меня уже на подкорке.
Поддержка vim-режима есть во всех популярных ИДЕ/редакторов включая Emacs (
#tools@ergonomic_code
Please open Telegram to view this post
VIEW IN TELEGRAM
Neovim
Hyperextensible Vim-based text editor
🔥4👍3😁2
Привет!
Теперь меня не только почитать, посмотреть (а некоторым даже и пощупать) можно, но и послушать:)
#talks@ergonomic_code #ergo_approach@ergonomic_code
Теперь меня не только почитать, посмотреть (а некоторым даже и пощупать) можно, но и послушать:)
#talks@ergonomic_code #ergo_approach@ergonomic_code
😁4
Forwarded from javaswag
https://javaswag.github.io/episode/71/
Слушать подкаст в Apple | Spotify | Yandex
В 71 выпуске подкаста Javaswag поговорили с Алексеем Жидковым об эргономичном подходе для разработки архитектуры проекта
00:00 Начало
12:06 Работа консультанта
17:38 Эргономичный подход и его принципы
26:44 Практика применения принципов разработки
30:55 Трудности внедрения DDD на практике
37:15 Популярность DDD и его реальная эффективность
39:33 TDD и его место в эргономичном подходе
41:00 Тестирование как основа разработки
43:55 Проблемы с моками в тестировании
48:50 Архитектурные подходы и JPA
51:01 Функциональная архитектура и ее влияние на разработку
55:36 Проблемы с ORM и Hibernate
01:00:03 Эргономичность и альтернативы ORM
01:01:53 Неизменяемая модель данных
01:05:58 Эргономичный подход в разработке
01:08:32 Обсуждение стека технологий и его эволюция
01:11:21 Эргономичный подход в разработке проектов
01:17:14 Проблемы объектно-ориентированного программирования
01:20:56 Декомпозиция системы и создание API
01:22:38 Тестирование и разработка по TDD
01:27:24 Экономика эргономичной архитектуры
01:30:59 Элементы эргономичного подхода
01:40:15 Проблемы многопоточности
01:42:58 Непопулярное мнение
Гость - https://t.me/ergonomic_code
Канал в телеграме @ergonomic_code
Сайт Алексея
Кип сейф! 🖖
Слушать подкаст в Apple | Spotify | Yandex
В 71 выпуске подкаста Javaswag поговорили с Алексеем Жидковым об эргономичном подходе для разработки архитектуры проекта
00:00 Начало
12:06 Работа консультанта
17:38 Эргономичный подход и его принципы
26:44 Практика применения принципов разработки
30:55 Трудности внедрения DDD на практике
37:15 Популярность DDD и его реальная эффективность
39:33 TDD и его место в эргономичном подходе
41:00 Тестирование как основа разработки
43:55 Проблемы с моками в тестировании
48:50 Архитектурные подходы и JPA
51:01 Функциональная архитектура и ее влияние на разработку
55:36 Проблемы с ORM и Hibernate
01:00:03 Эргономичность и альтернативы ORM
01:01:53 Неизменяемая модель данных
01:05:58 Эргономичный подход в разработке
01:08:32 Обсуждение стека технологий и его эволюция
01:11:21 Эргономичный подход в разработке проектов
01:17:14 Проблемы объектно-ориентированного программирования
01:20:56 Декомпозиция системы и создание API
01:22:38 Тестирование и разработка по TDD
01:27:24 Экономика эргономичной архитектуры
01:30:59 Элементы эргономичного подхода
01:40:15 Проблемы многопоточности
01:42:58 Непопулярное мнение
Гость - https://t.me/ergonomic_code
Канал в телеграме @ergonomic_code
Сайт Алексея
Кип сейф! 🖖
Javaswag
#71 - Алексей Жидков - эргономичный подход и декомпозиция архитектуры
В 71 выпуске подкаста Javaswag поговорили с Алексеем Жидковым об эргономичном подходе для разработки архитектуры проекта
🔥14👍8❤3
Привет!
Опубликовал пост по мотивам доклада на Joker.
#structured_design@ergonomic_code #ergo_approach@ergonomic_code #talks@ergonomic_code #posts@ergonomic_code
Опубликовал пост по мотивам доклада на Joker.
#structured_design@ergonomic_code #ergo_approach@ergonomic_code #talks@ergonomic_code #posts@ergonomic_code
Алексей Жидков
Структурный дизайн. Древний секрет простого и быстрого кода - Алексей Жидков
https://azhidkov.pro/
👍6❤4🔥4🥰2
Эргономичный код
Привет! Кажется у меня по мотивам Проекта Э на горизонте замаячил очередной кризис Эргономичного подхода. При том зашатались одновременно два столпа - декомпозиция на базе эффектов и функциональная архитектура. С декомпозицией на базе эффектов в одном из…
Привет!
Вы, наверное, забыли, что полтора года назад в Эргономичном подходе было две проблемы (см. цитируемое сообщение), а я - нет:)
В общем я тут внезапно осознал, что гамак-дривен девелопмент сработал и я тихой сапой решил обе проблемы:)
Проблема №1
Тут сейчас ответ такой: пофиг:) Лишь бы команде было удобно ориентироваться. Можете делать так же, как сейчас раскладываете контроллеры. Может плясать от страниц/экранов/компонентов UI, можете от ролей пользователей, можете от юз кейсов, можете от ресурсов REST API.
В Trainer-Advisor, например, сейчас код приложения сначала разбит по ролям пользователей, потом по страницам/компонентам
Проблема №2
Во-первых, я сформулировал к каким систематическим проблемам это ведёт. К заметанию сложности под ковёр. И в итоге появлению таких скрытых монстров, как на картинке №1 - чтобы осознать весь масштаб трагедии этой операции, мне пришлось 4 часа методично код читать.
Во-вторых, я нашёл решение этой проблемы.
Оно состоит из двух частей:
1. Я отказался от сервисов приложений в пользу классов-операций - класс, который имеет один публичный метод, реализующий одну операцию (эндпоинт) системы и имеющий поля для всех ресурсов (гейтвеев, репозов, клиентов внешних систем), требующихся для реализации этой операции. См, например операцию регистрации терапевта в Trainer-Advisor
2. Я завёл штуки, которые сейчас называю "доменные операции" - это процедуры (Kotlin top-level function), которые нужные им ресурсы получают в качестве параметров. В том же коде регистрации терапевта надо CreateTherapistUserWorkflow заменить на процедуру
с кодом его реализации, которая зависимости получает явно в качестве параметров. Реального публичного кода с иллюстрацией у меня пока нет, но есть картинка №2:)
В результате, для того чтобы оценить масштаб трагедии достаточно посмотреть на кол-во зависимостей класса-операции. А для того чтобы ограничить масштаб трагедии - достаточно ввести ограничение на кол-во зависимостей.
При том вы можете избегать дублирования "подопераций" и в целом ограничивать длину методов операций и вводить промежуточные уровни абстракции.
Параметры с ресурсами, конечно, придётся таскать - но это будет напоминалкой, чтобы искать возможность повысить уровень абстракции ресурсов и/или уменьшить количество вещей, которые делает операция. В примере из TA, например, пришло время завести UsersService, который скрывает за собой usersRepo и usersFactory
вин-вин-вин, я считаю:)
#ergo_approach@ergonomic_code #ergo_arch@ergonomic_code
Вы, наверное, забыли, что полтора года назад в Эргономичном подходе было две проблемы (см. цитируемое сообщение), а я - нет:)
В общем я тут внезапно осознал, что гамак-дривен девелопмент сработал и я тихой сапой решил обе проблемы:)
Проблема №1
А вот как декомозировать слой приложения - я пока не знаю.
Тут сейчас ответ такой: пофиг:) Лишь бы команде было удобно ориентироваться. Можете делать так же, как сейчас раскладываете контроллеры. Может плясать от страниц/экранов/компонентов UI, можете от ролей пользователей, можете от юз кейсов, можете от ресурсов REST API.
В Trainer-Advisor, например, сейчас код приложения сначала разбит по ролям пользователей, потом по страницам/компонентам
Проблема №2
Однако на практике у меня некоторые операции ещё и другие операции дёргают. И мне это кажется нарушением принципа одного уровня абстракции.
Но я пока не могу сформулировать к каким систематическим проблемам это ведёт.
Во-первых, я сформулировал к каким систематическим проблемам это ведёт. К заметанию сложности под ковёр. И в итоге появлению таких скрытых монстров, как на картинке №1 - чтобы осознать весь масштаб трагедии этой операции, мне пришлось 4 часа методично код читать.
Во-вторых, я нашёл решение этой проблемы.
Оно состоит из двух частей:
1. Я отказался от сервисов приложений в пользу классов-операций - класс, который имеет один публичный метод, реализующий одну операцию (эндпоинт) системы и имеющий поля для всех ресурсов (гейтвеев, репозов, клиентов внешних систем), требующихся для реализации этой операции. См, например операцию регистрации терапевта в Trainer-Advisor
2. Я завёл штуки, которые сейчас называю "доменные операции" - это процедуры (Kotlin top-level function), которые нужные им ресурсы получают в качестве параметров. В том же коде регистрации терапевта надо CreateTherapistUserWorkflow заменить на процедуру
fun createTherapistUser(
usersRepo: UsersRepo,
therapistsRepo: TherapistsRepo,
usersFactory: UsersFactory,
registerTherapistRequest: RegisterTherapistReques,
password: CharSequence) {
...
}
с кодом его реализации, которая зависимости получает явно в качестве параметров. Реального публичного кода с иллюстрацией у меня пока нет, но есть картинка №2:)
В результате, для того чтобы оценить масштаб трагедии достаточно посмотреть на кол-во зависимостей класса-операции. А для того чтобы ограничить масштаб трагедии - достаточно ввести ограничение на кол-во зависимостей.
При том вы можете избегать дублирования "подопераций" и в целом ограничивать длину методов операций и вводить промежуточные уровни абстракции.
Параметры с ресурсами, конечно, придётся таскать - но это будет напоминалкой, чтобы искать возможность повысить уровень абстракции ресурсов и/или уменьшить количество вещей, которые делает операция. В примере из TA, например, пришло время завести UsersService, который скрывает за собой usersRepo и usersFactory
вин-вин-вин, я считаю:)
#ergo_approach@ergonomic_code #ergo_arch@ergonomic_code
👍9🔥4❤3
Привет!
Предистория.
Как вы знаете, я недавно ходил в гости к javaswag. Но, возможно, вы (как и я до этой записи) не знаете, что javaswag – это не только звук, но и нарезка видео, и небольшие тексты с комментариями к ссылкам.
У меня ссылок было аж 19 штук и Дима предложил сделать развёрнутые комментарии к ссылкам.
Но внезапно оказалось, что я не умею писать комментарии к ссылкам и вместо комментариев у меня как обычно вышел небольшой пост-очерк “Что такое ООП?”.
Но пост – уже не формат для javaswag, поэтому я его представляю вам у себя.
—-
История
В книге “What every programmer should know about object-oriented design” Пейдж-Джонс на первой же странице пишет:
Наверное, если провести опрос среди разработчиков, то самым популярным ответом будет “ООП – это наследование, полиморфизм и инкапсуляция”. И последний выпуск javaswag (см. ответ на моё непопулярное мнение), кстати, это подтверждает.
Однако Алан Кей, автор термина, в одном из своих докладов заявил: “На самом деле это я придумал термин “объектно-ориентированный” и я могу сказать вам, что я не имел С++ ввиду”.
А имел он ввиду: обмен сообщениями, сокрытие состояния и экстремально позднее связывание.
И, как следствие, Джо Армстронг, создатель Erlang считает: “Erlang, возможно, является единственным объектно-ориентированным языком, потому что три принципа объектно-ориентированного программирования заключаются в передаче сообщений, изоляции между объектами и полиморфизмом. [...] ООП — это не про объекты и классы, ООП — это про сообщения”.
Для меня же объектно-ориентированный подход — это подход к разработке программ, в котором базовым блоком является объект.
А объект — это сущность, которая обладает состоянием и ограничивает пространство своих допустимых состояний.
На удивление, идею пространства состояний и его ограничения я нашёл и в книге Пейдж-Джонса спустя пару лет, после того как написал свой пост.
А что такое ООП для вас?
#oop@ergonomic_code #terminology@ergonomic_code #archeology@ergonomic_code #books@ergonomic_code
Предистория.
Как вы знаете, я недавно ходил в гости к javaswag. Но, возможно, вы (как и я до этой записи) не знаете, что javaswag – это не только звук, но и нарезка видео, и небольшие тексты с комментариями к ссылкам.
У меня ссылок было аж 19 штук и Дима предложил сделать развёрнутые комментарии к ссылкам.
Но внезапно оказалось, что я не умею писать комментарии к ссылкам и вместо комментариев у меня как обычно вышел небольшой пост-очерк “Что такое ООП?”.
Но пост – уже не формат для javaswag, поэтому я его представляю вам у себя.
—-
История
В книге “What every programmer should know about object-oriented design” Пейдж-Джонс на первой же странице пишет:
Термин “объектно-ориентированный”, по сути своей, бессмысленен. “Объект” — это одно из самых общих слов в английском языке. Если вы посмотрите его значение в словаре, то увидите что-то вроде:
Объект — вещь, представленная или которую можно представить чувствам [человека].
Другими словами, объект - это практически всё что угодно.
Слово “ориентированный” также не особо помогает. Опредёленное как “направленный в сторону”, оно обычно используется для превращения термина “объекто-ориентированный” в прилагательное.
Таким образом, мы имеем:
Объектно-ориентированный — направленный в сторону практически чего угодно, о чём вы можете только подумать.
Не удивительно, что наша индустрия не смогла договориться об определении термина “объектно-ориентированный”.
Наверное, если провести опрос среди разработчиков, то самым популярным ответом будет “ООП – это наследование, полиморфизм и инкапсуляция”. И последний выпуск javaswag (см. ответ на моё непопулярное мнение), кстати, это подтверждает.
Однако Алан Кей, автор термина, в одном из своих докладов заявил: “На самом деле это я придумал термин “объектно-ориентированный” и я могу сказать вам, что я не имел С++ ввиду”.
А имел он ввиду: обмен сообщениями, сокрытие состояния и экстремально позднее связывание.
И, как следствие, Джо Армстронг, создатель Erlang считает: “Erlang, возможно, является единственным объектно-ориентированным языком, потому что три принципа объектно-ориентированного программирования заключаются в передаче сообщений, изоляции между объектами и полиморфизмом. [...] ООП — это не про объекты и классы, ООП — это про сообщения”.
Для меня же объектно-ориентированный подход — это подход к разработке программ, в котором базовым блоком является объект.
А объект — это сущность, которая обладает состоянием и ограничивает пространство своих допустимых состояний.
На удивление, идею пространства состояний и его ограничения я нашёл и в книге Пейдж-Джонса спустя пару лет, после того как написал свой пост.
А что такое ООП для вас?
#oop@ergonomic_code #terminology@ergonomic_code #archeology@ergonomic_code #books@ergonomic_code
Telegram
javaswag
Еженедельная рассылка вручную отобранных статей по Java и JVM. https://javaswag.github.io
Предложить новость: @volyx
Реклама: @anabilisa
Предложить новость: @volyx
Реклама: @anabilisa
👍11
Привет!
Полезняшка.
Я вчера по своему невежеству часа два потратил на то, чтобы воткнуть в локальном окружении проксю между запущенными на хосте фронтом, который ходит на один урл и двумя бэк-сервисами, так, чтобы определённый путь уходил на один сервис, а все остальные - на другой.
В итоге всё оказалось предельно просто.
Запустил компоузом nginx с network_mode: host и собрал минимальный конфиг nginx-а.
Не сказать, что откровение века, но может кому-то ещё пригодится.
#devx@ergonomic_code #docker@ergonomic_code #nginx@ergonomic_code
Полезняшка.
Я вчера по своему невежеству часа два потратил на то, чтобы воткнуть в локальном окружении проксю между запущенными на хосте фронтом, который ходит на один урл и двумя бэк-сервисами, так, чтобы определённый путь уходил на один сервис, а все остальные - на другой.
В итоге всё оказалось предельно просто.
Запустил компоузом nginx с network_mode: host и собрал минимальный конфиг nginx-а.
name: my-project-nginx
services:
nginx:
image: nginx
volumes:
- ./nginx/dev.conf:/etc/nginx/conf.d/default.conf
network_mode: host
server {
listen 8081;
location ~ ^/api/(public|external)/ {
proxy_pass http://localhost:8084;
}
location / {
proxy_pass http://localhost:8082;
}
}
Не сказать, что откровение века, но может кому-то ещё пригодится.
#devx@ergonomic_code #docker@ergonomic_code #nginx@ergonomic_code
👍8
Если бы я сделал курсы по ЭП, какие бы вы купили?
Anonymous Poll
40%
Классический TDD на практике
79%
Промышленная функциональная архитектура
27%
Spring Data Relational для продакшена
Привет!
На днях перевёл Проект Р и Trainer Advisor на Kotlin 2.1.0 и Spring Boot 3.4.0
В целом всё прошло без проблем, делюсь впечатлениями
Проект Р/Котлин 2.0.0 -> 2.1.0
1. Т.к. переходил с версии 2.0.0 так же возникла проблема с пропажей продовых зависимостей в testFixtures source sets. И со второй попытки я её определил и починил быстро
2. В паре data классов с приватными конструкторами пришлось развесить @ConsistentCopyVisibility, чтобы варнинг убрать
Проект Р/Спринг 3.3.1 -> 3.4.0
1. Тест на корс, который ломился без авторизации на закрытый урл начал валиться по 401/3 (забыл уже) - перевёл его на запрос к публичному пути - заработало
Trainer Adviser/Котлин 2.0.21 -> 2.1.0
1. Заглючила идея 2024.2 и опять на testsFixtures - гредлом всё ок собирается, в редакторе ошибок нет, но при попытке сборки проектов идеевским билд тулом (я юзаю его для разработки, так как он быстрее гредлового) - ругается что не может в коде тестов найти символ из кода фикстур. Это поличилось обновлением самой идеи до 2024.3
Trainer Advisor/Спринг 3.3.5 -> 3.4.0
1. Начало взрываться
2. В одном из эндпоинтов на параметр принципала не был навешан
—
На обновление Проекта Р у меня ушло часа три.
Львиная доля ушла на:
1. переход на обратнонесовместимый Kover 0.8.3
2. datafaker в котором задепрекейтили один из методов
3. не связанные с обновлением разборки с гредлом
Trainer Advisor вообще за час максимум обновил.
Держите свои зависимости актуальными - если это делать своевременно, то это требует минимума усилий. А вот нагонять большое отставание - это уже беда. Для некоторых трудозатраты на такое приключение становятся фактически заградительными и проект начинает планомерно превращаться в мамонта.
#kotlin@ergonomic_code #spring@ergonomic_code #projectr@ergonomic_code #trainer_advisor@ergonomic_code
На днях перевёл Проект Р и Trainer Advisor на Kotlin 2.1.0 и Spring Boot 3.4.0
В целом всё прошло без проблем, делюсь впечатлениями
Проект Р/Котлин 2.0.0 -> 2.1.0
1. Т.к. переходил с версии 2.0.0 так же возникла проблема с пропажей продовых зависимостей в testFixtures source sets. И со второй попытки я её определил и починил быстро
2. В паре data классов с приватными конструкторами пришлось развесить @ConsistentCopyVisibility, чтобы варнинг убрать
Проект Р/Спринг 3.3.1 -> 3.4.0
1. Тест на корс, который ломился без авторизации на закрытый урл начал валиться по 401/3 (забыл уже) - перевёл его на запрос к публичному пути - заработало
Trainer Adviser/Котлин 2.0.21 -> 2.1.0
1. Заглючила идея 2024.2 и опять на testsFixtures - гредлом всё ок собирается, в редакторе ошибок нет, но при попытке сборки проектов идеевским билд тулом (я юзаю его для разработки, так как он быстрее гредлового) - ругается что не может в коде тестов найти символ из кода фикстур. Это поличилось обновлением самой идеи до 2024.3
Trainer Advisor/Спринг 3.3.5 -> 3.4.0
1. Начало взрываться
responseEntity.contentLength = storedFileInputStream.metaData.size
при size = 0
. Добавил if (size > 0) - завелось2. В одном из эндпоинтов на параметр принципала не был навешан
@AuthenticationPrincipal
. Раньше это как-то работало, после преезда перестало, после добавления аннотации снова заработало.—
На обновление Проекта Р у меня ушло часа три.
Львиная доля ушла на:
1. переход на обратнонесовместимый Kover 0.8.3
2. datafaker в котором задепрекейтили один из методов
3. не связанные с обновлением разборки с гредлом
Trainer Advisor вообще за час максимум обновил.
Держите свои зависимости актуальными - если это делать своевременно, то это требует минимума усилий. А вот нагонять большое отставание - это уже беда. Для некоторых трудозатраты на такое приключение становятся фактически заградительными и проект начинает планомерно превращаться в мамонта.
#kotlin@ergonomic_code #spring@ergonomic_code #projectr@ergonomic_code #trainer_advisor@ergonomic_code
Telegram
Эргономичный код
Привет!
Существует расхожее мнение, что разработчик большую часть жизни проводит в легаси браун филд проектах.
Но моя карьера его опровергает.
Первые 12 лет работы в найме, мне действительно приходилось довольно много работать с чужим кодом: я поработал…
Существует расхожее мнение, что разработчик большую часть жизни проводит в легаси браун филд проектах.
Но моя карьера его опровергает.
Первые 12 лет работы в найме, мне действительно приходилось довольно много работать с чужим кодом: я поработал…
👍4❤3👌1
Привет!
Новая рубрика в канале - челлендж! :)
Предыстория
Собрался я тут писать на свою вики статью "Функциональная (типизированная) обработка ошибок". Текст написал, решил сдобрить примерами. В качестве задачи решил взять парсинг строк в инты. Сначала запилил тупую императивную реализацию. Потом подумал, что это как-то не конгруэнтно и попробовал переписать в декларативном стиле. И такое ощущение, что получилось заметно хуже - и медленнее и сложнее.
История
Предлагаю вам поучаствовать в челлендже на самую понятную и эффективную реализацию функции парсинга:)
Условия:
1. Надо форкнуть репоз-фреймворк, реализовать функцию parseInt так, чтобы проходили тесты
2. Завести пуллреквест со своей реализацией. Ограничений на реализацию нет - можно писать и в императивном стиле, и в декларативном, и с помощью ии
3. Через выходные 16-ого декабря я опубликую в канале все варианты включая свои и заведу голосовалку, какой из вариантов наиболее понятен
4. Победитель получит почёт, свой код в вики эргономичного подхода и ссылки на себя в вики, репозе и канале:)
Новая рубрика в канале - челлендж! :)
Предыстория
Собрался я тут писать на свою вики статью "Функциональная (типизированная) обработка ошибок". Текст написал, решил сдобрить примерами. В качестве задачи решил взять парсинг строк в инты. Сначала запилил тупую императивную реализацию. Потом подумал, что это как-то не конгруэнтно и попробовал переписать в декларативном стиле. И такое ощущение, что получилось заметно хуже - и медленнее и сложнее.
История
Предлагаю вам поучаствовать в челлендже на самую понятную и эффективную реализацию функции парсинга:)
Условия:
1. Надо форкнуть репоз-фреймворк, реализовать функцию parseInt так, чтобы проходили тесты
2. Завести пуллреквест со своей реализацией. Ограничений на реализацию нет - можно писать и в императивном стиле, и в декларативном, и с помощью ии
3. Через выходные 16-ого декабря я опубликую в канале все варианты включая свои и заведу голосовалку, какой из вариантов наиболее понятен
4. Победитель получит почёт, свой код в вики эргономичного подхода и ссылки на себя в вики, репозе и канале:)
GitHub
GitHub - ergonomic-code/Functional-error-handling: Примеры функционального (типизированного) подхода к обработке ошибок на Kotlin
Примеры функционального (типизированного) подхода к обработке ошибок на Kotlin - ergonomic-code/Functional-error-handling
👍8🔥3
Эргономичный код
Привет! Новая рубрика в канале - челлендж! :) Предыстория Собрался я тут писать на свою вики статью "Функциональная (типизированная) обработка ошибок". Текст написал, решил сдобрить примерами. В качестве задачи решил взять парсинг строк в инты. Сначала…
Привет!
Так, ну чтош, обещанная голосовалка.
В первую очередь, спасибо всем кто отозвался и прислал варианты.
Всего вышло аш 10 вариантов - 5 моих и 5 от подписчиков.
Я решил, что корректнее будет если я не буду их выделять, поэтому варианты идут в случайном порядке.
Сейчас запилю пост с опросом - голосуем:)
Напомню, моя цель выбрать вариант, который проще всего прочитать и понять широкой аудитории.
Так, ну чтош, обещанная голосовалка.
В первую очередь, спасибо всем кто отозвался и прислал варианты.
Всего вышло аш 10 вариантов - 5 моих и 5 от подписчиков.
Я решил, что корректнее будет если я не буду их выделять, поэтому варианты идут в случайном порядке.
Сейчас запилю пост с опросом - голосуем:)
Напомню, моя цель выбрать вариант, который проще всего прочитать и понять широкой аудитории.