Первичные конструкторы в dotnet
ДО .NET 8 (Традиционный подход с конструктором):
ПОСЛЕ .NET 8 (Использование Primary Constructor):
Круто или нет?
👉 @KodBlog
ДО .NET 8 (Традиционный подход с конструктором):
public class UserService
{
private readonly HospitalDBContext _dbContext;
private readonly ILogger<UserService> _logger;
private readonly IEmailService _emailService;
public UserService(
HospitalDBContext dbContext,
ILogger<UserService> logger,
IEmailService emailService)
{
_dbContext = dbContext;
_logger = logger;
_emailService = emailService;
}
// Методы бизнес-логики здесь...
}
ПОСЛЕ .NET 8 (Использование Primary Constructor):
public class UserService(
HospitalDBContext _dbContext,
ILogger<UserService> _logger,
IEmailService _emailService)
{
// Методы бизнес-логики здесь...
}
Круто или нет?
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥19🤨7❤6🐳2😁1
Не совершайте эту ошибку
Не используйте
Метод
Представьте метод, который вызывается очень часто — это может деградировать производительность приложения.
Кроме того,
Что использовать вместо этого?
В .NET есть мощное перечисление —
Возможные варианты StringComparison:
- Ordinal — используйте в большинстве случаев, когда культурные правила не важны. Самый быстрый вариант.
- OrdinalIgnoreCase — для сравнений без учёта регистра, где культурные правила не имеют значения.
- CurrentCulture и CurrentCultureIgnoreCase — используйте при сравнении строк, отображаемых пользователю, так как они учитывают культурные правила.
- InvariantCulture и InvariantCultureIgnoreCase — подходят, когда нужна единообразная логика вне зависимости от культуры, например, при сохранении и извлечении данных.
> EF Core выбросит исключение, если использовать методы вроде
>
Это не будет работать с EF.
Если вы используете SQL Server с коллацией по умолчанию, сравнение строк уже нечувствительно к регистру, поэтому обычное
👉 @KodBlog
Не используйте
.ToLower()
для сравнения строк. Почему? Метод
.ToLower()
создаёт новую строку в памяти для каждого сравнения, что приводит к лишним аллокациям. Представьте метод, который вызывается очень часто — это может деградировать производительность приложения.
Кроме того,
.ToLower()
чувствителен к культуре, то есть результат может различаться в зависимости от текущей культуры, установленной в исполняющем потоке. Что использовать вместо этого?
В .NET есть мощное перечисление —
StringComparison
. Возможные варианты StringComparison:
- Ordinal — используйте в большинстве случаев, когда культурные правила не важны. Самый быстрый вариант.
- OrdinalIgnoreCase — для сравнений без учёта регистра, где культурные правила не имеют значения.
- CurrentCulture и CurrentCultureIgnoreCase — используйте при сравнении строк, отображаемых пользователю, так как они учитывают культурные правила.
- InvariantCulture и InvariantCultureIgnoreCase — подходят, когда нужна единообразная логика вне зависимости от культуры, например, при сохранении и извлечении данных.
> EF Core выбросит исключение, если использовать методы вроде
>
String.Equals(string, StringComparison)
, так как они не транслируются в SQL. Это не будет работать с EF.
Если вы используете SQL Server с коллацией по умолчанию, сравнение строк уже нечувствительно к регистру, поэтому обычное
a == b
или string.Equals(a, b)
в LINQ будет работать.Please open Telegram to view this post
VIEW IN TELEGRAM
👍30❤3
Посмотрите этот классный open-source инструмент для визуализации JSON-данных в интерактивных графах.
Он предлагает функции конвертации JSON в другие форматы (CSV, YAML), генерацию JSON Schema, выполнение запросов и экспорт визуализаций в виде изображений.
Также он умеет форматировать, валидировать и создавать интерфейсы TypeScript.
Репозиторий: https://github.com/AykutSarac/jsoncrack.com
👉 @KodBlog
Он предлагает функции конвертации JSON в другие форматы (CSV, YAML), генерацию JSON Schema, выполнение запросов и экспорт визуализаций в виде изображений.
Также он умеет форматировать, валидировать и создавать интерфейсы TypeScript.
Репозиторий: https://github.com/AykutSarac/jsoncrack.com
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤8🥴2
Что нового в C# 14
Главные апдейты
✅
✅
✅ Условный доступ слева от присваивания то есть
✅
✅ Модификаторы у параметров простых лямбд
✅ Больше не мучаемся со
✅ Больше
✅ Пользовательские составные операторы присваивания то есть можно задавать свою семантику для вроде
Пара мини примеров
Условное присваивание
Модификатор у лямбды без явных типов
Как попробовать
Ставишь свежий .NET 10 SDK и актуальный Visual Studio 2022 эти фичи уже в превью ветки для десятки. Страница с новыми фичами обновлялась под .NET 10 Preview 1 в апреле 2025.
🔸 подробнее - https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-14
👉 @KodBlog
Главные апдейты
Extension
members теперь можно расширять не только методами но и свойствами и индексаторами плюс есть статические расширения для самого типа.field
как контекстный токен для простых автосвойств с логикой сеттера без явного бэкинг филда.?.
и ?[]
можно ставить перед тем что присваиваешь удобно и безопасно.nameof
понимает «пустой» дженерик тип например nameof(List<>)
.ref, in, out, scoped
теперь можно без явного типа.Span<T>
и ReadOnlySpan<T>
стало больше неявных конверсий и это лучше дружит с инференсом и экстеншенами.partial
теперь можно частично объявлять конструкторы и события.+=
.Пара мини примеров
field
в действииpublic class Box
{
public string Title
{
get;
set => field = value ?? throw new ArgumentNullException(nameof(value));
}
}
Условное присваивание
customer?.Order = FetchOrder();
bag?["count"] += 1;
nameof
с незаполненным дженерикомvar n = nameof(List<>); // "List"
Модификатор у лямбды без явных типов
delegate void Bump(ref int x);
Bump inc = (ref x) => x++;
Как попробовать
Ставишь свежий .NET 10 SDK и актуальный Visual Studio 2022 эти фичи уже в превью ветки для десятки. Страница с новыми фичами обновлялась под .NET 10 Preview 1 в апреле 2025.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤14😁1
Лучший урок по C# за сегодня
(чтобы срезать количество багов примерно на 50%)
Не возвращайте из методов
Возвращайте пустые коллекции
STOP:
- Заставлять вызывающий код проверять
- Захламлять код лишними условиями
- Рисковать трудноотлавливаемыми runtime-исключениями
Начните:
- Возвращать
- Возвращать
- Возвращать
Так пишется безопасный, чистый и читаемый код
Пусть остальные продолжают тонуть в проверках на👍
👉 @KodBlog
(чтобы срезать количество багов примерно на 50%)
Не возвращайте из методов
null
для коллекций Возвращайте пустые коллекции
STOP:
- Заставлять вызывающий код проверять
null
- Захламлять код лишними условиями
- Рисковать трудноотлавливаемыми runtime-исключениями
Начните:
- Возвращать
new List<T>()
- Возвращать
Enumerable.Empty<T>()
- Возвращать
[]
(фича C# 12 — collection expression)Так пишется безопасный, чистый и читаемый код
Пусть остальные продолжают тонуть в проверках на
null
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🕊7❤5🐳1
Джуниор должен знать 4 паттерна
Мидл — уже 12
Сеньор — около 20
Паттерны проектирования помогают решать типовые задачи и прокачивают качество кода, если использовать их с умом
Задумывался, на какие паттерны стоит делать упор, когда растешь как разработчик?
Это реально разница между «писать неплохой код» и «строить крутое ПО»
Тебе не нужно сразу выучить всё.
Сконцентрируйся на базовых паттернах, которые встречаются повсюду
> Builder
> Factory Method
> Singleton
> Decorator
Эти четыре паттерна помогут эффективно создавать, организовывать и расширять объекты.
Освоишь их — с первого дня начнешь писать чище и гибче
Готов прокачаться дальше
Пора добавить в свой арсенал более универсальные инструменты
> Strategy
> Adapter
> Abstract Factory
> Template Method
> Facade
> Bridge
> Command
> Mediator
Они научат подменять поведение на лету, упрощать сложные системы и писать более модульный код
Базу ты уже знаешь.
Теперь можно разбираться с паттернами, которые решают самые жёсткие архитектурные задачи
> Prototype
> Composite
> Chain of Responsibility
> State
> Flyweight
> Proxy
> Visitor
> Interpreter
Эти штуки дают тебе суперсилы для работы со сложными структурами, динамическим поведением и оптимизацией ресурсов.
Чем крупнее задачи, тем чаще они будут попадаться
Не пытайся выучить всё за раз
Иди по порядку — сначала базу, потом средний уровень, потом продвинутые паттерны
Кстати, а у тебя какой паттерн дольше всего не заходил, и как ты в итоге его понял?
Please open Telegram to view this post
VIEW IN TELEGRAM
🤨15❤12👍6😁2🤣1
Паттерн Options в .NET — это одна из тех фич, которые я стабильно использую во всех своих C#-проектах
✅ Более чистое управление конфигами
✅ Сильно типизированные классы
✅ Простая интеграция с DI
✅ Без проблем работает с
Почему это важно
Вместо того чтобы раскидывать значения конфигов по всему коду, ты централизуешь их в структурированных классах. Это не только улучшает читаемость, но и делает код более тестируемым и удобным в сопровождении.
Обычно это выглядит так
🔹 Определяешь конфиг в
🔹 Создаёшь POCO-класс
🔹 Биндишь его через
🔹 Инжектишь в сервисы через
Просто. Масштабируемо. Аккуратно.
А ты используешь этот паттерн у себя или до сих пор дёргаешь значения конфигов через😃
👉 @KodBlog
appsettings.json
, secrets.json
, Azure Key Vault и прочим Почему это важно
Вместо того чтобы раскидывать значения конфигов по всему коду, ты централизуешь их в структурированных классах. Это не только улучшает читаемость, но и делает код более тестируемым и удобным в сопровождении.
Обычно это выглядит так
appsettings.json
.AddOptions<T>().BindConfiguration()
IOptions<T>
Просто. Масштабируемо. Аккуратно.
А ты используешь этот паттерн у себя или до сих пор дёргаешь значения конфигов через
IConfiguration["key"]
Please open Telegram to view this post
VIEW IN TELEGRAM
❤26👍6🍓3👨💻1
В любом проекте важен контекст задачи.
Поэтому в моей архитектуре используется:
Подход с организацией по фичам
Классическая структура кода обычно строится вокруг технических паттернов:
- Command
- Queries
- Events
Из-за этого возникает серьёзная проблема — по коду непонятно, чем реально занимается приложение.
Подход с организацией по фичам полностью меняет эту логику.
Приложение структурируется вокруг бизнес-возможностей и фич.
Цель простая — проект должен «кричать» о своём назначении:
- Пользователи
- Заказы
- Продукты
Почему такая трансформация важна?
1. Высокая связанность внутри фич.
2. Низкая связанность между фичами.
3. Архитектура сама документирует себя.
4. Логичная и удобная навигация по проекту.
А что выберешь ты?🌟
👉 @KodBlog
Поэтому в моей архитектуре используется:
Подход с организацией по фичам
Классическая структура кода обычно строится вокруг технических паттернов:
- Command
- Queries
- Events
Из-за этого возникает серьёзная проблема — по коду непонятно, чем реально занимается приложение.
Подход с организацией по фичам полностью меняет эту логику.
Приложение структурируется вокруг бизнес-возможностей и фич.
Цель простая — проект должен «кричать» о своём назначении:
- Пользователи
- Заказы
- Продукты
Почему такая трансформация важна?
1. Высокая связанность внутри фич.
2. Низкая связанность между фичами.
3. Архитектура сама документирует себя.
4. Логичная и удобная навигация по проекту.
А что выберешь ты?
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6🔥2
This media is not supported in your browser
VIEW IN TELEGRAM
Это настоящий кладезь годных бесплатных инструментов для разработчиков.
Здесь есть всё: хостинг, базы данных, CDN, API, домены и куча других полезностей. Всё аккуратно разделено по категориям, что помогает легко находить нужное
https://free-for.dev/#/
👉 @KodBlog
Здесь есть всё: хостинг, базы данных, CDN, API, домены и куча других полезностей. Всё аккуратно разделено по категориям, что помогает легко находить нужное
https://free-for.dev/#/
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6
Запуск .NET в браузере без Blazor
https://andrewlock.net/running-dotnet-in-the-browser-without-blazor/
В этой статье автор показывает, как запустить .NET в браузере без использования Blazor, а вместо этого опереться на более низкоуровневые абстракции, которые предоставляют [JSImport] и [JSExport].
👉 @KodBlog
https://andrewlock.net/running-dotnet-in-the-browser-without-blazor/
В этой статье автор показывает, как запустить .NET в браузере без использования Blazor, а вместо этого опереться на более низкоуровневые абстракции, которые предоставляют [JSImport] и [JSExport].
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10❤5👍2
В .NET долгое время одним из самых удобных инструментов для организации CQRS и разделения логики был MediatR, он помогал структурировать команды и запросы, разгружал API слой и снижал связанность кода. Многие проекты, особенно с архитектурой Vertical Slice, держались на нём годами.
Но в работе со сложными сценариями у MediatR есть нюанс. Из-за отвязки команд и обработчиков навигация по коду и отладка становятся менее очевидными, особенно когда один обработчик начинает вызывать другой.
Альтернатива, которая решает эти проблемы, — переход на простые ручные обработчики. Такой подход убирает лишнюю рефлексию и декораторы, упрощает трассировку, а IDE быстрее находит нужный участок кода.
Вот гайд как выстроить систему, где:
> Стартовая реализация использует MediatR, а затем заменяется на ручные обработчики
> Регистрация обработчиков происходит автоматически
> Уведомления обрабатываются без MediatR Notifications
> Общая функциональность (логирование, валидация, транзакции) подключается без лишней обвязки
В результате получается решение с теми же преимуществами в архитектуре, но с более прямым и прозрачным кодом, что особенно полезно для крупных и долгоживущих проектов.
👉 @KodBlog
Но в работе со сложными сценариями у MediatR есть нюанс. Из-за отвязки команд и обработчиков навигация по коду и отладка становятся менее очевидными, особенно когда один обработчик начинает вызывать другой.
Альтернатива, которая решает эти проблемы, — переход на простые ручные обработчики. Такой подход убирает лишнюю рефлексию и декораторы, упрощает трассировку, а IDE быстрее находит нужный участок кода.
Вот гайд как выстроить систему, где:
> Стартовая реализация использует MediatR, а затем заменяется на ручные обработчики
> Регистрация обработчиков происходит автоматически
> Уведомления обрабатываются без MediatR Notifications
> Общая функциональность (логирование, валидация, транзакции) подключается без лишней обвязки
В результате получается решение с теми же преимуществами в архитектуре, но с более прямым и прозрачным кодом, что особенно полезно для крупных и долгоживущих проектов.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9❤6
image_2025-08-14_11-10-45.png
1.7 MB
Примеры middleware для ограничения частоты запросов в
1. Fixed Window Limiter (20 запросов за 2 минуты)
Фиксированное временное окно. После достижения лимита блокирует все запросы до конца текущего окна. Лимит сбрасывается каждые 2 минуты.
2. Sliding Window Limiter (20 запросов за 2 минуты, 4 сегмента)
Делит окно на сегменты (в примере 4 сегмента по 30 секунд). Когда открывается новый сегмент, самый старый истекает. Это распределяет нагрузку более равномерно и сглаживает трафик.
3. Token Bucket Limiter (15 токенов максимум, пополнение 1 токен/сек)
Позволяет кратковременные всплески нагрузки за счёт накопленных токенов. Каждый запрос расходует токен, при их нехватке запросы ограничиваются до восстановления токенов (по 1 в секунду).
4. Concurrency Limiter (5 параллельных запросов, 10 в очереди)
Ограничивает число одновременно обрабатываемых запросов (в примере до 5). Остальные попадают в очередь (до 10). Если очередь переполнена, новые запросы возвращают 503 или 429 (если переопределено).
В коде эти лимитеры регистрируются в
👉 @KodBlog
ASP .NET
1. Fixed Window Limiter (20 запросов за 2 минуты)
Фиксированное временное окно. После достижения лимита блокирует все запросы до конца текущего окна. Лимит сбрасывается каждые 2 минуты.
2. Sliding Window Limiter (20 запросов за 2 минуты, 4 сегмента)
Делит окно на сегменты (в примере 4 сегмента по 30 секунд). Когда открывается новый сегмент, самый старый истекает. Это распределяет нагрузку более равномерно и сглаживает трафик.
3. Token Bucket Limiter (15 токенов максимум, пополнение 1 токен/сек)
Позволяет кратковременные всплески нагрузки за счёт накопленных токенов. Каждый запрос расходует токен, при их нехватке запросы ограничиваются до восстановления токенов (по 1 в секунду).
4. Concurrency Limiter (5 параллельных запросов, 10 в очереди)
Ограничивает число одновременно обрабатываемых запросов (в примере до 5). Остальные попадают в очередь (до 10). Если очередь переполнена, новые запросы возвращают 503 или 429 (если переопределено).
В коде эти лимитеры регистрируются в
AddRateLimiter()
и привязываются к конкретным эндпоинтам через .RequireRateLimiting()
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9👏3❤2🔥1
Как находить медленные запросы в Entity Framework
Используя систему перехватчиков Entity Framework и подключаясь к событию
Сохрани в закладки🧀
Как это работает
1. Создаём класс перехватчика, наследуемся от
2. Регистрируем этот перехватчик в контексте через
👉 @KodBlog
Используя систему перехватчиков Entity Framework и подключаясь к событию
ReaderExecuted
мы можем видеть сколько времени реально занимают запросыСохрани в закладки
public class SlowQueryInterceptor : DbCommandInterceptor
{
private const int _slowQueryThreshold = 200; // миллисекунды
public override DbDataReader ReaderExecuted(
DbCommand command,
CommandExecutedEventData eventData,
DbDataReader result)
{
if (eventData.Duration.TotalMilliseconds > _slowQueryThreshold)
{
// Логируем медленный запрос — тут можно вставить свою систему логирования
Console.WriteLine(
$"Slow query ({eventData.Duration.TotalMilliseconds} ms): {command.CommandText}");
}
return base.ReaderExecuted(command, eventData, result);
}
}
public class YourDbContext : DbContext
{
// ... твои DbSet ...
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlServer("YourConnectionString") // замени на свою строку подключения
.AddInterceptors(new SlowQueryInterceptor());
}
}
Как это работает
1. Создаём класс перехватчика, наследуемся от
DbCommandInterceptor
и реализуем метод ReaderExecuted
2. Регистрируем этот перехватчик в контексте через
AddInterceptors
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19❤1
Изоляция данных в модульном монолите
- Схема и роль на модуль — для каждого модуля создаётся собственная схема и роль
- Привилегии только для своей схемы — модуль не имеет доступа к данным других схем
- Отдельный DbContext + схема по умолчанию — разделение кода и данных на уровне ORM
- Разные строки подключения и миграции — независимое управление конфигурацией и развёртыванием
- Read-only представления для межмодульных запросов — безопасный доступ к данным между модулями
Смотрите пошаговое руководство: ссылка
👉 @KodBlog
- Схема и роль на модуль — для каждого модуля создаётся собственная схема и роль
- Привилегии только для своей схемы — модуль не имеет доступа к данным других схем
- Отдельный DbContext + схема по умолчанию — разделение кода и данных на уровне ORM
- Разные строки подключения и миграции — независимое управление конфигурацией и развёртыванием
- Read-only представления для межмодульных запросов — безопасный доступ к данным между модулями
Смотрите пошаговое руководство: ссылка
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5
Сохрани этот пост
Покажу репозиторий на GitHub, где есть 99% кода, который тебе нужен для разработки
485 примеров кода .NET в одном месте🙏
Репозиторий называется:
practical-aspnetcore — https://github.com/dodyg/practical-aspnetcore
В одном месте собрано 485 практических примеров, чтобы ты мог понять и эффективно внедрить ключевые возможности ASP .NET Core
Что покрыто:
Это, по сути, швейцарский нож для .NET - инструменты почти для любой ситуации
👉 @KodBlog
Покажу репозиторий на GitHub, где есть 99% кода, который тебе нужен для разработки
485 примеров кода .NET в одном месте
Репозиторий называется:
practical-aspnetcore — https://github.com/dodyg/practical-aspnetcore
В одном месте собрано 485 практических примеров, чтобы ты мог понять и эффективно внедрить ключевые возможности ASP .NET Core
Что покрыто:
Authentication
Blazor
Caching
gRPC
HealthCheck
Localization
Logging
Middleware
Minimal API
Open Telemetry
Routing
SignalR
Security
YARP
Это, по сути, швейцарский нож для .NET - инструменты почти для любой ситуации
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15❤4🔥4😁1
Что такое RBAC и как это помогает с авторизацией
RBAC расшифровывается как Role-Based Access Control, то есть управление доступом на основе ролей
Суть простая
• У ролей есть набор разрешений
• Пользователи получают роли
• Разрешения определяют, что пользователи могут делать
Всё довольно просто, но при этом мощно
Хотя сами по себе роли могут быть слишком широкими
Поэтому я предпочитаю комбинировать роли с более точечными разрешениями.
Вместо того чтобы хардкодить правила доступа, я привязываю разрешения к конкретным действиям и уже потом связываю эти разрешения с ролями
Так проще управлять и легче расширять
Как смоделировать такой подход и применить его в .NET — читать
А как у тебя сейчас устроена авторизация в системе😏
👉 @KodBlog
RBAC расшифровывается как Role-Based Access Control, то есть управление доступом на основе ролей
Суть простая
• У ролей есть набор разрешений
• Пользователи получают роли
• Разрешения определяют, что пользователи могут делать
Всё довольно просто, но при этом мощно
Хотя сами по себе роли могут быть слишком широкими
Поэтому я предпочитаю комбинировать роли с более точечными разрешениями.
Вместо того чтобы хардкодить правила доступа, я привязываю разрешения к конкретным действиям и уже потом связываю эти разрешения с ролями
Так проще управлять и легче расширять
Как смоделировать такой подход и применить его в .NET — читать
А как у тебя сейчас устроена авторизация в системе
Please open Telegram to view this post
VIEW IN TELEGRAM
❤🔥3👍2❤1🔥1
Forwarded from Сазонов о Web
🤩 Nintendo Switch, оригинальный Labubu и Робот-доставщик на пульте управления: разыгрываем среди подписчиков!
Все что нужно сделать:
1. ПОДПИСАТЬСЯ на все каналы:
2. Нажать на кнопку «УЧАСТВУЮ» под постом
❗️ Победителя определим 22 августа в 19:00 мск на стриме! Итоги также появятся в телеграм-каналах.
Победителей выберем случайно с помощью бота. Важно быть подписанным на все каналы.
P.S. Все каналы по геймдеву
Please open Telegram to view this post
VIEW IN TELEGRAM
🤣7🤯2😐2🥴1
Я отучаюсь от всего, что знал про юнит-тестирование
Потому что большая часть этого — неправда
Для юнит-тестов нужен mocking-фреймворк
Юнит-тест должен покрывать один метод
С EF Core обязательно использовать Repository-паттерн для тестирования
Если всё это совместить, получаются хрупкие тесты, которые ничего не говорят о требованиях и вынуждают плодить ненужные слои
Вместо этого я придерживаюсь простых правил
• Использовать фейки вместо mocking-фреймворка
• Юнит-тесты проверяют поведение, а не структуру
• При работе с EF Core использовать in-memory или SQLite провайдер и обходить их ограничения через интеграционные тесты
Так тесты становятся менее хрупкими, покрывают больше кода и требуют меньше поддержки
Кто со мной?
👉 @KodBlog
Потому что большая часть этого — неправда
Для юнит-тестов нужен mocking-фреймворк
Юнит-тест должен покрывать один метод
С EF Core обязательно использовать Repository-паттерн для тестирования
Если всё это совместить, получаются хрупкие тесты, которые ничего не говорят о требованиях и вынуждают плодить ненужные слои
Вместо этого я придерживаюсь простых правил
• Использовать фейки вместо mocking-фреймворка
• Юнит-тесты проверяют поведение, а не структуру
• При работе с EF Core использовать in-memory или SQLite провайдер и обходить их ограничения через интеграционные тесты
Так тесты становятся менее хрупкими, покрывают больше кода и требуют меньше поддержки
Кто со мной?
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤3😁1🤔1
Предпочитай
1. Корректность (например, проблема с турецкой буквой
2. Читаемость
3. Производительность
👉 @KodBlog
string.Equals
вместо ToLower
/ ToUpper
для нечувствительных к регистру сравнений строк1. Корректность (например, проблема с турецкой буквой
i
)2. Читаемость
3. Производительность
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤2