C# Portal | Программирование
13.9K subscribers
1.15K photos
126 videos
29 files
928 links
Присоединяйтесь к нашему каналу и погрузитесь в мир для C#-разработчика

Сотрудничество, реклама: @devmangx

Менеджер: @Spiral_Yuri

РКН: https://clck.ru/3FocB6
Download Telegram
Оператор LINQ FullJoin() появится в dotnet 11?

https://github.com/dotnet/runtime/issues/124787

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Когда стоит использовать паттерн Outbox?

Паттерн Outbox хранит исходящие сообщения в таблице базы данных, а потом фоновый процесс публикует их в брокер сообщений.

Зачем вообще заморачиваться?

Потому что в распределённых системах всё ломается: падают downstream-сервисы, отваливается сеть и т.д.

Если публиковать сообщения прямо внутри обработки запроса, есть риск их потерять, когда что-то пойдёт не так.

Outbox опирается на атомарные транзакции БД:

Сохранить состояние приложения
Сохранить сообщение в Outbox (либо оба шага, либо ни один)

А дальше фоновый процесс уже безопасно доставляет сообщение.

Важно помнить: Outbox решает надёжность публикации.

А на стороне консюмера всё равно нужна идемпотентность, чтобы нормально переживать ретраи.

Хочешь глубже?

Полная статья тут: https://milanjovanovic.tech/blog/implementing-the-outbox-pattern

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍43
C# records как value objects?

Records по задумке иммутабельные, и у них структурное сравнение (равенство по значениям).

А именно это обычно и нужно от value object.

Плюс сверху получаем pattern matching, короткий синтаксис и deconstruction.

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);


👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9😁1
Каждый раз, когда ты пишешь очередной новенький List<>,
ты на самом деле принимаешь решение по производительности.

Большинство разработчиков воспринимают структуры данных как контейнеры. А это не так. Это контракты по перформансу.

Вот как полезно думать о самых популярных структурах в .NET, по-практически:

Array
Бери, когда размер фиксирован и нужен честный O(1) доступ по индексу.
Самый быстрый вариант. Нет ресайза. Нет сюрпризов.

List<T>
Отличный дефолтный выбор, пока не упираешься в ресайз.
Под капотом при росте capacity копируется весь массив.

Dictionary<TKey, TValue>
В среднем O(1) на поиск.
Но плохое распределение хеша -> коллизии -> деградация скорости.

Stack<T>
Идеален для рекурсии, парсинга, undo/redo.
Но глубокая рекурсия? Привет, StackOverflow (сайт) или stack overflow (ошибка).

Queue<T>
FIFO. Отлично для фоновой обработки и пайплайнов.
Типа планирования задач, обработки сообщений.

Tree / Graph
Используются чаще, чем кажется:
роутинг, индексация, разрешение зависимостей, поиск.

Смысл не в том, чтобы заучивать Big-O.

Смысл понимать:

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

Хорошие инженеры пишут код, который работает.

Классные инженеры знают, почему он работает и в какой момент перестанет.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍76
GitHub Copilot SDK для .NET: полное руководство разработчика

Разберись с GitHub Copilot SDK для .NET в этом полном гайде для разработчиков. Собирай кастомных AI-агентов на базе CopilotClient и CopilotSession, со стримингом, tools и поддержкой нескольких моделей в C#.

Статья здесь

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
5
Пример Vertical Slice Architecture в ASP.NET

Я один такой, кто складывает вообще всё в один файл?

С этим работать просто мечта 😍

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🤯7🥴43🔥1
Паттерн Builder в реальном мире на C#: полная реализация

Посмотрите, как паттерн Builder работает на практике, на полноценном реальном примере на C#. Пошаговая реализация конфигурационной системы, которая показывает поэтапную сборку объекта.

Статья здесь

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
5
Как применять EF-миграции в продакшене?

Самый распространенный подход: накатывать их через CLI командой Update-Database.

Но я предпочитаю генерировать для миграций SQL-скрипты. Так можно проверить SQL-выражения и убедиться, что все ок.

Еще лучше, если у вас есть DBA.

CREATE TABLE IF NOT EXISTS "__EFMigrationsHistory" (
"MigrationId" character varying(150) NOT NULL,
"ProductVersion" character varying(32) NOT NULL,
CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY ("MigrationId")
);

START TRANSACTION;

CREATE TABLE "Products" (
"Id" integer GENERATED BY DEFAULT AS IDENTITY,
"Name" character varying(100) NOT NULL,
"Description" character varying(1000),
"Price" numeric(18,2) NOT NULL,
CONSTRAINT "PK_Products" PRIMARY KEY ("Id"),
CONSTRAINT "CK_Price_NotNegative" CHECK (Price > 0)
);

CREATE UNIQUE INDEX "IX_Products_Name" ON "Products" ("Name");

INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
VALUES ('20240516095344_Create_Database', '8.0.5');

COMMIT;


👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🥴9🤔1
Отсутствие нейминг-конвенций в коде меня дико бесит.

Можешь с этим что-нибудь сделать?

Только без истерик в PR (так не надо).

Если вдруг не знал: довольно легко написать архитектурные тесты, которые проверяют нейминг-конвенции в твоём коде.

Вот пример для именования command handler-ов.

[Fact]
public void CommandHandler_ShouldHave_NameEndingWith_CommandHandler()
{
Types.InAssembly(ApplicationAssembly)
.That()
.ImplementInterface(typeof(ICommandHandler<>))
.Or()
.ImplementInterface(typeof(ICommandHandler<,>))
.Should()
.HaveNameEndingWith("CommandHandler")
.GetResult()
.ShouldBeSuccessful();
}


👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🥴76👍4🤔1
Кто-то собрал вообще все туториалы в стиле сделай это с нуля со всего интернета в одном месте.

Называется build-your-own-x, и это самый популярный репозиторий в истории GitHub по числу звёзд.

466 000 звёзд. Больше, чем у React. Больше, чем у TensorFlow. Больше, чем у любого инструмента, который когда-либо делали.

И это не код. Это кураторская подборка пошаговых туториалов, которые учат пересобирать с нуля технологии, которыми ты пользуешься каждый день. С нуля.

Ричард Фейнман сказал: "Чего я не могу создать, того я не понимаю."

https://github.com/codecrafters-io/build-your-own-x

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍113🤔1
Как сделать ваши API-эндпоинты быстрее в 426 раз:
(подсказка: это не кэш)

Когда разработчики видят медленные API, первая реакция часто такая: лечить тормоза неправильным лекарством, кэшем.

Но это решение держится на ключевом заблуждении:

будто кэширование может исправить тормоза, вызванные плохими запросами к базе данных.

Поэтому первый шаг к более масштабируемым системам это починить именно запросы.

Чтобы это показать, проведем небольшой эксперимент.

Я сделал небольшой веб-API с одним эндпоинтом /products.

До оптимизации:

- Количество обработанных запросов: 378
- Среднее запросов/сек: 11.01
- Средняя длительность запроса: примерно 4 секунды

После оптимизации:
- Количество обработанных запросов: 140,331
- Среднее запросов/сек: 4,689.36
- Средняя длительность запроса: 10.69 мс

Сначала исправляй доступ к данным.
А кэш используй потом, чтобы масштабироваться, а не выживать.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍72👎1🤔1
Поддержка MinBy / MaxBy скоро появится в Entity Framework 😍

Судя по всему, это должно приехать в EF 11 Preview 2.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
8🔥1🤔1
Жирный лайфхак: как бесплатно и за пару минут сделать сайт с документацией для любого репозитория на GitHub:

👉 @KodBlog
This media is not supported in your browser
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👎3🥴21🤔1🤨1
У нас новости: нативная трассировка OpenTelemetry появится в ASP.NET 11 Preview 2! ✌️

ASP.NET Core теперь нативно добавляет атрибуты семантических конвенций OpenTelemetry в Activity HTTP-сервера, приводя это в соответствие со спецификацией OpenTelemetry HTTP server span. Все обязательные атрибуты теперь включены по умолчанию, то есть метаданные совпадают с теми, что раньше были доступны только через библиотеку OpenTelemetry.Instrumentation.AspNetCore.

Чтобы собирать встроенные данные трассировки, подпишитесь на source Microsoft.AspNetCore в вашей конфигурации OpenTelemetry:

builder.Services.AddOpenTelemetry()
.WithTracing(tracing => tracing
.AddSource("Microsoft.AspNetCore")
.AddConsoleExporter());


Никакая дополнительная библиотека инструментирования (например OpenTelemetry.Instrumentation.AspNetCore) больше не нужна. Фреймворк теперь напрямую проставляет атрибуты семантических конвенций, такие как http.request.method, url.path, http.response.status_code и server.address, в Activity запроса.


👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
5🤔1
Самый простой способ добавить валидацию в Options Pattern

Можно использовать data annotations, например атрибут Required.

Также нужно обновить настройку DI и вызвать метод ValidateDataAnnotations.

Это включит валидацию при разрешении options из DI-контейнера.

public class GitHubSettings
{
[Required]
public string AccessToken { get; init; }

[Required]
public string RepositoryName { get; init; }
}

builder.Services
.AddOptions<GitHubSettings>()
.BindConfiguration("GitHubSettings")
.ValidateDataAnnotations();


👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🤔2
thoseThreeOnlyBringRegret

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥101🤔1
Самое мощное правило для написания читаемого C# кода:

(Я вынес его из одного ТВ-шоу 90-х про бои на мечах)

Никогда не делайте цепочку больше чем из одного тернарного оператора.

Сейчас объясню.

В детстве я смотрел сериал Highlander.

Если не знакомы с этим шоу:

Там куча людей дерется на мечах.

Главное правило? Должен остаться только один.

То есть в конце выживает только один.

Золотое правило при работе с тернарным оператором в C#:

Должен быть только один.

То есть избегайте цепочек из более чем одного тернарного оператора.

Решение:

1. Перепишите в if-else.
2. Посмотрите, можно ли еще сильнее отрефакторить и упростить код.

Запомните:

Если видите цепочку тернарных операторов, доставайте меч, ну то есть рефакторьте, и рубите эту цепочку.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
13🥴10💯2🤔1
В EF Core есть способ получше для массовых обновлений.

Можно использовать метод ExecuteUpdate. Его добавили в EF 7.

При выполнении в базе данных он преобразуется в один SQL-запрос.

Но тут нужно заранее знать, какое именно свойство ты обновляешь и в какое значение.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥73🤔1🥴1
В .NET 11 Preview 3 добавили раннюю preview-фичу из C# 15: unions.

Она добавляет объявления union (union Pet(Cat, Dog, Bird) { ... }) и union-типы, помечаемые атрибутом [Union].

Их можно обрабатывать через pattern matching / switch expressions как замкнутый набор вариантов, с проверкой exhaustiveness.

https://github.com/dotnet/csharplang/blob/main/proposals/unions.md

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9🤔4