Надоело раскладывать проект по слоям?
Vertical Slice Architecture предлагает другой подход: код группируется по фичам, а не по горизонтальным слоям вроде Controllers, Services и Repositories.
В результате всё, что относится к конкретной фиче, находится рядом:
— выше связность кода
— проще вносить изменения
— меньше переходов между слоями и папками
— бизнес-логика не размазана по всему проекту
И есть ещё один актуальный плюс: такой подход хорошо ложится на работу с LLM и кодинг-агентами. Когда весь контекст фичи собран в одном месте, модели проще понять, что именно нужно изменить.
👉 @KodBlog
Vertical Slice Architecture предлагает другой подход: код группируется по фичам, а не по горизонтальным слоям вроде Controllers, Services и Repositories.
В результате всё, что относится к конкретной фиче, находится рядом:
— выше связность кода
— проще вносить изменения
— меньше переходов между слоями и папками
— бизнес-логика не размазана по всему проекту
И есть ещё один актуальный плюс: такой подход хорошо ложится на работу с LLM и кодинг-агентами. Когда весь контекст фичи собран в одном месте, модели проще понять, что именно нужно изменить.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🍾2🤨1
Используете ли вы человекочитаемые ID объектов?
Разберёмся, почему такой подход стоит применять в приложениях.
Начнём с выбора типа данных для идентификаторов объектов, или первичных ключей.
В реляционных базах данных часто используют целые числа: база автоматически присваивает каждой новой строке следующий порядковый номер. Это простое решение, которое хорошо подходит для небольших систем.
Однако у автоинкрементных ID есть недостаток: они делают приложение уязвимым для перебора идентификаторов. Если ID текущего объекта —
UUID устраняют эту проблему благодаря случайной генерации. Кроме того, они удобны в распределённых системах, поскольку снижают риск коллизий.
UUID также полезны, когда ID объекта необходимо сгенерировать непосредственно в коде, а не на стороне базы данных.
Но какой бы тип данных вы ни выбрали, остаётся один недостаток: сам идентификатор ничего не сообщает об объекте, которому он принадлежит.
Иначе обстоит дело с такими ID:
*
*
По префиксу можно понять, к какому типу относится объект. Например,
При этом такие ID необязательно делать первичными ключами в базе данных. Их можно генерировать в коде перед возвратом данных клиенту.
Такой формат сделает API более удобным и понятным для его потребителей.
Как вы относитесь к человекочитаемым ID объектов?
👉 @KodBlog
Разберёмся, почему такой подход стоит применять в приложениях.
Начнём с выбора типа данных для идентификаторов объектов, или первичных ключей.
В реляционных базах данных часто используют целые числа: база автоматически присваивает каждой новой строке следующий порядковый номер. Это простое решение, которое хорошо подходит для небольших систем.
Однако у автоинкрементных ID есть недостаток: они делают приложение уязвимым для перебора идентификаторов. Если ID текущего объекта —
42, злоумышленник может предположить, что следующий объект имеет ID 43. При наличии незащищённых API-эндпоинтов этим можно воспользоваться.UUID устраняют эту проблему благодаря случайной генерации. Кроме того, они удобны в распределённых системах, поскольку снижают риск коллизий.
UUID также полезны, когда ID объекта необходимо сгенерировать непосредственно в коде, а не на стороне базы данных.
Но какой бы тип данных вы ни выбрали, остаётся один недостаток: сам идентификатор ничего не сообщает об объекте, которому он принадлежит.
Иначе обстоит дело с такими ID:
*
ord_01HZW2RKF63AWC1BT901FPGRGT*
tr_afdf5738-6a8e-4d1a-90db-e894a3828320По префиксу можно понять, к какому типу относится объект. Например,
ord может означать Order — заказ, а tr — Transaction — транзакцию.При этом такие ID необязательно делать первичными ключами в базе данных. Их можно генерировать в коде перед возвратом данных клиенту.
Такой формат сделает API более удобным и понятным для его потребителей.
Как вы относитесь к человекочитаемым ID объектов?
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🍾1
Если вы создаёте новый API на .NET 9 или .NET 10 и ищете привычную страницу документации, её больше нет.
Годами в стандартном шаблоне использовался Swashbuckle, а интерактивная документация появлялась сразу из коробки. Теперь всё изменилось. Фреймворк сам генерирует OpenAPI-документ, а встроенный UI больше не входит в шаблон по умолчанию.
На первый взгляд кажется, что это потеря. Но потом становится понятно, что пришло на замену. Фреймворк сам создаёт OpenAPI-спеку одним вызовом. Дальше можно подключить современный UI поверх этой спеки.
Я обычно использую Scalar: он быстрый, сразу хорошо выглядит и работает с тем же документом, который уже генерирует фреймворк.
Главное изменение — поменялось место, где находится ответственность за описание API. Теперь OpenAPI-спека принадлежит самому фреймворку, а не сторонней библиотеке UI, которую приходится накручивать поверх. Интерфейс документации становится тонким слоем, который можно заменить без изменения процесса генерации спеки.
Старый вариант всё ещё можно оставить — достаточно вручную установить нужный пакет. Но если вы всё равно обновляетесь, это хороший момент убрать одну зависимость и заодно получить более современный UI.
👉 @KodBlog
Годами в стандартном шаблоне использовался Swashbuckle, а интерактивная документация появлялась сразу из коробки. Теперь всё изменилось. Фреймворк сам генерирует OpenAPI-документ, а встроенный UI больше не входит в шаблон по умолчанию.
На первый взгляд кажется, что это потеря. Но потом становится понятно, что пришло на замену. Фреймворк сам создаёт OpenAPI-спеку одним вызовом. Дальше можно подключить современный UI поверх этой спеки.
Я обычно использую Scalar: он быстрый, сразу хорошо выглядит и работает с тем же документом, который уже генерирует фреймворк.
Главное изменение — поменялось место, где находится ответственность за описание API. Теперь OpenAPI-спека принадлежит самому фреймворку, а не сторонней библиотеке UI, которую приходится накручивать поверх. Интерфейс документации становится тонким слоем, который можно заменить без изменения процесса генерации спеки.
Старый вариант всё ещё можно оставить — достаточно вручную установить нужный пакет. Но если вы всё равно обновляетесь, это хороший момент убрать одну зависимость и заодно получить более современный UI.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3🍾2
Анонсирована v2.0 официального MCP SDK для C#.
MCP C# SDK 2.0 реализует спецификацию от 28 июля 2026 года и включает:
- протокол с приоритетом на stateless-режим работы;
- стандартизированные HTTP-заголовки;
- поддержку Multi Round-Trip Requests для интерактивных инструментов.
При этом SDK сохраняет обратную совместимость с предыдущими версиями.
👉 @KodBlog
MCP C# SDK 2.0 реализует спецификацию от 28 июля 2026 года и включает:
- протокол с приоритетом на stateless-режим работы;
- стандартизированные HTTP-заголовки;
- поддержку Multi Round-Trip Requests для интерактивных инструментов.
При этом SDK сохраняет обратную совместимость с предыдущими версиями.
Please open Telegram to view this post
VIEW IN TELEGRAM
Microsoft News
Announcing v2.0 of the official MCP C# SDK
MCP C# SDK v2.0 implements the 2026-07-28 specification with a stateless-first protocol, standardized HTTP headers, and Multi Round-Trip Requests for interactive tools, all while staying backward compatible.
❤4🍾1
В C# 15 появятся
«Они заменят обходные решения для управления потоком выполнения во вложенных циклах: например, булевый флаг, который устанавливается во внутреннем цикле и затем проверяется на каждом внешнем уровне, или
👉 @KodBlog
break и continue с метками.«Они заменят обходные решения для управления потоком выполнения во вложенных циклах: например, булевый флаг, который устанавливается во внутреннем цикле и затем проверяется на каждом внешнем уровне, или
goto, перескакивающий за пределы циклов».Please open Telegram to view this post
VIEW IN TELEGRAM
👍15❤🔥6🍾5🥰1
Блог .NET: от сгенерированного кода к проверенному с помощью агента для написания юнит-тестов.
https://devblogs.microsoft.com/dotnet/polyglot-unit-testing-agent/
👉 @KodBlog
https://devblogs.microsoft.com/dotnet/polyglot-unit-testing-agent/
Please open Telegram to view this post
VIEW IN TELEGRAM
🍾1
Middleware, но для исходящих HTTP-запросов?
Да, в ASP.NET Core такое есть.
Это похоже на middleware, только работает в обратном направлении.
Отличный сценарий использования? Добавление заголовков аутентификации в запрос.
👉 @KodBlog
Да, в ASP.NET Core такое есть.
DelegatingHandler позволяет добавлять дополнительную логику вокруг исходящих запросов.Это похоже на middleware, только работает в обратном направлении.
Отличный сценарий использования? Добавление заголовков аутентификации в запрос.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤🔥10❤3😍2🍾1
Агенты Copilot Studio получили полноценные корпоративные идентификаторы.
Теперь каждому новому агенту автоматически выдаётся собственный Microsoft Entra Agent ID. Отключить это нельзя.
После публикации агента разрешения поддерживаемых коннекторов Power Platform отображаются прямо в его профиле в Entra.
Администраторы могут:
DLP и Advanced Connector Policies по-прежнему контролируют доступ во время выполнения.
Теперь у агента есть собственный идентификатор, назначенный ответственный, видимые разрешения, журналы и политики.
Именно такой уровень управления был нужен корпоративным агентам.
Пока есть одно ограничение: сквозное применение Conditional Access по Agent ID к вызовам коннекторов сейчас работает только в Teams. При этом разрешения видны во всех каналах.
Microsoft готовит серьёзные вещи.
👉 @KodBlog
Теперь каждому новому агенту автоматически выдаётся собственный Microsoft Entra Agent ID. Отключить это нельзя.
После публикации агента разрешения поддерживаемых коннекторов Power Platform отображаются прямо в его профиле в Entra.
Администраторы могут:
Видеть, к каким сервисам настроено обращение агента
Проверять историю входов
Управлять его жизненным циклом
Настраивать доступ к коннекторам через Conditional Access
DLP и Advanced Connector Policies по-прежнему контролируют доступ во время выполнения.
Теперь у агента есть собственный идентификатор, назначенный ответственный, видимые разрешения, журналы и политики.
Именно такой уровень управления был нужен корпоративным агентам.
Пока есть одно ограничение: сквозное применение Conditional Access по Agent ID к вызовам коннекторов сейчас работает только в Teams. При этом разрешения видны во всех каналах.
Microsoft готовит серьёзные вещи.
Please open Telegram to view this post
VIEW IN TELEGRAM
Docs
Automatically create Entra Agent IDs - Microsoft Copilot Studio
Automatically create and manage Microsoft Entra Agent IDs for agents built in Microsoft Copilot Studio.
🍾1
C# 15: примеры использования именованных
После анонса вокруг этой возможности разгорелось немало споров. Главный аргумент критиков — для выхода из вложенных циклов уже есть
На практике же разработчикам обычно приходится выбирать между
👉 @KodBlog
break и continue до и после изменений.После анонса вокруг этой возможности разгорелось немало споров. Главный аргумент критиков — для выхода из вложенных циклов уже есть
goto.На практике же разработчикам обычно приходится выбирать между
goto и дополнительными переменными для отслеживания состояния. На мой взгляд, именованные break и continue передают намерение кода заметно яснее, а примеры выше это хорошо показывают.Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4🍾3🤨1
В .NET 11 появилось множество изменений в JIT (они также применяются к Native AOT), которые устраняют избыточные проверки границ массива. Цель — сделать безопасный код таким же быстрым, как и
Эти изменения можно отслеживать по метке
https://github.com/EgorBot/Benchmarks/issues/169
#dotnet
👉 @KodBlog
unsafe.Эти изменения можно отслеживать по метке
reduce-unsafe. Один из примеров улучшений — по ссылке ниже.https://github.com/EgorBot/Benchmarks/issues/169
#dotnet
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7❤🔥2🍾1
А вы знали? Теперь в C# есть ключевое слово
Оно обязательно для всех P/Invoke-объявлений и полей в структурах с
👉 @KodBlog
safe 🙃Оно обязательно для всех P/Invoke-объявлений и полей в структурах с
explicit или extended layout. Нужно явно указать либо safe, либо unsafe — если не указать модификатор, код не скомпилируется.Please open Telegram to view this post
VIEW IN TELEGRAM
🤨8🥴4👍1👎1🍾1
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯8😁5🍾1👨💻1
Интересный эксперимент: windows-csharp
https://github.com/microsoft/windows-rs/pull/4777
Генератор C#, который строит проекции Windows API из метаданных Windows, но вместо обёрток CsWinRT генерирует прямые вызовы COM/ABI. Без
Это пока не полноценная замена (?), но уже работает с реальными приложениями на базе Composition/WinUI. 🤔
👉 @KodBlog
https://github.com/microsoft/windows-rs/pull/4777
Генератор C#, который строит проекции Windows API из метаданных Windows, но вместо обёрток CsWinRT генерирует прямые вызовы COM/ABI. Без
WinRT.Runtime.dll и без SDK projections.Это пока не полноценная замена (?), но уже работает с реальными приложениями на базе Composition/WinUI. 🤔
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
`windows-csharp` by kennykerr · Pull Request #4777 · microsoft/windows-rs
Note: this is a prototype to improve C# Reactor performance and not meant to compete with C#/WinRT.
windows-csharp is an experimental code generator that projects Windows metadata directly into C#...
windows-csharp is an experimental code generator that projects Windows metadata directly into C#...
🍾6
Что такое breaking change для API?
Вот несколько примеров:
> Удаление или переименование API-методов или параметров API.
> Изменение поведения существующих API.
> Изменение кодов ошибок API.
Breaking change означает, что вам нужно версионировать API — иначе вы рискуете сломать существующих потребителей API.
К счастью, ASP.NET Core упрощает добавление версионирования API.
И ещё немного спорное мнение: версионирование API должно быть крайней мерой.
👉 @KodBlog
Вот несколько примеров:
> Удаление или переименование API-методов или параметров API.
> Изменение поведения существующих API.
> Изменение кодов ошибок API.
Breaking change означает, что вам нужно версионировать API — иначе вы рискуете сломать существующих потребителей API.
К счастью, ASP.NET Core упрощает добавление версионирования API.
И ещё немного спорное мнение: версионирование API должно быть крайней мерой.
Please open Telegram to view this post
VIEW IN TELEGRAM
🍾1
Знали ли вы, что обмен сообщениями можно использовать по схеме request–response?
Один сервис — отправитель запроса — посылает сообщение с запросом и ожидает соответствующее ответное сообщение. Со стороны отправителя это выглядит как синхронное взаимодействие.
Вот как выглядит такой поток.
Плюсы:
Слабая связанность ✅
Прозрачность расположения сервисов ✅
Минусы:
Высокая задержка ❌
Дополнительная сложность реализации ❌
Я реализовывал такой подход с RabbitMQ и NATS — в обоих случаях он отлично себя показал.
👉 @KodBlog
Один сервис — отправитель запроса — посылает сообщение с запросом и ожидает соответствующее ответное сообщение. Со стороны отправителя это выглядит как синхронное взаимодействие.
Вот как выглядит такой поток.
Плюсы:
Слабая связанность ✅
Прозрачность расположения сервисов ✅
Минусы:
Высокая задержка ❌
Дополнительная сложность реализации ❌
Я реализовывал такой подход с RabbitMQ и NATS — в обоих случаях он отлично себя показал.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤2🐳1🍾1
Как контролировать соблюдение архитектурных правил в проекте?
Возможности компилятора C# здесь довольно ограничены, а проверять всё вручную на код-ревью дорого.
Есть промежуточный вариант, который я использую в своих проектах — архитектурные тесты.
Это автоматические тесты, которые проверяют структуру и устройство кода.
С их помощью можно задавать архитектурные правила прямо на C#:
* контролировать направление зависимостей между проектами;
* задавать правила именования классов;
* требовать, чтобы классы были
👉 @KodBlog
Возможности компилятора C# здесь довольно ограничены, а проверять всё вручную на код-ревью дорого.
Есть промежуточный вариант, который я использую в своих проектах — архитектурные тесты.
Это автоматические тесты, которые проверяют структуру и устройство кода.
С их помощью можно задавать архитектурные правила прямо на C#:
* контролировать направление зависимостей между проектами;
* задавать правила именования классов;
* требовать, чтобы классы были
sealed.Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🍾1
О правилах Clean Architecture спорят много. Но по-настоящему важно только одно.
Зависимости направлены внутрь.
Посмотрите на схему. Web.Api находится снаружи. Затем Infrastructure. Затем Application. В центре — Domain, и он ничего не знает ни об одном из этих слоёв.
В вашем Domain нет зависимостей от базы данных, веб-фреймворка или сервиса отправки почты. Там только бизнес-правила на обычном C#.
Что это даёт:
* Можно заменить Postgres на что-то другое, не меняя Domain. Хотя лучше не надо.
* Можно тестировать бизнес-правила вообще без базы данных — быстрыми юнит-тестами, которые могут написать ваши агенты.
* Новый разработчик может разобраться в ядре приложения, не изучая весь стек.
Понять это правило легко. Намного сложнее не нарушить его спустя шесть месяцев дедлайнов.
Поэтому в моём шаблоне есть архитектурные тесты, которые валят сборку в тот момент, когда внутренний слой нарушает это правило.
👉 @KodBlog
Зависимости направлены внутрь.
Посмотрите на схему. Web.Api находится снаружи. Затем Infrastructure. Затем Application. В центре — Domain, и он ничего не знает ни об одном из этих слоёв.
В вашем Domain нет зависимостей от базы данных, веб-фреймворка или сервиса отправки почты. Там только бизнес-правила на обычном C#.
Что это даёт:
* Можно заменить Postgres на что-то другое, не меняя Domain. Хотя лучше не надо.
* Можно тестировать бизнес-правила вообще без базы данных — быстрыми юнит-тестами, которые могут написать ваши агенты.
* Новый разработчик может разобраться в ядре приложения, не изучая весь стек.
Понять это правило легко. Намного сложнее не нарушить его спустя шесть месяцев дедлайнов.
Поэтому в моём шаблоне есть архитектурные тесты, которые валят сборку в тот момент, когда внутренний слой нарушает это правило.
Please open Telegram to view this post
VIEW IN TELEGRAM
🍾3👍1
C# 15 позволяет объявить тип, который может быть только одним из заранее заданного набора других типов.
Union types. Новое ключевое слово, одна строка, базовый класс не нужен.
Теперь
✔️ Неявное преобразование каждого из допустимых типов напрямую в union
✔️ Компилятор заставляет
✔️ Не нужна иерархия наследования, класс-обёртка или ручные проверки в духе «это Cat или Dog»
Пока это предварительная функция в .NET 11, поэтому синтаксис ещё может измениться до релиза.
Но попробовать уже сейчас вполне можно, если хотите заранее разобраться с новой возможностью.
👉 @KodBlog
Union types. Новое ключевое слово, одна строка, базовый класс не нужен.
public record class Cat(string Name);
public record class Dog(string Name);
public record class Bird(string Name);
public union Pet(Cat, Dog, Bird);
Теперь
Pet может содержать Cat, Dog или Bird — и ничего больше.Pet pet = new Dog("Rex");
string name = pet switch
{
Dog d => d.Name,
Cat c => c.Name,
Bird b => b.Name,
};✔️ Неявное преобразование каждого из допустимых типов напрямую в union
✔️ Компилятор заставляет
switch обработать все варианты — пропустите один, и проект не соберётся✔️ Не нужна иерархия наследования, класс-обёртка или ручные проверки в духе «это Cat или Dog»
Пока это предварительная функция в .NET 11, поэтому синтаксис ещё может измениться до релиза.
Но попробовать уже сейчас вполне можно, если хотите заранее разобраться с новой возможностью.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤🔥12🤯8❤4🎉3🍾1
Пробовали IExceptionHandler в .NET 10?
Это более простой способ глобально обрабатывать исключения. IExceptionHandler встроен в стандартный middleware обработки ошибок.
Можно обрабатывать либо все исключения, либо только конкретные типы. А значит, обработчики можно выстраивать в цепочку.
👉 @KodBlog
Это более простой способ глобально обрабатывать исключения. IExceptionHandler встроен в стандартный middleware обработки ошибок.
Можно обрабатывать либо все исключения, либо только конкретные типы. А значит, обработчики можно выстраивать в цепочку.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9👍5🍾1