.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
День 1547. #Microservices
12 Способов Улучшить Монолит Перед Переходом на Микросервисы. Окончание
Начало
Продолжение

10. Сделайте монолит модульным
Если ваш монолит представляет собой запутанный клубок кода, вы вполне можете получить запутанный клубок распределённого кода после завершения миграции. Подобно уборке дома перед капитальным ремонтом, модульность монолита является необходимым подготовительным этапом.
Модульный монолит — это паттерн разработки ПО, представляющий собой вертикально расположенные модули, независимые и взаимозаменяемые. Противоположностью является классический N-уровневый монолит, в коде которого слишком много зависимостей (иногда циклических), что затрудняет внесение изменений.
Модульный монолит — ступенька к микросервисам. Модули могут обмениваться данными только через общедоступные API и по умолчанию всё приватно. В результате код менее переплетён, отношения легко идентифицировать, а зависимости чётко очерчены.
Два паттерна могут помочь вам провести рефакторинг монолита:
1) Душитель
Проводится рефакторинг монолита от края к центру, постепенно переписывая отдельные функции, пока монолит не будет полностью переделан.
Подробнее о паттерне «Душитель».
2) Слой защиты от повреждений
Вы обнаружите, что в некоторых случаях изменения в одном модуле распространяются на другие по мере рефакторинга монолита. Чтобы бороться с этим, вы можете создать слой перевода между быстро меняющимися модулями. Этот слой защиты предотвращает влияние изменений в одном модуле на остальные.
Подробнее о паттерне «Слой защиты от повреждений».

11. Разделите данные
Сила микросервисов в возможности развёртывать любой микросервис в любое время практически без координации с другими микросервисами. Вот почему следует любой ценой избегать связывания данных, поскольку оно создаёт зависимости между сервисами. Каждый микросервис должен иметь отдельную и независимую базу данных.
Может быть шокирующим осознание того, что вам нужно денормализировать общую базу данных монолита на (часто избыточные) меньшие базы данных. Но локальность данных — это то, что в итоге позволит микросервисам работать автономно.
После разделения нужно будет установить механизмы для синхронизации старых и новых данных во время перехода. Вы можете, например, настроить сервис зеркалирования данных или изменить код, чтобы транзакции записывались в оба набора баз данных.

12. Улучшите наблюдение
Новая система должна быть быстрее, производительнее и масштабируемее, чем старая. Иначе зачем возиться с микросервисами? Нужен базовый уровень для сравнения старого с новым. Перед началом миграции убедитесь, что у вас есть хорошие метрики и журналы. Может быть хорошей идеей установить какую-нибудь централизованную службу ведения журналов и мониторинга, так как это ключевой компонент для наблюдения за любым микросервисным приложением.

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

Источник: https://semaphoreci.com/blog/monolith-microservices
👍9👎1
День 1548. #ЗаметкиНаПолях
Управление Контейнерами в .NET 7 SDK
В .NET SDK 7.0.200 представлена новая функция, которая позволяет создавать и публиковать образы контейнеров непосредственно из файла проекта.

Для этого в файл проекта надо добавить:
<EnableSdkContainerSupport>true</EnableSdkContainerSupport>

Теперь с помощью dotnet publish можно создавать и публиковать приложения .NET в виде образов Docker:
- Создавать образ Docker для приложения, не создавая Dockerfile.
- Публиковать образ в реестре контейнеров.
- Указывать переменные, такие как базовый образ, тег образа и имя реестра в файле проекта.

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

dotnet publish --os linux --arch x64 -p:PublishProfile=DefaultContainer -c Release

По умолчанию dotnet publish публикует образ в локальном демоне Docker. Чтобы опубликовать образ в реестре контейнеров, нужно добавить новое свойство в файл .csproj:
<ContainerRegistry>myregistry.azurecr.io</ContainerRegistry>

Другой, возможно более предпочтительный, вариант – не засорять файл проекта, а использовать профили публикации, файлы .pubxml в папке /Properties/PublishProfiles:
<Project>
<PropertyGroup>
<EnableSdkContainerSupport>true</EnableSdkContainerSupport>
<WebPublishMethod>Container</WebPublishMethod>
</PropertyGroup>
</Project>

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

.NET SDK был протестирован в следующих реестрах: Azure Container Registry, GitLab Container Registry, Google Cloud Artifact Registry, Quay.io, AWS Elastic Container Registry, GitHub Package Registry, and Docker Hub.

Перед публикацией потребуется пройти аутентификацию в реестре контейнеров. Подробнее об этом здесь.

Указание параметров контейнера
По умолчанию SDK определяет лучший базовый образ для использования. Он может использовать значения свойств вашего проекта, таких как TargetFramework, или проверять, является ли приложение автономным или приложением ASP.NET Core. Тем не менее, вы можете переопределить базовый образ по умолчанию, порт, имя контейнера, тэг и т.п.:
<ContainerBaseImage>mcr.microsoft.com/dotnet/aspnet:7.0</ContainerBaseImage>
<ContainerImageName>mycompany/my-awesome-webapp</ContainerImageName>
<ContainerImageTag>1.2.3-alpha2</ContainerImageTag>
<ItemGroup>
<ContainerPort Include="80" Type="tcp" />
</ItemGroup>

Про другие настройки контейнера можно почитать здесь.

Источник: https://laurentkempe.com/2023/03/13/dotnet-7-sdk-built-in-container-improvements/
👍17👎1
День 1549. #ЗаметкиНаПолях
Используем Группы Конечных Точек для Версионирования Минимальных API
В ASP.NET Core 7 значительно улучшены минимальные API, в частности добавлена функция групп конечных точек. Это способ объявить некоторую общую информацию о маршрутизации для нескольких конечных точек, а также добавить общие ограничения, такие как авторизация, правила CORS и т. д.

Группы конечных точек позволяют управлять версиями API. Просто добавляем базовый маршрут в метод MapGroup, например: MapGroup("/v1") или MapGroup("/v2").

ASP.NET Core 7 предоставляет класс RouteGroupBuilder для создания правил и группировки конечных точек. Создадим две группы конечных точек:
public static class MyGroups
{
public static RouteGroupBuilder
Group1(this RouteGroupBuilder g)
{
g.MapGet("/", () =>
Results.Ok(new List<int> { 1, 2, 3 }));
g.MapGet("/{id}", (int id) =>
Results.Ok(id));

return g;
}

public static RouteGroupBuilder
Group2(this RouteGroupBuilder g)
{
g.MapGet("/", () =>
Results.Ok(new List<int> { 4, 5, 6 }));
g.MapGet("/{id}", (int id) =>
Results.Ok(id + 1));

return g;
}
}

