.NET Разработчик
6.51K subscribers
427 photos
2 videos
14 files
2.04K links
Дневник сертифицированного .NET разработчика.

Для связи: @SBenzenko

Поддержать канал:
- https://boosty.to/netdeveloperdiary
- https://patreon.com/user?u=52551826
- https://pay.cloudtips.ru/p/70df3b3b
Download Telegram
День 1643. #PostgresTips
Советы по Postgres для Начинающих

2. Делайте EXPLAIN ANALYZE всегда с BUFFERS
Понимание того, как работает запрос, имеет решающее значение для оптимизации его производительности. В PostgreSQL команда EXPLAIN является основным инструментом для достижения этой цели. Однако для более детального разбора следует использовать EXPLAIN (ANALYZE, BUFFERS). И вот почему:
- EXPLAIN сам по себе предоставляет план запроса, давая вам представление об операциях, которые Postgres намеревается использовать для выборки или изменения данных: последовательное сканирование, сканирование индекса, объединение, сортировку и многое другое. Эту команду следует использовать исключительно для проверки плана запроса без выполнения.
- EXPLAIN ANALYZE не только показывает запланированные операции, но также выполняет запрос и предоставляет фактическую статистику времени выполнения. Это позволяет сравнивать, например, предполагаемые количества строк на каждом этапе с фактическими количествами, помогая определить, где Postgres может делать неточные предположения. Также ANALYZE предоставляет информацию о времени выполнения каждого этапа.
- EXPLAIN (ANALYZE, BUFFERS) предоставляет информацию об использовании буфера — в частности, сколько блоков попало в пул буферов или считано в него из базового кеша или диска. Это даёт ценную информацию о том, насколько интенсивен по дисковому чтению/записи ваш запрос, что может серьёзно сказаться на времени его выполнения. А если у вас задан параметр track_io_timing = on, вы получите информацию о времени выполнения для всех операций ввода-вывода.

3. Оптимальный выбор UI-инструментов: помимо pgAdmin
При изучении Postgres одним из первых вопросов, с которым вы столкнётесь, будет выбор клиента или IDE. Многие новички начинают с pgAdmin из-за его популярности и доступности. Но доступны более мощные и универсальные инструменты.

Одним из самых мощных клиентов для PostgreSQL является встроенный инструмент командной строки psql. Он содержит функции, обеспечивающие эффективное взаимодействие с базой данных, и вы найдёте его практически в любой системе, где установлен PostgreSQL.

Если вы больше склоняетесь к графическим IDE, есть несколько, которые предлагают баланс между удобством для пользователя и расширенными возможностями: DBeaver, DataGrip от JetBrains и Postico предоставляют сложные UI-интерфейсы с поддержкой выполнения запросов, визуализации данных и многого другого.

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

Источник: https://postgres.ai/blog/20230722-10-postgres-tips-for-beginners
👍14
День 1644. #ЧтоНовенького
JetBrains Представили Предиктивную Отладку
Меня иногда спрашивают, почему я рассказываю о новинках или инструментах Visual Studio, но редко пишу про Rider или ReSharper. Ответ прост: «Я пользуюсь Visual Studio и не могу достоверно оценить инструменты от JetBrains, поэтому не хочу писать о том, чего сам не пробовал». Однако об этой новинке очень захотелось рассказать, потому что, на мой взгляд, это очень круто.

С введением инструментов отладки разработчики ПО получили возможность интерактивно исследовать поток исполнения программ для поиска ошибок в реальных средах. Эти инструменты постоянно совершенствовались по мере того, как росла сложность создаваемого ПО. Тем не менее, разработчики часто оказываются в ситуации пошаговой отладки с множеством перезапусков и разбросанными по коду точками останова. Теперь в ReSharper 2023.2 появился предиктивный отладчик (в Rider появится позднее). Его можно включить в меню Tools > Debugger > Editor Integration > Predictive Debugger (Инструменты > Отладчик > Интеграция с Редактором > Предиктивный Отладчик), отметив флажок Show predicted values (beta) (Показывать прогнозируемые значения (бета)).

Простой пример предиктивной отладки (см. анимацию ниже)
Цвета дают представление о том, что происходит:
- Выражения, выделенные зелёным или красным цветом, означают, что выражение было оценено как истинное или ложное соответственно.
- Операторы, выделенные серым цветом, указывают на то, что этот путь кода не будет выполняться (подобно мертвому коду).
- Значения в конце строк, выделенные синим цветом, показывают прогнозируемые значения после выполнения соответствующего оператора.
- Жёлтые или красные подсказки показывают, где заканчивается предсказание; например, когда метод возвращает значение, выдаётся исключение (перехваченное или не перехваченное) или программа останавливается (Environment.Exit).

Прогноз также может заканчиваться вызовом функции, которую отладчик не решается оценить. Поскольку во время предиктивной отладки код исполняется, отладчик должен быть уверен, что он вызывает только чистые функции и не приводит к изменению состояния приложения. В анимации ниже такая функция int.TryParse (изменяет состояние локальной переменной), поэтому при отладке вам будет предложено явно разрешить выполнение оценки таких функций.

