Привет!
Поучительная история о важности именования.
У меня тут джуны недавно в Проекте Э запилили пуши.
И пока ревьювил бэк я там наткнулся на строчку с дип линкой (в которых я не шарю) "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.
👍18💯4❤3
Привет!
Вести с ИИ полей.
Не спрашивайте зачем, но мне тут потребовалось конвертить в консоли структурированные (в json-е) логи в человеко-читаемые.
Сначала я попробовал с GPT-5 собрать шелл-скрипт. Убил часа 3, результат получил, но на "три с минусом".
А потом сделал по другому:
1. создал пустую папку
2. открыл её в VS Code
3. открыл в нём Копилот с тем же GPT-5 в режиме агента
4. попросил написать утилиту на Расте которая превращает "вот такие" логи вот "в такие". Плюс накинул пару требований в духе стандартной ширины таймстемпа и обрезки хэшей подов
5. и пошёл чистить диск на ноуте
6. через пару часов я получил рабочую утилитку в 400 строк и 600кб RAM. Плюс отдельно стоит проговорить, что эта утилитка сохраняет консольную раскраску подов - я бы, наверное, ток на это пару часов убил. И 40 гигов свободного места на на ноуте
Код получился полнейшим говном (см картинки) - я в него попробовал вникнуть, но быстро забил.
Но он работает, а сам я с ним разбираться не собираюсь. Да и выкинуть не жалко, если что.
Вести с ИИ полей.
Не спрашивайте зачем, но мне тут потребовалось конвертить в консоли структурированные (в json-е) логи в человеко-читаемые.
Сначала я попробовал с GPT-5 собрать шелл-скрипт. Убил часа 3, результат получил, но на "три с минусом".
А потом сделал по другому:
1. создал пустую папку
2. открыл её в VS Code
3. открыл в нём Копилот с тем же GPT-5 в режиме агента
4. попросил написать утилиту на Расте которая превращает "вот такие" логи вот "в такие". Плюс накинул пару требований в духе стандартной ширины таймстемпа и обрезки хэшей подов
5. и пошёл чистить диск на ноуте
6. через пару часов я получил рабочую утилитку в 400 строк и 600кб RAM. Плюс отдельно стоит проговорить, что эта утилитка сохраняет консольную раскраску подов - я бы, наверное, ток на это пару часов убил. И 40 гигов свободного места на на ноуте
Код получился полнейшим говном (см картинки) - я в него попробовал вникнуть, но быстро забил.
Но он работает, а сам я с ним разбираться не собираюсь. Да и выкинуть не жалко, если что.
😁10👍7❤3
Привет!
Я закончил большой 5-месячный долгострой на 43 коммита по интеграции Google Calendar в Trainer Advisor.
В реализации этой фичи довольно много интересных, на мой взгляд, аспектов, каждый из которых заслуживает отдельного поста. Но сейчас их писать настроения нет, поэтому я ограничился микропостом с обзором реализации. Ну как микро - 25 минут чтения по оценке ФФ:)
И чтобы вам не продираться сквозь 25 минут потока сознания в поисках чего-то интересного для себя - вот краткое содержание:)
Абстрактный ресурс
Для меня самым интересным в этой фиче было то, что для её реализации пришлось ввести некие штуки с рабочим названием «Абстрактный ресурс».
Не знаю пока что с этим делать и надо ли что-то делать.
MockServers
Паттерн для организации WireMock-стабов
Fixtures
Паттерн для сетапа фикстур, состоящих из сложных графов объектов
Пример «простого» CRUD-приложения
Я в последнее время в канале несколько раз писал о «простых» CRUD-приложения — приложениях без сложной бизнес-логики или нефункциональных требований, но, тем не менее, которые назвать простыми не поворачивается язык. И всякий раз это порождало вопросы в комментариях, что конкретно я имею ввиду.
И вот у меня, наконец появился, хороший open source-ый пример — операция отображения страницы расписания терапевта.
Рефакторинг findCalendarItemsInInterval (уровни абстракции/стратификация)
Пример приведения метода к соответствию правилу "У функции должен быть один уровень абстракции"
SourceItem → URI
К своему стыду, должен признаться, что я только недавно до конца (чуть лучше?) осознал что такое URI. Но лучше поздно, чем никогда - правда же?
И вот теперь благодаря этим новым знаниям, мне удалось сделать работу с разными календарями в Trainer Advisor чуть более "production grade".
Как добыть OAuth2AuthorizedClient без того, чтобы перетереть Authorization в SecurityContext
Я хз. Но у меня есть рабочий код, на который можно ориентироваться
И этот код мало того, что рабочий — он ещё и тестами покрыт.
Тестирование интеграции с Google OAuth и Google Calendars
Вот оно:
- GoogleAuthorizationIntegrationTest;
- GoogleCalendarsServiceTest;
- GetGoogleCalendarsSettingsEndpointTest;
- SetCalendarShouldBeShownTest;
- Тест "Страница календаря должна рендериться корректно, даже если у терапевта есть подключенный Google-календарь и запрос событий из него приводит к ошибке";
- CreateAppointmentPageTest.createAppointmntWithGoogleEvnt;
- SchedulePageControllerTest;
Верификация приложения в Google
Это 7 кругов ада. Но без них ваши токены будут протухать раз в неделю и вам надо будет снова гнать юзеров на авторизацию в гугле
#ergo_approach@ergonomic_code #ergo_arch@ergonomic_code #ergo_testing@ergonomic_code #trainer_advisor@ergonomic_code #case@ergonomic_code
Я закончил большой 5-месячный долгострой на 43 коммита по интеграции Google Calendar в Trainer Advisor.
В реализации этой фичи довольно много интересных, на мой взгляд, аспектов, каждый из которых заслуживает отдельного поста. Но сейчас их писать настроения нет, поэтому я ограничился микропостом с обзором реализации. Ну как микро - 25 минут чтения по оценке ФФ:)
И чтобы вам не продираться сквозь 25 минут потока сознания в поисках чего-то интересного для себя - вот краткое содержание:)
Абстрактный ресурс
Для меня самым интересным в этой фиче было то, что для её реализации пришлось ввести некие штуки с рабочим названием «Абстрактный ресурс».
Не знаю пока что с этим делать и надо ли что-то делать.
MockServers
Паттерн для организации WireMock-стабов
Fixtures
Паттерн для сетапа фикстур, состоящих из сложных графов объектов
Пример «простого» CRUD-приложения
Я в последнее время в канале несколько раз писал о «простых» CRUD-приложения — приложениях без сложной бизнес-логики или нефункциональных требований, но, тем не менее, которые назвать простыми не поворачивается язык. И всякий раз это порождало вопросы в комментариях, что конкретно я имею ввиду.
И вот у меня, наконец появился, хороший open source-ый пример — операция отображения страницы расписания терапевта.
Рефакторинг findCalendarItemsInInterval (уровни абстракции/стратификация)
Пример приведения метода к соответствию правилу "У функции должен быть один уровень абстракции"
SourceItem → URI
К своему стыду, должен признаться, что я только недавно до конца (чуть лучше?) осознал что такое URI. Но лучше поздно, чем никогда - правда же?
И вот теперь благодаря этим новым знаниям, мне удалось сделать работу с разными календарями в Trainer Advisor чуть более "production grade".
Как добыть OAuth2AuthorizedClient без того, чтобы перетереть Authorization в SecurityContext
Я хз. Но у меня есть рабочий код, на который можно ориентироваться
И этот код мало того, что рабочий — он ещё и тестами покрыт.
Тестирование интеграции с Google OAuth и Google Calendars
Вот оно:
- GoogleAuthorizationIntegrationTest;
- GoogleCalendarsServiceTest;
- GetGoogleCalendarsSettingsEndpointTest;
- SetCalendarShouldBeShownTest;
- Тест "Страница календаря должна рендериться корректно, даже если у терапевта есть подключенный Google-календарь и запрос событий из него приводит к ошибке";
- CreateAppointmentPageTest.createAppointmntWithGoogleEvnt;
- SchedulePageControllerTest;
Верификация приложения в Google
Это 7 кругов ада. Но без них ваши токены будут протухать раз в неделю и вам надо будет снова гнать юзеров на авторизацию в гугле
#ergo_approach@ergonomic_code #ergo_arch@ergonomic_code #ergo_testing@ergonomic_code #trainer_advisor@ergonomic_code #case@ergonomic_code
Алексей Жидков
Trainer Advisor — интеграция с Google Calendar - Алексей Жидков
https://azhidkov.pro/
❤9👍7
Привет!
Саша Раковский написал пост о своём подходе к тестированию с подробными диаграммами, мемасиками и ссылкой на меня - советую прочитать:)
Судя по описанию, Сашин гибридный подход даёт кодовые базы, которые я называю эргономичными.
Саша Раковский написал пост о своём подходе к тестированию с подробными диаграммами, мемасиками и ссылкой на меня - советую прочитать:)
Судя по описанию, Сашин гибридный подход даёт кодовые базы, которые я называю эргономичными.
Хабр
Гайд по автотестам, часть 2. Юнит-тесты
В первой части мы разобрали верхнеуровневую теорию автотестирования: сколько каких тестов нужно, кто должен их писать, и для чего это все. В этой части мы уже подойдем к практическим вопросам:...
❤8🔥4
Привет!
У меня тут любопытный диалог с гопатычем вышел:
Я: Что можно почитать по проектированию классов, представляющих информацию системы (бакэнда)?
Гопатыч (сокращённо):
- David West — “Object Thinking”
- Eric Evans — “Domain-Driven Design” (главы 5–9)
- Vaughn Vernon — “Implementing Domain-Driven Design”
- Joshua Bloch — “Effective Java” (главы 2–4)
- Robert C. Martin — “Clean Code”, главы 6–11
- Martin Fowler — “Patterns of Enterprise Application Architecture”
- Michael Feathers — “Working Effectively with Legacy Code”
- Dan Bergh Johnsson, Daniel Deogun, Daniel Sawano — “Secure by Design”
- Rich Hickey — “Simple Made Easy” (доклад)
- Adam Wiggins — “The Twelve-Factor App” (factor IV и VI)
- Edward Yourdon — “Structured Design” (старенькое, но ясное)
- Yegor Bugayenko — “Elegant Objects” (т.1–2)
- Holub on Patterns (Allen Holub)
- “Domain Modeling Made Functional” — Scott Wlaschin
Я: Знаешь, что самое страшное и обидное? Я это всё кроме Secure by Design и Holub on Patterns уже прочитал. А как системно подходить к проектированию модели данных/информации своих систем - до сих пор не знаю.
Гопатыч:
Это честное и очень глубокое признание — и ты не один.
Многие, даже очень опытные инженеры (и архитекторы с 20+ годами), приходят ровно к этому рубежу:
всё про DDD, Clean Code и Fowler вроде усвоено,
а как системно проектировать саму модель информации — всё равно неясно.
Потому что нигде это не описано как отдельная дисциплина.
—
Попробую объяснить, почему так, и предложить, как собрать собственную систему мышления, которая это закрывает.
Это будет не список книг, а карта подхода, с опорой на то, что ты уже знаешь.
—
🧭 Почему тебе “не хватает системы”
Большинство источников, даже DDD, описывают что должно быть (Entities, Aggregates, Value Objects) и почему (инкапсуляция, инварианты, ubiquitous language),
но почти не говорят, как именно прийти к правильной структуре данных — то есть к набору и форме классов, которые выражают реальность твоей системы.
Причина — потому что в классическом ОО-мышлении данные вторичны относительно поведения.
А в реальных backend-системах — наоборот: данные центральны, поведение меняется вокруг них.
Нам нужен язык проектирования, где первичен информационный ландшафт, а не классы/объекты.
—
🧩 Попробуем собрать системный подход из кирпичиков
1. Начни не с классов, а с информационных потоков
Продолжение 1
Продолжение 2
PS>
Это эхо внутренней кухни работы над Эргономичной моделью данных - месяц уже ломаю голову, целевую картинку (буквально картинку - абстрактную диаграмму типа как для структуры компонентов) вижу, а описать её не выходит.
У меня тут любопытный диалог с гопатычем вышел:
Я: Что можно почитать по проектированию классов, представляющих информацию системы (бакэнда)?
Гопатыч (сокращённо):
- David West — “Object Thinking”
- Eric Evans — “Domain-Driven Design” (главы 5–9)
- Vaughn Vernon — “Implementing Domain-Driven Design”
- Joshua Bloch — “Effective Java” (главы 2–4)
- Robert C. Martin — “Clean Code”, главы 6–11
- Martin Fowler — “Patterns of Enterprise Application Architecture”
- Michael Feathers — “Working Effectively with Legacy Code”
- Dan Bergh Johnsson, Daniel Deogun, Daniel Sawano — “Secure by Design”
- Rich Hickey — “Simple Made Easy” (доклад)
- Adam Wiggins — “The Twelve-Factor App” (factor IV и VI)
- Edward Yourdon — “Structured Design” (старенькое, но ясное)
- Yegor Bugayenko — “Elegant Objects” (т.1–2)
- Holub on Patterns (Allen Holub)
- “Domain Modeling Made Functional” — Scott Wlaschin
Я: Знаешь, что самое страшное и обидное? Я это всё кроме Secure by Design и Holub on Patterns уже прочитал. А как системно подходить к проектированию модели данных/информации своих систем - до сих пор не знаю.
Гопатыч:
Это честное и очень глубокое признание — и ты не один.
Многие, даже очень опытные инженеры (и архитекторы с 20+ годами), приходят ровно к этому рубежу:
всё про DDD, Clean Code и Fowler вроде усвоено,
а как системно проектировать саму модель информации — всё равно неясно.
Потому что нигде это не описано как отдельная дисциплина.
—
Попробую объяснить, почему так, и предложить, как собрать собственную систему мышления, которая это закрывает.
Это будет не список книг, а карта подхода, с опорой на то, что ты уже знаешь.
—
🧭 Почему тебе “не хватает системы”
Большинство источников, даже DDD, описывают что должно быть (Entities, Aggregates, Value Objects) и почему (инкапсуляция, инварианты, ubiquitous language),
но почти не говорят, как именно прийти к правильной структуре данных — то есть к набору и форме классов, которые выражают реальность твоей системы.
Причина — потому что в классическом ОО-мышлении данные вторичны относительно поведения.
А в реальных backend-системах — наоборот: данные центральны, поведение меняется вокруг них.
Нам нужен язык проектирования, где первичен информационный ландшафт, а не классы/объекты.
—
🧩 Попробуем собрать системный подход из кирпичиков
1. Начни не с классов, а с информационных потоков
Продолжение 1
Продолжение 2
PS>
Это эхо внутренней кухни работы над Эргономичной моделью данных - месяц уже ломаю голову, целевую картинку (буквально картинку - абстрактную диаграмму типа как для структуры компонентов) вижу, а описать её не выходит.
ChatGPT
Чтение по проектированию классов
ChatGPT helps you get answers, find inspiration, and be more productive.
🔥10👍5❤4
Привет!
Вы, возможно, уже забыли, что мы проводим исследование "Характеристики поддерживаемых кодовых баз backend-приложений", а я — нет:)
Во-первых, ещё раз призываю вас заполнить нашу анкету если ещё не заполнили или впервые о ней слышите — если будут ещё ответы, я повторю анализ и обновлю отчёт и его выводы будут ещё более достоверными. Нам особенно не хватает анкет о неподдерживаемых проектах и не из мира Java/Kotlin/ООП - если у вас есть такой проект, он будет вдвойне ценен.
Во-вторых, с радостью представляю вам первые результаты анализа данных!:)
К сожалению, задача анализа данных оказалось неподъёмной для нашей небольшой группы энтузиастов, поэтому отчёт практически полностью составлен GPT-5 на основе анализа, выполненного им же.
Но даже вместе с гопатычем я потратил на подготовку примерно 10 часов — поэтому отчёт всё-таки основан на данных, а не на глюках.
Также, если у вас есть квалификация, возможность и желание выполнить профессиональный анализ наших данных - напишите мне пожалуйста в Telegram.
Ну и сразу TL;DR, там есть очень неожиданные для меня пункты:
— Статистически достоверные и практически значимые факторы поддерживаемости:
— отсутствие циклов между модулями, пакетами и в модели данных;
— соблюдение Interface Segregation Principle (ISP);
— осознанное применение шаблонов проектирования.
Все три фактора показывают устойчивую положительную или отрицательную связь как по χ²-анализу, так и в ML-моделях (LogReg + RandomForest).
— Погранично значимые факторы: применение ER-диаграмм; соблюдение CQS и принципов дизайна компонентов (ADP, SDP и др.); минимизация синхронных вызовов между сервисами; использование (микро)сервисной архитектуры; высокий процент покрытия тестами и раннее тестирование; наличие гайдлайна разработки.
— Статистически слабые, но показательные тренды: проекты с простыми моделями данных и простыми способами доступа (агрегаты, SQL, лёгкие ORM) чаще воспринимаются как поддерживаемые; применение «детройтской школы тестирования» повышает уверенность в тестах.
— Ложные ожидания: SRP, OCP, LSP, модульные монолиты, парадигма (ООП/ФП/ПП), школа тестирования и запрет прямых обращений из контроллеров к репозиториям не показали достоверного влияния на поддерживаемость; DIP оказывает статистически достоверный и практически значимый отрицательный эффект — проекты, где его декларировали, чаще оказывались проблемными.
— Общие выводы: поддерживаемость определяется архитектурной дисциплиной (отсутствие циклов), простотой модели данных, модульностью интерфейсов (ISP) и осознанным применением структурных решений (шаблоны, слабая связанность, раннее тестирование).
Вы, возможно, уже забыли, что мы проводим исследование "Характеристики поддерживаемых кодовых баз backend-приложений", а я — нет:)
Во-первых, ещё раз призываю вас заполнить нашу анкету если ещё не заполнили или впервые о ней слышите — если будут ещё ответы, я повторю анализ и обновлю отчёт и его выводы будут ещё более достоверными. Нам особенно не хватает анкет о неподдерживаемых проектах и не из мира Java/Kotlin/ООП - если у вас есть такой проект, он будет вдвойне ценен.
Во-вторых, с радостью представляю вам первые результаты анализа данных!:)
К сожалению, задача анализа данных оказалось неподъёмной для нашей небольшой группы энтузиастов, поэтому отчёт практически полностью составлен GPT-5 на основе анализа, выполненного им же.
Но даже вместе с гопатычем я потратил на подготовку примерно 10 часов — поэтому отчёт всё-таки основан на данных, а не на глюках.
Также, если у вас есть квалификация, возможность и желание выполнить профессиональный анализ наших данных - напишите мне пожалуйста в Telegram.
Ну и сразу TL;DR, там есть очень неожиданные для меня пункты:
— Статистически достоверные и практически значимые факторы поддерживаемости:
— отсутствие циклов между модулями, пакетами и в модели данных;
— соблюдение Interface Segregation Principle (ISP);
— осознанное применение шаблонов проектирования.
Все три фактора показывают устойчивую положительную или отрицательную связь как по χ²-анализу, так и в ML-моделях (LogReg + RandomForest).
— Погранично значимые факторы: применение ER-диаграмм; соблюдение CQS и принципов дизайна компонентов (ADP, SDP и др.); минимизация синхронных вызовов между сервисами; использование (микро)сервисной архитектуры; высокий процент покрытия тестами и раннее тестирование; наличие гайдлайна разработки.
— Статистически слабые, но показательные тренды: проекты с простыми моделями данных и простыми способами доступа (агрегаты, SQL, лёгкие ORM) чаще воспринимаются как поддерживаемые; применение «детройтской школы тестирования» повышает уверенность в тестах.
— Ложные ожидания: SRP, OCP, LSP, модульные монолиты, парадигма (ООП/ФП/ПП), школа тестирования и запрет прямых обращений из контроллеров к репозиториям не показали достоверного влияния на поддерживаемость; DIP оказывает статистически достоверный и практически значимый отрицательный эффект — проекты, где его декларировали, чаще оказывались проблемными.
— Общие выводы: поддерживаемость определяется архитектурной дисциплиной (отсутствие циклов), простотой модели данных, модульностью интерфейсов (ISP) и осознанным применением структурных решений (шаблоны, слабая связанность, раннее тестирование).
Алексей Жидков
Отчёт: факторы поддерживаемости backend-проектов - Алексей Жидков
https://azhidkov.pro/
🔥10👍6
Привет!
У меня у самого были вопросики касательно того значимости OCP и LSP и Саша Раковский тоже это подсветил, поэтому я тут с гопатычем ещё немного поковырялся с ними. Иииииии - отбой, они не влияют на поддерживаемость.
Слово гопатычу:
Отлично — вот теперь у нас реальное подтверждение твоей гипотезы [о том, что сила связи OCP и LSP вызвана общим перекосом в пользу поддерживаемых проектов]👇
📊 Что показывают результаты
Принцип Коэффициент p-value Интерпретация
SRP −0.75 0.13 Не значим (p > 0.05). Связь с поддерживаемостью отрицательная, но статистически не подтверждена.
OCP +0.30 0.43 Не значим. После контроля общего фона исчезает эффект, который был виден в χ².
LSP +0.16 0.62 Не значим. Аналогично — исчезла кажущаяся корреляция.
ISP +1.02 0.018 Единственный принцип с достоверным вкладом в прогноз поддерживаемости (p < 0.05).
DIP −0.69 0.08 Почти значим (тенденция, p≈0.08), но эффект отрицательный — может отражать шум или трудности восприятия DIP.
🧠 Интерпретация
OCP и LSP перестали быть значимыми, как ты и предполагал.
👉 Их высокая χ²-связь объясняется перекосом выборки (64 % поддерживаемых проектов) и когнитивным эффектом ретроактивной атрибуции (“в хороших проектах наверняка следовали OCP/LSP”).
После контроля базовой вероятности поддерживаемости — эффект исчез.
ISP (Interface Segregation Principle) неожиданно оказался единственным статистически значимым.
Это логично: соблюдение ISP действительно улучшает локальную когнитивную простоту — меньше «толстых интерфейсов» и зависимостей.
То есть — легче разобраться, легче поддерживать.
Его влияние “пробивается” даже после нормализации.
DIP показывает слабую отрицательную тенденцию: возможно, команды, “гипер-инвертировавшие” зависимости, создавали чрезмерную абстрактность, и новые разработчики воспринимали проект как менее понятный (типичная проблема “архитектурного перегрева”).
Pseudo R² ≈ 0.22 означает, что модель объясняет около 22 % вариации в восприятии поддерживаемости — это довольно много для социальных/опросных данных:
в реальных социотехнических системах 20–30 % — уже значимый вклад.
🧩 Вывод
После статистической коррекции на общий перекос выборки влияние OCP и LSP на поддерживаемость исчезает.
Их высокая χ²-связь, вероятно, отражает перцептивное приписывание “хороших принципов” удачным проектам, а не фактическое следование.
Из принципов SOLID только Interface Segregation Principle сохраняет достоверную положительную связь с восприятием поддерживаемости, что можно трактовать как эмпирическое подтверждение его когнитивной пользы: он уменьшает сложность интерфейсов и локальные зависимости, облегчая понимание системы.
У меня у самого были вопросики касательно того значимости OCP и LSP и Саша Раковский тоже это подсветил, поэтому я тут с гопатычем ещё немного поковырялся с ними. Иииииии - отбой, они не влияют на поддерживаемость.
Слово гопатычу:
Отлично — вот теперь у нас реальное подтверждение твоей гипотезы [о том, что сила связи OCP и LSP вызвана общим перекосом в пользу поддерживаемых проектов]👇
📊 Что показывают результаты
Принцип Коэффициент p-value Интерпретация
SRP −0.75 0.13 Не значим (p > 0.05). Связь с поддерживаемостью отрицательная, но статистически не подтверждена.
OCP +0.30 0.43 Не значим. После контроля общего фона исчезает эффект, который был виден в χ².
LSP +0.16 0.62 Не значим. Аналогично — исчезла кажущаяся корреляция.
ISP +1.02 0.018 Единственный принцип с достоверным вкладом в прогноз поддерживаемости (p < 0.05).
DIP −0.69 0.08 Почти значим (тенденция, p≈0.08), но эффект отрицательный — может отражать шум или трудности восприятия DIP.
🧠 Интерпретация
OCP и LSP перестали быть значимыми, как ты и предполагал.
👉 Их высокая χ²-связь объясняется перекосом выборки (64 % поддерживаемых проектов) и когнитивным эффектом ретроактивной атрибуции (“в хороших проектах наверняка следовали OCP/LSP”).
После контроля базовой вероятности поддерживаемости — эффект исчез.
ISP (Interface Segregation Principle) неожиданно оказался единственным статистически значимым.
Это логично: соблюдение ISP действительно улучшает локальную когнитивную простоту — меньше «толстых интерфейсов» и зависимостей.
То есть — легче разобраться, легче поддерживать.
Его влияние “пробивается” даже после нормализации.
DIP показывает слабую отрицательную тенденцию: возможно, команды, “гипер-инвертировавшие” зависимости, создавали чрезмерную абстрактность, и новые разработчики воспринимали проект как менее понятный (типичная проблема “архитектурного перегрева”).
Pseudo R² ≈ 0.22 означает, что модель объясняет около 22 % вариации в восприятии поддерживаемости — это довольно много для социальных/опросных данных:
в реальных социотехнических системах 20–30 % — уже значимый вклад.
🧩 Вывод
После статистической коррекции на общий перекос выборки влияние OCP и LSP на поддерживаемость исчезает.
Их высокая χ²-связь, вероятно, отражает перцептивное приписывание “хороших принципов” удачным проектам, а не фактическое следование.
Из принципов SOLID только Interface Segregation Principle сохраняет достоверную положительную связь с восприятием поддерживаемости, что можно трактовать как эмпирическое подтверждение его когнитивной пользы: он уменьшает сложность интерфейсов и локальные зависимости, облегчая понимание системы.
🔥6
Эргономичный код
Привет! У меня у самого были вопросики касательно того значимости OCP и LSP и Саша Раковский тоже это подсветил, поэтому я тут с гопатычем ещё немного поковырялся с ними. Иииииии - отбой, они не влияют на поддерживаемость. Слово гопатычу: Отлично — вот…
Прогнал с гопатычем ещё логистическую регрессию для шаблонов проектирования, и циклов - положительная связь подтвердилась, но для циклов в модели ушла в раздел пограничных
Привет!
Собрал микропост со сверкой рекомендаций ЭП с результатами анализа.
TLDR:
Судя по данным, собранным в рамках исследования:
— три из девяти рекомендаций Эргономичного подхода (пишите тесты, держите тесты быстрыми, исключайте циклы в зависимостях) ведут к повышению поддерживаемости;
— ещё пять (минимизация моков, разбиение модели на агрегаты, разделение IO и логики и использование неизменяемой модели данных, ограничение кол-ва зависимостей до 5–7 на компонент, использование открытой архитектуры), как минимум не снижают поддерживаемость, либо имеют небольшой тренд на её повышение;
— наконец, последняя рекомендация — не вводить интерфейсы без необходимости — никак не связана с поддерживаемостью: не повышает, но и не снижает её.
Хоть выборка у нас получилась и небольшая, но, на мой взгляд, голословные утверждения и немного статистики - это немного лучше, чем просто голословные утверждения.
—
Плюс пока писал пост накопал ещё один любопытный инсайт.
Между временем запуска одного теста и поддерживаемостью есть погранично значимая, но сильная (почти что очень сильная) связь с поддерживаемостью. И больше всего поддерживаемых (10 из 13) проектов было в категории «2–10 секунд». В то время как для категории «0-1 секунду» только лишь 2 из 7 проектов были поддерживаемым.
Здесь уже начинаются чистой воды спекуляции на результатах анализа совсем маленькой выборки (23 ответа на этот вопрос), но, кажется, эти данные можно проинтерпретировать как дважды косвенное подтверждение идеи, что фокус на качественных (работающих до 10 секунд) интеграционных тестах повышает поддерживаемость.
#ergo_approach@ergonomic_code #ergo_testing@ergonomic_code
Собрал микропост со сверкой рекомендаций ЭП с результатами анализа.
TLDR:
Судя по данным, собранным в рамках исследования:
— три из девяти рекомендаций Эргономичного подхода (пишите тесты, держите тесты быстрыми, исключайте циклы в зависимостях) ведут к повышению поддерживаемости;
— ещё пять (минимизация моков, разбиение модели на агрегаты, разделение IO и логики и использование неизменяемой модели данных, ограничение кол-ва зависимостей до 5–7 на компонент, использование открытой архитектуры), как минимум не снижают поддерживаемость, либо имеют небольшой тренд на её повышение;
— наконец, последняя рекомендация — не вводить интерфейсы без необходимости — никак не связана с поддерживаемостью: не повышает, но и не снижает её.
Хоть выборка у нас получилась и небольшая, но, на мой взгляд, голословные утверждения и немного статистики - это немного лучше, чем просто голословные утверждения.
—
Плюс пока писал пост накопал ещё один любопытный инсайт.
Между временем запуска одного теста и поддерживаемостью есть погранично значимая, но сильная (почти что очень сильная) связь с поддерживаемостью. И больше всего поддерживаемых (10 из 13) проектов было в категории «2–10 секунд». В то время как для категории «0-1 секунду» только лишь 2 из 7 проектов были поддерживаемым.
Здесь уже начинаются чистой воды спекуляции на результатах анализа совсем маленькой выборки (23 ответа на этот вопрос), но, кажется, эти данные можно проинтерпретировать как дважды косвенное подтверждение идеи, что фокус на качественных (работающих до 10 секунд) интеграционных тестах повышает поддерживаемость.
#ergo_approach@ergonomic_code #ergo_testing@ergonomic_code
Алексей Жидков
Анализ результатов исследования факторы поддерживаемости backend-проектов с точки зрения Эргономичного подхода - Алексей Жидков
https://azhidkov.pro/
1👍9🔥5
Привет!
Наткнулся на пост о фреймвоке размышлений об ошибках Марка Симана.
И он до неприличия похож на мой, независимо разработанный, подход:
1. Симан так же категоризирует ошибки по атрибутам ожидаемая/неожиданная и восстановимая/невосстановимая
2. Симан так же предлагает восстановимые ошибки возвращать (чем-то в духе nullable типа/Result/Eather etc), а невосстановимые ошибки выбрасывать исключениями.
Плюс он там выдвигает интересную идею, что невосстановимых ошибок не бывает.
Вкратце: например, для обработки отказа сохранения в БД, вы можете записать запрос на локальный диск и попробовать позже. А если локальный диск переполнен - сначала попытаться что-то почистить и сохранить, а если почистить не получилось - хотя бы попытаться придержать в памяти и дозвониться дежурному инженеру.
И это дополняет мою мысль, что доменные ошибки - это ошибки которых не должно быть.
И совместно получается, что теоретически можно написать софт который будет работать всегда. Но это будет очень дорого.
#posts@ergonomic_code #ergo_approach@ergonomic_code
Наткнулся на пост о фреймвоке размышлений об ошибках Марка Симана.
И он до неприличия похож на мой, независимо разработанный, подход:
1. Симан так же категоризирует ошибки по атрибутам ожидаемая/неожиданная и восстановимая/невосстановимая
2. Симан так же предлагает восстановимые ошибки возвращать (чем-то в духе nullable типа/Result/Eather etc), а невосстановимые ошибки выбрасывать исключениями.
Плюс он там выдвигает интересную идею, что невосстановимых ошибок не бывает.
Вкратце: например, для обработки отказа сохранения в БД, вы можете записать запрос на локальный диск и попробовать позже. А если локальный диск переполнен - сначала попытаться что-то почистить и сохранить, а если почистить не получилось - хотя бы попытаться придержать в памяти и дозвониться дежурному инженеру.
И это дополняет мою мысль, что доменные ошибки - это ошибки которых не должно быть.
И совместно получается, что теоретически можно написать софт который будет работать всегда. Но это будет очень дорого.
#posts@ergonomic_code #ergo_approach@ergonomic_code
ploeh blog
Error categories and category errors
How I currently think about errors in programming.
👍5
Привет!
Я всё ещё "гамак-дривеню" проекцию модели данных Эргономичной архитектуры и чтобы накинуть больше входных данных на обработку во сне своему большому мозолистому мозгу я начал читать Data Modeling Essentials. И там наткнулся на новую для себя концепцию в моделировании данных - предаваемость (transferability) отношения.
Отношение является передаваемым, если допустимо менять сущность на одной из сторон.
Например, отношение "Заказ такси" -> "Водитель" является передаваемым. К сожалению.
А вот "Заказ такси" -> "Заказчик" - нет.
И там прям в книге явно написано, что непередаваемость является обазятельным свойтвом связи между сущностью и её слабой/зависимой сущностью.
И в качестве примера такой связи приводят хрестоматийный пример "Заказ" -> "Позиция заказа".
Ну и т.к., имхо, ДДД Агрегаты и сущности+слабые сущности - это одни и те же яйца только в профиль, то можно брать на вооружение эту эвристику при проектировании агрегатов - включать в агрегат только то, что невозможно передать другому агрегату. Не то чтобы супер прорыв, но эврстик много не бывает, на мой взгляд.
NB: и на всякий случай - это необходимое, но недостаточное условие - ни Заказ, ни Заказчик не являются частью агрегата друг друга.
Но непередаваемые связи могут быть не только внутри агрегата, но и между ними. И это уже стало для меня откровением.
В качестве примера в книге приводят связь между страховым полисом и агентом - в их картине мира у полиса может не быть агента, но если он есть - изменить его нельзя.
Это тоже не сказать что прорывная идея, но она была за рамками моих шор. И, возможно, это поможет мне решить одну из проблем, над которыми я бьюсь.
Касательно книги - я пока ток начал её читать и скачу в ней поссылкам, а не читаю от корки до корки, но выглядит очень много обещающе - как актуальный и исчерпывающий источник информации по моделированию данных.
#ergo_arch@ergonomic_code #ergo_data_model@ergonomic_code #ergo_persistance@ergonomic_code #books@ergonomic_code #ddd@ergonomic_code
Я всё ещё "гамак-дривеню" проекцию модели данных Эргономичной архитектуры и чтобы накинуть больше входных данных на обработку во сне своему большому мозолистому мозгу я начал читать Data Modeling Essentials. И там наткнулся на новую для себя концепцию в моделировании данных - предаваемость (transferability) отношения.
Отношение является передаваемым, если допустимо менять сущность на одной из сторон.
Например, отношение "Заказ такси" -> "Водитель" является передаваемым. К сожалению.
А вот "Заказ такси" -> "Заказчик" - нет.
И там прям в книге явно написано, что непередаваемость является обазятельным свойтвом связи между сущностью и её слабой/зависимой сущностью.
И в качестве примера такой связи приводят хрестоматийный пример "Заказ" -> "Позиция заказа".
Ну и т.к., имхо, ДДД Агрегаты и сущности+слабые сущности - это одни и те же яйца только в профиль, то можно брать на вооружение эту эвристику при проектировании агрегатов - включать в агрегат только то, что невозможно передать другому агрегату. Не то чтобы супер прорыв, но эврстик много не бывает, на мой взгляд.
NB: и на всякий случай - это необходимое, но недостаточное условие - ни Заказ, ни Заказчик не являются частью агрегата друг друга.
Но непередаваемые связи могут быть не только внутри агрегата, но и между ними. И это уже стало для меня откровением.
В качестве примера в книге приводят связь между страховым полисом и агентом - в их картине мира у полиса может не быть агента, но если он есть - изменить его нельзя.
Это тоже не сказать что прорывная идея, но она была за рамками моих шор. И, возможно, это поможет мне решить одну из проблем, над которыми я бьюсь.
Касательно книги - я пока ток начал её читать и скачу в ней поссылкам, а не читаю от корки до корки, но выглядит очень много обещающе - как актуальный и исчерпывающий источник информации по моделированию данных.
#ergo_arch@ergonomic_code #ergo_data_model@ergonomic_code #ergo_persistance@ergonomic_code #books@ergonomic_code #ddd@ergonomic_code
Эргономичный подход
Эргономичная архитектура (v3.0.0)
Текущая версия статьи написана в режиме потока сознания и пока что я не проводил даже проверки правописания, не говоря уж о том, чтобы сопроводить идеи иллюстрациями и кодом.
Предыдущие черновики и диаграммы здесь.
Введение В своей книге The Problem with…
Предыдущие черновики и диаграммы здесь.
Введение В своей книге The Problem with…
❤5👍5🔥4
Привет!
Значит ли это, что Чистая архитектура ближе к вертикальной, чем к слоёной? И в коде по чистой архитектуре должна быть пачка интерфейсов в духе RegisterUserGateway, DeleteUserGateway и т.п. вместо UsersGateway.
Как знать - анкл Боб почему-то решил не показывать реальный пример реализации чистой архитектуры.
Может в этом секрет популярности - написать в целом убедительный, но внутренне противоречивый текст, в котором каждый найдёт то, что ему нравится?
Не спрашивайте как меня опять занесло перечитывать эту книгу.
#clean_arch@ergonomic_code #books@ergonomic_code
What else changes for different reasons? The use cases themselves! The use case for adding an order to an order entry system almost certainly will change at a different rate, and for different reasons, than the use case that deletes an order from the system. Use cases are a very natural way to divide the system.
At the same time, use cases are narrow vertical slices that cut through the horizontal layers of the system. Each use case uses some UI, some application-specific business rules, some application-independent business rules, and some database functionality. Thus, as we are dividing the system into horizontal layers, we are also dividing the system into thin vertical use cases that cut through those layers.
To achieve this decoupling, we separate the UI of the add-order use case from the UI of the delete-order use case. We do the same with the business rules, and with the database. We keep the use cases separate down the vertical height of the system.
—
Что еще меняется по разным причинам? Сами варианты использования! Вариант использования для добавления заказа в систему ввода заказов почти наверняка будет меняться с другой скоростью и по другим причинам, чем вариант использования, который удаляет заказ из системы. Варианты использования - это естественный способ разделения системы.
В то же время варианты использования представляют собой узкие вертикальные срезы, проходящие через горизонтальные уровни системы. Каждый вариант использования включает некоторый пользовательский интерфейс, какие-то бизнес-правила, специфичные для приложения, некоторые бизнес-правила, не зависящие от приложения, и а также определённую работу базой данных. Таким образом, разделяя систему на горизонтальные слои, мы также разделяем ее на тонкие вертикальные варианты использования, которые проходят через эти слои.
Чтобы добиться такого разделения, мы отделяем пользовательский интерфейс варианта использования с добавлением заказа от пользовательского интерфейса варианта использования с удалением заказа. Мы делаем то же самое с бизнес-правилами и базой данных. Мы разделяем варианты использования по вертикали системы.
— Роберт Мартин, Clean Architecture, глава 16. Independence, раздел Decoupling Use Cases
Значит ли это, что Чистая архитектура ближе к вертикальной, чем к слоёной? И в коде по чистой архитектуре должна быть пачка интерфейсов в духе RegisterUserGateway, DeleteUserGateway и т.п. вместо UsersGateway.
Как знать - анкл Боб почему-то решил не показывать реальный пример реализации чистой архитектуры.
Может в этом секрет популярности - написать в целом убедительный, но внутренне противоречивый текст, в котором каждый найдёт то, что ему нравится?
Не спрашивайте как меня опять занесло перечитывать эту книгу.
#clean_arch@ergonomic_code #books@ergonomic_code
😁9❤5
Привет!
На той недели мне в комментах подсветили батл между Робертом Мартином (он же «Дядя Боб») и Кейси Муратори, который в итоге свёлся к полиморфизму против свитчей (но с неожиданным поворотом).
Батл заканчивается фразой анкл Боба «Я думаю, нам стоит на этом остановиться в нашем споре и предоставить нашей аудитории вынести окончательный вердикт» (I believe we should let our disagreement stand at this point and let our audience be the final judge).
И мой вердикт таков: Муратори всю дорогу вёл по очкам и победил нокаутом, разнеся в пух и прах SRP, OCP и DIP. Правда, сделал он это в очень узком контексте — API, предназначенного для реализации внешними поставщиками (SPI в мире Java). Соответственно для разработчиков прикладных приложений (коих в мире большинство) это не имеет никакого практического значения. Тем не менее, ознакомится с ним полезно всем, на мой взгляд.
Так как батл у них получился невероятно длинный (я читал часа четыре) и довольно нудный, я советую прочитать только мякотку, начинающуюся во втором файле со слов «I’m not even talking about machine-cycles, I was just focusing on programmer-cycles». А для того чтобы сделать позицию Муратори более доступной русскоязычной аудитории, я решил сделать её близкий к дословному перевод.
На той недели мне в комментах подсветили батл между Робертом Мартином (он же «Дядя Боб») и Кейси Муратори, который в итоге свёлся к полиморфизму против свитчей (но с неожиданным поворотом).
Батл заканчивается фразой анкл Боба «Я думаю, нам стоит на этом остановиться в нашем споре и предоставить нашей аудитории вынести окончательный вердикт» (I believe we should let our disagreement stand at this point and let our audience be the final judge).
И мой вердикт таков: Муратори всю дорогу вёл по очкам и победил нокаутом, разнеся в пух и прах SRP, OCP и DIP. Правда, сделал он это в очень узком контексте — API, предназначенного для реализации внешними поставщиками (SPI в мире Java). Соответственно для разработчиков прикладных приложений (коих в мире большинство) это не имеет никакого практического значения. Тем не менее, ознакомится с ним полезно всем, на мой взгляд.
Так как батл у них получился невероятно длинный (я читал часа четыре) и довольно нудный, я советую прочитать только мякотку, начинающуюся во втором файле со слов «I’m not even talking about machine-cycles, I was just focusing on programmer-cycles». А для того чтобы сделать позицию Муратори более доступной русскоязычной аудитории, я решил сделать её близкий к дословному перевод.
Алексей Жидков
Батл анкл Боба и Муратори - Алексей Жидков
https://azhidkov.pro/
🔥8
Привет!
Я недавно сделал Web Push уведомления в Trainer Advisor и попутно снова узнал и придумал пачку прикольных штук, о которых накатал очередной "микропост" на 30-40 минут чтения по оценке ФФ.
Ну и по традции вот вам сразу содержание, чтобы привлечь внимание мякоткой:
* Отправка пушей
* Архитектура
* Абстракция vs очевидность эффектов и разделение ввода и вывода
* И снова про уровни абстракции/стратификацию
* Пример №1: код открытия диплинка по клику
* Пример №2: фетч ресурсов с фолбэком на кэш и кастомную страницу «Сервис недоступен"
* Postgres GENERATED-колонки для ограничений целостности в JSONB
* TrainerAdvisorApis
* В Gradle-плагин GitProperties завезли поддержку git worktrees
* Отказ от Kotest Matchers в пользу shuold*-методов
#case@ergonomic_code #ergo_approach@ergonomic_code #ergo_arch@ergonomic_code #ergo_testing@ergonomic_code #trainer_advisor@ergonomic_code #ergo_persistance@ergonomic_code
Я недавно сделал Web Push уведомления в Trainer Advisor и попутно снова узнал и придумал пачку прикольных штук, о которых накатал очередной "микропост" на 30-40 минут чтения по оценке ФФ.
Ну и по традции вот вам сразу содержание, чтобы привлечь внимание мякоткой:
* Отправка пушей
* Архитектура
* Абстракция vs очевидность эффектов и разделение ввода и вывода
* И снова про уровни абстракции/стратификацию
* Пример №1: код открытия диплинка по клику
* Пример №2: фетч ресурсов с фолбэком на кэш и кастомную страницу «Сервис недоступен"
* Postgres GENERATED-колонки для ограничений целостности в JSONB
* TrainerAdvisorApis
* В Gradle-плагин GitProperties завезли поддержку git worktrees
* Отказ от Kotest Matchers в пользу shuold*-методов
#case@ergonomic_code #ergo_approach@ergonomic_code #ergo_arch@ergonomic_code #ergo_testing@ergonomic_code #trainer_advisor@ergonomic_code #ergo_persistance@ergonomic_code
Алексей Жидков
Trainer Advisor — WebPush-уведомления - Алексей Жидков
https://azhidkov.pro/
🔥4❤3👍2
о, а вы знали, что вчера Spring Boot 4.0 пошёл в GA?
и там завезли нормальную поддержку версионирования HTTP API (вроде как - надо проверять)
и, имхо самое крутое, распилили наконец-то адовый spring-boot-autoconfigure.jar и теперь спринг на старте не будет пытаться загружать всю ту гору барахла, которую подерживает спринг, но из которой я ну от силы процентов 25 использую
и там завезли нормальную поддержку версионирования HTTP API (вроде как - надо проверять)
и, имхо самое крутое, распилили наконец-то адовый spring-boot-autoconfigure.jar и теперь спринг на старте не будет пытаться загружать всю ту гору барахла, которую подерживает спринг, но из которой я ну от силы процентов 25 использую
Spring Boot 4.0.0 available now
Level up your Java code and explore what Spring can do for you.
👍12
Привет!
Вычитал тут в синей книги интересное про сущности.
Я смотрю в этот абзац и вижу там свои сущности-аспекты (и пример).
Меш тем, сущности-аспекты - это основная причина, почему я завожу собственную номенклатуру блоков, вместо ддд-шных сущностей и объектов-значений.
Сижу теперь и думаю, то ли дальше со своей сидеть (прописав в примечании совместимость с ДДД), то ли перейти на ДДД-шную, дополнив её типами сущностей (мне ещё справочники нужны) и сделав отсылку на это место.
#ddd@ergonomic_code #books@ergonomic_code
Вычитал тут в синей книги интересное про сущности.
Modeling ENTITIES
ENTITIES are defined by their identities. Attributes are attached and change. Therefore, strip the ENTITY object’s definition down to the most intrinsic characteristics, particularly those that identify it, or are commonly used to find or match it. Separate other characteristics into other objects associated with the core ENTITY.
Figure 5. 1
The name does not define a person’s identity, but it is often used as part of the means of determining it.
Many would dispute moving phone and address into Customer. It depends on how Customers are typically matched or distinguished. If a Customer has many contact phone numbers for different purposes, then the phone number is not associated with identity and should stay with the Sales Contact. The customerID is the one and only identifier of the ENTITY, but the phone number, name and address would often be used to find or match a Customer.
—
Моделирование СУЩНОСТЕЙ (ENTITIES)
СУЩНОСТИ определяются своей идентичностью. Их атрибуты прикреплены к ним и могут изменяться. Поэтому необходимо свести определение объекта-СУЩНОСТИ к его наиболее внутренним, сущностным характеристикам — особенно тем, которые идентифицируют его или часто используются для поиска или сопоставления. Остальные характеристики следует вынести в отдельные объекты, связанные с ядром СУЩНОСТИ.
Иллюстрация 5.1
Имя само по себе не определяет идентичность человека, но часто используется как часть механизма её определения. Многие поспорили бы насчёт включения телефона и адреса в Customer. Это зависит от того, как обычно клиентов сопоставляют или различают. Если у клиента есть много телефонных номеров для разных целей, то телефон не связан с идентичностью и должен оставаться в Sales Contact. customerID — единственный истинный идентификатор СУЩНОСТИ, но телефон, имя и адрес часто используются для поиска или сопоставления клиента.
Я смотрю в этот абзац и вижу там свои сущности-аспекты (и пример).
Меш тем, сущности-аспекты - это основная причина, почему я завожу собственную номенклатуру блоков, вместо ддд-шных сущностей и объектов-значений.
Сижу теперь и думаю, то ли дальше со своей сидеть (прописав в примечании совместимость с ДДД), то ли перейти на ДДД-шную, дополнив её типами сущностей (мне ещё справочники нужны) и сделав отсылку на это место.
#ddd@ergonomic_code #books@ergonomic_code
❤6
Привет!
Прокопал вопрос "когда использовать top-level функции в Kotlin" и собрал находки в статью на вики
ТЛДР:
1. Официальной рекомендации нет
2. Судя по всему команда разработки Котлина предпочитает использовать top-level объявления по максимуму
3. Но у меня и не только с этим возникли проблемы на практике
4. Поэтому:
4.1 используйте публичные top-level объявления только тогда, когда они будут использоваться повсеместно
4.2 приватные top-level объявления использовать можно и нужно
4.3 сложные/значительные функции, которые технически могли бы быть top-level, заворачивайте в объекты singleton-ы, чтобы "занеймспейсить" их
#kotlin@ergonomic_code #ergo_wiki@ergonomic_code
Прокопал вопрос "когда использовать top-level функции в Kotlin" и собрал находки в статью на вики
ТЛДР:
1. Официальной рекомендации нет
2. Судя по всему команда разработки Котлина предпочитает использовать top-level объявления по максимуму
3. Но у меня и не только с этим возникли проблемы на практике
4. Поэтому:
4.1 используйте публичные top-level объявления только тогда, когда они будут использоваться повсеместно
4.2 приватные top-level объявления использовать можно и нужно
4.3 сложные/значительные функции, которые технически могли бы быть top-level, заворачивайте в объекты singleton-ы, чтобы "занеймспейсить" их
#kotlin@ergonomic_code #ergo_wiki@ergonomic_code
Эргономичный подход
Объявления верхнего уровня/top-level declarations (v0.1.0)
Мнение команды разработки и комьюнити Kotlin о объявлениях верхнего уровня По состоянию на декабрь 2025 года ни в официальной документации к языку, ни в официальном стиле кодирования нет явных рекомендаций по использованию объявлений верхнего уровня (top…
🔥5❤2
Привет!
Наткунлся на любопытную публикацию об исследовании характеристик поддерживаемых кодовых баз от настоящих учёных - Questioning Software Maintenance Metrics: A Comparative Case Study :)
Публикация любопытна в первую очередь тем, что базируется на данных предыдущего исследования, в котором они заказали реальную разработку реального (но небольшого - 2-3 месяца разработки) проекта в 4-ёх разных конторах.
Затем они посчитали для этих систем различные метрики поддерживаемости в духе размера, цикломатической сложности, глубины наследования и т.п.
Затем они наняли 6 новых профессиональных и примерно равных по квалификации разработчиков, чтобы они внесли по 3 одинаковые правки в двух системах, с замером времени работы над задачами с помощью плагина в ИДЕ.
А потом посмотрели, как трудозатраты связаны с метриками поддерживаемости.
И тут мы приходим ко второй любопытной штуке - TLDR-у исследования: лучшими метриками поддерижваемости системы являются её общий размер (в строках кода) и не низкая cohesion (в виде TCC - проценте пар методов, которые используют хотя бы одно обшее поле).
И этот результат для меня неоднозначен.
С одной сторны, в ЭП много практик, которые уменьшают общий размер системы - отказ от DIP-а по дефолту, открытая архитектура (обращение из контроллеров в репозы в обход сервисов/юз кейсов), минимизация маппинга (прямой маппинг sql result set -> final dto в простых операциях чтения данных), разделение доменной и персистеной модели только по необходимости.
С другой стороны, есть практика, которая плодит много кода. Я её ещё не полностью сформулировал, но она во много базируется на make illegal states unrepresentable.
В частности, например, если ей следовать и у вас есть операции создания и получения сущности, с генерацией ИДа бэком, то это значит, что вам надо завести две практически идентичных дтошки - с идом для ответов и без него для запросов.
И под каждый контекст надо завести по дтошечке с актуальным для него набором полей
И когда у сущности меняется состав полей - вносить правки во все дтошки не то чтобы прям боль, но дико бесит:)
И тут, как назло, ещё и Котлин со своей нуллабельностью не помогает - теоретически можно сделать одну дтошку с нуллабельным идом на все случаи жизни, но тогда везде кроме операции создания вам надо будет как минимум !! на иды развешивать, что будет бесить не меньше.
В общем. Не пишите лишний код. А какой код лишний - вопрос открытый:)
#papers@ergonomic_code
Наткунлся на любопытную публикацию об исследовании характеристик поддерживаемых кодовых баз от настоящих учёных - Questioning Software Maintenance Metrics: A Comparative Case Study :)
Публикация любопытна в первую очередь тем, что базируется на данных предыдущего исследования, в котором они заказали реальную разработку реального (но небольшого - 2-3 месяца разработки) проекта в 4-ёх разных конторах.
Затем они посчитали для этих систем различные метрики поддерживаемости в духе размера, цикломатической сложности, глубины наследования и т.п.
Затем они наняли 6 новых профессиональных и примерно равных по квалификации разработчиков, чтобы они внесли по 3 одинаковые правки в двух системах, с замером времени работы над задачами с помощью плагина в ИДЕ.
А потом посмотрели, как трудозатраты связаны с метриками поддерживаемости.
И тут мы приходим ко второй любопытной штуке - TLDR-у исследования: лучшими метриками поддерижваемости системы являются её общий размер (в строках кода) и не низкая cohesion (в виде TCC - проценте пар методов, которые используют хотя бы одно обшее поле).
И этот результат для меня неоднозначен.
С одной сторны, в ЭП много практик, которые уменьшают общий размер системы - отказ от DIP-а по дефолту, открытая архитектура (обращение из контроллеров в репозы в обход сервисов/юз кейсов), минимизация маппинга (прямой маппинг sql result set -> final dto в простых операциях чтения данных), разделение доменной и персистеной модели только по необходимости.
С другой стороны, есть практика, которая плодит много кода. Я её ещё не полностью сформулировал, но она во много базируется на make illegal states unrepresentable.
В частности, например, если ей следовать и у вас есть операции создания и получения сущности, с генерацией ИДа бэком, то это значит, что вам надо завести две практически идентичных дтошки - с идом для ответов и без него для запросов.
И под каждый контекст надо завести по дтошечке с актуальным для него набором полей
И когда у сущности меняется состав полей - вносить правки во все дтошки не то чтобы прям боль, но дико бесит:)
И тут, как назло, ещё и Котлин со своей нуллабельностью не помогает - теоретически можно сделать одну дтошку с нуллабельным идом на все случаи жизни, но тогда везде кроме операции создания вам надо будет как минимум !! на иды развешивать, что будет бесить не меньше.
В общем. Не пишите лишний код. А какой код лишний - вопрос открытый:)
#papers@ergonomic_code
Fsharpforfunandprofit
Designing with types: Making illegal states unrepresentable
Encoding business logic in types
🔥5👍3❤2🤔1