День 1773. #ЗаметкиНаПолях #PatternMatching
Шпаргалка по Сопоставлению по Шаблону в C#. Продолжение
C# 7
С# 8
Шаблон свойства
Вы можете включать в шаблон элементы объекта вместо переменных, для соответствия заданным условиям. Его можно легко использовать с другими типами шаблонов для создания гибких и мощных логических выражений.
Использование вложенных свойств было доступно в 8 и 9 версиях языка, но его реализация не была самым чистым решением или самым лаконичным синтаксисом.
Шаблон отказа
Оператор отказа (discard) _ в шаблоне соответствует всему, включая значение null. Его использование проявляется в новых выражениях switch, чтобы соответствовать выбору по умолчанию. В примере ниже, если вид хранения продуктов не указан или не соответствует ни одному варианту, будет выдано исключение:
Позиционный шаблон
В основном используется со структурами, использует деконструктор для сопоставления шаблона в соответствии с позицией значений в деконструкторе. В примере ниже Price – структура со значением и валютой. Здесь используется шаблон отказа, чтобы игнорировать валюту, когда цена 0.
Шаблон кортежа
Особый вариант позиционного шаблона, позволяющий проверять несколько свойств класса в одном выражении.
Продолжение следует…
Источник: https://codingsonata.com/your-quick-guide-to-pattern-matching-in-c/
Шпаргалка по Сопоставлению по Шаблону в C#. Продолжение
C# 7
С# 8
Шаблон свойства
Вы можете включать в шаблон элементы объекта вместо переменных, для соответствия заданным условиям. Его можно легко использовать с другими типами шаблонов для создания гибких и мощных логических выражений.
public bool IsOrganic(Food food)
{
return food is
{
NoGMO: true,
NoFertilizers: true,
NoPesticides: true
};
}
Использование вложенных свойств было доступно в 8 и 9 версиях языка, но его реализация не была самым чистым решением или самым лаконичным синтаксисом.
Шаблон отказа
Оператор отказа (discard) _ в шаблоне соответствует всему, включая значение null. Его использование проявляется в новых выражениях switch, чтобы соответствовать выбору по умолчанию. В примере ниже, если вид хранения продуктов не указан или не соответствует ни одному варианту, будет выдано исключение:
public int GetStorageTemp(
StorageRequirement req)
=> req switch
{
StorageRequirement.Freezer => -18,
StorageRequirement.Fridge => 4,
StorageRequirement.RoomTemp => 25,
_ => throw new
InvalidStorageRequirementException()
};
Позиционный шаблон
В основном используется со структурами, использует деконструктор для сопоставления шаблона в соответствии с позицией значений в деконструкторе. В примере ниже Price – структура со значением и валютой. Здесь используется шаблон отказа, чтобы игнорировать валюту, когда цена 0.
public bool IsFree(Food food)
=> food.Price is (0, _);
Шаблон кортежа
Особый вариант позиционного шаблона, позволяющий проверять несколько свойств класса в одном выражении.
public string GetDescription(Food food)
=> (food.NonGMO, food.Category.ID) switch
{
(true, (int)Category.Fresh)
=> "Non-GMO Fresh Product",
(true, (int)Category.Dairy)
=> "Non-GMO Dairy",
(false, (int)Category.Meats)
=> "GMO Meat!",
(_, _) => "Invalid Food Group"
};
Продолжение следует…
Источник: https://codingsonata.com/your-quick-guide-to-pattern-matching-in-c/
👍15
День 1774. #ЗаметкиНаПолях #PatternMatching
Шпаргалка по Сопоставлению по Шаблону в C#. Продолжение
С# 7
С# 8
C# 9
«Расширенный» шаблон типа
Позволяет выполнять проверку типов в выражениях switch.
Логический шаблон
Представляет собой совокупность отрицания (not), конъюнкции (and) и дизъюнкции (or). Вместе они называются комбинаторами шаблонов. Они используются для объединения шаблонов и применения к ним логических условий.
Шаблон отношения
Позволяет применять реляционные операторы > < >= <= для сопоставления шаблонов с константами или перечислениями.
Шаблон отрицания null
Проверяет выражение на ненулевое значение
Скобки в шаблоне
Круглые скобки в шаблоне используются для управления порядком выполнения и группировки логических выражений. Их можно использовать в любом типе шаблона, но в основном это связано с использованием комбинаторов шаблонов.
Окончание следует…
Источник: https://codingsonata.com/your-quick-guide-to-pattern-matching-in-c/
Шпаргалка по Сопоставлению по Шаблону в C#. Продолжение
С# 7
С# 8
C# 9
«Расширенный» шаблон типа
Позволяет выполнять проверку типов в выражениях switch.
public string CheckValueType(object value)
=> value switch
{
int => "integer",
decimal => "decimal",
double => "double",
_ => "not a number"
};
Логический шаблон
Представляет собой совокупность отрицания (not), конъюнкции (and) и дизъюнкции (or). Вместе они называются комбинаторами шаблонов. Они используются для объединения шаблонов и применения к ним логических условий.
public bool RequiresFrige(Category cat)
=> cat is Category.Dairy or Category.Meats;
Шаблон отношения
Позволяет применять реляционные операторы > < >= <= для сопоставления шаблонов с константами или перечислениями.
public StorageRequirement
GetStorageRequirement(Food food)
=> food.StorageTemp switch
{
<= -18 => StorageRequirement.Freezer,
>= 2 and < 6 => StorageRequirement.Frige,
> 6 and < 30 => StorageRequirement.RoomTemp,
_ => throw new
InvalidStorageRequirementException(
food.StorageTemperature)
};
Шаблон отрицания null
Проверяет выражение на ненулевое значение
public bool Exists(Blog blog)
=> blog is not null;
Скобки в шаблоне
Круглые скобки в шаблоне используются для управления порядком выполнения и группировки логических выражений. Их можно использовать в любом типе шаблона, но в основном это связано с использованием комбинаторов шаблонов.
public bool RequiresFridge(int storageTemp)
=> storageTemp is > 1 and (< 6);
Окончание следует…
Источник: https://codingsonata.com/your-quick-guide-to-pattern-matching-in-c/
👍17
День 1775. #ЗаметкиНаПолях #PatternMatching
Шпаргалка по Сопоставлению по Шаблону в C#. Окончание
С# 7
С# 8
C# 9
C# 10
Расширенный шаблон свойств
В C# 10 была решена проблема соответствия синтаксиса вложенных свойств. С появлением расширенного шаблона свойств синтаксис использования вложенных свойств при сопоставлении с шаблоном стал понятным и кратким.
C# 11
Шаблон списка
Позволяет сопоставить список или массив с набором последовательных элементов. Вы можете комбинировать его с шаблонами отказа, комбинаторами шаблонов, диапазонами, переменными и типом назначения, чтобы создать очень гибкое и мощное сопоставление по шаблону списка.
См. подробнее про шаблоны списков.
Итого
С добавлением функций сопоставления по шаблону C# добавил замечательные возможности функционального программирования, которые десятилетиями использовались во множестве языков. Конечно, всегда нужно проявлять осторожность, чтобы не злоупотреблять сопоставлением по шаблону.
Если вы работаете над большим проектом с другими членами команды, помните, что не все знают о некоторых или всех функциях сопоставления по шаблону, поэтому не стоит сразу вводить слишком много.
Источник: https://codingsonata.com/your-quick-guide-to-pattern-matching-in-c/
Шпаргалка по Сопоставлению по Шаблону в C#. Окончание
С# 7
С# 8
C# 9
C# 10
Расширенный шаблон свойств
В C# 10 была решена проблема соответствия синтаксиса вложенных свойств. С появлением расширенного шаблона свойств синтаксис использования вложенных свойств при сопоставлении с шаблоном стал понятным и кратким.
public bool RequiresFridge(Food food)
=> food is
{
Category.ID: (int)Category.Dairy or
(int)Category.Meats
};
C# 11
Шаблон списка
Позволяет сопоставить список или массив с набором последовательных элементов. Вы можете комбинировать его с шаблонами отказа, комбинаторами шаблонов, диапазонами, переменными и типом назначения, чтобы создать очень гибкое и мощное сопоставление по шаблону списка.
public (int?, int?) FindOneAndFour()
{
int[] numbers = { 1, 2, 3, 4, 5 };
// Совпадает, если
// - 2й элемент любой
// - 3й больше или равен 3
// - 5й равен 5
if (numbers is
[var one, _, >= 3, int four, 5])
{
return (one, four);
}
return (null, null);
}
См. подробнее про шаблоны списков.
Итого
С добавлением функций сопоставления по шаблону C# добавил замечательные возможности функционального программирования, которые десятилетиями использовались во множестве языков. Конечно, всегда нужно проявлять осторожность, чтобы не злоупотреблять сопоставлением по шаблону.
Если вы работаете над большим проектом с другими членами команды, помните, что не все знают о некоторых или всех функциях сопоставления по шаблону, поэтому не стоит сразу вводить слишком много.
Источник: https://codingsonata.com/your-quick-guide-to-pattern-matching-in-c/
👍16
День 1777. #ЗаметкиНаПолях
Где Имеет Смысл Применять Первичные Конструкторы
Первичные конструкторы классов появились в C# 12. Один из первых вопросов, который может возникнуть: как они работают и какова область их применения?
Во-первых, параметры первичных конструкторов ведут себя как параметры метода или обычного конструктора. Т.е. к этому параметру можно получить доступ и изменить его, как и любой другой параметр, из любого места внутри класса. Например:
После того, как вы вызовете метод Format(), все ссылки на name будут использовать изменённую версию name, поскольку параметр изменяемый. Т.е., если вы собираетесь использовать первичные конструкторы для внедрения зависимостей, любой оператор внутри принимающего класса может изменить значение параметра. По сути, вы не можете доверять тому, что значение параметра соответствует тому, что было передано.
Валидация
Как правило, рекомендуется проверять аргументы конструктора. Типичное место проверки входных данных — конструктор с использованием защитных предложений.
Примечание: я не нашёл, как можно проверять собственно параметры первичного конструктора. Поэтому подозреваю, что это придётся делать при каждом использовании, например:
Если вы знаете другой способ (исключая сторонние библиотеки), пожалуйста, напишите в комментариях.
Внедрение зависимостей
Вы можете использовать первичные конструкторы для зависимостей, как и обычный конструктор:
В небольшом простом классе сервиса может быть приемлемо использовать аргументы первичного конструктора. Однако это быстро может перерасти в проблему.
Во-первых, как упоминалось выше, параметры первичных конструкторов изменяемы. То есть любой метод может изменить их, и тогда полагаться на их значение будет нельзя. Вы не можете пометить их как только для чтения. Пока для этого недостаточно поддержки на уровне языка.
Во-вторых, по мере роста объёма кода класса становится неочевидно, откуда берутся параметры класса. Они называются как закрытые поля полями (с префиксом _), но ими не являются. Если вы попытаетесь получить к ним доступ через this, это не сработает.
DTO
Конечно, это будет работать. Но вам всё равно захочется назначить их свойствам. Однако в этом случае проще использовать запись, которая даст и неизменяемость, и переопределённый ToString, и прочие преимущества.
Итого
Учитывая текущую реализацию первичных конструкторов классов C#:
- Используйте аргументы первичного конструктора только для инициализации полей и свойств. Избегайте доступа к ним где-либо ещё (за исключением, возможно, тривиальных реализаций классов).
- Учитывая, что это параметры, их лучше называть, как и обычные параметры с помощью camelCase, без префикса
- До тех пор, пока не будут доступны дополнительные ограничения для параметров первичного конструктора, они представляют собой ружьё, которым разработчики могут отстрелить себе …, если не будут осторожны. Обязательно включите TreatWarningsAsErrors, чтобы отслеживать любые случаи, когда вы ссылаетесь на параметры уровня класса, помимо инициализации (особенно предупреждение CS9124).
Источник: https://blog.nimblepros.com/blogs/where-csharp-primary-constructors-make-sense/
Где Имеет Смысл Применять Первичные Конструкторы
Первичные конструкторы классов появились в C# 12. Один из первых вопросов, который может возникнуть: как они работают и какова область их применения?
Во-первых, параметры первичных конструкторов ведут себя как параметры метода или обычного конструктора. Т.е. к этому параметру можно получить доступ и изменить его, как и любой другой параметр, из любого места внутри класса. Например:
public class Customer(string name)
{
// выдаст предупреждение компилятора
public string Name { get; } = name;
public string FullName => name;
public void Format() => name = name.ToUpper();
}
var c = new Customer("steve");
c.Format();
Console.WriteLine(c.Name); // steve
Console.WriteLine(c.FullName); // STEVE
После того, как вы вызовете метод Format(), все ссылки на name будут использовать изменённую версию name, поскольку параметр изменяемый. Т.е., если вы собираетесь использовать первичные конструкторы для внедрения зависимостей, любой оператор внутри принимающего класса может изменить значение параметра. По сути, вы не можете доверять тому, что значение параметра соответствует тому, что было передано.
Валидация
Как правило, рекомендуется проверять аргументы конструктора. Типичное место проверки входных данных — конструктор с использованием защитных предложений.
Примечание: я не нашёл, как можно проверять собственно параметры первичного конструктора. Поэтому подозреваю, что это придётся делать при каждом использовании, например:
public class Customer(string name)
{
public string Name
{
get
{
ArgumentException
.ThrowIfNullOrEmpty(nameof(name));
return name;
}
}
}
Если вы знаете другой способ (исключая сторонние библиотеки), пожалуйста, напишите в комментариях.
Внедрение зависимостей
Вы можете использовать первичные конструкторы для зависимостей, как и обычный конструктор:
public class MyService(
IMyRepo _repo,
ILogger<MyService> _logger)
{
…
}
В небольшом простом классе сервиса может быть приемлемо использовать аргументы первичного конструктора. Однако это быстро может перерасти в проблему.
Во-первых, как упоминалось выше, параметры первичных конструкторов изменяемы. То есть любой метод может изменить их, и тогда полагаться на их значение будет нельзя. Вы не можете пометить их как только для чтения. Пока для этого недостаточно поддержки на уровне языка.
Во-вторых, по мере роста объёма кода класса становится неочевидно, откуда берутся параметры класса. Они называются как закрытые поля полями (с префиксом _), но ими не являются. Если вы попытаетесь получить к ним доступ через this, это не сработает.
DTO
Конечно, это будет работать. Но вам всё равно захочется назначить их свойствам. Однако в этом случае проще использовать запись, которая даст и неизменяемость, и переопределённый ToString, и прочие преимущества.
Итого
Учитывая текущую реализацию первичных конструкторов классов C#:
- Используйте аргументы первичного конструктора только для инициализации полей и свойств. Избегайте доступа к ним где-либо ещё (за исключением, возможно, тривиальных реализаций классов).
- Учитывая, что это параметры, их лучше называть, как и обычные параметры с помощью camelCase, без префикса
_
.- До тех пор, пока не будут доступны дополнительные ограничения для параметров первичного конструктора, они представляют собой ружьё, которым разработчики могут отстрелить себе …, если не будут осторожны. Обязательно включите TreatWarningsAsErrors, чтобы отслеживать любые случаи, когда вы ссылаетесь на параметры уровня класса, помимо инициализации (особенно предупреждение CS9124).
Источник: https://blog.nimblepros.com/blogs/where-csharp-primary-constructors-make-sense/
👍14
День 1778. #ЧтоНовенького
Новый Способ Логирования в .NET 8
В последней версии .NET представлен новый, более гибкий и усовершенствованный, способ ведения журнала – атрибут LoggerMessageAttribute.
Вот старый способ:
В .NET 8 атрибут
Чтобы генераторы исходного кода работали, мы должны определить класс как частичный. Генератор кода сгенерирует недостающую часть класса. Получается меньше кода, что приятнее читать. Вы также можете сэкономить драгоценные ресурсы и немного производительности, хотя в 99% случаев это не имеет значения. Но хорошо, что это бесплатно.
Подробнее об атрибуте
Источник: https://steven-giesel.com/blogPost/1add3827-4233-4e31-9ce9-bcc34d64e76f
Новый Способ Логирования в .NET 8
В последней версии .NET представлен новый, более гибкий и усовершенствованный, способ ведения журнала – атрибут LoggerMessageAttribute.
Вот старый способ:
public class MyRepo
{
public async Task Delete(
IEnumerable<string> ids)
{
for (var i = 0; i < totalBatches; i++)
{
…
_logger.LogDebug(
"Deleted Batch {BatchNumber} - {TotalDeleted} elements.",
i+1, (i+1)*batchSize);
}
}
}
В .NET 8 атрибут
LoggerMessageAttribute
получил некоторые расширения, которые помогут вам сделать то же самое с помощью генераторов исходного кода:public partial class MyRepo
{
public async ValueTask DeleteBulkAsync(IEnumerable<string> ids)
{
for (var i = 0; i < totalBatches; i++)
{
…
LogDelete(i+1, (i+1)*batchSize);
}
}
[LoggerMessage(LogLevel.Debug,
"Deleted Batch {BatchNumber} - {TotalDeleted} elements")]
private partial void LogDelete(
int batchNumber, int totalDeleted);
}
Чтобы генераторы исходного кода работали, мы должны определить класс как частичный. Генератор кода сгенерирует недостающую часть класса. Получается меньше кода, что приятнее читать. Вы также можете сэкономить драгоценные ресурсы и немного производительности, хотя в 99% случаев это не имеет значения. Но хорошо, что это бесплатно.
Подробнее об атрибуте
LoggerMessageAttribute
можно почитать в официальном анонсе .NET 8 превью 6.Источник: https://steven-giesel.com/blogPost/1add3827-4233-4e31-9ce9-bcc34d64e76f
👍15👎1
День 1779. #ЗаметкиНаПолях
Сравниваем Алгоритмы Ограничения Обработки Запросов. Начало
Всегда следует устанавливать ограничение на количество входящих запросов. Иначе система может оказаться уязвимой для злоумышленников. Рассмотрим 4 основных алгоритма ограничения обработки запросов.
Ограничение обработки запросов (Rate Limiting) — это способ запретить клиентам слишком часто обращаться к системе.
Преимущества:
1. Защищает систему от DoS атак
Если злоумышленник попытается повлиять на систему, вызывая API так часто, что вся система выйдет из строя, ограничение поможет уменьшить количество выполняемых операций.
2. Добавляет уровень безопасности, предотвращающий атаки грубой силой.
Если злоумышленник попытается получить доступ к системе, перепробовав все возможные пароли, политика ограничения обработки запросов не позволит ему выполнить слишком много попыток.
3. Защищает медленно работающую часть системы.
Если часть системы не может быстро обработать запрос, клиент может добавить политику повтора запроса. Так он может перегрузить и без того плохо работающий компонент, что сделает его совершенно неспособным обрабатывать любые запросы.
Чтобы клиенты знали, что их запросы не обрабатываются из-за слишком частых попыток, нужно использовать код ответа HTTP: 429 Too Many Requests. Так клиенты могут реализовать логику повторных попыток, учитывая это. Ответ также должен включать HTTP-заголовок Retry-After, чтобы сообщить клиенту, как долго ждать перед выполнением следующего запроса.
Теперь рассмотрим стратегии ограничения количества запросов.
1. Фиксированное окно
Ограничивает количество запросов, разрешённых в течение данного временного окна. Временные рамки определяются сервером и одинаковы для всех клиентов.
Допустим, мы можем принимать 100 запросов в минуту. По прошествии минуты, сможем принять ещё 100. Можно выбрать два типа ограничения:
- на уровне пользователя позволяет каждому пользователю выполнять, в нашем примере, 100 запросов в минуту,
- на уровне сервера означает, что сервер способен обрабатывать всего 100 запросов в минуту от всех клиентов.
Алгоритм прост в реализации, но имеет некоторые недостатки:
1) Может допускать всплески запросов в начале или в конце каждого окна, что может перегрузить систему.
2) Предположим, что многие запросы переводятся на следующую минуту. В этом случае вы в итоге добавляете всё больше запросов в начало следующей минуты, вызывая всплеск запросов, которые система может быть не в состоянии обработать.
2. Скользящее окно
Делит время на фиксированные интервалы, и каждый интервал начинается с первого запроса клиента. Если окно составляет 100 запросов в минуту, то:
- Клиент А делает первый запрос в 09:00:05 и может обратиться к системе 100 раз до 09:01:05.
- Клиент B - первый запрос в 09:00:38 - 100 запросов до 09:01:38.
Так оба клиента могут обращаться к системе по 100 раз в минуту, но их временные окна не зависят друг от друга и могут пересекаться.
Этот алгоритм более справедлив, чем алгоритм фиксированного окна, поскольку рассматривает историю запросов каждого клиента независимо. Однако теперь необходимо хранить информацию о количестве запросов и времени окна для каждого клиента, что более сложно и ресурсоемко.
Окончание следует…
Источник: https://www.code4it.dev/architecture-notes/rate-limiting-algorithms/
Сравниваем Алгоритмы Ограничения Обработки Запросов. Начало
Всегда следует устанавливать ограничение на количество входящих запросов. Иначе система может оказаться уязвимой для злоумышленников. Рассмотрим 4 основных алгоритма ограничения обработки запросов.
Ограничение обработки запросов (Rate Limiting) — это способ запретить клиентам слишком часто обращаться к системе.
Преимущества:
1. Защищает систему от DoS атак
Если злоумышленник попытается повлиять на систему, вызывая API так часто, что вся система выйдет из строя, ограничение поможет уменьшить количество выполняемых операций.
2. Добавляет уровень безопасности, предотвращающий атаки грубой силой.
Если злоумышленник попытается получить доступ к системе, перепробовав все возможные пароли, политика ограничения обработки запросов не позволит ему выполнить слишком много попыток.
3. Защищает медленно работающую часть системы.
Если часть системы не может быстро обработать запрос, клиент может добавить политику повтора запроса. Так он может перегрузить и без того плохо работающий компонент, что сделает его совершенно неспособным обрабатывать любые запросы.
Чтобы клиенты знали, что их запросы не обрабатываются из-за слишком частых попыток, нужно использовать код ответа HTTP: 429 Too Many Requests. Так клиенты могут реализовать логику повторных попыток, учитывая это. Ответ также должен включать HTTP-заголовок Retry-After, чтобы сообщить клиенту, как долго ждать перед выполнением следующего запроса.
Теперь рассмотрим стратегии ограничения количества запросов.
1. Фиксированное окно
Ограничивает количество запросов, разрешённых в течение данного временного окна. Временные рамки определяются сервером и одинаковы для всех клиентов.
Допустим, мы можем принимать 100 запросов в минуту. По прошествии минуты, сможем принять ещё 100. Можно выбрать два типа ограничения:
- на уровне пользователя позволяет каждому пользователю выполнять, в нашем примере, 100 запросов в минуту,
- на уровне сервера означает, что сервер способен обрабатывать всего 100 запросов в минуту от всех клиентов.
Алгоритм прост в реализации, но имеет некоторые недостатки:
1) Может допускать всплески запросов в начале или в конце каждого окна, что может перегрузить систему.
2) Предположим, что многие запросы переводятся на следующую минуту. В этом случае вы в итоге добавляете всё больше запросов в начало следующей минуты, вызывая всплеск запросов, которые система может быть не в состоянии обработать.
2. Скользящее окно
Делит время на фиксированные интервалы, и каждый интервал начинается с первого запроса клиента. Если окно составляет 100 запросов в минуту, то:
- Клиент А делает первый запрос в 09:00:05 и может обратиться к системе 100 раз до 09:01:05.
- Клиент B - первый запрос в 09:00:38 - 100 запросов до 09:01:38.
Так оба клиента могут обращаться к системе по 100 раз в минуту, но их временные окна не зависят друг от друга и могут пересекаться.
Этот алгоритм более справедлив, чем алгоритм фиксированного окна, поскольку рассматривает историю запросов каждого клиента независимо. Однако теперь необходимо хранить информацию о количестве запросов и времени окна для каждого клиента, что более сложно и ресурсоемко.
Окончание следует…
Источник: https://www.code4it.dev/architecture-notes/rate-limiting-algorithms/
👍13
День 1780. #ЗаметкиНаПолях
Сравниваем Алгоритмы Ограничения Обработки Запросов. Окончание
Начало
3. Дырявое ведро
Представьте себе ведро с отверстием в дне. Ведро наполняется водой (что символизирует поступающие запросы) с разной скоростью, но вода постоянно вытекает из отверстия. Если ведро уже заполнено и добавляется дополнительная вода, она выливается, что означает отказ от дополнительных запросов.
Этот алгоритм обеспечивает постоянство потока запросов и уменьшает перегрузку. Если запросы добавляются быстрее, чем могут быть обработаны, лишние запросы отбрасываются.
Алгоритм может быть реализован с использованием очереди FIFO (First In, First Out). В очереди хранится список запросов, и фиксированное количество запросов извлекается из очереди с постоянной скоростью, а затем обрабатывается.
Например: каждый запрос заполняет одну ячейку в ведре, и одна ячейка извлекается через постоянные промежутки времени. Если размер ведра 100 запросов, а скорость утечки — 5 запросов в секунду, то, если будет поступать более 5 запросов в секунду, ведро заполнится, а входящие запросы будут блокироваться до тех пор, пока не освободится место.
4. Корзина токенов
Аналогичен алгоритму дырявого ведра, но вместо заполнения слотов запросами он потребляет токены из корзины. Каждому клиенту выделяется определённое количество токенов, которые он может использовать. Он может использовать их все сразу или постепенно.
В корзине теперь есть минимальное (ноль) и максимальное количество доступных токенов. При поступлении запроса система извлекает соответствующее количество токенов из корзины. При этом токены добавляются с постоянной скоростью. Например, в корзину, вместимостью 100 токенов, система может добавлять 5 токенов каждые 10 секунд. Как только корзина достигнет предела, система отбрасывает лишние токены (а не запросы).
Одно из отличий от «дырявого ведра» в том, что «корзина токенов» допускает пакетные запросы, тогда как «дырявое ведро» поддерживает только обработку запросов с постоянной скоростью.
Итого
Здесь лишь поверхностно рассмотрены четыре основных алгоритма ограничения обработки запросов. На картинке ниже они изображены схематически. Каждый из алгоритмов в реальности намного сложнее. Однако знание того, что они существуют и решают различные проблемы, может помочь выбрать тот, который подходит для ваших приложений.
См. также «Промежуточное ПО для ограничений в .NET 7»
Источник: https://www.code4it.dev/architecture-notes/rate-limiting-algorithms/
Сравниваем Алгоритмы Ограничения Обработки Запросов. Окончание
Начало
3. Дырявое ведро
Представьте себе ведро с отверстием в дне. Ведро наполняется водой (что символизирует поступающие запросы) с разной скоростью, но вода постоянно вытекает из отверстия. Если ведро уже заполнено и добавляется дополнительная вода, она выливается, что означает отказ от дополнительных запросов.
Этот алгоритм обеспечивает постоянство потока запросов и уменьшает перегрузку. Если запросы добавляются быстрее, чем могут быть обработаны, лишние запросы отбрасываются.
Алгоритм может быть реализован с использованием очереди FIFO (First In, First Out). В очереди хранится список запросов, и фиксированное количество запросов извлекается из очереди с постоянной скоростью, а затем обрабатывается.
Например: каждый запрос заполняет одну ячейку в ведре, и одна ячейка извлекается через постоянные промежутки времени. Если размер ведра 100 запросов, а скорость утечки — 5 запросов в секунду, то, если будет поступать более 5 запросов в секунду, ведро заполнится, а входящие запросы будут блокироваться до тех пор, пока не освободится место.
4. Корзина токенов
Аналогичен алгоритму дырявого ведра, но вместо заполнения слотов запросами он потребляет токены из корзины. Каждому клиенту выделяется определённое количество токенов, которые он может использовать. Он может использовать их все сразу или постепенно.
В корзине теперь есть минимальное (ноль) и максимальное количество доступных токенов. При поступлении запроса система извлекает соответствующее количество токенов из корзины. При этом токены добавляются с постоянной скоростью. Например, в корзину, вместимостью 100 токенов, система может добавлять 5 токенов каждые 10 секунд. Как только корзина достигнет предела, система отбрасывает лишние токены (а не запросы).
Одно из отличий от «дырявого ведра» в том, что «корзина токенов» допускает пакетные запросы, тогда как «дырявое ведро» поддерживает только обработку запросов с постоянной скоростью.
Итого
Здесь лишь поверхностно рассмотрены четыре основных алгоритма ограничения обработки запросов. На картинке ниже они изображены схематически. Каждый из алгоритмов в реальности намного сложнее. Однако знание того, что они существуют и решают различные проблемы, может помочь выбрать тот, который подходит для ваших приложений.
См. также «Промежуточное ПО для ограничений в .NET 7»
Источник: https://www.code4it.dev/architecture-notes/rate-limiting-algorithms/
👍4
День 1781. #ЗаметкиНаПолях
Доброго зимнего субботнего утра всем. Не желаете ли немного Кавки на завтрак?)))
Да, вот такой у меня сегодня юмор. И нет, я не опечатался в фамилии. Я говорю о Ернеи Кавке, разработчике из Словении. Не так давно он выступил на конференции NDC Oslo с докладом «Common mistakes in EF Core», который я сегодня и хочу вам предложить посмотреть.
Для опытных разработчиков, давно работающих с Entity Framework, он, конечно, не откроет Америки. Ошибки, которые он рассматривает, довольно хорошо известны. Однако, если вам не давал покоя вопрос, насколько же хуже может быть, например, использование IEnumerable вместо IQueriable, то Ерней заморочился с тестами и покажет это наглядно.
В общем, приятногоаппетита просмотра.
Доброго зимнего субботнего утра всем. Не желаете ли немного Кавки на завтрак?)))
Да, вот такой у меня сегодня юмор. И нет, я не опечатался в фамилии. Я говорю о Ернеи Кавке, разработчике из Словении. Не так давно он выступил на конференции NDC Oslo с докладом «Common mistakes in EF Core», который я сегодня и хочу вам предложить посмотреть.
Для опытных разработчиков, давно работающих с Entity Framework, он, конечно, не откроет Америки. Ошибки, которые он рассматривает, довольно хорошо известны. Однако, если вам не давал покоя вопрос, насколько же хуже может быть, например, использование IEnumerable вместо IQueriable, то Ерней заморочился с тестами и покажет это наглядно.
В общем, приятного
YouTube
Common mistakes in EF Core - Jernej Kavka - NDC Oslo 2023
When JK worked with many different clients and projects, he frequently heard "EF Core is slow" or "We should do this in raw SQL" only to realize they haven't used EF Core correctly.
JK will show you how to improve your EF Core statements as well as how various…
JK will show you how to improve your EF Core statements as well as how various…
👍13
День 1782. #ЧтоНовенького
Помечаем Экспериментальные API Атрибутом Experimental
При написании библиотек и фреймворков, которые используют другие, иногда нужно сообщить клиентам, что данный API по-прежнему считается «экспериментальным». Например, предоставить другим возможность работать с частью кода, оставив для себя возможность что-то ломать. В C# 12 это можно сделать с помощью ExperimentalAttribute.
Например, в JetBrains Space SDK есть метод MapSpaceAttachmentProxy, который пока является экспериментальной функцией:
Сборка проекта, использующего этот метод, по умолчанию завершается неудачей с ошибкой “Error SPC101: ‘MapSpaceAttachmentProxy(…)’ is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.” (Ошибка SPC101: 'MapSpaceAttachmentProxy(…)' предназначен только для ознакомительных целей и может быть изменён или удалён в будущих обновлениях. Подавите эту диагностику, чтобы продолжить.)
Также с помощью свойства UrlFormat в атрибут можно добавить URL, где люди смогут найти дополнительную информацию об API. Здесь заместитель {0} MSBuild заменит диагностическим идентификатором:
Вы можете подавить диагностику экспериментальных атрибутов в файле проекта, добавив свойство <NoWarn>:
Либо с помощью директивы pragma в коде:
Что делать в старых версиях языка?
Как вариант, можно использовать атрибут Obsolete. Хотя он по умолчанию отображается только как предупреждение, но, по крайней мере, это будет видно в журнале сборки. Начиная с .NET6, вы также можете добавить к атрибуту диагностический идентификатор, давая людям возможность подавить сообщение, если они согласны использовать этот экспериментальный API:
Источник: https://blog.maartenballiauw.be/post/2023/11/08/opt-in-to-experimental-apis-using-csharp-12-experimentalattribute.html
Помечаем Экспериментальные API Атрибутом Experimental
При написании библиотек и фреймворков, которые используют другие, иногда нужно сообщить клиентам, что данный API по-прежнему считается «экспериментальным». Например, предоставить другим возможность работать с частью кода, оставив для себя возможность что-то ломать. В C# 12 это можно сделать с помощью ExperimentalAttribute.
Например, в JetBrains Space SDK есть метод MapSpaceAttachmentProxy, который пока является экспериментальной функцией:
using System.Diagnostics.CodeAnalysis;
public static class SpaceMapAttachmentProxyExtensions
{
[Experimental("SPC101")]
public static IEndpointConventionBuilder
MapSpaceAttachmentProxy(
this IEndpointRouteBuilder endpoints,
string path)
{
//…
}
}
Сборка проекта, использующего этот метод, по умолчанию завершается неудачей с ошибкой “Error SPC101: ‘MapSpaceAttachmentProxy(…)’ is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.” (Ошибка SPC101: 'MapSpaceAttachmentProxy(…)' предназначен только для ознакомительных целей и может быть изменён или удалён в будущих обновлениях. Подавите эту диагностику, чтобы продолжить.)
Также с помощью свойства UrlFormat в атрибут можно добавить URL, где люди смогут найти дополнительную информацию об API. Здесь заместитель {0} MSBuild заменит диагностическим идентификатором:
[Experimental("SPC101", UrlFormat = "https://www.example.com/diagnostics/{0}.html")]
Вы можете подавить диагностику экспериментальных атрибутов в файле проекта, добавив свойство <NoWarn>:
<Project Sdk="Microsoft.NET.Sdk.Web">
<!-- ... -->
<PropertyGroup>
<NoWarn>SPC101</NoWarn>
</PropertyGroup>
</Project>
Либо с помощью директивы pragma в коде:
#pragma warning disable SPC001
Что делать в старых версиях языка?
Как вариант, можно использовать атрибут Obsolete. Хотя он по умолчанию отображается только как предупреждение, но, по крайней мере, это будет видно в журнале сборки. Начиная с .NET6, вы также можете добавить к атрибуту диагностический идентификатор, давая людям возможность подавить сообщение, если они согласны использовать этот экспериментальный API:
[Obsolete("'MapSpaceAttachmentProxy(...)' is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to remove this warning.", DiagnosticId = "SPC101")]
Источник: https://blog.maartenballiauw.be/post/2023/11/08/opt-in-to-experimental-apis-using-csharp-12-experimentalattribute.html
👍11
День 1783. #ЗаметкиНаПолях
Лучшие Практики Логирования с Serilog. Начало
Serilog — это библиотека структурированного логирования для .NET. Она поддерживает множество мест хранения логов, которые называются приёмники данных (sink): от консоли и файлов до управляемых служб ведения журналов, таких как Application Insights. Рассмотрим лучшие практические советы при использовании Serilog.
1. Используйте систему конфигурации
Настроить Serilog в ASP.NET Core можно двумя способами:
1) Fluent API
Позволяет настраивать Serilog в коде. Недостатком является жёстко закодированная конфигурация. Любые изменения требуют развёртывания новой версии.
2) Система конфигурации
Требует установки библиотеки Serilog.Settings.Configuration. После этого добавьте следующий код:
Ниже настраивается запись логов в консоль, а также в блоке Enrich дополнительная информация для записи в лог:
2. Используйте логирование запросов
Библиотека Serilog.AspNetCore позволяет добавить логирование для конвейера запросов ASP.NET Core. Она добавляет внутренние операции ASP.NET в те же логи, что и события вашего приложения. Для этого надо вызвать метод:
SourceContext для этого типа логов — Serilog.AspNetCore.RequestLoggingMiddleware. Вот пример вывода:
3. Используйте Seq для локальной разработки
Seq — это автономный сервер поиска, анализа и оповещений, созданный для структурированных логов. Его можно бесплатно использовать для локальной разработки. Он предлагает расширенные возможности поиска и фильтрации структурированных логов. Экземпляр Seq можно развернуть в контейнере Docker:
Также в настройках Serilog нужно будет добавить запись логов в Seq. Тогда в панели управления сервера Seq вы сможете анализировать логи.
Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/5-serilog-best-practices-for-better-structured-logging
Лучшие Практики Логирования с Serilog. Начало
Serilog — это библиотека структурированного логирования для .NET. Она поддерживает множество мест хранения логов, которые называются приёмники данных (sink): от консоли и файлов до управляемых служб ведения журналов, таких как Application Insights. Рассмотрим лучшие практические советы при использовании Serilog.
1. Используйте систему конфигурации
Настроить Serilog в ASP.NET Core можно двумя способами:
1) Fluent API
Позволяет настраивать Serilog в коде. Недостатком является жёстко закодированная конфигурация. Любые изменения требуют развёртывания новой версии.
2) Система конфигурации
Требует установки библиотеки Serilog.Settings.Configuration. После этого добавьте следующий код:
builder.Host.UseSerilog((context, сonfig) =>
сonfig.ReadFrom.Configuration(context.Configuration));
Ниже настраивается запись логов в консоль, а также в блоке Enrich дополнительная информация для записи в лог:
{
"Serilog": {
"Using": ["Serilog.Sinks.Console"],
"MinimiumLevel": {
"Default": "Information",
"Override": {
"Micrsoft": "Information"
}
},
"WriteTo": [
{ "Name": "Console" }
],
"Enrich": [
"FromLogContext",
"WithMachineName",
"WithThreadId"
]
}
}
2. Используйте логирование запросов
Библиотека Serilog.AspNetCore позволяет добавить логирование для конвейера запросов ASP.NET Core. Она добавляет внутренние операции ASP.NET в те же логи, что и события вашего приложения. Для этого надо вызвать метод:
app.UseSerilogRequestLogging();
SourceContext для этого типа логов — Serilog.AspNetCore.RequestLoggingMiddleware. Вот пример вывода:
{
"@t": "2023-12-16T00:00:00.0000000Z",
"@mt": "HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms",
"@m": "HTTP POST /api/users responded 409 in 24.7928 ms",
"@i": "37aa1435",
"@r": ["24.7928"],
"@tr": "61a449a8606fdb64e88d6c64b7b7354e",
"@sp": "163ed90674cb12f6",
"ConnectionId": "0HMVSP0L8FVEN",
"CorrelationId": "0HMVSP0L8FVEN:0000000B",
"Elapsed": 24.792778,
"RequestId": "0HMVSP0L8FVEN:0000000B",
"RequestMethod": "POST",
"RequestPath": "/api/users",
"SourceContext": "Serilog.AspNetCore.RequestLoggingMiddleware",
"StatusCode": 409
}
3. Используйте Seq для локальной разработки
Seq — это автономный сервер поиска, анализа и оповещений, созданный для структурированных логов. Его можно бесплатно использовать для локальной разработки. Он предлагает расширенные возможности поиска и фильтрации структурированных логов. Экземпляр Seq можно развернуть в контейнере Docker:
version: '3.4'
services:
seq:
image: datalust/seq:latest
container_name: seq
environment:
- ACCEPT_EULA=Y
ports:
- 5341:5341
- 8081:80
Также в настройках Serilog нужно будет добавить запись логов в Seq. Тогда в панели управления сервера Seq вы сможете анализировать логи.
Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/5-serilog-best-practices-for-better-structured-logging
👍20
День 1784. #ЗаметкиНаПолях
Лучшие Практики Логирования с Serilog. Окончание
Начало
4. Обогатите логи с помощью CorrelationId
Свойство CorrelationId помогает отслеживать логи, относящиеся к одному и тому же запросу. Это также работает в нескольких приложениях. Для этого необходимо передать CorrelationId через HTTP-заголовок, например, X-Correlation-Id. В примере ниже создадим промежуточное ПО для добавления CorrelationId:
Затем добавим промежуточное ПО в конвейер. Обратите внимание, что порядок регистрации важен. Если вам нужен CorrelationId во всех логах, нужно зарегистрировать его в начале:
5. Логируйте важные события приложений
К важным событиям можно отнести информацию о текущем запросе, ошибках, сбоях, неожиданных значениях, точках ветвления и т. д. Одни предпочитают использовать шаблон Result для обработки сбоев приложения. Поэтому понадобится специальное промежуточное ПО для логирования результатов обработки запросов. Другие используют исключения для достижения той же функциональности. Использование исключений для управления потоком — плохая практика. Но все же не забудьте добавить глобальный обработчик для необработанных исключений.
Итого
Все структурированные логи имеют одну и ту же структуру. Это облегчает фильтрацию и поиск конкретной информации в них. Также они предоставляют больше контекста и подробную информацию об ошибках приложений, облегчают выявление и устранение проблем.
Вы можете использовать LogContext в Serilog, чтобы обогатить ваши логи значением CorrelationId, что позволит легко отслеживать все записи, относящиеся к одному запросу.
Когда вы настроите структурированное ведение журнала, вам понадобится искать и анализировать свои журналы. Seq — отличный инструмент для этого, который можно бесплатно использовать для локальной разработки.
Источник: https://www.milanjovanovic.tech/blog/5-serilog-best-practices-for-better-structured-logging
Лучшие Практики Логирования с Serilog. Окончание
Начало
4. Обогатите логи с помощью CorrelationId
Свойство CorrelationId помогает отслеживать логи, относящиеся к одному и тому же запросу. Это также работает в нескольких приложениях. Для этого необходимо передать CorrelationId через HTTP-заголовок, например, X-Correlation-Id. В примере ниже создадим промежуточное ПО для добавления CorrelationId:
public class RequestLoggingMiddleware
{
private const string HEADER = "X-Correlation-Id";
private RequestDelegate _next;
public RequestLoggingMiddleware(
RequestDelegate next)
{
_next = next;
}
public Task Invoke(HttpContext ctx)
{
var cId = GetCorrelationId(ctx);
using (LogContext.PushProperty(
"CorrelationId", cId))
{
return _next.Invoke(ctx);
}
}
private static string GetCorrelationId(
HttpContext ctx)
{
ctx.Request.Headers.TryGetValue(
HEADER, out StringValues cId);
return cId.FirstOrDefault() ?? ctx.TraceIdentifier;
}
}
Затем добавим промежуточное ПО в конвейер. Обратите внимание, что порядок регистрации важен. Если вам нужен CorrelationId во всех логах, нужно зарегистрировать его в начале:
app.UseMiddleware<RequestContextLoggingMiddleware>();
5. Логируйте важные события приложений
К важным событиям можно отнести информацию о текущем запросе, ошибках, сбоях, неожиданных значениях, точках ветвления и т. д. Одни предпочитают использовать шаблон Result для обработки сбоев приложения. Поэтому понадобится специальное промежуточное ПО для логирования результатов обработки запросов. Другие используют исключения для достижения той же функциональности. Использование исключений для управления потоком — плохая практика. Но все же не забудьте добавить глобальный обработчик для необработанных исключений.
Итого
Все структурированные логи имеют одну и ту же структуру. Это облегчает фильтрацию и поиск конкретной информации в них. Также они предоставляют больше контекста и подробную информацию об ошибках приложений, облегчают выявление и устранение проблем.
Вы можете использовать LogContext в Serilog, чтобы обогатить ваши логи значением CorrelationId, что позволит легко отслеживать все записи, относящиеся к одному запросу.
Когда вы настроите структурированное ведение журнала, вам понадобится искать и анализировать свои журналы. Seq — отличный инструмент для этого, который можно бесплатно использовать для локальной разработки.
Источник: https://www.milanjovanovic.tech/blog/5-serilog-best-practices-for-better-structured-logging
👍15
День 1785. #ЗаметкиНаПолях
Разбираем Native AOT в .NET
Сегодня разберём подробно, что такое AOT-компиляция в .NET.
Ahead-of-Time (AOT) компиляция в .NET представляет собой компиляцию кода C# в нативный код на целевом компьютере.
Традиционная компиляция в .NET включает два этапа:
1) Компиляция C# создаёт файлы DLL, содержащие код на промежуточном языке (IL). Такая DLL называется .NET-сборкой.
2) При выполнении программы среда исполнения .NET (CLR) загружает .NET-сборки. Подсистема CLR (Just-In-Time компилятор) отвечает за компиляцию IL-кода метода при первом его вызове в нативный код, выполняемый непосредственно процессором.
С другой стороны, Native AOT компиляция состоит из одного шага: компиляции исходного кода C# в нативный код машины. Это включает преобразование кода C# в код IL, а затем в нативный код, но это детали реализации.
Преимущества
1) Производительность.
Native AOT значительно сокращает время запуска и повышает общую производительность приложения. Отсутствие накладных расходов на JIT-компиляцию во время выполнения приводит к более быстрому выполнению кода.
2) Упрощённое развертывание.
AOT часто приводит к созданию автономных исполняемых файлов с минимальным или нулевым количеством зависимостей. Это упрощает процессы развёртывания, исключая необходимость установки компонентов среды выполнения.
3) Меньший размер приложения.
Удаляя ненужный код, AOT может значительно уменьшить размер приложения. Это не только экономит место, но и оптимизирует использование памяти, что особенно важно в средах с ограниченными ресурсами, таких как мобильные устройства или устройства IoT.
4) Защита исходного кода.
AOT-компиляция преобразует исходный код в оптимизированный машинный код, который более запутан и сложен для расшифровки, чем IL-код, который можно легко декомпилировать в исходный код C#. Это повышает безопасность чувствительных алгоритмов и бизнес-логики.
Недостатки
1) Компиляция для конкретной платформы
AOT создаёт нативный код для конкретной платформы, адаптированный к конкретной архитектуре или операционной системе. Полученный исполняемый файл не будет работать на другой платформе.
2) Нет поддержки кросс-ОС компиляции.
Например, в Windows нельзя создать версию для Linux и наоборот.
3) Частичная поддержка рефлексии.
Рефлексия опирается на динамическую генерацию кода и обнаружение типов во время выполнения, что противоречит природе предварительной компиляции статического кода при AOT. Хотя до некоторой степени рефлексия всё же работает.
4) Требуются зависимости, совместимые с AOT.
Необходимо, чтобы все зависимости, используемые в проекте, были AOT-совместимыми.
5) Увеличенное время сборки.
Генерация нативного кода может значительно увеличить время сборки, особенно для более крупных проектов или приложений с обширной базой кода.
6) Для разработки требуются инструменты C++ разработки.
AOT может компилироваться только с установленными инструментами для C++ разработки, которые могут занимать до 7Гб на диске.
Поддержка Native AOT .NET 8
Поддерживаются:
- Промежуточное ПО
- Минимальные API
- gRPC
- HTTP-Сервер Kestrel
- Авторизация
- Аутентификация через JWT
- CORS
- Проверки работоспособности
- Кэширование вывода и ответа
- Декомпрессия запроса
- Сжатие ответа
- Статические файлы
- Веб-сокеты
- ADO.NET
- PostgreSQL
- Dapper
- SQLite
Не поддерживаются:
- ASP.NET Core MVC
- WebAPI
- SignalR
- Blazor Server
- Razor Pages
- Сессии
- Spa
- Entity Framework Core
Итого
В .NET 8 Native AOT уже достаточно развит и может использоваться в производстве. Мы, безусловно, можем надеяться, что Microsoft продолжит улучшать поддержку AOT.
Источник: https://blog.ndepend.com/net-native-aot-explained/
Разбираем Native AOT в .NET
Сегодня разберём подробно, что такое AOT-компиляция в .NET.
Ahead-of-Time (AOT) компиляция в .NET представляет собой компиляцию кода C# в нативный код на целевом компьютере.
Традиционная компиляция в .NET включает два этапа:
1) Компиляция C# создаёт файлы DLL, содержащие код на промежуточном языке (IL). Такая DLL называется .NET-сборкой.
2) При выполнении программы среда исполнения .NET (CLR) загружает .NET-сборки. Подсистема CLR (Just-In-Time компилятор) отвечает за компиляцию IL-кода метода при первом его вызове в нативный код, выполняемый непосредственно процессором.
С другой стороны, Native AOT компиляция состоит из одного шага: компиляции исходного кода C# в нативный код машины. Это включает преобразование кода C# в код IL, а затем в нативный код, но это детали реализации.
Преимущества
1) Производительность.
Native AOT значительно сокращает время запуска и повышает общую производительность приложения. Отсутствие накладных расходов на JIT-компиляцию во время выполнения приводит к более быстрому выполнению кода.
2) Упрощённое развертывание.
AOT часто приводит к созданию автономных исполняемых файлов с минимальным или нулевым количеством зависимостей. Это упрощает процессы развёртывания, исключая необходимость установки компонентов среды выполнения.
3) Меньший размер приложения.
Удаляя ненужный код, AOT может значительно уменьшить размер приложения. Это не только экономит место, но и оптимизирует использование памяти, что особенно важно в средах с ограниченными ресурсами, таких как мобильные устройства или устройства IoT.
4) Защита исходного кода.
AOT-компиляция преобразует исходный код в оптимизированный машинный код, который более запутан и сложен для расшифровки, чем IL-код, который можно легко декомпилировать в исходный код C#. Это повышает безопасность чувствительных алгоритмов и бизнес-логики.
Недостатки
1) Компиляция для конкретной платформы
AOT создаёт нативный код для конкретной платформы, адаптированный к конкретной архитектуре или операционной системе. Полученный исполняемый файл не будет работать на другой платформе.
2) Нет поддержки кросс-ОС компиляции.
Например, в Windows нельзя создать версию для Linux и наоборот.
3) Частичная поддержка рефлексии.
Рефлексия опирается на динамическую генерацию кода и обнаружение типов во время выполнения, что противоречит природе предварительной компиляции статического кода при AOT. Хотя до некоторой степени рефлексия всё же работает.
4) Требуются зависимости, совместимые с AOT.
Необходимо, чтобы все зависимости, используемые в проекте, были AOT-совместимыми.
5) Увеличенное время сборки.
Генерация нативного кода может значительно увеличить время сборки, особенно для более крупных проектов или приложений с обширной базой кода.
6) Для разработки требуются инструменты C++ разработки.
AOT может компилироваться только с установленными инструментами для C++ разработки, которые могут занимать до 7Гб на диске.
Поддержка Native AOT .NET 8
Поддерживаются:
- Промежуточное ПО
- Минимальные API
- gRPC
- HTTP-Сервер Kestrel
- Авторизация
- Аутентификация через JWT
- CORS
- Проверки работоспособности
- Кэширование вывода и ответа
- Декомпрессия запроса
- Сжатие ответа
- Статические файлы
- Веб-сокеты
- ADO.NET
- PostgreSQL
- Dapper
- SQLite
Не поддерживаются:
- ASP.NET Core MVC
- WebAPI
- SignalR
- Blazor Server
- Razor Pages
- Сессии
- Spa
- Entity Framework Core
Итого
В .NET 8 Native AOT уже достаточно развит и может использоваться в производстве. Мы, безусловно, можем надеяться, что Microsoft продолжит улучшать поддержку AOT.
Источник: https://blog.ndepend.com/net-native-aot-explained/
👍16
День 1786. #Карьера
12 Качеств Сеньора, Которыми Должны Овладеть Джуны. Начало
Самый быстрый способ достичь вершины в любой области — изучать людей, которые уже находятся на вершине… И делать то, что они делают, а вы — нет. Если вы зарабатываете на жизнь написанием кода, вам стоит обратить внимание на навыки, привычки и отличительные черты старших разработчиков.
1. Внимание
Сосредоточиться означает сказать «нет» одним вещам, чтобы заняться другими. В идеале — говорить «да» тому, что позволяет вам прогрессировать, а остальному – «нет». Для многих разработчиков это сложно, потому что это противоречит нашему естественному инстинкту. Признайте, что вы не можете сделать всё и что не у всех равные возможности.
Вы не можете изучить все новинки, посетить все конференции или прочитать все статьи. Ваше время ограничено. Как и ваша энергия.
Как ни странно, чем лучше вы сможете выбирать важные вещи, тем быстрее вы будете прогрессировать. Старшие разработчики говорят больше «нет», чем «да». Они заканчивают больше проектов и осваивают фреймворк, с которым уже работают, прежде чем изучать новый.
Поэтому первое качество, которое нужно развить - сосредоточенность.
2. Мышление второго порядка
Отличительная черта джуна – мышление «давайте сделаем это, а там посмотрим». Они склонны сначала писать код, а потом думать. Это может быть хорошим подходом в начале, но, когда вы работаете над промышленным ПО, некоторые технические решения вы не сможете изменить, или это будет слишком сложно.
Старшие разработчики знают, что, если вы влюбитесь в фреймворки и библиотеки, которые знаете лучше всего, вы начнёте принимать неверные технические решения. Сеньоры дважды думают о последствиях своего выбора и о возможных недостатках, которые может иметь их решение.
Учёт обстоятельств второго порядка сделает вас гораздо лучшим разработчиком. Это также поможет вам во время технических собеседований.
3. Прагматизм
Когда джуны читают книгу о лучших практиках, они сразу же пытаются применить их к каждой строке кода, следуя им неукоснительно. Если вы не можете принимать технические решения самостоятельно, гораздо проще придерживаться заранее определённых правил. Но разработка ПО — это не религия.
Старшие разработчики знают, как сбалансировать лучшие практики и время выхода на рынок. Когда следует использовать костыли, а когда нет. Костыль приведёт к появлению ошибок и технического долга. Постоянное соблюдение правил при изменении контекста вашего кода приведёт к неверным решениям. Нужен баланс. Будьте готовы пересматривать свои технические решения в зависимости от обстоятельств.
4. Состоятельность
Из-за неуверенности в себе младшие разработчики постоянно пытаются доказать другим свою состоятельность. То же самое и со старшими разработчиками, которые не уверены в своей ценности и навыках. Они основывают свою уверенность на подтверждении, которое получают от других. Это проигрышная стратегия - пытаться показать, насколько много вы знаете, в технических дискуссиях, обсуждая других или доделывая работу поздно вечером или на выходных. Такое поведение создаёт токсичную командную среду и приводит к неприятным последствиям.
Есть два способа справиться с этим:
1) Прекратить ожидать признания извне. Правда в том, что вам не нужно никому доказывать свою правоту. Только себе.
2) Примириться с негативными голосами в вашей голове. Вы можете быть своим худшим критиком. Перфекционизм, страх неудачи и ошибочное представление о том, кто такой «настоящий» разработчик, разрушают вашу самооценку. Вот почему, как бы усердно вы ни работали, вы всегда будете чувствовать, что терпите неудачу.
Сосредоточьтесь на овладении своим ремеслом, а остальное приложится. Вы мгновенно станете более уверенными в себе и своих силах. И перестанете пытаться доказать свою правоту незнакомцам.
Продолжение следует…
Источник: https://dev.to/dragosnedelcu/12-senior-developer-traits-junior-developers-need-to-master-285m
12 Качеств Сеньора, Которыми Должны Овладеть Джуны. Начало
Самый быстрый способ достичь вершины в любой области — изучать людей, которые уже находятся на вершине… И делать то, что они делают, а вы — нет. Если вы зарабатываете на жизнь написанием кода, вам стоит обратить внимание на навыки, привычки и отличительные черты старших разработчиков.
1. Внимание
Сосредоточиться означает сказать «нет» одним вещам, чтобы заняться другими. В идеале — говорить «да» тому, что позволяет вам прогрессировать, а остальному – «нет». Для многих разработчиков это сложно, потому что это противоречит нашему естественному инстинкту. Признайте, что вы не можете сделать всё и что не у всех равные возможности.
Вы не можете изучить все новинки, посетить все конференции или прочитать все статьи. Ваше время ограничено. Как и ваша энергия.
Как ни странно, чем лучше вы сможете выбирать важные вещи, тем быстрее вы будете прогрессировать. Старшие разработчики говорят больше «нет», чем «да». Они заканчивают больше проектов и осваивают фреймворк, с которым уже работают, прежде чем изучать новый.
Поэтому первое качество, которое нужно развить - сосредоточенность.
2. Мышление второго порядка
Отличительная черта джуна – мышление «давайте сделаем это, а там посмотрим». Они склонны сначала писать код, а потом думать. Это может быть хорошим подходом в начале, но, когда вы работаете над промышленным ПО, некоторые технические решения вы не сможете изменить, или это будет слишком сложно.
Старшие разработчики знают, что, если вы влюбитесь в фреймворки и библиотеки, которые знаете лучше всего, вы начнёте принимать неверные технические решения. Сеньоры дважды думают о последствиях своего выбора и о возможных недостатках, которые может иметь их решение.
Учёт обстоятельств второго порядка сделает вас гораздо лучшим разработчиком. Это также поможет вам во время технических собеседований.
3. Прагматизм
Когда джуны читают книгу о лучших практиках, они сразу же пытаются применить их к каждой строке кода, следуя им неукоснительно. Если вы не можете принимать технические решения самостоятельно, гораздо проще придерживаться заранее определённых правил. Но разработка ПО — это не религия.
Старшие разработчики знают, как сбалансировать лучшие практики и время выхода на рынок. Когда следует использовать костыли, а когда нет. Костыль приведёт к появлению ошибок и технического долга. Постоянное соблюдение правил при изменении контекста вашего кода приведёт к неверным решениям. Нужен баланс. Будьте готовы пересматривать свои технические решения в зависимости от обстоятельств.
4. Состоятельность
Из-за неуверенности в себе младшие разработчики постоянно пытаются доказать другим свою состоятельность. То же самое и со старшими разработчиками, которые не уверены в своей ценности и навыках. Они основывают свою уверенность на подтверждении, которое получают от других. Это проигрышная стратегия - пытаться показать, насколько много вы знаете, в технических дискуссиях, обсуждая других или доделывая работу поздно вечером или на выходных. Такое поведение создаёт токсичную командную среду и приводит к неприятным последствиям.
Есть два способа справиться с этим:
1) Прекратить ожидать признания извне. Правда в том, что вам не нужно никому доказывать свою правоту. Только себе.
2) Примириться с негативными голосами в вашей голове. Вы можете быть своим худшим критиком. Перфекционизм, страх неудачи и ошибочное представление о том, кто такой «настоящий» разработчик, разрушают вашу самооценку. Вот почему, как бы усердно вы ни работали, вы всегда будете чувствовать, что терпите неудачу.
Сосредоточьтесь на овладении своим ремеслом, а остальное приложится. Вы мгновенно станете более уверенными в себе и своих силах. И перестанете пытаться доказать свою правоту незнакомцам.
Продолжение следует…
Источник: https://dev.to/dragosnedelcu/12-senior-developer-traits-junior-developers-need-to-master-285m
👍29
День 1787. #Карьера
12 Качеств Сеньора, Которыми Должны Овладеть Джуны. Продолжение
Начало
5. Знание основ
Знание фреймворков или библиотек не делает вас сеньором. Это всего лишь верхушка айсберга. Такие темы, как отладка или оптимизация производительности, являются для большинства разработчиков игрой в угадайку. Они не привыкли копаться в глубинах библиотек и инструментов, с которыми работают. Чтобы стать старшим разработчиком, вы должны понимать не только «Что», но и «Почему». Старший разработчик сможет не только создать приложение на фреймворке, но он также понимает, почему он выбрал этот фреймворк, и как он устроен. Хорошая новость заключается в том, что как только вы освоите основы, ваш уровень в целом повысится.
6. Поставка под ключ
Компании избегают нанимать джунов, потому что им нужно много внешней помощи, чтобы добиться цели. Внешняя помощь означает, что вам придётся беспокоить старшего разработчика, чтобы выполнить ваши задачи.
Старшие разработчики выполняют работу «под ключ». Дайте им список требований, а со всем остальным они разберутся. Это не значит, что они волки-одиночки, обычно они отлично умеют работать в команде. И это не означает, что они знают каждую часть жизненного цикла разработки. Но они понимают все основные этапы и могут внести свой вклад в каждый из них (фронтенд, бэкенд, развёртывание).
7. Ментальные модели
Сеньоры могут понимать более сложные кодовые базы и требования. Они могут понять обстоятельства второго порядка. Как изменения в кодовой базе повлияют на производительность, затраты и даже на команду. И это не потому, что они запоминают каждую деталь реализации, а потому что абстрагируют сложность кода в ментальные модели.
Они это делают, изучая фреймворки и библиотеки и лежащие в их основе паттерны проектирования. Паттернов невероятное множество, поэтому лучший способ начать — это выбрать любую среду, с которой вы работаете, и попытаться выйти за рамки кода.
Начните спрашивать себя, почему создатели фреймворка построили его таким образом? Построен он на новых концепциях или это просто реализация старых принципов (что обычно и происходит)? Так вы построите свои ментальные модели разработки и сможете справляться с более сложными задачами.
8. Коммуникация
Сеньоры могут хорошо вести технические дискуссии и влиять на людей вокруг них: бизнес, менеджеров продукта или коллег-разработчиков, - сеньоры знают, как направить их в правильном направлении. Они делают это, используя сочетание настойчивости, технических знаний и коммуникативных навыков.
Также они могут устанавливать чёткие границы. Не соглашаться, не проявляя эмоций, постоять за себя (и других) во время митингов, агрессивно договориться о своей зарплате.
Если коллега во время проверки кода начнёт обвинять других, сеньор знает, как его остановить. Если руководство пытается вмешиваться в работу и заниматься микроменеджментом, сеньор знает, как прекратить это, не повредив отношениям. Не существует пошагового руководства, как таким стать, поможет только практика. Первый шаг — перестать все время говорить «Да». И начать добиваться своего на переговорах о зарплате.
9. Долгосрочное мышление
Джун думает про «сейчас». Он изменяет фрагмент кода, не задумываясь о его правильном рефакторинге, или просто игнорирует тестирование и производительность. Так же джуны думают о своей карьере: слишком часто меняют работу, сжигая мосты, не совершенствуются, если работа стабильна и т.п.
Хорошие вещи требуют времени. Старшие разработчики знают это и соответствующим образом корректируют своё мышление. Если вы решили, что ваша карьера будет связана с разработкой ПО в ближайшие хотя бы 10 лет, инвестируйте в свои навыки, потому что эти инвестиции окупятся. Инвестируйте в коммуникации, потому что никто не знает, когда то или иное знакомство сможет вам пригодиться.
Окончание следует…
Источник: https://dev.to/dragosnedelcu/12-senior-developer-traits-junior-developers-need-to-master-285m
12 Качеств Сеньора, Которыми Должны Овладеть Джуны. Продолжение
Начало
5. Знание основ
Знание фреймворков или библиотек не делает вас сеньором. Это всего лишь верхушка айсберга. Такие темы, как отладка или оптимизация производительности, являются для большинства разработчиков игрой в угадайку. Они не привыкли копаться в глубинах библиотек и инструментов, с которыми работают. Чтобы стать старшим разработчиком, вы должны понимать не только «Что», но и «Почему». Старший разработчик сможет не только создать приложение на фреймворке, но он также понимает, почему он выбрал этот фреймворк, и как он устроен. Хорошая новость заключается в том, что как только вы освоите основы, ваш уровень в целом повысится.
6. Поставка под ключ
Компании избегают нанимать джунов, потому что им нужно много внешней помощи, чтобы добиться цели. Внешняя помощь означает, что вам придётся беспокоить старшего разработчика, чтобы выполнить ваши задачи.
Старшие разработчики выполняют работу «под ключ». Дайте им список требований, а со всем остальным они разберутся. Это не значит, что они волки-одиночки, обычно они отлично умеют работать в команде. И это не означает, что они знают каждую часть жизненного цикла разработки. Но они понимают все основные этапы и могут внести свой вклад в каждый из них (фронтенд, бэкенд, развёртывание).
7. Ментальные модели
Сеньоры могут понимать более сложные кодовые базы и требования. Они могут понять обстоятельства второго порядка. Как изменения в кодовой базе повлияют на производительность, затраты и даже на команду. И это не потому, что они запоминают каждую деталь реализации, а потому что абстрагируют сложность кода в ментальные модели.
Они это делают, изучая фреймворки и библиотеки и лежащие в их основе паттерны проектирования. Паттернов невероятное множество, поэтому лучший способ начать — это выбрать любую среду, с которой вы работаете, и попытаться выйти за рамки кода.
Начните спрашивать себя, почему создатели фреймворка построили его таким образом? Построен он на новых концепциях или это просто реализация старых принципов (что обычно и происходит)? Так вы построите свои ментальные модели разработки и сможете справляться с более сложными задачами.
8. Коммуникация
Сеньоры могут хорошо вести технические дискуссии и влиять на людей вокруг них: бизнес, менеджеров продукта или коллег-разработчиков, - сеньоры знают, как направить их в правильном направлении. Они делают это, используя сочетание настойчивости, технических знаний и коммуникативных навыков.
Также они могут устанавливать чёткие границы. Не соглашаться, не проявляя эмоций, постоять за себя (и других) во время митингов, агрессивно договориться о своей зарплате.
Если коллега во время проверки кода начнёт обвинять других, сеньор знает, как его остановить. Если руководство пытается вмешиваться в работу и заниматься микроменеджментом, сеньор знает, как прекратить это, не повредив отношениям. Не существует пошагового руководства, как таким стать, поможет только практика. Первый шаг — перестать все время говорить «Да». И начать добиваться своего на переговорах о зарплате.
9. Долгосрочное мышление
Джун думает про «сейчас». Он изменяет фрагмент кода, не задумываясь о его правильном рефакторинге, или просто игнорирует тестирование и производительность. Так же джуны думают о своей карьере: слишком часто меняют работу, сжигая мосты, не совершенствуются, если работа стабильна и т.п.
Хорошие вещи требуют времени. Старшие разработчики знают это и соответствующим образом корректируют своё мышление. Если вы решили, что ваша карьера будет связана с разработкой ПО в ближайшие хотя бы 10 лет, инвестируйте в свои навыки, потому что эти инвестиции окупятся. Инвестируйте в коммуникации, потому что никто не знает, когда то или иное знакомство сможет вам пригодиться.
Окончание следует…
Источник: https://dev.to/dragosnedelcu/12-senior-developer-traits-junior-developers-need-to-master-285m
👍20
День 1788. #Карьера
12 Качеств Сеньора, Которыми Должны Овладеть Джуны. Окончание
Начало 1-4
Продолжение 5-9
10. Совершенство как привычка
Кажется, Кент Бек произнес знаменитую фразу «Я не великий программист, я просто хороший программист с отличными привычками». Привычки важны, потому что они выдерживают испытание временем. Любые ваши знания о фреймворке рано или поздно устареют. Технологии меняются. Но ваши привычки останутся с вами навсегда.
Люди — существа привычек. Нелегко установить в голове новый распорядок дня. Но как только мы повторим его много раз, это войдёт в привычку, и будет легко доводить дело до конца. Лучший способ воспользоваться этим — поставить любую цель и разбить её на ежедневные действия. Затем превратите эти действия в привычки посредством повторения.
Если вы хотите стать лучше в тестировании, пишите по одному тесту каждый день. Если вы хотите быть более готовым к ежедневным митингам и ясно мыслить, ведите дневник. Найти новую работу и нужно разослать 100 резюме, отправляйте по 10 каждый день.
Выработайте новые привычки, и ваш прогресс будет постоянным и устойчивым.
11. Защита самого важного актива
Сеньор думает на перспективу не только о своём коде и технических решениях, но и о здоровье. Работа разработчиков сидячая, а это очень вредно для здоровья. Кроме того, в офисе есть всякая мусорная еда. Т.е. если вы не приложите сознательных усилий, вам будет трудно оставаться здоровым и в форме.
Но если вы хотите иметь долгую и продуктивную карьеру без проблем со спиной, диабетом или чем-то похуже, нужно начать заботиться о своём здоровье. Это не значит, ходить в спортзал 5 раз в неделю или сесть на сумасшедшую диету. Занимайтесь спортом хотя бы 2–3 раза в неделю, сократите потребление сахара и быстрых углеводов. Подумайте и о психическом здоровье. На живите по принципу «eat, sleep, code, repeat», стройте жизнь вне работы: найдите хобби, встречайтесь с друзьями, отдыхайте.
В краткосрочной перспективе вы можете прогрессировать немного медленнее. Но в долгосрочной перспективе вы сможете оставаться в игре дольше.
12. Замкните круг
Старшие разработчики понимают, как работает карма. Они знают, что как бы усердно они ни работали или насколько бы умны они ни были, десятки людей помогли им на пути к вершине. Это не умаляет их заслуг, но признаёт вклад других людей. Так они замыкают круг - помогают другим разработчикам. И делают это без обязательств. Не потому, что это может принести повышение, уважение или статус, а потому что это правильно.
Вы также можете найти время, чтобы помочь новичку. Помощь тому, кто только начинает, частично вернёт вам вдохновение. Страсть и любопытство, которые испытывает новичок, когда видит что-то впервые, очень заразительны. Ещё одна вещь, которую вы можете превратить в привычку.
Я ничего не упустил? Какие черты характера сеньоров, по-вашему, следует добавить в список? Пишите в комментарии.
Источник: https://dev.to/dragosnedelcu/12-senior-developer-traits-junior-developers-need-to-master-285m
12 Качеств Сеньора, Которыми Должны Овладеть Джуны. Окончание
Начало 1-4
Продолжение 5-9
10. Совершенство как привычка
Кажется, Кент Бек произнес знаменитую фразу «Я не великий программист, я просто хороший программист с отличными привычками». Привычки важны, потому что они выдерживают испытание временем. Любые ваши знания о фреймворке рано или поздно устареют. Технологии меняются. Но ваши привычки останутся с вами навсегда.
Люди — существа привычек. Нелегко установить в голове новый распорядок дня. Но как только мы повторим его много раз, это войдёт в привычку, и будет легко доводить дело до конца. Лучший способ воспользоваться этим — поставить любую цель и разбить её на ежедневные действия. Затем превратите эти действия в привычки посредством повторения.
Если вы хотите стать лучше в тестировании, пишите по одному тесту каждый день. Если вы хотите быть более готовым к ежедневным митингам и ясно мыслить, ведите дневник. Найти новую работу и нужно разослать 100 резюме, отправляйте по 10 каждый день.
Выработайте новые привычки, и ваш прогресс будет постоянным и устойчивым.
11. Защита самого важного актива
Сеньор думает на перспективу не только о своём коде и технических решениях, но и о здоровье. Работа разработчиков сидячая, а это очень вредно для здоровья. Кроме того, в офисе есть всякая мусорная еда. Т.е. если вы не приложите сознательных усилий, вам будет трудно оставаться здоровым и в форме.
Но если вы хотите иметь долгую и продуктивную карьеру без проблем со спиной, диабетом или чем-то похуже, нужно начать заботиться о своём здоровье. Это не значит, ходить в спортзал 5 раз в неделю или сесть на сумасшедшую диету. Занимайтесь спортом хотя бы 2–3 раза в неделю, сократите потребление сахара и быстрых углеводов. Подумайте и о психическом здоровье. На живите по принципу «eat, sleep, code, repeat», стройте жизнь вне работы: найдите хобби, встречайтесь с друзьями, отдыхайте.
В краткосрочной перспективе вы можете прогрессировать немного медленнее. Но в долгосрочной перспективе вы сможете оставаться в игре дольше.
12. Замкните круг
Старшие разработчики понимают, как работает карма. Они знают, что как бы усердно они ни работали или насколько бы умны они ни были, десятки людей помогли им на пути к вершине. Это не умаляет их заслуг, но признаёт вклад других людей. Так они замыкают круг - помогают другим разработчикам. И делают это без обязательств. Не потому, что это может принести повышение, уважение или статус, а потому что это правильно.
Вы также можете найти время, чтобы помочь новичку. Помощь тому, кто только начинает, частично вернёт вам вдохновение. Страсть и любопытство, которые испытывает новичок, когда видит что-то впервые, очень заразительны. Ещё одна вещь, которую вы можете превратить в привычку.
Я ничего не упустил? Какие черты характера сеньоров, по-вашему, следует добавить в список? Пишите в комментарии.
Источник: https://dev.to/dragosnedelcu/12-senior-developer-traits-junior-developers-need-to-master-285m
👍21
День 1789. #ЧтоНовенького
Новые Аннотации Данных в .NET 8
В .NET 8 появилось несколько дополнений к аннотациям данных, которые обеспечивают большую гибкость при проверке модели в ASP.NET Core.
1. Указание допустимых значений
Атрибут AllowedValues позволяет добавлять к свойству допустимые значения. Значения представляют собой тип object, что означает, что они могут принимать тип свойства. Т.е. можно использовать строки, числа или даже перечисления. В следующем примере для проверки свойства Fruit в классе ValidatedModel должно быть установлено значение банан или яблоко.
2. Запрет определённых значений
Атрибут DeniedValues является противоположностью атрибуту AllowedValues и запрещает определённые значения свойства. Он будет работать с типом, установленным в свойстве. В примере ниже свойство Age не может иметь значение 16 или 17:
3. Проверка строки в кодировке Base64
Атрибут Base64String гарантирует, что строка должна быть закодирована в Base64. Это гарантирует, что свойство пройдёт проверку только в том случае, если значение закодировано. В примере ниже свойство Hash должно быть закодировано в Base64:
4. Указание длины списка
Если у нас есть свойство типа списка, и мы хотим проверять минимальное и максимальное количество элементов, мы можем использовать атрибут Length. В этом примере длина списка любимых фруктов должна быть от 1 до 3 элементов:
5. Границы диапазонов
Атрибут Range существует уже некоторое время, но в него были добавлены дополнительные необязательные параметры. Если для параметра MinimIsExclusive или MaximumIsExclusive установлено значение true, минимальное или максимальное значение будет исключено из диапазона допустимых значений. В примере ниже задан диапазон от 10 до 19, не включая границы:
Источник: https://www.roundthecode.com/dotnet-tutorials/data-annotations-awesome-additions-dotnet-8
Новые Аннотации Данных в .NET 8
В .NET 8 появилось несколько дополнений к аннотациям данных, которые обеспечивают большую гибкость при проверке модели в ASP.NET Core.
1. Указание допустимых значений
Атрибут AllowedValues позволяет добавлять к свойству допустимые значения. Значения представляют собой тип object, что означает, что они могут принимать тип свойства. Т.е. можно использовать строки, числа или даже перечисления. В следующем примере для проверки свойства Fruit в классе ValidatedModel должно быть установлено значение банан или яблоко.
public class ValidatedModel
{
[AllowedValues("banana", "apple")]
public string Fruit { get; set; }
}
2. Запрет определённых значений
Атрибут DeniedValues является противоположностью атрибуту AllowedValues и запрещает определённые значения свойства. Он будет работать с типом, установленным в свойстве. В примере ниже свойство Age не может иметь значение 16 или 17:
public class ValidatedModel
{
[DeniedValues(16, 17)]
public int Age { get; set; }
}
3. Проверка строки в кодировке Base64
Атрибут Base64String гарантирует, что строка должна быть закодирована в Base64. Это гарантирует, что свойство пройдёт проверку только в том случае, если значение закодировано. В примере ниже свойство Hash должно быть закодировано в Base64:
public class ValidatedModel
{
[Base64String]
public string Hash { get; set; }
}
4. Указание длины списка
Если у нас есть свойство типа списка, и мы хотим проверять минимальное и максимальное количество элементов, мы можем использовать атрибут Length. В этом примере длина списка любимых фруктов должна быть от 1 до 3 элементов:
public class ValidatedModel
{
[Length(1, 3)]
public List<string> FavouriteFruits { get; set; }
}
5. Границы диапазонов
Атрибут Range существует уже некоторое время, но в него были добавлены дополнительные необязательные параметры. Если для параметра MinimIsExclusive или MaximumIsExclusive установлено значение true, минимальное или максимальное значение будет исключено из диапазона допустимых значений. В примере ниже задан диапазон от 10 до 19, не включая границы:
public class MyValidationModel
{
[Range(10, 19, MinimumIsExclusive = true, MaximumIsExclusive = true)]
public int Age { get; set; }
}
Источник: https://www.roundthecode.com/dotnet-tutorials/data-annotations-awesome-additions-dotnet-8
👍32
День 1790. #ЗаметкиНаПолях
Перехват HTTP-запросов с помощью DelegatingHandler
Перехват HTTP-запросов позволяет вам выполнить некоторую логику до того, как будет сделан запрос или после получения ответа. В ASP.NET перехватчик можно реализовать с помощью DelegatingHandler.
Вариант использования перехватчика — добавление заголовка (например, авторизации). Если это статическое значение, проще установить его при настройке HttpClient, но, если оно динамическое – это не подойдёт. Другим вариантом использования может быть ведение журнала или обработка ошибок. Нам бы не хотелось засорять процесс выполнения HTTP-запросов слишком большим количеством деталей, а также лучше не повторяться, если одна логика нужна в разных местах.
DelegatingHandler решает эту проблему, предоставляя единую точку, где может существовать эта логика. Общее поведение может быть написано один раз и автоматически применяется ко всем HTTP-запросам (для данного HTTP-клиента). Это упрощает тесты и изменение поведения в будущем.
Заметьте, что в примере использован первичный конструктор, добавленный в C# 12.
Чтобы использовать перехватчик, добавьте его в контейнер DI и зарегистрируйте для HTTP-клиента с помощью AddHttpMessageHandler:
После этих изменений запросы, вызываемые через ExternalClient, будут проходить обработчик AuthHeaderHandler.
Итого
DelegatingHandler позволяет перехватывать HTTP-запрос для выполнения кода до запуска запроса или после получения ответа. Это помогает удалить избыточный код, сохраняя логику приложения чистой и компактной. Подробнее о DelegatingHandler можно почитать в документации.
Источник: https://timdeschryver.dev/blog/intercepting-http-requests-with-a-delegatinghandler
Перехват HTTP-запросов с помощью DelegatingHandler
Перехват HTTP-запросов позволяет вам выполнить некоторую логику до того, как будет сделан запрос или после получения ответа. В ASP.NET перехватчик можно реализовать с помощью DelegatingHandler.
Вариант использования перехватчика — добавление заголовка (например, авторизации). Если это статическое значение, проще установить его при настройке HttpClient, но, если оно динамическое – это не подойдёт. Другим вариантом использования может быть ведение журнала или обработка ошибок. Нам бы не хотелось засорять процесс выполнения HTTP-запросов слишком большим количеством деталей, а также лучше не повторяться, если одна логика нужна в разных местах.
DelegatingHandler решает эту проблему, предоставляя единую точку, где может существовать эта логика. Общее поведение может быть написано один раз и автоматически применяется ко всем HTTP-запросам (для данного HTTP-клиента). Это упрощает тесты и изменение поведения в будущем.
public class AuthHeaderHandler(
IOptions<AuthOptions> opts) : DelegatingHandler
{
protected override async
Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken ct)
{
var token = CreateToken();
request.Headers.Authorization =
new AuthenticationHeaderValue(
"Bearer", bearerToken);
var response = await
base.SendAsync(request, ct);
return response;
}
private string CreateToken()
{
// Получаем токен
return "…";
}
}
Заметьте, что в примере использован первичный конструктор, добавленный в C# 12.
Чтобы использовать перехватчик, добавьте его в контейнер DI и зарегистрируйте для HTTP-клиента с помощью AddHttpMessageHandler:
var builder =
WebApplication.CreateBuilder(args);
builder.Services
.AddTransient<AuthHeaderHandler>();
builder.Services
.AddHttpClient<ExternalClient>(
"external-service",
b =>
{
var url = builder.Configuration
.GetSection("ExternalService:Url").Value;
b.BaseAddress = new Uri(url);
})
.AddHttpMessageHandler<AuthHeaderHandler>();
var app = builder.Build();
app.UseHttpsRedirection();
app.Run();
После этих изменений запросы, вызываемые через ExternalClient, будут проходить обработчик AuthHeaderHandler.
Итого
DelegatingHandler позволяет перехватывать HTTP-запрос для выполнения кода до запуска запроса или после получения ответа. Это помогает удалить избыточный код, сохраняя логику приложения чистой и компактной. Подробнее о DelegatingHandler можно почитать в документации.
Источник: https://timdeschryver.dev/blog/intercepting-http-requests-with-a-delegatinghandler
👍12
День 1791. #DDD
Объекты-Значения в .NET. Начало
Объектом-значением (value object) называется объект, который представляет описательный аспект предметной области и не имеет собственной идентичности. Такие объекты создаются в программе для представления элементов проекта, о которых достаточно знать только, что они собой представляют, но не каким именно предметом они являются.
— Эрик Эванс
Объекты-значения инкапсулируют примитивные типы в предметной области и решают проблему одержимости примитивами.
Основные качества:
- неизменяемость,
- отсутствие идентичности,
- структурное равенство (два объекта-значения равны, если их значения одинаковы).
Реализация
Объект Booking ниже с примитивными значениями, представляющими адрес, а также даты начала и окончания бронирования:
Можно заменить эти примитивы объектами-значениями Address и DateRange:
1. Записи
В С# для представления объектов-значений можно использовать записи. Записи неизменяемы, реализуют структурное равенство и лаконичны за счёт использования первичных конструкторов:
Однако, при этом вы теряете возможность реализовывать инварианты (например, валидацию параметров). Также проблема инвариантов объектов-значений возникает при использовании выражения with.
2. Базовый класс
Альтернативный способ — использование базового класса ValueObject с переопределением равенства (метод GetValues). Наследники должны реализовать этот метод и определить компоненты равенства (равенство каких свойств означает равенство объектов).
Преимущество ValueObject в его явности. Понятно, какие классы домена представляют объекты-значения и какие свойства отвечают за равенство.
Реализация объекта-значения Address:
Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/value-objects-in-dotnet-ddd-fundamentals
Объекты-Значения в .NET. Начало
Объектом-значением (value object) называется объект, который представляет описательный аспект предметной области и не имеет собственной идентичности. Такие объекты создаются в программе для представления элементов проекта, о которых достаточно знать только, что они собой представляют, но не каким именно предметом они являются.
— Эрик Эванс
Объекты-значения инкапсулируют примитивные типы в предметной области и решают проблему одержимости примитивами.
Основные качества:
- неизменяемость,
- отсутствие идентичности,
- структурное равенство (два объекта-значения равны, если их значения одинаковы).
Реализация
Объект Booking ниже с примитивными значениями, представляющими адрес, а также даты начала и окончания бронирования:
public class Booking
{
public string Street { get; init; }
public string City { get; init; }
public string Country { get; init; }
public DateOnly StartDate { get; init; }
public DateOnly EndDate { get; init; }
}
Можно заменить эти примитивы объектами-значениями Address и DateRange:
public class Booking
{
public Address Address { get; init; }
public DateRange Period { get; init; }
}
1. Записи
В С# для представления объектов-значений можно использовать записи. Записи неизменяемы, реализуют структурное равенство и лаконичны за счёт использования первичных конструкторов:
public record Address(
string Street,
string City,
string Country
);
Однако, при этом вы теряете возможность реализовывать инварианты (например, валидацию параметров). Также проблема инвариантов объектов-значений возникает при использовании выражения with.
2. Базовый класс
Альтернативный способ — использование базового класса ValueObject с переопределением равенства (метод GetValues). Наследники должны реализовать этот метод и определить компоненты равенства (равенство каких свойств означает равенство объектов).
Преимущество ValueObject в его явности. Понятно, какие классы домена представляют объекты-значения и какие свойства отвечают за равенство.
public abstract class ValueObject
: IEquatable<ValueObject>
{
public static bool operator ==
(ValueObject? a, ValueObject? b)
{
if (a is null && b is null)
return true;
if (a is null || b is null)
return false;
return a.Equals(b);
}
public static bool operator !=
(ValueObject? a, ValueObject? b)
=> !(a == b);
public virtual bool Equals
(ValueObject? other)
=> other is not null && ValuesEqual(other);
public override bool Equals
(object? obj)
=> obj is ValueObject v
&& ValuesEqual(v);
public override int GetHashCode() =>
GetValues().Aggregate(
default(int),
(hash, value) =>
HashCode.Combine(hash, value.GetHashCode()));
protected abstract IEnumerable<object> GetValues();
private bool ValuesEqual(ValueObject v) =>
GetValues().SequenceEqual(v.GetValues());
}
Реализация объекта-значения Address:
public sealed class Address : ValueObject
{
public string Street { get; init; }
public string City { get; init; }
public string Country { get; init; }
protected override IEnumerable<object> GetValues()
{
yield return Street;
yield return City;
yield return Country;
}
}
Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/value-objects-in-dotnet-ddd-fundamentals
👍16