Также предполагается использование аннотаций (например, из JetBrains.Annotations) для тонкой настройки.

Будущие улучшения и ограничения
Планируется использовать внешние аннотации, чтобы пометить код, который будет разрешено оценивать, чтобы уменьшить количество возможных прерываний из-за нечистых вычислений. Например, объявить File.Exists или int.TryParse «чистыми» функциями.

К сожалению, код async/await не поддерживается, поскольку отладчик не допускает многопоточных вычислений.

Источник: https://blog.jetbrains.com/dotnet/2023/07/27/introducing-predictive-debugging-a-game-changing-look-into-the-future/
👍10
День 1645. #ЗаметкиНаПолях
Scrutor в .NET
Сегодня рассмотрим библиотеку Scrutor, варианты её использования и что она предлагает для упрощения внедрения зависимостей, а также о реализации сквозных задач с использованием шаблона декоратора.

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

Использование Scrutor для сканирования сборки
Scrutor помогает упростить наш код внедрения зависимостей за счёт динамического поиска типов внутри сборок и их регистрации во время выполнения. Используя сканирование сборки, мы можем частично автоматизировать наш код регистрации зависимостей. Кроме того, мы можем использовать сканирование сборки для создания расширяемых систем. С помощью сканирования мы можем создать программу, способную находить и загружать дополнительные модули во время выполнения.
builder.Services.Scan(s => s
.FromCallingAssembly()
.AddClasses(c =>
с.InNamespaces("MyApp.Services"))
.AsImplementedInterfaces()
);

Здесь мы вызываем метод расширения Scan() который выполнит сканирование сборки (в данном случае - той, из которой он вызван) и выберет сервисы для регистрации на основе предоставленного нами селектора (в данном случае из пространства имён "MyApp.Services"). Наконец, мы регистрируем выбранные нами типы в качестве подстановки для всех интерфейсов, которые они реализуют, вызывая AsImplementedInterfaces(), т.к. обычно наши зависимости представляют собой интерфейсы (типа IUserService), а не классы напрямую.

Используя широкий спектр методов расширения, которые предоставляет Scrutor, мы можем очень точно определить сервисы, которые мы хотим зарегистрировать, например, из другой сборки (библиотеки классов):
builder.Services.Scan(s => s
.FromAssemblyOf<ICustomerService>()
.AddClasses(c =>
c.AssignableTo<ICustomerService>())
.AsMatchingInterface());

Здесь мы просим Scrutor сканировать сборку, в которой находится интерфейс ICustomerService, используя метод расширения FromAssemblyOf<ICustomerService>(). Затем среди всех реализаций в этой сборке мы выбираем только те, которые могут быть назначены ICustomerService.

Работа с обобщёнными типами
Если мы хотим добавить реализацию обобщённого типа, то вместо обобщённой реализации метода AssignableTo, мы можем использовать метод с аргументом типа:

.AddClasses(c =>
c.AssignableTo(typeof(IService<>)))


Указание времени жизни зависимостей
Мы можем использовать спецификаторы времени жизни зависимостей:
builder.Services.Scan(s => s

.WithTransientLifetime()
);
Или соответственно WithScopedLifetime() и WithSingletonLifetime().

Обработка нескольких реализаций
Стратегия регистрации — это то, как Scrutor обрабатывает случаи, когда для одного и того же интерфейса существует несколько реализаций:
builder.Services.Scan(s => s

.UsingRegistrationStrategy(RegistrationStrategy.Skip)
.AsImplementedInterfaces()
);
В этом коде, используя метод UsingRegistrationStrategy() с параметром RegistrationStrategy.Skip, мы указываем Scrutor игнорировать дополнительные реализации любого интерфейса после регистрации первой. Другие варианты:
- RegistrationStrategy.Append - добавляет новую регистрацию для существующих сервисов.
- RegistrationStrategy.Throw - выдаёт ошибку при попытке зарегистрировать существующий сервис.

Окончание следует…

Источник:
https://code-maze.com/dotnet-dependency-injection-with-scrutor/
👍17
День 1646. #ЗаметкиНаПолях
Scrutor в .NET. Окончание
Начало

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

Реализация простого декоратора
Мы можем использовать метод расширения Decorate() для управления регистрацией объектов-декораторов. Определим декоратор для репозитория, который делает запись в консоль, когда мы обращаемся к списку сущностей.

Для этого нам нужно наследоваться от того же интерфейса, который реализует репозиторий:
public class RepositoryLoggerDecorator<T> : IRepository<T>
{
private readonly IRepository<T> _decoratedRepo;
public RepositoryLoggerDecorator(
IRepository<T> decoratedRepo)
{
_decoratedRepo = decoratedRepo;
}
public IEnumerable<T> GetAll()
{
Console.WriteLine("Retrieved list of users");
return _decoratedRepo.GetAll();
}
}

