CQRS ≠ MediatR.
Перестаньте смешивать CQRS и MediatR.
То, что вы используете MediatR, не означает, что у вас реализован CQRS.
CQRS — это про разделение операций чтения и записи, часто с разными моделями, стратегиями хранения и иногда с разными хранилищами данных.
MediatR — это библиотека для диспетчеризации сообщений внутри процесса. Она удобна для организации команд и запросов, но это не фреймворк CQRS.
Можно использовать MediatR в архитектуре, построенной по CQRS.
Но не стоит считать, что одно автоматически означает другое.
Сначала разберитесь в различии, прежде чем внедрять паттерн или инструмент.
👉 @KodBlog
Перестаньте смешивать CQRS и MediatR.
То, что вы используете MediatR, не означает, что у вас реализован CQRS.
CQRS — это про разделение операций чтения и записи, часто с разными моделями, стратегиями хранения и иногда с разными хранилищами данных.
MediatR — это библиотека для диспетчеризации сообщений внутри процесса. Она удобна для организации команд и запросов, но это не фреймворк CQRS.
Можно использовать MediatR в архитектуре, построенной по CQRS.
Но не стоит считать, что одно автоматически означает другое.
Сначала разберитесь в различии, прежде чем внедрять паттерн или инструмент.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤4🍾1
Два списания одновременно с одного и того же банковского счёта — что может пойти не так?
Если плохо управлять конкурентным доступом, последствия могут быть критичными:
-» дублирующиеся списания
-» потеря денег💸
Начиная с .NET 9, используйте
#dotnet #csharp
👉 @KodBlog
Если плохо управлять конкурентным доступом, последствия могут быть критичными:
-» дублирующиеся списания
-» потеря денег
Начиная с .NET 9, используйте
Lock и контролируйте конкурентный доступ.#dotnet #csharp
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10🥴4👎2🍾1
В EF Core методы
Они лишь помечают сущность как новую для последующей вставки.
Сам
#dotnet #efcore
👉 @KodBlog
Add() и AddAsync() не выполняют вставку в БД.Они лишь помечают сущность как новую для последующей вставки.
Сам
INSERT происходит при вызове SaveChanges() или SaveChangesAsync().AddAsync() имеет смысл только в специфичных кейсах, например с HiLo, когда EF Core может получить идентификатор до сохранения.#dotnet #efcore
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🍾2
Вот насколько просто создать HTTP-сервер с помощью минимального API в .NET на C#.
Ты уже знал об этом?
👉 @KodBlog
Ты уже знал об этом?
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16🍾2
Please open Telegram to view this post
VIEW IN TELEGRAM
Andrew Lock | .NET Escapades
Removing byte[] allocations in .NET Framework using ReadOnlySpan<T>
In this post I describe how to remove static byte[] allocations, even on .NET Framework, by using Span<T>, look at the associated IL, and discuss the risks
👍6❤1🍾1
This media is not supported in your browser
VIEW IN TELEGRAM
90% разработчиков используют LINQ неправильно… и теряют производительность
Если вы повторяете вычисления внутри запроса, вы делаете двойную работу
Используйте
✅ одно вычисление
✅ + производительность
✅ + читаемость
👉 @KodBlog
Если вы повторяете вычисления внутри запроса, вы делаете двойную работу
Используйте
let и оптимизируйте всёPlease open Telegram to view this post
VIEW IN TELEGRAM
👍10🤯3❤2🍾1
Кэширование — одна из тех вещей, где каждый .NET-разработчик уверен, что разобрался.
Пока не ломается прод.
Большинство команд, с которыми я работал, используют IMemoryCache или Redis и на этом останавливаются. У обоих есть реальные проблемы, которые проявляются только на масштабе.
Потом в .NET 9 появился HybridCache и тихо закрыл то, что обычно костылят вручную.
Разберём по порядку.
𝗜𝗠𝗲𝗺𝗼𝗿𝘆𝗖𝗮𝗰𝗵𝗲
Очень быстрый. Живёт внутри приложения, чтение практически бесплатное.
Но как только появляется больше одного инстанса — начинаются рассинхроны. Каждый сервер держит свою копию. Пользователь попадает на сервер A — получает свежие данные. Следующий запрос уходит на сервер B — получает устаревшие. Баги, которые всплывают только в проде.
𝗥𝗲𝗱𝗶𝘀 (или любой распределённый кэш)
Общий для всех инстансов. Проблему консистентности закрывает.
Но каждое чтение — это сетевой вызов плюс сериализация с обеих сторон. Быстрее базы, но уже не уровень in-memory.
𝗛𝘆𝗯𝗿𝗶𝗱𝗖𝗮𝗰𝗵𝗲
Идея простая: использовать оба слоя.
Сначала проверяется память (L1). Если есть — возврат мгновенно.
Если нет — проверяется Redis (L2). Если есть — вернуть и прогреть L1.
Если нет — запрос в базу, запись в оба слоя, возврат.
Скорость памяти для горячих данных. Консистентность распределённого кэша для остального.
𝗣𝗿𝗼𝗯𝗹𝗲𝗺𝗮, о которой редко говорят
Часто ловит даже опытные команды.
Представим: популярный ключ протух. В этот же момент приходит 500 запросов на этот ключ. Все 500 промахиваются по кэшу. Все 500 одновременно идут в базу.
База ложится. Локально почти не воспроизводится.
Обычно это закрывают через SemaphoreSlim и ретраи. HybridCache решает это из коробки: только один запрос идёт за данными, остальные ждут тот же результат.
𝗣𝗼𝗷𝗲𝗺𝘂 это становится дефолтом
• Работает без Redis: старт с in-memory, потом подключение распределённого слоя без переписывания
• Инвалидация по тегам встроена — не нужно вручную трекать ключи
• Защита от конкурентных промахов уже есть
• Единый API — GetOrCreateAsync закрывает весь флоу
• Поставляется вместе с .NET 9
Если до сих пор пишется cache-aside логика с ручными локами и ретраями — HybridCache уже покрывает этот сценарий.
👉 @KodBlog
Пока не ломается прод.
Большинство команд, с которыми я работал, используют IMemoryCache или Redis и на этом останавливаются. У обоих есть реальные проблемы, которые проявляются только на масштабе.
Потом в .NET 9 появился HybridCache и тихо закрыл то, что обычно костылят вручную.
Разберём по порядку.
𝗜𝗠𝗲𝗺𝗼𝗿𝘆𝗖𝗮𝗰𝗵𝗲
Очень быстрый. Живёт внутри приложения, чтение практически бесплатное.
Но как только появляется больше одного инстанса — начинаются рассинхроны. Каждый сервер держит свою копию. Пользователь попадает на сервер A — получает свежие данные. Следующий запрос уходит на сервер B — получает устаревшие. Баги, которые всплывают только в проде.
𝗥𝗲𝗱𝗶𝘀 (или любой распределённый кэш)
Общий для всех инстансов. Проблему консистентности закрывает.
Но каждое чтение — это сетевой вызов плюс сериализация с обеих сторон. Быстрее базы, но уже не уровень in-memory.
𝗛𝘆𝗯𝗿𝗶𝗱𝗖𝗮𝗰𝗵𝗲
Идея простая: использовать оба слоя.
Сначала проверяется память (L1). Если есть — возврат мгновенно.
Если нет — проверяется Redis (L2). Если есть — вернуть и прогреть L1.
Если нет — запрос в базу, запись в оба слоя, возврат.
Скорость памяти для горячих данных. Консистентность распределённого кэша для остального.
𝗣𝗿𝗼𝗯𝗹𝗲𝗺𝗮, о которой редко говорят
Часто ловит даже опытные команды.
Представим: популярный ключ протух. В этот же момент приходит 500 запросов на этот ключ. Все 500 промахиваются по кэшу. Все 500 одновременно идут в базу.
База ложится. Локально почти не воспроизводится.
Обычно это закрывают через SemaphoreSlim и ретраи. HybridCache решает это из коробки: только один запрос идёт за данными, остальные ждут тот же результат.
𝗣𝗼𝗷𝗲𝗺𝘂 это становится дефолтом
• Работает без Redis: старт с in-memory, потом подключение распределённого слоя без переписывания
• Инвалидация по тегам встроена — не нужно вручную трекать ключи
• Защита от конкурентных промахов уже есть
• Единый API — GetOrCreateAsync закрывает весь флоу
• Поставляется вместе с .NET 9
Если до сих пор пишется cache-aside логика с ручными локами и ретраями — HybridCache уже покрывает этот сценарий.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🍾2
Три способа описания навыков агента в .NET — файл, класс или встроенный вариант — все работают через одного провайдера. Добавляется выполнение скриптов и ручное подтверждение, что даёт гибкую и управляемую модель навыков для реальных приложений.
Статья: https://buff.ly/4jUlnBi
👉 @KodBlog
Статья: https://buff.ly/4jUlnBi
Please open Telegram to view this post
VIEW IN TELEGRAM
Microsoft News
Agent Skills in .NET: Three Ways to Author, One Provider to Run Them
Your agents can now draw on skills authored in three different ways – as files on disk, as inline C# code, or as encapsulated classes – and combine them freely in a single provider. Add built-in script execution support and a human-approval mechanism for…
🍾2
dotNET 11 Preview 3 уже доступен — улучшения в JIT, доработки асинхронности, обновления WebCIL, поддержка Zstandard повсеместно, апдейты карт в MAUI, упрощение SQL в EFCore и подписанные контейнерные образы.
Если важны скорость, чистота и современный стек — есть на что посмотреть.
👉 @KodBlog
Если важны скорость, чистота и современный стек — есть на что посмотреть.
Please open Telegram to view this post
VIEW IN TELEGRAM
🍾3
GitHub Quick Review (ghqr)
Бесплатный CLI с открытым исходным кодом, который сканирует организации и репозитории GitHub на соответствие лучшим практикам.
Одна команда — полный отчёт по состоянию.
https://github.com/microsoft/ghqr
👉 @KodBlog
Бесплатный CLI с открытым исходным кодом, который сканирует организации и репозитории GitHub на соответствие лучшим практикам.
Одна команда — полный отчёт по состоянию.
https://github.com/microsoft/ghqr
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
GitHub - microsoft/ghqr: GitHub Quick Review. Evaluate your enterprise and organizations with GitHub best practices
GitHub Quick Review. Evaluate your enterprise and organizations with GitHub best practices - microsoft/ghqr
🍾1
Не знаю, сколько из вас знают про этот репозиторий на GitHub по веб-сокетам.
В нём собрана вся документация, связанная с реализацией и использованием веб-сокетов, а также статьи и научные работы — в целом всё, что относится к ws, в одном месте.
(Это курируемый список инструментов, библиотек и материалов по веб-сокетам, сгруппированный по языкам и темам)
https://github.com/facundofarias/awesome-websockets
👉 @KodBlog
В нём собрана вся документация, связанная с реализацией и использованием веб-сокетов, а также статьи и научные работы — в целом всё, что относится к ws, в одном месте.
(Это курируемый список инструментов, библиотек и материалов по веб-сокетам, сгруппированный по языкам и темам)
https://github.com/facundofarias/awesome-websockets
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
GitHub - facundofarias/awesome-websockets: A curated list of Websocket libraries and resources.
A curated list of Websocket libraries and resources. - facundofarias/awesome-websockets
🍾1
Минимальные API и версионирование API — это бардак.
Если только не сделать это правильно.
Вместо того чтобы вешать
Версия задаётся один раз и применяется ко всем эндпоинтам внутри группы.
Маршруты становятся чище, дублирования меньше. Плюс удобно для префиксов вроде
Хочешь посмотреть, как это работает (и с Minimal API, и с контроллерами)?
Вот гайд: https://milanjovanovic.tech/blog/api-versioning-in-aspnetcore
👉 @KodBlog
Если только не сделать это правильно.
Вместо того чтобы вешать
ApiVersionSet на каждый эндпоинт, можно определить группу маршрутов.Версия задаётся один раз и применяется ко всем эндпоинтам внутри группы.
Маршруты становятся чище, дублирования меньше. Плюс удобно для префиксов вроде
/v1.Хочешь посмотреть, как это работает (и с Minimal API, и с контроллерами)?
Вот гайд: https://milanjovanovic.tech/blog/api-versioning-in-aspnetcore
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2🍾1
Ответы об ошибках в API обычно выглядят как мусор. ProblemDetails это исправляет.
Вот типичный ответ при ошибке:
"Object reference not set to an instance of an object."
Пользы ноль.
А вот что даёт ProblemDetails:
Структурировано. Читаемо. Соответствует стандарту (RFC 9457).
В .NET 10 настройка стала удобнее.
Нужно три вещи:
→ AddProblemDetails() — регистрирует встроенные сервисы ProblemDetails
→ IExceptionHandler — современный способ обработки исключений (вместо кастомного посредника)
→ StatusCodeSelector — автоматически мапит типы исключений на HTTP-статусы
Изменение в .NET 10:
Если
Теперь обработчик сам отвечает за логирование.
Если нужно старое поведение — используй
Базовая настройка в Program.cs занимает несколько строк:
- AddProblemDetails()
- AddExceptionHandler<YourHandler>()
- UseExceptionHandler()
- UseStatusCodePages()
Без сторонних пакетов. Без самописных посредников. Всё встроено в .NET.
👉 @KodBlog
Вот типичный ответ при ошибке:
"Object reference not set to an instance of an object."
Пользы ноль.
А вот что даёт ProblemDetails:
{
"title": "Product not found",
"status": 404,
"detail": "No product with ID 42.",
"instance": "/products/42"
}Структурировано. Читаемо. Соответствует стандарту (RFC 9457).
В .NET 10 настройка стала удобнее.
Нужно три вещи:
→ AddProblemDetails() — регистрирует встроенные сервисы ProblemDetails
→ IExceptionHandler — современный способ обработки исключений (вместо кастомного посредника)
→ StatusCodeSelector — автоматически мапит типы исключений на HTTP-статусы
Изменение в .NET 10:
Если
IExceptionHandler возвращает true, посредник больше не пишет диагностику (логи, метрики) по умолчанию.Теперь обработчик сам отвечает за логирование.
Если нужно старое поведение — используй
SuppressDiagnosticsCallback.Базовая настройка в Program.cs занимает несколько строк:
- AddProblemDetails()
- AddExceptionHandler<YourHandler>()
- UseExceptionHandler()
- UseStatusCodePages()
Без сторонних пакетов. Без самописных посредников. Всё встроено в .NET.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6🤣2🍾1
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
GitHub - h4ckf0r0day/obscura: The headless browser for AI agents and web scraping
The headless browser for AI agents and web scraping - h4ckf0r0day/obscura
🌚5🤩2🤣2🍾1
Как правильно структурировать фичу в формате вертикального среза?
Вот простая структура вертикального среза, которую можно смело брать на вооружение:
🔸 Объект запроса/ответа
🔸 Определение эндпоинта
🔸 Бизнес-логика
Всё, что относится к одной фиче, находится в одном месте.
Почему это круто — объяснено здесь
Если ты до сих пор не используешь подход с вертикальными срезами, скорее всего, твое приложение концептуально сложнее, чем нужно.
👉 @KodBlog
Вот простая структура вертикального среза, которую можно смело брать на вооружение:
Всё, что относится к одной фиче, находится в одном месте.
Почему это круто — объяснено здесь
Если ты до сих пор не используешь подход с вертикальными срезами, скорее всего, твое приложение концептуально сложнее, чем нужно.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤3🍾2
Это изменит работу с вашими API:
(начиная с .NET 9)
Начиная с .NET 9, Swagger больше не входит в стартовый шаблон Web API.
Microsoft убрали Swashbuckle.AspNetCore, так как он больше не поддерживается активно.
Вместо этого из коробки доступен Microsoft.AspNetCore.OpenApi для генерации OpenAPI-документов.
Но это означает, что встроенного UI для отображения эндпоинтов API больше нет.
Поэтому можно вручную вернуть Swashbuckle.
Либо использовать альтернативы, например Scalar.
Некоторые возможности Scalar:
- Встроенный API-клиент / playground
- Интерактивная документация API
- Тёмная тема из коробки
- Лёгкий деплой
- Интеграции с фреймворками
.NET мог отказаться от Swagger.
Но это может привести к более качественной документации API.
👉 @KodBlog
(начиная с .NET 9)
Начиная с .NET 9, Swagger больше не входит в стартовый шаблон Web API.
Microsoft убрали Swashbuckle.AspNetCore, так как он больше не поддерживается активно.
Вместо этого из коробки доступен Microsoft.AspNetCore.OpenApi для генерации OpenAPI-документов.
Но это означает, что встроенного UI для отображения эндпоинтов API больше нет.
Поэтому можно вручную вернуть Swashbuckle.
Либо использовать альтернативы, например Scalar.
Некоторые возможности Scalar:
- Встроенный API-клиент / playground
- Интерактивная документация API
- Тёмная тема из коробки
- Лёгкий деплой
- Интеграции с фреймворками
.NET мог отказаться от Swagger.
Но это может привести к более качественной документации API.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍4🍾2
Что не нужно на старте:
- Kubernetes
- Микросервисы
- Раздельные базы для чтения/записи
Что нужно:
- Юнит-тесты
- Конвейер CI/CD
- Здоровые кодовые привычки
- Монолитная архитектура на старте
«А что, если монолит перерастёт сам себя?»
В этом и идея. Монолит — не навсегда.
Начинаешь с простого.
Дальше эволюционируешь осознанно по мере изменения требований.
Это называется Эволюционная архитектура, и лучше всего это понимается на практике.
4 репозитория на GitHub:
1. Evolutionary Architecture by Example:
https://github.com/evolutionary-architecture/evolutionary-architecture-by-example
2. Booking to Cloud Architecture — монолит:
https://github.com/meysamhadeli/booking-monolith
3. Booking to Cloud Architecture — модульный монолит:
https://github.com/meysamhadeli/booking-modular-monolith
4. Booking to Cloud Architecture — микросервисы:
https://github.com/meysamhadeli/booking-microservices
Отсутствие простоты, а не времени — основной враг в любом проекте.
👉 @KodBlog
- Kubernetes
- Микросервисы
- Раздельные базы для чтения/записи
Что нужно:
- Юнит-тесты
- Конвейер CI/CD
- Здоровые кодовые привычки
- Монолитная архитектура на старте
«А что, если монолит перерастёт сам себя?»
В этом и идея. Монолит — не навсегда.
Начинаешь с простого.
Дальше эволюционируешь осознанно по мере изменения требований.
Это называется Эволюционная архитектура, и лучше всего это понимается на практике.
4 репозитория на GitHub:
1. Evolutionary Architecture by Example:
https://github.com/evolutionary-architecture/evolutionary-architecture-by-example
2. Booking to Cloud Architecture — монолит:
https://github.com/meysamhadeli/booking-monolith
3. Booking to Cloud Architecture — модульный монолит:
https://github.com/meysamhadeli/booking-modular-monolith
4. Booking to Cloud Architecture — микросервисы:
https://github.com/meysamhadeli/booking-microservices
Отсутствие простоты, а не времени — основной враг в любом проекте.
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
GitHub - evolutionary-architecture/evolutionary-architecture-by-example: Navigate the complex landscape of .NET software architecture…
Navigate the complex landscape of .NET software architecture with our step-by-step, story-like guide. Unpack the interplay between modular monoliths, microservices, domain-driven design, and variou...
❤5🍾1
State и Strategy в C#: ключевые отличия
Сравнение паттернов State и Strategy в C# с примерами кода бок о бок, ключевыми различиями в поведении и рекомендациями, когда какой использовать.
Читать статью здесь: https://bgh.st/3cce96
👉 @KodBlog
Сравнение паттернов State и Strategy в C# с примерами кода бок о бок, ключевыми различиями в поведении и рекомендациями, когда какой использовать.
Читать статью здесь: https://bgh.st/3cce96
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5🍾1
Как использовать enum в C#: объявление, значения и лучшие практики
Разбор использования перечислений в C# с нуля: объявление, задание значений, приведение типов, сравнение, перебор и практики, которые стоит применять в продакшене.
Читать статью здесь: https://bgh.st/djmghy
👉 @KodBlog
Разбор использования перечислений в C# с нуля: объявление, задание значений, приведение типов, сравнение, перебор и практики, которые стоит применять в продакшене.
Читать статью здесь: https://bgh.st/djmghy
Please open Telegram to view this post
VIEW IN TELEGRAM
Dev Leader
How to Use Enum in C#: Declaration, Values, and Best Practices
Learn how to use enum in C# from scratch. Covers declaring enums, assigning values, casting, comparing, iterating, and the best practices every C# developer sho
👍6🍾1
required string и string? в EF Core — это не просто разница в синтаксисе, это семантика модели и контракт с базой.
- required string → обязательная инициализация в модели + колонка NOT NULL в БД
- string? → допускает null + колонка с NULL в БД
EF Core использует nullable-аннотации и контекст компилятора, чтобы выводить ограничение целостности схемы. Это напрямую влияет на миграции и поведение трекинга изменений.
Важно: доменную модель нужно задавать явно, а бизнес-ограничения дублировать через Fluent API, чтобы исключить расхождения между кодом и схемой базы.
👉 @KodBlog
- required string → обязательная инициализация в модели + колонка NOT NULL в БД
- string? → допускает null + колонка с NULL в БД
EF Core использует nullable-аннотации и контекст компилятора, чтобы выводить ограничение целостности схемы. Это напрямую влияет на миграции и поведение трекинга изменений.
Важно: доменную модель нужно задавать явно, а бизнес-ограничения дублировать через Fluent API, чтобы исключить расхождения между кодом и схемой базы.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🍾3