This media is not supported in your browser
VIEW IN TELEGRAM
AviyalWM: портативный и лёгкий оконный менеджер, написанный на C#
Рад сообщить о релизе AviyalWM — простого, лёгкого и портативного динамического тайлингового оконного менеджера для Windows. Краткий список возможностей:
▪️ Рабочие пространства
▪️ Анимации рабочих пространств (горизонтальные и вертикальные)
▪️ Макеты: Dwindle, Stack, Master
▪️ Переключение в плавающий режим
▪️ Закрытие окна в фокусе
▪️ Переключение фокуса
▪️ Конфигурация через JSON
▪️ Горячая перезагрузка
▪️ Запрос состояния через WebSocket и выполнение команд
▪️ Запуск приложений с помощью горячих клавиш
Репозиторий: https://github.com/TheAjaykrishnanR/aviyal
👉 @KodBlog
Рад сообщить о релизе AviyalWM — простого, лёгкого и портативного динамического тайлингового оконного менеджера для Windows. Краткий список возможностей:
Репозиторий: https://github.com/TheAjaykrishnanR/aviyal
Please open Telegram to view this post
VIEW IN TELEGRAM
❤12🔥2
В .NET теперь добавили
Это изменение вчера влито в dotnet main и, судя по всему, будет доступно в .NET 11.
На втором фото есть таблица от Gemini с сравнением Gzip, Brotli и Zstandard по скорости и сжатию.
👉 @KodBlog
DecompressionMethods.Zstandard для автоматической распаковки HTTP-ответов Это изменение вчера влито в dotnet main и, судя по всему, будет доступно в .NET 11.
На втором фото есть таблица от Gemini с сравнением Gzip, Brotli и Zstandard по скорости и сжатию.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👏13🔥2❤1
Когда появился Docker, это была настоящая революция.
Теперь .NET Aspire меняет способ доставки ПО навсегда.
И многие разработчики до сих пор не осознают масштаб этого сдвига.
Docker решил хаос с окружениями
До Docker проблема «у меня работает» была ежедневной:
• Разные версии ОС
• Отсутствующие зависимости
• Сломанные окружения повсюду
Docker решил это, стандартизировав окружения через контейнеры.
Одна команда → одно и то же приложение, одинаковое поведение, везде.
Это действительно было революцией.
Но Docker не решил всё
Он пакует приложения, но связи между сервисами всё ещё настраиваются вручную:
• Всё ещё приходится управлять строками подключения
• Всё ещё самому настраивать наблюдаемость
И распределённые системы остаются сложными.
Здесь .NET Aspire меняет правила игры
Aspire — это слой оркестрации для современных приложений.
Что Aspire делает из коробки:
• Service discovery → никаких хардкодных URL или портов
• Injection конфигураций → базы данных и кеши подключаются автоматически
• Встроенная наблюдаемость → логи, метрики, трассировки, готово с первого дня
• Локальная оркестрация → запускаем всю систему одной командой
• Production-ready деплой → через Docker Compose
• Cloud-ready деплой → Azure или AWS
Вот сам гайд
👉 @KodBlog
Теперь .NET Aspire меняет способ доставки ПО навсегда.
И многие разработчики до сих пор не осознают масштаб этого сдвига.
Docker решил хаос с окружениями
До Docker проблема «у меня работает» была ежедневной:
• Разные версии ОС
• Отсутствующие зависимости
• Сломанные окружения повсюду
Docker решил это, стандартизировав окружения через контейнеры.
Одна команда → одно и то же приложение, одинаковое поведение, везде.
Это действительно было революцией.
Но Docker не решил всё
Он пакует приложения, но связи между сервисами всё ещё настраиваются вручную:
• Всё ещё приходится управлять строками подключения
• Всё ещё самому настраивать наблюдаемость
И распределённые системы остаются сложными.
Здесь .NET Aspire меняет правила игры
Aspire — это слой оркестрации для современных приложений.
Что Aspire делает из коробки:
• Service discovery → никаких хардкодных URL или портов
• Injection конфигураций → базы данных и кеши подключаются автоматически
• Встроенная наблюдаемость → логи, метрики, трассировки, готово с первого дня
• Локальная оркестрация → запускаем всю систему одной командой
• Production-ready деплой → через Docker Compose
• Cloud-ready деплой → Azure или AWS
Вот сам гайд
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9👍6
Вышел новый превью .NET для Microsoft Agent Framework! Обновлённые API, только асинхронные потоки и помощники
Подробнее: https://hubs.li/Q0410DQ-0
👉 @KodBlog
AsAIAgent. Разбираем критические изменения, новые примеры с Durable Agents и ключевые обновления пакетов.Подробнее: https://hubs.li/Q0410DQ-0
Please open Telegram to view this post
VIEW IN TELEGRAM
❤🔥3👍2❤1🔥1
Я очень долго не знал, что в Swagger есть такая фича. Даже не задумывался о ней до недавнего времени.
Совет:
Если ты тоже об этом не знал, это вполне может сэкономить тебе немного времени!
👉 @KodBlog
Совет:
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(c =>
{
// подожди… он ЗАПОМИНАЕТ мой Bearer Token?!
// даже после полного обновления браузера…
c.EnablePersistAuthorization();
// на один клик меньше, на одно лишнее дёрганье мышью меньше
c.EnableTryItOutByDefault();
});
}
Если ты тоже об этом не знал, это вполне может сэкономить тебе немного времени!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍24❤4🤯2
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
ASP.NET Core roadmap for .NET 11 · Issue #64787 · dotnet/aspnetcore
ASP.NET Core planning for .NET 11 is now in progress! This roadmap is currently just a placeholder. We'll update the roadmap with specific planned features as planning progresses. This issue re...
❤4
Перестаньте использовать булевые параметры.
Когда читаешь такой код, приходится останавливаться и думать.
Что значит
Это называется flag argument.
Он заставляет лезть в определение метода, чтобы понять намерение.
Решение: заменяйте размытые булевые значения явными методами.
Вместо
✅ Намерение очевидно.
✅ Язык читается естественно.
✅ Комментарии не нужны.
Код читают намного чаще, чем пишут.
👉 @KodBlog
user.SetStatus(true)Когда читаешь такой код, приходится останавливаться и думать.
Что значит
true? Активен? Подтверждён? Удалён?Это называется flag argument.
Он заставляет лезть в определение метода, чтобы понять намерение.
Решение: заменяйте размытые булевые значения явными методами.
Вместо
SetStatus(true) используйте user.Activate().Код читают намного чаще, чем пишут.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16❤4👎1
Деплой и апгрейд сервисов это всегда риск. В этом посте разбираем, как этот риск снижать.
Диаграмма выше показывает самые частые подходы.
▪️ Multi-Service Deployment
В этой модели мы выкатываем изменения сразу в несколько сервисов одновременно. Реализовать просто. Но из-за того, что все сервисы обновляются в один момент, сложно управлять и тестировать зависимости. И так же сложно безопасно откатиться.
▪️ Blue-Green Deployment
В blue-green деплое есть две одинаковые среды: одна staging (blue), другая production (green). Staging на одну версию впереди прода. Когда тесты в staging пройдены, пользовательский трафик переключается на staging, и staging становится продом. У этой стратегии простой rollback, но держать две одинаковые прод-качества среды может быть дорого.
▪️ Canary Deployment
Canary-деплой обновляет сервисы постепенно, каждый раз только для части пользователей. Это дешевле, чем blue-green, и откатываться тоже удобно. Но так как staging-среды нет, тестировать приходится на проде. Процесс сложнее, потому что нужно мониторить canary и шаг за шагом переводить все больше пользователей со старой версии на новую.
▪️ A/B Test
В A/B тесте разные версии сервисов одновременно крутятся в проде. Каждая версия проводит “эксперимент” на своей доле пользователей. Это дешевый способ проверять новые фичи в проде. При этом нужно жестко контролировать деплой, чтобы какие-то фичи случайно не уехали пользователям.
Твой ход: какую стратегию деплоя ты использовал? Были ли у тебя продовые инциденты из-за деплоя, и почему они случились?
👉 @KodBlog
Диаграмма выше показывает самые частые подходы.
В этой модели мы выкатываем изменения сразу в несколько сервисов одновременно. Реализовать просто. Но из-за того, что все сервисы обновляются в один момент, сложно управлять и тестировать зависимости. И так же сложно безопасно откатиться.
В blue-green деплое есть две одинаковые среды: одна staging (blue), другая production (green). Staging на одну версию впереди прода. Когда тесты в staging пройдены, пользовательский трафик переключается на staging, и staging становится продом. У этой стратегии простой rollback, но держать две одинаковые прод-качества среды может быть дорого.
Canary-деплой обновляет сервисы постепенно, каждый раз только для части пользователей. Это дешевле, чем blue-green, и откатываться тоже удобно. Но так как staging-среды нет, тестировать приходится на проде. Процесс сложнее, потому что нужно мониторить canary и шаг за шагом переводить все больше пользователей со старой версии на новую.
В A/B тесте разные версии сервисов одновременно крутятся в проде. Каждая версия проводит “эксперимент” на своей доле пользователей. Это дешевый способ проверять новые фичи в проде. При этом нужно жестко контролировать деплой, чтобы какие-то фичи случайно не уехали пользователям.
Твой ход: какую стратегию деплоя ты использовал? Были ли у тебя продовые инциденты из-за деплоя, и почему они случились?
Please open Telegram to view this post
VIEW IN TELEGRAM
❤🔥3❤1
Что мне реально нравится в C#
Это не какая-то огромная или супер-впечатляющая фича, но мне заходит вот такое:
Наверное потому что это близко к C и ассемблеру, поэтому такие штуки мне особенно кайфовые :-D
Почти всегда лучше дать компилятору сделать свою работу: он оптимизирует лучше, чем мы руками. Поэтому такие фичи и полезны.
Трюк и самая сложная часть для разработчика это понимать, когда компилятор что-то оптимизирует, а когда нет. И без понимания, как эти штуки устроены, и без чтения release notes ты этого просто не узнаешь.
Раньше было так: переписал LINQ-запрос и почти всегда получал ускорение. Но в .NET 10 это уже не так, потому что теперь он оптимизирует и LINQ тоже.
Вообще на современном .NET 10 и актуальной версии C# стало как никогда просто писать код на C#, который по перформансу близок к C++, а иногда даже обгоняет его. Потому что теперь есть LibraryImport, и он может генерировать MSIL-интероп код без runtime marshalling...
По сути, единственный реально сильный аргумент против C# вместо системных языков сейчас это сборщик мусора.
Если GC в твоем кейсе неприемлем, тогда да, бери системный язык. Но если GC не критичен, и ты не пишешь драйвер или код под embedded, то скорее всего C# тебе ок.
GC это реально единственное, что мешает делать AAA 3D игры на C#.
Но даже это сейчас довольно управляемо благодаря stackalloc, Memory<T>, Span<T> и ref struct.
Пулы памяти тоже теперь есть: можно создавать объекты из пула и переиспользовать RAM, что отлично для GPU-сцен, где хочется минимум мусора и аллокаций.
👉 @KodBlog
Это не какая-то огромная или супер-впечатляющая фича, но мне заходит вот такое:
if (element is { Name: "tileset" })
{
...
}Наверное потому что это близко к C и ассемблеру, поэтому такие штуки мне особенно кайфовые :-D
Почти всегда лучше дать компилятору сделать свою работу: он оптимизирует лучше, чем мы руками. Поэтому такие фичи и полезны.
Трюк и самая сложная часть для разработчика это понимать, когда компилятор что-то оптимизирует, а когда нет. И без понимания, как эти штуки устроены, и без чтения release notes ты этого просто не узнаешь.
Раньше было так: переписал LINQ-запрос и почти всегда получал ускорение. Но в .NET 10 это уже не так, потому что теперь он оптимизирует и LINQ тоже.
Вообще на современном .NET 10 и актуальной версии C# стало как никогда просто писать код на C#, который по перформансу близок к C++, а иногда даже обгоняет его. Потому что теперь есть LibraryImport, и он может генерировать MSIL-интероп код без runtime marshalling...
По сути, единственный реально сильный аргумент против C# вместо системных языков сейчас это сборщик мусора.
Если GC в твоем кейсе неприемлем, тогда да, бери системный язык. Но если GC не критичен, и ты не пишешь драйвер или код под embedded, то скорее всего C# тебе ок.
GC это реально единственное, что мешает делать AAA 3D игры на C#.
Но даже это сейчас довольно управляемо благодаря stackalloc, Memory<T>, Span<T> и ref struct.
Пулы памяти тоже теперь есть: можно создавать объекты из пула и переиспользовать RAM, что отлично для GPU-сцен, где хочется минимум мусора и аллокаций.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤13
This media is not supported in your browser
VIEW IN TELEGRAM
Как можно использовать состояние при работе с MediatR?
Популярный nuget-пакет MediatR по умолчанию не делает хендлеры stateful. То есть при обработке сообщения каждый раз создается новый инстанс хендлера.
Само по себе это не проблема, и я уверен, что это осознанное архитектурное решение... Но бывают ситуации, когда хочется иметь хотя бы какое-то состояние.
Например, что если тебе нужен кэш?
Самое простое решение: вынести ответственность за состояние в отдельный компонент. А дальше пусть dependency injection подсовывает этот компонент в хендлер.
Проблема решена✌️
Полное видео тут
👉 @KodBlog
Популярный nuget-пакет MediatR по умолчанию не делает хендлеры stateful. То есть при обработке сообщения каждый раз создается новый инстанс хендлера.
Само по себе это не проблема, и я уверен, что это осознанное архитектурное решение... Но бывают ситуации, когда хочется иметь хотя бы какое-то состояние.
Например, что если тебе нужен кэш?
Самое простое решение: вынести ответственность за состояние в отдельный компонент. А дальше пусть dependency injection подсовывает этот компонент в хендлер.
Проблема решена
Полное видео тут
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🥴1
Git Tip: юзай команду
👉 @KodBlog
git checkout -, чтобы быстро переключаться на предыдущую ветку, с которой ты только что работал.Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🥴7😁2🔥1😐1
Начиная с Entity Framework 10 у нас появилась поддержка именованных (и нескольких) query filters 🥳
👉 @KodBlog
// Entity Framework 10 will support Named query filters:
modelBuilder.Entity<Blog>()
.HasQueryFilter("SoftDeletionFlter", b => !b.IsDeleted)
.HasQueryFilter("TenantFilter", b => b.TenantId == tenantId);
// this allows us to remove explicit query filters:
var allBlogs = await
context.Blogs.IgnoreQueryFilters(["SoftDeletionFlter"]).ToListAsync();
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
API Gateway как RESTful-микросервис (версия 6.0)
Эта новая версия поддерживает .NET 10.
То есть теперь поддерживаются .NET 8/9/10.
hubs.li/Q041B9js0
👉 @KodBlog
Эта новая версия поддерживает .NET 10.
То есть теперь поддерживаются .NET 8/9/10.
hubs.li/Q041B9js0
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🤔2
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍4🔥3
Если ты все еще сидишь на Swashbuckle в .NET 10, то вот что ты пропустил.
Swashbuckle нормально не обновлялся уже больше года. Поэтому Microsoft убрали его из шаблонов .NET 9+ и сделали свой встроенный вариант.
Замена:
Встроенный, легче, поддерживается и развивается.
UI: Scalar лучше, чем Swagger UI. Быстрее, выглядит приятнее, и темная тема есть из коробки.
Миграция реально на 5 минут: убираешь Swashbuckle, добавляешь
Статья, которая поможет переехать: https://codewithmukesh.com/blog/dotnet-swagger-alternatives-openapi/
👉 @KodBlog
Swashbuckle нормально не обновлялся уже больше года. Поэтому Microsoft убрали его из шаблонов .NET 9+ и сделали свой встроенный вариант.
Замена:
Microsoft.AspNetCore.OpenApiВстроенный, легче, поддерживается и развивается.
UI: Scalar лучше, чем Swagger UI. Быстрее, выглядит приятнее, и темная тема есть из коробки.
Миграция реально на 5 минут: убираешь Swashbuckle, добавляешь
builder.Services.AddOpenApi(), и готово.Статья, которая поможет переехать: https://codewithmukesh.com/blog/dotnet-swagger-alternatives-openapi/
Please open Telegram to view this post
VIEW IN TELEGRAM
👍20🔥4👎2
Асинхронное общение делает интеграционные тесты болью.
Ты шлёшь событие из одного модуля и... ждёшь?
Если опираться на
Не жди. Опрашивай.
Я использую паттерн “retry assertion” для проверки логики между модулями в модульных монолитах:
▪️ Выполняем команду (модуль A)
▪️ Поллим запрос (модуль B), пока
▪️ Делаем ассерты по результату
Так флейковый, медленный тест превращается в детерминированный и быстрый.
Почитай про эту стратегию в статье
👉 @KodBlog
Ты шлёшь событие из одного модуля и... ждёшь?
Если опираться на
Thread.sleep, твой CI/CD быстро начнёт страдать.Не жди. Опрашивай.
Я использую паттерн “retry assertion” для проверки логики между модулями в модульных монолитах:
Result != nullТак флейковый, медленный тест превращается в детерминированный и быстрый.
Почитай про эту стратегию в статье
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤5
Статические абстрактные члены интерфейсов появились в C# 11. Основной мотивацией для них является поддержка обобщённой математики. Но они могут быть полезны и в других сценариях. Например, упростить код регистрации и использования типов разделов пользовательской конфигурации.
Например, вы хотите настроить клиент API в appSettings.json:
Хорошей практикой является связать раздел с отдельным типом:
Упростим регистрацию через статические члены интерфейсов. Сначала определим интерфейс:
Все реализации этого интерфейса должны иметь статическое свойство SectionName:
Добавим методы расширения для регистрации секций конфигурации:
Теперь можно регистрировать различные секции конфигурации так:
👉 @KodBlog
Например, вы хотите настроить клиент API в appSettings.json:
{
…
"GoogleAPI": {
"ApiKey": "…",
"OrganizationId": "…",
…
}
}Хорошей практикой является связать раздел с отдельным типом:
public class GoogleOptions {
public string? ApiKey { get; init; }
public string? OrganizationId { get; init; }
…
}
…
// добавляем в Program.cs
builder.Configuration
.Configure<GoogleOptions>(
builder.Configuration.GetSection("GoogleAPI"));
…
// внедряем через DI
public class GoogleClient(
IOptions<GoogleOptions> options) {
// …
}Упростим регистрацию через статические члены интерфейсов. Сначала определим интерфейс:
public interface IConfigOptions
{
static abstract string SectionName { get; }
}
Все реализации этого интерфейса должны иметь статическое свойство SectionName:
public class GoogleOptions: IConfigOptions {
public static string SectionName => "GoogleAPI";
// остальные члены
}Добавим методы расширения для регистрации секций конфигурации:
public static class OptionsExtensions {
public static IHostApplicationBuilder
Configure<TOptions>(
this IHostApplicationBuilder builder)
where TOptions : class, IConfigOptions
{
var sect = builder.Configuration
.GetSection(TOptions.SectionName);
builder.Services.Configure<TOptions>(sect);
return builder;
}
}Теперь можно регистрировать различные секции конфигурации так:
builder.Configure<GoogleOptions>()
.Configure<GitHubOptions>()
.Configure<WeatherOptions>()
Please open Telegram to view this post
VIEW IN TELEGRAM
❤11🥴5
Все еще держишь бизнес-логику в сервисах Application-слоя?
Это обычно знак, что доменная модель почти ничего не делает.
Если твои entity выглядят как голые DTO с полями, то у тебя анемичная доменная модель.
Как рефакторнуться в сторону behavior-driven дизайна:
✅ Проталкивай бизнес-логику в домен
✅ Делай методы, которые жестко держат инварианты
✅ Делай так, чтобы невалидные состояния были невозможны в принципе
✅ Пересмотри границы сервисов
В итоге код проще сопровождать, тестировать и расширять.
Пошаговый разбор рефакторинга
👉 @KodBlog
Это обычно знак, что доменная модель почти ничего не делает.
Если твои entity выглядят как голые DTO с полями, то у тебя анемичная доменная модель.
Как рефакторнуться в сторону behavior-driven дизайна:
В итоге код проще сопровождать, тестировать и расширять.
Пошаговый разбор рефакторинга
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2