Декоратор должен принимать в конструкторе экземпляр декорируемого репозитория, в нашем случае это экземпляр IRepository<T>, который мы будем оборачивать. В методе GetAll() мы записываем сообщение в консоль, а затем вызываем метод GetAll() обёрнутого объекта.

Регистрация декораторов в Scrutor
Для регистрации декоратора в контейнере зависимостей в Scrutor используется метод расширения Decorate<,>():
builder.Services
.Decorate<IRepository<User>,
RepositoryLoggerDecorator<User>>();

Первый аргумент типа метода Decorate<,>() представляет тип сервиса, который мы хотим декорировать, а второй аргумент типа — это тип декоратора.

После того, как мы зарегистрируем декоратор в Scrutor, все вызовы методов IRepository<User> будут перехвачены RepositoryLoggingDecorator<User>.

Замечание: В этом примере мы использовали метод Console.WriteLine() для ведения журнала, в реальном же сценарии мы бы использовали ILogger<T> и фреймворк журналирования.

Источник:
https://code-maze.com/dotnet-dependency-injection-with-scrutor/
👍7
День 1647. #ВопросыНаСобеседовании
Самые часто задаваемые вопросы на собеседовании по C#
Давненько не было ничего из этой рубрики. Нумерацию продолжу, если что, предыдущие вопросы доступны по тегу #ВопросыНаСобеседовании.

19. В чем разница между интерфейсами IEnumerable, ICollection и IList в C#?
IEnumerable, ICollection и IList — это интерфейсы, предоставляемые библиотеками платформы .NET для работы с коллекциями данных. Они имеют следующие особенности.

IEnumerable:
- Предоставляет базовые функции для итерации по коллекции с использованием цикла foreach.
- Поддерживает доступ только для чтения.
- Идеально подходит для ситуаций, когда вам нужно только перебирать коллекцию.
- Определяет только один метод: GetEnumerator(), который возвращает IEnumerator.

ICollection:
- Наследуется от IEnumerable.
- Представляет собой группу элементов с дополнительными функциями, такими как размер (свойство Count), перечисление и синхронизация (через свойства IsSynchronized и SyncRoot).
- Добавляет основные операции с коллекцией, такие как Add, Remove, Clear, проверку вхождения элемента (Contains) или проверку списка на доступность записи IsReadOnly.
- Поддерживает доступ как для чтения, так и для записи.

IList:
- Наследуется от ICollection.
- Представляет список элементов, доступных по индексу.
- Предоставляет расширенные возможности управления коллекцией, такие как вставка и удаление по индексу (методы Insert и RemoveAt).
- Поддерживает произвольный доступ к элементам через индексатор.

См. также
- «В чём разница между IEnumerable и IQueryable?»
- «Какой Интерфейс Коллекции Использовать?»

Источник: https://dev.to/bytehide/20-c-interview-questions-for-experienced-2023-1hl6
👍25
День 1648.
Сегодня порекомендую вам один из лучших, на мой взгляд, докладов DotNext Autumn 2022 (почти год ждал, когда его выложат в открытый доступ). Роман Неволин «Пишем приложения, которые не ломаются в продакшене»

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

Об этом и пойдет речь:
1. О написании кода, который уменьшает вероятность ошибки
- Уменьшайте шансы пропустить валидацию и прочее
- Делайте модели настолько точными, насколько можете
- Отделяйте внешние данные от бизнесовых моделей
- Отделяйте бизнес-логику от всего остального

2. О тестировании
- Вынесите общую инициализацию из теста
- Спрячьте конкретные инструменты и детали реализации
- Держите специфическую инициализацию в тесте, а не в файлах
- Воспроизводите реальное окружение

3 О деплое
- Автоматизируйте все проверки, какие можете
- Наблюдайте за всем, что происходит в приложении
- Пишите постмортемы (что случилось, почему, как исправить в будущем)
- Действительно делайте то, что написано в постмортеме

Роман разбирает, как на каждом из этапов разработки уменьшить вероятность возникновения багов, как отслеживать их в тестировании и что делать, если вы все-таки задеплоили некорректный код.
👍27
День 1649. #юмор
👍27
День 1650. #ЗаметкиНаПолях
Используем Дискриминатор в Entity Framework
Допустим вы создаёте систему управления школой, в которой есть разные типы сотрудников Учитель и Администратор. Они имеют как общие свойства (Id, Имя, Дата найма), так и уникальные (например, Предмет у учителя и Отдел у администратора).
public class Staff
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime HireDate { get; set; }
}

public class Teacher : Staff
{
public string Subject { get; set; }
}
public class Administrator : Staff
{
public string Department { get; set; }
}

Если вы хотите получить всех сотрудников, вам нужно сделать отдельные свойства контекста и запросы для учителей и администраторов:
var teachers = context.Teachers.ToList();
var admins = context.Administrators.ToList();

Это требует не только больше кода, но и ручного управления этими отношениями. Для общих операций придётся дважды написать один и тот же код для учителей и администраторов. Также может быть сложнее поддерживать согласованность данных, особенно если в будущем появится больше типов сотрудников.