Для удобства мы сгруппировали конечные точки в отдельных методах расширения. Теперь добавим ограничения и базовый маршрут к каждой группе в основном файле Program.cs. Кроме того, для демонстрации различий добавим Swagger, установив NuGet пакет Microsoft.AspNetCore.OpenApi и добавив необходимые методы расширения:
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

app.UseSwagger();
app.UseSwaggerUI();

// Demo group endpoints
app.MapGroup("/v1")
.Group1()
.RequireCors("CorsPolicy1")
.AllowAnonymous()
.WithTags("v1");

app.MapGroup("/v2")
.Group2()
.RequireCors("CorsPolicy2")
.RequireAuthorization()
.RequireRateLimiting("LimitPolicy")
.WithTags("v2");

app.Run();

Как видите, к первой группе применена одна политика CORS, а ко второй группе — другая, а также правила авторизации и ограничения скорости https://t.iss.one/NetDeveloperDiary/1487. Также для удобства отображения в SwaggerUI каждой группе добавлены теги с помощью метода WithTags(…). Результат на картинке ниже.

Источник: https://anthonygiretti.com/2023/03/16/asp-net-core7-use-endpoint-groups-to-manage-minimal-apis-versioning/
👍14👎2
День 1550. #Карьера
Создание Асинхронной Рабочей Среды
«Вопросик к тебе…» — есть ли что-то более раздражающее, когда ты с головой погружён в отладку? А чтобы вернуться к сложной проблеме после того, как вас отвлекли, может потребоваться уйма времени.

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

Вероятно, самая распространенная причина – сотрудники в разных часовых поясах. Это даёт компаниям доступ к глобальному рынку кадров. Кроме того, сотрудники могут не только работать, когда им удобно, но и так, как они работают лучше всего. Люди счастливее, когда у них есть гибкость, а когда они счастливее, они более продуктивны. Менее очевидным преимуществом является запись почти каждого разговора.

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

Для менеджера наличие асинхронной команды означает, что нельзя полагаться на такие показатели, как количество отработанных часов. Нужно использовать метрики на основе результатов, которые побуждают членов команды работать более эффективно. Также невозможно сразу получить ответы на все свои вопросы. Вот ещё несколько достойных внимания вещей:
1. Навыки письма
Письмо занимает больше времени, чем речь, но оно помогает выразить мысль по-другому. У всех был момент озарения, пока мы печатали мысль, которая нас смущала.

2. Процессы документации
Вполне естественно, что часть письменных обсуждений превратится в документацию. Конечно, не вся документация пишется специально. Возможно записывать созвоны и встречи. Эти записи затем служат контекстом для людей, которые не смогли прийти.

3. Правильные инструменты
Есть несколько всем известных инструментов: Zoom, Slack, Google Docs и т. д. Но есть инструменты, которые особенно хорошо подходят для асинхронных команд. Например, Stack Overflow for Teams предоставляет командам место для совместной работы, где они могут задавать вопросы и отвечать на них, не прерывая друг друга в чатах реального времени.

Проблемы с асинхронной работой
1. Доверие является ключевым
Если сотрудникам разрешено работать, когда, где и как они хотят, вы должны им доверять. Некоторым менеджерам может быть трудно это принять. Но главное иметь меры по отслеживанию результатов. Одни отчитываются о своих часах еженедельно, другим платят по результатам. Это позволяет объективно сравнивать производительность.
Но сотрудники также должны уметь доверять друг другу. Если вы не можете доверять своим коллегам по команде или своим сотрудникам, асинхронная работа вам не подойдет.

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

3. Задачи реального времени
Некоторые задачи, вроде мозгового штурма, просто не подходят для асинхронной работы. Главное – честно объяснить новым сотрудникам, что без некоторой работы в реальном времени не обойтись.

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

Источник: https://stackoverflow.blog/2023/03/27/building-a-collaborative-asynchronous-work-environment/
👍20👎1
День 1551. #ЗаметкиНаПолях
Сокращаем Количество Обращений к Коллекциям
Многие проекты C# содержат множество мест, где разработчики добавляют элементы в коллекции, такие как HashSet и Dictionary. Довольно часто добавляют проверку, чтобы убедиться, находится ли элемент в коллекции. Однако это может быть довольно расточительно, так как методы Add() и TryAdd() в этих коллекциях уже выполняют эту проверку за вас. Посмотрим на некоторые примеры.

1. Работа с HashSet<T>
При написании кода с использованием HashSet<T> есть большая вероятность, что ваш код использует следующий шаблон: проверяет, существует ли элемент в наборе, и, если нет, добавляет его.
var person = new Person("Jon", "Smith");
if (!people.Contains(person))
people.Add(person);

Вам не нужно этого проверять. Если вы посмотрите на исходный код HashSet<T>, вы увидите, что и Constains(), и Add() проверяют, содержит ли набор элемент. Другими словами, вы выполняете одну и ту же операцию дважды.

2. Работа с Dictionary<TKey, TValue>
При работе с экземпляром Dictionary аналогичная проверка обычно делается, используя ContainsKey() и Add():
if (employees.ContainsKey(id))
employees[id] = employee;
else
employees.Add(id, employee);

При использовании индексатора словаря для установки значения, под капотом в Dictionary используется метод TryInsert(), поэтому проверка ContainsKey() лишняя.

Другим распространённым шаблоном является добавление записи только если ключ отсутствует в словаре:
if (!employees.ContainsKey(id))
employees.Add(id, employee);

Для таких случаев Dictionary и Dictionary<TKey, TValue> имеют метод TryAdd(), который делает то же самое:
if (employees.TryAdd(id, employee))
{
… // элемент успешно добавлен
}
else
{
… // элемент с таким ключом уже существует
}

Для получения значений словаря, только если ключ существует, есть метод TryGetValue(key, out value):
// До:
if (employees.ContainsKey(id))
return employees[id];

// После:
if (employees.TryGetValue(id, out var employee))
return employee;

Итого
JetBrains недавно объявили в своём блоге, что новые наборы проверок для анализатора кода в ReSharper и Rider содержат описанные выше проверки и соответствующие быстрые исправления для оптимизации вашей работы с различными типами коллекций за счёт сокращения количества операций поиска в коллекциях. Особенно при работе с большими коллекциями или частом добавлении записей оптимизация шаблона использования повысит производительность вашего кода.

Источник: https://blog.jetbrains.com/dotnet/2023/04/18/reduce-lookups-in-hashset-dictionary-and-other-collections-with-resharper/
👍37
День 1552. #ЗаметкиНаПолях
Проверки Работоспособности в
ASP.NET Core. Начало
Мы все хотим создавать надёжные приложения, которые можно бесконечно масштабировать, чтобы обрабатывать любое количество запросов. Крайне важно, чтобы у вас была система для получения быстрой обратной связи о работоспособности приложения. В этом помогут проверки работоспособности (Health Checks).

