C# (C Sharp) programming
18.5K subscribers
810 photos
41 videos
8 files
702 links
По всем вопросам- @haarrp

C# - обучающий канал Senior C# разработчика.

@ai_machinelearning_big_data - Machine learning

@itchannels_telegram - 🔥лучшие ит-каналы

@csharp_ci - C# академия

@pythonlbooks- книги📚

Реестр РКН: https://clck.ru/3Fk3kb
Download Telegram
⚙️ 3 способа определить Middleware в ASP.NET Core

Middleware - это компоненты, которые добавляют дополнительную логику до или после обработки HTTP-запроса.

С их помощью можно реализовать аутентификацию, логирование, кеширование, обработку ошибок и другие сквозные функции приложения.

🔧 В ASP.NET Core уже встроено множество middleware (Static Files, Routing, Authentication и др.),
но вы можете создавать и свои собственные.

Вот три основных способа это сделать:
- Request Delegates - определяете логику прямо в app.Use(...)
- Convention-based - создаёте класс с методом Invoke или InvokeAsync
- Factory-based - используете фабрику с внедрением зависимостей (DI)

🧠 Подробный разбор и примеры кода - в статье


#dotnet #aspnetcore #backend #middleware #csharp
Media is too big
VIEW IN TELEGRAM
🖥 Шардирование в базах данных: обзор концепции

Шардирование или шардинг - это принцип проектирования базы данных, при котором данные разбиваются на части и размещаются на разных шардах.

Интерактивный лонгрид по шардированию баз данных.

В нем разобрано все - от принципов работы шардов и причин, зачем это вообще нужно, до тонкостей проектирования и типовых ошибок.
Каждый раздел сопровождается интерактивными диаграммами, с которыми можно экспериментировать прямо в статье.

Отличный материал, чтобы прокачать понимание распределённых БД на выходных 💡

Статья: https://planetscale.com/blog/database-sharding

Видео: https://www.youtube.com/watch?v=R2ML2jLs3_U
Please open Telegram to view this post
VIEW IN TELEGRAM
Ubuntu Unity остался без разработчиков и новых релизов

Проект Ubuntu Unity не может сформировать новый релиз 25.10 из-за отсутствия разработчиков, способных исправить критические проблемы с работой пользовательского окружения Unity, возникающие при использовании пакетной базы Ubuntu 25.10. Пользователям Ubuntu Unity не рекомендуется обновлять свои системы до ветки 25.10 или пытаться установить пакеты с Unity поверх других редакций Ubuntu 25.10, так как это может нарушить работоспособность системы.

https://opennet.ru/64125/
Но я уже и сам догадался
🔐 Что такое RBAC (Role-Based Access Control)

RBAC - это модель контроля доступа на основе ролей. Она помогает управлять авторизацией в приложениях просто и масштабируемо.

Как работает RBAC:
- Ролям назначаются определённые разрешения (permissions);
- Пользователям присваиваются роли, и через них - разрешения;
- Разрешения определяют, что пользователь может или не может делать.

📌 Преимущество RBAC в том, что можно централизованно управлять правами доступа.
Но часто роли оказываются слишком «грубыми» — не хватает точности для отдельных политик безопасности.

Здесь на помощь приходят permissions — разрешения на конкретные действия.
Если нужно дать доступ другой роли, достаточно просто добавить разрешение к роли, не переписывая всю систему авторизации.

💡 Простая концепция, но невероятно мощная в управлении доступом.

Подробнее
⚡️ Хорошая архитектура ничего не стоит, если её легко сломать.

Есть три способа заставить команду придерживаться дизайна:
- компилятор и статический анализ
- архитектурные тесты
- код-ревью

Компилятор - лучший друг. Он мгновенно ловит ошибки и не даст собрать проект, если что-то нарушено.
Но как использовать это для защиты архитектуры?

В .NET можно скрывать типы через internal и разделять код на проекты, чтобы изолировать модули.
Проблема - при масштабировании проектов становится слишком много.