Столбец-дискриминатор в используется в сценариях наследования Table-per-Hierarchy, для представления отношений наследования в реляционной БД. Он предполагает использование одной таблицы для представления всех различных типов в иерархии со специальным столбцом (дискриминатор) для различения типов.
public class SchoolContext : DbContext
{
public DbSet<Staff> StaffMembers { get; set; }

protected override void OnModelCreating(ModelBuilder mb)
{
mb.Entity<Staff>()
.HasDiscriminator<string>("StaffType")
.HasValue<Teacher>("Teacher")
.HasValue<Administrator>("Administrator");
}
}
В методе OnModelCreating мы вызываем HasDiscriminator для настройки столбца-дискриминатора, задавая ему имя (StaffType) и тип. Метод HasValue позволяет указать, какие значения следует использовать для представления каждого типа в иерархии.

Теперь в запросах StaffMembers EF Core будет использовать столбец-дискриминатор для правильного создания экземпляров Teacher или Administrator в зависимости от ситуации.
var staff = context.StaffMembers.ToList();
foreach (var s in staff)
{
switch (s)
{
case Teacher t:

case Administrator a:

}
}
Также можно добавлять экземпляры этих классов, и EF Core автоматически задаст нужное значение дискриминатора при вставке строки в БД.

Преимущества
1. Простота. Одна таблица для всей иерархии может упростить понимание и поддержку схемы БД.
2. Повторное использование кода. Общие операции для всех типов используют один и тот же код.
3. Производительность. Часто можно получить данные с меньшим числом обращений к БД.

Недостатки
1. Неиспользуемое пространство. В одной таблице должны быть столбцы для всех свойств всех типов в иерархии, даже если некоторые типы не используют определенные свойства.
2. Ограниченная гибкость. Подход может стать сложным, если у вас сложная иерархия наследования или если нужно смоделировать отношения «многие-ко-многим» между различными типами.
3. Целостность данных. С одной таблицей сложнее обеспечить целостность данных на уровне БД. Например, вы не можете запретить строке, которая должна представлять учителя, иметь значение в столбце «Отдел» (который должен быть специфичным для администраторов).

Источник: https://stefandjokic.tech/blog/
👍9
День 1651. #ЗаметкиНаПолях
Флаги функций в
ASP.NET Core. Начало
Возможность включать или отключать функции в приложениях без повторного развёртывания кода — мощный инструмент, который можно использовать для быстрой итерации новых функций.

Флаги функций — это метод разработки ПО, который позволяет заключать функции приложения в условный блок, предоставляя переключатель для включения или отключения функции. Главное – возможность переключать функции во время выполнения, т.е. не нужно повторно развёртывать приложение.

Преимущества
1. Возможность развёртывать новые функции в производственных средах в отключённом состоянии. Так мы можем гарантировать, что наша новая функция не повлияет на остальную часть приложения, прежде чем мы включим её для всех пользователей.
2. Канареечное развёртывание — возможность постепенно увеличивать использование новой функции, чтобы гарантировать отсутствие последствий для производительности или каких-либо других ошибок в коде.
3. A/B-тестирование — определение реакции пользователей на новую функцию. Например, новый UI предоставляется только определённой группе пользователей, чтобы увидеть, предпочтут ли они его старому UI.

Виды
1. Логический фильтр – функция включена/выключена.
2. Фильтр по времени - функция активна только между заданным временем начала и окончания.
3. Процентный фильтр - процент определяет вероятность того, что функция включена.
4. Фильтр таргетинга - определяет правила включения функций на основе целевой аудитории.
5. Собственные настраиваемые фильтры.

Использование флагов функций в ASP.NET Core
Для начала добавим пакет Microsoft.FeatureManagement.AspNetCore. Он под капотом управляет жизненным циклом флагов функций. Это даёт нам возможность изменять флаги функций во время выполнения без необходимости перезапуска приложения.

1. Логический фильтр
Добавим фильтр функций в appsettings.json:
{
"FeatureManagement": {
"BoolFeature": true
}
}
NuGet пакет будет по умолчанию искать секцию FeatureManagement. Мы добавили фильтр функции BoolFeature и задали ему значение «включено».

Добавим FeatureManagment в классе Program:
builder.Services.AddFeatureManagement();

Проверим, как это работает:
public class FeatureController : ControllerBase
{
private IFeatureManager featureMgr;
public FeatureController(IFeatureManager fm)
{
featureMgr = fm;
}

public async Task<IActionResult> BoolFeature()
{
if (await featureMgr.IsEnabledAsync("BoolFeature"))
return Ok("Enabled");
else
return BadRequest("Disabled");
}
}

Если перейти на /Feature/BoolFeature, мы увидим результат Ok. Теперь, пока приложение работает, изменим значение BoolFeature на false и повторим запрос. На этот раз мы получим 400 BadRequest.

Продолжение следует…

