18377
По всем вопросам- @haarrp C# - обучающий канал Senior C# разработчика. @ai_machinelearning_big_data - Machine learning @itchannels_telegram - 🔥лучшие ит-каналы @csharp_ci - C# академия @pythonlbooks- книги📚 Реестр РКН: https://clck.ru/3Fk3kb
🔵Ozon Tech приглашает на Community .NET Meetup
24 марта (вторник) в Москве (Лофт Casa Picassa) и онлайн.
В программе три доклада, много кейсов и камерная дискуссия без записи. В фокусе primitive obsession, нагрузка с Load Shedding и Escape Analysis в JIT.
За подробной программой и регистрацией — сюда ⬅️
C# records - идеальный способ создавать value objects.
Почему это важно?
В DDD value object должен:
- быть неизменяемым (immutable)
- сравниваться по значениям, а не по ссылке
Именно это records дают из коробки.
Что получаем:
- неизменяемость через init
- структурное сравнение (Value Equality)
- короткий и чистый синтаксис
- deconstruction
- pattern matching
Пример:
public class Booking
{
public Address Address { get; init; }
public DateRange Period { get; init; }
}
public record Address(
string Street,
string City,
string State,
string Country,
string ZipCode);
В .NET 8 появился простой способ сделать HttpClient устойчивым к сбоям — буквально одной строкой.
Microsoft добавила библиотеку Microsoft.Extensions.Http.Resilience, в которой уже есть готовые pipeline’ы для обработки ошибок при HTTP-запросах.
Что это даёт из коробки:
- Retry при временных сбоях
- Timeout
- Circuit Breaker
- Rate limiting
- Защиту от перегрузки
Подключается максимально просто:
Читать полностью…
services.AddHttpClient<GitHubService>(static httpClient =>
{
httpClient.BaseAddress = new Uri("https://api.github.com/");
})
.AddStandardResilienceHandler();
🖥 Разделяйте код с помощью Domain Events
Без событий сервисы быстро превращаются в «комбайн»:
— бизнес-логика
— отправка email
— аналитика
— интеграции
— и всё в одном методе
Каждая новая функция добавляет прямые зависимости.
Метод растёт. Связанность увеличивается. Поддержка усложняется.
С Domain Events подход меняется:
Вы выполняете бизнес-действие и просто публикуете событие.
await _domainEventsDispatcher.DispatchAsync(
[new UserRegisteredDomainEvent(user.Id, user.Email)]
);
UserService.
🖥 Асинхронщина ломает интеграционные тесты? Есть простой паттерн
Проблема:
Вы отправляете событие в одном модуле…
И начинаете ждать.
Если используете Thread.Sleep —
готовьтесь к:
- медленным тестам
- flaky-падениям
- ненависти от CI/CD
Решение — Retry Assertion (Polling)
Как работает паттерн:
1. Выполняем команду (Module A)
2. Периодически опрашиваем состояние (Module B)
3. Ждём, пока результат появится
4. Делаем assert
Схема:
- Execute Command (Module A)
- Poll Query (Module B) until result != null
- Assert
Почему это лучше:
- Нет случайных падений
- Тесты работают быстрее
- Полностью детерминированное поведение
- Отлично подходит для async, событий и modular monolith
Главная идея:
Не жди фиксированное время — жди состояние.
Такой подход превращает нестабильные интеграционные тесты в надёжные и быстрые.
⚡️ Async-коммуникация ломает интеграционные тесты.
Вы отправляете событие в одном модуле… и что дальше? Ждать?
Если используете Thread.Sleep — готовьтесь к:
- медленным тестам
- flaky-поведению
- падениям в CI/CD
Решение — не ждать. Опрос (Polling).
Я использую паттерн Retry Assertion для тестирования асинхронного взаимодействия между модулями:
Как это работает:
1. Выполняем команду (Модуль A)
2. Периодически выполняем запрос (Модуль B)
3. Ждём, пока результат появится
4. Делаем assert
Пример:
Читать полностью…
var userId = await Sender.Send(new RegisterUserCommand(...));
var result = await Poller.WaitAsync(
TimeSpan.FromSeconds(15),
async () =>
{
return await Sender.Send(new GetCustomerQuery(userId));
});
result.Should().NotBeNull();
result.IsSuccess.Should().BeTrue();
✔️ Unity обещает создание игр через текстовые команды.
CEO Unity Мэтт Бромберг определил "AI-driven authoring" как приоритетное направление развития компании на 2026 год. Компания готовит инструмент, который сможет собирать казуальные игры с нуля, используя только естественный язык.
Бета-версию Unity AI покажут на GDC в марте 2026 года. Технология будет работать нативно внутри платформы, Unity возьмет топовые внешние модели и доучит их понимать контекст движка.
В компании уверены, что такой подход даст результат лучше, чем попытки заставить универсальные LLM писать сложный игровой код. Цель - окончательная демократизация геймдева, порог входа в который, похоже, скоро исчезнет совсем.
wccftech.com
🔥На Stepik вышел курс: Linux: полный апгрейд твоих скиллов
Хочешь реально понимать, что происходит под капотом твоей системы, а не просто кликать по GUI?
Без глубокого знания базы ты не инженер - ты просто пользователь.
🔹 В курсе ты:
- Освоишь bash, grep, sed, awk - инструменты, которыми живут админы.
- Разберёшь права, процессы, сеть, файловую систему и научишься чинить всё, что падает.
- Настроишь SSH, firewall, systemd, crontab, демоны и автозапуск.
- Научишься анализировать логи, следить за нагрузкой, и не паниковать при 100% CPU.
💡 Формат: пошаговое объяснение базы и разбор важных практик по работе с Linux.
🎯 После курса ты: будешь чувствовать Linux как родную среду и забудешь, что такое “permission denied”.
🚀 24 часа действует скидка 30%
👉 Учиться со скидкой
⚡️ КАК СДЕЛАТЬ ИНТЕГРАЦИИ БЕЗ ПОТЕРИ ДАННЫХ
Вы регистрируете пользователя и сразу вызываете внешние сервисы:
- сохраняете пользователя в БД
- отправляете welcome-email
- публикуете событие в event bus
public async Task RegisterUserAsync(User user, CancellationToken token)
{
_userRepository.Insert(user);
await _unitOfWork.SaveChangesAsync(token);
await _emailService.SendWelcomeEmailAsync(user, token);
await _eventBus.PublishAsync(new UserRegisteredEvent(user.Id), token);
}
public async Task RegisterUserAsync(User user, CancellationToken token)
{
_userRepository.Insert(user);
_outbox.Insert(new UserRegisteredEvent(user.Id));
await _unitOfWork.SaveChangesAsync(token);
}
⚡ Лучший конфиг HttpClient тот, который ты не повторяешь в каждом сервисе.
В .NET всё настраивается один раз через IHttpClientFactory (и Aspire, если используешь его):
• Service discovery для service-to-service вызовов
• Встроенная устойчивость к сбоям (retry, handling transient errors)
После этого ты просто инжектишь клиент и пишешь бизнес-логику — без ручной магии с сокетами, таймаутами и DNS.
Чистый код. Меньше багов. Больше фокуса на логике.
Полный разбор
Если вы думаете, что EF Core «медленный» в 2026 — вы просто живёте в прошлом.
Одна из мощных современных фич — bulk-операции, в том числе массовое удаление.
Теперь можно удалить любое количество записей одним запросом к базе.
Пример: e-commerce платформа хочет удалить все корзины, созданные более года назад. Раньше это выглядело так: загрузили сущности в память, RemoveRange, SaveChanges — лишние аллокации, трафик и нагрузка.
Теперь достаточно:
context.Carts
.Where(o => o.CreatedOn < DateTime.Now.AddYears(-1))
.ExecuteDelete();
🟥 Утечки данных в .NET-приложениях чаще происходят не из-за хакеров, а из-за неверной работы с ключами, конфигурациями и базовой криптографией. Ошибки на уровне кода быстро превращаются в инциденты.
На открытом уроке разберём практическое применение System.Security.Cryptography: AES, RSA, хеширование и цифровые подписи. Поговорим о безопасном хранении и передаче секретов, управлении ключами и принципе наименьших привилегий.
❗️ Вы системно разберёте уязвимости OWASP Top-10 для .NET: инъекции, небезопасную десериализацию, XSS, CSRF — и способы их нейтрализации на уровне кода и архитектуры. Отдельно обсудим шифрование данных в БД, защиту строк подключения и безопасное логирование без утечек токенов.
🟥Встречаемся 10 февраля в 20:00 МСК в преддверии старта курса «C# Developer. Professional».
Зарегистрируйтесь, чтобы не пропустить: https://tglink.io/73e7493a7d6ff1?erid=2W5zFGXFxba
#реклама
О рекламодателе
⚡️ Модульный монолит хорош ровно настолько, насколько хороши его границы.
Если Module A может “по-тихому” лезть в базу Module B - у тебя не модули.
У тебя хаос, просто внутри одного репозитория.
Самое сложное в модульной архитектуре - не “разбить на папки”, а решить, что модуль вообще имеет право показывать наружу.
Моё правило для Public API:
1) Начинай с нуля
Считай, что любой класс должен быть приватным по умолчанию.
2) Открывай только по необходимости
Доступ даётся не “на будущее”, а только если другой модуль реально просит функциональность.
3) Экспортируй возможности, а не данные
API должно отражать сценарии (use-cases), а не “вот тебе таблица/репозиторий/DTO”.
И главное - просто договориться недостаточно.
Границы нужно технически запрещать нарушать: модификаторы, сборки, internal, анализаторы, тесты на зависимости.
🏗️ Пытаться вытаскивать микросервисы из “спагетти-монолита” - почти всегда плохая идея.
Вместо красивой архитектуры ты получишь распределённую кашу, ещё больше зависимостей, ошибок и боли при поддержке.
Самый безопасный путь миграции - паттерн Strangler Fig:
выносить функциональность по кускам, постепенно “замещая” монолит.
Но есть важное условие:
сначала нужно привести систему к Modular Monolith.
То есть:
- чётко выделить границы модулей
- изолировать данные
- оставить только чистые публичные API для общения между модулями
И только после этого выбирать, какой модуль выносить первым.
Как выбрать правильного кандидата на первый микросервис?
Ищи 4 “зелёных флага”:
1) Low Coupling - минимум зависимостей от других модулей
2) High Cohesion - логика внутри модуля максимально связная и цельная
3) Distinct Domain - чёткая бизнес-область (например, “платежи” или “инвойсинг”)
4) Scale Needs - модулю нужны другие ресурсы/масштабирование, чем остальной системе
Если модуль соответствует этим критериям - его можно вынести относительно безопасно,
не превращая архитектуру в распределённый хаос.
⚙️ Вы настраиваете ASP.NET Core «по наитию» и тратите время на поиск, почему приложение ведет себя по-разному в продакшене и локально?
📆 29 января в 20:00 OTUS проводит открытый урок «Конфигурирование приложения ASP.NET Core» в преддверии старта курса «C# ASP.NET Core разработчик».
На занятии разберем, как выстроить прозрачную и управляемую систему настроек: appsettings.json, провайдеры конфигурации, приоритет применения конфигураций, настройки специфичные для среды и шаблон Options для работы с настройками. Вы поймете, как проектировать конфигурации так, чтобы приложения были стабильными и предсказуемыми.
❗️Урок будет полезен разработчикам ASP.NET Core начального и среднего уровня, которые хотят систематизировать знания и работать по индустриальным стандартам.
➡️ Регистрируйтесь на бесплатный урок: https://tglink.io/f0de1b0a6e87?erid=2W5zFH3PFGL
🎁 Все участники открытого урока получат скидку на обучение.
#реклама
О рекламодателе
Есть более эффективный способ делать массовые обновления в EF Core.
Начиная с EF Core 7 появился метод ExecuteUpdate, который позволяет обновлять записи напрямую на стороне базы данных.
Вместо того чтобы загружать объекты в память, изменять их в цикле и затем вызывать SaveChanges, можно выполнить обновление одним SQL-запросом.
Это значительно быстрее и снижает нагрузку на приложение, особенно при работе с большими таблицами.
Однако есть важное условие: нужно заранее знать, какое поле вы обновляете и какое значение ему присваиваете, поскольку операция формируется как прямой SQL-update.
Такой подход отлично подходит для массовых операций и оптимизации производительности в EF Core.
Как меняется роль разработчика в 2026 году?
AI стремительно меняет то, как создаются продукты и пишется код. Всё чаще обсуждают не только новые инструменты, но и более фундаментальный вопрос: какой будет роль разработчика в ближайшие годы.
24 марта Mindbox проводит открытые дебаты, где эксперты по AI из SberDevices и Itsy обсудят, куда движутся технологии и как это влияет на работу инженеров.
Что будет на встрече:
— разговор о том, как на AI смотрят с двух сторон: со стороны бизнеса и со стороны разработки
— возможность задать свои вопросы и обсудить их прямо во время дебатов
— реальные идеи и практики, которые уже используют команды
Если вам интересно, как меняется индустрия и какие навыки будут важны дальше — подключайтесь и приносите свои вопросы.
Канал Сергея Маркова
Канал Никиты Архипова
📅 24 марта
⏰ 19:00–20:30 мск
📍 Онлайн, бесплатно
👉 Зарегистрироваться
Реклама. ООО «Майндбокс», ИНН: 7713688880, erid: 2W5zFGn2zp1
⚡️ Exceptions - это для действительно исключительных ситуаций.
Но в реальном приложении они все равно будут случаться, и их нужно обрабатывать предсказуемо.
Самый удобный способ в ASP.NET Core - сделать глобальный обработчик через middleware:
- перехватываем любые необработанные исключения
- логируем ошибку
- возвращаем клиенту единый JSON-ответ (ProblemDetails) с 500
Пример:
Читать полностью…
public class ExceptionHandlingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ExceptionHandlingMiddleware> _logger;
public ExceptionHandlingMiddleware(
RequestDelegate next,
ILogger<ExceptionHandlingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception exception)
{
_logger.LogError(
exception, "Exception occurred: {Message}", exception.Message);
var problemDetails = new ProblemDetails
{
Status = StatusCodes.Status500InternalServerError,
Title = "Server Error"
};
context.Response.StatusCode =
StatusCodes.Status500InternalServerError;
await context.Response.WriteAsJsonAsync(problemDetails);
}
}
}
💡 Soft delete в EF Core без лишней логики в сервисах
Удалять данные физически — не всегда хорошая идея.
Логи, аудит, восстановление, аналитика — всё это требует soft delete.
Вот удобный способ реализовать его через EF Core interceptor.
Что делает перехватчик:
- Проверяет ChangeTracker на сущности с интерфейсом ISoftDeletable
- Если состояние сущности — Deleted
- Меняет его на Modified
- Устанавливает:
- IsDeleted = true
- DeletedOnUtc = DateTime.UtcNow
В итоге:
Вы вызываете обычный:
context.Remove(entity);
Динамическая строка подключения в EF Core - когда и зачем это нужно
Факт
В EF Core можно задать connection string динамически при регистрации DbContext. Для этого используется делегат, который выполняется в момент получения контекста из DI.
Как это работает
При регистрации DbContext вы передаёте функцию, которая получает IServiceProvider.
Внутри неё можно:
- получить любой сервис
- определить текущего пользователя или tenant
- выбрать нужную базу данных
- и только после этого установить строку подключения
Пример
builder.Services.AddDbContext<OrdersDbContext>((sp, o) =>
{
var tenantProvider = sp.GetRequiredService<TenantProvider>();
var connectionString = tenantProvider.GetConnectionString();
o.UseSqlServer(connectionString);
});
⚡️ КАСТОМИЗАЦИЯ ИСТОРИИ МИГРАЦИЙ В ENTITY FRAMEWORK
В Entity Framework можно гибко настроить таблицу истории миграций и это полезно в реальных проектах.
По умолчанию EF создаёт таблицу __EFMigrationsHistory в стандартной схеме (dbo).
Но часто требуется:
- вынести её в отдельную схему
- изменить имя таблицы
- разделить миграции между модулями
- привести структуру БД к корпоративным стандартам
Это можно сделать прямо при настройке DbContext через метод MigrationsHistoryTable.
Читать полностью…
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(
connectionString,
sqlOptions =>
{
sqlOptions.MigrationsHistoryTable(
tableName: "MigrationHistory",
schema: "infrastructure"
);
}));
// Теперь EF будет хранить историю миграций в:
// infrastructure.MigrationHistory
⚡️ Guard Clauses в .NET: проверяй ошибки одной строкой
Хочешь упростить код и избавиться от вложенных if? Используй guard clauses — быстрые проверки входных данных в самом начале метода.
Вместо длинной логики и вложенности ты сразу останавливаешь выполнение, если данные некорректны. Код становится чище, короче и легче для чтения.
В новых версиях .NET появилось много встроенных проверок:
.NET 6:
- ArgumentNullException.ThrowIfNull
.NET 7:
- ArgumentException.ThrowIfNullOrEmpty
.NET 8:
- ThrowIfNullOrWhiteSpace
- ThrowIfNullOrEmpty (для коллекций)
- ThrowIfZero
- ThrowIfNegative
- ThrowIfGreaterThan
Когда это особенно полезно:
- в сервисах и API для валидации входных данных
- в доменных моделях — чтобы не допустить невалидного состояния
- в конструкторах и фабриках
Главная мысль:
Guard clauses — это не про «больше проверок»,
а про ранний отказ и чистую архитектуру.
Читать полностью…
public class Order
{
public Order(string customerName, decimal amount)
{
ArgumentException.ThrowIfNullOrWhiteSpace(customerName);
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(amount);
CustomerName = customerName;
Amount = amount;
}
public string CustomerName { get; }
public decimal Amount { get; }
}
🚀 Научитесь создавать AI-проекты и зарабатывать на них
🦾🦾 Сегодня ценится не умение «пользоваться ChatGPT», а навык проектировать и запускать полноценные AI-решения под реальные задачи бизнеса
🤖 Университет искусственного интеллекта - один из самых крупных образовательных проектов в сфере AI:
7 лет на рынке, более 11 000 студентов, практические программы и стажировки в реальных компаниях
🔥🔥 Сейчас открыт доступ к презентации программы GPT Engineer - обучения, где показывают путь от базы до разработки AI-приложений и сервисов
Что вы узнаете из презентации:
🔹 Программа курса по занятиям
🔹 Необходимый уровень для поступления
🔹 Тарифы и цены
🔹 Описание формата практики на стажировках
🔹 Обзор процесса трудоустройства
🔹 Разбор программы поддержки студентов
👉 Если планируете развиваться в сфере искусственного интеллекта или хотите перейти в новую востребованную профессию - обязательно посмотрите презентацию
👨💻 Ручная сборка, деплой по инструкции в Confluence и ночные правки на сервере — частая реальность ASP.NET-проектов. Пока система доставки не автоматизирована, скорость разработки и стабильность всегда под угрозой.
На открытом уроке разберём, как выстроить рабочий pipeline от коммита до деплоя. Покажем типовую цепочку: сборка, тесты, упаковка в Docker-образ, публикация в реестр и автоматическое развертывание.
❗️ Вы увидите CI/CD не как абстрактную DevOps-теорию, а как воспроизводимый процесс, который можно применить в собственном проекте. Это фундамент для перехода к микросервисам и контейнерной инфраструктуре без лишней сложности.
🗓 Встречаемся 11 февраля в 20:00 МСК в преддверии старта курса «C# ASP.NET Core-разработчик».
➡️ Регистрация открыта: https://tglink.io/3e020aa35caaf6?erid=2W5zFGkbWek
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
#реклама
О рекламодателе
🔥 Полезная подборка каналов только код, практика и самые передовые инструменты, которые используют разработчики прямо сейчас.👇
🖥 C#: t.me/csharp_1001_notes
🖥 ИИ: t.me/ai_machinelearning_big_data
🖥 Python: t.me/pythonl
🖥 Linux: t.me/linuxacademiya
🖥 C++ t.me/cpluspluc
🖥 Docker: t.me/DevopsDocker
🖥 Хакинг: t.me/linuxkalii
🖥 Devops: t.me/DevOPSitsec
👣 Golang: t.me/Golang_google
🖥 Аналитика: t.me/data_analysis_ml
🖥 Javascript: t.me/javascriptv
🖥 Java: t.me/javatg
🖥 Базы данных: t.me/sqlhub
👣 Rust: t.me/rust_code
🤖 Технологии: t.me/vistehno
💰 Экономика и инвестиции в ИИ t.me/financeStable
💼 Актуальные вакансии: t.me/addlist/_zyy_jQ_QUsyM2Vi
🖥 Chatgpt бот в тг: t.me/Chatgpturbobot
📚 Бесплатные ит-книги: /channel/addlist/HwywK4fErd8wYzQy
🖥Подборка по Golang: /channel/addlist/MUtJEeJSxeY2YTFi
⚡️ Лучшие ИИ ресурсы: /channel/addlist/2Ls-snqEeytkMDgy
Самое лучшее в этом: ты учишься даже тогда, когда “нет времени, просто потому что читаешь правильную ленту.
Если вы не используете OpenTelemetry, вы буквально летите вслепую в продакшене.
И хорошая новость — вам не нужно переписывать код, чтобы получить “рентген-зрение” для своих сервисов.
Достаточно подключить правильные пакеты авто-инструментирования.
Вот базовый стартовый набор для .NET:
- AspNetCore — автоматически трейсит все входящие HTTP-запросы
- HttpClient — показывает тайминги и статусы всех исходящих API-вызовов
- EF Core — логирует реальные SQL-запросы и их длительность
- Npgsql — добавляет глубокий трейсинг для PostgreSQL
- StackExchange.Redis — помогает увидеть cache hits, misses и скачки латентности
После установки вы начинаете видеть полный жизненный цикл запроса через все микросервисы — от входящего HTTP до базы, кэша и внешних API.
Это уже не “логи и надежда”.
Это наблюдаемость продакшен-уровня.
Я разобрал, как всё это подключить к Grafana или Jaeger и получить полноценную визуализацию трейсов.
Полный гайд по настройке:
https://milanjovanovic.tech/blog/introduction-to-distributed-tracing-with-opentelemetry-in-dotnet?utm_source=X&utm_medium=social&utm_campaign=19.01.2026
⚡️ 10 причин перейти на .NET 10 (чтобы это одобрил руководитель)
.NET 10 и C# 14 вышли 11 ноября 2025. Ниже - 10 причин, почему апгрейд реально стоит запланировать.
1) LTS-релиз
- .NET 10 - Long-Term Support, поддержка до 14 ноября 2028
- поддержка .NET 8 заканчивается 10 ноября 2026 → лучше не тянуть
2) Быстрее ASP.NET Core
- до +15% RPS по сравнению с .NET 8
- до -93% потребления памяти → меньше нагрузка и дешевле инфраструктура
3) Общий прирост производительности .NET
- сотни улучшений “из коробки” просто после апгрейда проекта
4) File-Based Apps (один .cs файл)
- можно сделать один файл *.cs и запускать напрямую
- удобно для CLI, автоматизации и утилит без создания проекта
5) Server-Sent Events (SSE)
- лёгкий способ стримить данные на клиента
- идеален для real-time обновлений без сложности WebSocket
6) Extension Members в C# 14
- более удобный синтаксис расширений
- можно расширять свойства и static members
7) Minimal APIs: Validation + JSON Patch
- встроенная валидация для Minimal APIs
- JSON Patch доступен из коробки
8) EF 10: LeftJoin / RightJoin в LINQ
- наконец-то нормальные LeftJoin/RightJoin
- запросы становятся проще и читаемее
9) EF 10: Named Query Filters
- можно заводить несколько фильтров на одну сущность
- включать/выключать их независимо
10) Улучшения Blazor
- Hot Reload для Blazor WASM и .NET on WASM
- профилирование производительности + диагностические счётчики
Источник/подробности:
antondevtips.com/draft/10-reasons-to-upgrade-to-dotnet-10/
Перестань падать из-за одного внешнего API - добавь Fallback в .NET через Resilience Pipeline 🛡️
Вместо того чтобы приложение валилось, когда GitHub (или любой сервис) не отвечает, ты можешь вернуть безопасный дефолт и продолжить работу.
Идея простая:
Ты добавляешь fallback-стратегию в pipeline, и если запрос падает — система вернёт запасной результат.
Что происходит в примере:
— В DI регистрируется Resilience Pipeline
— Добавляется FallbackStrategy
— Если вызов неудачный, возвращается GitHubUser.Empty вместо исключения
Дальше в endpoint ты не вызываешь HttpClient напрямую — ты запускаешь его через pipeline:
pipeline.ExecuteAsync(...)
И если API:
❌ упало
❌ вернуло ошибку
❌ словило таймаут
Пользователь не увидит 500. Он получит контролируемый ответ.
Это особенно важно для:
- внешних API
- микросервисов
- нестабильных сетей
- интеграций с SaaS
Fallback — это не про «скрыть ошибку».
Это про graceful degradation, когда система продолжает жить даже при частичных сбоях.
Надёжность — это архитектура, а не try/catch в каждом методе.
#dotnet #backend #architecture
🖥 Как обычные Linux-пользователи смотрят файлы:
$ ls -a
$ echo */ *. *
- */ покажет папки
- * покажет обычные файлы
- .* покажет скрытые файлы