Статический анализ полезен, но писать свои Roslyn-правила - удовольствие на любителя.

Поэтому я делаю ставку на архитектурные тесты.
Они позволяют задать правила в виде автотестов и контролировать зависимости между модулями, особенно в модульном монолите: каждый модуль видит только публичный API других модулей.

Ну и код-ревью - финальный фильтр. Кто-то должен глазами подтвердить, что всё ок.

Что выбрать?
Я больше всего полагаюсь на компилятор и архитектурные тесты - это помогает ловить проблемы максимально рано.

Хотите больше? Посмотрите пример использования архитектурных тестов и подход shift left.
Please open Telegram to view this post
VIEW IN TELEGRAM
Как вы организуете свои Vertical Slices?

Есть два подхода, и оба встречаются в живых проектах:

1) Один файл → статический класс + вложенные типы
- Request / Response внутри
- Handler внутри
- Validator внутри
- Endpoint там же
- максимум локальности и контекста
- удобно читать как "одна фича – один файл"

2) Каждый тип в отдельном файле
- Request.cs
- Response.cs
- Handler.cs
- Validator.cs
- Endpoint.cs
- привычно для больших команд
- проще искать по имени файла
- лучше работает при очень длинных обработчиках

По сути:

- маленькие обработчики → один файл с вложенными типами
- большие и долгоживущие фичи → отдельные файлы + папка

Главный принцип Vertical Slice — держать фичу целостной.
Не заставлять прыгать по всему solution ради одной команды.