Они позволяют отслеживать работоспособность различных компонентов, в том числе: баз данных, API, кэша, внешних сервисов. ASP.NET Core имеет встроенную поддержку проверки работоспособности.

Вот базовая конфигурация, которая регистрирует сервис проверки работоспособности:
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHealthChecks();

var app = builder.Build();

app.MapHealthChecks("/health");

app.Run();

Проверка возвращает значение HealthStatus, которое может быть 3х видов:
- Healthy
- Degraded
- Unhealthy
Например, если приложение работает медленнее обычного, можно возвратить HealthStatus.Degraded.

Специальные проверки
Специальные проверки можно создавать, реализуя интерфейс IHealthCheck. Например, для базы данных SQL, можно использовать запрос, который быстро выполняется, вроде SELECT 1:
public class SqlHealthCheck : IHealthCheck
{
private readonly string connStr;

public SqlHealthCheck(IConfiguration cfg)
{
connStr =
cfg.GetConnectionString("Database");
}

public async Task<HealthCheckResult>
CheckHealthAsync(
HealthCheckContext context,
CancellationToken ct = default)
{
try
{
using var conn =
new SqlConnection(connStr);

await conn.OpenAsync(ct);
using var cmd = conn.CreateCommand();
cmd.CommandText = "SELECT 1";
await cmd.ExecuteScalarAsync(ct);

return HealthCheckResult.Healthy();
}
catch(Exception ex)
{
return HealthCheckResult.Unhealthy(
context.Registration.FailureStatus,
exception: ex);
}
}
}

Проверку необходимо зарегистрировать, для этого добавим метод к AddHealthChecks:
builder.Services.AddHealthChecks()
.AddCheck<SqlHealthCheck>(
"custom-sql",
HealthStatus.Unhealthy);

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

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

Источник:
https://www.milanjovanovic.tech/blog/health-checks-in-asp-net-core
👍26👎1
День 1553. #ЗаметкиНаПолях
Проверки Работоспособности в
ASP.NET Core. Окончание
Начало

Для многих популярных сервисов реализованы свои проверки работоспособности. Вот несколько примеров:
SQL Server - AspNetCore.HealthChecks.SqlServer
Postgres - AspNetCore.HealthChecks.Npgsql
Redis - AspNetCore.HealthChecks.Redis
RabbitMQ - AspNetCore.HealthChecks.RabbitMQ
AWS S3 - AspNetCore.HealthChecks.Aws.S3
SignalR - AspNetCore.HealthChecks.SignalR

А в репозитории AspNetCore.Diagnostics.HealthChecks их гораздо больше.

Например, вот как добавить проверки для PostgreSQL и RabbitMQ:
builder.Services.AddHealthChecks()
.AddCheck<SqlHealthCheck>(
"custom-sql",
HealthStatus.Unhealthy);
.AddNpgSql(pgConnectionString)
.AddRabbitMQ(rabbitConnectionString);

Форматирование ответа
По умолчанию конечная точка, возвращающая статус проверки работоспособности, выдаёт строковое значение, представляющее HealthStatus. Это неудобно, если у вас настроено несколько проверок, поскольку хорошо было бы просматривать состояние отдельно для каждого сервиса. Что ещё хуже, если один из сервисов выходит из строя, проверка просто вернёт Unhealthy, и вы не узнаете, что вызывает проблему.

Эту проблему можно решить, предоставив ResponsWriter, который уже существует в пакете AspNetCore.HealthChecks.UI.Client. После установки пакета надо изменить вызов MapHealthChecks, чтобы использовать ResponseWriter:
app.MapHealthChecks(
"/health",
new HealthCheckOptions
{
ResponseWriter =
UIResponseWriter.WriteHealthCheckUIResponse
});

Вот пример вывода:
{
"status": "Unhealthy",
"totalDuration": "00:00:00.3285211",
"entries": {
"npgsql": {
"data": {},
"duration": "00:00:00.1183517",
"status": "Healthy",
"tags": []
},
"rabbitmq": {
"data": {},
"duration": "00:00:00.1189561",
"status": "Healthy",
"tags": []
},
"custom-sql": {
"data": {},
"description": "Unable to connect to the database.",
"duration": "00:00:00.2431813",
"exception": "Unable to connect to the database.",
"status": "Unhealthy",
"tags": []
}
}
}
Показано, что из трёх сервисов не работает один, а также показана ошибка.

Итого
Мониторинг приложений важен для отслеживания доступности, использования ресурсов и изменений в производительности. Отслеживать работоспособность ваших приложений ASP.NET Core легко, предоставляя проверки работоспособности для ваших сервисов. Вы можете внедрить пользовательские проверки работоспособности, но сначала проверьте, существуют ли готовые решения.

Источник: https://www.milanjovanovic.tech/blog/health-checks-in-asp-net-core
👍26
День 1554. #ЗаметкиНаПолях
Как Исключить Свойства при Сериализации в JSON. Начало
Распространённая проблема при сериализации объектов в JSON в том, что результат содержит множество нежелательных свойств. По умолчанию сериализуются все свойства. Однако очень часто нам не нужна вся информация. Рассмотрим, как убрать ненужные свойства при сериализации объекта на примере двух популярных библиотек сериализации System.Text.Json и Newtonsoft.Json.

1. Игнорируем отдельные свойства
Для отдельных свойств можно использовать атрибут [JsonIgnore], чтобы исключить его из вывода при сериализации объекта. Атрибут доступен в пространстве имен System.Text.Json.Serialization или Newtonsoft.Json соответственно:
public class Person
{
[JsonIgnore]
public int Id { get; set; }
public string? Name { get; set; }
public string? LastName { get; set; }
}

var person = new Person()
{
Id = 1,
Name = "John",
LastName = "Smith"
};

var json1 = JsonSerializer.Serialize(person);
var json2 = JsonConvert.SerializeObject(person);

Вывод:
{
"Name": "John",
"LastName": "Smith"
}

2. Условное игнорирование отдельных свойств
Мы также можем применять условия при индивидуальном игнорировании свойства. Для атрибута [JsonIgnore] можно установить свойство Condition . Например,
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public int Id { get; set; }

Доступные значения:
- Always — свойство всегда игнорируется (по умолчанию),
- Never — свойство всегда сериализуется и десериализуется, независимо от глобальных параметров DefaultIgnoreCondition, IgnoreReadOnlyProperties и IgnoreReadOnlyFields,
- WhenWritingDefault — свойство не учитывается при сериализации, если содержит значение по умолчанию для типа (default),
- WhenWritingNull — свойство не учитывается при сериализации, если оно равно null.

В Newtonsoft.Json сериализацию свойства можно настроить с помощью JsonPropertyAttribute.

3. Атрибуты DataContract и DataMember
В некоторых сценариях у нас есть классы со многими свойствами, а мы хотим сериализовать только некоторые из них. При использовании Newtonsoft.Json мы можем добавить атрибут класса [DataContract], а для свойств, которые должны оставаться при сериализации - атрибут [DataMember]. Оба доступны в пространстве имен System.Runtime.Serialization.
public class Customer
{
public int Id { get; set; }
[DataMember]
public string? Name { get; set; }
[DataMember]
public string? LastName { get; set; }
}

var customer = new Customer()
{
Id = 1,
Name = "John",
LastName = "Smith"
};
var json = JsonConvert.SerializeObject(customer);

Вывод:
{ 
"Name": "John",
"LastName": "Smith"
}

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

Источник:
https://code-maze.com/csharp-exclude-properties-from-json-serialization/
👍25
День 1555. #ЗаметкиНаПолях
Как Исключить Свойства при Сериализации в JSON. Окончание
Начало

4. Игнорировать все свойства с null или default
Можно не учитывать при сериализации свойства со значениями null или значениями по умолчанию для типа (default).
public class Book
{
public int Id { get; set; }
public string? Title { get; set; }
public int? Pages { get; set; }
public int Sells { get; set; }
public Author? Author { get; set; }
}

var book = new Book()
{
Id = 1,
Title = "Dracula"
};

В System.Text.Json для этого нужно задать опцию DefaultIgnoreCondition со значением WhenWritingNull или WhenWritingDefault соответственно:
var json1 = JsonSerializer.Serialize(book, 
new JsonSerializerOptions
{
DefaultIgnoreCondition
= JsonIgnoreCondition.WhenWritingNull
// или JsonIgnoreCondition.WhenWritingDefault
});

В Newtonsoft.Json нужно задать параметры NullValueHandling или DefaultValueHandling соответственно:
var json2 = JsonConvert.SerializeObject(book,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
// или
// DefaultValueHandling =
// DefaultValueHandling.Ignore
});

Вывод:
{
"Id": 1,
"Title": "Dracula",
"Sells": 0
}
Если мы зададим игнорирование значений по умолчанию, то свойства "Sells" не будет в выводе.

5. Используем IContractResolver
Newtonsoft.Json предоставляет этот интерфейс для тонкой настройки сериализации. Проще всего создать класс, унаследованный от DefaultContractResolver, в котором либо:
- переопределить метод CreateProperty, который позволяет обратиться к метаданным свойства и задать ему булево значение ShouldSerialize, определяющее, должно ли свойство попасть в вывод при сериализации,
- переопределить метод CreateProperties, который должен вернуть список свойств, попадающих в вывод при сериализации.
После создания класса, реализующего этот интерфейс, его можно подключить в настройках сериализации:
var json = JsonConvert.SerializeObject(book, 
new JsonSerializerSettings
{
ContractResolver =
new MyPropertiesResolver()
});

Пример создания класса ContractResolver можно найти здесь.

Источник: https://code-maze.com/csharp-exclude-properties-from-json-serialization/
👍19
День 1556. #ЧтоНовенького
Новые Атрибуты Валидации в .NET 8
В .NET 8 превью 2, представлены несколько новых атрибутов, которые наверняка вызовут интерес у разработчиков.

1. RequiredAttribute.DisallowAllDefaultValues
Атрибут Required используется для пометки свойства или параметра как обязательного, что означает, что он не может быть null. Теперь добавлено свойство DisallowAllDefaultValues, которое позволяет проверять, что структура не равна своему значению по умолчанию. Допустим, у нас есть свойство типа Guid. По умолчанию Guid инициализируется как Guid.Empty. Чтобы гарантировать, что значение этого свойства всегда установлено, мы можем использовать атрибут Required со свойством DisallowAllDefaultValues, установленным в true. Если значение свойства не задано явно и остаётся равным Guid.Empty, валидация завершится ошибкой:
public class MyClass
{
[Required(DisallowAllDefaultValues = true)]
public Guid Value { get; set; }
}

Эта особенно полезно в сценариях, где важно убедиться, что значение свойства или параметра задано явно и его нельзя оставить в значении по умолчанию.

2. Явные границы Range
Теперь можно явно указывать границы при проверке диапазона с помощью RangeAttribute. Можно определять диапазоны с границами, которые исключаются из проверки:
[Range(0d, 1d, 
MinimumIsExclusive = true,
MaximumIsExclusive = true)]
public double Sample { get; set; }

Здесь атрибут указывает, что допустимым диапазоном для Sample типа double является любое значение больше 0 и меньше 1, однако граничные значения 0 и 1 исключаются из допустимого диапазона.

3. Атрибут Length
Этот атрибут теперь можно использовать для установки как нижних, так и верхних границ для строк или коллекций, что обеспечивает большую гибкость при проверке:
[Length(10, 20)]
public ICollection<int> Values { get; set; }

Атрибут Length в коде выше гарантирует, что коллекция Values должна содержать не менее 10 и не более 20 элементов.

4. Атрибуты AllowedValues и DeniedValues
Следующие атрибуты можно использовать для проверки свойства по списку разрешённых или запрещённых значений. AllowedValues указывает список допустимых значений. DeniedValues - список запрещённых значений.
[AllowedValues("chocolate", "vanilla")]
public string IceCreamFlavor { get; set; }

[DeniedValues("beetroot", "eggplant")]
public string CakeFlavor { get; set; }

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

Источник: https://dev.to/bytehide/net-8-preview-2-unveiled-5-new-features-you-need-to-know-2cof
👍29
День 1557. #юмор
👍19
День 1558. #МоиИнструменты
WireMock.NET
Я как-то рассказывал про библиотеку Alba, которая позволяет проводить интеграционное тестирование API. Сегодня же расскажу вам про утилиту, позволяющую тестировать клиентов API и имитировать HTTP-запросы.

WireMock.NET — это .NET-версия WireMock, библиотеки для заглушек и имитации HTTP-сервисов. С WireMock.NET вы можете определить ожидаемые ответы для конкретных запросов, а библиотека будет перехватывать и управлять этими запросами для вас. Это позволяет легко тестировать код, выполняющий HTTP-запросы, не полагаясь на фактическую доступность внешнего сервиса и не взламывая HttpClient.

После установки nuget-пакета вы можете начать использовать WireMock.NET, создав экземпляр класса WireMockServer и настроив его на желаемое поведение. Это можно легко сделать, вызвав метод WireMockServer.Start или WireMockServer.StartWithAdminInterface:
using var wireMock = 
WireMockServer.Start(port: 1080, ssl: false);