Источник:
https://code-maze.com/aspnetcore-feature-flags/
👍25👎1
День 1652. #ЗаметкиНаПолях
Флаги функций в
ASP.NET Core. Продолжение
Начало

2. Фильтр по времени
Если мы хотим, чтобы функция была включена только в течение определённого временного окна, используем TimeWindowFilter.
Сначала зарегистрируем фильтр:
builder.Services.AddFeatureManagement()
.AddFeatureFilter<TimeWindowFilter>();

В appsettings.json, определим конфигурацию:
"FeatureManagement": {
// …
"TimeFeature": {
"EnabledFor": [
{
"Name": "TimeWindow",
"Parameters": {
"Start": "2023-08-09T09:00:00+03:00",
"End": "2023-08-24T11:00:00+03:00"
}
}
]
}
}
Функция TimeFeature будет включена с 09:00 (Мск) 09.08.2023 до 11:00 (Мск) 24.08.2023. Проверка работы функции аналогична логическому фильтру.

3. Процентный фильтр
Аналогично фильтру по времени, нужно добавить его в сервисы:
 ….AddFeatureFilter<PercentageFilter>();
И в appsettings.json:
"FeatureManagement": {
"PercentFeature": {
"EnabledFor": [
{
"Name": "Percentage",
"Parameters": {
"Value": 50
}
}
]
}
}
Эта функция будет «включена» в 50% случаев.

4. Фильтр таргетинга
Фильтры таргетинга позволяют включить функцию для определённых пользователей или групп. Как обычно, нам нужно зарегистрировать фильтр таргетинга:
….AddFeatureFilter<TargetingFilter>();
И добавить настройку в appsettings.json:
"FeatureManagement": {
"TargetFeature": {
"EnabledFor": [
{
"Name": "Targeting",
"Parameters": {
"Audience": {
"Users": [],
"Groups": [
{
"Name": "Beta Testers",
"RolloutPercentage": 20
}
]
}
}
}
]
}
}
Здесь функция TargetFeature будет доступна для 20% пользователей из группы "Beta Testers". В Users можно задать список Id отдельных пользователей.

Также мы должны добавить логику определения аудитории. Для этого нужно создать сервис реализующий интерфейс ITargetingContextAccessor и зарегистрировать его в DI.
Интерфейс содержит один метод GetContextAsync(), возвращающий ValueTask<TargetingContext>. TargetingContext, в свою очередь, содержит свойства:
- UserId (строка) – сопоставляется со списком Users в appsettings,
- Groups (коллекция строк) – сопоставляется со списком Groups.
Для определения Id или группы для текущего пользователя, в сервис, реализующий ITargetingContextAccessor, можно внедрить IHttpContextAccessor (об этом завтра).

Продолжение следует…

Источник:
https://code-maze.com/aspnetcore-feature-flags/
👍8
День 1653.
MOQ-Гейт или Закрытый-Открытый Код

🔥 BRKNG!!!
🔥

Мы прерываем нашу программу… Короче, не мог пройти мимо. Вчера в интернетах разгорелся нешуточный срач вокруг популярнейшего пакета для создания фиктивных объектов в тестах Moq.

Один из пользователей Reddit написал следующий пост:
Я только что обновил Moq в одном из наших проектов и после сборки получил предупреждение о том, что я не установил приложение GitHub Sponsors.
После небольшого расследования выяснилось, что Moq, начиная с версии 4.20, включает в себя анализатор .NET, который сканирует вашу локальную конфигурацию git при сборке, получает ваш email и отправляет его в какой-то сервис в Azure, чтобы проверить, действительно ли вы спонсор.

Потом в GitHub проекта появилась новая ишью:
Похоже, начиная с версии 4.20 в проект добавлена зависимость SponsorLink. Это проект с закрытым кодом, представленный в виде dll с обфусцированным кодом (sic!), который, кажется, сканирует локальные данные (git config?) и отправляет хешированный адрес электронной почты текущего разработчика в облачный сервис. Сканирование предоставляется как инструмент анализатора .NET, который запускается во время сборки. Нет возможности его отключить.
Я могу понять причину этого, но, честно говоря, это довольно страшно с точки зрения конфиденциальности.

Насколько я понял, суть в следующем.
Спонсорство – это фича гитхаба по поддержке разработчиков проектов с открытым кодом. SponsorLink – отдельный пакет от разработчика Moq, работающий как анализатор кода в IDE и проверяющий при сборке проекта, являетесь ли вы спонсором используемого вами пакета с открытым кодом. Если нет, он выдаёт предупреждение компилятора с предложением стать спонсором и ссылкой на спонсорство. Если да, выдаётся благодарственное сообщение. При использовании в терминале или CI/CD, он не делает ничего, таким образом не мешая процессу.

Автор утверждает, что опросил знакомых разработчиков, и идею поддержали, однако лично у меня возникают вопросы по поводу того, так ли это надо. Если в теории за спонсорство анализатор будет «открывать» какие-то новые фишки в пакете (видимо, такая и была задумка на будущее). Впрочем, я отвлёкся.

