День 1017. #ЧтоНовенького
Изменения в Структурах в C# 10
C# 10 представляет функции для структур, которые обеспечивают лучшее соответствие структур и классов.
Конструкторы без параметров и инициализаторы полей
До C# 10 каждая структура имела неявный общедоступный конструктор без параметров, который устанавливал для полей структуры значения по умолчанию. Создание конструктора без параметров для структуры было ошибкой.
Теперь вы можете добавлять конструкторы структур без параметров. Они должны быть публичными и не могут быть частичными. Если вы его не добавите, будет предоставлен неявный конструктор без параметров, устанавливающий для всех полей значения по умолчанию.
Структуры-записи
Начиная с C# 10, записи можно определять как структуры:
Структуры и так сравниваются по значению. Структуры-записи добавляют поддержку
Также поддерживается позиционная запись:
Это упрощает преобразование кортежей в именованные типы. Изменение типов возвращаемых значений с кортежа, вроде
Чтобы создать неизменяемую структуру записи, добавьте
Теперь метод
Выражение with в структурах и анонимных типах
C# 10 поддерживает выражение with для всех структур, включая структуры-записи, а также для анонимных типов:
Источник: https://devblogs.microsoft.com/dotnet/welcome-to-csharp-10/
Изменения в Структурах в C# 10
C# 10 представляет функции для структур, которые обеспечивают лучшее соответствие структур и классов.
Конструкторы без параметров и инициализаторы полей
До C# 10 каждая структура имела неявный общедоступный конструктор без параметров, который устанавливал для полей структуры значения по умолчанию. Создание конструктора без параметров для структуры было ошибкой.
Теперь вы можете добавлять конструкторы структур без параметров. Они должны быть публичными и не могут быть частичными. Если вы его не добавите, будет предоставлен неявный конструктор без параметров, устанавливающий для всех полей значения по умолчанию.
public struct Address {Можно инициализировать поля в конструкторе без параметров, как выше, либо через инициализаторы полей или свойств:
public Address() {
City = "<unknown>";
}
public string City { get; init; }
}
public struct Address {Структуры, созданные через ключевое слово
public string City { get; init; } = "<unknown>";
}
default
или при определении массива, игнорируют явные конструкторы без параметров и всегда устанавливают для членов значения по умолчанию.Структуры-записи
Начиная с C# 10, записи можно определять как структуры:
public record struct PersonВы можете продолжить определять записи как классы либо просто по слову
{
public string FirstName { get; init; }
public string LastName { get; init; }
}
record
, либо через record class
для ясности.Структуры и так сравниваются по значению. Структуры-записи добавляют поддержку
IEquatable<T>
и оператор ==
, а также включают переопределение ToString()
.Также поддерживается позиционная запись:
public record struct Person (string FirstName, string LastName);Параметры первичного конструктора становятся публичными свойствами структуры-записи. В отличие от классов-записей, неявно созданные свойства доступны для чтения и записи.
Это упрощает преобразование кортежей в именованные типы. Изменение типов возвращаемых значений с кортежа, вроде
(string FirstName, string LastName)
, на именованный тип Person, может очистить ваш код и гарантировать согласованные имена членов.Чтобы создать неизменяемую структуру записи, добавьте
readonly
в определение структуры или отдельных свойств. Инициализаторы объектов являются частью этапа построения, на котором можно установить свойства только для чтения, поэтому следующая инициализация сработает и для readonly-структур:var person = new Person { FirstName = "Mads", LastName = "Torgersen"};Модификатор sealed для ToString() в классах-записях
Теперь метод
ToString()
может включать модификатор sealed
, который не позволит его переопределять в производных типах записей.Выражение with в структурах и анонимных типах
C# 10 поддерживает выражение with для всех структур, включая структуры-записи, а также для анонимных типов:
var person2 = person with {LastName = "Kristensen"};Выражение возвращает новый экземпляр с новым значением. Вы можете обновить любое количество полей. Поля, которые вы не установили, сохранят то же значение, что и исходный экземпляр.
Источник: https://devblogs.microsoft.com/dotnet/welcome-to-csharp-10/
Вы пользуетесь структурами?
Anonymous Poll
7%
Да, постоянно
38%
Да, но редко
38%
Знаю теоретически, на практике не доводилось
15%
Нет, мало о них знаю
2%
Другой ответ (в комментариях)
День 1018. #ProjectManagement
Почему Надо Выбирать Простую Веб-архитектуру
Координация команды разработчиков — тяжелая работа! Когда команда предлагает вам варианты, не всегда легко понять, что выбрать и почему.
Почему стоит выбрать более простой вариант?
1. Экономия. ПО требует денег на создание, улучшение и поддержку. Решения влияют на бюджет в долгосрочной перспективе. Чем сложнее веб-архитектура, тем больше нужно будет потратить в долгосрочной перспективе на запуск продукта, обеспечение безопасности и улучшения.
2. Обслуживаемость. У руководителей много различных забот и мало времени. Менее сложное ПО будет легче поддерживать в будущем, что сэкономит время и нервы.
3. Доступность. Более сложные архитектуры, такие как одностраничные приложения, могут быть менее доступны по умолчанию и требуют дополнительной работы для обеспечения доступности.
4. Производительность. Приложения, использующие сложные веб-архитектуры, зачастую дольше загружают даже относительно простые данные.
Более простой подход означает:
- Меньше уровней технологий
- Использование стабильных технологий вместо передовых
- По возможности меньше сложности
Ниже представлен план различных архитектур веб-приложений, от самых простых к более сложным.
1. Если можете, сделайте статический сайт
Содержание страниц статического сайта не меняется, пока владелец сайта не обновит его, например, опубликовав новую страницу.
Когда это хороший выбор: многим компаниям просто нужно публиковать информацию о себе в сети. Статические сайты проще всего создавать, поддерживать и размещать. Кроме того, они дешевле.
2. Если статического сайта недостаточно, сделайте серверное приложение
Здесь нужно подумать о создании приложения, базы данных и надёжном хранении пользовательской информации.
Когда это хороший выбор:
- нужна система регистрации и есть разные роли пользователей в приложении,
- нужна сложная логика или обработка данных.
3. Если требуется взаимодействие на стороне клиента, добавьте JavaScript
Веб-браузер может делать вычисления, анимацию и обрабатывать взаимодействия с пользователем. Интерактивность на стороне клиента означает отображение информации или обработку логики в самом браузере.
Когда это хороший выбор: «использование достаточного количества JS» можно рассматривать как способ добавить необходимую интерактивность, не добавляя ненужной сложности. Но нужно поставить вопрос, вводятся ли новые функции в ответ на требования пользователей и тестируются ли они на постоянной основе.
4. Если требуется сложная интерактивность на стороне клиента, может потребоваться одностраничное приложение (single-page application)
React, Angular, Vue.js или Blazor - все эти фреймворки используют JavaScript в браузере для предоставления пользователям функциональных возможностей. Для них часто требуются два набора приложений: на стороне клиента для интерактивности и на стороне сервера для доставки и хранения данных.
Когда это хороший выбор: одностраничные приложения предполагают компромиссы. Из-за нескольких уровней технологий их создание может быть более дорогостоящим и сложным в обслуживании. Часто требуется дополнительная работа, чтобы сделать приложение доступным. Безопасность может быть более сложной задачей. Одностраничные приложения могут быть правильным выбором, когда вы и ваша команда взвесили эти компромиссы и определили, что для предоставления основных функций приложения необходима интенсивная интерактивность на стороне клиента, автономность или отображение данных из публичного API.
Вот несколько вопросов, которые вы можете задать при выборе вариантов веб-архитектуры в проекте:
- Как эти варианты повлияют на доступность, пользовательский опыт и безопасность?
- Сколько разных языков программирования или наборов навыков понадобится, чтобы исправлять проблемы и развёртывать обновления?
- Есть ли пример успешного приложения на этой технологией в арсенале команды?
- Что будет, если команда сменится? Насколько легко или сложно будет нанять разработчиков, обладающих схожими навыками?
Источник: https://18f.gsa.gov/2021/04/05/why_simplicity_choosing_a_web_architecture/
Почему Надо Выбирать Простую Веб-архитектуру
Координация команды разработчиков — тяжелая работа! Когда команда предлагает вам варианты, не всегда легко понять, что выбрать и почему.
Почему стоит выбрать более простой вариант?
1. Экономия. ПО требует денег на создание, улучшение и поддержку. Решения влияют на бюджет в долгосрочной перспективе. Чем сложнее веб-архитектура, тем больше нужно будет потратить в долгосрочной перспективе на запуск продукта, обеспечение безопасности и улучшения.
2. Обслуживаемость. У руководителей много различных забот и мало времени. Менее сложное ПО будет легче поддерживать в будущем, что сэкономит время и нервы.
3. Доступность. Более сложные архитектуры, такие как одностраничные приложения, могут быть менее доступны по умолчанию и требуют дополнительной работы для обеспечения доступности.
4. Производительность. Приложения, использующие сложные веб-архитектуры, зачастую дольше загружают даже относительно простые данные.
Более простой подход означает:
- Меньше уровней технологий
- Использование стабильных технологий вместо передовых
- По возможности меньше сложности
Ниже представлен план различных архитектур веб-приложений, от самых простых к более сложным.
1. Если можете, сделайте статический сайт
Содержание страниц статического сайта не меняется, пока владелец сайта не обновит его, например, опубликовав новую страницу.
Когда это хороший выбор: многим компаниям просто нужно публиковать информацию о себе в сети. Статические сайты проще всего создавать, поддерживать и размещать. Кроме того, они дешевле.
2. Если статического сайта недостаточно, сделайте серверное приложение
Здесь нужно подумать о создании приложения, базы данных и надёжном хранении пользовательской информации.
Когда это хороший выбор:
- нужна система регистрации и есть разные роли пользователей в приложении,
- нужна сложная логика или обработка данных.
3. Если требуется взаимодействие на стороне клиента, добавьте JavaScript
Веб-браузер может делать вычисления, анимацию и обрабатывать взаимодействия с пользователем. Интерактивность на стороне клиента означает отображение информации или обработку логики в самом браузере.
Когда это хороший выбор: «использование достаточного количества JS» можно рассматривать как способ добавить необходимую интерактивность, не добавляя ненужной сложности. Но нужно поставить вопрос, вводятся ли новые функции в ответ на требования пользователей и тестируются ли они на постоянной основе.
4. Если требуется сложная интерактивность на стороне клиента, может потребоваться одностраничное приложение (single-page application)
React, Angular, Vue.js или Blazor - все эти фреймворки используют JavaScript в браузере для предоставления пользователям функциональных возможностей. Для них часто требуются два набора приложений: на стороне клиента для интерактивности и на стороне сервера для доставки и хранения данных.
Когда это хороший выбор: одностраничные приложения предполагают компромиссы. Из-за нескольких уровней технологий их создание может быть более дорогостоящим и сложным в обслуживании. Часто требуется дополнительная работа, чтобы сделать приложение доступным. Безопасность может быть более сложной задачей. Одностраничные приложения могут быть правильным выбором, когда вы и ваша команда взвесили эти компромиссы и определили, что для предоставления основных функций приложения необходима интенсивная интерактивность на стороне клиента, автономность или отображение данных из публичного API.
Вот несколько вопросов, которые вы можете задать при выборе вариантов веб-архитектуры в проекте:
- Как эти варианты повлияют на доступность, пользовательский опыт и безопасность?
- Сколько разных языков программирования или наборов навыков понадобится, чтобы исправлять проблемы и развёртывать обновления?
- Есть ли пример успешного приложения на этой технологией в арсенале команды?
- Что будет, если команда сменится? Насколько легко или сложно будет нанять разработчиков, обладающих схожими навыками?
Источник: https://18f.gsa.gov/2021/04/05/why_simplicity_choosing_a_web_architecture/
День 1019. #ЧтоНовенького
Улучшения Интерполяции Строк в C# 10
Продолжаем знакомиться с новинками в новой версии C#.
Интерполированные обработчики строк
Как известно, компилятор превращает интерполированные строки в вызов
В C# 10 добавили библиотечный шаблон, который позволяет API «брать на себя» обработку аргумента в виде интерполированной строки. Когда используется интерполированная строка, компилятор проверяет, назначена ли интерполированная строка типу, который удовлетворяет шаблону обработчика интерполированной строки. Обработчик интерполированной строки - это особый тип, который преобразует интерполированную строку в обычную строку. Он применяется в специализированных сценариях обычно по соображениям производительности.
Для примера рассмотрим
Авторы API проделали некоторую работу «под капотом» и добавили перегрузки с параметрами вида
Иногда вы хотите выполнить работу по построению строки только при определенных условиях. Примером является
Наконец, вот пример фактического изменения поведения строковой интерполяции.
Константные интерполированные строки
Если все замены в интерполированной строке являются константными строками, тогда результирующая строка также будет константой. Это позволяет использовать синтаксис интерполяции строк в большем количестве мест, например в атрибутах:
Источник: https://devblogs.microsoft.com/dotnet/welcome-to-csharp-10/
Улучшения Интерполяции Строк в C# 10
Продолжаем знакомиться с новинками в новой версии C#.
Интерполированные обработчики строк
Как известно, компилятор превращает интерполированные строки в вызов
string.Format
. Это может привести к большому количеству аллокаций: упаковке аргументов, выделению массива аргументов и, конечно же, самой результирующей строки. Кроме того, он не оставляет места для манёвра в смысле самой интерполяции.В C# 10 добавили библиотечный шаблон, который позволяет API «брать на себя» обработку аргумента в виде интерполированной строки. Когда используется интерполированная строка, компилятор проверяет, назначена ли интерполированная строка типу, который удовлетворяет шаблону обработчика интерполированной строки. Обработчик интерполированной строки - это особый тип, который преобразует интерполированную строку в обычную строку. Он применяется в специализированных сценариях обычно по соображениям производительности.
Для примера рассмотрим
StringBuilder.Append
:var sb = new StringBuilder();До сих пор это вызывало перегрузку
sb.Append($"Привет, {args[0]}, как дела?");
Append(string? value)
, передавая туда аллоцированную и вычисленную строку, и добавляло её к StringBuilder
одним блоком. Однако теперь есть новая перегрузка Append(ref StringBuilder.AppendInterpolatedStringHandler handler)
, которая имеет приоритет над предыдущей, когда в качестве аргумента используется интерполированная строка.Авторы API проделали некоторую работу «под капотом» и добавили перегрузки с параметрами вида
[Something]InterpolatedStringHandler
, чтобы обрабатывать интерполированные строки более подходящим образом для своих целей. В нашем примере с добавлением строки " Привет, "
, args[0]
и ", как дела?"
будут по отдельности добавлены к StringBuilder
, что намного эффективнее, хотя имеет тот же результат.Иногда вы хотите выполнить работу по построению строки только при определенных условиях. Примером является
Debug.Assert
:Debug.Assert(condition, $"{КакойТоСложныйМетод()}");В большинстве случаев
condition
будет true
, и второй параметр не будет использоваться. Однако все аргументы вычисляются при каждом вызове, излишне замедляя выполнение. Debug.Assert
теперь имеет перегрузку с обработчиком интерполированных строк, который гарантирует, что второй аргумент даже не вычисляется, если условие истинно.Наконец, вот пример фактического изменения поведения строковой интерполяции.
String.Create()
позволяет вам указать IFormatProvider
, используемый для форматирования заменяемых выражений:String.Create(CultureInfo.InvariantCulture, $"Ответ: {result}");Значение
result
(число или дата) будет отформатировано в соответствии с переданной культурой.Константные интерполированные строки
Если все замены в интерполированной строке являются константными строками, тогда результирующая строка также будет константой. Это позволяет использовать синтаксис интерполяции строк в большем количестве мест, например в атрибутах:
[Obsolete($"Используйте {nameof(OtherMethod)}")]Обратите внимание, что замещаемые элементы должны быть заполнены константными строками. Другие типы, такие как числовые значения или значения даты, использовать нельзя, поскольку они чувствительны к культуре и не могут быть вычислены во время компиляции.
Источник: https://devblogs.microsoft.com/dotnet/welcome-to-csharp-10/
День 1020. #ЗаметкиНаПолях #AsyncTips
Когда Использовать ValueTask. Начало
Простейший способ реализации метода, возвращающего
В следующем примере показана реализация
Окончание следует…
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Главы 2, 11.
Когда Использовать ValueTask. Начало
ValueTask<T>
используется как возвращаемый тип в ситуациях, в которых чаще всего может быть возвращён синхронный результат, а асинхронное поведение встречается реже. Обычно следует использовать Task<T>
, а не ValueTask<T>
. Рассматривать использование ValueTask<T>
в качестве возвращаемого типа следует только после профилирования, которое показывает, что это приведёт к повышению быстродействия.Простейший способ реализации метода, возвращающего
ValueTask<T>
, основан на использовании async
и await
, как и обычный async-метод. Нередко метод, возвращающий ValueTask<T>
, способен немедленно вернуть значение. В таких случаях можно применить оптимизацию для этого сценария с использованием конструктора ValueTask<T>
, и передавать управление медленному асинхронному методу только при необходимости:public ValueTask<int> MethodAsync()Возможны ситуации, в которых требуется реализовать метод, возвращающий
{
if (CanBehaveSynchronously)
return new ValueTask<int>(13);
return new ValueTask<int>(SlowMethodAsync());
}
private Task<int> SlowMethodAsync();
ValueTask<T>
. Например, при использовании интерфейса IAsyncDisposable
, метод DisposeAsync
которого возвращает ValueTask
. В C# 8.0 и .NET Core 3.0 появилось асинхронное освобождение ресурсов. В BCL появился новый интерфейс IAsyncDisposable
, который является асинхронным аналогом IDisposable
. Также была введена команда await using
— асинхронный аналог using
. Таким образом, типы, которые собирались выполнить асинхронную работу при освобождении, получили такую возможность. Возвращаемым типом DisposeAsync
является ValueTask
, а не Task
.В следующем примере показана реализация
IAsyncDisposable
, которая выполняет свою логику асинхронного освобождения однократно. При следующих вызовах метод DisposeAsync
завершается успешно и синхронно:class MyClass : IAsyncDisposableИспользование:
{
private Func<Task> _disposeLogic;
public ValueTask DisposeAsync()
{
if (_disposeLogic == null)
return default;
// Этот простой пример непотокобезопасный;
// если сразу несколько потоков вызовут DisposeAsync,
// логика может быть выполнена более одного раза.
Func<Task> logic = _disposeLogic;
_disposeLogic = null;
return new ValueTask(logic());
}
}
await using (var myClass = new MyClass())Большинство методов должно возвращать
{
...
} // Здесь вызывается DisposeAsync (с ожиданием)
Task<T>
, поскольку при потреблении Task<T>
возникает меньше скрытых ловушек, чем при потреблении ValueTask<T>
. Чаще всего при реализации интерфейсов, использующих ValueTask
или ValueTask<T>
, можно просто применять async
и await
.Окончание следует…
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Главы 2, 11.
День 1021. #ЗаметкиНаПолях #AsyncTips
Потребление ValueTask
Когда Использовать ValueTask
Задача
Требуется организовать потребление ValueTask<T>.
Решение
В большинстве случаев все, что необходимо сделать – добавить await:
Чтобы сделать что-то более сложное, преобразуйте ValueTask<T> в Task<T> вызовом AsTask:
Также возможны другие операции, например, асинхронное ожидание завершения нескольких операций:
Другие свойства ValueTask<T> предназначены для нетривиального использования. Обычно они работают не так, как другие известные свойства. В частности, для ValueTask<T>.Result действуют более жёсткие ограничения, чем для Task<T>.Result. Код, который синхронно получает результат от ValueTask<T>, может вызвать ValueTask<T>.Result или ValueTask<T>. GetAwaiter().GetResult(), но эти компоненты не должны вызываться до завершения ValueTask<T>. Синхронная загрузка результата из Task<T> блокирует вызывающий поток до завершения задачи; ValueTask<T> таких гарантий не даёт. Синхронное получение результатов от ValueTask или ValueTask<T> может быть выполнено только один раз, после завершения ValueTask, и это значение ValueTask уже не может использоваться для ожидания или преобразования в задачу. В противном случае вы получите непредсказуемый результат операции.
Итого
Когда ваш код вызывает метод, возвращающий ValueTask или ValueTask<T>, он должен либо немедленно выполнить await для этого ValueTask, либо немедленно вызвать AsTask для преобразования в Task. Возможно, эта простая рекомендация не исчерпывает все нетривиальные сценарии, но большинству приложений этого будет вполне достаточно.
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 2.
Потребление ValueTask
Когда Использовать ValueTask
Задача
Требуется организовать потребление ValueTask<T>.
Решение
В большинстве случаев все, что необходимо сделать – добавить await:
ValueTask<int> MethodAsync();Также можно выполнить await после выполнения конкурентной операции, как в случае с Task<T>:
…
int value = await MethodAsync();
ValueTask<int> valueTask = MethodAsync();Однако следует помнить, что ValueTask или ValueTask<T> может ожидаться только один раз.
// Другая параллельная работа.
int value = await valueTask;
Чтобы сделать что-то более сложное, преобразуйте ValueTask<T> в Task<T> вызовом AsTask:
Task<int> task = MethodAsync().AsTask();Многократное ожидание Task<T> абсолютно безопасно.
// Другая параллельная работа.
int value = await task;
int anotherValue = await task;
Также возможны другие операции, например, асинхронное ожидание завершения нескольких операций:
Task<int> task1 = MethodAsync().AsTask();Тем не менее для каждого ValueTask<T> можно вызвать AsTask только один раз. Также вы не можете одновременно использовать await и вызвать AsTask для одного ValueTask<T>.
Task<int> task2 = MethodAsync().AsTask();
int[] results = await Task.WhenAll(task1, task2);
Другие свойства ValueTask<T> предназначены для нетривиального использования. Обычно они работают не так, как другие известные свойства. В частности, для ValueTask<T>.Result действуют более жёсткие ограничения, чем для Task<T>.Result. Код, который синхронно получает результат от ValueTask<T>, может вызвать ValueTask<T>.Result или ValueTask<T>. GetAwaiter().GetResult(), но эти компоненты не должны вызываться до завершения ValueTask<T>. Синхронная загрузка результата из Task<T> блокирует вызывающий поток до завершения задачи; ValueTask<T> таких гарантий не даёт. Синхронное получение результатов от ValueTask или ValueTask<T> может быть выполнено только один раз, после завершения ValueTask, и это значение ValueTask уже не может использоваться для ожидания или преобразования в задачу. В противном случае вы получите непредсказуемый результат операции.
Итого
Когда ваш код вызывает метод, возвращающий ValueTask или ValueTask<T>, он должен либо немедленно выполнить await для этого ValueTask, либо немедленно вызвать AsTask для преобразования в Task. Возможно, эта простая рекомендация не исчерпывает все нетривиальные сценарии, но большинству приложений этого будет вполне достаточно.
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 2.
👍3
День 1022. #ЧтоНовенького
Улучшения Лямбда-Выражений в C# 10
Последний (по крайней мере пока) пост о новинках в новой версии C#. На всякий случай вот предыдущие посты о C# 10 и .NET 6:
- Улучшения в Асинхронности
- Улучшения в LINQ 1, 2
- PriorityQueue
- Статические абстрактные члены интерфейсов
- Обобщённая математика
- IEnumerable.Chunk()
- Глобальные Директивы Using
- Неявные Директивы Using
- Изменения в Структурах
- Улучшения Интерполяции Строк
Выведение типа в лябмдах
Лямбда-выражения теперь могут иметь «естественный» тип, то есть компилятор часто может самостоятельно определить тип лямбда-выражения. До сих пор лямбда-выражение приходилось преобразовывать в тип делегата или выражения. В большинстве случаев вы использовали один из перегруженных типов делегатов Func<…> или Action<…>:
Типы возврата для лямбда-выражений
В предыдущих примерах тип возвращаемого значения лямбда-выражения был очевиден и выводился. Это не всегда так:
Теперь вы можете помещать атрибуты в лямбда-выражения так же, как для методов и локальных функций. Cписок параметров при этом также должен быть заключен в круглые скобки:
Лямбда-выражения вызываются иначе, чем методы и локальные функции, и в результате атрибуты не имеют эффекта при вызове лямбда-выражения. Однако атрибуты лямбда-выражений по-прежнему полезны для анализа кода, и они также генерируются в методах, которые компилятор генерирует для лямбда-выражений, так что их можно обнаружить с помощью рефлексии.
Источник: https://devblogs.microsoft.com/dotnet/welcome-to-csharp-10/
Улучшения Лямбда-Выражений в C# 10
Последний (по крайней мере пока) пост о новинках в новой версии C#. На всякий случай вот предыдущие посты о C# 10 и .NET 6:
- Улучшения в Асинхронности
- Улучшения в LINQ 1, 2
- PriorityQueue
- Статические абстрактные члены интерфейсов
- Обобщённая математика
- IEnumerable.Chunk()
- Глобальные Директивы Using
- Неявные Директивы Using
- Изменения в Структурах
- Улучшения Интерполяции Строк
Выведение типа в лябмдах
Лямбда-выражения теперь могут иметь «естественный» тип, то есть компилятор часто может самостоятельно определить тип лямбда-выражения. До сих пор лямбда-выражение приходилось преобразовывать в тип делегата или выражения. В большинстве случаев вы использовали один из перегруженных типов делегатов Func<…> или Action<…>:
Func<string, int> parse = (string s) => int.Parse(s);Начиная с C# 10 компилятор может вывести тип за вас. Вы можете навести курсор на переменную и убедиться, что её тип всё так же
Func<string, int>
:var parse = (string s) => int.Parse(s);Обычно компилятор будет использовать доступный делегат
Func
или Action
, если подходящий существует. В противном случае он будет синтезировать тип делегата (например, если у вас есть ref-параметры или большое количество параметров). Не все лямбды имеют естественные типы - некоторым просто не хватает информации о типах. Например, если не указывать типы параметров, компилятор не сможет решить, какой тип делегата использовать, что приведёт к ошибке компиляции:var parse = s => int.Parse(s);Вывод естественного типа лямбды означает, что она может быть присвоена более базовому типу, например,
object
или Delegate
:Delegate parse = (string s) => int.Parse(s);В деревьях выражений используется комбинация «целевой» и «естественной» типизации. Если целевым типом является
LambdaExpression
или необобщённый Expression
(базовый тип для всех деревьев выражений), а лямбда имеет естественный тип делегата D
, будет выведен тип Expression<D>
:Expression parseExpr = (string s) => int.Parse(s);Здесь для
parseExpr
будет выведен тип Expression<Func<string, int>>
.Типы возврата для лямбда-выражений
В предыдущих примерах тип возвращаемого значения лямбда-выражения был очевиден и выводился. Это не всегда так:
var choose = (bool b) => b ? 1 : "two";В C# 10 вы можете указать явный тип возвращаемого значения для лямбда-выражения прямо перед параметрами. При этом параметры должны быть заключены в круглые скобки:
// Ошибка, т.к. тип результата непонятен
var choose = object (bool b) => b ? 1 : "two";Атрибуты лямбда-выражений
// Func<bool, object>
Теперь вы можете помещать атрибуты в лямбда-выражения так же, как для методов и локальных функций. Cписок параметров при этом также должен быть заключен в круглые скобки:
Func<string, int> parse =Как и для локальных функции, к лямбдам могут применяться только атрибуты, имеющие
[Example(1)] (s) => int.Parse(s);
var choose =
[Example(2)][Example(3)] object (bool b)
=> b ? 1 : "two";
AttributeTargets.Method
.Лямбда-выражения вызываются иначе, чем методы и локальные функции, и в результате атрибуты не имеют эффекта при вызове лямбда-выражения. Однако атрибуты лямбда-выражений по-прежнему полезны для анализа кода, и они также генерируются в методах, которые компилятор генерирует для лямбда-выражений, так что их можно обнаружить с помощью рефлексии.
Источник: https://devblogs.microsoft.com/dotnet/welcome-to-csharp-10/
Какую версию языка C# вы используете в вашей основной деятельности?
Anonymous Poll
13%
Уже 10 и .NET 6
41%
9 и .NET 5
22%
8 и .NET Core 3.x
3%
7 и .NET Core 2.x
16%
7 в .NET Framework
6%
Более старую версию (другую платформу)
День 1023. #Testing
Когда Использовать Mock-объекты
В тестировании можно пускаться в разные крайности относительно создания объектов-имитаций (mock-объектов). От имитации всего на свете до полного отказа их использовать. Обычно имитировать стоит только один конкретный тип зависимостей - неуправляемые зависимости: зависимости вне процесса, взаимодействия с которыми наблюдаются извне (SMTP-сервис, шина сообщений и т.д.).
Обычно существует несколько классов на пути от пользовательского ввода до вызова неуправляемой зависимости. Например, когда
Вам нужно имитировать акт отправки email (потому что SMTP-сервис является неуправляемой зависимостью), но какой именно класс имитировать?
Нужно имитировать самый последний класс в цепочке. Это позволяет использовать максимальное количество кода и улучшить защиту теста от ошибок.
Ещё один совет - имитировать только те типы, которыми вы владеете. Впервые он был представлен Стивом Фриманом и Натом Прайсом в их книге «Growing Object-Oriented Software, Guided by Tests».
Суть в написании собственных адаптеров поверх сторонних библиотек и имитации этих адаптеров вместо библиотечных типов. Это полезно, потому что:
1. Часто у вас нет глубокого понимания того, как работает сторонний код.
2. Даже если этот код уже предоставляет удобный интерфейс, имитировать этот интерфейс рискованно, потому что вы должны быть уверены, что поведение, которое вы имитируете, соответствует тому, что на самом деле делает внешняя библиотека.
3. Адаптеры абстрагируют несущественные технические детали стороннего кода и определяют отношения с библиотекой в условиях вашего приложения.
4. Если библиотека изменится, не придётся обновлять все тесты (и производственный код), которые с ней работают. Оболочка помогает ограничить такие изменения одним местом - самой оболочкой.
Обратите внимание, что правило имитации только тех типов, которыми вы владеете, не является на 100% строгим. Главное ограничение - ваше понимание того, как работает внешняя библиотека. Если эта библиотека тривиальна (до такой степени, что её поведение становится очевидным), то прямая имитация библиотеки становится приемлемой.
Гойко Аджич уточнил правило «Имитируйте только те типы, которые принадлежат вам», на «Имитируйте только те типы, которые вы понимаете».
Источник: https://enterprisecraftsmanship.com
Автор оригинала: Vladimir Khorikov
Когда Использовать Mock-объекты
В тестировании можно пускаться в разные крайности относительно создания объектов-имитаций (mock-объектов). От имитации всего на свете до полного отказа их использовать. Обычно имитировать стоит только один конкретный тип зависимостей - неуправляемые зависимости: зависимости вне процесса, взаимодействия с которыми наблюдаются извне (SMTP-сервис, шина сообщений и т.д.).
Обычно существует несколько классов на пути от пользовательского ввода до вызова неуправляемой зависимости. Например, когда
UserController
регистрирует пользователя, ему может потребоваться отправить email с подтверждением регистрации. Для этого контроллер может использовать вспомогательный класс, который сам использует другой класс и так далее, в конце концов вызывая SMTP-сервис.Вам нужно имитировать акт отправки email (потому что SMTP-сервис является неуправляемой зависимостью), но какой именно класс имитировать?
Нужно имитировать самый последний класс в цепочке. Это позволяет использовать максимальное количество кода и улучшить защиту теста от ошибок.
Ещё один совет - имитировать только те типы, которыми вы владеете. Впервые он был представлен Стивом Фриманом и Натом Прайсом в их книге «Growing Object-Oriented Software, Guided by Tests».
Суть в написании собственных адаптеров поверх сторонних библиотек и имитации этих адаптеров вместо библиотечных типов. Это полезно, потому что:
1. Часто у вас нет глубокого понимания того, как работает сторонний код.
2. Даже если этот код уже предоставляет удобный интерфейс, имитировать этот интерфейс рискованно, потому что вы должны быть уверены, что поведение, которое вы имитируете, соответствует тому, что на самом деле делает внешняя библиотека.
3. Адаптеры абстрагируют несущественные технические детали стороннего кода и определяют отношения с библиотекой в условиях вашего приложения.
4. Если библиотека изменится, не придётся обновлять все тесты (и производственный код), которые с ней работают. Оболочка помогает ограничить такие изменения одним местом - самой оболочкой.
Обратите внимание, что правило имитации только тех типов, которыми вы владеете, не является на 100% строгим. Главное ограничение - ваше понимание того, как работает внешняя библиотека. Если эта библиотека тривиальна (до такой степени, что её поведение становится очевидным), то прямая имитация библиотеки становится приемлемой.
Гойко Аджич уточнил правило «Имитируйте только те типы, которые принадлежат вам», на «Имитируйте только те типы, которые вы понимаете».
Источник: https://enterprisecraftsmanship.com
Автор оригинала: Vladimir Khorikov
День 1024. #ЧтоНовенького
Однофайловые Приложения в .NET 6
В .NET Core 3.0 мы познакомились с концепцией публикации приложения в виде одного exe-файла. Но в этом релизе было несколько вещей, которые не понравились людям. Основными проблемами были:
- Единственный файл exe на самом деле был самораспаковывающимся zip-архивом, который распаковывался во временное место и затем запускался. Иногда это создавало проблемы с точки зрения безопасности.
- Размер файла был астрономическим (70Мб для «Hello World»), хотя надо сказать, что он включает в себя всю среду исполнения .NET Core, поэтому на целевой машине не нужно было ничего устанавливать.
Давайте посмотрим, что изменилось в .NET 6.
Создадим простейшее консольное приложение:
Если открыть папку
Самораспаковывающегося архива, больше нет
В .NET 6 практика упаковки содержимого в большой архив была изменена на один настоящий исполняемый файл, который загружается в память, а не извлекается во временные папки. Хотя, сжатие можно по-прежнему включить с помощью флага:
.NET 6 имеет возможность убирать ненужные зависимости из вашего приложения. По умолчанию, когда вы публикуете автономное приложение, вы получаете всё. Но, используя функцию тримминга, вы можете удалить из среды исполнения зависимости, которые вы на самом деле не используете.
Заметьте, что это может привести к непредвиденным последствиям, поскольку компилятор не всегда может знать, какие зависимости вы используете, а какие нет (например, если вы используете рефлексию).
Попробуем:
Источник: https://dotnetcoretutorials.com/2021/11/10/single-file-apps-in-net-6/
Однофайловые Приложения в .NET 6
В .NET Core 3.0 мы познакомились с концепцией публикации приложения в виде одного exe-файла. Но в этом релизе было несколько вещей, которые не понравились людям. Основными проблемами были:
- Единственный файл exe на самом деле был самораспаковывающимся zip-архивом, который распаковывался во временное место и затем запускался. Иногда это создавало проблемы с точки зрения безопасности.
- Размер файла был астрономическим (70Мб для «Hello World»), хотя надо сказать, что он включает в себя всю среду исполнения .NET Core, поэтому на целевой машине не нужно было ничего устанавливать.
Давайте посмотрим, что изменилось в .NET 6.
Создадим простейшее консольное приложение:
Console.WriteLine("Hello, World!");Чтобы опубликовать это как единый исполняемый файл, выполним команду в терминале:
Console.ReadLine();
dotnet publish -p:PublishSingleFile=true -r win-x64 -c Release --self-contained trueЗаметьте, что когда вы публикуете один файл, вы должны включать целевой тип ОС, так как exe поставляется специально для этой ОС.
Если открыть папку
MyProject\bin\Release\net6.0\win-x64\publish
, там будет один EXE-файл. Он довольно большой, ~60Мб, (хотя немного меньше, чем был раньше). Исполняемый файл с параметром --self-contained false
получается размером в 151Кб. Понятно, что размер – цена включения среды исполнения.Самораспаковывающегося архива, больше нет
В .NET 6 практика упаковки содержимого в большой архив была изменена на один настоящий исполняемый файл, который загружается в память, а не извлекается во временные папки. Хотя, сжатие можно по-прежнему включить с помощью флага:
-p:EnableCompressionInSingleFile=trueТримминг IL
.NET 6 имеет возможность убирать ненужные зависимости из вашего приложения. По умолчанию, когда вы публикуете автономное приложение, вы получаете всё. Но, используя функцию тримминга, вы можете удалить из среды исполнения зависимости, которые вы на самом деле не используете.
Заметьте, что это может привести к непредвиденным последствиям, поскольку компилятор не всегда может знать, какие зависимости вы используете, а какие нет (например, если вы используете рефлексию).
Попробуем:
dotnet publish -p:PublishSingleFile=true -r win-x64 -c Release --self-contained true -p:PublishTrimmed=trueУ меня получился файл размером ~10Мб. Ещё раз замечу, что это всё приложение, включая среду исполнения. Неплохо!
Источник: https://dotnetcoretutorials.com/2021/11/10/single-file-apps-in-net-6/
День 1026. #ВопросыНаСобеседовании
Сегодня порекомендую вам очередное видео от Сергея Немчинского, в котором он отвечает на популярные вопросы про собеседования.
В какой одежде приходить? Что, если вы опоздали? Сколько времени длится собеседование? Нужно ли писать код на листочке? Почему спрашивают то, что не пригодится на конкретной позиции? Почему компании не дают фидбек в случае, если вы не подошли? И про многое другое.
Честно говоря, после просмотра очень хотелось прособеседоваться у Сергея. Жаль, что он не специализируется в .NET.
https://youtu.be/YeKmEmM7I2A
Сегодня порекомендую вам очередное видео от Сергея Немчинского, в котором он отвечает на популярные вопросы про собеседования.
В какой одежде приходить? Что, если вы опоздали? Сколько времени длится собеседование? Нужно ли писать код на листочке? Почему спрашивают то, что не пригодится на конкретной позиции? Почему компании не дают фидбек в случае, если вы не подошли? И про многое другое.
Честно говоря, после просмотра очень хотелось прособеседоваться у Сергея. Жаль, что он не специализируется в .NET.
https://youtu.be/YeKmEmM7I2A
День 1027. #Карьера
Софт-Скилы, Которые Вам Потребуются, Чтобы Добиться Успеха
При собеседовании на джуна в основном оценивают ваши навыки программирования и ничего больше. При собеседовании на более старшие вакансии эти навыки также важны, но требуется и кое-что ещё. Вот пять ключевых «софт»-навыков, которые действительно выделяют хорошего разработчика ПО из толпы.
1. Эффективная коммуникация
Умение хорошо объяснять ваши идеи другим.
Создание ПО - командный вид спорта. Команда состоит из людей с разным опытом, убеждениями, предубеждениями и знаниями. Если вы хотите создать хороший продукт, вы должны хорошо работать вместе. Система, которую вы разрабатываете, будет имитировать структуру коммуникации вашей организации: плохое общение между членами команды приведет к плохо спроектированным продуктам.
Лучшие разработчики грамотно доносят сложные технические концепции нетехническим людям или младшим специалистам. Вы далеко пойдёте как разработчик, если сможете эффективно общаться и учить других.
2. Эмпатия
Умение ставить себя на место пользователей.
Разработчик должен руководствоваться предназначением своего продукта. Конечно, интересно изучать новые технологии или копаться в последних инструментах разработки, но как насчёт того, почему именно важна наша работа?
Лучшие разработчики заботятся о цели, ради которой они создают ПО, и стремятся понять людей, которым помогают. Существует распространённое упражнение по управлению продуктом под названием «Сопоставление интересов», которое направлено на чёткое определение того, как пользователь думает, чувствует и взаимодействует с продуктом. Понимая поведение и чувства пользователей, мы можем создать продукт, который они будут действительно использовать по назначению.
Слишком часто продукты создаются без предварительного разговора с пользователями. Даже если вы разработчик в команде, понимание того, как думает ваш пользователь, приведёт к улучшению качества продукта.
3. Креативность
Умение искать решения.
Одна из величайших сверхспособностей любого разработчика - это способность гуглить. Когда появляется нерешаемая проблема, креативный разработчик знает, что решение, вероятно, уже существует. А когда этого не происходит, он не боится провести мозговой штурм по поиску нового решения.
Решение проблем требует обдумывания. Оно не приходит свыше, только чтобы бездумно его закодировать. Вы должны исследовать возможности, взвешивая различные технологии и навыки своей команды. После получения некоторого опыта, позволяющего понять, какие технологии существуют, придумать, как объединить эти решения становится проще.
4. Ответственность
Уверенность ваших коллег в том, что вы справитесь со своей работой.
В команде люди полагаются на то, что вы сделаете свою работу, особенно если вы пообещали выполнить задачу. Если вы надёжны, никому не нужно будет следить за вашими успехами, поскольку вы доказали, что можете брать на себя ответственность.
Руководителям нужны разработчики, которым не нужна няня. Им нужны подчиненные, которые соглашаются что-то делать, и выполняют то, за что берутся. Вы не поверите, но многие люди ненадёжны, поэтому ответственный разработчик никогда не пропадёт.
5. Любопытство
Умение задавать достаточно вопросов.
Есть люди, которые никогда не задают вопросов. Обычно это связано со стеснительностью, особенно в больших командах. Однако вопросы могут быть очень полезными, потому что они дают возможность учиться как вам, так и отвечающему.
В индустрии высоких технологий всегда есть чему поучиться. Любознательные разработчики ставят под сомнение существующие нормы, исследуют новые технологии и любят учиться. Задавать вопросы, чтобы бросить вызов устоявшемуся порядку, - отличный способ ускорить прогресс вашей команды. Вопросы - это возможность улучшить себя, свою команду и свой продукт.
Источник: https://betterprogramming.pub/5-soft-skills-you-need-to-succeed-as-a-developer-357f7eac3372
Автор оригинала: Marisa Hoenig
Софт-Скилы, Которые Вам Потребуются, Чтобы Добиться Успеха
При собеседовании на джуна в основном оценивают ваши навыки программирования и ничего больше. При собеседовании на более старшие вакансии эти навыки также важны, но требуется и кое-что ещё. Вот пять ключевых «софт»-навыков, которые действительно выделяют хорошего разработчика ПО из толпы.
1. Эффективная коммуникация
Умение хорошо объяснять ваши идеи другим.
Создание ПО - командный вид спорта. Команда состоит из людей с разным опытом, убеждениями, предубеждениями и знаниями. Если вы хотите создать хороший продукт, вы должны хорошо работать вместе. Система, которую вы разрабатываете, будет имитировать структуру коммуникации вашей организации: плохое общение между членами команды приведет к плохо спроектированным продуктам.
Лучшие разработчики грамотно доносят сложные технические концепции нетехническим людям или младшим специалистам. Вы далеко пойдёте как разработчик, если сможете эффективно общаться и учить других.
2. Эмпатия
Умение ставить себя на место пользователей.
Разработчик должен руководствоваться предназначением своего продукта. Конечно, интересно изучать новые технологии или копаться в последних инструментах разработки, но как насчёт того, почему именно важна наша работа?
Лучшие разработчики заботятся о цели, ради которой они создают ПО, и стремятся понять людей, которым помогают. Существует распространённое упражнение по управлению продуктом под названием «Сопоставление интересов», которое направлено на чёткое определение того, как пользователь думает, чувствует и взаимодействует с продуктом. Понимая поведение и чувства пользователей, мы можем создать продукт, который они будут действительно использовать по назначению.
Слишком часто продукты создаются без предварительного разговора с пользователями. Даже если вы разработчик в команде, понимание того, как думает ваш пользователь, приведёт к улучшению качества продукта.
3. Креативность
Умение искать решения.
Одна из величайших сверхспособностей любого разработчика - это способность гуглить. Когда появляется нерешаемая проблема, креативный разработчик знает, что решение, вероятно, уже существует. А когда этого не происходит, он не боится провести мозговой штурм по поиску нового решения.
Решение проблем требует обдумывания. Оно не приходит свыше, только чтобы бездумно его закодировать. Вы должны исследовать возможности, взвешивая различные технологии и навыки своей команды. После получения некоторого опыта, позволяющего понять, какие технологии существуют, придумать, как объединить эти решения становится проще.
4. Ответственность
Уверенность ваших коллег в том, что вы справитесь со своей работой.
В команде люди полагаются на то, что вы сделаете свою работу, особенно если вы пообещали выполнить задачу. Если вы надёжны, никому не нужно будет следить за вашими успехами, поскольку вы доказали, что можете брать на себя ответственность.
Руководителям нужны разработчики, которым не нужна няня. Им нужны подчиненные, которые соглашаются что-то делать, и выполняют то, за что берутся. Вы не поверите, но многие люди ненадёжны, поэтому ответственный разработчик никогда не пропадёт.
5. Любопытство
Умение задавать достаточно вопросов.
Есть люди, которые никогда не задают вопросов. Обычно это связано со стеснительностью, особенно в больших командах. Однако вопросы могут быть очень полезными, потому что они дают возможность учиться как вам, так и отвечающему.
В индустрии высоких технологий всегда есть чему поучиться. Любознательные разработчики ставят под сомнение существующие нормы, исследуют новые технологии и любят учиться. Задавать вопросы, чтобы бросить вызов устоявшемуся порядку, - отличный способ ускорить прогресс вашей команды. Вопросы - это возможность улучшить себя, свою команду и свой продукт.
Источник: https://betterprogramming.pub/5-soft-skills-you-need-to-succeed-as-a-developer-357f7eac3372
Автор оригинала: Marisa Hoenig
👍1
День 1028. #Microservices
Хватит Использовать Микросервисы. Создавайте Монолиты
Микросервисы могут показаться идеальным решением. Теоретически они увеличивают скорость разработки, позволяя независимо масштабировать различные части вашего приложения. Но на самом деле микросервисы сопряжены со скрытыми расходами. Трудно по-настоящему оценить их сложность, не попробовав создать приложение на микросервисах. Вот с чем приходится сталкиваться.
1. Управление данными превращается в кошмар
Синхронизация данных между микросервисами может быть сложной задачей.
База данных на микросервис - рекомендуемый шаблон. Он обеспечивает слабую связь и позволяет командам, специализирующимся на конкретных сервисах, работать независимо. Но что произойдёт, если один из микросервисов выйдет из строя? Например, один микросервис обновляет свою базу данных, а другой - нет. Подобные ситуации приводят к несогласованности данных. Поиск несоответствий данных между сервисами может быть болезненным. Придётся работать с несколькими сервисами, чтобы исправить ошибку. Это сразу сводит на нет одно из преимуществ – разделение на команды. Такую же ситуацию в монолитном приложении можно было бы легко предотвратить, заключив оба вызова БД в одну атомарную транзакцию. Слабая связь микросервисов усложняет задачу.
2. Больше времени на настройку
Создание архитектуры микросервисов занимает больше времени. Хотя отдельный сервис прост, набор взаимодействующих сервисов значительно сложнее сопоставимого монолита. Функции в монолите могут вызывать любые другие общедоступные функции. Но функции в микросервисе ограничены вызовом функций в том же микросервисе. Это требует создания системы связи между сервисами, что само по себе нетривиальная задача. Кроме того, сложнее избежать дублирования кода.
3. Микросервисы лучше всего подходят для больших команд
Хотя это одно из самых разрекламированных преимуществ микросервисов, вохможность выделить команду на микросервис есть только тогда, когда у вас достаточно специалистов, чтобы выделить несколько инженеров для каждого сервиса. Уменьшение объёма кода позволяет разработчикам лучше понимать код и увеличивает скорость разработки. Но у большинства стартапов этого нет. Тогда некоторым инженерам приходится работать со всеми сервисами. Это снижает производительность, из-за постоянного переключения контекста. А поиск ошибок в микросервисах, над которыми давно не работал, очень утомителен.
4. DevOps усложняется
Одна из наиболее веских причин для выбора микросервисов - это возможность запускать разные сервисы на разных типах серверов. Например, React имеет требования к памяти, процессору и времени безотказной работы отличные от сервиса машинного обучения. Это может значительно снизить затраты. Но тут есть свои проблемы. Например, можно потерять данные, просто забыв обновить один из сервисов. Настройка, обслуживание и мониторинг нескольких микросервисов требует больше усилий по сравнению с одним монолитным приложением. Теоретически «слабосвязанные» сервисы позволяют каждому сервису продолжать работу в случае отказа других. Но это принятие желаемого за действительное: истинная слабая связь редко возможна для сложного бизнеса.
В конце концов, архитектура вашего приложения настолько надежна, насколько надежна ее самая слабая часть. Чем больше движущихся частей, тем больше вероятность ошибки.
Итого
- Многие компании используют микросервисы, даже не нуждаясь в них. И, несмотря на популярность, микросервисы не для новичков.
- Большинству компаний было бы лучше построить монолит, а затем разделить его части на микросервисы, если это абсолютно необходимо.
- Оставьте создание микросервисной архитектуры с нуля для крупных технологических компаний с глубокими карманами.
- Ваш стартап, вероятно, ещё не готов. Это обычно так, и это приводит к большим затратам времени и энергии.
Источник: https://betterprogramming.pub/stop-using-microservices-build-monoliths-instead-9eac180ac908
Хватит Использовать Микросервисы. Создавайте Монолиты
Микросервисы могут показаться идеальным решением. Теоретически они увеличивают скорость разработки, позволяя независимо масштабировать различные части вашего приложения. Но на самом деле микросервисы сопряжены со скрытыми расходами. Трудно по-настоящему оценить их сложность, не попробовав создать приложение на микросервисах. Вот с чем приходится сталкиваться.
1. Управление данными превращается в кошмар
Синхронизация данных между микросервисами может быть сложной задачей.
База данных на микросервис - рекомендуемый шаблон. Он обеспечивает слабую связь и позволяет командам, специализирующимся на конкретных сервисах, работать независимо. Но что произойдёт, если один из микросервисов выйдет из строя? Например, один микросервис обновляет свою базу данных, а другой - нет. Подобные ситуации приводят к несогласованности данных. Поиск несоответствий данных между сервисами может быть болезненным. Придётся работать с несколькими сервисами, чтобы исправить ошибку. Это сразу сводит на нет одно из преимуществ – разделение на команды. Такую же ситуацию в монолитном приложении можно было бы легко предотвратить, заключив оба вызова БД в одну атомарную транзакцию. Слабая связь микросервисов усложняет задачу.
2. Больше времени на настройку
Создание архитектуры микросервисов занимает больше времени. Хотя отдельный сервис прост, набор взаимодействующих сервисов значительно сложнее сопоставимого монолита. Функции в монолите могут вызывать любые другие общедоступные функции. Но функции в микросервисе ограничены вызовом функций в том же микросервисе. Это требует создания системы связи между сервисами, что само по себе нетривиальная задача. Кроме того, сложнее избежать дублирования кода.
3. Микросервисы лучше всего подходят для больших команд
Хотя это одно из самых разрекламированных преимуществ микросервисов, вохможность выделить команду на микросервис есть только тогда, когда у вас достаточно специалистов, чтобы выделить несколько инженеров для каждого сервиса. Уменьшение объёма кода позволяет разработчикам лучше понимать код и увеличивает скорость разработки. Но у большинства стартапов этого нет. Тогда некоторым инженерам приходится работать со всеми сервисами. Это снижает производительность, из-за постоянного переключения контекста. А поиск ошибок в микросервисах, над которыми давно не работал, очень утомителен.
4. DevOps усложняется
Одна из наиболее веских причин для выбора микросервисов - это возможность запускать разные сервисы на разных типах серверов. Например, React имеет требования к памяти, процессору и времени безотказной работы отличные от сервиса машинного обучения. Это может значительно снизить затраты. Но тут есть свои проблемы. Например, можно потерять данные, просто забыв обновить один из сервисов. Настройка, обслуживание и мониторинг нескольких микросервисов требует больше усилий по сравнению с одним монолитным приложением. Теоретически «слабосвязанные» сервисы позволяют каждому сервису продолжать работу в случае отказа других. Но это принятие желаемого за действительное: истинная слабая связь редко возможна для сложного бизнеса.
В конце концов, архитектура вашего приложения настолько надежна, насколько надежна ее самая слабая часть. Чем больше движущихся частей, тем больше вероятность ошибки.
Итого
- Многие компании используют микросервисы, даже не нуждаясь в них. И, несмотря на популярность, микросервисы не для новичков.
- Большинству компаний было бы лучше построить монолит, а затем разделить его части на микросервисы, если это абсолютно необходимо.
- Оставьте создание микросервисной архитектуры с нуля для крупных технологических компаний с глубокими карманами.
- Ваш стартап, вероятно, ещё не готов. Это обычно так, и это приводит к большим затратам времени и энергии.
Источник: https://betterprogramming.pub/stop-using-microservices-build-monoliths-instead-9eac180ac908
👍1
День 1029. #ЗаметкиНаПолях #AsyncTips
Создание асинхронных потоков
Задача
Нужно вернуть несколько значений, при этом каждое значение может потребовать некоторой асинхронной работы.
Решение
Возвращение нескольких значений из метода может осуществляться командой yield return, а асинхронные методы используют async и await. Асинхронные потоки (асинхронные перечисления) объединяют эти два подхода. Используйте возвращаемый тип
Когда метод GetAsync начинает работу, он асинхронный запрашивает первую страницу данных, после чего производит первый элемент. Второй элемент выдаётся немедленно, потому что он содержится на той же странице данных. И т.д. 10 элементов. При запросе 11-го элемента цикл foreach завершится, выполнение цикла while продолжится. На следующей итерации цикла while выполнится асинхронный запрос второй страницы данных, после чего будет выдан 11-й элемент. И т.д…
В течение многих лет использовать async и await с yield return было невозможно, но асинхронные потоки ввели эту возможность. В примере выше стоит обратить внимание, что асинхронная работа нужна не для всех результатов. Здесь только приблизительно одному из каждых 10 элементов потребуется асинхронная работа. Если размер страницы равен 20, то асинхронная работа потребуется только одному из 20 элементов.
Это обычное поведение с асинхронными потоками. Для многих потоков большинство операций асинхронного перебора на самом деле синхронно; асинхронные потоки только позволяют асинхронно получить любой следующий элемент. Асинхронные потоки проектировались с учетом как асинхронного, так и синхронного кода; вот почему они построены на основе ValueTask<T>.
Когда вы реализуете асинхронные потоки, подумайте о поддержке отмены. Некоторые сценарии не требуют реальной отмены: потребляющий код всегда может отказаться от получения следующего элемента. Это абсолютно нормальный подход при отсутствии внешнего источника для отмены. Если вы хотите, чтобы асинхронный поток можно было отменить даже в процессе получения следующего элемента, то следует обеспечить поддержку отмены с использованием
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 3.
Создание асинхронных потоков
Задача
Нужно вернуть несколько значений, при этом каждое значение может потребовать некоторой асинхронной работы.
Решение
Возвращение нескольких значений из метода может осуществляться командой yield return, а асинхронные методы используют async и await. Асинхронные потоки (асинхронные перечисления) объединяют эти два подхода. Используйте возвращаемый тип
IAsyncEnumerable<T>
. В следующем примере асинхронно перебираются результаты API, использующего параметры для страничной организации результатов:async IAsyncEnumerable<string> GetAsync(HttpClient client)
{
int off = 0;
const int lim = 10;
while (true)
{
// Получаем текущую страницу результатов
var result = await client.GetStringAsync(
$"{apiURL}/values?offset={off}&limit={lim}"
);
var values = result.Split('\n');
// Выдаём результаты с этой страницы
foreach (var value in values)
yield return value;
// Если последняя страница, выходим
if (values.Length != lim)
break;
// Переходим к следующей странице
off += lim;
}
}
Когда метод GetAsync начинает работу, он асинхронный запрашивает первую страницу данных, после чего производит первый элемент. Второй элемент выдаётся немедленно, потому что он содержится на той же странице данных. И т.д. 10 элементов. При запросе 11-го элемента цикл foreach завершится, выполнение цикла while продолжится. На следующей итерации цикла while выполнится асинхронный запрос второй страницы данных, после чего будет выдан 11-й элемент. И т.д…
В течение многих лет использовать async и await с yield return было невозможно, но асинхронные потоки ввели эту возможность. В примере выше стоит обратить внимание, что асинхронная работа нужна не для всех результатов. Здесь только приблизительно одному из каждых 10 элементов потребуется асинхронная работа. Если размер страницы равен 20, то асинхронная работа потребуется только одному из 20 элементов.
Это обычное поведение с асинхронными потоками. Для многих потоков большинство операций асинхронного перебора на самом деле синхронно; асинхронные потоки только позволяют асинхронно получить любой следующий элемент. Асинхронные потоки проектировались с учетом как асинхронного, так и синхронного кода; вот почему они построены на основе ValueTask<T>.
Когда вы реализуете асинхронные потоки, подумайте о поддержке отмены. Некоторые сценарии не требуют реальной отмены: потребляющий код всегда может отказаться от получения следующего элемента. Это абсолютно нормальный подход при отсутствии внешнего источника для отмены. Если вы хотите, чтобы асинхронный поток можно было отменить даже в процессе получения следующего элемента, то следует обеспечить поддержку отмены с использованием
CancellationToken
.Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 3.
👍1
День 1030. #ЗаметкиНаПолях #AsyncTips
Потребление асинхронных потоков
Создание асинхронных потоков
Задача: обработать результаты асинхронного потока.
Решение
Потребление асинхронного потока основано на объединении конструкций ожидания и перечисления в
На концептуальном уровне вызывается метод
Также можно выполнить асинхронную обработку каждого элемента:
В этом случае
В
Итого
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 3.
Потребление асинхронных потоков
Создание асинхронных потоков
Задача: обработать результаты асинхронного потока.
Решение
Потребление асинхронного потока основано на объединении конструкций ожидания и перечисления в
await foreach
. Например, для асинхронного потока, который потребляет ответы API по страницам, можно организовать вывод элементов в консоль:public async Task ProcessAsync(HttpClient client)
{
await foreach (var value in GetAsync(client))
{
Console.WriteLine(value);
}
}
На концептуальном уровне вызывается метод
GetAsync
, который возвращает IAsyncEnumerable<T>
. Цикл foreach затем создаёт асинхронный перечислитель на базе асинхронного потока. Асинхронные перечислители на логическом уровне похожи на обычные перечислители, не считая того, что операция «получить следующий элемент» может быть асинхронной. Таким образом, await foreach
будет ожидать поступления следующего элемента или завершения асинхронного перечислителя. Если элемент поступил, то await foreach
выполнит тело цикла; если асинхронный перечислитель завершён, происходит выход из цикла.Также можно выполнить асинхронную обработку каждого элемента:
await foreach (var val in GetAsync(client))
{
// асинхронная работа
await Task.Delay(100);
Console.WriteLine(val);
}
В этом случае
await foreach
не переходит к следующему элементу до завершения тела цикла. Таким образом, await foreach
асинхронно получит первый элемент, после чего асинхронно выполнит тело цикла для первого элемента, затем асинхронно получит второй элемент, асинхронно выполнит тело цикла для второго элемента и т.д.В
await foreach
скрыта команда await: к операции «получить следующий элемент» применяется await
. С обычной командой await
можно обойти захват контекста с помощью ConfigureAwait(false)
. Асинхронные потоки также это поддерживают:await foreach (var val in
GetValuesAsync(client).ConfigureAwait(false))
{
await Task.Delay(100)
.ConfigureAwait(false);
Console.WriteLine(val);
}
Итого
await foreach
— самый логичный способ потребления асинхронных потоков. Язык поддерживает ConfigureAwait(false)
для предотвращения захвата контекста в await foreach
. Также возможен вариант с передачей маркеров отмены. Об этом позже.Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 3.
День 1031. #Карьера
Как Избежать Вредных Привычек, Работая Удалённо
Локдаун поспособствовал переходу многих разработчиков ПО на удалёнку. Но возникла проблема, как сохранить рабочий настрой дома? Ниже приведены пять вредных привычек, которые могут завести работающие дома, и советы, как их избежать.
1. Совмещение домашних и рабочих задач
Это может не показаться дурной привычкой. В конце концов, одновременное выполнение множества дел помогает сделать больше, не так ли? Так почему бы не помыть посуду, пока вы сидите на вебинаре, только не забыв отключить звук.
Некоторые люди склонны выполнять несколько задач одновременно, когда их руководители и коллеги не видят. Но одновременное выполнение двух или более дел, особенно когда вы выполняете домашние задачи в рабочее время или наоборот, приводит только к чрезмерному стрессу. Многозадачность никогда не бывает так же эффективна, как концентрация на одной задаче.
Делайте только одно дело за раз и в первую очередь беритесь за самые насущные проекты. Одновременное выполнение нескольких дел только помешает вам делать что-либо из них эффективно.
2. Работа круглосуточно
То, что вы можете работать с полуночи до 3 часов ночи, не означает, что вы должны это делать. На самом деле, наиболее продуктивные люди работают в обычное время, без выходных или сверхурочных. Кэл Ньюпорт - профессор вычислительной техники Джорджтаунского университета - в своей книге «В работу с головой» («Deep Work») помогает повысить продуктивность на работе.
Один из примеров - то, что он называет «продуктивностью по графику». Планирование всего рабочего дня по часам, заранее, при этом позволяя себе перемещать блоки при необходимости. По словам Ньюпорта, поддержание регулярного рабочего графика и отключение «домашнего офиса» в конце рабочего дня - это наиболее эффективный способ работы без стресса или выгорания. Если вы ограничиваете свой рабочий день, вам не нужно работать по ночам из-за того, что вы тратили рабочее время на социальные сети.
3. Проверка почты и «мелкая работа»
По словам Ньюпорта, важная работа требует умственного труда и большой концентрации. Не избегайте этого, заполняя время мелкой работой, которую Ньюпорт определяет как «когнитивно простые логистические задачи, которые часто выполняются в фоновом режиме». Это проверка почты, сотни мелких правок в вашей презентации и прочие слабо связанные с основной работой вещи.
Когда вы сохраняете свои умственные способности, чтобы по-настоящему сосредоточиться на поставленной задаче, вы сможете сделать её даже лучше, чем ожидали. Это потому, что, погрузившись в работу с головой, вы попадаете в состояние потока, когда время проходит незаметно.
4. Домашняя одежда
Возможно, вы шутили с друзьями о том, что весь день работаете в пижаме. Но, если вы действительно так делаете, самое время надеть соответствующую рабочую одежду. По словам Шэрон Койфман, президента кадрового агентства, которое нанимает удалённых сотрудников, между тем, что вы носите, и вашим настроением существует сильная связь. Вот почему рекомендуется вставать в установленное время и носить ту же одежду, что и в реальном офисе, вплоть до обуви. Профессиональная одежда способствует профессиональному отношению. С другой стороны, пижама может вселить в вас чувство неопрятности и дезорганизованности.
5. Экономия на инструментах
Домашний офис должен быть оснащён теми же инструментами и технологиями, которые используются в реальном офисе, или даже лучше. Удалённым сотрудникам нужен хороший микрофон, который экранирует фоновый шум (например, лай соседской собаки), и эргономичные офисные стол и кресло, чтобы избежать боли в спине, запястьях и т.п.
Есть ещё один бонусный совет: сохраняйте чувство юмора. Оно понадобится вам, когда дети шумят в соседней комнате, где-то на улице орёт автомобильная сигнализация, а вашему боссу нужно срочно провести онлайн конференцию.
Удалёнщики, какие у вас возникали плохие привычки, и как вы с ними боролись?
Источник: https://www.asme.org/topics-resources/content/five-tips-in-avoiding-bad-habits-when-working-remotely
Как Избежать Вредных Привычек, Работая Удалённо
Локдаун поспособствовал переходу многих разработчиков ПО на удалёнку. Но возникла проблема, как сохранить рабочий настрой дома? Ниже приведены пять вредных привычек, которые могут завести работающие дома, и советы, как их избежать.
1. Совмещение домашних и рабочих задач
Это может не показаться дурной привычкой. В конце концов, одновременное выполнение множества дел помогает сделать больше, не так ли? Так почему бы не помыть посуду, пока вы сидите на вебинаре, только не забыв отключить звук.
Некоторые люди склонны выполнять несколько задач одновременно, когда их руководители и коллеги не видят. Но одновременное выполнение двух или более дел, особенно когда вы выполняете домашние задачи в рабочее время или наоборот, приводит только к чрезмерному стрессу. Многозадачность никогда не бывает так же эффективна, как концентрация на одной задаче.
Делайте только одно дело за раз и в первую очередь беритесь за самые насущные проекты. Одновременное выполнение нескольких дел только помешает вам делать что-либо из них эффективно.
2. Работа круглосуточно
То, что вы можете работать с полуночи до 3 часов ночи, не означает, что вы должны это делать. На самом деле, наиболее продуктивные люди работают в обычное время, без выходных или сверхурочных. Кэл Ньюпорт - профессор вычислительной техники Джорджтаунского университета - в своей книге «В работу с головой» («Deep Work») помогает повысить продуктивность на работе.
Один из примеров - то, что он называет «продуктивностью по графику». Планирование всего рабочего дня по часам, заранее, при этом позволяя себе перемещать блоки при необходимости. По словам Ньюпорта, поддержание регулярного рабочего графика и отключение «домашнего офиса» в конце рабочего дня - это наиболее эффективный способ работы без стресса или выгорания. Если вы ограничиваете свой рабочий день, вам не нужно работать по ночам из-за того, что вы тратили рабочее время на социальные сети.
3. Проверка почты и «мелкая работа»
По словам Ньюпорта, важная работа требует умственного труда и большой концентрации. Не избегайте этого, заполняя время мелкой работой, которую Ньюпорт определяет как «когнитивно простые логистические задачи, которые часто выполняются в фоновом режиме». Это проверка почты, сотни мелких правок в вашей презентации и прочие слабо связанные с основной работой вещи.
Когда вы сохраняете свои умственные способности, чтобы по-настоящему сосредоточиться на поставленной задаче, вы сможете сделать её даже лучше, чем ожидали. Это потому, что, погрузившись в работу с головой, вы попадаете в состояние потока, когда время проходит незаметно.
4. Домашняя одежда
Возможно, вы шутили с друзьями о том, что весь день работаете в пижаме. Но, если вы действительно так делаете, самое время надеть соответствующую рабочую одежду. По словам Шэрон Койфман, президента кадрового агентства, которое нанимает удалённых сотрудников, между тем, что вы носите, и вашим настроением существует сильная связь. Вот почему рекомендуется вставать в установленное время и носить ту же одежду, что и в реальном офисе, вплоть до обуви. Профессиональная одежда способствует профессиональному отношению. С другой стороны, пижама может вселить в вас чувство неопрятности и дезорганизованности.
5. Экономия на инструментах
Домашний офис должен быть оснащён теми же инструментами и технологиями, которые используются в реальном офисе, или даже лучше. Удалённым сотрудникам нужен хороший микрофон, который экранирует фоновый шум (например, лай соседской собаки), и эргономичные офисные стол и кресло, чтобы избежать боли в спине, запястьях и т.п.
Есть ещё один бонусный совет: сохраняйте чувство юмора. Оно понадобится вам, когда дети шумят в соседней комнате, где-то на улице орёт автомобильная сигнализация, а вашему боссу нужно срочно провести онлайн конференцию.
Удалёнщики, какие у вас возникали плохие привычки, и как вы с ними боролись?
Источник: https://www.asme.org/topics-resources/content/five-tips-in-avoiding-bad-habits-when-working-remotely
👍1
День 1032. #юмор
А править прямо на проде. Ммм... непередаваемые ощущения.
А править прямо на проде. Ммм... непередаваемые ощущения.
День 1033. #Карьера
Чему Можно Научиться из Книг «Программист-прагматик» и «Идеальный программист». Часть 1
Вы найдете эти книги почти в каждой подборке «10 лучших книг по разработке ПО». Когда вы разрабатываете ПО, вы можете застрять на том, что видео из YouTube и ответы на StackOverflow не помогают. Вы в итоге обращаетесь к документации или к исходному коду этой технологии, чтобы найти ответ. То же самое происходит, когда вы хотите действительно глубоко понять предмет. Иногда статей может не хватать, и чтение хороших книг - лучший выход. В этих книгах основное внимание уделяется не столько написанию кода, сколько обучению передовым методам разработки и даже полезным жизненным урокам.
1. Как брать на себя ответственность
Как разработчик вы несёте ответственность за создаваемый код. Вы должны убедиться, что он не только работает сейчас, но и будет работать наилучшим образом в течение длительного времени.
Программист-прагматик принимает на себя ответственность за свою собственную карьеру и не боится признаваться в незнании или ошибке.
- Программист-прагматик
Однако ответственность связана не только с написанием кода. Вы также должны взять на себя ответственность за самосовершенствование и выделение времени для этого.
Профессионалы не жалеют времени на совершенствование в своей профессии. Скорей всего, вы стали разработчиком, потому что вы увлечены программным обеспечением, и ваше желание стать профессионалом мотивировано этой страстью.
- Идеальный программист
Знание и опыт являются самыми важными профессиональными активами.
- Программист-прагматик
2. Тестирование важно
Важность тестирования в разработке ПО настолько велика, что обе книги посвящены этой теме. Вы должны смотреть на тесты как на первых пользователей вашего кода, т.к. они являются лучшей обратной связью, которая ведёт вашу разработку.
Практикуйтесь в разработке через тестирование (TDD):
- Выберите функцию, которую нужно добавить, и напишите тест, который пройдёт после её реализации. Теперь все тесты, кроме нового, должны проходить.
- Напишите код, необходимый для прохождения теста.
- Выполните рефакторинг кода и убедитесь, что все тесты проходят.
При этом важно смотреть на картину в целом и не упустить главную цель, создавая слишком много тестов.
Есть три способа тестирования: «сначала», «во время» и «никогда». «Сначала» (TDD) - лучший. «Во время» - запасной вариант, когда первый бесполезен. «Никогда» часто называют «протестирую позже», но, к сожалению, в большинстве случаев «позже» означает «никогда».
Наличие тестов даёт вам уверенность в необходимости более частого рефакторинга кода, потому что вы можете убедиться, что тесты по-прежнему проходят после внесения изменений.
Тесты следует выполнять как можно чаще, чтобы обеспечить максимальную обратную связь и гарантировать постоянную «чистоту» системы.
- Идеальный программист
Используйте приёмочные тесты, чтобы определить, выполняются ли требования, в сотрудничестве с заинтересованными сторонами.
У разработчиков должна быть цель: «QA не должен ничего находить». Вы можете добиться этого, реализуя различные виды тестов: модульные, компонентные, интеграционные, системные, приёмочные.
Продолжение следует…
Источник: https://www.freecodecamp.org/news/lessons-learned-from-the-pragmatic-programmer-and-the-clean-coder/
Чему Можно Научиться из Книг «Программист-прагматик» и «Идеальный программист». Часть 1
Вы найдете эти книги почти в каждой подборке «10 лучших книг по разработке ПО». Когда вы разрабатываете ПО, вы можете застрять на том, что видео из YouTube и ответы на StackOverflow не помогают. Вы в итоге обращаетесь к документации или к исходному коду этой технологии, чтобы найти ответ. То же самое происходит, когда вы хотите действительно глубоко понять предмет. Иногда статей может не хватать, и чтение хороших книг - лучший выход. В этих книгах основное внимание уделяется не столько написанию кода, сколько обучению передовым методам разработки и даже полезным жизненным урокам.
1. Как брать на себя ответственность
Как разработчик вы несёте ответственность за создаваемый код. Вы должны убедиться, что он не только работает сейчас, но и будет работать наилучшим образом в течение длительного времени.
Программист-прагматик принимает на себя ответственность за свою собственную карьеру и не боится признаваться в незнании или ошибке.
- Программист-прагматик
Однако ответственность связана не только с написанием кода. Вы также должны взять на себя ответственность за самосовершенствование и выделение времени для этого.
Профессионалы не жалеют времени на совершенствование в своей профессии. Скорей всего, вы стали разработчиком, потому что вы увлечены программным обеспечением, и ваше желание стать профессионалом мотивировано этой страстью.
- Идеальный программист
Знание и опыт являются самыми важными профессиональными активами.
- Программист-прагматик
2. Тестирование важно
Важность тестирования в разработке ПО настолько велика, что обе книги посвящены этой теме. Вы должны смотреть на тесты как на первых пользователей вашего кода, т.к. они являются лучшей обратной связью, которая ведёт вашу разработку.
Практикуйтесь в разработке через тестирование (TDD):
- Выберите функцию, которую нужно добавить, и напишите тест, который пройдёт после её реализации. Теперь все тесты, кроме нового, должны проходить.
- Напишите код, необходимый для прохождения теста.
- Выполните рефакторинг кода и убедитесь, что все тесты проходят.
При этом важно смотреть на картину в целом и не упустить главную цель, создавая слишком много тестов.
Есть три способа тестирования: «сначала», «во время» и «никогда». «Сначала» (TDD) - лучший. «Во время» - запасной вариант, когда первый бесполезен. «Никогда» часто называют «протестирую позже», но, к сожалению, в большинстве случаев «позже» означает «никогда».
Наличие тестов даёт вам уверенность в необходимости более частого рефакторинга кода, потому что вы можете убедиться, что тесты по-прежнему проходят после внесения изменений.
Тесты следует выполнять как можно чаще, чтобы обеспечить максимальную обратную связь и гарантировать постоянную «чистоту» системы.
- Идеальный программист
Используйте приёмочные тесты, чтобы определить, выполняются ли требования, в сотрудничестве с заинтересованными сторонами.
У разработчиков должна быть цель: «QA не должен ничего находить». Вы можете добиться этого, реализуя различные виды тестов: модульные, компонентные, интеграционные, системные, приёмочные.
Продолжение следует…
Источник: https://www.freecodecamp.org/news/lessons-learned-from-the-pragmatic-programmer-and-the-clean-coder/
День 1034.
Асинхронный Обмен Сообщениями. Начало
1. Основы распределённой архитектуры
Это совсем не новая проблема, но в последние несколько лет она становится все более и более распространённой. Кроме того, эту проблему трудно решить быстро - или даже быстро описать решение.
Задача
Проблема обычно проявляется в желании досрочно вернуться из HTTP-запроса. Как только запрос был получен, разработчик хочет, чтобы серверный API не дожидался завершения обработки, а немедленно отправил ответ клиенту. Обычно это называют «запустил и забыл».
Цель состоит в том, чтобы HTTP-вызов просто запускал рабочий процесс. Затем этот рабочий процесс выполнялся бы на стороне сервера без дополнительных действий со стороны клиентского приложения.
Назовём это «внешний запрос», т.к. это код, который выполняется вне основного запроса. Это может быть опасно, поэтому решение более сложное, чем кажется на первый взгляд необходимым.
Решение
Подходящим решением для внешнего запроса является асинхронный обмен сообщениями. Он состоит из двух частей (с необязательной третьей частью):
1) Перманентная очередь
Под «перманентной» подразумевается очередь, которая, по крайней мере, сохраняется на диск при добавлении элемента. Другими словами, сообщения, отправленные в очередь, долговечны. Таким образом, очереди в памяти
2) Бэкенд-сервис
Это независимый сервис, который читает из этой перманентной очереди и обрабатывает элементы в ней (т.е. выполняет длительную операцию).
3) (необязательно) Какой-либо метод получения результатов.
Если клиенту необходимо знать результат длительной операции, то это та часть, которая предоставляет этот результат клиенту.
Один из распространённых примеров - отправка e-mail. Если API хочет отправить письмо, но не хочет ждать окончания отправки перед возвратом клиенту, то API должен добавить сообщение в перманентную очередь с описанием отправляемого письма, а затем вернуться. Поскольку это перманентная очередь, сообщение очереди сохраняется на диск перед отправкой HTTP-ответа клиенту. Затем отдельный сервис, читающий из этой очереди, извлекает сообщение и фактически отправляет e-mail.
Другой распространённый пример - запись в базу данных. Иногда возникают ситуации, когда API знает, что писать в БД, но не хочет заставлять клиента ждать. В этом случае API должен записать информацию в перманентную очередь, а затем выдать ответ клиенту. Затем отдельный бэкенд-сервис, читающий из этой очереди, извлекает информацию и выполняет фактическое обновление БД.
Получения результатов часто не требуется. Например, собственно письмо обычно является результатом отправки e-mail, а записи в базе данных в итоге будут отображаться, когда пользователь обновит страницу. Но иногда вам нужно, чтобы клиент был уведомлён о результатах. Это возможно либо с помощью опроса, либо с помощью упреждающего уведомления с использованием технологии обмена сообщениями, такой как WebSockets.
Далее мы подробно остановимся на каждой части решения и рассмотрим конкретные подходы.
Продолжение следует…
Источник: https://blog.stephencleary.com/2021/01/asynchronous-messaging-1-basic-distributed-architecture.html
Асинхронный Обмен Сообщениями. Начало
1. Основы распределённой архитектуры
Это совсем не новая проблема, но в последние несколько лет она становится все более и более распространённой. Кроме того, эту проблему трудно решить быстро - или даже быстро описать решение.
Задача
Проблема обычно проявляется в желании досрочно вернуться из HTTP-запроса. Как только запрос был получен, разработчик хочет, чтобы серверный API не дожидался завершения обработки, а немедленно отправил ответ клиенту. Обычно это называют «запустил и забыл».
Цель состоит в том, чтобы HTTP-вызов просто запускал рабочий процесс. Затем этот рабочий процесс выполнялся бы на стороне сервера без дополнительных действий со стороны клиентского приложения.
Назовём это «внешний запрос», т.к. это код, который выполняется вне основного запроса. Это может быть опасно, поэтому решение более сложное, чем кажется на первый взгляд необходимым.
Решение
Подходящим решением для внешнего запроса является асинхронный обмен сообщениями. Он состоит из двух частей (с необязательной третьей частью):
1) Перманентная очередь
Под «перманентной» подразумевается очередь, которая, по крайней мере, сохраняется на диск при добавлении элемента. Другими словами, сообщения, отправленные в очередь, долговечны. Таким образом, очереди в памяти
Queue<T>
, BlockingCollection<T>
или ChannelWriter<T>
не являются «перманентными очередями».2) Бэкенд-сервис
Это независимый сервис, который читает из этой перманентной очереди и обрабатывает элементы в ней (т.е. выполняет длительную операцию).
3) (необязательно) Какой-либо метод получения результатов.
Если клиенту необходимо знать результат длительной операции, то это та часть, которая предоставляет этот результат клиенту.
Один из распространённых примеров - отправка e-mail. Если API хочет отправить письмо, но не хочет ждать окончания отправки перед возвратом клиенту, то API должен добавить сообщение в перманентную очередь с описанием отправляемого письма, а затем вернуться. Поскольку это перманентная очередь, сообщение очереди сохраняется на диск перед отправкой HTTP-ответа клиенту. Затем отдельный сервис, читающий из этой очереди, извлекает сообщение и фактически отправляет e-mail.
Другой распространённый пример - запись в базу данных. Иногда возникают ситуации, когда API знает, что писать в БД, но не хочет заставлять клиента ждать. В этом случае API должен записать информацию в перманентную очередь, а затем выдать ответ клиенту. Затем отдельный бэкенд-сервис, читающий из этой очереди, извлекает информацию и выполняет фактическое обновление БД.
Получения результатов часто не требуется. Например, собственно письмо обычно является результатом отправки e-mail, а записи в базе данных в итоге будут отображаться, когда пользователь обновит страницу. Но иногда вам нужно, чтобы клиент был уведомлён о результатах. Это возможно либо с помощью опроса, либо с помощью упреждающего уведомления с использованием технологии обмена сообщениями, такой как WebSockets.
Далее мы подробно остановимся на каждой части решения и рассмотрим конкретные подходы.
Продолжение следует…
Источник: https://blog.stephencleary.com/2021/01/asynchronous-messaging-1-basic-distributed-architecture.html