Теперь можно начать определять моки для внешних HTTP-запросов, в том числе, используя Fluent API:
wireMock
.Given(
Request.Create()
.WithPath("/foo")
.UsingGet()
)
.RespondWith(
Response.Create()
.WithStatusCode(200)
.WithHeader("Content-Type",
"application/json; charset=utf-8")
.WithBodyAsJson(new
{ msg = "Hello world!" })
);

В тестах легко написать проверку результатов HTTP-запроса:
[Fact]
public async Task sample_test()
{
var response = await new HttpClient()
.GetAsync($"{_wireMock.Urls[0]}/foo");

Assert.Equal(HttpStatusCode.OK,
response.StatusCode);
Assert.Equal(
"""{"msg":"Hello world!"}""",
await response.Content.ReadAsStringAsync());
}

Замечание: в реальном приложении, конечно, тестироваться будут не собственно HTTP-ответы, а код, обрабатывающий эти ответы.

WireMock.NET предлагает множество функций, помимо базовых заглушек и имитаций HTTP-запросов:
1. Прокси-запросы к реальному сервису и захват ответов в виде маппинга. Вы можете использовать их в качестве основы для своих заглушек, устраняя необходимость в ручном определении ответов.
2. Чтение маппингов и определение заглушек из статических файлов, вместо того, чтобы определять их программно. Это может быть полезно для совместного использования заглушек в разных тестах или проектах.
3. Создание динамических шаблонов ответов, которые включают данные из запроса. Это позволяет создавать ответы, которые различаются в зависимости от данных запроса, что может быть полезно для тестирования пограничных случаев или моделирования поведения реального сервиса.
4. Моделирование поведения сервиса с помощью сценариев и состояний. Вы можете легко имитировать различные состояния сервиса и переключаться между ними. Это может быть полезно для проверки того, как ваш код обрабатывает различные типы сбоев или ответов от сервиса.

Узнать больше о возможностях WireMock.NET можно на странице WireMock Wiki.

Источник: https://cezarypiatek.github.io/post/mocking-outgoing-http-requests-p1/
👍30
День 1559. #Карьера
Вещи, Которые не Стоит Раскрывать на Собеседовании
Нам всем приходится проходить собеседования в течение своей карьеры. Кому-то больше, кому-то меньше. Понять, что стоит говорить на собеседовании, а чего не стоит, можно только с опытом, и во многом это зависит от компании и интервьюера. Но вот универсальные вещи, которые лучше оставить при себе, даже если они на первый взгляд кажутся безобидными.

1. Слишком много фактов о себе
Даже если у вас есть чрезвычайно увлекательная, но длинная история из вашей практики, её лучше сократить, либо вообще не рассказывать. Интервьюер ищет человека, который может кратко и чётко выражать свои мысли. Кроме того, наниматель вольно или невольно может использовать то, что вы скажете, как в вашу пользу, так и против вас. Ваши личные увлечения, пристрастия или тем более политические взгляды могут повлиять на решение о вашем трудоустройстве.

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

3. Карьерные планы, не связанные с текущей вакансией
В продолжение предыдущего пункта. Если вас спросят, где вы видите себя через пять лет, отвечать, что вы хотите сменить сферу деятельности либо открыть собственный бизнес – не лучшая идея. Работодателю нужен ресурс, на который можно рассчитывать в долгосрочной перспективе. А ваше желание в скором времени сменить карьерный путь может означать, что вы не полностью будете отдаваться работе.

4. Факт, что вы ищете любую работу
У любого из нас бывают сложные моменты в жизни. Однако не стоит сообщать потенциальному работодателю, что вы в отчаянии ищете любой способ заработать деньги.

5. Возраст
Да, в ИТ это не главный фактор, и сложно будет уйти от прямого вопроса, но всё-таки, пока не спрашивают, лучше лишний раз не сообщать (что, например, часто встречается в резюме).

6. Сколько вы собираетесь отработать на этом месте
Этот пункт в некотором роде связан с п.3. Не стоит сообщать, что вы собираетесь отработать Х лет и уйти на заслуженный отдых (даже если это так). Многие работодатели ищут кандидатов с потенциалом роста либо на более долгий срок, чем вы рассчитываете, поэтому раскрытие того, что кандидат собирается «отбыть срок» и уйти, может сильно навредить.

7. Проблемы со здоровьем
Понятно, что, если проблема со здоровьем мешает вам выполнять ваши обязанности, о ней стоит сообщить. Об остальном, если вас напрямую не спрашивают, лучше не распространяться, чтобы опять же не вызывать ненужную предвзятость у интервьюера.

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

Источник: https://www.youtube.com/watch?v=eza-l-kBK40
👍16👎1
День 1560. #BestPractices
Лучшие Практики Безопасного Развёртывания и Масштабирования Приложений. Начало
Кодовая база приложения — живой объект. Она растёт, меняется и приспосабливается. Всегда есть новая функция, которую нужно добавить, ошибки, которые нужно исправить и которые создаются в результате. По мере роста проекта код меняется чаще, появляется все больше функций, больше проблем и больше ошибок. Ручное тестирование становится невозможным. Как убедиться, что приложение остаётся работоспособным, что развёртывание ничего не сломало? Автоматизировать. Вот лучшие практики, позволяющие быстро развёртывать изменения и поддерживать высокое качество приложения.

1. Используйте флаги функций
Флаги функций - это механизм, который позволяет вам отключить функциональность в рабочей среде, если что-то пойдёт не так:
if (IsFeatureFlagEnabled(
"MyNewFeature",
defaultValue: false))
{
//…
}

Фактические значения флагов функций могут находиться в какой-либо удалённой БД или сервисе, которым вы можете управлять. Можно разработать их самостоятельно или использовать инструмент вроде LaunchDarkly, который сохраняет значения флагов функций, предоставляет API для их получения и UI, позволяющий легко их изменять.
Функция может быть защищена флагом «высокого уровня», который отключает всё, и флагами «низкого уровня», которые контролируют более мелкие части функции. Можно ввести политику, согласно которой каждое изменение кода должно быть защищено флагом функции.
Флаги функций упрощают разработку. Вместо того, чтобы иметь побочную ветку, которую команда разработчиков хранит отдельно в течение нескольких месяцев, можно работать в «основной» ветке, но отключить функциональность с помощью флага функции.
Кстати, со временем не забывайте удалять флаги устоявшихся функций, прежде чем код станет нагромождением условных операторов.