Однако, как обычно, благими намерениями. Реализация этой проверки спонсорства, собственно, и вызвала бурление. Анализатор (без предупреждения) запускает фоновый процесс, который сканирует параметры вашего git репозитория, находит там email пользователя (по другим данным – все email адреса из истории проекта) и отправляет его по сети в облачный сервис для проверки спонсорства. Вот тут вопросов гораздо больше. В первую очередь это нарушает некоторые законы о защите персональных данных, ведь всё это происходит без согласия и даже без уведомления пользователя. Во-вторых, что там реально происходит, и действительно ли отправляется только email и туда ли, куда говорит автор, посмотреть нельзя, т.к. код самого SponsorLink закрыт. В-третьих, email в настройках git может быть корпоративным и не для публичного распространения. В-четвёртых, даже запретить пакету это делать нельзя.

В общем, получить такую интересную закрытую зависимость, просто обновив широко известный пакет «с открытым исходным кодом» - то ещё удовольствие. Автору справедливо накидали полную панамку… ишьюсов и репортов в NuGet, и проблемная версия Moq 4.20.1 была удалена из репозитория NuGet. Вместо неё вчера появилась версия 4.20.2, в которой заявлено, что ссылка на зависимость от SponsorLink была удалена.

Можете также посмотреть, как Ник Чапсас довольно смешно бомбит с этого.

Источник: https://www.reddit.com/r/dotnet/comments/15ljdcc/does_moq_in_its_latest_version_extract_and_send/
👍32
День 1654. #ЗаметкиНаПолях
Флаги функций в
ASP.NET Core. Продолжение 2
Начало
Продолжение 1

5. Собственные фильтры
Если встроенных фильтров функций недостаточно, у нас есть возможность написать собственные фильтры, реализовав IFeatureFilter. Создадим фильтр, позволяющий использовать функцию только клиентам, у которых установлен определённый язык:
"FeatureManagement": {
"LangFeature": {
"EnabledFor": [
{
"Name": "LangFilter",
"Parameters": {
"AllowedLangs": [
"en-US", "ru-RU"
]
}
}
]
}
}

Мы определяем функцию LangFeature и фильтр LangFilter для неё, добавляя в параметры массив AllowedLangs с языками, для которых функция включена.

Создадим LangFilter:
[FilterAlias(nameof(LangFilter))]
public class LangFilter : IFeatureFilter
{
private IHttpContextAccessor _hCA;
public LangFilter(IHttpContextAccessor hCA)
{
_hCA = hCA;
}
public Task<bool> EvaluateAsync(
FeatureFilterEvaluationContext ctx)
{
var userLang = _hCA
.HttpContext
.Request
.Headers["Accept-Language"]
.ToString();
var settings = ctx
.Parameters
.Get<LangFilterSettings>();

return Task.FromResult(
settings.AllowedLangs
.Any(a => userLang.Contains(a)));
}
}
Сначала внедряем IHttpContextAccessor. Это позволит нам получить доступ к заголовку Accept-Language из запроса пользователя.
Мы реализуем интерфейс IFeatureFilter, который даёт нам метод EvaluateAsync(). В этом методе мы проверяем язык пользователя по параметрам (settings), определённым в appsettings.json, и возвращаем true, если язык есть в списке. Параметры фильтра в строго типизированном виде нам помогает получить класс FeatureFilterEvaluationContext. Создадим простой класс LangFilterSettings для хранения массива AllowedLangs:
public class LangFilterSettings
{
public string[] AllowedLangs { get; set; }
}

Прежде чем протестировать наш фильтр, нужно зарегистрировать в сервисах его и HttpContextAccessor:
builder.Services.AddFeatureManagement()
.AddFeatureFilter<LangFilter>();
builder.Services.AddHttpContextAccessor();

Проверка аналогична проверке логического фильтра:
public async Task<IActionResult> LangFeature()
{
if (await featureMgr.IsEnabledAsync("LangFeature"))
return Ok("Enabled");
else
return BadRequest("Disabled");
}

Окончание следует…

Источник:
https://code-maze.com/aspnetcore-feature-flags/
👍8
День 1655. #ЗаметкиНаПолях
Флаги функций в
ASP.NET Core. Окончание
Начало
Продолжение 1
Продолжение 2

Другие способы проверки флагов функций
Интерфейс IFeatureManager и блок if-else - не единственный метод проверки флагов функций. Вот несколько других.

1. Атрибут FeatureGate
В ASP.NET Core есть возможность помечать конечные точки или контроллеры атрибутом флага функции FeatureGate:
[FeatureGate("BoolFeature")]
public IActionResult BoolFeature()
{ … }
Здесь конечная точка BoolFeature помечена атрибутом флага функции BoolFeature (имена не обязательно должны совпадать). Если функция отключена, при обращении к этой конечной точке мы получим 404 NotFound. Это код ответа по умолчанию, но поведение можно настроить, создав обработчик отключённых функций, реализующий IDisabledFeaturesHandler.
Кроме того, в атрибуте можно указывать несколько функций через запятую, а также задать, должны ли они быть включены все либо хотя бы одна с помощью перечисления RequirementType.