А вы как делаете: всё в одном файле или дробите?```
⚡️ Что выведет код?


using System;

namespace MyApplication {
class Program {
static void Main(string[] args) {
int a = 10, b = 20;
Console.WriteLine("{0}+{1}", a, b);
}
}
}


- Объясните, почему вывод именно такой.
- Измените одну строку так, чтобы программа печатала сумму чисел в виде 10+20=30.

1) Ответ

Программа выведет:

10+20

2) Почему так

- В Console.WriteLine("{0}+{1}", a, b); используется композитное форматирование (аналог string.Format).

- Подстановки {0} и {1} заменяются на значения соответствующих аргументов — a и b.

- Знак + находится внутри строкового литерала, значит это просто символ, а не операция сложения.

- Поэтому получается «подставь a, затем символ +, затем b» → 10+20.

Частая ошибка: думать, что + выполнит сложение. Нет — внутри кавычек это обычный текст.
На Stepik вышел курс - Linux: полный апгрейд твоих скиллов

Хочешь реально понимать, что происходит под капотом твоей системы, а не просто кликать по GUI?

Без глубокого знания базы ты не инженер - ты просто пользователь.

🔹 В курсе ты:

- Освоишь bash, grep, sed, awk - инструменты, которыми живут админы.
- Разберёшь права, процессы, сеть, файловую систему и научишься чинить всё, что падает.
- Настроишь SSH, firewall, systemd, crontab, демоны и автозапуск.
- Научишься анализировать логи, следить за нагрузкой, и не паниковать при 100% CPU.

💡 Формат: пошаговое объяснение базы и разбор важных практик по работе с Linux.

🎯 После курса ты: будешь чувствовать Linux как родную среду и забудешь, что такое “permission denied”.

🚀 Сейчас действуют скидка целых - 30%, не упусти реальный шанс прокачаться.

👉 Пройти курс на Stepik
🔥 EF Core 10 принес нормальные JOIN'ы в LINQ

Больше не нужно вспоминать, как извращаться с GroupJoin + DefaultIfEmpty, чтобы сделать обычный LEFT JOIN.
Теперь есть прямые методы:

LeftJoin
RightJoin

И они делают ровно то, что ты пишешь:
«Оставь все из левой таблицы и подтяни правые записи, если есть совпадения».

Плюсы
- Читаемость выше
- Код короче и очевиднее
- Транслируется в тот же SQL, что и раньше, но без боли

Примерно так LINQ наконец становится ближе к привычному SQL-пониманию разработчика: пишешь join — получаешь join, без магии и обходных путей.

Подробнее про LeftJoin и RightJoin в EF Core 10


#dotnet #efcore #csharp #linq #backend #devtools
Хочешь разобраться с event-driven архитектурой?

Начни с самого простого - событийных уведомлений. В DDD это делается через domain events.

Как это работает:

- В доменной модели есть агрегаты - они отвечают за целостность внутри своих границ.
- Если нужно инициировать действие вне агрегата, он не вызывает его напрямую, а публикует domain event.
- Другие агрегаты подписываются на эти события и реагируют, когда нужно.

Получается слабое связывание: один объект просто сообщает «что произошло», а не «что делать дальше».

Агрегат поднял событие — другие обработали. Чисто, понятно, без прямых зависимостей.

Так строятся системы, которые легко расширять и поддерживать, не превращая код в паутину вызовов.

Event-driven начинается не с Kafka и очередей, а с простого: правильно разделять границы и общаться через события.

Подробнее
𝟵𝟬% API на самом деле НЕ RESTful — и почти всегда по одной причине 👇

По модели зрелости Ричардсона REST имеет 4 уровня:

• 0 — просто один эндпоинт, всё через XML/JSON
• 1 — ресурсы с разными URI
• 2 — корректное использование HTTP-методов
• 3 — HATEOAS, когда сам API подсказывает клиенту, какие действия доступны дальше

Проблема в том, что большинство сервисов останавливаются на уровне 2 — то есть формально используют GET/POST/PUT/DELETE, но не дают клиенту навигации через гипермедиа.

Почему почти никто не добавляет HATEOAS:
1. Нужно больше кода
2. Вырастают ответы
3. Нет жёсткого стандарта, как это оформлять
4. Клиент усложняется
5. Кажется оверинжинирингом

Но что происходит без него?
1. Клиент и сервер становятся жёстко связаны
2. Бизнес-логика дублируется на клиенте
3. API плохо открывается и не подсказывает, как по нему ходить

HATEOAS — не обязательный компонент, но именно он делает API настоящим REST, а не просто HTTP поверх JSON.

Здесь разбор, когда это действительно важно и когда нет.
🖥 Если вы создаёте новое приложение на .NET и используете минимальные API, вот понятный и согласованный пост без разделителей.

Минимальные API проще, чем контроллеры: меньше шаблонного кода, быстрее старт, короче путь от запроса к логике. Они органично ложатся на архитектуру вертикальных срезов, где каждая фича - самостоятельный модуль с собственным API, моделями и обработчиком.

Каждый endpoint можно оформлять как отдельную фичу. В одном файле находятся запрос, ответ, обработчик и маршрут — всё компактно и по делу. Такой подход улучшает читаемость и делает зависимости между фичами минимальными.

Пример:

public static class CreateProduct
{
public record Request(string Name, decimal Price);
public record Response(int Id, string Name, decimal Price);

public class Endpoint : IEndpoint
{
public void MapEndpoint(IEndpointRouteBuilder app)
{
app.MapPost("products", Handler).WithTags("Products");
}

public static IResult Handler(Request request, AppDbContext context)
{
var product = new Product { Name = request.Name, Price = request.Price };
context.Products.Add(product);
context.SaveChanges();
return Results.Ok(new Response(product.Id, product.Name, product.Price));
}
}
}


У минимальных API действительно меньше встроенных возможностей, чем у контроллеров, но это решается через middleware, фильтры или библиотеки вроде FastEndpoints, где одну фичу можно определить в одном файле с аккуратным разделением логики.

Подход помогает масштабировать код без усложнения архитектуры: новые фичи добавляются как новые независимые вертикальные срезы, без изменения существующих модулей.

https://milanjovanovic.tech/blog/vertical-slice-architecture-is-easier-than-you-think
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM