C# (C Sharp) programming
18.1K subscribers
978 photos
51 videos
8 files
780 links
По всем вопросам- @notxxx1

Реестр РКН: https://clck.ru/3Fk3kb

#VRHSZ
Download Telegram
15 проезный .NET-библиотек, которые используют senior-разработчики

Open-source библиотеки, которые делают код чище, тесты надёжнее, а разработку быстрее.


**HTTP, устойчивость и DI**

**1. Refit**
Превращает REST API в типизированные C# интерфейсы. Меньше boilerplate вокруг HttpClient.
GitHub: https://github.com/reactiveui/refit

2. Polly
Retry, circuit breaker, timeout и resilience-политики для исходящих вызовов.
GitHub: https://github.com/App-vNext/Polly

3. Scrutor
Автосканирование и регистрация сервисов в DI по конвенциям.
GitHub: https://github.com/khellang/Scrutor

Тестирование

4. Bogus
Генератор реалистичных fake-данных для тестов и сидинга.
GitHub: https://github.com/bchavez/Bogus

5. Verify
Snapshot-тесты для .NET: один раз утвердил вывод, дальше ловишь регрессии.
GitHub: https://github.com/VerifyTests/Verify

6. Testcontainers for .NET
Поднимает реальный PostgreSQL, SQL Server, Redis и другие сервисы в Docker для интеграционных тестов.
GitHub: https://github.com/testcontainers/testcontainers-dotnet

API и фоновые задачи

7. FastEndpoints
Быстрые Minimal API по паттерну REPR без раздутых контроллеров.
Сайт: https://fast-endpoints.com
GitHub: https://github.com/FastEndpoints/FastEndpoints

8. TickerQ
Нативный планировщик фоновых задач без Hangfire, Quartz и лишнего оверхеда.
GitHub: https://github.com/Arcenox-co/TickerQ

9. HotChocolate
Мощный GraphQL-сервер для .NET, когда один гибкий endpoint удобнее десятков REST-маршрутов.
Сайт: https://chillicream.com/docs/hotchocolate
GitHub: https://github.com/ChilliCream/graphql-platform

Микросервисы и messaging

10. Dapr
Service discovery, pub/sub и state management для микросервисов без лишней инфраструктурной сантехники.
Сайт: https://dapr.io
GitHub: https://github.com/dapr/dotnet-sdk

11. Wolverine
Mediator и messaging в одном фреймворке. Как MediatR, только шире по возможностям.
Сайт: https://wolverinefx.net
GitHub: https://github.com/JasperFx/wolverine

Утилиты и работа с данными

12. UnitsNet
Безопасная работа с единицами измерения вместо сырых double для температуры, скорости и расстояний.
GitHub: https://github.com/angularsen/UnitsNet

13. Humanizer
Превращает строки, даты, числа и enum-ы в читаемый вид одной строкой кода.
GitHub: https://github.com/Humanizr/Humanizer

14. ImageSharp
Обработка, ресайз и конвертация изображений в .NET. Кросс-платформенно, без GDI+.
Сайт: https://sixlabors.com/products/imagesharp
GitHub: https://github.com/SixLabors/ImageSharp

Архитектура

15. ArchUnitNET
Тесты для архитектурных правил. Нарушения слоёв и Clean Architecture падают прямо в CI.
GitHub: https://github.com/TNG/ArchUnitNET
Forwarded from Machinelearning
📌 OpenAI показала редкий для ИИ результат: внутренняя модель самостоятельно нашла контрпример к известной задаче из дискретной геометрии, которую Пал Эрдёш сформулировал ещё в 1946 году.

Суть задачи простая: есть n точек на плоскости. Нужно понять, сколько пар точек могут находиться ровно на расстоянии 1 друг от друга.

Долгое время считалось, что почти оптимальный ответ дают конструкции, похожие на квадратную решётку. Модель OpenAI показала, что это неверно.

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

Модель связала задачу о точках на плоскости с алгебраической теорией чисел.

В доказательстве используются решётки Минковского (способ превратить числа из алгебраической теории чисел в точки в обычном евклидовом пространстве), элементы нормы один и pro-3 башни числовых полей. Это инструменты из другой части математики, и именно их перенос в геометрию дал результат.

Нога Алон из Принстона отметил, что ответ оказался неожиданным, а применённые методы выглядят элегантно и нетривиально.

При этом доказательство не даёт нового «чисто геометрического» метода, на который многие надеялись. Гипотеза опровергнута, но сама структура задачи стала ещё интереснее.

Задачу сформулировал ИИ, решение сгенерировала внутренняя модель OpenAI, первичная проверка тоже прошла через автоматический ИИ-пайплайн. После этого люди проверили детали, улучшили изложение и довели работу до публикации.

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

Оригинал: https://openai.com/index/model-disproves-discrete-geometry-conjecture/

@ai_machinelearning_big_data
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Полезная находка для геймдевов: большая коллекция open-source игр в одном месте.

В репозитории собраны десятки проектов разных жанров. Всё разложено по категориям, у каждой игры есть краткое описание и ссылка на исходники.

Можно смотреть, как устроены реальные игровые проекты, разбирать архитектуру, контрибьютить или просто запускать и играть.

Для тех, кто учится геймдеву, это почти готовая база примеров из живого кода.

https://github.com/bobeff/open-source-games
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 C# задачка с подвохом

Что выведет код?


using System;
using System.Collections.Generic;