2. Промежуточное ПО
Если наша функция более сложная и затрагивает промежуточное ПО приложения, мы можем условно добавить её с помощью флагов функций:
app.UseMiddlewareForFeature<MyMiddlewareFeature>(
"MyMiddlewareFeatureFlag");

При этом MyMiddlewareFeature будет добавлена в конвейер только в том случае, если MyMiddlewareFeatureFlag включен.

3. Представления MVC
Если в приложении MVC нам нужно условно показать или скрыть фрагмент пользовательского интерфейса в зависимости от состояния флага функции, ASP.NET Core предоставляет для этого простой способ:
<feature name="MyUIFeature">
<p>Отображается, если MyUIFeature включена.</p>
</feature>
<feature name="MyUIFeature" negate="true">
<p>Отображается, если MyUIFeature отключена.</p>
</feature>
<feature name="FeatureA, FeatureB" requirement="All">
<p>Отображается, если обе функции включены.</p>
</feature>

Для этого надо добавить тэг-хелпер в файл _ViewImports.cshtml:
@addTagHelper *, Microsoft.FeatureManagement.AspNetCore

4. Azure App Configuration
Когда мы развёртываем приложение, использовать appsettings.json - не самый идеальный сценарий. Вместо этого мы можем использовать что-то вроде Azure App Configuration для независимого управления флагами функций. Это предпочтительно, поскольку нам предоставляется пользовательский интерфейс для управления функциями, и это означает, что не нужно вручную изменять файл appsettings.json приложения.

Источник: https://code-maze.com/aspnetcore-feature-flags/
👍9
DotNext 2023 — крупнейшая в России конференция для .NET-разработчиков

Вас ждут два дня офлайна и возможность подключиться к онлайн-трансляции. В программе — несколько десятков докладов о практике .NET-разработки, воркшоп и fail-митап, на котором спикеры расскажут о неудачах компаний — без записи и без комплексов.

Кроме этого, DotNext — это живые дискуссии, возможность познакомиться со спикерами и другими участниками, а также обсудить .NET-разработку и другие рабочие вопросы в неформальной обстановке.

Поскольку я решил посетить конференцию офлайн, разыграю среди желающих онлайн-билет. Условия простые: подписка на канал и комментарий "хочу билет" к этому посту.
Единственное условие - не просите ради прикола, а реально используйте (посмотрите хотя бы в записи).
Победителя выберу рандомом через несколько дней.
👍7
День 1656. #PostgresTips
Советы по Postgres для Начинающих

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

Что логировать
Ключ к эффективному ведению журнала — это знать, что записывать, не перегружая систему. Установив такие параметры, как
log_checkpoints = on,
log_autovacuum_min_duration = 0,
log_temp_files = 0,
log_lock_waits = on
вы получаете видимость контрольных точек, операций автоочистки, создания временных файлов и ожидания блокировки. Это некоторые из наиболее распространённых областей, в которых могут возникнуть проблемы, что делает их крайне важными для мониторинга.

Баланс между информативностью и избыточностью
Важно отметить, что, хотя детальное ведение журнала может предоставить ценную информацию, оно также может привести к накладным расходам. Это особенно верно, если вы установите log_min_duration_statement на очень низкое значение. Например, если установить его на 200мс, запрос будет логироваться дольше, чем выполняться, что может как повысить информативность, так и потенциально снизить производительность. Всегда будьте осторожны и помните об «эффекте наблюдателя» — влиянии процесса мониторинга на наблюдаемую систему. Но без детальной информации из журналов диагностика проблем была бы намного сложнее.

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

5. Улучшите наблюдаемость с помощью расширений
Когда вы стремитесь поддерживать производительность и работоспособность Postgres, расширения могут серьёзно помочь. Среди них pg_stat_statements выделяется как обязательный элемент, который не подлежит обсуждению.

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

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

- pg_wait_sampling или pgsentinel
Дают более чёткое представление о том, где запросы тратят время на ожидание, обеспечивая так называемый анализ событий ожидания, также известный как анализ истории активных сеансов.

- auto_explain
Автоматически регистрирует планы выполнения медленных операторов, что упрощает их понимание и оптимизацию.

Помните, что эти расширения требуют начальной установки и настройки, чтобы получить наилучшие результаты и снизить накладные расходы. И, к сожалению, большинство провайдеров Postgres не предоставляют pg_stat_kcache или pg_wait_sampling/pgsentinel.

Источник: https://postgres.ai/blog/20230722-10-postgres-tips-for-beginners
👍8
День 1657. #ЧтоНовенького
Улучшения Работы с Git в Visual Studio 2022 17.8 Превью 1
Вышла первая превью версия VS 17.8, в которую добавили пару интересных улучшений для работы с Git.