2. Добавьте телеметрию для обнаружения регрессий
Ключевой частью понимания того, что приложение работает должным образом, является возможность наблюдать за тем, что происходит. Вы хотите узнать как можно скорее, когда что-то пойдёт не так. Этот вид мониторинга проявляется во многих формах:
- Журналы ошибок. Добавляйте их во все приложения. Если есть исключение или неожиданное поведение регистрируйте его. Всплеск числа ошибок в журнале быстро указывает на наличие проблемы и определяет ее основную причину.
- Телеметрия времени выполнения. Это может быть время выполнения операции, время выполнения запроса или что-либо ещё, что вы можете измерить. Его легко отслеживать, и вы можете быстро обнаруживать аномалии, такие как зависшие запросы и низкая производительность. Кстати, уменьшение времени выполнения также может указывать на то, что что-то пошло не так. Можно регистрировать время выполнения самостоятельно с помощью журналов приложений или использовать счетчики производительности или инструменты вроде Azure Monitor.
- Телеметрия сбоев. Сбои — это плохо, и вы хотите узнавать о них как можно скорее. Надёжная система сообщения о сбоях будет иметь большое значение. Можно разработать собственные или использовать инструменты для создания отчетов о сбоях, такие как Raygun.
- Панели мониторинга приложений. Информационные панели хороши тем, что картинка стоит тысячи слов. Простая информационная панель может быстро показать, что что-то пошло не так. Вы можете отображать время выполнения запроса, использование ЦП и памяти, частоту сбоев и т. д. Чем больше, тем лучше. Если вы можете визуально увидеть всплеск или падение, вы быстро обнаружите проблему, которую можете исправить, прежде чем она серьёзно повлияет на бизнес. Существуют отличные инструменты для создания панелей мониторинга, включая Azure Data Explorer, Grafana и DataDog.

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

Источник:
https://michaelscodingspot.com/safe-application-deployment/
👍6
День 1561. #BestPractices
Лучшие Практики Безопасного Развёртывания и Масштабирования Приложений. Продолжение
Начало

3. Добавьте оповещения телеметрии, когда что-то идёт не так
Добавление журналов и информационных панелей — это здорово, но полагаться на то, что кто-то всегда будет их просматривать, обречено на провал. Лучший способ обеспечить наблюдаемость — автоматизировать аномалии. Автоматизируйте информационные панели, чтобы отправлять оповещения, когда что-то идёт не так. Если есть серьёзное замедление продолжительности запросов, вы захотите узнать об этом как можно скорее. То же касается роста количества записей в журналах ошибок и сбоев процессов. Практически всё, за чем вы стараетесь следить, стоит автоматизировать для уведомлений в случае возникновения проблемы. Большинство инструментов, предоставляющих отчеты и визуализацию информационных панелей, также имеют функции оповещения, включая Kibana, Azure Monitor и Datadog.

4. Добавьте для клиентов простой способ оставить отзыв
Ваши клиенты, помимо оплаты счетов за ваш сервис, могут быть отличными QA-инженерами. Добавьте в приложение лёгкий способ предоставления отзывов. Убедитесь, что вы можете сопоставить соответствующие журналы приложений с заявкой пользователя. Помимо бесплатной гарантии качества, предоставление возможности оставить отзыв — это отличный опыт для клиента.
Да, и как только у вас будет конвейер для получения отзывов клиентов, обязательно добавьте счётчик отзывов в качестве телеметрии, создайте панель мониторинга и оповещение.

5. Дежурные инженеры
Добавление телеметрии, отзывов клиентов и информационных панелей не очень полезно, если за ними никто не следит. На определённом этапе роста компании обычно вводят какую-либо политику ротации дежурств. Это так же просто, как назначить еженедельные или ежемесячные смены среди ваших инженеров. Во время смены дежурный отвечает за любые соответствующие оповещения и уведомления, активно просматривает информационные панели работоспособности приложений и реагирует на аномалии. Обычно дежурный инженер не решает проблему, а только назначает её соответствующему разработчику или устраняет её, отключая некоторые функции или, возможно, перезапуская какой-либо сервер.
Вы можете выбрать альтернативный путь - иметь постоянных инженеров по надёжности (Site Reliability Engineer, SRE). Подход с ротацией предпочтительнее в том, что разработчики лучше знают, что происходит в коде, и одни и те же люди следят за работоспособностью приложения и устраняют проблемы. Это может усилить их чувство ответственности.

6. Используйте канареечные релизы
Как только ваше приложение достаточно разрастётся, вы больше не сможете позволить себе развёртывать изменения для всех клиентов, независимо от того, насколько изменения защищены флагами функций и отличной телеметрией. Риск слишком велик. Чтобы свести его к минимуму, стандартной практикой является использование канареечных выпусков. Вместо того, чтобы выдавать новый код всем, он постепенно выдаётся группам (кольцам) клиентов. Во-первых, новые изменения развёртываются в первом кольце, которое представляет собой небольшое подмножество пользователей, возможно, во внутренней тестовой среде. Затем код передается второму кольцу, которое представляет собой большее подмножество пользователей. Каждый раз, когда код развёртывается в более крупном кольце, вы должны отслеживать журналы приложений, информационные панели и отзывы клиентов, чтобы убедиться, что ничего не сломалось. Если что-то сломалось, вы сможете вовремя это обнаружить с минимальным воздействием на большинство клиентов.

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

Источник:
https://michaelscodingspot.com/safe-application-deployment/
👍6
День 1562. #BestPractices
Лучшие Практики Безопасного Развёртывания и Масштабирования Приложений. Окончание
Начало
Продолжение

7. Добавьте эксперименты и A/B-тестирование
При добавлении каких-либо изменений, таких как новая функция или изменение UX, отлично подходит A/B-тест, чтобы убедиться, что изменение является положительным и не создаёт никаких проблем. Добавьте механизм для разделения ваших пользователей на 2 или более групп и запускайте для них разный код. Контролируйте обе группы эксперимента: контрольную и экспериментальную (группу A и группу B). Есть ли увеличение в журналах ошибок? Как насчёт всплесков жалоб от клиентов? Проверьте информационные панели, есть ли аномалии?
Такие эксперименты отлично подходят для выявления проблемных изменений, если у вас есть хороший способ сопоставить телеметрию с экспериментальными группами. Нужно просто при запуске сессии регистрировать все сессии экспериментальной группы, а затем сопоставлять их с проблемными сессиями.

