В любом проекте важен контекст задачи.
Поэтому в моей архитектуре используется:
Подход с организацией по фичам
Классическая структура кода обычно строится вокруг технических паттернов:
- Command
- Queries
- Events
Из-за этого возникает серьёзная проблема — по коду непонятно, чем реально занимается приложение.
Подход с организацией по фичам полностью меняет эту логику.
Приложение структурируется вокруг бизнес-возможностей и фич.
Цель простая — проект должен «кричать» о своём назначении:
- Пользователи
- Заказы
- Продукты
Почему такая трансформация важна?
1. Высокая связанность внутри фич.
2. Низкая связанность между фичами.
3. Архитектура сама документирует себя.
4. Логичная и удобная навигация по проекту.
А что выберешь ты?🌟
👉 @KodBlog
Поэтому в моей архитектуре используется:
Подход с организацией по фичам
Классическая структура кода обычно строится вокруг технических паттернов:
- Command
- Queries
- Events
Из-за этого возникает серьёзная проблема — по коду непонятно, чем реально занимается приложение.
Подход с организацией по фичам полностью меняет эту логику.
Приложение структурируется вокруг бизнес-возможностей и фич.
Цель простая — проект должен «кричать» о своём назначении:
- Пользователи
- Заказы
- Продукты
Почему такая трансформация важна?
1. Высокая связанность внутри фич.
2. Низкая связанность между фичами.
3. Архитектура сама документирует себя.
4. Логичная и удобная навигация по проекту.
А что выберешь ты?
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7🔥2
This media is not supported in your browser
VIEW IN TELEGRAM
Это настоящий кладезь годных бесплатных инструментов для разработчиков.
Здесь есть всё: хостинг, базы данных, CDN, API, домены и куча других полезностей. Всё аккуратно разделено по категориям, что помогает легко находить нужное
https://free-for.dev/#/
👉 @KodBlog
Здесь есть всё: хостинг, базы данных, CDN, API, домены и куча других полезностей. Всё аккуратно разделено по категориям, что помогает легко находить нужное
https://free-for.dev/#/
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6
Запуск .NET в браузере без Blazor
https://andrewlock.net/running-dotnet-in-the-browser-without-blazor/
В этой статье автор показывает, как запустить .NET в браузере без использования Blazor, а вместо этого опереться на более низкоуровневые абстракции, которые предоставляют [JSImport] и [JSExport].
👉 @KodBlog
https://andrewlock.net/running-dotnet-in-the-browser-without-blazor/
В этой статье автор показывает, как запустить .NET в браузере без использования Blazor, а вместо этого опереться на более низкоуровневые абстракции, которые предоставляют [JSImport] и [JSExport].
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10❤5👍2
В .NET долгое время одним из самых удобных инструментов для организации CQRS и разделения логики был MediatR, он помогал структурировать команды и запросы, разгружал API слой и снижал связанность кода. Многие проекты, особенно с архитектурой Vertical Slice, держались на нём годами.
Но в работе со сложными сценариями у MediatR есть нюанс. Из-за отвязки команд и обработчиков навигация по коду и отладка становятся менее очевидными, особенно когда один обработчик начинает вызывать другой.
Альтернатива, которая решает эти проблемы, — переход на простые ручные обработчики. Такой подход убирает лишнюю рефлексию и декораторы, упрощает трассировку, а IDE быстрее находит нужный участок кода.
Вот гайд как выстроить систему, где:
> Стартовая реализация использует MediatR, а затем заменяется на ручные обработчики
> Регистрация обработчиков происходит автоматически
> Уведомления обрабатываются без MediatR Notifications
> Общая функциональность (логирование, валидация, транзакции) подключается без лишней обвязки
В результате получается решение с теми же преимуществами в архитектуре, но с более прямым и прозрачным кодом, что особенно полезно для крупных и долгоживущих проектов.
👉 @KodBlog
Но в работе со сложными сценариями у MediatR есть нюанс. Из-за отвязки команд и обработчиков навигация по коду и отладка становятся менее очевидными, особенно когда один обработчик начинает вызывать другой.
Альтернатива, которая решает эти проблемы, — переход на простые ручные обработчики. Такой подход убирает лишнюю рефлексию и декораторы, упрощает трассировку, а IDE быстрее находит нужный участок кода.
Вот гайд как выстроить систему, где:
> Стартовая реализация использует MediatR, а затем заменяется на ручные обработчики
> Регистрация обработчиков происходит автоматически
> Уведомления обрабатываются без MediatR Notifications
> Общая функциональность (логирование, валидация, транзакции) подключается без лишней обвязки
В результате получается решение с теми же преимуществами в архитектуре, но с более прямым и прозрачным кодом, что особенно полезно для крупных и долгоживущих проектов.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9❤6
image_2025-08-14_11-10-45.png
1.7 MB
Примеры middleware для ограничения частоты запросов в
1. Fixed Window Limiter (20 запросов за 2 минуты)
Фиксированное временное окно. После достижения лимита блокирует все запросы до конца текущего окна. Лимит сбрасывается каждые 2 минуты.
2. Sliding Window Limiter (20 запросов за 2 минуты, 4 сегмента)
Делит окно на сегменты (в примере 4 сегмента по 30 секунд). Когда открывается новый сегмент, самый старый истекает. Это распределяет нагрузку более равномерно и сглаживает трафик.
3. Token Bucket Limiter (15 токенов максимум, пополнение 1 токен/сек)
Позволяет кратковременные всплески нагрузки за счёт накопленных токенов. Каждый запрос расходует токен, при их нехватке запросы ограничиваются до восстановления токенов (по 1 в секунду).
4. Concurrency Limiter (5 параллельных запросов, 10 в очереди)
Ограничивает число одновременно обрабатываемых запросов (в примере до 5). Остальные попадают в очередь (до 10). Если очередь переполнена, новые запросы возвращают 503 или 429 (если переопределено).
В коде эти лимитеры регистрируются в
👉 @KodBlog
ASP .NET
1. Fixed Window Limiter (20 запросов за 2 минуты)
Фиксированное временное окно. После достижения лимита блокирует все запросы до конца текущего окна. Лимит сбрасывается каждые 2 минуты.
2. Sliding Window Limiter (20 запросов за 2 минуты, 4 сегмента)
Делит окно на сегменты (в примере 4 сегмента по 30 секунд). Когда открывается новый сегмент, самый старый истекает. Это распределяет нагрузку более равномерно и сглаживает трафик.
3. Token Bucket Limiter (15 токенов максимум, пополнение 1 токен/сек)
Позволяет кратковременные всплески нагрузки за счёт накопленных токенов. Каждый запрос расходует токен, при их нехватке запросы ограничиваются до восстановления токенов (по 1 в секунду).
4. Concurrency Limiter (5 параллельных запросов, 10 в очереди)
Ограничивает число одновременно обрабатываемых запросов (в примере до 5). Остальные попадают в очередь (до 10). Если очередь переполнена, новые запросы возвращают 503 или 429 (если переопределено).
В коде эти лимитеры регистрируются в
AddRateLimiter()
и привязываются к конкретным эндпоинтам через .RequireRateLimiting()
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11👏3❤2🔥1
Как находить медленные запросы в Entity Framework
Используя систему перехватчиков Entity Framework и подключаясь к событию
Сохрани в закладки🧀
Как это работает
1. Создаём класс перехватчика, наследуемся от
2. Регистрируем этот перехватчик в контексте через
👉 @KodBlog
Используя систему перехватчиков Entity Framework и подключаясь к событию
ReaderExecuted
мы можем видеть сколько времени реально занимают запросыСохрани в закладки
public class SlowQueryInterceptor : DbCommandInterceptor
{
private const int _slowQueryThreshold = 200; // миллисекунды
public override DbDataReader ReaderExecuted(
DbCommand command,
CommandExecutedEventData eventData,
DbDataReader result)
{
if (eventData.Duration.TotalMilliseconds > _slowQueryThreshold)
{
// Логируем медленный запрос — тут можно вставить свою систему логирования
Console.WriteLine(
$"Slow query ({eventData.Duration.TotalMilliseconds} ms): {command.CommandText}");
}
return base.ReaderExecuted(command, eventData, result);
}
}
public class YourDbContext : DbContext
{
// ... твои DbSet ...
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlServer("YourConnectionString") // замени на свою строку подключения
.AddInterceptors(new SlowQueryInterceptor());
}
}
Как это работает
1. Создаём класс перехватчика, наследуемся от
DbCommandInterceptor
и реализуем метод ReaderExecuted
2. Регистрируем этот перехватчик в контексте через
AddInterceptors
Please open Telegram to view this post
VIEW IN TELEGRAM
👍20❤2
Изоляция данных в модульном монолите
- Схема и роль на модуль — для каждого модуля создаётся собственная схема и роль
- Привилегии только для своей схемы — модуль не имеет доступа к данным других схем
- Отдельный DbContext + схема по умолчанию — разделение кода и данных на уровне ORM
- Разные строки подключения и миграции — независимое управление конфигурацией и развёртыванием
- Read-only представления для межмодульных запросов — безопасный доступ к данным между модулями
Смотрите пошаговое руководство: ссылка
👉 @KodBlog
- Схема и роль на модуль — для каждого модуля создаётся собственная схема и роль
- Привилегии только для своей схемы — модуль не имеет доступа к данным других схем
- Отдельный DbContext + схема по умолчанию — разделение кода и данных на уровне ORM
- Разные строки подключения и миграции — независимое управление конфигурацией и развёртыванием
- Read-only представления для межмодульных запросов — безопасный доступ к данным между модулями
Смотрите пошаговое руководство: ссылка
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5
Сохрани этот пост
Покажу репозиторий на GitHub, где есть 99% кода, который тебе нужен для разработки
485 примеров кода .NET в одном месте🙏
Репозиторий называется:
practical-aspnetcore — https://github.com/dodyg/practical-aspnetcore
В одном месте собрано 485 практических примеров, чтобы ты мог понять и эффективно внедрить ключевые возможности ASP .NET Core
Что покрыто:
Это, по сути, швейцарский нож для .NET - инструменты почти для любой ситуации
👉 @KodBlog
Покажу репозиторий на GitHub, где есть 99% кода, который тебе нужен для разработки
485 примеров кода .NET в одном месте
Репозиторий называется:
practical-aspnetcore — https://github.com/dodyg/practical-aspnetcore
В одном месте собрано 485 практических примеров, чтобы ты мог понять и эффективно внедрить ключевые возможности ASP .NET Core
Что покрыто:
Authentication
Blazor
Caching
gRPC
HealthCheck
Localization
Logging
Middleware
Minimal API
Open Telemetry
Routing
SignalR
Security
YARP
Это, по сути, швейцарский нож для .NET - инструменты почти для любой ситуации
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16❤4🔥4😁1
Что такое RBAC и как это помогает с авторизацией
RBAC расшифровывается как Role-Based Access Control, то есть управление доступом на основе ролей
Суть простая
• У ролей есть набор разрешений
• Пользователи получают роли
• Разрешения определяют, что пользователи могут делать
Всё довольно просто, но при этом мощно
Хотя сами по себе роли могут быть слишком широкими
Поэтому я предпочитаю комбинировать роли с более точечными разрешениями.
Вместо того чтобы хардкодить правила доступа, я привязываю разрешения к конкретным действиям и уже потом связываю эти разрешения с ролями
Так проще управлять и легче расширять
Как смоделировать такой подход и применить его в .NET — читать
А как у тебя сейчас устроена авторизация в системе😏
👉 @KodBlog
RBAC расшифровывается как Role-Based Access Control, то есть управление доступом на основе ролей
Суть простая
• У ролей есть набор разрешений
• Пользователи получают роли
• Разрешения определяют, что пользователи могут делать
Всё довольно просто, но при этом мощно
Хотя сами по себе роли могут быть слишком широкими
Поэтому я предпочитаю комбинировать роли с более точечными разрешениями.
Вместо того чтобы хардкодить правила доступа, я привязываю разрешения к конкретным действиям и уже потом связываю эти разрешения с ролями
Так проще управлять и легче расширять
Как смоделировать такой подход и применить его в .NET — читать
А как у тебя сейчас устроена авторизация в системе
Please open Telegram to view this post
VIEW IN TELEGRAM
❤🔥4👍3❤2🔥2
Я отучаюсь от всего, что знал про юнит-тестирование
Потому что большая часть этого — неправда
Для юнит-тестов нужен mocking-фреймворк
Юнит-тест должен покрывать один метод
С EF Core обязательно использовать Repository-паттерн для тестирования
Если всё это совместить, получаются хрупкие тесты, которые ничего не говорят о требованиях и вынуждают плодить ненужные слои
Вместо этого я придерживаюсь простых правил
• Использовать фейки вместо mocking-фреймворка
• Юнит-тесты проверяют поведение, а не структуру
• При работе с EF Core использовать in-memory или SQLite провайдер и обходить их ограничения через интеграционные тесты
Так тесты становятся менее хрупкими, покрывают больше кода и требуют меньше поддержки
Кто со мной?
👉 @KodBlog
Потому что большая часть этого — неправда
Для юнит-тестов нужен mocking-фреймворк
Юнит-тест должен покрывать один метод
С EF Core обязательно использовать Repository-паттерн для тестирования
Если всё это совместить, получаются хрупкие тесты, которые ничего не говорят о требованиях и вынуждают плодить ненужные слои
Вместо этого я придерживаюсь простых правил
• Использовать фейки вместо mocking-фреймворка
• Юнит-тесты проверяют поведение, а не структуру
• При работе с EF Core использовать in-memory или SQLite провайдер и обходить их ограничения через интеграционные тесты
Так тесты становятся менее хрупкими, покрывают больше кода и требуют меньше поддержки
Кто со мной?
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤3😁1🤔1
Предпочитай
1. Корректность (например, проблема с турецкой буквой
2. Читаемость
3. Производительность
👉 @KodBlog
string.Equals
вместо ToLower
/ ToUpper
для нечувствительных к регистру сравнений строк1. Корректность (например, проблема с турецкой буквой
i
)2. Читаемость
3. Производительность
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤3🔥2👏1
Нужны пиксельно идеальные PDF-отчёты в .NET?
Забей на проприетарные библиотеки, используй HTML-шаблоны и PuppeteerSharp.
Собери отчёт как HTML-шаблон на Handlebars, подставь данные, а потом отрендерь в PDF через headless-браузер.
Учись генерировать удобные и красивые PDF-отчёты с
👉 @KodBlog
Забей на проприетарные библиотеки, используй HTML-шаблоны и PuppeteerSharp.
Собери отчёт как HTML-шаблон на Handlebars, подставь данные, а потом отрендерь в PDF через headless-браузер.
Учись генерировать удобные и красивые PDF-отчёты с
Handlebars.NET
и PuppeteerSharp — гайд МиланаPlease open Telegram to view this post
VIEW IN TELEGRAM
❤11👍4
Вызов Azure Function из Azure SQL DB
Да, это реально. Хранимая процедура
Кто-то уже пробовал?
👉 @KodBlog
Да, это реально. Хранимая процедура
sp_invoke_external_rest_endpoint
позволяет дергать HTTPS REST endpoint, переданный ей в качестве аргумента.Кто-то уже пробовал?
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍2🤔2🎉2
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🤔3🍌2🤨1
Лучшая техника dependency injection, которой почти никто не пользуется
(больше никаких конструкторов на 10 строк)
Используй
Это малоизвестная фича в ASP.NET Core, которая позволяет инжектить зависимости прямо в метод эндпоинта
Для этого можно использовать
Но
Когда это уместно
• Когда сервис нужен только в одном экшене
• Когда конструктор превращается в лапшу
• Когда сервис тяжёлый и хочется лучше контролировать память
Да, constructor injection по умолчанию — это стандартный подход
Но method injection — это удобный инструмент, если хочется делать более мелкие сервисы, которые соблюдают принцип единственной ответственности, и при этом иметь контроллеры, не превращённые в свалку зависимостей
👉 @KodBlog
(больше никаких конструкторов на 10 строк)
Используй
Method Injection
Это малоизвестная фича в ASP.NET Core, которая позволяет инжектить зависимости прямо в метод эндпоинта
Для этого можно использовать
[FromServices] IYourService
Но
[FromServices]
можно и не указыватьКогда это уместно
• Когда сервис нужен только в одном экшене
• Когда конструктор превращается в лапшу
• Когда сервис тяжёлый и хочется лучше контролировать память
Да, constructor injection по умолчанию — это стандартный подход
Но method injection — это удобный инструмент, если хочется делать более мелкие сервисы, которые соблюдают принцип единственной ответственности, и при этом иметь контроллеры, не превращённые в свалку зависимостей
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤🔥2😁2
Твой опыт с NuGet в .NET ограничивается AutoMapper?
Быть в курсе .NET = быть в курсе инструментов.
Не отставай — вот 24 NuGet-библиотеки
👉 @KodBlog
Быть в курсе .NET = быть в курсе инструментов.
Не отставай — вот 24 NuGet-библиотеки
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6🔥1
Когда исключения неизбежны, нужен механизм для их обработки.
Вот как это можно настроить за несколько минут:
Начиная с .NET 8 у вас есть интерфейс
Это абстракция для управления исключениями с одним методом:
Он отвечает за обработку исключений в пайплайне ASP.NET Core.
Метод возвращает
Это позволяет реализовать кастомную логику под разные сценарии.
Для конфигурации нужно сделать три шага:
1. Зарегистрировать сервис
2. Зарегистрировать
3. Зарегистрировать
Третий шаг опционален, но я настоятельно рекомендую его использовать, чтобы ошибки были более читаемыми.
👉 @KodBlog
Вот как это можно настроить за несколько минут:
Начиная с .NET 8 у вас есть интерфейс
IExceptionHandler
Это абстракция для управления исключениями с одним методом:
TryHandleAsync
Он отвечает за обработку исключений в пайплайне ASP.NET Core.
Метод возвращает
true
, если исключение обработано успешно, и false
, если его нельзя обработать.Это позволяет реализовать кастомную логику под разные сценарии.
Для конфигурации нужно сделать три шага:
1. Зарегистрировать сервис
IExceptionHandler
через dependency injection2. Зарегистрировать
ExceptionHandlerMiddleware
в пайплайне запросов3. Зарегистрировать
ProblemDetails
ответТретий шаг опционален, но я настоятельно рекомендую его использовать, чтобы ошибки были более читаемыми.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤3
Хочешь писать более чистый C#-код?
Начни с чистых функций.
Чистая функция проста:
Берёт входные данные, возвращает результат и больше ни на что не влияет.
Никаких запросов в базу. Никаких случайных значений. Никаких скрытых побочных эффектов
Такой код легче тестировать, отлаживать и ему проще доверять.
Если логика кажется непредсказуемой — попробуй вынести её в чистую функцию.
Удивишься, насколько всё станет понятнее.
👉 @KodBlog
Начни с чистых функций.
Чистая функция проста:
Берёт входные данные, возвращает результат и больше ни на что не влияет.
Никаких запросов в базу. Никаких случайных значений. Никаких скрытых побочных эффектов
Такой код легче тестировать, отлаживать и ему проще доверять.
Если логика кажется непредсказуемой — попробуй вынести её в чистую функцию.
Удивишься, насколько всё станет понятнее.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7