Трансформация конференций
Если кто-то пропустил, то в течение года нарастал хайп на тему того, что текущий формат конференций уже устарел. И вот накануне нового года Онтико сформулировало концепцию "конференций развития", заявив об этом во всех своих каналах и чатах.
Честно говоря, концепция больше похожа на манифест, и можно только догадываться, какие именно трансформации произойдут. Между тем, очевиден вектор развития — практическая направленность и ориентация на текущие потребности аудитории. Пожалуй, в эпоху доступности информации это единственно правильное направление развития. Не рассчитываю, что ближайшие конференции сразу получатся такими, как заявлено, т.к. новый формат требует перестройки на всех уровнях (сознания), но очень надеюсь на итоговый успех.🔥
#conf
Если кто-то пропустил, то в течение года нарастал хайп на тему того, что текущий формат конференций уже устарел. И вот накануне нового года Онтико сформулировало концепцию "конференций развития", заявив об этом во всех своих каналах и чатах.
Честно говоря, концепция больше похожа на манифест, и можно только догадываться, какие именно трансформации произойдут. Между тем, очевиден вектор развития — практическая направленность и ориентация на текущие потребности аудитории. Пожалуй, в эпоху доступности информации это единственно правильное направление развития. Не рассчитываю, что ближайшие конференции сразу получатся такими, как заявлено, т.к. новый формат требует перестройки на всех уровнях (сознания), но очень надеюсь на итоговый успех.
#conf
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥3
Первичный анализ задачи поиска медицинских документов
Сегодня предлагаю рассмотреть вполне конкретную задачу из реального проекта. Думаю, что подобный кейс достаточно интересен и его можно рассматривать для прокачки своих навыков по System Design.💪
Разбор получился большим, поэтому я оформил его в виде статьи. Зато в ней всё, что мы любим: архитектура и базы данных. В статье рассматривается вариант реализации быстрого поиска по метаданным медицинских документов; некоторые проблемы производительности SQL-хранилищ; преимущества OLAP-хранилищ и колоночных баз данных, включая ClickHouse.🌌
Сразу скажу, что мы ещё не полностью решили описанную в статье задачу. Представленное решение — лишь один из возможных вариантов, черновик, который ещё не проверен на практике. Однако, выполнив достаточно подробный анализ, я решил поделиться им с вами, а не оставлять пылиться результаты проделанной работы у себя в столе. В статье постарался адаптировать материал, чтобы он был понятен широкому кругу читателей и не требовал глубокого погружения в предметную область. Надеюсь, у меня получилось, и желаю вам приятного чтения!❤️
➡️ Ссылка на статью ⬅️
〰️ 〰️ 〰️
Всё чаще появляются новости об ограничении доступа к информационным ресурсам, включая Telegram. Решил, что было бы неплохо обзавестись web-версией своего канала, в том числе для публикации статей, которые не помещаются в размер поста.
#arch #db
Сегодня предлагаю рассмотреть вполне конкретную задачу из реального проекта. Думаю, что подобный кейс достаточно интересен и его можно рассматривать для прокачки своих навыков по System Design.
Разбор получился большим, поэтому я оформил его в виде статьи. Зато в ней всё, что мы любим: архитектура и базы данных. В статье рассматривается вариант реализации быстрого поиска по метаданным медицинских документов; некоторые проблемы производительности SQL-хранилищ; преимущества OLAP-хранилищ и колоночных баз данных, включая ClickHouse.
Сразу скажу, что мы ещё не полностью решили описанную в статье задачу. Представленное решение — лишь один из возможных вариантов, черновик, который ещё не проверен на практике. Однако, выполнив достаточно подробный анализ, я решил поделиться им с вами, а не оставлять пылиться результаты проделанной работы у себя в столе. В статье постарался адаптировать материал, чтобы он был понятен широкому кругу читателей и не требовал глубокого погружения в предметную область. Надеюсь, у меня получилось, и желаю вам приятного чтения!
Всё чаще появляются новости об ограничении доступа к информационным ресурсам, включая Telegram. Решил, что было бы неплохо обзавестись web-версией своего канала, в том числе для публикации статей, которые не помещаются в размер поста.
#arch #db
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8👍1
Итоги 2025 года
Вот и пришло время подводить итоги года. Стараюсь следовать своим же рекомендациям и делать небольшой ретроспективный анализ своей деятельности.😏
👨🏻💻 Рабочий год у меня прошёл под девизом "импортозамещения". На моей совести была разработка общего подхода и инструмента для миграции данных с одной базы в другую. Миграция прошла практически безукоризненно, перенесли две больших базы — на 5 млрд и 40 млрд строк соответственно. Всё было онлайн, всё без остановки работы системы. Ещё остались некоторые работы, но считаю, что основная и самая сложная часть уже позади. Помимо этого удалось переработать и отдать в разработку новую концептуальную архитектуру своего любимого олимпиадного проекта.
👨🏻🎨 Творческий год был не менее продуктивным. Моему каналу исполнился 1 год, и я искренне рад, что мой контент находит своего читателя. Спасибо вам большое, Вы — супер!⭐️ За минувший год моя тяга к графомании заставила меня написать 62 поста и 5 статей. 🙈 Мне удалось посетить 3 крупных конференции в роли докладчика; поучаствовать в 3 публичных митапах, один из которых был Fail-митапом; поучаствовать в десятке online-конференций. Возможно, для кого-то не так много, зато по делу. 😃 В конце года оформил веб-версию блога, в котором старательно собрал подборку постов, статей и публичных выступлений. В следующем году могу пожелать себе быть не менее заряженным и продуктивным! 🚀
Желаю всем счастливого и продуктивного Нового года! 🎄 И не забывайте, что помимо рабочего и творческого года, есть еще и семейный год, который должен занимать центральное место в нашей жизни!❤️
〰️ 〰️ 〰️
Думаю, что первые две недели января я буду сохранять молчание в эфире. Но чтобы вам не было скучно и, как и мне, было чем заняться свободными зимними вечерами, поделюсь своей подборкой каналов.
🕚 Архитектура ИТ-решений — хотите прокачать свои навыки в архитектуре корпоративных информационных систем или находиться в курсе того, что там происходит, тогда вам точно сюда. Канал полезен не только постами, но и последующими обсуждениями в комментариях.
🕚 Архитектура распределённых систем — об ИТ-архитектуре и разработке. С Русланом я знаком лично уже много лет, мне очень близки его взгляды, нравится нестандартный и свежий взгляд на, казалось бы, привычные вещи.
🕚 Позовите Олега | Архитектура и разработка — привычные нам всем вещи про архитектуру, разработку и менеджмент в ИТ, но с упором на личный опыт и практику. Всё чётко, структурно, обстоятельно и по делу.
🕚 Токсичный (it) архитектор — даёт заряд отрицательной энергии, которая помогает принять правильное и взвешенное архитектурное решение. Несмотря на намеренно провокационную стилистику, посты всегда имеют аргументацию позиции автора.
🕚 Саша Раковский — про экстремальное программирование и разработку программного обеспечения, которые, очевидно, пропитаны годами бесценного опыта. Саша на самом деле выдаёт уникальный контент, как он сам о себе всегда говорит.
🕚 Инженер и Менеджер — если вы в поисках здравого смысла в менеджменте ИТ, то заходите. Захватывающая и местами манипулятивная подача, злободневные темы и инженерный взгляд на управленческие вопросы.
#summary
Вот и пришло время подводить итоги года. Стараюсь следовать своим же рекомендациям и делать небольшой ретроспективный анализ своей деятельности.
👨🏻💻 Рабочий год у меня прошёл под девизом "импортозамещения". На моей совести была разработка общего подхода и инструмента для миграции данных с одной базы в другую. Миграция прошла практически безукоризненно, перенесли две больших базы — на 5 млрд и 40 млрд строк соответственно. Всё было онлайн, всё без остановки работы системы. Ещё остались некоторые работы, но считаю, что основная и самая сложная часть уже позади. Помимо этого удалось переработать и отдать в разработку новую концептуальную архитектуру своего любимого олимпиадного проекта.
👨🏻🎨 Творческий год был не менее продуктивным. Моему каналу исполнился 1 год, и я искренне рад, что мой контент находит своего читателя. Спасибо вам большое, Вы — супер!
Желаю всем счастливого и продуктивного Нового года! 🎄 И не забывайте, что помимо рабочего и творческого года, есть еще и семейный год, который должен занимать центральное место в нашей жизни!
Думаю, что первые две недели января я буду сохранять молчание в эфире. Но чтобы вам не было скучно и, как и мне, было чем заняться свободными зимними вечерами, поделюсь своей подборкой каналов.
#summary
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7🎄4👍2
Throttling == бесполезная трата CPU
К такому выводу я пришёл на одном из проектов. Если контейнер приложения находится в состоянии тротлинга, это может вызвать не только замедление вычислений, но и бессмысленный перерасход CPU. Суммарно перерасход может достигать 50%, т.е. до половины выделенных процессорных ресурсов может уходить на "обогрев воздуха", а не на полезную работу.🔥
Всё началось с того, что нужно было достаточно точно измерить время использования CPU (CPU Usage) параллельно выполняющихся процессов ОС. Точность измерения оценивалась относительно аналогичного показателя, полученного при последовательном выполнении. По итогу нужно было выполнить калибровку системы и найти оптимальный уровень параллелизма, при котором CPU Usage каждого процесса приемлемо близок к эталону.
Иначе говоря, представьте, что есть некоторая вычислительная программа (задача, функция). Сначала делается серия последовательных запусков программы, и для каждого процесса измеряется его CPU Usage. Затем делается серия параллельных запусков с разным уровнем параллелизма. Например, в первой серии запускается по 2 одновременно работающих процесса; во второй – по 4, в третьей – по 8 и т.д. Все процессы запускаются в одном и том же окружении и выполняют одну и ту же вычислительную работу. По условию задачи уровень параллелизма считается приемлемым, если CPU Usage параллельного исполнения не превышает 30% последовательного.
Для чего всё это нужно?
➡️ Если у вас есть большой объём/поток вычислительных задач, и нужно обработать его как можно быстрей, но так, чтобы вычислительные затраты на каждую задачу были минимальны. Минимальны, значит, основная работа должна идти на вычисления, а не на переключение контекста и прочие накладные расходы, связанные с организацией параллелизма.
Конкретно в моём случае требовалось сделать проверку олимпиадных решений по программированию. Сделать это нужно было как можно скорей, а CPU Usage при этом использовался как критерий оценки корректности решения.
Проведя серию экспериментов, я ожидаемо подтвердил закон Амдала, но самое интересное заключалось в другом. С ростом уровня параллелизма CPU Usage начинает значительно деградировать – в среднем до 50% относительно эталона (иллюстрация).
Положительный момент в том, что деградация не бесконечна и имеет предел; отрицательный – большая часть вычислительных ресурсов тратится на организацию параллелизма (иллюстрация). Выводы очевидны, но полученные мной показатели заставили относиться к вопросу более серьёзно.
Какие из этого можно сделать выводы?
1️⃣ Частый тротлинг – проблема в конфигурации лимитов или неадекватно большом уровне параллелизма. В Kubernetes для контроля тротлинга можно использовать метрику container_cpu_cfs_throttled_seconds_total.
2️⃣ Тротлинг – это момент, когда потоки ОС часто и много конкурируют за CPU, следовательно, значительная часть вычислительных ресурсов используется впустую. Это справедливо, ведь большая часть приложений – это многопоточные web-приложения.
3️⃣ Превалирование принудительных переключений – это CPU-bound-задачи или высокий уровень параллелизма. Для большинства приложений справедливо второе. Подтвердить данный факт можно, посмотрев на соотношение метрик
4️⃣ CPU Usage – это не абсолют, это плавающий показатель. Анализируя или сравнивая профили производительности приложения, смотрите не только на CPU Usage, но и на Elapsed Time, также принимая во внимание количество параллельных вычислений, производимых во время снятия профиля.
〰️ 〰️ 〰️
А какие подходы позволяют контролировать уровень параллелизма, рассмотрим в следующий раз. Всем добра и поменьше параллельных активностей!❤️
#dev #devops
К такому выводу я пришёл на одном из проектов. Если контейнер приложения находится в состоянии тротлинга, это может вызвать не только замедление вычислений, но и бессмысленный перерасход CPU. Суммарно перерасход может достигать 50%, т.е. до половины выделенных процессорных ресурсов может уходить на "обогрев воздуха", а не на полезную работу.
Всё началось с того, что нужно было достаточно точно измерить время использования CPU (CPU Usage) параллельно выполняющихся процессов ОС. Точность измерения оценивалась относительно аналогичного показателя, полученного при последовательном выполнении. По итогу нужно было выполнить калибровку системы и найти оптимальный уровень параллелизма, при котором CPU Usage каждого процесса приемлемо близок к эталону.
Иначе говоря, представьте, что есть некоторая вычислительная программа (задача, функция). Сначала делается серия последовательных запусков программы, и для каждого процесса измеряется его CPU Usage. Затем делается серия параллельных запусков с разным уровнем параллелизма. Например, в первой серии запускается по 2 одновременно работающих процесса; во второй – по 4, в третьей – по 8 и т.д. Все процессы запускаются в одном и том же окружении и выполняют одну и ту же вычислительную работу. По условию задачи уровень параллелизма считается приемлемым, если CPU Usage параллельного исполнения не превышает 30% последовательного.
Для чего всё это нужно?
Конкретно в моём случае требовалось сделать проверку олимпиадных решений по программированию. Сделать это нужно было как можно скорей, а CPU Usage при этом использовался как критерий оценки корректности решения.
Проведя серию экспериментов, я ожидаемо подтвердил закон Амдала, но самое интересное заключалось в другом. С ростом уровня параллелизма CPU Usage начинает значительно деградировать – в среднем до 50% относительно эталона (иллюстрация).
Положительный момент в том, что деградация не бесконечна и имеет предел; отрицательный – большая часть вычислительных ресурсов тратится на организацию параллелизма (иллюстрация). Выводы очевидны, но полученные мной показатели заставили относиться к вопросу более серьёзно.
🗂 Интересно и то, что ОС включает затраты на переключение контекста в статистику процесса. Это справедливо, но немного неожиданно, ведь за переключение контекста отвечает диспетчер задач ОС, а не процесс.
Какие из этого можно сделать выводы?
voluntary_ctxt_switches и nonvoluntary_ctxt_switches (добровольные и принудительные переключения), которые доступны в файле статуса Linux-процесса /proc/<PID>/status.А какие подходы позволяют контролировать уровень параллелизма, рассмотрим в следующий раз. Всем добра и поменьше параллельных активностей!
#dev #devops
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥1
OOM/Killer к нам приходит
Думаю, каждый хотя бы раз сталкивался с Out Of Memory (OOM), а особо удачливые встречали OOM Killer. Страшней всего, когда это происходит без явных предпосылок в коде. 🙈
Скажу честно, проблемы с памятью обычно встречаю с чувством тревоги. Во-первых, чаще всего OOM происходит в приложениях с монолитной архитектурой, которые отличаются обилием функциональности. Во-вторых, как правило, OOM — инцидент, и нет времени на долгие исследования. Наконец, объективно OOM случается крайне редко, чтобы каждый был гуру в этом вопросе.
Чтобы побороть животные страхи, нужно немного разобраться в теме и попытаться классифицировать возможные ситуации. Определить, что перед нами: ошибка в коде или конфигурировании окружения. Поэтому не соглашайтесь уходить в исследование дампов, пока не узнаете всю предысторию возникновения OOM/Killer, иначе будете гоняться за призраками.
В ОС для контроля памяти есть два основных показателя:
1️⃣ Сколько выделено. Сколько памяти ОС выделила процессу, включая данные кучи (heap), стека (stack), код процесса и используемых библиотек, но исключая память, которая была выгружена в swap. Показатель отражает фактическое состояние дел на текущий момент. В Linux — это Resident Set Size (RSS); в Windows — Working Set; в Kubernetes — container_memory_working_set_bytes.
2️⃣ Сколько запрошено. Сколько памяти процесс запросил у ОС. Совсем не факт, что запрошенный объем имеется сейчас в наличии или будет доступен в будущем. Это преднамеренное поведение, называемое резервированием (overcommitment). Показатель всегда больше RSS и отражает намерения процесса. В Linux — это VmData; в Windows — Private Bytes; в Kubernetes — нет аналога.
Что это даёт?
➡️ Большой объем выделенной памяти не всегда свидетельство утечек. Часто приложение просто "жирное", потому что так написано. В таких случаях проблема с OOM решается увеличением лимитов и заведением задач на оптимизацию кода.
➡️ Если нужно контролировать и предотвращать нежелательное поведение процесса, нужно следить за динамикой запрашиваемой памяти. Например, сразу прерывать процесс, если он запросил больше лимита.
Как анализировать расход памяти?
🕚 Пилообразный график. Это нормально, например, при наличии повторяющихся задач или сборщика мусора.
🕚 На продолжительном интервале видна тенденция к росту. Это нормально, например, при наполнении кэшей или повышении нагрузки.
🕚 Взрывной рост. Это нормально, например, при повышении нагрузки или выполнении тяжёлых операций (импорт/экспорт данных, формирование отчётов и т.д.).
➡️ Проанализируйте динамику роста, сопоставьте её с тем, что вы знаете про приложение и что этому предшествовало, и уже после этого выносите вердикт, является ли поведение аномальным и говорящим об утечке памяти.
А теперь вернемся к двум возможным ситуациям:
🔥 OOM — приложение упёрлось в лимит и завершилось самостоятельно.
🔥 OOM Killer — в системе возникла острая нехватка памяти. Защитный механизм ОС вызывает OOM Killer, который убивает самые "жирные" процессы. Под раздачу может попасть кто угодно, включая само приложение. Особенно неприятно, когда приложение умирает, а контейнер продолжает жить.
❗️ Первопричины обеих ситуаций схожие. Операции с памятью инертны: память выделяется/освобождается не сразу. Сборка мусора, активные аллокации, пиковые нагрузки, шумные соседи и т.п. Всё это может привести к тому, что упираемся в лимит быстрей, чем рассчитывали. Однако OOM Killer чаще всего означает ошибку конфигурирования окружения:
➡️ Если анализ возможных причин указывает, что утечек нет, просто такой код и такие обстоятельства, то увеличиваем лимиты и спокойно идём оптимизировать код, анализируя снятый дамп памяти. Либо откатываемся. Так решается большинство ситуаций с OOM, и они не требуют героизма. В противном случае страдаем по полной. 😄
〰️ 〰️ 〰️
Будьте бдительны. И да прибудет с вами Память!❤️
#dev #devops
Думаю, каждый хотя бы раз сталкивался с Out Of Memory (OOM), а особо удачливые встречали OOM Killer. Страшней всего, когда это происходит без явных предпосылок в коде. 🙈
Скажу честно, проблемы с памятью обычно встречаю с чувством тревоги. Во-первых, чаще всего OOM происходит в приложениях с монолитной архитектурой, которые отличаются обилием функциональности. Во-вторых, как правило, OOM — инцидент, и нет времени на долгие исследования. Наконец, объективно OOM случается крайне редко, чтобы каждый был гуру в этом вопросе.
Чтобы побороть животные страхи, нужно немного разобраться в теме и попытаться классифицировать возможные ситуации. Определить, что перед нами: ошибка в коде или конфигурировании окружения. Поэтому не соглашайтесь уходить в исследование дампов, пока не узнаете всю предысторию возникновения OOM/Killer, иначе будете гоняться за призраками.
В ОС для контроля памяти есть два основных показателя:
Что это даёт?
Как анализировать расход памяти?
А теперь вернемся к двум возможным ситуациям:
limits не учитывает всплески или выбран неправильный QoS.🗂 Приход OOM/Killer всегда сопровождается повышенной нагрузкой на CPU, т.к. в этот момент система судорожно пытается найти свободные страницы памяти.
Будьте бдительны. И да прибудет с вами Память!
#dev #devops
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥2
Плохо знаешь данные - рискуешь здоровьем
Я следовал твоим рекомендациям, мой код написан почти идеально и полностью покрыт тестами. Более того, он уже год работает в проде! Почему вдруг сегодня всё упало?! 🐒
На этой неделе я наткнулся на не очень приятный кусок кода и понял, что в причины возникновения проблем с CPU/RAM не включил еще одну➡️ плохое знание своих данных.
Почему мы плохо знаем данные и как это контролировать - тема отдельного обсуждения. Не до конца разобрались в предметной области; не предполагали такого сценария использования системы; не рассчитывали на популярность какой-то функции; не заметили наличия бэкдора; тестовый стенд содержал мало данных; временное решение осталось постоянным; всосали всю таблицу в кэш и т.д. Главное, что подобные упущения приводят к тому, что в некоторых сценариях существующие алгоритмы начинают работать крайне неэффективно или даже деструктивно. И мы на собственной шкуре начинаем понимать, что такое сложность🫥
Например, недавно был кейс. Пользователи нашего API догадались завести "синтетический агрегат", на который отношением many-to-one подвесили несколько тысяч связанных сущностей. Изначально предполагалось, что количество связей не будет превышать сотни. Естественно, что большая часть кода была написана без расчёта на подобный объем данных.
Но вот на днях попался пример откровенного вредительства. Возможно, некоторые скажут, что это могло быть временное решение, которое осталось постоянным, но на самом деле, немного зная историю проекта, я так сказать не могу. Приведу пример кода на Java (я его изменил, но суть проблемы должна быть ясна).
Вопрос даже не в том, как это сделано, а в том, что тут делается и почему! Ясно, что с ростом таблицы
➡️ Если мы плохо знаем свои данные, мы закладываем уродливую пасхалку и мину замедленного действия.
Как этого избежать?
➡️ При работе с данными всегда себя спрашиваю: "А что если?" Что, если тут будет не 100 элементов, а 100000? Что, если этот запрос будет выполняться не 10 мс, а 10 секунд?
Конечно, это не всегда спасает, но приём точно рабочий!😏
#dev
Я следовал твоим рекомендациям, мой код написан почти идеально и полностью покрыт тестами. Более того, он уже год работает в проде! Почему вдруг сегодня всё упало?! 🐒
На этой неделе я наткнулся на не очень приятный кусок кода и понял, что в причины возникновения проблем с CPU/RAM не включил еще одну
Почему мы плохо знаем данные и как это контролировать - тема отдельного обсуждения. Не до конца разобрались в предметной области; не предполагали такого сценария использования системы; не рассчитывали на популярность какой-то функции; не заметили наличия бэкдора; тестовый стенд содержал мало данных; временное решение осталось постоянным; всосали всю таблицу в кэш и т.д. Главное, что подобные упущения приводят к тому, что в некоторых сценариях существующие алгоритмы начинают работать крайне неэффективно или даже деструктивно. И мы на собственной шкуре начинаем понимать, что такое сложность
O(n), проблема с N+1 запросами, почему файлы нужно обрабатывать блоками, почему не нужно логику засовывать в транзакцию БД и т.п. Например, недавно был кейс. Пользователи нашего API догадались завести "синтетический агрегат", на который отношением many-to-one подвесили несколько тысяч связанных сущностей. Изначально предполагалось, что количество связей не будет превышать сотни. Естественно, что большая часть кода была написана без расчёта на подобный объем данных.
Но вот на днях попался пример откровенного вредительства. Возможно, некоторые скажут, что это могло быть временное решение, которое осталось постоянным, но на самом деле, немного зная историю проекта, я так сказать не могу. Приведу пример кода на Java (я его изменил, но суть проблемы должна быть ясна).
List<City> getCities(String regionCode) {
return em.createNativeQuery(
"SELECT DISTINCT " +
" city_code AS code, " +
" city_name AS name " +
"FROM patients " +
"WHERE region_code = :region " +
"ORDER BY city_name ASC",
City.class)
.setParameter("region", regionCode)
.getResultList();
}Вопрос даже не в том, как это сделано, а в том, что тут делается и почему! Ясно, что с ростом таблицы
patients будет расти время выполнения запроса; следовательно, соединение БД будет держаться дольше; быстрей упрёмся в нехватку соединений. Вишенка на торте: у таблицы patients нет индекса на region_code.Как этого избежать?
Конечно, это не всегда спасает, но приём точно рабочий!
#dev
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥1
Архитектура лечит причину
Архитектура должна лечить причину; в противном случае будете обречены бесконечно бороться с симптомами. Постараюсь объяснить эту аксиому на трёх кейсах из практики.⬇️
У меня не получилось без потери качества уместить весь материал в размер поста, поэтому решил не ограничивать себя в объеме и написал небольшую статью. 🙈 Здесь оставлю прямые ссылки на описание каждого кейса.
1️⃣ Аналог LeetCode
2️⃣ Поиск медицинских документов
3️⃣ Гетерогенное хранилище документов
Если архитектура не решает корень проблемы, пересматривайте её! Цепляясь за неудачное архитектурное решение, вы провоцируете лишь бесконтрольное усложнение системы. В итоге у разработчиков, как у самураев, не будет цели, только путь; каждый следующий шаг на этом пути будет тяжелей предыдущего, а повернуть назад однажды может быть очень непросто. Не становитесь самураями, своевременно производите реструктуризацию решения и не забывайте о неизбежности эволюции программных систем.
И еще одно важное дополнение. Если кто-то озадачился вопросом, почему предлагаемые выше решения не были очевидны изначально. Во-первых, следует вспомнить закон Гола: сложные рабочие системы получаются только из простых и рабочих. Во-вторых, иногда осознание причины требует глубокого погружения в детали проекта и должной широты взгляда на все процессы системы.
#arch
Архитектура должна лечить причину; в противном случае будете обречены бесконечно бороться с симптомами. Постараюсь объяснить эту аксиому на трёх кейсах из практики.
У меня не получилось без потери качества уместить весь материал в размер поста, поэтому решил не ограничивать себя в объеме и написал небольшую статью. 🙈 Здесь оставлю прямые ссылки на описание каждого кейса.
Если архитектура не решает корень проблемы, пересматривайте её! Цепляясь за неудачное архитектурное решение, вы провоцируете лишь бесконтрольное усложнение системы. В итоге у разработчиков, как у самураев, не будет цели, только путь; каждый следующий шаг на этом пути будет тяжелей предыдущего, а повернуть назад однажды может быть очень непросто. Не становитесь самураями, своевременно производите реструктуризацию решения и не забывайте о неизбежности эволюции программных систем.
И еще одно важное дополнение. Если кто-то озадачился вопросом, почему предлагаемые выше решения не были очевидны изначально. Во-первых, следует вспомнить закон Гола: сложные рабочие системы получаются только из простых и рабочих. Во-вторых, иногда осознание причины требует глубокого погружения в детали проекта и должной широты взгляда на все процессы системы.
#arch
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6👍4❤1⚡1🤔1
Domain Vision Statement
Волею судьбы мне достался крайне аскетичный репозиторий. Постепенно приводя его в порядок, продолжил думать, чего ещё обычно не хватает на старте знакомства с проектом.👔
Вот приходите вы в новую команду, уже успели прочитать базовую документацию для знакомства с проектом и предметной областью, подходите к наставнику, а он вам: "Давай расскажу суть проекта, познакомлю со структурой и с чем придётся работать в ближайшее время." И далее обычно следует, действительно, короткий, но очень ёмкий, точный, последовательный и понятный рассказ. Рассказ, которого вы не видели ни в документации, ни в README репозитория.
Скажу честно, я сам так делал много раз, объясняя суть проекта новым сотрудникам, но всегда старался это делать до того, как они пойдут читать первые страницы документации или смотреть код. И однажды я решил прекратить заниматься этой полезной, но очень неблагодарной работой.
Код и его первый запуск в локальном окружении — это первое, что хочет видеть каждый разработчик, вступающий в проект. Поэтому мне очень импонирует подход, когда ключевые знания о технической реализации проекта лежат в репозитории с кодом. Пусть первое, что видит каждый, кто открывает репозиторий, будет README, в котором в самом начале изложена суть проекта.
Вот ровно то, чтобы вы рассказали новому члену команды в первые 5 минут разговора. Два-три абзаца: просто, чётко и по делу. Это изложение должно определять цель и назначение проекта и конкретно данной кодовой базы.
Что включить в описание?
☑️ Название проекта, понятное всем и каждому. Без сложных аббревиатур и терминов предметной области, т.к. с этим человек познакомится позже.
☑️ Общая цель проекта. Какую основную задачу или проблему решаете. Возможно, тут придётся поверхностно пояснить небольшие особенности предметной области.
☑️ Положение проекта в общей экосистеме. Как именно встраиваетесь в общее решение, описание назначения интеграций с внешними системами.
❗️ Не грузите деталями, которые могут измениться. Никаких микросервисов, баз данных или технологических особенностей! Основной фокус и упор — создание правильного представления о предназначении проекта.
Не получилось с первого раза?
➡️ Не страшно! Отлаживайте и итеративно дорабатывайте это описание. Можете начать с одного предложения или абзаца. Сделайте сами или попросите AI сгенерировать базовый вариант. Вы всегда сможете добавить необходимые детали, по мере своего погружения в предметную область.
Хорошо, давай пример!
Если однажды решу, что это описание не работает как нужно, сделаю его лучше и точней!
И уже после этого я ожидаю увидеть какой-то интерактивный навигатор по репозиторию, включающий всё то, что помогает разобраться со структурой и начать работу.
Ты не придумал ничего нового!
➡️ Да, верно. Эрик Эванс назвал это описание "Domain Vision Statement", указывая, что оно задает разработчикам общее направление, на чем должны быть сконцентрированы все усилия. Фокус не на технологиях и алгоритмах, а на решаемой задаче. Именно эту эстафету и нужно передать на входе.
И еще. Пишите не для себя в будущем, а для себя в прошлом! Пишите для незнакомца, который только-только начинает работу с проектом. И будет замечательно, если такие незнакомцы будут выступать основными рецензентами.
〰️ 〰️ 〰️
А что у вас в README корня репозитория? Как вы доносите суть до новичков? 😉
#arch #dev
Волею судьбы мне достался крайне аскетичный репозиторий. Постепенно приводя его в порядок, продолжил думать, чего ещё обычно не хватает на старте знакомства с проектом.
Вот приходите вы в новую команду, уже успели прочитать базовую документацию для знакомства с проектом и предметной областью, подходите к наставнику, а он вам: "Давай расскажу суть проекта, познакомлю со структурой и с чем придётся работать в ближайшее время." И далее обычно следует, действительно, короткий, но очень ёмкий, точный, последовательный и понятный рассказ. Рассказ, которого вы не видели ни в документации, ни в README репозитория.
Скажу честно, я сам так делал много раз, объясняя суть проекта новым сотрудникам, но всегда старался это делать до того, как они пойдут читать первые страницы документации или смотреть код. И однажды я решил прекратить заниматься этой полезной, но очень неблагодарной работой.
Код и его первый запуск в локальном окружении — это первое, что хочет видеть каждый разработчик, вступающий в проект. Поэтому мне очень импонирует подход, когда ключевые знания о технической реализации проекта лежат в репозитории с кодом. Пусть первое, что видит каждый, кто открывает репозиторий, будет README, в котором в самом начале изложена суть проекта.
Вот ровно то, чтобы вы рассказали новому члену команды в первые 5 минут разговора. Два-три абзаца: просто, чётко и по делу. Это изложение должно определять цель и назначение проекта и конкретно данной кодовой базы.
Что включить в описание?
Не получилось с первого раза?
Хорошо, давай пример!
Основное назначение проекта — формирование реестра с данными о паллиативных пациентах и организация процесса сопровождения и ухода за ними, а именно: планирование записей на осмотр, организация работы выездной службы и проведение осмотров. Реестр формируется на основе событий от внешних служб, интеграция с которыми производится через корпоративную шину сообщений. Некоторые недостающие данные запрашиваются у внешних сервисов (например, данные о пациенте, данные о смерти, поиск медицинских документов)...
Если однажды решу, что это описание не работает как нужно, сделаю его лучше и точней!
И уже после этого я ожидаю увидеть какой-то интерактивный навигатор по репозиторию, включающий всё то, что помогает разобраться со структурой и начать работу.
Ты не придумал ничего нового!
И еще. Пишите не для себя в будущем, а для себя в прошлом! Пишите для незнакомца, который только-только начинает работу с проектом. И будет замечательно, если такие незнакомцы будут выступать основными рецензентами.
А что у вас в README корня репозитория? Как вы доносите суть до новичков? 😉
#arch #dev
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤4🔥2
Workflow Event pattern
Зрелость системы в том числе определяется её прочностью и устойчивостью. Если адаптируемость — важное архитектурное свойство системы, то она должна уметь подстраиваться под определенные условия эксплуатации. Сегодня хочу поделиться интересным шаблоном, в который очень хорошо вписывается использование AI/ML. 🤖
Контекст
Имеется источник слабоструктурированных событий или событий, в которых допускаются ошибки ввода или частичное нарушение формата. Необходимо организовать потоковую обработку таких событий.
Чтобы лучше понять контекст, можно рассмотреть несколько возможных ситуаций.
✅ Интеграция с внешними системами. Источником событий является сервис, на качество которого мы не можем повлиять. Например, какой-то баг или особенность работы внешней системы, приводящая к нарушению контракта.
✅ Ручной ввод или частичное заполнение. Корректировка пользовательского ввода или необходимость обогащения события данными. Например, уточнить адрес заказа по GPS-координатам пользователя.
✅ Некачественная или шумная телеметрия. Показания выходят за допустимый диапазон, и трудно сказать, что это было: случайный выброс или начало нового тренда из-за недели распродаж. Постанализ может сделать алармы более интеллектуальными.
✅ Первичная отбраковка событий. Основной обработчик производит быструю проверку события на пригодность. Например, грубая/быстрая проверка выявила признаки необходимости блокировки транзакции, и нужна более тщательная проверка.
✅ Устаревшие справочные данные. Внешние системы продолжают присылать события со ссылкой на устаревшие справочные данные. Чтобы не сломать интеграцию, вместо отказа можно делать автоматическое сопоставление и корректировку.
Проблема
Некорректное событие нарушает workflow его обработки или даже останавливает обработку всего потока событий (этого и всех последующих). Последнее характерно для log-based-брокеров.
Решение
Если основной обработчик (Event Consumer) не может обработать очередное событие, оно направляется на детальный анализ и корректировку (Event Collector). Причиной может послужить, например, исключение при чтении данных события (десериализация, приведение к типу, нарушение формата и т.д.), недостаточность данных, нарушение диапазона допустимых значений и т.д. и т.п. в зависимости от прикладного сценария. Анализ и корректировка выполняется асинхронно, а основной обработчик тем временем переходит к следующему событию в очереди.
Корректировщик (Event Collector) может:
⛔️ отбросить событие, как действительно некорректное;
✅ исправить его и направить на повторную обработку;
➡️ отправить на интеллектуальное исправление (AI/ML Corrector).
Предполагается, что корректировщик (Event Corrector) работает на базе аналитического алгоритма, а интеллектуальное исправление (AI/ML Corrector) производится на базе AI/ML как попытка автоматизировать действия человека, например, сотрудников службы поддержки.
Интеллектуальный корректировщик (AI/ML Corrector) может:
⛔️ отбросить событие, как действительно некорректное;
✅ исправить его и направить на повторную обработку;
🧑 призвать на помощь человека.
Шаги аналитической и интеллектуальной корректировки могут взаимодополнять или заменять друг друга. Также допустимо (и даже разумно), если интеллектуальная корректировка будет вызываться асинхронно.
Плюсы
👍 Непрерывная обработка потока событий — некорректные события не блокируют поток.
👍 Возможное увеличение скорости обработки — некорректные события откладываются.
👍 Улучшение адаптируемости системы — подстройка под реалии.
Минусы
👎 Решение никак не учитывает и может нарушить порядок следования событий.
Если это критически важно, то можно предложить, как минимум, два возможных решения.
✅ Сделать событие, содержащее все элементы, порядок обработки которых важен. Иначе говоря, мелкие события группируются в одно крупное (batch event), которое либо целиком обрабатывается, либо целиком отправляется на корректировку.
✅ Сделать корректировку частью конвейера обработки. Однако это уже совершенно другой архитектурный подход.
#tip #arch #ai
Зрелость системы в том числе определяется её прочностью и устойчивостью. Если адаптируемость — важное архитектурное свойство системы, то она должна уметь подстраиваться под определенные условия эксплуатации. Сегодня хочу поделиться интересным шаблоном, в который очень хорошо вписывается использование AI/ML. 🤖
Контекст
Имеется источник слабоструктурированных событий или событий, в которых допускаются ошибки ввода или частичное нарушение формата. Необходимо организовать потоковую обработку таких событий.
Чтобы лучше понять контекст, можно рассмотреть несколько возможных ситуаций.
Проблема
Некорректное событие нарушает workflow его обработки или даже останавливает обработку всего потока событий (этого и всех последующих). Последнее характерно для log-based-брокеров.
Решение
Если основной обработчик (Event Consumer) не может обработать очередное событие, оно направляется на детальный анализ и корректировку (Event Collector). Причиной может послужить, например, исключение при чтении данных события (десериализация, приведение к типу, нарушение формата и т.д.), недостаточность данных, нарушение диапазона допустимых значений и т.д. и т.п. в зависимости от прикладного сценария. Анализ и корректировка выполняется асинхронно, а основной обработчик тем временем переходит к следующему событию в очереди.
Корректировщик (Event Collector) может:
Предполагается, что корректировщик (Event Corrector) работает на базе аналитического алгоритма, а интеллектуальное исправление (AI/ML Corrector) производится на базе AI/ML как попытка автоматизировать действия человека, например, сотрудников службы поддержки.
Интеллектуальный корректировщик (AI/ML Corrector) может:
Шаги аналитической и интеллектуальной корректировки могут взаимодополнять или заменять друг друга. Также допустимо (и даже разумно), если интеллектуальная корректировка будет вызываться асинхронно.
Плюсы
Минусы
Если это критически важно, то можно предложить, как минимум, два возможных решения.
#tip #arch #ai
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍6🔥2
Intention-Revealing Interface
Я думаю, что у каждого было такое при чтении кода. В одном случае всё понятно с первой строчки, метода, класса. В другом случае можно перерыть тонну кода, но уверенности в его понимании не возникает. В первом случае часто говорят, что его писал профи. Так ли это? И как научиться писать понятный код?!
🔻 Сразу сделаю оговорку, что понятный код — дело относительное, ведь чтобы иметь возможность что-то понять, нужно иметь какую-то базу, необходимую для возникновения понимания. В дальнейших рассуждениях будем считать, что у нас есть такая база при знакомстве с проектом и его кодом. Также не будем рассматривать случаи низкоуровневой оптимизации, когда код пишется в угоду производительности, а не читабельности.
Рассматриваемый ниже принцип в каком-то смысле является следствием второго закона архитектуры, и для себя я коротко его формулирую так:
Говоря "код", я в том числе имею в виду и его организацию: структура проекта, наименование каталогов, модулей, файлов, классов, методов, аргументов и переменных.
➡️ Код является отражением каких-то операций предметной области. Если он написан в стиле "как", то он не раскрывает намерения написанного, не проясняет логический смысл производимых операций, создаёт когнитивную перегрузку и, наконец, обесценивает инкапсуляцию. Такой код обычно нуждается в комментариях, без которых очень легко сделать неправильные выводы, допустить ошибки, нарушить авторскую задумку или даже архитектуру. Всё это не оставляет читателю шансов на выстраивание короткой и единственно верной логической цепочки, лежащей в основе реализации, необходимой для запуска критического мышления и осознанного сопровождения.
Код, написанный в стиле "как", напоминает обезьяну, которая таскает кокосы из одной корзины в другую. 🐒 И даже обезьяна не ответит вам на вопрос, почему именно она; почему кокосы, а не бананы; и почему их нужно переносить из корзины в корзину. И чтобы найти ответы, приходится перерыть не только код, но и всё в округе: документацию, историю репозитория и задач, данные в базе, и даже поговорить с людьми, кто в курсе истории проекта.
Перейдем к примерам.
Посмотрите на следующий отвратительно красочный пример-гиперболу. В нём беспощадно использован мощный инструмент — Spring Data JPA Query Methods, который строит SQL-запрос по имени метода.
Что мы вынуждены делать в таких случаях? Провалиться в реализацию метода и начать ментально исполнять код.
🤖 findBy PersonId In (personIds) And DeletedAt Null And Bindings NotNull OrderBy PersonId Asc UpdatedAt Desc
Давайте снимем эту ненужную ментальную нагрузку.
Согласитесь, что стало "легче", но этого недостаточно! Метод по-прежнему отвечает на вопрос "как".
Допустим, нужен не просто список аккаунтов, а список аккаунтов, удовлетворяющий условиям рассылки уведомлений. В итоге, используя имеющийся словарь предметной области проекта (ubiquitous language), принимаем решение назвать метод
Рассмотренный принцип называется Intention-Revealing Interface. Он является шаблоном рефакторинга в DDD и естественен для последователей TDD. Помимо прочего, принцип провоцирует писать тесты, которые проверяют функциональность, а не то, как написан код.
May the Clarity be with you!❤️
#arch #dev
Я думаю, что у каждого было такое при чтении кода. В одном случае всё понятно с первой строчки, метода, класса. В другом случае можно перерыть тонну кода, но уверенности в его понимании не возникает. В первом случае часто говорят, что его писал профи. Так ли это? И как научиться писать понятный код?!
Рассматриваемый ниже принцип в каком-то смысле является следствием второго закона архитектуры, и для себя я коротко его формулирую так:
Код должен отвечать на вопрос что, а не как.
Говоря "код", я в том числе имею в виду и его организацию: структура проекта, наименование каталогов, модулей, файлов, классов, методов, аргументов и переменных.
Код, написанный в стиле "как", напоминает обезьяну, которая таскает кокосы из одной корзины в другую. 🐒 И даже обезьяна не ответит вам на вопрос, почему именно она; почему кокосы, а не бананы; и почему их нужно переносить из корзины в корзину. И чтобы найти ответы, приходится перерыть не только код, но и всё в округе: документацию, историю репозитория и задач, данные в базе, и даже поговорить с людьми, кто в курсе истории проекта.
Давайте такие имена элементам кода — классам, методам и т.п., чтобы они описывали их назначение и результат, но не реализацию.
Перейдем к примерам.
Посмотрите на следующий отвратительно красочный пример-гиперболу. В нём беспощадно использован мощный инструмент — Spring Data JPA Query Methods, который строит SQL-запрос по имени метода.
interface AccountRepository {
List<Account> findByPersonIdInAndDeletedAtNullAndBindingsNotNullOrderByPersonIdAscUpdatedAtDesc(List<UUID> personIds);
}Что мы вынуждены делать в таких случаях? Провалиться в реализацию метода и начать ментально исполнять код.
Давайте снимем эту ненужную ментальную нагрузку.
@Query("""
SELECT a
FROM Account a
WHERE a.personId IN :personIds
AND a.deletedAt IS NULL
AND a.bindings IS NOT NULL
ORDER BY a.personId ASC, a.updatedAt DESC
""")
List<Account> findByPersonId(List<UUID> personIds);Согласитесь, что стало "легче", но этого недостаточно! Метод по-прежнему отвечает на вопрос "как".
Допустим, нужен не просто список аккаунтов, а список аккаунтов, удовлетворяющий условиям рассылки уведомлений. В итоге, используя имеющийся словарь предметной области проекта (ubiquitous language), принимаем решение назвать метод
findDeliverableAccounts. Так мы чётко выражаем намерения и исключаем какие-либо попытки сделать неверные предположения о назначении этого кода.Рассмотренный принцип называется Intention-Revealing Interface. Он является шаблоном рефакторинга в DDD и естественен для последователей TDD. Помимо прочего, принцип провоцирует писать тесты, которые проверяют функциональность, а не то, как написан код.
May the Clarity be with you!
#arch #dev
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4🔥3👍2
Я принёс тебе аналитику
Наши действия или намерения – это проекция нашего сознания. Есть какой-то внешний стимул, есть субъективная интерпретация этого стимула. Стоит ли говорить, что интерпретация может быть неверной?! На подобные мысли меня навел предыдущий пост и недавние события на текущем проекте.
Эта проблема известна всем, кто работает по принципу, когда между пользователем, бизнесом и разработчиком стоит некоторый посредник. Это может быть представитель заказчика, бизнес-аналитик, системный аналитик, архитектор или автор задачи. Вся эта цепочка посредников часто образует "глухой телефон", результат работы которого как цунами обрушивается на непосредственного исполнителя.😮💨
Императив не работает так, как вы хотите! Императив – это ваша субъективная проекция исходной мысли, не более. Не случайно приверженцы гибких методологий очень любят такой инструмент, как User Story, ведь он несет в себе изначальный посыл и предполагает наличие обратной связи. Имея цепочку посредников-аналитиков-архитекторов между пользователем и разработчиком, обязательно включайте в описание сведения о том, для чего это делается, почему это делается, что на самом деле от нас ждут, укажите важные требования и ограничения. И только после этого, если считаете, что это действительно несет ценность, опишите ваш способ решения – как вы предлагаете это сделать. При этом под словом "как" я больше имею в виду что-то близкое к Use Cases или пошаговому формату без перегрузки деталями, которые непременно устареют.
Что это даёт?
Сколько раз мне приносили многостраничные документы, изначальный посыл которых становился понятен только после прочтения последнего предложения; и только после того, как я прочитал это на раза 2-3. Пожалуйста, никогда не делайте так! Пусть в самом начале повествования будет побуждающий мотив, а затем ваша версия решения. Видя цель, читатель вовлекается постепенно, его мыслительный процесс практически сразу запускает "обратную связь", критическое мышление, которое будет работать от первой до последней страницы. В результате он придёт к вам с правильными вопросами и, возможно, укажет на ошибки или недочёты, и их можно будет устранить на ранних этапах.
Свежий пример того, как не нужно делать.
Всей командой разбирались со странным поведением приложения. Если быть конкретным, то приложение должно было отображать дату последнего вызова скорой помощи. Однако после первого вызова скорой эта дата не отображалась. По коду всё выглядело как ошибка разработчика. Тестов, естественно, не было; а в системной аналитике был только императив – пошаговый алгоритм, больше напоминающий псевдокод. К счастью, к концу дня мы смогли найти документ с бизнес-постановкой, в которой скромно затесалась фраза: "Вызов скорой помощи является для пользователя сигнальной информацией, начиная со второго". Эта простая и короткая фраза могла бы сэкономить кучу времени и сил. Трудно было её добавить в постановку задачи или в комментарий к коду, написать тест для этого кейса? Не думаю.
➡️ Если коротко, то предлагаю и настаиваю всегда сохранять исходный контекст, не терять его в цепочке документов, и даже дублировать при необходимости. Использовать преимущественно декларативный, а не императивный стиль изложения.
Только так вы добьётесь эффективности в работе и получите желаемый результат.
#arch #tip
Наши действия или намерения – это проекция нашего сознания. Есть какой-то внешний стимул, есть субъективная интерпретация этого стимула. Стоит ли говорить, что интерпретация может быть неверной?! На подобные мысли меня навел предыдущий пост и недавние события на текущем проекте.
Эта проблема известна всем, кто работает по принципу, когда между пользователем, бизнесом и разработчиком стоит некоторый посредник. Это может быть представитель заказчика, бизнес-аналитик, системный аналитик, архитектор или автор задачи. Вся эта цепочка посредников часто образует "глухой телефон", результат работы которого как цунами обрушивается на непосредственного исполнителя.
Императив не работает так, как вы хотите! Императив – это ваша субъективная проекция исходной мысли, не более. Не случайно приверженцы гибких методологий очень любят такой инструмент, как User Story, ведь он несет в себе изначальный посыл и предполагает наличие обратной связи. Имея цепочку посредников-аналитиков-архитекторов между пользователем и разработчиком, обязательно включайте в описание сведения о том, для чего это делается, почему это делается, что на самом деле от нас ждут, укажите важные требования и ограничения. И только после этого, если считаете, что это действительно несет ценность, опишите ваш способ решения – как вы предлагаете это сделать. При этом под словом "как" я больше имею в виду что-то близкое к Use Cases или пошаговому формату без перегрузки деталями, которые непременно устареют.
Что это даёт?
Сколько раз мне приносили многостраничные документы, изначальный посыл которых становился понятен только после прочтения последнего предложения; и только после того, как я прочитал это на раза 2-3. Пожалуйста, никогда не делайте так! Пусть в самом начале повествования будет побуждающий мотив, а затем ваша версия решения. Видя цель, читатель вовлекается постепенно, его мыслительный процесс практически сразу запускает "обратную связь", критическое мышление, которое будет работать от первой до последней страницы. В результате он придёт к вам с правильными вопросами и, возможно, укажет на ошибки или недочёты, и их можно будет устранить на ранних этапах.
Свежий пример того, как не нужно делать.
Всей командой разбирались со странным поведением приложения. Если быть конкретным, то приложение должно было отображать дату последнего вызова скорой помощи. Однако после первого вызова скорой эта дата не отображалась. По коду всё выглядело как ошибка разработчика. Тестов, естественно, не было; а в системной аналитике был только императив – пошаговый алгоритм, больше напоминающий псевдокод. К счастью, к концу дня мы смогли найти документ с бизнес-постановкой, в которой скромно затесалась фраза: "Вызов скорой помощи является для пользователя сигнальной информацией, начиная со второго". Эта простая и короткая фраза могла бы сэкономить кучу времени и сил. Трудно было её добавить в постановку задачи или в комментарий к коду, написать тест для этого кейса? Не думаю.
Только так вы добьётесь эффективности в работе и получите желаемый результат.
#arch #tip
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4🔥2👍1
Словарь предметной области
Мне много раз приходилось знакомиться с новыми для себя проектами. Для ускорения понимания проекта и кода я каждый раз начинал с одного и того же: составлял словарь предметной области. 📔
И это не про графоманию, а про необходимость и реально рабочий инструмент – базис Domain-Driven Design – Ubiquitous Language. Чтобы общаться на иностранном языке, нужно пополнять словарный запас.
Вы можете обратиться к трудам Эрика Эванса, но не найдете там того, как именно должно выглядеть описание языка. Поэтому делюсь своим способом оформления и использования словаря.
Оформление
Формат словаря прост – это таблица из трёх колонок:
1️⃣ Термин – как должно быть.
2️⃣ Синонимы – как на самом деле в коде и моделях.
3️⃣ Определение – очень краткое толкование простым языком.
Термин и синонимы часто просто слова, иногда аббревиатуры или словосочетания. При необходимости в синонимах можно указать перевод.
Например:
🕚 Термин:
🕚 Синонимы:
🕚 Определение:
Использование
Синонимы позволяют увидеть отсутствие терминологической однородности. Это может быть нормально, но чаще является признаком наличия проблем в коде или модели, а именно:
➡️ В коде нет единства именования. Не страшно, но это делает код более хаотичным и менее понятным; провоцирует развитие беспорядка и появление ошибок. Это сродни тому, когда иностранец говорит с акцентом, а абориген его плохо понимает.
➡️ Модель имеет неточность или какое-то упрощение. К сожалению, это распространенная проблема, и синонимы часто скрывают какие-то бизнес-процессы, с которыми вы ещё не столкнулись или не выявили. Подобные ошибки могут обойтись очень дорого, но словарь позволяет заметить эту проблему заранее.
❗️ Словарь не всегда прямолинеен: "термин – синонимы". Бывает, когда разные термины по факту имеют один и тот же синоним. И это уже очень серьёзный сигнал!
Например, в одном из проектов перечисление (enum) объединяло в один список два разных набора, которые использовались в двух разных бизнес-контекстах. Как например, если бы вы объединили в один список месяцы и дни недели. В реальной жизни эти списки используются по отдельности, но в коде они были объединены в один, который интерпретировался в каждой ситуации по-своему. Не трудно догадаться, какие проблемы в коде может породить подобное. Самое безобидное – это увеличение цикломатической сложности из-за обилия проверок и фильтров.
В таких случаях я создаю в словаре столько терминов, сколько требует прикладная область, но в синонимы записываю одно и тоже.
Хранение
Словарь предлагаю хранить в Markdown-файле в корне git-репозитория. И пусть корневой
Не рекомендую использовать внешние wiki вроде Confluence по многим причинам. Во-первых, словарь должен отражать текущее положение дел, следовательно, требует версионирования. Во-вторых, нет необходимости доступа к внешним ресурсам, что удобно как для человека, так и для машины (AI). Хотите словарь в wiki – сделайте его копию, но оригинал пусть будет в репозитории.
Достоинства
1️⃣ Ускорение входа в проект. Это реально так: 30 минут на освоение словаря и вы готовы читать и понимать код и диаграммы, разговаривать на "птичьем" языке с коллегами по цеху. 🐥
2️⃣ Обнаружение неточностей в моделях. Словарь позволяет вскрывать проблемы моделирования и скрытые концепты.
3️⃣ Помощь в унификации именования в коде. В идеале все синонимы должны стать терминами.
4️⃣ Реальное подспорье для онбординга и AI-агентов. Думаю, что это становится крайне важно в современных реалиях.
И пусть ваш код говорит без акцента!❤️
#arch #devops
Мне много раз приходилось знакомиться с новыми для себя проектами. Для ускорения понимания проекта и кода я каждый раз начинал с одного и того же: составлял словарь предметной области. 📔
И это не про графоманию, а про необходимость и реально рабочий инструмент – базис Domain-Driven Design – Ubiquitous Language. Чтобы общаться на иностранном языке, нужно пополнять словарный запас.
Вы можете обратиться к трудам Эрика Эванса, но не найдете там того, как именно должно выглядеть описание языка. Поэтому делюсь своим способом оформления и использования словаря.
Оформление
Формат словаря прост – это таблица из трёх колонок:
Термин и синонимы часто просто слова, иногда аббревиатуры или словосочетания. При необходимости в синонимах можно указать перевод.
Например:
ProblemTask, ЗадачаЗадача по программированиюИспользование
Синонимы позволяют увидеть отсутствие терминологической однородности. Это может быть нормально, но чаще является признаком наличия проблем в коде или модели, а именно:
Например, в одном из проектов перечисление (enum) объединяло в один список два разных набора, которые использовались в двух разных бизнес-контекстах. Как например, если бы вы объединили в один список месяцы и дни недели. В реальной жизни эти списки используются по отдельности, но в коде они были объединены в один, который интерпретировался в каждой ситуации по-своему. Не трудно догадаться, какие проблемы в коде может породить подобное. Самое безобидное – это увеличение цикломатической сложности из-за обилия проверок и фильтров.
В таких случаях я создаю в словаре столько терминов, сколько требует прикладная область, но в синонимы записываю одно и тоже.
Хранение
Словарь предлагаю хранить в Markdown-файле в корне git-репозитория. И пусть корневой
readme.md имеет ссылку на этот файл где-то в самом начале.Не рекомендую использовать внешние wiki вроде Confluence по многим причинам. Во-первых, словарь должен отражать текущее положение дел, следовательно, требует версионирования. Во-вторых, нет необходимости доступа к внешним ресурсам, что удобно как для человека, так и для машины (AI). Хотите словарь в wiki – сделайте его копию, но оригинал пусть будет в репозитории.
Достоинства
🗂 Если у вас еще нет словаря, то у меня для вас отличная новость: хорошую заготовку можно легко и быстро сгенерировать с помощью AI. Например, используя такой промт.
И пусть ваш код говорит без акцента!
#arch #devops
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍3🔥3
Consumer-Driven Contracts
Относительно давно интересуюсь темой Consumer-Driven Contracts и тестированием контрактов. В своём текущем проекте начал пробовать использовать Pact (и он уже помог найти несколько багов). И вот недавно мне попалась интересная подборка ссылок на эту тему.
Скажу честно, мне не удалось просмотреть весь найденный материал, но зато я актуализировал ссылки из оригинальной статьи. Результат решил оставить у себя на странице, чтобы никуда не пропало.😏
➡️ Подборка материалов на тему Consumer-Driven Contracts ⬅️
От себя лично добавлю, что для входа в тему лучше почитать соответствующие главы из книги "Microservices Patterns" (Chris Richardson). Недавно вышло 2-е издание, а 1-е есть в русском переводе. Книга хорошо и пошагово разбирает многие нюансы разработки микросервисов, включая тестирование. Особенно полезно, если вы ведёте разработку на Java-стеке.
Более краткий и универсальный вариант изучения – это документация Pact. Pact поддерживает множество языков и, кажется, в своей документации они собрали самую лучшую и актуальную информацию на тему CDC. Кстати, иллюстрация к посту как раз с их сайта.
〰️ 〰️ 〰️
🔥 Также приглашаю вас 17-18 апреля принять участие в конференции Merge 2026, которая пройдёт в Казани (Иннополис). Промокод MEZHOV даёт скидку 20%. Также у меня есть 1 бесплатный билет, который я готов отдать тому, кто хочет и может побывать на этой конференции. Если что, то пишите в ЛС или в комментариях к посту. 😉
#tip
Относительно давно интересуюсь темой Consumer-Driven Contracts и тестированием контрактов. В своём текущем проекте начал пробовать использовать Pact (и он уже помог найти несколько багов). И вот недавно мне попалась интересная подборка ссылок на эту тему.
🗂 Consumer-Driven Contracts и инструменты, автоматизирующие этот процесс, хорошо подходят при использовании MSA и в случае, когда в проекте есть важные интеграции, сломать которые было бы кране нежелательно.
Скажу честно, мне не удалось просмотреть весь найденный материал, но зато я актуализировал ссылки из оригинальной статьи. Результат решил оставить у себя на странице, чтобы никуда не пропало.
От себя лично добавлю, что для входа в тему лучше почитать соответствующие главы из книги "Microservices Patterns" (Chris Richardson). Недавно вышло 2-е издание, а 1-е есть в русском переводе. Книга хорошо и пошагово разбирает многие нюансы разработки микросервисов, включая тестирование. Особенно полезно, если вы ведёте разработку на Java-стеке.
Более краткий и универсальный вариант изучения – это документация Pact. Pact поддерживает множество языков и, кажется, в своей документации они собрали самую лучшую и актуальную информацию на тему CDC. Кстати, иллюстрация к посту как раз с их сайта.
#tip
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4❤2
Неожиданный параллелизм при обработке сообщений в Kafka
Есть распространённое заблуждение, что в рамках одной консюмер-группы сообщения одной и той же партиции топика Apache Kafka обрабатываются последовательно, одно за другим. И конкурентный доступ к сообщениям партиции со стороны консюмера невозможен. Спешу вас разуверить, такое возможно, и вот вам моя история.
Рассмотрим последовательность событий:
1️⃣ Партиция
2️⃣
3️⃣
4️⃣ Случилась ребалансировка.
5️⃣ Иных консюмеров нет.
6️⃣ Партиция
7️⃣
8️⃣
➡️ Что тут может пойти не так?
Если консюмер осуществляет обработку событий в отдельном пуле потоков (worker threads pool), то копии считанных сообщений будут находиться в памяти клиентского приложения. Следовательно, в момент, когда консюмер после ребалансировки еще раз считает и начнёт обработку тех же самых сообщений, но в рамках другого потока из пула, возникает коллизия. Как минимум, могут существовать два потока, которые одновременно обрабатывают одни и те же сообщения.
➡️ Может ли такое произойти в вашем проекте?
В целом, может, и вот по какой причине.
С одной стороны, Kafka предлагает достаточно простой и универсальный API для обслуживания сообщений топика. Продюсер пишет сообщения, консюмер их читает, обрабатывает и сдвигает указатель на следующую пачку сообщений. Партиция, действительно назначается одному-единственному консюмеру в группе с гарантией, что только этот консюмер будет её обслуживать.
С другой стороны, Kafka API определяет событийную модель и предполагает, что все клиенты следуют некоторому предопределённому регламенту обработки этих событий. Из основных событий можно выделить назначение и отзыв партиций. То, как именно будут обрабатываться данные события, во многом определяется реализацией используемого Kafka Client или прикладным кодом. И тут начинается самое интересное.
В целом, основная ответственность ложится на прикладной код: будете ли вы обрабатывать момент ребалансировки, чтобы отменить уже запущенную обработку. И тут нужно ответить на два вопроса:
1️⃣ Насколько критично, если сообщение обработается дважды (idempotence)?
2️⃣ Насколько критично, если одни и те же сообщения будут обрабатываться параллельно (concurrency)?
К первому чаще всего многие готовы, а вот ко второму – нет.
К сожалению, в моём текущем проекте не был готов и я, ибо для работы с Kafka пришлось использовать проприетарную библиотеку, в которой не было никакой возможности обрабатывать момент ребалансировки. Конечно, сейчас я к этому готов, но осадочек остался, поскольку в какой-то степени понадеялся на фреймворк.😮💨
Надеюсь, что эта небольшая, но поучительная история, поможет вам обойти стороной подобную проблему.❤️
#dev #tip
Есть распространённое заблуждение, что в рамках одной консюмер-группы сообщения одной и той же партиции топика Apache Kafka обрабатываются последовательно, одно за другим. И конкурентный доступ к сообщениям партиции со стороны консюмера невозможен. Спешу вас разуверить, такое возможно, и вот вам моя история.
Рассмотрим последовательность событий:
MyTopic#0 назначена консюмеру MyConsumer#0.MyConsumer#0 считал из партиции N сообщений.MyConsumer#0 начал обработку сообщений.MyTopic#0 вновь назначена MyConsumer#0.MyConsumer#0 вновь считал из партиции те же сообщения.MyConsumer#0 вновь начал обработку тех же сообщений.Если консюмер осуществляет обработку событий в отдельном пуле потоков (worker threads pool), то копии считанных сообщений будут находиться в памяти клиентского приложения. Следовательно, в момент, когда консюмер после ребалансировки еще раз считает и начнёт обработку тех же самых сообщений, но в рамках другого потока из пула, возникает коллизия. Как минимум, могут существовать два потока, которые одновременно обрабатывают одни и те же сообщения.
В целом, может, и вот по какой причине.
С одной стороны, Kafka предлагает достаточно простой и универсальный API для обслуживания сообщений топика. Продюсер пишет сообщения, консюмер их читает, обрабатывает и сдвигает указатель на следующую пачку сообщений. Партиция, действительно назначается одному-единственному консюмеру в группе с гарантией, что только этот консюмер будет её обслуживать.
С другой стороны, Kafka API определяет событийную модель и предполагает, что все клиенты следуют некоторому предопределённому регламенту обработки этих событий. Из основных событий можно выделить назначение и отзыв партиций. То, как именно будут обрабатываться данные события, во многом определяется реализацией используемого Kafka Client или прикладным кодом. И тут начинается самое интересное.
В целом, основная ответственность ложится на прикладной код: будете ли вы обрабатывать момент ребалансировки, чтобы отменить уже запущенную обработку. И тут нужно ответить на два вопроса:
К первому чаще всего многие готовы, а вот ко второму – нет.
К сожалению, в моём текущем проекте не был готов и я, ибо для работы с Kafka пришлось использовать проприетарную библиотеку, в которой не было никакой возможности обрабатывать момент ребалансировки. Конечно, сейчас я к этому готов, но осадочек остался, поскольку в какой-то степени понадеялся на фреймворк.
Надеюсь, что эта небольшая, но поучительная история, поможет вам обойти стороной подобную проблему.
#dev #tip
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8👍5❤2
Важность авторского контроля
Каждый раз ловлю себя на мысли, что пока какая-то концепция не укоренится в реализации проекта, она неминуемо требует авторского контроля. И чем сложней решение, тем сильней должен быть контроль, особенно на старте разработки.
Вроде бы очевидные вещи, но раз за разом вижу, что это правило нарушается с завидной регулярностью. Приходишь на новый проект и видишь два-три варианта реализации одного и того же. Начинаешь разбираться, и не находишь концептуальных различий в вариантах. И чаще всего такое случается просто потому, что автор не довел идею до конца, а тот, кто продолжил разработку, не понял изначальной концепции и стал делать всё то же самое, но на свой лад.
Такое бывает, в том числе, когда в команде нет ротации знаний, нет фиксации ADR, и каждый годами сидит на своём "участке". Естественно, что с уходом такого сотрудника, возникший коллапс начинает быстро заполняться чем-то новым и, как правильно, не содержащим принципиальных отличий. В таком случае можно сказать, что подобная ситуация вызвана недостатком знаний, но я считаю, что исходная причина в слабости архитектурных границ и отсутствии вектора развития.
Архитектура в том числе – вектор, направление развития. Если направления нет, то мы будем крутиться на месте, как корабль в полный штиль. В начале пути архитектор задаёт и корректирует этот вектор, поэтому очень важна обратная связь с разработкой, с помощью чего происходит уточнение и усиление направления движения.
К чему все эти рассуждения?
➡️ Во-первых, если вы даёте архитектору задание, а он в ответ выдаёт вам какой-то концепт, то пусть он за него и отвечает, сопровождая разработку до того момента, пока не будет достигнут хотя бы минимальный успех. В противном случае те идеи, те квадратики и стрелочки будут интерпретированы не так, как задумано, и все останутся недовольны.
➡️ Во-вторых, есть вещи, которые достаточно затруднительно передать в одних только диаграммах и ADR. Понимание общей концепции, взгляд со стороны, опыт, позволяющий понять, что началось отклонение от курса, всё это позволяет вовремя среагировать и не допустить ухода от цели.
К сожалению, был свидетелем, когда архитектора приглашали как "художника", а потом обижались, почему по его письменам получился не тот результат, на который рассчитывали. Был свидетелем, когда потеря направления приводила не к решению проблемы, а её перемещению из одного угла в другой. Всё это я связываю только с одним – отсутствием авторского контроля и, как следствие, непонимание направления движения, уход от цели и последующий хаос в действиях.
Почему это особенно важно сейчас?
➡️ С бурным развитием AI человеку – архитектору и разработчику – остаётся всё больше человеческой работы, а именно: следить за порядком и задавать направление развития. Агентская разработка приумножает, а мы определяем, что именно: хаос или порядок. Это во многом объясняет успешное сочетание AI со стратегическими шаблонами DDD.
Теперь, как мне кажется, нам очень важно не только навести порядок и заложить правильный курс, определив концепцию разработки в каком-нибудь
Guide your force and may the order be with you!❤️
#arch #ai
Каждый раз ловлю себя на мысли, что пока какая-то концепция не укоренится в реализации проекта, она неминуемо требует авторского контроля. И чем сложней решение, тем сильней должен быть контроль, особенно на старте разработки.
Вроде бы очевидные вещи, но раз за разом вижу, что это правило нарушается с завидной регулярностью. Приходишь на новый проект и видишь два-три варианта реализации одного и того же. Начинаешь разбираться, и не находишь концептуальных различий в вариантах. И чаще всего такое случается просто потому, что автор не довел идею до конца, а тот, кто продолжил разработку, не понял изначальной концепции и стал делать всё то же самое, но на свой лад.
Такое бывает, в том числе, когда в команде нет ротации знаний, нет фиксации ADR, и каждый годами сидит на своём "участке". Естественно, что с уходом такого сотрудника, возникший коллапс начинает быстро заполняться чем-то новым и, как правильно, не содержащим принципиальных отличий. В таком случае можно сказать, что подобная ситуация вызвана недостатком знаний, но я считаю, что исходная причина в слабости архитектурных границ и отсутствии вектора развития.
Архитектура в том числе – вектор, направление развития. Если направления нет, то мы будем крутиться на месте, как корабль в полный штиль. В начале пути архитектор задаёт и корректирует этот вектор, поэтому очень важна обратная связь с разработкой, с помощью чего происходит уточнение и усиление направления движения.
К чему все эти рассуждения?
К сожалению, был свидетелем, когда архитектора приглашали как "художника", а потом обижались, почему по его письменам получился не тот результат, на который рассчитывали. Был свидетелем, когда потеря направления приводила не к решению проблемы, а её перемещению из одного угла в другой. Всё это я связываю только с одним – отсутствием авторского контроля и, как следствие, непонимание направления движения, уход от цели и последующий хаос в действиях.
Почему это особенно важно сейчас?
Теперь, как мне кажется, нам очень важно не только навести порядок и заложить правильный курс, определив концепцию разработки в каком-нибудь
CLAUDE.md или AGENTS.md, но и, как капитану корабля, неустанно следить за сохранением этого курса. И для каждой новой идеи эта навигация должна осуществляться до тех пор, пока все члены команды не начнут придерживаться общей цели.Guide your force and may the order be with you!
#arch #ai
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥1
Chronicle Queue - Kafka на минималках
Что, если нужна простая и высокопроизводительная очередь, но вы не хотите усложнять решение путём добавления полноценного брокера? Или нужно обеспечить распределённую обработку огромного потока событий с непредсказуемыми всплесками активности? Сегодня поговорим еще об одном классе решений – локальные очереди.🚀
Контекст
Имеется связка Producer-Consumer, в которой Producer может генерировать события намного быстрей, чем Consumer успевает их обрабатывать. При этом Producer отправляет события синхронно, а Consumer не должен замедлять его работу, вынуждая ждать окончания обработки или требуя повторной отправки в случае ошибки.
Примеры:
✅ Высокочастотный источник, например, биржевые котировки – миллионы событий в секунду и/или случайные всплески активности. Нужно предоставить возможность быстрой записи событий, а их обработку делать в фоне.
✅ При обработке событий производится обращение к ресурсу с низкой доступностью, но нужно гарантировать успешность обработки. Например, гарантировать запись в БД или вызов сервиса, с которым возможна потеря сетевого соединения. Иначе говоря, когда нужно пережить недоступность внешнего компонента.
✅ Нужно обеспечить высокий уровень масштабируемости, параллелизма обработки и адаптируемости к нагрузкам. При этом порядок обработки событий в общем случае не важен. Например, система, подобная LeetCode, в которой агенты должны осуществлять проверку присылаемых решений во время проведения соревнований.
Проблема
Получив событие, Consumer сразу отвечает успехом, но добавляет задачу в очередь асинхронной обработки. С появлением очереди возникает целый комплекс проблем.
Где Consumer будет хранить необработанные события? Если в оперативной памяти, то можно быстро дойти до OOM/Killer. Если использовать брокер сообщений, то какой?
Если Kafka, то как адаптировать её под всплески активности и выбрать оптимальное количество партиций, fetch size, poll timeout и т.п.? А если в системе нет никакого брокера и его добавление крайне нежелательно или преждевременно? Например, не нужны все возможности Kafka, а её добавление выливается в огромные траты по сопровождению.
Решение
Суть решения:
➡️ Consumer использует персистентную очередь, которую хранит в локальной файловой системе. Получив от Producer событие, Consumer сохраняет её в файл очереди – append-only-лог – и тут же отвечает успехом.
➡️ Обработку событий из файла очереди Consumer выполняет в отдельном потоке или процессе. Если событие требует принципиально разной обработки, Consumer может запустить разные обработчики в разных потоках или в отдельных процессах.
Дополнительно нужно учесть:
⚠️ Каждый экземпляр Consumer должен иметь свой собственный файл очереди. Соответственно, в Docker нужно настроить Volumes; в Kubernetes – PV. Это позволит не потерять события при перезапуске Consumer.
⚠️ Желательно, чтобы Consumer реализовывал Graceful Shutdown, гарантируя обработку оставшихся сообщений в очереди до прекращения своей работы. Это позволит адаптировать количество обработчиков как в большую, так и в меньшую сторону.
⚠️ Для обеспечения микросекундных задержек, а также для возможности конкурентного доступа к файлу очереди, можно использовать Memory-mapped files.
Шаблон реализуется самостоятельно, с помощью специальных библиотек, файловых или embedded-баз данных (RocksDB, SQLite, LiteDB и т.п.).
🔥 Для JVM/Java/Kotlin отличным решением может быть Chronicle Queue (при запуске в Java 17+ для JVM нужно указать дополнительные настройки).
Плюсы
👍 Концептуальная простота решения.
👍 Масштабируемость, адаптируемость, производительность.
👍 Высокий уровень параллелизма и распределённой обработки.
👍 Нет сетевых издержек на общение с брокером.
👍 Простота деплоя и сопровождения.
Минусы
👎 Нет гарантий порядка обработки.
👎 Риск потери части событий при выходе из строя узла, на котором хранились файлы очередей. Снижать эти риски нужно самостоятельно.
👎 Нет партиционирования данных. Его нужно реализовывать самостоятельно, например, на уровне роутинга событий от Producer к Consumer.
#tip #arch #dev
Что, если нужна простая и высокопроизводительная очередь, но вы не хотите усложнять решение путём добавления полноценного брокера? Или нужно обеспечить распределённую обработку огромного потока событий с непредсказуемыми всплесками активности? Сегодня поговорим еще об одном классе решений – локальные очереди.
Контекст
Имеется связка Producer-Consumer, в которой Producer может генерировать события намного быстрей, чем Consumer успевает их обрабатывать. При этом Producer отправляет события синхронно, а Consumer не должен замедлять его работу, вынуждая ждать окончания обработки или требуя повторной отправки в случае ошибки.
Примеры:
Проблема
Получив событие, Consumer сразу отвечает успехом, но добавляет задачу в очередь асинхронной обработки. С появлением очереди возникает целый комплекс проблем.
Где Consumer будет хранить необработанные события? Если в оперативной памяти, то можно быстро дойти до OOM/Killer. Если использовать брокер сообщений, то какой?
Если Kafka, то как адаптировать её под всплески активности и выбрать оптимальное количество партиций, fetch size, poll timeout и т.п.? А если в системе нет никакого брокера и его добавление крайне нежелательно или преждевременно? Например, не нужны все возможности Kafka, а её добавление выливается в огромные траты по сопровождению.
Решение
Суть решения:
Дополнительно нужно учесть:
Шаблон реализуется самостоятельно, с помощью специальных библиотек, файловых или embedded-баз данных (RocksDB, SQLite, LiteDB и т.п.).
Плюсы
Минусы
#tip #arch #dev
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4👍2
📺 От разработчика к AI-агенту: единые правила игры
В мире разработки появился искусственный интеллект – катализатор, ускоряющий все процессы. AI действительно ускоряет разработку, но не делает её автоматически лучше – он просто масштабирует текущее состояние проекта. Если в коде царит хаос, AI поможет быстрее его размножить; если есть структура – он начнёт её усиливать. Существуют ли практики, которые позволят заложить основу, способную одинаково хорошо работать как для людей, так и для AI-агентов? Позволят ли они ускорить процесс передачи (управления)?
🕒 12 мая в 16:00 МСК приглашаю на онлайн-митап, на котором я поделюсь своим опытом проектирования AI-контекста. Расскажу, какие практики из DDD заиграли новыми красками и позволили мне значительно улучшить качество работы с AI.
Формат митапа не ограничен временем, количеством участников. Можно свободноматериться высказываться и делиться опытом. Обещают, что запись будет, но чуть позже.
🥰 Ссылка на Google-клендарь
😊 Ссылка на Yandex-календарь
😄 [ Ссылку для подключения я выложу чуть позже ]
#conf #uwdc
В мире разработки появился искусственный интеллект – катализатор, ускоряющий все процессы. AI действительно ускоряет разработку, но не делает её автоматически лучше – он просто масштабирует текущее состояние проекта. Если в коде царит хаос, AI поможет быстрее его размножить; если есть структура – он начнёт её усиливать. Существуют ли практики, которые позволят заложить основу, способную одинаково хорошо работать как для людей, так и для AI-агентов? Позволят ли они ускорить процесс передачи (управления)?
Формат митапа не ограничен временем, количеством участников. Можно свободно
🗂 Кстати, данный митап является "приквелом" к моему предстоящему докладу на UWDC 2026 "Передача проекта глазами инженера", на который я таже приглашаю всех 16 мая. Если вы будете в это время в Челябинске, то обязательно приходите на UWDC – это крупнейшая ежегодная ИТ-конференция нашего региона, которая всегда отличалась хорошим качеством контента.
#conf #uwdc
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3👎1🔥1