8. Проводите пассивное тестирование
Пассивные тесты — отличный способ убедиться, что ваши изменения ведут себя правильно в большой среде, которую вы не до конца понимаете. Учтите, что, когда вы делаете какую-то оптимизацию или рефакторинг в огромном приложении, вы не можете с полной уверенностью предсказать, что ничего не сломали. Конечно, у вас есть набор тестов, но вы никогда не знаете наверняка, что он охватывает все случаи. Вместо этого вы можете сделать пассивный тест. Выполняйте любую оптимизацию или изменение, которое вам нужно, в темноте, работая пассивно, в дополнение к исходной реализации. Запустите как старый (активный) код, так новый (пассивный), а затем сравните результаты в логах. Разверните новый код в производственной среде и убедитесь, что поведение исходного и изменённого кода совпадает. Как только вы увидите, что они идеально совпадают, вы можете уверенно переключиться со старого кода на новый.

9. Тестируйте
Тесты оставлены напоследок, потому это вроде бы и очевидно, но тем не менее важно и о них нужно упомянуть.
Одним из самых важных механизмов, позволяющих убедиться, что следующее развёртывание не сломает ничего существенного, является набор тестов. Это должно быть стандартной практикой в наши дни, но множество проектов даже сейчас всё ещё существуют без них. Когда у вас есть тесты, обязательно применяйте их, что обычно означает добавление политики в пулл-реквесты, которая гарантирует, что все тесты пройдены.
Когда у вас есть непрерывный процесс интеграции, пришло время рассмотреть стратегию тестирования. Вы стремитесь к определённому уровню покрытия кода? Все ли новые функции требуют некоторого количества тестов? Автоматически применять такие правила сложно, но всё же полезно определить политику для команды и попытаться следовать ей самостоятельно и при обзорах кода.
Помимо модульных тестов, хорошо иметь приличное количество интеграционных и сквозных тестов. Они не определят основную причину, если тест не пройдёт, но отлично подойдут для обнаружения ошибок и проверки работоспособности вашей системы в целом. Модульные тесты, как правило, легко ломаются при рефакторинге или изменении поведения, даже если система работает так, как ожидалось, в то время как сквозные тесты обычно остаются нетронутыми, если вы не вносите ошибки. Можно даже удалить некоторые или большинство модульных тестов после завершения разработки и оставить только интеграционные и E2E-тесты. Или, по крайней мере, будьте гибкими, чтобы со временем отказаться от модульных тестов в пользу более глобальных.

Источник: https://michaelscodingspot.com/safe-application-deployment/
👍6
День 1563. #Карьера
Совещания Делают Вас Менее Продуктивными?
Согласно исследованию SurveyMonkey, 32% людей считают, что то, что было на совещании, могли бы прислать в e-mail. Скорее всего, где бы вы ни работали, вы не устраивались в эту компанию ради совещаний. Вы хотели создавать ПО. Но митинги стали частью процесса, и чем выше ваша позиция, тем больше встреч вас, вероятно, приглашают посетить. Сегодня рассмотрим влияние совещаний на продуктивность и способы сделать их лучше (или вообще избежать их).

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

Все эти недостатки совещаний могут заставить вас задаться вопросом, зачем вообще их проводить?

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

Многие люди воспринимают нежелание посещать встречи или отказ от неё как оскорбление. Кто-то, возможно, предпочёл бы e-mail с описанием задачи. Но другой человек может рассматривать встречу как способ прощупать идею, найти лучшее решение, работая с экспертом — с вами.

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

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

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

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

Все исследования свидетельствуют в пользу того, чтобы проводить меньше встреч. Хотя они по-прежнему иногда необходимы. Dropbox использует систему 3D: решения (decisions), дебаты (debates) и обсуждение (discussion). Это действия, для выполнения которых люди должны сотрудничать. Всё остальное можно подать другими способами.

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

Источник: https://stackoverflow.blog/2023/04/12/are-meetings-making-you-less-productive/
👍12
День 1564. #ЗаметкиНаПолях
Утечки Памяти в C#
Утечка памяти в C# происходит, когда приложение неоднократно выделяет память, но не освобождает её даже после того, как память выполнила своё предназначение. В результате приложение постепенно использует всё больше памяти с течением времени, что в итоге может привести к сбою приложения или прекращению его работы. Ошибки программирования включают в себя неспособность освободить объекты, которые больше не нужны, или хранение ссылок дольше, чем необходимо, что может привести к утечке памяти. Циклические ссылки на объекты, неправильное использование структур данных, таких как списки и словари, а также неправильная обработка исключений — вот лишь некоторые из причин этих ошибок.
Сегодня рассмотрим различные ситуации утечки памяти.

1. Использование статических объектов.
Когда мы используем статический класс, переменные будут доступны на протяжении всего жизненного цикла приложения. Мы должны быть очень осторожны, когда используем статические переменные/классы. Это связано с тем, что сборщик мусора не собирает статические объекты и всё, на что они ссылаются. Не используйте ключевое слово static, если в этом нет необходимости.

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

3. Кэширование.
Это очень хорошая стратегия для повышения производительности приложения. Но если мы используем кэширование во всех областях приложения, это приведёт к избыточному кэшированию и нехватке памяти. Всегда полезно кэшировать только часто используемые объекты.

4. Использование неуправляемых объектов.
Работа с файловой системой ОС — один из лучших примеров неуправляемых объектов. Если мы собираемся использовать файловую систему, мы должны правильно избавляться от всех объектов после завершения работы. В противном случае, поскольку сборщик мусора не очищает их, это приведёт к утечке памяти.

5. Ручная реализация шаблона IDisposable.
Всегда используйте метод Dispose в классе, который реализует интерфейс IDisposable. В противном случае может произойти утечка памяти. Конструкция using, которая вызывает метод Dispose для каждого экземпляра, является лучшим подходом для достижения этой цели. Если вы не можете использовать оператор using, не забудьте сделать это вручную и подавить метод finalize, так как он не требуется.
GC.SuppressFinalize();

Если мы используем интерфейс IDisposable, мы вручную освобождаем объект с помощью метода Dispose. Finalize — это метод автоматического управления памятью, вызываемый сборщиком мусора для удаления неиспользуемых объектов. Поэтому при ручной очистке он не требуется.

Источник: https://dev.to/arunkumar2331996/memory-leaks-in-c-3koj
👍23
День 1565.
Мониторинг и Производительность Entity Framework. Вопросы и Ответы. Начало
ORM-технологии, такие как Entity Framework, могут значительно упростить модель программирования для баз данных, но при небрежном исполнении может пострадать производительность. Чтобы этого не произошло, разработчики используют мониторинг, профилирование взаимодействия с БД и тонкую настройку запросов. Джим Вули, архитектор решений в Slalom Consulting делится своими знаниями о том, как максимально эффективно использовать EF.

