Union types в C# 15
Годами разработчики C# имитировали union types — типы-объединения — через маркерные интерфейсы, базовые классы и библиотеку OneOf. Всё ради того, чтобы выразить простую идею: «результат — либо Success, либо Failure». C# 15 переносит эту возможность на уровень языка.
Что меняется на практике:
• Набор вариантов объявляется один раз, например Success или Failure, и компилятор знает все допустимые случаи.
• Компилятор проверяет полноту
• Для описания закрытого набора результатов больше не нужна сторонняя библиотека.
Такие возможности помогают предотвращать ошибки при моделировании состояний. То, что раньше требовало обходных решений, получает встроенную поддержку.
👉 @KodBlog
Годами разработчики C# имитировали union types — типы-объединения — через маркерные интерфейсы, базовые классы и библиотеку OneOf. Всё ради того, чтобы выразить простую идею: «результат — либо Success, либо Failure». C# 15 переносит эту возможность на уровень языка.
Что меняется на практике:
• Набор вариантов объявляется один раз, например Success или Failure, и компилятор знает все допустимые случаи.
• Компилятор проверяет полноту
switch: если пропустить вариант, он сообщит об этом ещё при компиляции.• Для описания закрытого набора результатов больше не нужна сторонняя библиотека.
Такие возможности помогают предотвращать ошибки при моделировании состояний. То, что раньше требовало обходных решений, получает встроенную поддержку.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥1🍾1
Архитектура ПО — это просто?..
Объединяйте связанные концепции, и приложения станут лучше. Неужели всё настолько просто? Конечно, нет. Но направление верное.
За этим стоит cohesion — связность. Идея в том, чтобы держать компоненты одной функциональности рядом.
В слоистой архитектуре они обычно разнесены по разным слоям. Чтобы добавить или изменить одну функцию, приходится править код сразу в нескольких местах.
Vertical Slice Architecture предлагает другой подход: все файлы одного сценария использования располагаются рядом. Так проще найти нужные компоненты, разобраться в их взаимодействии и внести изменения.
Подробнее о Vertical Slice Architecture
👉 @KodBlog
Объединяйте связанные концепции, и приложения станут лучше. Неужели всё настолько просто? Конечно, нет. Но направление верное.
За этим стоит cohesion — связность. Идея в том, чтобы держать компоненты одной функциональности рядом.
В слоистой архитектуре они обычно разнесены по разным слоям. Чтобы добавить или изменить одну функцию, приходится править код сразу в нескольких местах.
Vertical Slice Architecture предлагает другой подход: все файлы одного сценария использования располагаются рядом. Так проще найти нужные компоненты, разобраться в их взаимодействии и внести изменения.
Подробнее о Vertical Slice Architecture
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3🍾1
Ваш API отвечает пять минут? Это уже захват заложников
Пользователь смотрит на индикатор загрузки. Запрос занимает ресурсы сервера. Балансировщик обрывает соединение по тайм-ауту. Клиент повторяет запрос — и один отчёт строится уже дважды. Здесь поможет перенос долгой операции в фоновую обработку.
Как выглядит схема:
• Клиент отправляет
• API ставит задачу в очередь и быстро возвращает
• Фоновый воркер забирает задачу и выполняет пятиминутную работу.
• Клиент запрашивает
• При следующей проверке получает
Что это даёт:
• HTTP-запросы завершаются быстро, не дожидаясь построения отчёта.
• Длительность фоновой задачи больше не упирается в тайм-аут запроса.
• Воркеры масштабируются независимо от API.
• Повторная проверка статуса не запускает создание отчёта заново.
Для безопасного повторения самого
Ещё две детали:
• Возвращайте
• Используйте SignalR или webhook, если нужно уведомлять о готовности вместо периодических запросов.
Длительная операция становится отдельным ресурсом: её можно создать, проверить состояние и получить результат. А как вы обрабатываете долгие задачи в своих API: polling, webhooks или SignalR?
👉 @KodBlog
Пользователь смотрит на индикатор загрузки. Запрос занимает ресурсы сервера. Балансировщик обрывает соединение по тайм-ауту. Клиент повторяет запрос — и один отчёт строится уже дважды. Здесь поможет перенос долгой операции в фоновую обработку.
Как выглядит схема:
• Клиент отправляет
POST /reports.• API ставит задачу в очередь и быстро возвращает
202 Accepted с заголовком Location: /reports/42.• Фоновый воркер забирает задачу и выполняет пятиминутную работу.
• Клиент запрашивает
GET /reports/42 и получает статус Running.• При следующей проверке получает
Done и ссылку на результат.Что это даёт:
• HTTP-запросы завершаются быстро, не дожидаясь построения отчёта.
• Длительность фоновой задачи больше не упирается в тайм-аут запроса.
• Воркеры масштабируются независимо от API.
• Повторная проверка статуса не запускает создание отчёта заново.
Для безопасного повторения самого
POST предусмотрите ключ идемпотентности, чтобы не создавать дубликаты задач.Ещё две детали:
• Возвращайте
Retry-After, чтобы клиент понимал, через какое время снова проверить статус.• Используйте SignalR или webhook, если нужно уведомлять о готовности вместо периодических запросов.
Длительная операция становится отдельным ресурсом: её можно создать, проверить состояние и получить результат. А как вы обрабатываете долгие задачи в своих API: polling, webhooks или SignalR?
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5🍾1
Health Checks в .NET — два вызова методов
•
•
Но это только инфраструктура. Сами проверки нужно зарегистрировать отдельно.
Для популярных баз данных, брокеров сообщений и других зависимостей уже существуют готовые библиотеки проверок.
Подробнее о Health Checks
👉 @KodBlog
•
AddHealthChecks() регистрирует необходимые сервисы.•
MapHealthChecks() добавляет эндпоинт для проверки состояния приложения.Но это только инфраструктура. Сами проверки нужно зарегистрировать отдельно.
Для популярных баз данных, брокеров сообщений и других зависимостей уже существуют готовые библиотеки проверок.
Подробнее о Health Checks
Please open Telegram to view this post
VIEW IN TELEGRAM
🍾1
Хватит возвращать BadRequest("какая-то строка")
Когда каждый эндпоинт возвращает ошибки в своём формате, клиентам приходится отдельно обрабатывать каждый вариант.
В ASP.NET Core есть
👉 @KodBlog
Когда каждый эндпоинт возвращает ошибки в своём формате, клиентам приходится отдельно обрабатывать каждый вариант.
В ASP.NET Core есть
ProblemDetails: AddProblemDetails() и Results.Problem() помогают использовать единый машиночитаемый формат ошибок по стандарту RFC.Please open Telegram to view this post
VIEW IN TELEGRAM
❤4🍾1
Пишете код каждый день? Помните о пяти вещах:
• Сначала добейтесь, чтобы код работал.
• Затем сделайте его понятным и аккуратным.
• Подстрахуйте его тестами.
• Избегайте избыточного усложнения.
• Проводите рефакторинг, когда это необходимо — а обычно это необходимо.
Рефакторинг — ваша суперсила для приведения кода в порядок.
Пять проверенных техник рефакторинга
С ИИ-агентами этот подход тоже работает. Но нужно уметь направлять их: ваши навыки разработки по-прежнему пригодятся.
👉 @KodBlog
• Сначала добейтесь, чтобы код работал.
• Затем сделайте его понятным и аккуратным.
• Подстрахуйте его тестами.
• Избегайте избыточного усложнения.
• Проводите рефакторинг, когда это необходимо — а обычно это необходимо.
Рефакторинг — ваша суперсила для приведения кода в порядок.
Пять проверенных техник рефакторинга
С ИИ-агентами этот подход тоже работает. Но нужно уметь направлять их: ваши навыки разработки по-прежнему пригодятся.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8🍾1
Один API-запрос на несколько минут создаёт проблемы всем.
Пользователь смотрит на индикатор загрузки, сервер держит соединение открытым, а балансировщик или прокси может оборвать запрос по тайм-ауту. Повторные попытки только усугубляют ситуацию.
Решение — изменить подход к обработке долгих задач:
• Принять задачу и сразу вернуть
• Выполнить тяжёлую работу в фоновом обработчике.
• Позволить клиенту опрашивать статус или получить уведомление о готовности результата.
Теперь отчёт, который формируется пять минут, не требует держать HTTP-запрос открытым всё это время. API остаётся отзывчивым, а фоновые обработчики можно масштабировать независимо от веб-серверов.
Длительная задача — это ресурс, который вы создаёте и отслеживаете, а не ответ, которого нужно ждать в открытом соединении.
👉 @KodBlog
Пользователь смотрит на индикатор загрузки, сервер держит соединение открытым, а балансировщик или прокси может оборвать запрос по тайм-ауту. Повторные попытки только усугубляют ситуацию.
Решение — изменить подход к обработке долгих задач:
• Принять задачу и сразу вернуть
202 Accepted со ссылкой для проверки статуса.• Выполнить тяжёлую работу в фоновом обработчике.
• Позволить клиенту опрашивать статус или получить уведомление о готовности результата.
Теперь отчёт, который формируется пять минут, не требует держать HTTP-запрос открытым всё это время. API остаётся отзывчивым, а фоновые обработчики можно масштабировать независимо от веб-серверов.
Длительная задача — это ресурс, который вы создаёте и отслеживаете, а не ответ, которого нужно ждать в открытом соединении.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5🍾1
🦈 Открытое собеседование на Middle C# | 6 октября, 19:00 МСК
Приглашаем на открытое собеседование: Senior C# разработчик проведёт его в прямом эфире. Можно посмотреть, как всё устроено изнутри, и понять, насколько ты готов к такому интервью.
Как это будет:
📂 Собеседует Александр Моргунов — Senior C# разработчик, 7+ лет в европейских высоконагруженных сервисах. Отвечает разработчик-доброволец;
📂 Всё как на настоящем собесе: Александр задаёт те вопросы и задачи, которые даёт кандидатам на своих интервью. Заранее их никто не знает;
📂 После каждого ответа Александр даст обратную связь: что прозвучало сильно, а что стоило раскрыть иначе. Так станет понятнее, на что обращают внимание на собесе;
📂 В конце можно задать любой вопрос.
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для C# разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир -> @shortcut_csharp_bot
Реклама.
О рекламодателе.
Приглашаем на открытое собеседование: Senior C# разработчик проведёт его в прямом эфире. Можно посмотреть, как всё устроено изнутри, и понять, насколько ты готов к такому интервью.
Как это будет:
📂 Собеседует Александр Моргунов — Senior C# разработчик, 7+ лет в европейских высоконагруженных сервисах. Отвечает разработчик-доброволец;
📂 Всё как на настоящем собесе: Александр задаёт те вопросы и задачи, которые даёт кандидатам на своих интервью. Заранее их никто не знает;
📂 После каждого ответа Александр даст обратную связь: что прозвучало сильно, а что стоило раскрыть иначе. Так станет понятнее, на что обращают внимание на собесе;
📂 В конце можно задать любой вопрос.
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для C# разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир -> @shortcut_csharp_bot
Реклама.
О рекламодателе.
🍾1
Не начинайте с микросервисов ❌
Даже если уверены, что в будущем они понадобятся вашему приложению.
У микросервисов есть скрытые издержки:
• Координация команд.
• Сбои в распределённой системе.
• Работа с eventual consistency — согласованностью данных в конечном счёте.
• Автоматизация развёртывания нескольких сервисов.
• Управление множеством инфраструктурных компонентов.
• Выделение дополнительных ресурсов по мере необходимости.
На старте проекта такая сложность часто не оправдана. Менее рискованный подход:
• Начните с монолита.
• Определите границы предметной области — bounded contexts.
• Решите, нужно ли выделять отдельные контексты в самостоятельные сервисы.
На выбор архитектуры влияют и другие факторы, которые не уместить в одном посте. Но начинать с более простой системы и усложнять её по мере необходимости — разумная отправная точка.
👉 @KodBlog
Даже если уверены, что в будущем они понадобятся вашему приложению.
У микросервисов есть скрытые издержки:
• Координация команд.
• Сбои в распределённой системе.
• Работа с eventual consistency — согласованностью данных в конечном счёте.
• Автоматизация развёртывания нескольких сервисов.
• Управление множеством инфраструктурных компонентов.
• Выделение дополнительных ресурсов по мере необходимости.
На старте проекта такая сложность часто не оправдана. Менее рискованный подход:
• Начните с монолита.
• Определите границы предметной области — bounded contexts.
• Решите, нужно ли выделять отдельные контексты в самостоятельные сервисы.
На выбор архитектуры влияют и другие факторы, которые не уместить в одном посте. Но начинать с более простой системы и усложнять её по мере необходимости — разумная отправная точка.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4🍾1
Domain Events и Integration Events: в чём разница?
По мере развития приложения часто приходят к событийному взаимодействию. Один из простейших паттернов — уведомление о событии, или Event Notification.
В Domain-Driven Design агрегат задаёт границу согласованности. Если произошедшее внутри него должно вызвать изменения за его пределами, можно опубликовать доменное событие. Обработчики отреагируют на него и выполнят нужные действия, сохраняя слабую связанность между агрегатами.
Доменные события — внутри bounded context. Они помогают отделить основную доменную логику от дополнительных действий.
Интеграционные события — между bounded contexts. Например, один микросервис публикует событие, а другой получает его и обрабатывает.
Важный нюанс: доменные события могут обрабатываться как синхронно, так и асинхронно. Интеграционные обычно передаются асинхронно, после успешного сохранения изменений.
Пример реализации
👉 @KodBlog
По мере развития приложения часто приходят к событийному взаимодействию. Один из простейших паттернов — уведомление о событии, или Event Notification.
В Domain-Driven Design агрегат задаёт границу согласованности. Если произошедшее внутри него должно вызвать изменения за его пределами, можно опубликовать доменное событие. Обработчики отреагируют на него и выполнят нужные действия, сохраняя слабую связанность между агрегатами.
Доменные события — внутри bounded context. Они помогают отделить основную доменную логику от дополнительных действий.
Интеграционные события — между bounded contexts. Например, один микросервис публикует событие, а другой получает его и обрабатывает.
Важный нюанс: доменные события могут обрабатываться как синхронно, так и асинхронно. Интеграционные обычно передаются асинхронно, после успешного сохранения изменений.
Пример реализации
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍2🍾1
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🍾1
Переписать legacy-приложение на .NET с нуля — заманчивый путь в ловушку.
Полтора года работы, заморозка новых функций — и новая система всё ещё не умеет того, что старая незаметно делала в продакшене. Альтернатива — постепенная модернизация с Claude. Последовательный процесс, а не кнопка «переписать всё».
1. Оцените состояние кода
Дайте AI-агентам доступ только на чтение и поручите составить план изменений. Приоритеты определяйте по рискам и ценности для бизнеса.
2. Создайте страховочную сетку
Напишите characterization tests — тесты, фиксирующие текущее поведение приложения, включая существующие баги. Чтобы безопасно менять код, нужно уметь проверять его поведение.
3. Устраните критичный техдолг на старом фреймворке
Исправьте SQL-инъекции, отсутствие необходимых транзакций и утечки ресурсов. Намеренные изменения поведения отражайте в тестах.
4. Подготовьте границы, затем обновляйтесь
Разделите зависимости через DI и обновляйте фреймворк поэтапно, проверяя работоспособность после каждого перехода.
AI берёт на себя рутину: тесты, параметризацию запросов, замену API. Архитектурные решения остаются за разработчиком, а сборка и тесты должны проходить на каждом этапе.
Полный процесс модернизации
👉 @KodBlog
Полтора года работы, заморозка новых функций — и новая система всё ещё не умеет того, что старая незаметно делала в продакшене. Альтернатива — постепенная модернизация с Claude. Последовательный процесс, а не кнопка «переписать всё».
1. Оцените состояние кода
Дайте AI-агентам доступ только на чтение и поручите составить план изменений. Приоритеты определяйте по рискам и ценности для бизнеса.
2. Создайте страховочную сетку
Напишите characterization tests — тесты, фиксирующие текущее поведение приложения, включая существующие баги. Чтобы безопасно менять код, нужно уметь проверять его поведение.
3. Устраните критичный техдолг на старом фреймворке
Исправьте SQL-инъекции, отсутствие необходимых транзакций и утечки ресурсов. Намеренные изменения поведения отражайте в тестах.
4. Подготовьте границы, затем обновляйтесь
Разделите зависимости через DI и обновляйте фреймворк поэтапно, проверяя работоспособность после каждого перехода.
AI берёт на себя рутину: тесты, параметризацию запросов, замену API. Архитектурные решения остаются за разработчиком, а сборка и тесты должны проходить на каждом этапе.
Полный процесс модернизации
Please open Telegram to view this post
VIEW IN TELEGRAM
🥴6❤3🍾1
Модульный монолит: как сохранить границы модулей в базе данных
Модульный монолит обещает удобство разработки монолита и чёткие границы между частями системы. У каждого модуля своя доменная модель, логика и данные.
Но именно в базе эти границы легко нарушить: достаточно сделать
Каждый модуль должен владеть своими данными. Другие модули взаимодействуют с ним через явный контракт, а детали хранения остаются внутренним делом владельца.
Закрепить это можно на уровне БД:
• Выделить каждому модулю отдельную схему и роль.
• Дать роли доступ только к нужной схеме. Настроить
• Использовать отдельный
• Для межмодульного чтения при необходимости предоставить представление с доступом только на чтение — как явно согласованный контракт.
• Если нужно ограничить доступ к отдельным строкам внутри таблицы, использовать Row-Level Security.
Такие ограничения защищают от случайного доступа к чужим данным и упрощают выделение модуля в отдельный сервис в будущем.
Подробнее о реализации
👉 @KodBlog
Модульный монолит обещает удобство разработки монолита и чёткие границы между частями системы. У каждого модуля своя доменная модель, логика и данные.
Но именно в базе эти границы легко нарушить: достаточно сделать
JOIN с чужими таблицами или обратиться к ним напрямую, обходя публичный API модуля. Так появляется тесная связанность.Каждый модуль должен владеть своими данными. Другие модули взаимодействуют с ним через явный контракт, а детали хранения остаются внутренним делом владельца.
Закрепить это можно на уровне БД:
• Выделить каждому модулю отдельную схему и роль.
• Дать роли доступ только к нужной схеме. Настроить
search_path, помня, что сам по себе он не ограничивает права.• Использовать отдельный
DbContext в EF Core для каждого модуля, со своей схемой и строкой подключения под соответствующей ролью.• Для межмодульного чтения при необходимости предоставить представление с доступом только на чтение — как явно согласованный контракт.
• Если нужно ограничить доступ к отдельным строкам внутри таблицы, использовать Row-Level Security.
Такие ограничения защищают от случайного доступа к чужим данным и упрощают выделение модуля в отдельный сервис в будущем.
Подробнее о реализации
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3