Эргономичный код pinned «Привет! Свершилось!🎉🎉🎉 Наша исследовательская группа — я, @goloshchapov и @VektorAB — закончила разработку анкеты и приглашает вас поучаствовать в опросе! Напомню кратко цель исследования: выяснить, как делать проекты так, чтобы последователи сочли их …»
Привет!
У нас в группе за последнюю пару недель было сразу два холивара на тему разделения на слой приложения и домена в DDD. Я смотрел на них и про себя думал, что это очень попахивает искусственной/побочной сложностью.
В ЭП тоже есть очень похожее разделение и даже с теми же названиями, потому что выросло оно у меня из ДДД. Но у меня оно сейчас если не проще, то чётче, на мой взгляд.
В слое домена у меня живёт состояние - классы сущностей/агрегатов и репозитории*.
В слое приложения живут операции системы - в первую очередь порты/точки входа - хттп эндпоинты, обработчики крон-задач, слушатели всевозможных событий и сообщений.
Если операция системы простая - меняет только один ресурс - то она реализуется прямо в порте. В идеале - единственным вызовом репозитория, но см. правила ниже.
Если же операции надо потрогать два или более репозитория, то она оформляется в отдельный класс операции с единственным публичным методом, который помещается в слой приложения и может звать уже сколько угодно репозиториев. Но тоже см. правила ниже.
И для выбора места размещения кода у меня есть два подхода на выбор разработчика.
1. снизу вверх. Код помещается на максимально низкий уровень, где доступно требуемое состояние. Трансоформация/вычисление на базе одной сущности помещается рядом с ней. Код, меняющий только один репоз помещается рядом с этим репозом. Код трансформирующий/вычисляющий на базе нескольких агрегатов/сущностей помещается в слой приложения рядом с операцией, которая его использует или в общий код пакета, содержащего все операции, которые его используют. Код работающий с несколькими ресурсами помещается аналогично максимально близко к операции(ям), его использующим
2. сверху вниз. Код помещается на самый высокий уровень, доступный всем его клиентам. Этот подход, на самом деле имеет смысл только для трансформаций сущностей и тут по большому счёту только два варианта. Трансформация одной сущности, которая используется только в одной операции помещается рядом с ней. Если он нужен нескольким операциям - помещается рядом с сущностью.
Я обычно придерживаюсь подхода снизу вверх, вынося трансформации выше если:
1. она явно относится к одной конкретной операции
2. вокруг сущности накопилось более 10 методов, многие из которых используются только в одной операции
Кроме того у меня есть пачка защитных-правил, которые предотвращают превращение реализации в кровавое месиво бизнес-логики и ввода-вывода и разных уровней абстракции:
1. каждая технология должна быть инкапсулирована либо в порте, либо в ресурсе. При том в случае ресурса инкапсуляция означает, что технология не фонит в API ресурса. В АПИ репозитория не должны упоминаться таблицы, колонки, внешние ключи и т.п. В АПИ хттп клиента внешней системы не должны упоминаться хттп методы, заголовки, куки, мультипарты и т.д.
2. Ни порты, ни операции, ни репозитории** не могут вызывать друг друга
3. метод порта не может вызывать более одной операции или метода ресурса
4. метод порта может содержать только одну конструкцию ветвления (if/when/switch) для выбора представления ответа
5. метод, который прямо или косвенно содержит ввод-вывод (методы портов, операций и репозиториев) может иметь когнитивную сложность не более 4
6. классы поведения (операции, ресурсы) должны иметь не более 7, край 10 зависимостей. А в идеале - до 5
В общем, мне кажется, хороший подход/гайдлайн/методика разработки должен минимизировать поле для холиваров и разночтений. А для этого он должен быть определён в максимально чётко сформулированных правилах, проверку которых, в идале, можно автоматизировать.
Подробнее об этом у меня написано в заготовке статьи Эргономичная архитектура
#ergo_approach@ergonomic_code #ddd@ergonomic_code
У нас в группе за последнюю пару недель было сразу два холивара на тему разделения на слой приложения и домена в DDD. Я смотрел на них и про себя думал, что это очень попахивает искусственной/побочной сложностью.
В ЭП тоже есть очень похожее разделение и даже с теми же названиями, потому что выросло оно у меня из ДДД. Но у меня оно сейчас если не проще, то чётче, на мой взгляд.
В слое домена у меня живёт состояние - классы сущностей/агрегатов и репозитории*.
В слое приложения живут операции системы - в первую очередь порты/точки входа - хттп эндпоинты, обработчики крон-задач, слушатели всевозможных событий и сообщений.
Если операция системы простая - меняет только один ресурс - то она реализуется прямо в порте. В идеале - единственным вызовом репозитория, но см. правила ниже.
Если же операции надо потрогать два или более репозитория, то она оформляется в отдельный класс операции с единственным публичным методом, который помещается в слой приложения и может звать уже сколько угодно репозиториев. Но тоже см. правила ниже.
И для выбора места размещения кода у меня есть два подхода на выбор разработчика.
1. снизу вверх. Код помещается на максимально низкий уровень, где доступно требуемое состояние. Трансоформация/вычисление на базе одной сущности помещается рядом с ней. Код, меняющий только один репоз помещается рядом с этим репозом. Код трансформирующий/вычисляющий на базе нескольких агрегатов/сущностей помещается в слой приложения рядом с операцией, которая его использует или в общий код пакета, содержащего все операции, которые его используют. Код работающий с несколькими ресурсами помещается аналогично максимально близко к операции(ям), его использующим
2. сверху вниз. Код помещается на самый высокий уровень, доступный всем его клиентам. Этот подход, на самом деле имеет смысл только для трансформаций сущностей и тут по большому счёту только два варианта. Трансформация одной сущности, которая используется только в одной операции помещается рядом с ней. Если он нужен нескольким операциям - помещается рядом с сущностью.
Я обычно придерживаюсь подхода снизу вверх, вынося трансформации выше если:
1. она явно относится к одной конкретной операции
2. вокруг сущности накопилось более 10 методов, многие из которых используются только в одной операции
Кроме того у меня есть пачка защитных-правил, которые предотвращают превращение реализации в кровавое месиво бизнес-логики и ввода-вывода и разных уровней абстракции:
1. каждая технология должна быть инкапсулирована либо в порте, либо в ресурсе. При том в случае ресурса инкапсуляция означает, что технология не фонит в API ресурса. В АПИ репозитория не должны упоминаться таблицы, колонки, внешние ключи и т.п. В АПИ хттп клиента внешней системы не должны упоминаться хттп методы, заголовки, куки, мультипарты и т.д.
2. Ни порты, ни операции, ни репозитории** не могут вызывать друг друга
3. метод порта не может вызывать более одной операции или метода ресурса
4. метод порта может содержать только одну конструкцию ветвления (if/when/switch) для выбора представления ответа
5. метод, который прямо или косвенно содержит ввод-вывод (методы портов, операций и репозиториев) может иметь когнитивную сложность не более 4
6. классы поведения (операции, ресурсы) должны иметь не более 7, край 10 зависимостей. А в идеале - до 5
В общем, мне кажется, хороший подход/гайдлайн/методика разработки должен минимизировать поле для холиваров и разночтений. А для этого он должен быть определён в максимально чётко сформулированных правилах, проверку которых, в идале, можно автоматизировать.
Подробнее об этом у меня написано в заготовке статьи Эргономичная архитектура
#ergo_approach@ergonomic_code #ddd@ergonomic_code
Telegram
Эргономичный код - группа
Помогаем друг другу применять на практике основные идеи Эргономичного подхода - модульные монолиты, неизменяемую модель данных, функциональную архитектуру, интеграционные тесты, outside in TTD, data-oriented programming.
Канал: https://t.me/ergonomic_code
Канал: https://t.me/ergonomic_code
❤5👍3
* - на самом деле не только репозитории, но и любые штуки с состоянием - клиенты внешних АПИ, очереди сообщений, мапы в памяти, сервисы отправки почты и сообщений в телеграм и т.д.
** - в случае если какую-то пару репозиториев надо позвать в нескольких операциях и этому действию можно дать вменяемое имя, оно оформляется в доменную операцию - класс, экземпляры которого создаются руками в классах операциях, а не ДИ-контейнером/composition root-ом.
Так же есть сложные ресурсы, инкапсулирующие нескольких простых. Например, если клиенту внешнего АПИ надо кэшировать в БД системы токен авторизации, то это реализуется тремя классами - верхнеуровневым ресурсом, ресурсом-клиентом внешнего АПИ и ресурсом-дао/репозом токенов. В это случае верхнеуровневый ресурс (и только он) может вызывать вложенные ресурсы.
** - в случае если какую-то пару репозиториев надо позвать в нескольких операциях и этому действию можно дать вменяемое имя, оно оформляется в доменную операцию - класс, экземпляры которого создаются руками в классах операциях, а не ДИ-контейнером/composition root-ом.
Так же есть сложные ресурсы, инкапсулирующие нескольких простых. Например, если клиенту внешнего АПИ надо кэшировать в БД системы токен авторизации, то это реализуется тремя классами - верхнеуровневым ресурсом, ресурсом-клиентом внешнего АПИ и ресурсом-дао/репозом токенов. В это случае верхнеуровневый ресурс (и только он) может вызывать вложенные ресурсы.
👍2
И ещё мысль в догонку. Такое ощущение, что у меня сейчас на Спринге небизнес-логики практически нет. Бывает, что надо из запроса с мультипартом надо собрать команду для бизнес-логики. Или что надо сделать какую-то хитрую координацию и обработку ошибок при работе с внешней системой. Но в моих проектах такого кода прям максимум процентов 10 наберётся
👍3
Forwarded from blzr
Инженерное совершенство
и детальный анализ
#инженерия
и детальный анализ
My father-in-law is a builder. It is difficult to get his attention in a magnificent space because he is lost in wonder. We were in a cathedral together years ago and I asked him what it would cost to build it today. I will never forget his answer… 'We can’t, we don’t know how to do it.'
how come a company founded over 100 years ago has the fastest site on the internet?
After a quick look:
· Agressive pre-loading pages on hover
· fixed image dimensions - there is no layout shift when they load
· Dependency Injection - only loading the JS needed on the pages where its needed
· Uses pushstate to change pages so it feels faster than a full reload
· agressive CDN and browser caching
· Server rendered HTML (ASP.net)
Funny enough they load almost a meg of JS (YUI and jQuery) but you dont notice because it feels so snappy
#инженерия
👍5❤3🔥2
Привет!
Представляю вам первого партёнра нашего исследования - канал Саши Раковского.
Саша и в бета-тесте поучаствовал, и рассказал об исследовании своим подписчикам по собственной инициативе.
А ещё у него в канале много крутых постов, например как ниже.
Ну и пользуясь случаем ещё раз призываю вас заполнить анкету - пока что у нас только 25 анкет, надо хотя бы до 50 дотянуть
Представляю вам первого партёнра нашего исследования - канал Саши Раковского.
Саша и в бета-тесте поучаствовал, и рассказал об исследовании своим подписчикам по собственной инициативе.
А ещё у него в канале много крутых постов, например как ниже.
Ну и пользуясь случаем ещё раз призываю вас заполнить анкету - пока что у нас только 25 анкет, надо хотя бы до 50 дотянуть
Telegram
Саша Раковский
Мой маленький канал про экстремальное программирование и разработку программного обеспечения.
❤2
Forwarded from Саша Раковский
Про лапки 🥰
В статье по дизайну я упомянул design stamina hypothesis. Гипотезу, что у хорошего дизайна кривая стоимости изменений гораздо более плоская, чем у плохого. Простым языком: если код - говно, то менять его тупо дороже, простите меня за мой французский.
Так вот, проблема этой идеи в том, что это гипотеза. Почему? Потому что мы не можем ее проверить - не умеем измерять скорость разработки.
Или всё-таки умеем?
Написать какой-нибудь майнкрафт в одиночку за неделю - это точно быстро. Поэтому сказать, что мы совсем не умеем оценивать, нельзя. Проблема в том, что мы просто делаем это очень плохо.
Не хочу долго мусолить методы сравнения, но из уважения к читателям укажу основные метрики, которые мы знаем:
- строчки кода
- сторипоинты
- тест-кейсы
- количество фич
- соотношение новой работы и остальной работы
- business value
- dora-метрики
- интуиция.
В частных случаях они все могут быть даже полезными, и это тема для отдельного поста, но в общем случае их нельзя использовать для измерения скорости команд.
Дурацкая импотенция
Вот эта вот скорость - это далеко не единственная штука, с которой у нас есть проблемы. Мы отвратительно оцениваем объём работ, плохо прикидываем business value той или иной фичи, ужасно справляемся с big upfront design, простите мне этот англицизм. И, если кто-то утверждает, что он все это умеет, то он или гений, или заблуждается, или просто врёт.
Про целеполагание
И во всей этой импотенции обязательно надо понимать: цель измерений-то какая?
Вот у вас есть быстрая команда, которая фигачит в два раза быстрее остальных. А толку, если она фигачит не туда? Это прям такая классика, когда 2/3 разработанных фич пользователями либо используются крайне редко, либо не используются вообще. Есть даже название такому софту: bloatware.
То же самое касается и оценки объёма работ. Вот вам дали ТЗ. Допустим, сами пользователи дали. Вы оценили: через год будет готово. Ну вот даже если вы прям угадали, и через год все готово. Вот даже если у вас супер быстрая команда, которая сделала это в 2 раза дешевле остальных. Ну вы все равно упираетесь в тот факт, что даже сами пользователи не знают, что им реально надо. И через год у них за пол стоимости есть функционал, 2/3 из которого можно было не делать.
Дежурный пинок водопада
Водопад, на самом деле, плохо работает не только и не столько потому, что мы не очень оцениваем на дальнюю перспективу, сильно ошибаемся при предварительном проектировании больших систем и откладываем все самые неприятные неожиданности на фазу тестирования. Все это, конечно же, в разы увеличивает расходы и ломает экономику большой доли проектов, которые отменяют спустя месяцы и годы разработки.
Но вот значительную часть оставшихся проектов, где выгода во много раз должна была бы превысить затраты, добивала ситуация, когда спустя десятки недель разработки пользователи получали совсем не то, что надо. Может быть, именно то, что они просили, но точно не то, что им было нужно.
К чему я это все?
Да к тому, что без качественной работы над скоупом все эти спекуляции про продуктивность, тесты, ДДД, рефакторинг, чистый код и т.п. - это все разговоры не туда, имитация бурной деятельности.
Для большинства команд самый быстрый способ ускориться в несколько раз - это перестать делать лишнюю работу. Необходимость работы над чем-то всегда нужно доказывать.
Куда копать дальше?
Три года назад, когда моя голова была забита всей этой экстремалкой, CD и прочим аджайлом, вот этот доклад для меня перевернул все. Gojko Adzic - самый главный амбассадор борьбы с работой не туда, поэтому рекомендую ознакомиться с его работами.
Эти же идеи транслирует и Эрик Райс в своём Lean Startup. У него есть одноимённая книга, но для быстрого ознакомления рекомендую вот этот доклад.
Ну и из всей горы экспертов, советов и методологий наиболее положительно, конечно, выделяется DORA со своими Accelerate и State of Devops. Эти просто померили, что влияет на успехи компании и предикторы этих успехов, а что - нет. Никаких вам умозрительных пальцесосаний, сухая конкретика.
В статье по дизайну я упомянул design stamina hypothesis. Гипотезу, что у хорошего дизайна кривая стоимости изменений гораздо более плоская, чем у плохого. Простым языком: если код - говно, то менять его тупо дороже, простите меня за мой французский.
Так вот, проблема этой идеи в том, что это гипотеза. Почему? Потому что мы не можем ее проверить - не умеем измерять скорость разработки.
Или всё-таки умеем?
Написать какой-нибудь майнкрафт в одиночку за неделю - это точно быстро. Поэтому сказать, что мы совсем не умеем оценивать, нельзя. Проблема в том, что мы просто делаем это очень плохо.
Не хочу долго мусолить методы сравнения, но из уважения к читателям укажу основные метрики, которые мы знаем:
- строчки кода
- сторипоинты
- тест-кейсы
- количество фич
- соотношение новой работы и остальной работы
- business value
- dora-метрики
- интуиция.
В частных случаях они все могут быть даже полезными, и это тема для отдельного поста, но в общем случае их нельзя использовать для измерения скорости команд.
Дурацкая импотенция
Вот эта вот скорость - это далеко не единственная штука, с которой у нас есть проблемы. Мы отвратительно оцениваем объём работ, плохо прикидываем business value той или иной фичи, ужасно справляемся с big upfront design, простите мне этот англицизм. И, если кто-то утверждает, что он все это умеет, то он или гений, или заблуждается, или просто врёт.
Про целеполагание
И во всей этой импотенции обязательно надо понимать: цель измерений-то какая?
Вот у вас есть быстрая команда, которая фигачит в два раза быстрее остальных. А толку, если она фигачит не туда? Это прям такая классика, когда 2/3 разработанных фич пользователями либо используются крайне редко, либо не используются вообще. Есть даже название такому софту: bloatware.
То же самое касается и оценки объёма работ. Вот вам дали ТЗ. Допустим, сами пользователи дали. Вы оценили: через год будет готово. Ну вот даже если вы прям угадали, и через год все готово. Вот даже если у вас супер быстрая команда, которая сделала это в 2 раза дешевле остальных. Ну вы все равно упираетесь в тот факт, что даже сами пользователи не знают, что им реально надо. И через год у них за пол стоимости есть функционал, 2/3 из которого можно было не делать.
Дежурный пинок водопада
Водопад, на самом деле, плохо работает не только и не столько потому, что мы не очень оцениваем на дальнюю перспективу, сильно ошибаемся при предварительном проектировании больших систем и откладываем все самые неприятные неожиданности на фазу тестирования. Все это, конечно же, в разы увеличивает расходы и ломает экономику большой доли проектов, которые отменяют спустя месяцы и годы разработки.
Но вот значительную часть оставшихся проектов, где выгода во много раз должна была бы превысить затраты, добивала ситуация, когда спустя десятки недель разработки пользователи получали совсем не то, что надо. Может быть, именно то, что они просили, но точно не то, что им было нужно.
К чему я это все?
Да к тому, что без качественной работы над скоупом все эти спекуляции про продуктивность, тесты, ДДД, рефакторинг, чистый код и т.п. - это все разговоры не туда, имитация бурной деятельности.
Для большинства команд самый быстрый способ ускориться в несколько раз - это перестать делать лишнюю работу. Необходимость работы над чем-то всегда нужно доказывать.
Куда копать дальше?
Три года назад, когда моя голова была забита всей этой экстремалкой, CD и прочим аджайлом, вот этот доклад для меня перевернул все. Gojko Adzic - самый главный амбассадор борьбы с работой не туда, поэтому рекомендую ознакомиться с его работами.
Эти же идеи транслирует и Эрик Райс в своём Lean Startup. У него есть одноимённая книга, но для быстрого ознакомления рекомендую вот этот доклад.
Ну и из всей горы экспертов, советов и методологий наиболее положительно, конечно, выделяется DORA со своими Accelerate и State of Devops. Эти просто померили, что влияет на успехи компании и предикторы этих успехов, а что - нет. Никаких вам умозрительных пальцесосаний, сухая конкретика.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤2
Саша Раковский
Про лапки 🥰 В статье по дизайну я упомянул design stamina hypothesis. Гипотезу, что у хорошего дизайна кривая стоимости изменений гораздо более плоская, чем у плохого. Простым языком: если код - говно, то менять его тупо дороже, простите меня за мой французский.…
Я любую нетривиальную фичу начинаю с написания "заметок по реализации" - неформального проектного решения.
И там первым разделом идёт "Что вообще происходит", в котором заполняется как обстоят дела сейчас, кого и чем это не устраивает, желаемое состояние дел и критерии оценки успеха проекта.
И очень часто даже у бизнеса нет убедительных ответов на эти вопросы, особенно на последний.
Но тем не менее, поиск ответов на эти вопросы я считаю очень полезным упражнением, которое команде стоит проделывать перед тем как тратить на какую-то фичу время.
И там первым разделом идёт "Что вообще происходит", в котором заполняется как обстоят дела сейчас, кого и чем это не устраивает, желаемое состояние дел и критерии оценки успеха проекта.
И очень часто даже у бизнеса нет убедительных ответов на эти вопросы, особенно на последний.
Но тем не менее, поиск ответов на эти вопросы я считаю очень полезным упражнением, которое команде стоит проделывать перед тем как тратить на какую-то фичу время.
👍5💯3
Привет!
С радостью представляю вам второго партнёра нашего исследования - Александр Кучук (Телеграм канал и Твиттер).
Ну и пользуясь случаем снова призываю вас заполнить анкету - пока что у нас только 26 анкет, надо хотя бы до 50 дотянуть
С радостью представляю вам второго партнёра нашего исследования - Александр Кучук (Телеграм канал и Твиттер).
Ну и пользуясь случаем снова призываю вас заполнить анкету - пока что у нас только 26 анкет, надо хотя бы до 50 дотянуть
Telegram
Блог Кучука
Простые мысли простого человека
❤3
Привет!
Представляю вам ещё одного партнёра нашего исследования - Александр Гранин.
Сашина поддержка для меня особенно ценна, так как он не просто уже написал две книги схожих по тематике и масштабу, той, которую пишу я - Functional Design and Architecture: Examples in Haskell и Проектирование на уровне типов. Системный взгляд на дизайн и архитектуру, но ещё и издал первую из них в Manning-е - одном из самых крутых издательств в сфере ИТ в мире.
Представляю вам ещё одного партнёра нашего исследования - Александр Гранин.
Сашина поддержка для меня особенно ценна, так как он не просто уже написал две книги схожих по тематике и масштабу, той, которую пишу я - Functional Design and Architecture: Examples in Haskell и Проектирование на уровне типов. Системный взгляд на дизайн и архитектуру, но ещё и издал первую из них в Manning-е - одном из самых крутых издательств в сфере ИТ в мире.
Inside a Black Hole
Lambda calculus meets creativity
🔥9
Привет!
Представляю вам ещё одного партнёра нашего исследования - канал 🦾 IT-Качалка Давида Шекунца 💪.
Давид, помимо рассказа о нашем исследовании, ещё и поучаствовал в бета-тесте анкеты, помог нам взглянуть на неё глазами Go/TypeScript-иста и существенно скорректировать наш перекос в Java.
Ну и пользуясь случаем ещё раз призываю вас заполнить анкету - до 50-ти мы уже дотянули, на данных всё ещё не хватает для того, чтобы делать статистически достоверные выводы.
Представляю вам ещё одного партнёра нашего исследования - канал 🦾 IT-Качалка Давида Шекунца 💪.
Давид, помимо рассказа о нашем исследовании, ещё и поучаствовал в бета-тесте анкеты, помог нам взглянуть на неё глазами Go/TypeScript-иста и существенно скорректировать наш перекос в Java.
Ну и пользуясь случаем ещё раз призываю вас заполнить анкету - до 50-ти мы уже дотянули, на данных всё ещё не хватает для того, чтобы делать статистически достоверные выводы.
Telegram
🦾 IT-Качалка Давида Шекунца 💪
Проектируем и разрабатываем HighLoad решения
С 🖤 от @davids_shek
С 🖤 от @davids_shek
Вы, полагаю, уже устали от этих постов. Но мясного материала пока нет - он весь варится.
А варится у меня следующее:
1. Я в #project_e собираюсь пилить новый небольший сервис на пару ресурсов и там хочу поставить пару экспериментов.
1.1 Во-первых, сделать пару прототипов на Spring MVC + Data JDBC и http4k + jooq и посмотреть какая будет разница по потреблению ресурсов (памяти в первую очередь). Об этом я точно напишу как минимум микропост. А если http4k/jooq уместятся хотя бы в половину памяти Спринга - скорее всего возьму их в прод и тогда там будет много инсайтов о жизни вне Спринга:)
1.2. Там же хочу поставить другой эксперимент - генерировать хттп-клиенты для тестов по Open API спеке. Надеюсь, что это мне даст:
1.2.1 Чистый код контроллеров и АПИ не ограниченные поддерживаемыми возможности генераторов по коду
1.2.2 Спеку отделённую от кода, так что её сможет саппортить аналитик
1.2.3 Гарантию актуальности спеки (за счёт контроля при сборке 100% покрытия кода контроллеров тестами)
1.2.4 Отсутствие кодогенерации кода контроллеров
2. В рамках пиара исследования, я собираюсь написать пару постов
2.1 Действительно ли SOLID повышает поддерживаемость? - по науке проанализировать имеющиеся анкеты на предмет того есть ли статестически достоверная (по ослабленному критерию достоверности) корреляция между применением принципов SOLID и оценкой проекта как поддерживаемого
2.2 Эргономичная архитектура тестов - актуализировать и нормально оформить старый микропост о том, как у меня устроены тесты
В общем, стей тюнед, будет интересно:)
А варится у меня следующее:
1. Я в #project_e собираюсь пилить новый небольший сервис на пару ресурсов и там хочу поставить пару экспериментов.
1.1 Во-первых, сделать пару прототипов на Spring MVC + Data JDBC и http4k + jooq и посмотреть какая будет разница по потреблению ресурсов (памяти в первую очередь). Об этом я точно напишу как минимум микропост. А если http4k/jooq уместятся хотя бы в половину памяти Спринга - скорее всего возьму их в прод и тогда там будет много инсайтов о жизни вне Спринга:)
1.2. Там же хочу поставить другой эксперимент - генерировать хттп-клиенты для тестов по Open API спеке. Надеюсь, что это мне даст:
1.2.1 Чистый код контроллеров и АПИ не ограниченные поддерживаемыми возможности генераторов по коду
1.2.2 Спеку отделённую от кода, так что её сможет саппортить аналитик
1.2.3 Гарантию актуальности спеки (за счёт контроля при сборке 100% покрытия кода контроллеров тестами)
1.2.4 Отсутствие кодогенерации кода контроллеров
2. В рамках пиара исследования, я собираюсь написать пару постов
2.1 Действительно ли SOLID повышает поддерживаемость? - по науке проанализировать имеющиеся анкеты на предмет того есть ли статестически достоверная (по ослабленному критерию достоверности) корреляция между применением принципов SOLID и оценкой проекта как поддерживаемого
2.2 Эргономичная архитектура тестов - актуализировать и нормально оформить старый микропост о том, как у меня устроены тесты
В общем, стей тюнед, будет интересно:)
Алексей Жидков
Тестирование Trainer Advisor: теория - Алексей Жидков
https://azhidkov.pro/
❤7👍5
Привет!
Молния!⚡️ ⚡️ ⚡️
В Postgres 18 готовят поддержку property graph query language! А в Oracle 23 она уже есть.
Пример
Источник примера
И дев-сборку можно уже руками потрогать.
Кажется, это наконец-то решит проблему выборки иерархичных данных (aka json-ов) из реляционных СУБД.
Молния!
В Postgres 18 готовят поддержку property graph query language! А в Oracle 23 она уже есть.
Пример
SELECT DISTINCT id, fof_parents, details
FROM GRAPH_TABLE(
characters
MATCH (a IS node WHERE a.name='Samwise Gamgee')-[x IS relationship WHERE x.type='friend']->
(b IS node)-[y IS relationship WHERE y.type='friend']->
(c IS node)<-[z IS relationship WHERE z.type='parent']-
(d IS node)
COLUMNS (d.id, d.name as fof_parents, d.details as details)
);
id | fof_parents | details
----+----------------+-----------------------
2 | Bilbo Baggins | {"species": "Hobbit"}
4 | Hamfast Gamgee | {"species": "Hobbit"}
7 | Arathorn | {"species": "Human"}
9 | Thranduil | {"species": "Elf"}
11 | Gloin | {"species": "Dwarf"}
Источник примера
И дев-сборку можно уже руками потрогать.
Кажется, это наконец-то решит проблему выборки иерархичных данных (aka json-ов) из реляционных СУБД.
Please open Telegram to view this post
VIEW IN TELEGRAM
Gavin Ray Blog
Experimenting with SQL:2023 Property-Graph Queries in Postgres 18
Hands-on guide to the upcoming SQL/PGQ graph syntax using a patched Postgres 18 beta.
👍5🔥5
Привет!
У меня на этой недели был леденящий душу опыт с хэппи эндом.
Я всю неделю активно девелопал новый сервис в Проекте Э и при этом активно экспериментировал с оптимизацией потребления РАМ и временем старта тестов.
И делал всё это вместе GPT-5 low reasoning через бесплатный план Windsurfa-а.
И он реально хорош. Он на порядок-два лучше GPT-4 и Sonnet-4. Практически не глючит и в 9 из 10 случаев быстрее меня решает WTF-ы со Спрингом. Например, у меня был value object в Sdj-модели с кастомным конвертером. И SDJ не мог найти конвертер. Я по привычке залез в кишки спринга и увидел, что конвертер доступен. Но не работает. Тут меня чёрт дёрнул спросить у гопатыча и он через минуту-две сказал, что я лупень и в модели импортнул не тот класс - у меня после экспериментов остался второй такой же класс в другом пакете. Мой опыт показывает, что я на такой фигне мог залипнуть на пару часов.
При решении другой проблемы, он в рассуждениях пошёл гуглить исходники спринга, нагуглил и выдал корректное решение.
Короче я напрягся и начал думать, что лавочку с ЭП пора прикрывать, потому как к тому времени когда я его закончу код будут писать только нейронки.
Однако сегодня я смог таки победить бездушную машину. В WTF-е с kover-ом. У меня была проблема с тем что конфиг на Kotlin DSL не компилялся. Тут я уже наоборот сходу пошёл к гопатычу и он начал глючить как не в себя. И не решил проблему. Тогда я сам вдумчиво прочитал сообщение об ошибке и решил проблему за минуту.
Плюс девелопать вайб-кодингом я с ним тоже попробовал. Вот это уже не особо понравилось. Код он генеряет в целом рабочий и сносный. Но делает это долго и хз чем самому в этот момент заниматься - на другую задачу не переключишься, т.к. за гопатычем следить надо на предмет хотя бы завершения. Ток котиков можно смотреть в этот момент.
Плюс код после него всё равно надо тщательно ревьювить и дорабатывать если не напильником, то мелкой наждачкой.
В общем у меня ощущение, что руками с автодополнением было бы точно не медленнее работать.
Но думать в направлении адаптации ЭП под нейронки - всё равно буду:) Соображения на этот счёт есть, но в другой раз напишу:)
В общем:
1. Для популярных фреймворков GPT 5 - нереально крут. Срочно пробуйте если ещё нет.
2. Но он всё ещё СЛАУ-переросток, не одупляет что он делает и в нестандартных случаях всё ещё бесполезен
#ai@ergonomic_code #project_e@ergonomic_code
У меня на этой недели был леденящий душу опыт с хэппи эндом.
Я всю неделю активно девелопал новый сервис в Проекте Э и при этом активно экспериментировал с оптимизацией потребления РАМ и временем старта тестов.
И делал всё это вместе GPT-5 low reasoning через бесплатный план Windsurfa-а.
И он реально хорош. Он на порядок-два лучше GPT-4 и Sonnet-4. Практически не глючит и в 9 из 10 случаев быстрее меня решает WTF-ы со Спрингом. Например, у меня был value object в Sdj-модели с кастомным конвертером. И SDJ не мог найти конвертер. Я по привычке залез в кишки спринга и увидел, что конвертер доступен. Но не работает. Тут меня чёрт дёрнул спросить у гопатыча и он через минуту-две сказал, что я лупень и в модели импортнул не тот класс - у меня после экспериментов остался второй такой же класс в другом пакете. Мой опыт показывает, что я на такой фигне мог залипнуть на пару часов.
При решении другой проблемы, он в рассуждениях пошёл гуглить исходники спринга, нагуглил и выдал корректное решение.
Короче я напрягся и начал думать, что лавочку с ЭП пора прикрывать, потому как к тому времени когда я его закончу код будут писать только нейронки.
Однако сегодня я смог таки победить бездушную машину. В WTF-е с kover-ом. У меня была проблема с тем что конфиг на Kotlin DSL не компилялся. Тут я уже наоборот сходу пошёл к гопатычу и он начал глючить как не в себя. И не решил проблему. Тогда я сам вдумчиво прочитал сообщение об ошибке и решил проблему за минуту.
Плюс девелопать вайб-кодингом я с ним тоже попробовал. Вот это уже не особо понравилось. Код он генеряет в целом рабочий и сносный. Но делает это долго и хз чем самому в этот момент заниматься - на другую задачу не переключишься, т.к. за гопатычем следить надо на предмет хотя бы завершения. Ток котиков можно смотреть в этот момент.
Плюс код после него всё равно надо тщательно ревьювить и дорабатывать если не напильником, то мелкой наждачкой.
В общем у меня ощущение, что руками с автодополнением было бы точно не медленнее работать.
Но думать в направлении адаптации ЭП под нейронки - всё равно буду:) Соображения на этот счёт есть, но в другой раз напишу:)
В общем:
1. Для популярных фреймворков GPT 5 - нереально крут. Срочно пробуйте если ещё нет.
2. Но он всё ещё СЛАУ-переросток, не одупляет что он делает и в нестандартных случаях всё ещё бесполезен
#ai@ergonomic_code #project_e@ergonomic_code
👍10❤4
Привет!
У меня в новом сервисе в Проекте Э на Spring Boot 3.5 новый рекорд скорости тестов:)
54 кейса за 2.7 секунды, 90% тестов - < 60мс, медиана - 14мс.
Сетап:
1. инфра (PostgreSQL и Minio на RAM-диске) запускается руками по кнопке в Идее docker compose-ом.
2. Отказ от компонент скана бинов
3. Отказ от скана авто-конфигов
4. ленивая иницилазиация бинов (spring.main.lazy-initialization)
5. Работа через WebTestClient с MockMvc
Не 5мс на кейс, как у Саши Раковского, конечно, но уже близко и это полный набор тестов, после которого можно деплоить в прод:)
#ergo_testing@ergonomic_code #project_e@ergonomic_code #spring_boot@ergonomic_code
У меня в новом сервисе в Проекте Э на Spring Boot 3.5 новый рекорд скорости тестов:)
54 кейса за 2.7 секунды, 90% тестов - < 60мс, медиана - 14мс.
Сетап:
1. инфра (PostgreSQL и Minio на RAM-диске) запускается руками по кнопке в Идее docker compose-ом.
2. Отказ от компонент скана бинов
3. Отказ от скана авто-конфигов
4. ленивая иницилазиация бинов (spring.main.lazy-initialization)
5. Работа через WebTestClient с MockMvc
Не 5мс на кейс, как у Саши Раковского, конечно, но уже близко и это полный набор тестов, после которого можно деплоить в прод:)
#ergo_testing@ergonomic_code #project_e@ergonomic_code #spring_boot@ergonomic_code
🔥8👍7
Привет!
Обещанный микропост про эксперимент с http4k.
Напомню контекст - мне недавно понадобилось сделать в Проекте Э новый небольшой сервис и у нас довольно сильно ограничена RAM на стендах, поэтому я решил поэксперементировать с http4k +jooq jdbi с целью сократить потреблением RAM.
Изначально я написал прототип на Spring Boot 3.5 (MVC + Data JDBC) буквально с парой методов - создание сущности на 3 поля плюс файла (в минио) и получение файла.
Далее методика всех измерений была следующая:
1. запустить сервис
2. curl-запросами создать сущность и получить картинку
3. померить ps-ом RSS процесса.
И для чистого Spring Boot я получил 270mb.
Тогда я написал прототип на http4k + jdbi и для него получил 236mb. В целом на этом можно было бы и закончить эксперимент, т.к. экономия была несущественная, зато с http4k пришлось бы руками писать аутентификацию, rbac, управление транзакциями, кэширование, да ещё и запросы на доменные модели руками мапить.
Но я не закончил и накопал ещё пару любопытных штук.
Первым делом я пошёл к гопатычу и спросил какой стэк под JVM дал бы большую экономию по памяти. Он накидал несколько вариантов, среди которых обещал ~150mb RAM для Micronaut. Я спросил за счёт чего Micronaut экономит память. Он сказал - за счёт Netty.
Я думаю ну ладно, в http4k переехать на Netty - дело пары строк.
И переехал. И получил 156mb RAM.
А заодно ещё и дикий WTF - у http4k API обработчиков запросов - синхронное. И нет ручки, чтобы настроить Netty на виртуальные потоки. То есть из коробки Netty в http4k - это фикция.
Пока разбирался как таки примострячить виртуальные потоки в http4k/Netty залез в исходники и нашёл там коммент с "элегантым" решением этой проблемы:
Ну т.е. хотите чтобы Нетти норм работал - копипастьте код либы и делайте с ним что хотите🤦♂️ О каких 99% юзкейсах они говорят - вообще не представляю.
В общем поматерился я на хттп4к и подумал, что Spring Boot же тоже может в Netty. И там вроде как даже не обязательно делать контроллеры на Reactor-е или корутинах - вроде как можно писать обычные контроллеры и настроить (вот это ничего себе!) тредпул на котором Спринг будет их дёргать.
Сказано-сделано, минут за 15-30 переехал на WebFlux, барабанная дробь... 245mb... Тут у меня бюджет на эксперименты начал уже заканчиваться, поэтому я решил, что дело количества зависимостей, которые тащит с собой WebFlux и пошёл дальше.
А дальше я решил дать ещё один шанс Spring Boot Native. Как и в прошлый раз пришлось повоевать с рефлекшеном, но на этот раз со мной был GPT-5 и эти проблемы он щёлкал на раз-два, поэтому ещё минут через 30 я получил цифры для нативной сборки - 157mb. Неплохо.
Однако пока копался с Нативом, я наткнулся на Spring Boot Ahead-of-Time Processing, который должен был дать оптимизацию времени запуска и потребления RAM без 3 минут компиляции и сюрпризов в рантайме Нативной сборки. И он в целом дал - 234mb RAM.
Итого вышли такие цифры:
1. Spring Boot + Tomcat - 270mb
2. http4k + Jetty - 236mb
3. http4k + Netty - 156mb
4. Spring Boot + Netty - 245mb
3. Spring Boot Native + Tomcat - 157mb
4. Spring Boot AOT Processing + Tomcat - 234mb
Помедитировав на них я решил, что переход на http4k того не стоит и снова остался на Spring Boot. Не люблю его за монструозность и количество автомагии но для меня сейчас он всё ещё остаётся наименьшим из зол.
#spring_boot@ergonomic_code #project_e@ergonomic_code
Обещанный микропост про эксперимент с http4k.
Напомню контекст - мне недавно понадобилось сделать в Проекте Э новый небольшой сервис и у нас довольно сильно ограничена RAM на стендах, поэтому я решил поэксперементировать с http4k +
Изначально я написал прототип на Spring Boot 3.5 (MVC + Data JDBC) буквально с парой методов - создание сущности на 3 поля плюс файла (в минио) и получение файла.
Далее методика всех измерений была следующая:
1. запустить сервис
2. curl-запросами создать сущность и получить картинку
3. померить ps-ом RSS процесса.
И для чистого Spring Boot я получил 270mb.
Тогда я написал прототип на http4k + jdbi и для него получил 236mb. В целом на этом можно было бы и закончить эксперимент, т.к. экономия была несущественная, зато с http4k пришлось бы руками писать аутентификацию, rbac, управление транзакциями, кэширование, да ещё и запросы на доменные модели руками мапить.
Но я не закончил и накопал ещё пару любопытных штук.
Первым делом я пошёл к гопатычу и спросил какой стэк под JVM дал бы большую экономию по памяти. Он накидал несколько вариантов, среди которых обещал ~150mb RAM для Micronaut. Я спросил за счёт чего Micronaut экономит память. Он сказал - за счёт Netty.
Я думаю ну ладно, в http4k переехать на Netty - дело пары строк.
И переехал. И получил 156mb RAM.
А заодно ещё и дикий WTF - у http4k API обработчиков запросов - синхронное. И нет ручки, чтобы настроить Netty на виртуальные потоки. То есть из коробки Netty в http4k - это фикция.
Пока разбирался как таки примострячить виртуальные потоки в http4k/Netty залез в исходники и нашёл там коммент с "элегантым" решением этой проблемы:
Stock version of an Netty Server. Not that if you want to configure your own server instance you
can duplicate this code and modify it as required. We are purposefully trying to limit options
here to keep the API simple for the 99% of use-cases.
Ну т.е. хотите чтобы Нетти норм работал - копипастьте код либы и делайте с ним что хотите
В общем поматерился я на хттп4к и подумал, что Spring Boot же тоже может в Netty. И там вроде как даже не обязательно делать контроллеры на Reactor-е или корутинах - вроде как можно писать обычные контроллеры и настроить (вот это ничего себе!) тредпул на котором Спринг будет их дёргать.
Сказано-сделано, минут за 15-30 переехал на WebFlux, барабанная дробь... 245mb... Тут у меня бюджет на эксперименты начал уже заканчиваться, поэтому я решил, что дело количества зависимостей, которые тащит с собой WebFlux и пошёл дальше.
А дальше я решил дать ещё один шанс Spring Boot Native. Как и в прошлый раз пришлось повоевать с рефлекшеном, но на этот раз со мной был GPT-5 и эти проблемы он щёлкал на раз-два, поэтому ещё минут через 30 я получил цифры для нативной сборки - 157mb. Неплохо.
Однако пока копался с Нативом, я наткнулся на Spring Boot Ahead-of-Time Processing, который должен был дать оптимизацию времени запуска и потребления RAM без 3 минут компиляции и сюрпризов в рантайме Нативной сборки. И он в целом дал - 234mb RAM.
Итого вышли такие цифры:
1. Spring Boot + Tomcat - 270mb
2. http4k + Jetty - 236mb
3. http4k + Netty - 156mb
4. Spring Boot + Netty - 245mb
3. Spring Boot Native + Tomcat - 157mb
4. Spring Boot AOT Processing + Tomcat - 234mb
Помедитировав на них я решил, что переход на http4k того не стоит и снова остался на Spring Boot. Не люблю его за монструозность и количество автомагии но для меня сейчас он всё ещё остаётся наименьшим из зол.
#spring_boot@ergonomic_code #project_e@ergonomic_code
Please open Telegram to view this post
VIEW IN TELEGRAM
👏7👍6🔥5❤4
Привет!
Довольно существенно дополнил, отполировал и актуализировал разделы "Проекция структуры компонентов" и "Раскладка кода по пакетам" из статьи об Эргономичной архитектуре.
И даже наконец добавил пару первых картинок:)
#ergo_arch@ergonomic_code
Довольно существенно дополнил, отполировал и актуализировал разделы "Проекция структуры компонентов" и "Раскладка кода по пакетам" из статьи об Эргономичной архитектуре.
И даже наконец добавил пару первых картинок:)
#ergo_arch@ergonomic_code
Эргономичный подход
Эргономичная архитектура (v3.0.0)
Текущая версия статьи написана в режиме потока сознания и пока что я не проводил даже проверки правописания, не говоря уж о том, чтобы сопроводить идеи иллюстрациями и кодом.
Предыдущие черновики и диаграммы здесь.
Введение (todo: ссылка)
В своей книге The…
Предыдущие черновики и диаграммы здесь.
Введение (todo: ссылка)
В своей книге The…
1🔥7
Привет!
Поучительная история о важности именования.
У меня тут джуны недавно в Проекте Э запилили пуши.
И пока ревьювил бэк я там наткнулся на строчку с дип линкой (в которых я не шарю) "myapp://<some-screen>", которая отправляется в МП.
И она мне сразу не понравилась из-за myapp. Фик знает почему myapp - плохо.
Попахивает дилетантством, небрежностью и копипастой со стековерфлоу.
И вроде как непонятно что она значит. Ну т.е. понятно, конечно - моё приложение. Но кто это писал? Чьё это приложение?
И тут вроде тоже, и мне, и любому читателю этого кода с вероятностью 99% будет очевидно, кто это писал и чьё это приложение.
Но всё равно с этим именем "что-то не то".
В общем я был уверен, что это имя херовое, но сам убедительных (для себя) аргументов не придумал и пошёл гуглить рекомендации по формированию диплинок.
И нагуглил, что кастомные схемы в диплинках - это дыра в безопасности в виде Deep Link Collision.
Из-за неё кто угодно может подписаться на наши диплинки. На андроиде в этом случае откроется диалог с вопросом в какое приложение перейти - наше или чужое (как вариант - с таким же именем и иконкой), а на иосе - вообще "If multiple apps register the same scheme, the app the system targets is undefined" 🤯
И это далеко не первый раз когда я на ревью начинаю докапываться до имени, а в итоге выхожу на серьёзный баг или проблему в архитектуре или просто нахожу лучшее решение, сформулированное в корректных терминах.
В общем мой совет: внимательно следите за именами в коде, кривые имена очень часто свидетельствуют о кривом коде.
На самом деле я считаю, что вопреки расхожему мнению, для разработчика [бакенда [информационных систем]] важнее умение хорошо писать на русском, чем "знать математику". Так что заводите свои блоги и каналы, чтобы практиковаться в письме и не делегируйте письмо ЛЛМкам:)
Если заведёте - пишите, напишу об этом в этом канале :)
#project_e@ergonomic_code
Поучительная история о важности именования.
У меня тут джуны недавно в Проекте Э запилили пуши.
И пока ревьювил бэк я там наткнулся на строчку с дип линкой (в которых я не шарю) "myapp://<some-screen>", которая отправляется в МП.
И она мне сразу не понравилась из-за myapp. Фик знает почему myapp - плохо.
Попахивает дилетантством, небрежностью и копипастой со стековерфлоу.
И вроде как непонятно что она значит. Ну т.е. понятно, конечно - моё приложение. Но кто это писал? Чьё это приложение?
И тут вроде тоже, и мне, и любому читателю этого кода с вероятностью 99% будет очевидно, кто это писал и чьё это приложение.
Но всё равно с этим именем "что-то не то".
В общем я был уверен, что это имя херовое, но сам убедительных (для себя) аргументов не придумал и пошёл гуглить рекомендации по формированию диплинок.
И нагуглил, что кастомные схемы в диплинках - это дыра в безопасности в виде Deep Link Collision.
Из-за неё кто угодно может подписаться на наши диплинки. На андроиде в этом случае откроется диалог с вопросом в какое приложение перейти - наше или чужое (как вариант - с таким же именем и иконкой), а на иосе - вообще "If multiple apps register the same scheme, the app the system targets is undefined" 🤯
И это далеко не первый раз когда я на ревью начинаю докапываться до имени, а в итоге выхожу на серьёзный баг или проблему в архитектуре или просто нахожу лучшее решение, сформулированное в корректных терминах.
В общем мой совет: внимательно следите за именами в коде, кривые имена очень часто свидетельствуют о кривом коде.
На самом деле я считаю, что вопреки расхожему мнению, для разработчика [бакенда [информационных систем]] важнее умение хорошо писать на русском, чем "знать математику". Так что заводите свои блоги и каналы, чтобы практиковаться в письме и не делегируйте письмо ЛЛМкам:)
Если заведёте - пишите, напишу об этом в этом канале :)
#project_e@ergonomic_code
Apple Developer Documentation
Defining a custom URL scheme for your app | Apple Developer Documentation
Use specially formatted URLs to link to content within your app.
👍16💯3❤2