1. Как ORM могут упростить модель программирования для баз данных?
Инструменты ORM, такие как EF, избавляют разработчиков от необходимости беспокоиться об управлении коммуникациями между приложением и базой данных и позволяют им сосредоточиться на добавлении ценности для бизнеса безопасным для типов способом (через LINQ). Разработчикам не нужно беспокоиться об управлении подключениями к базе данных, обновлении хранимых процедур для каждой операции или изучении тонких различий между различными диалектами SQL (TSQL, PLSQL, pgSQL и т. д.). Пока необходимо извлечь объект или граф объектов, внести изменения в эту структуру и обновить ее, инструменты OR/M могут легко обрабатывать 80-90% вариантов использования, не вызывая проблем с производительностью. Кроме того, по мере развития платформы находятся всё новые средства оптимизации производительности, и разработчики могут ими воспользоваться, просто обновив версию.

2. Какие распространённые ошибки допускают разработчики при использовании EF?
Инструменты ORM уменьшают потребность в ручном управлении, но по-прежнему необходимо следить за утечками, которые могут вызвать серьёзные проблемы в будущем. Однажды у меня был клиент, который столкнулся с проблемой производительности. Как оказалось, проблема была вызвана ленивой загрузкой дочерних записей на четыре уровня ниже во вложенных циклах. Помните о действиях, вызывающих запросы к базе, таких как foreach, First, Any, Sum, Count. С другой стороны, применяя дополнительную фильтрацию к возвращённому IEnumerable, надо понимать, что она выполняется в памяти, а не в базе данных.
Также нужно немного знать о настройке и индексировании базы данных, а также о влиянии ваших запросов на индексы. Например, если вы используете метод .Include() для выборки связанных дочерних записей, он будет включать все дочерние столбцы как часть запроса и, таким образом, будет игнорировать покрывающие индексы, то есть выполняться неоптимально.
Более тонкие проблемы могут возникнуть, когда разработчики пытаются применить вычисления дат в предложениях Where или не сопоставляют строки ANSI с типами данных varchar. В обоих случаях индексирование, которое, как вы думали, вы используете, может быть недоступно, и в результате вы получаете медленное полное сканирование таблицы.
Во всех этих случаях внимание, выявление плохо работающих запросов и их профилирование для определения необходимых изменений — это первый шаг к обеспечению хорошей работы приложения.

3. Как мониторинг производительности и настройка могут улучшить ситуацию?
Наличие набора тестов, который вы можете использовать для мониторинга производительности, — это первый шаг. Так вы сможете идентифицировать запросы или участки кода, которые плохо работают и нуждаются в настройке. Настройка без мониторинга часто приводит к преждевременной оптимизации. Даже с EF в .Net Framework, хотя запросы, сгенерированные EF, могли выглядеть довольно неприятно, планы выполнения, сгенерированные базой данных, могли генерировать такие же хорошие или, в некоторых случаях, лучшие запросы, чем вы могли бы написать сами.
Только после выявления проблемных запросов вы можете настроить или, в некоторых случаях, переосмыслить задачу для достижения той же конечной цели. Настройка производительности приложений во многом является искусством, и редко существует универсальный подход, который решит эту проблему. Вы должны попробовать несколько стратегий, чтобы выяснить, что лучше всего подходит для данного случая.

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

Источник:
https://visualstudiomagazine.com/articles/2023/04/05/ef-performance.aspx
👍12
День 1566.
Мониторинг и Производительность Entity Framework. Вопросы и Ответы.
Окончание
Начало

4. Профилирование взаимодействий с базой данных с помощью EF: что нужно и как это помогает?
В зависимости от вашей платформы и среды существует ряд бесплатных и коммерческих инструментов профилирования. От SQL Profiler (или соответствующего расширения для Azure Data Studio), Intellitrace и Application Insights до сторонних модулей, таких как EPFrof, OrmProfiler и MiniProfiler.
В некоторых случаях поддержка инструментов может быть добавлена без изменения кода вашего приложения, в других случаях требуется разместить в приложении небольшие хуки для перехвата. Кроме того, некоторые из более поздних инструментов облегчают нахождение строки кода, вызывающей запрос. Это может быть неоценимо при попытке выяснить, откуда взялся надоедливый плохо выполняющийся запрос.

5. Каковы плюсы и минусы работы без хранимых процедур?
Многие сторонники хранимых процедур рекламируют возможности, которые они привносят с точки зрения компиляции и кэширования запросов, а также параметризации. При этом они создавали динамические запросы внутри хранимых процедур, полностью нивелируя эти преимущества. EF генерирует запросы, которые можно кэшировать и которые гарантированно будут параметризованы (если только вы не используете FromSqlRaw). В результате использование EF может быть столь же эффективным и безопасным, как и хранимые процедуры.
Кроме того, вы получаете возможность менять провайдера базы данных, не переписывая все запросы. Или при добавлении столбца в таблицу, с EF вы добавляете только свойство в модель объекта. Для хранимых процедур также потребуется управление изменениями схемы таблиц и несколько изменений хранимых процедур (для операций CRUD).
Иногда необходимо использовать хранимые процедуры. Некоторые платформы предлагают определённые функции, которые LINQ может не поддерживать (подсказки запросов, иерархии, геопространственные данные, массовое копирование и т. д.), и для них может потребоваться нативный код. В более новых версиях EF устранены некоторые из этих пробелов. Если вы будете следовать правилу 80/20, используя EF, где это возможно, а где необходимо - хранимые процедуры или другие функции, специфичные для платформы, вы часто сможете найти подход, который хорошо работает для всех сценариев приложений.

6. С какими проблемами сталкиваются организации или команды при начале работы с EF?
Проблема чаще всего не технологическая, а человеческая. Для новых приложений внедрение новых технологий часто проще. Для существующих, которые создавались годами, часто приходится полагаться на то, что универсальная среда может быть такой же хорошей (или лучше), чем созданная командой за эти годы. Некоторые из таких приложений были специально созданы для передачи таких структур ADO, как DataSets и DataTables, в пользовательский интерфейс. Попытка обосновать рентабельность инвестиций в модернизацию уровня данных в таких обстоятельствах часто может быть затруднена.
Другая типичная проблема также сводится к доверию между инженерными командами и группами поддержки (часто между разработчиками и администраторами баз данных). Группы поддержки вызываются в 3 часа ночи, когда система даёт сбой из-за плохо выполняющегося запроса, который загружает ЦП сервера базы данных. Аргумент здесь в том, что, если бы запрос был абстрагирован в хранимую процедуру, они имели бы контроль над его изменением, а не заставляли разработчиков вносить изменения в код. Это можно смягчить, используя наборы тестов производительности с соответствующим охватом и просматривая сгенерированные запросы в течение циклов разработки. Этот подход требует общения между командами для установления большего доверия с течением времени.

Источник: https://visualstudiomagazine.com/articles/2023/04/05/ef-performance.aspx
👍6