var list = new List<Func<int>>();

for (int i = 0; i < 3; i++)
{
int x = i;
list.Add(() => x);
x = 100;
}

foreach (var f in list)
{
Console.Write(f() + " ");
}


A) 0 1 2

😎 100 100 100

C) 3 3 3

D) 0 100 100

Правильный ответ: 😎 100 100 100

Почему так:

Внутри каждой итерации создаётся новая локальная переменная x, и именно её захватывает лямбда. Кажется, что ответы должны быть 0 1 2, потому что x получает значение i.

Но после добавления лямбды переменная x всё ещё та же самая захваченная переменная. Потом мы меняем её на 100.

В итоге каждая лямбда хранит свою отдельную x, но каждая из этих x была изменена на 100.
Please open Telegram to view this post
VIEW IN TELEGRAM
✔️ Одна строчка .Result роняет ваш ASP.NET Core при CPU 8 %: разбор hill-climbing в .NET 9

TL;DR. Один foo.GetAsync().Result внутри middleware превращает ASP.NET Core, державший 50k RPS на p99 = 40 мс, в сервис на 12k RPS с p99 = 4 с при CPU 8 %. Виноват не блокирующий вызов сам по себе.

Виноват hill-climbing: фидбэк-луп в ThreadPool, внутри которого живёт дискретное преобразование Фурье.

Разбираемся по исходникам CoreCLR, как это работает, воспроизводим эффект на ~80 строках кода и показываем, почему SetMinThreads это не лечение, а анестезия.

https://habr.com/ru/articles/1040804/
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Алгоритму почти 70 лет, а он до сих пор живёт в ядре Linux.

В 1957 году Wilkes, Wheeler и Gill описали быстрый способ считать количество установленных битов в числе. Не циклом по одному биту, а через маски и арифметику сразу над группами битов.

Идея простая:

- сначала считаем биты парами
- потом группами по 4
- потом по байтам
- в конце умножение собирает сумму в старший байт

Если в процессоре нет инструкции POPCNT, Linux использует похожий подход в __sw_hweight64.

Красивый пример того, как старый битовый трюк пережил десятилетия и всё ещё работает в современном системном коде.
🐳 «Используй Testcontainers вместо in-memory» - это только половина правды

Все уже выучили: EF Core InMemory provider - не интеграционный тест.

Он не ловит:

- баги в LINQ-трансляции
- ограничения БД
- коллации
- реальные типы колонок
- поведение конкретного SQL-провайдера

Окей, заменили на реальный PostgreSQL через Testcontainers. Победа? Не совсем.

Вот что начинается дальше.

1. Вы получили «медленное враньё» вместо «быстрого»

Поднимать контейнер на каждый тест-класс - быстрый способ превратить CI из 30 секунд в 8 минут.

Нормальный вариант:

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

Respawn чистит таблицы с учётом графа foreign keys за миллисекунды.

2. Транзакционный откат ≠ реальный сценарий

Трюк «обернули тест в транзакцию и откатили» красиво выглядит, но ломается, когда в коде есть:

- свои транзакции
- несколько SaveChanges
- фоновые операции
- поведение, завязанное на commit

В итоге тестируется сценарий, которого в проде нет.

3. Самая коварная ловушка - общий DbContext

Если тест и код используют один экземпляр DbContext, EF может вернуть данные из change tracker, а не из базы.

Тест зелёный, но он врёт: реальный SQL-запрос мог вообще не выполниться.

Между Act и Assert стоит чистить трекер:


Db.ChangeTracker.Clear();


4. Бонус, который теряют 90% команд - тест миграций

Реальная БД позволяет прогнать EF-миграции на чистой схеме.

Если миграция падает или схема разъехалась с моделью, вы узнаёте об этом в CI, а не в проде в пятницу вечером.

Пример базового подхода:


public class IntegrationTestBase : IAsyncLifetime
{
private static readonly PostgreSqlContainer _db =
new PostgreSqlBuilder()
.WithImage("postgres:16-alpine")
.Build();

private Respawner _respawner = null!;
protected AppDbContext Db = null!;

public async Task InitializeAsync()
{
await _db.StartAsync();

var options = new DbContextOptionsBuilder<AppDbContext>()
.UseNpgsql(_db.GetConnectionString())
.Options;

Db = new AppDbContext(options);

// Реальные миграции - заодно проверяем, что они накатываются
await Db.Database.MigrateAsync();

await using var conn = new NpgsqlConnection(_db.GetConnectionString());
await conn.OpenAsync();

_respawner = await Respawner.CreateAsync(conn, new RespawnerOptions
{
DbAdapter = DbAdapter.Postgres,
SchemasToInclude = ["public"]
});
}

// Сброс данных перед каждым тестом - без пересоздания контейнера
protected async Task ResetAsync()
{
await using var conn = new NpgsqlConnection(_db.GetConnectionString());
await conn.OpenAsync();

await _respawner.ResetAsync(conn);

// Иначе тест может читать из кеша, а не из БД
Db.ChangeTracker.Clear();
}

public Task DisposeAsync() => Task.CompletedTask;
}


Testcontainers - это не галочка «best practice», а смена философии.

Без нормальной изоляции данных вы просто пересели с быстрого вранья на медленное.

А как вы изолируете состояние БД между интеграционными тестами - Respawn, транзакции или пересоздание контейнера?

#dotnet #csharp #testing #efcore