C# records как value objects?
Records по задумке иммутабельные, и у них структурное сравнение (равенство по значениям).
А именно это обычно и нужно от value object.
Плюс сверху получаем pattern matching, короткий синтаксис и deconstruction.
👉 @KodBlog
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);
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9😁1
Каждый раз, когда ты пишешь очередной новенький
ты на самом деле принимаешь решение по производительности.
Большинство разработчиков воспринимают структуры данных как контейнеры. А это не так. Это контракты по перформансу.
Вот как полезно думать о самых популярных структурах в .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
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.
Смысл понимать:
- как выделяется память
- как работает ресайз
- что происходит под нагрузкой
- на какой компромисс ты соглашаешься
Хорошие инженеры пишут код, который работает.
Классные инженеры знают, почему он работает и в какой момент перестанет.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤6
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🤯7🥴4❤3🔥1
Паттерн Builder в реальном мире на C#: полная реализация
Посмотрите, как паттерн Builder работает на практике, на полноценном реальном примере на C#. Пошаговая реализация конфигурационной системы, которая показывает поэтапную сборку объекта.
Статья здесь
👉 @KodBlog
Посмотрите, как паттерн Builder работает на практике, на полноценном реальном примере на C#. Пошаговая реализация конфигурационной системы, которая показывает поэтапную сборку объекта.
Статья здесь
Please open Telegram to view this post
VIEW IN TELEGRAM
Dev Leader
Builder Pattern Real-World Example in C#: Complete Implementation
See Builder pattern in action with a complete real-world C# example. Step-by-step implementation of a configuration system demonstrating step-by-step object con
❤5
Как применять EF-миграции в продакшене?
Самый распространенный подход: накатывать их через CLI командой
Но я предпочитаю генерировать для миграций SQL-скрипты. Так можно проверить SQL-выражения и убедиться, что все ок.
Еще лучше, если у вас есть DBA.
👉 @KodBlog
Самый распространенный подход: накатывать их через 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;
Please open Telegram to view this post
VIEW IN TELEGRAM
🥴9🤔1
Отсутствие нейминг-конвенций в коде меня дико бесит.
Можешь с этим что-нибудь сделать?
Только без истерик в PR (так не надо).
Если вдруг не знал: довольно легко написать архитектурные тесты, которые проверяют нейминг-конвенции в твоём коде.
Вот пример для именования command handler-ов.
👉 @KodBlog
Можешь с этим что-нибудь сделать?
Только без истерик в 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();
}
Please open Telegram to view this post
VIEW IN TELEGRAM
🥴7❤6👍4🤔1
Невозможно оставаться холодным и безразличным, когда речь про ИИ.
Так что эти ресурсы стоит чекнуть как можно скорее:
- https://github.com/AIDotNet/OpenDeepWiki
- https://github.com/shuyu-labs/AntSK
- https://github.com/AIDotNet/Thor
- https://github.com/AIDotNet/auto-prompt
👉 @KodBlog
Так что эти ресурсы стоит чекнуть как можно скорее:
- https://github.com/AIDotNet/OpenDeepWiki
- https://github.com/shuyu-labs/AntSK
- https://github.com/AIDotNet/Thor
- https://github.com/AIDotNet/auto-prompt
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
GitHub - AIDotNet/OpenDeepWiki: OpenDeepWiki is the open-source version of the DeepWiki project, aiming to provide a powerful knowledge…
OpenDeepWiki is the open-source version of the DeepWiki project, aiming to provide a powerful knowledge management and collaboration platform. The project is mainly developed using C# and TypeScrip...
👍1🤔1
Кто-то собрал вообще все туториалы в стиле сделай это с нуля со всего интернета в одном месте.
Называется build-your-own-x, и это самый популярный репозиторий в истории GitHub по числу звёзд.
466 000 звёзд. Больше, чем у React. Больше, чем у TensorFlow. Больше, чем у любого инструмента, который когда-либо делали.
И это не код. Это кураторская подборка пошаговых туториалов, которые учат пересобирать с нуля технологии, которыми ты пользуешься каждый день. С нуля.
Ричард Фейнман сказал: "Чего я не могу создать, того я не понимаю."
https://github.com/codecrafters-io/build-your-own-x
👉 @KodBlog
Называется build-your-own-x, и это самый популярный репозиторий в истории GitHub по числу звёзд.
466 000 звёзд. Больше, чем у React. Больше, чем у TensorFlow. Больше, чем у любого инструмента, который когда-либо делали.
И это не код. Это кураторская подборка пошаговых туториалов, которые учат пересобирать с нуля технологии, которыми ты пользуешься каждый день. С нуля.
Ричард Фейнман сказал: "Чего я не могу создать, того я не понимаю."
https://github.com/codecrafters-io/build-your-own-x
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤3🤔1
Как сделать ваши API-эндпоинты быстрее в 426 раз:
(подсказка: это не кэш)
Когда разработчики видят медленные API, первая реакция часто такая: лечить тормоза неправильным лекарством, кэшем.
Но это решение держится на ключевом заблуждении:
будто кэширование может исправить тормоза, вызванные плохими запросами к базе данных.
Поэтому первый шаг к более масштабируемым системам это починить именно запросы.
Чтобы это показать, проведем небольшой эксперимент.
Я сделал небольшой веб-API с одним эндпоинтом
До оптимизации:
- Количество обработанных запросов: 378
- Среднее запросов/сек: 11.01
- Средняя длительность запроса: примерно 4 секунды
После оптимизации:
- Количество обработанных запросов: 140,331
- Среднее запросов/сек: 4,689.36
- Средняя длительность запроса: 10.69 мс
Сначала исправляй доступ к данным.
А кэш используй потом, чтобы масштабироваться, а не выживать.
👉 @KodBlog
(подсказка: это не кэш)
Когда разработчики видят медленные API, первая реакция часто такая: лечить тормоза неправильным лекарством, кэшем.
Но это решение держится на ключевом заблуждении:
будто кэширование может исправить тормоза, вызванные плохими запросами к базе данных.
Поэтому первый шаг к более масштабируемым системам это починить именно запросы.
Чтобы это показать, проведем небольшой эксперимент.
Я сделал небольшой веб-API с одним эндпоинтом
/products.До оптимизации:
- Количество обработанных запросов: 378
- Среднее запросов/сек: 11.01
- Средняя длительность запроса: примерно 4 секунды
После оптимизации:
- Количество обработанных запросов: 140,331
- Среднее запросов/сек: 4,689.36
- Средняя длительность запроса: 10.69 мс
Сначала исправляй доступ к данным.
А кэш используй потом, чтобы масштабироваться, а не выживать.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤2👎1🤔1
Поддержка 😍
Судя по всему, это должно приехать в EF 11 Preview 2.
👉 @KodBlog
MinBy / MaxBy скоро появится в Entity Framework Судя по всему, это должно приехать в EF 11 Preview 2.
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🥴2❤1🤔1🤨1
У нас новости: нативная трассировка OpenTelemetry появится в ASP.NET 11 Preview 2! ✌️
ASP.NET Core теперь нативно добавляет атрибуты семантических конвенций OpenTelemetry в Activity HTTP-сервера, приводя это в соответствие со спецификацией OpenTelemetry HTTP server span. Все обязательные атрибуты теперь включены по умолчанию, то есть метаданные совпадают с теми, что раньше были доступны только через библиотеку
Чтобы собирать встроенные данные трассировки, подпишитесь на source
Никакая дополнительная библиотека инструментирования (например
👉 @KodBlog
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 запроса.Please open Telegram to view this post
VIEW IN TELEGRAM
❤5🤔1
Самый простой способ добавить валидацию в Options Pattern
Можно использовать data annotations, например атрибут
Также нужно обновить настройку DI и вызвать метод
Это включит валидацию при разрешении options из DI-контейнера.
👉 @KodBlog
Можно использовать 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();
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🤔2
Самое мощное правило для написания читаемого C# кода:
(Я вынес его из одного ТВ-шоу 90-х про бои на мечах)
Никогда не делайте цепочку больше чем из одного тернарного оператора.
Сейчас объясню.
В детстве я смотрел сериал Highlander.
Если не знакомы с этим шоу:
Там куча людей дерется на мечах.
Главное правило? Должен остаться только один.
То есть в конце выживает только один.
Золотое правило при работе с тернарным оператором в C#:
Должен быть только один.
То есть избегайте цепочек из более чем одного тернарного оператора.
Решение:
1. Перепишите в
2. Посмотрите, можно ли еще сильнее отрефакторить и упростить код.
Запомните:
Если видите цепочку тернарных операторов, доставайте меч, ну то есть рефакторьте, и рубите эту цепочку.
👉 @KodBlog
(Я вынес его из одного ТВ-шоу 90-х про бои на мечах)
Никогда не делайте цепочку больше чем из одного тернарного оператора.
Сейчас объясню.
В детстве я смотрел сериал Highlander.
Если не знакомы с этим шоу:
Там куча людей дерется на мечах.
Главное правило? Должен остаться только один.
То есть в конце выживает только один.
Золотое правило при работе с тернарным оператором в C#:
Должен быть только один.
То есть избегайте цепочек из более чем одного тернарного оператора.
Решение:
1. Перепишите в
if-else.2. Посмотрите, можно ли еще сильнее отрефакторить и упростить код.
Запомните:
Если видите цепочку тернарных операторов, доставайте меч, ну то есть рефакторьте, и рубите эту цепочку.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤13🥴10💯2🤔1
В EF Core есть способ получше для массовых обновлений.
Можно использовать метод
При выполнении в базе данных он преобразуется в один SQL-запрос.
Но тут нужно заранее знать, какое именно свойство ты обновляешь и в какое значение.
👉 @KodBlog
Можно использовать метод
ExecuteUpdate. Его добавили в EF 7.При выполнении в базе данных он преобразуется в один SQL-запрос.
Но тут нужно заранее знать, какое именно свойство ты обновляешь и в какое значение.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7❤3🤔1🥴1
В .NET 11 Preview 3 добавили раннюю preview-фичу из C# 15: unions.
Она добавляет объявления union (
Их можно обрабатывать через pattern matching / switch expressions как замкнутый набор вариантов, с проверкой exhaustiveness.
https://github.com/dotnet/csharplang/blob/main/proposals/unions.md
👉 @KodBlog
Она добавляет объявления union (
union Pet(Cat, Dog, Bird) { ... }) и union-типы, помечаемые атрибутом [Union].Их можно обрабатывать через pattern matching / switch expressions как замкнутый набор вариантов, с проверкой exhaustiveness.
https://github.com/dotnet/csharplang/blob/main/proposals/unions.md
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
csharplang/proposals/unions.md at main · dotnet/csharplang
The official repo for the design of the C# programming language - dotnet/csharplang
🔥9🤔4
Правильно ли вы внедряете зависимости в Controllers?
Многие разработчики этого не знают
Внедрять зависимости в Controller можно двумя способами:
↳ через конструктор
↳ через внедрение в метод
Сталкивались с раздутыми контроллерами, у которых в конструкторе слишком много зависимостей?
При этом конкретный endpoint использует только часть из них.
❌ Вы зря расходуете память, потому что все зависимости из конструктора аллоцируются в куче при вызове Controller, независимо от того, будут они использоваться или нет.
✅ Так почему бы не внедрять нужные объекты прямо в метод endpoint-а?
Их можно внедрять без атрибута
Когда вы внедряете зависимости только там, где они реально нужны, это улучшает читаемость, упрощает поддержку и повышает производительность контроллеров.
👉 @KodBlog
Многие разработчики этого не знают
Внедрять зависимости в Controller можно двумя способами:
↳ через конструктор
↳ через внедрение в метод
Сталкивались с раздутыми контроллерами, у которых в конструкторе слишком много зависимостей?
При этом конкретный endpoint использует только часть из них.
Их можно внедрять без атрибута
[FromServices], он больше не нужен. Почти так же, как и в Minimal APIs.Когда вы внедряете зависимости только там, где они реально нужны, это улучшает читаемость, упрощает поддержку и повышает производительность контроллеров.
Please open Telegram to view this post
VIEW IN TELEGRAM
👎6❤5👍2🤔2
Хватит инжектить IConfiguration. Вот правильный подход в .NET 10
Однажды я выкатил систему feature-флагов, которая читала настройки из
Исправление? Заменить
Изменение в одну строку, которое стоило мне трёх часов дебага и инцидент-репорта. Этот случай показал мне: понимать Options Pattern — не опционально. Это базовая вещь. Разберёмся.
Завариваем кофею и читаем статью
👉 @KodBlog
Однажды я выкатил систему feature-флагов, которая читала настройки из
appsettings.json через IOptions<FeatureFlagOptions>. В деве всё работало нормально. Но в проде, когда команда DevOps переключала флаг, обновляя appsettings.json, ничего не происходило. API продолжал возвращать старые значения. Пользователи застряли. Чтобы подхватить изменения, мне пришлось перезапустить приложение.Исправление? Заменить
IOptions<T> на IOptionsMonitor<T>.Изменение в одну строку, которое стоило мне трёх часов дебага и инцидент-репорта. Этот случай показал мне: понимать Options Pattern — не опционально. Это базовая вещь. Разберёмся.
Завариваем кофею и читаем статью
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8🔥6🥴2🤨2🤔1