1. Добавление рецензентов в пул-реквесты
Теперь вы можете добавлять рецензентов в свои пул-реквесты в Visual Studio как для Azure DevOps, так и для GitHub.
Нажмите на ссылку Create a Pull Request (Создать Пул-Реквест), которая появляется после коммита или выберите Git > GitHub или Azure DevOps > New Pull Request в меню. Перейдите в раздел Reviewers (Рецензенты) и найдите рецензентов, которых вы хотите добавить.

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

Источник: https://devblogs.microsoft.com/visualstudio/visual-studio-2022-17-8-preview-1-has-arrived/
👍10👎1
День 1658. #ВопросыНаСобеседовании
Самые часто задаваемые вопросы на собеседовании по C#

20. Какие типы делегатов существуют в C#?

Делегаты в C# можно разделить на три основных типа:
1) Обычные
Ссылаются на один метод с соответствующей сигнатурой. Когда делегат вызывается, он вызывает указанный метод.
public delegate void DisplayMessage(string message);

DisplayMessage display = ShowMessage;
display("Hello, delegate!");

void ShowMessage(string message)
=> Console.WriteLine(message);

2) Многоадресные (Multicast)
Могут ссылаться на несколько методов с совпадающей сигнатурой. Когда делегат вызывается, он вызывает все указанные методы в том порядке, в котором они были добавлены. Многоадресные делегаты создаются из обычных с помощью операторов += или -=.
DisplayMessage display = ShowMessage1;
display += ShowMessage2;
display("Hello, Multicast delegate!");

void ShowMessage1(string msg)
=> Console.WriteLine($"Message 1: {msg}");
void ShowMessage2(string msg)
=> Console.WriteLine($"Message 2: {msg}");

3) Обобщённые
Используют параметры типа, что позволяет им работать с несколькими типами без приведения или упаковки/распаковки. C# предоставляет три встроенных обобщённых делегата: Func, Action и Predicate.
- Func<TResult>: представляет функцию с возвращаемым типом.
- Action: представляет метод, возвращающий void, без параметров.
- Predicate<T>: представляет метод, который принимает входной параметр и возвращает логическое значение.
Func и Action имеют перегрузки, принимающие большее количество аргументов.

Func<int, int, int> add = 
(x, y) => x + y;
int sum = add(10, 20);

Action<string> display =
msg => Console.WriteLine(msg);
display($"Sum: {sum}");

Predicate<string> startsWithHello =
x => x.StartsWith("Hello, ");
bool checkHello = startsWithHello("Hello, delegate");

См. также:
- Управление цепочками делегатов
- Анонимные методы
- Лямбда-выражения

Источник: https://dev.to/bytehide/20-c-interview-questions-for-experienced-2023-1hl6
👍28
День 1659. #МоиИнструменты
Веб-Инструменты для Каждого Разработчика
Сегодня поделюсь с вами подборкой веб-сайтов с инструментами, которые пригодятся каждому разработчику вне зависимости от области и языка программирования.

1. Transform.tools
Позволяет преобразовывать почти всё, например, HTML в JSX, JavaScript в JSON, CSS в объекты JS и многое другое. Действительно экономит время. К сожалению, отсутствует поддержка C#, поэтому JSON можно преобразовать разве что в объект Java, но с парочкой изменений руками (когда уже в Java человеческие свойства завезут?) потянет.

2. Convertio
Простой инструмент для конвертации файлов онлайн. Более 309 различных документов, изображений, электронных таблиц, электронных книг, архивов, презентаций, аудио и видео форматов. Например, PNG в JPEG, SVG в PNG, PNG в ICO и многие другие. Попробовал конвертнуть PDF книгу в DOCX. Очень даже неплохо. У бесплатной версии есть ограничение на общее время конвертации в день, но сколько это, я не нашёл. Думаю, для конвертации парочки файлов время от времени хватит.

3. Code Beautify
Онлайн версия программ Code Beautifier и Code Formatter, позволяющая форматировать исходный код. Но, кроме этого, также поддерживает некоторые преобразователи, такие как изображение в base64, CSV в Excel и т.п., минификаторы и обфускаторы кода для многих языков и много чего ещё.

4. Removebg
Мы программисты чаще всего плохо умеем в фотошоп, поэтому ловите инструмент, который позволяет легко удалить фон любого изображения. RemoveBG мгновенно определяет объект изображения и удаляет фон, оставляя изображение объекта на прозрачном фоне, которое вы можете легко использовать в своих проектах. Я попробовал его на паре фоток и должен отметить, что работает отлично. Потом результат можно перенести визуальный редактор canva.com и добавить фон, эффекты и даже создать видео.

5. ray.so
ray.so преобразует ваш фрагмент кода в визуально привлекательное изображение в пару кликов! Вы можете настроить иллюстрацию, выбрав из множества подсветок синтаксиса, добавить фон или выбрать тёмную или светлую тему. Это идеальный способ продемонстрировать свой код в посте или презентации по-настоящему стильно.

Источник: https://dev.to/j471n/top-10-websites-every-developer-needs-to-know-about-f5j
👍19👎1