День восемьсот семьдесят второй. #Оффтоп #КакСтатьСеньором
Проектирование
Почему я ставлю проектирование после написания кода и тестирования? Оно может идти и первым, но, если бы я не писал код и не тестировал его в среде, в которой я нахожусь (под средой тут понимается в том числе и стек технологий), я, вероятно, не смог бы спроектировать систему, которая учитывает особенности среды.
При проектировании системы нужно о многом подумать:
- Какая будет нагрузка?
- Сколько существует пользователей и каков их ожидаемый прирост? (Это может повлиять на размер БД)
- Какие могут быть подводные камни в будущем?
Всё это нужно преобразовать в контрольный список требований. Тут важно соблюсти баланс: какую часть вы можете спроектировать, прежде чем приступить к реализации? Когда имеет смысл нырять с головой в реализацию, а когда делать шаг назад?
Конечно, просто собрать требования - это еще не всё, о чем стоит подумать. Включение процессов разработки в проектирование также окупается:
- Как будет организовано написание кода, сборка, развёртывание и CI/CD?
- Как мы будем проводить сквозное и нагрузочное тестирование?
- Как мы будем управлять секретами?
Например, кто бы мог подумать, что управление секретами в производственной среде может оказаться таким сложным? Вы не можете поместить их в код, так как тогда их сможет увидеть любой.
Поместить их в переменные среды? Хорошая идея. Как их туда поместить и как ими управлять? Хранить файл секретов? Откуда он будет браться и как его изменять? И т.д., и т.п. Кроме того, мы не хотим, чтобы всё это выполнялось вручную. Можно рассмотреть базу данных, чтобы код получал секреты из базы при запуске. Опять же, подход может сильно отличаться при использовании облачного провайдера, где не нужно много думать о секретах, т.к. для этого есть специальный функционал.
Проектирование с учетом поддержки
Проектировать системы - это увлекательно. Поддерживать их – не очень. Рано или поздно задаёшься вопросом, почему и как системы деградируют?
Во-первых, проблема в нежелании выбрасывать старые вещи, всегда добавляя новые. Склонность к добавлению вместо удаления (есть за вами такой грешок?)
Вторая проблема — это проектирование с учётом конечной цели. Система, которая эволюционирует, добавляя функционал, который не был в неё изначально заложен, никогда не работает так же хорошо, как система, разработанная с нуля для этого функционала.
Есть как минимум три способа снизить скорость деградации:
1. Разделяйте бизнес-логику и инфраструктуру. Обычно быстрее деградирует инфраструктура: увеличивается нагрузка, фреймворки устаревают, появляются уязвимости и т.д.
2. Стройте процессы вокруг поддержки. Обновляйте как новый, так и устаревший код. Это предотвращает различие между новыми и старыми частями и сохраняет весь код «современным».
3. Убедитесь, что вы на постоянной основе избавляетесь от всех ненужных/устаревших вещей.
Источник: https://neilkakkar.com/things-I-learnt-from-a-senior-dev.html
Автор оригинала – Neil Kakkar
Проектирование
Почему я ставлю проектирование после написания кода и тестирования? Оно может идти и первым, но, если бы я не писал код и не тестировал его в среде, в которой я нахожусь (под средой тут понимается в том числе и стек технологий), я, вероятно, не смог бы спроектировать систему, которая учитывает особенности среды.
При проектировании системы нужно о многом подумать:
- Какая будет нагрузка?
- Сколько существует пользователей и каков их ожидаемый прирост? (Это может повлиять на размер БД)
- Какие могут быть подводные камни в будущем?
Всё это нужно преобразовать в контрольный список требований. Тут важно соблюсти баланс: какую часть вы можете спроектировать, прежде чем приступить к реализации? Когда имеет смысл нырять с головой в реализацию, а когда делать шаг назад?
Конечно, просто собрать требования - это еще не всё, о чем стоит подумать. Включение процессов разработки в проектирование также окупается:
- Как будет организовано написание кода, сборка, развёртывание и CI/CD?
- Как мы будем проводить сквозное и нагрузочное тестирование?
- Как мы будем управлять секретами?
Например, кто бы мог подумать, что управление секретами в производственной среде может оказаться таким сложным? Вы не можете поместить их в код, так как тогда их сможет увидеть любой.
Поместить их в переменные среды? Хорошая идея. Как их туда поместить и как ими управлять? Хранить файл секретов? Откуда он будет браться и как его изменять? И т.д., и т.п. Кроме того, мы не хотим, чтобы всё это выполнялось вручную. Можно рассмотреть базу данных, чтобы код получал секреты из базы при запуске. Опять же, подход может сильно отличаться при использовании облачного провайдера, где не нужно много думать о секретах, т.к. для этого есть специальный функционал.
Проектирование с учетом поддержки
Проектировать системы - это увлекательно. Поддерживать их – не очень. Рано или поздно задаёшься вопросом, почему и как системы деградируют?
Во-первых, проблема в нежелании выбрасывать старые вещи, всегда добавляя новые. Склонность к добавлению вместо удаления (есть за вами такой грешок?)
Вторая проблема — это проектирование с учётом конечной цели. Система, которая эволюционирует, добавляя функционал, который не был в неё изначально заложен, никогда не работает так же хорошо, как система, разработанная с нуля для этого функционала.
Есть как минимум три способа снизить скорость деградации:
1. Разделяйте бизнес-логику и инфраструктуру. Обычно быстрее деградирует инфраструктура: увеличивается нагрузка, фреймворки устаревают, появляются уязвимости и т.д.
2. Стройте процессы вокруг поддержки. Обновляйте как новый, так и устаревший код. Это предотвращает различие между новыми и старыми частями и сохраняет весь код «современным».
3. Убедитесь, что вы на постоянной основе избавляетесь от всех ненужных/устаревших вещей.
Источник: https://neilkakkar.com/things-I-learnt-from-a-senior-dev.html
Автор оригинала – Neil Kakkar
День восемьсот семьдесят третий.
RestClient.Net 5
RestClient.Net упрощает HTTP-вызовы в .NET. Вы можете отправлять строго типизированный объект в теле запроса и получать обратно строго типизированный объект. Вы можете внедрить абстракцию в сервисные классы и легко имитировать его в тестах, не беспокоясь о подключении HTTP или преобразовании в JSON. RestClient.Net 5 значительно улучшен, относительно 4й версии: представлены неизменяемые типы и fluent API. Он прекрасно работает с внедрением зависимостей, интегрируется с Polly, а дизайн должен быть знаком и удобен программистам на F#.
Зачем использовать Rest Client?
RestClient.Net решает эту проблему с помощью интерфейса
Вы можете напрямую внедрить интерфейс
Url-адреса
RestClient.Net использует библиотеку Urls вместо
Неизменяемые типы
Все классы в RestClient.Net неизменяемы. Вы не можете изменить их значения после создания экземпляра. Вы можете быстро клонировать существующего клиента, используя методы
Кроме того
- RestClient.Net поддерживает .NET Framework 4.5 и .NET Standard 2.0.
- Тщательно протестирован с помощью Stryker Mutator.
- Простой в использовании и легко масштабируется. Вы можете выполнить HTTP-вызов в одну строку кода, а затем повторно использовать клиента и выполнять последующие вызовы, задавая новые URL.
Источник: https://christianfindlay.com/2021/05/26/restclient-net-5/
RestClient.Net 5
RestClient.Net упрощает HTTP-вызовы в .NET. Вы можете отправлять строго типизированный объект в теле запроса и получать обратно строго типизированный объект. Вы можете внедрить абстракцию в сервисные классы и легко имитировать его в тестах, не беспокоясь о подключении HTTP или преобразовании в JSON. RestClient.Net 5 значительно улучшен, относительно 4й версии: представлены неизменяемые типы и fluent API. Он прекрасно работает с внедрением зависимостей, интегрируется с Polly, а дизайн должен быть знаком и удобен программистам на F#.
Зачем использовать Rest Client?
HttpClient
значительно затрудняет модульное тестирование вашего кода. Прежде всего, HttpClient
не имеет простой абстракции. Если вы хотите имитировать HttpClient
для модульного тестирования, вам необходимо внедрить DelegatingHandler
в клиента. Даже в этом случае вам нужно имитировать преобразование в необработанные данные и обратно. Это отвлекает от простого действия по проверке того, что клиент отправляет и получает правильный объект.RestClient.Net решает эту проблему с помощью интерфейса
IClient
. Вы отправляете строго типизированный объект и в теле ответа получаете строго типизированный объект.using var client = new Client(Внедрение зависимости
"jsonplaceholder.typicode.com".ToHttpsUriFromHost());
UserPost userPost =
await client.PostAsync<UserPost, UserPost>(
new UserPost { title = "Title" }, "posts"
);
Вы можете напрямую внедрить интерфейс
IClient
или использовать фабричный подход с CreateClient
. Пакет RestClient.Net.DependencyInjection работает с внедрением зависимостей ASP.NET Core и использует реализацию IHttpClientFactory
по умолчанию для создания HttpClient
. Это означает, что RestClient.Net всегда получает HttpClient
через фабрику, которая поддерживается Microsoft.Url-адреса
RestClient.Net использует библиотеку Urls вместо
System.Uri
. Это упрощает создание URL-адресов, делает их более читаемыми и менее подверженными ошибкам. Добавление пути и строки запроса к базовому URL-адресу всегда безопасно, и вам не нужно беспокоиться об объединении строк вручную:var absoluteUrl =Этот подход я подробнее описывал для пакета Flurl.
Host.ToHttpUrlFromHost(Port)
.AddQueryParameter(FieldName1, FieldValue1)
.WithCredentials(Username, Password)
.AddQueryParameter(FieldName2, FieldValue2)
.WithFragment(Fragment)
.WithPath(PathPart1, PathPart2);
Неизменяемые типы
HttpClient
позволяет изменять множество свойств. Это означает, что, если несколько частей вашей системы используют один и тот же экземпляр, они могут изменить какое-то свойство и сломать другую часть системы. Например, один класс может добавить заголовок по умолчанию, а другой класс может удалить его.Все классы в RestClient.Net неизменяемы. Вы не можете изменить их значения после создания экземпляра. Вы можете быстро клонировать существующего клиента, используя методы
With
или использовать параметры фабрики CreateClient
, чтобы указать свойства клиента.Кроме того
- RestClient.Net поддерживает .NET Framework 4.5 и .NET Standard 2.0.
- Тщательно протестирован с помощью Stryker Mutator.
- Простой в использовании и легко масштабируется. Вы можете выполнить HTTP-вызов в одну строку кода, а затем повторно использовать клиента и выполнять последующие вызовы, задавая новые URL.
Источник: https://christianfindlay.com/2021/05/26/restclient-net-5/
День восемьсот семьдесят четвёртый.
Ответы на Самые Популярные Вопросы по Микросервисам в .NET
1. При масштабировании сервисов как мы можем масштабировать базы данных, связанные с этими сервисами?
Существуют чётко определенные шаблоны и передовые методы повышения производительности и масштабирования баз данных. Обратитесь к разделу «Горизонтальное, вертикальное и функциональное разбиение данных», чтобы понять, как данные делятся на разделы для повышения масштабируемости, уменьшения числа конфликтов и оптимизации производительности. Чтобы углубиться в темы масштабирования микросервисов, распределённых данных, подхода «база данных на микросервис», выбора между реляционными или NoSQL базами данных, обратитесь к книге «Архитектура облачных приложений .NET для Azure» (PDF).
2. Нужно ли использовать отдельную базу данных для каждого микросервиса или микросервисы могут совместно использовать один и тот же экземпляр базы данных?
Автономность команд при работе со своими микросервисами - важнейшее преимущество архитектуры облачных приложений. Предпочтительно использовать независимые экземпляры базы данных, чтобы дать командам гибкость при развёртывании обновлений и исправлений в производственной среде, не нарушая работу других микросервисов. Архитектура облачных приложений вдохновлена известными методологиями 12-факторных приложений https://12factor.net/ru/. Один из факторов, «Сторонние сервисы», гласит, что вспомогательные ресурсы, такие как хранилища данных, кэши, брокеры сообщений, должны быть доступны через адресный URL. Поставщики облачных услуг предлагают широкий ассортимент управляемых сторонних сервисов.
3. Может ли монолитный веб-API взаимодействовать с микросервисами?
Да. Монолитные приложения могут взаимодействовать с микросервисами, если их конечные точки доступны внутри инфраструктуры или публично через безопасный протокол. Микросервисы и их данные могут использоваться либо синхронно через их конечные точки, либо асинхронно через обмен сообщениями, например шину событий. При модернизации приложения мы рекомендуем паттерн «Душитель» (Strangler), который помогает постепенно переходить с устаревшей системы на новую. В рамках решения вам необходимо создать фасад, который перехватывает запросы. Фасад направляет эти запросы либо в унаследованное приложение, либо в новые сервисы.
4. Если микросервисы слабо связаны и развертываются независимо, как они взаимодействуют друг с другом? Как синхронизировать данные между микросервисами?
Это довольно объёмный вопрос. Он подробно разъясняется в двух разделах книги «Архитектура облачных приложений .NET для Azure»:
- Модели связи в облаке
- Распределённые данные
5. Обязательно ли микросервисам использовать контейнеры?
Не обязательно. Однако использование контейнеров имеет свои преимущества. Микросервисы (или микросервисная архитектура) представляют собой рекомендации по проектированию и передовой опыт. Они помогают разделить приложение на несколько более мелких сервисов, определяемых конкретными бизнес-границами, которые независимо управляются небольшими группами разработчиков. Контейнеры объединяют приложение, его конфигурацию и зависимости в единый, независимо развёртываемый модуль. Контейнеры отлично подходят для объединения и развёртывания независимых микросервисов. Посмотрите руководство по написанию вашего первого микросервиса, чтобы оценить преимущества.
Больше вопросов и ответов в видео Microsoft Let’s Learn: Microservices.
Источник: https://devblogs.microsoft.com/aspnet/your-top-dotnet-microservices-questions-answered/
Ответы на Самые Популярные Вопросы по Микросервисам в .NET
1. При масштабировании сервисов как мы можем масштабировать базы данных, связанные с этими сервисами?
Существуют чётко определенные шаблоны и передовые методы повышения производительности и масштабирования баз данных. Обратитесь к разделу «Горизонтальное, вертикальное и функциональное разбиение данных», чтобы понять, как данные делятся на разделы для повышения масштабируемости, уменьшения числа конфликтов и оптимизации производительности. Чтобы углубиться в темы масштабирования микросервисов, распределённых данных, подхода «база данных на микросервис», выбора между реляционными или NoSQL базами данных, обратитесь к книге «Архитектура облачных приложений .NET для Azure» (PDF).
2. Нужно ли использовать отдельную базу данных для каждого микросервиса или микросервисы могут совместно использовать один и тот же экземпляр базы данных?
Автономность команд при работе со своими микросервисами - важнейшее преимущество архитектуры облачных приложений. Предпочтительно использовать независимые экземпляры базы данных, чтобы дать командам гибкость при развёртывании обновлений и исправлений в производственной среде, не нарушая работу других микросервисов. Архитектура облачных приложений вдохновлена известными методологиями 12-факторных приложений https://12factor.net/ru/. Один из факторов, «Сторонние сервисы», гласит, что вспомогательные ресурсы, такие как хранилища данных, кэши, брокеры сообщений, должны быть доступны через адресный URL. Поставщики облачных услуг предлагают широкий ассортимент управляемых сторонних сервисов.
3. Может ли монолитный веб-API взаимодействовать с микросервисами?
Да. Монолитные приложения могут взаимодействовать с микросервисами, если их конечные точки доступны внутри инфраструктуры или публично через безопасный протокол. Микросервисы и их данные могут использоваться либо синхронно через их конечные точки, либо асинхронно через обмен сообщениями, например шину событий. При модернизации приложения мы рекомендуем паттерн «Душитель» (Strangler), который помогает постепенно переходить с устаревшей системы на новую. В рамках решения вам необходимо создать фасад, который перехватывает запросы. Фасад направляет эти запросы либо в унаследованное приложение, либо в новые сервисы.
4. Если микросервисы слабо связаны и развертываются независимо, как они взаимодействуют друг с другом? Как синхронизировать данные между микросервисами?
Это довольно объёмный вопрос. Он подробно разъясняется в двух разделах книги «Архитектура облачных приложений .NET для Azure»:
- Модели связи в облаке
- Распределённые данные
5. Обязательно ли микросервисам использовать контейнеры?
Не обязательно. Однако использование контейнеров имеет свои преимущества. Микросервисы (или микросервисная архитектура) представляют собой рекомендации по проектированию и передовой опыт. Они помогают разделить приложение на несколько более мелких сервисов, определяемых конкретными бизнес-границами, которые независимо управляются небольшими группами разработчиков. Контейнеры объединяют приложение, его конфигурацию и зависимости в единый, независимо развёртываемый модуль. Контейнеры отлично подходят для объединения и развёртывания независимых микросервисов. Посмотрите руководство по написанию вашего первого микросервиса, чтобы оценить преимущества.
Больше вопросов и ответов в видео Microsoft Let’s Learn: Microservices.
Источник: https://devblogs.microsoft.com/aspnet/your-top-dotnet-microservices-questions-answered/
День восемьсот семьдесят пятый.
ASP.NET Core 6 и Серверы Аутентификации
Начиная с .NET 3.0 IdentityServer4 поставляется как часть шаблона приложения для поддержки выпуска токенов JWT в приложениях SPA и Blazor. Через некоторое время выпуска продукта команда IdentityServer сделала объявление об изменении лицензии для будущих версий IdentityServer на взаимную общественную лицензию (RPL), в которой код по-прежнему является открытым, но, если он используется в коммерческих целях, необходимо покупать платную лицензию. Такой подход распространён в мире открытого исходного кода, где трудно поддерживать доход, поскольку ваш проект становится вашей работой на полную ставку.
Причинами для выпуска IdentityServer было четко выраженное желание сообщества не конкурировать с существующим проектом с открытым исходным кодом и глубокое понимание командой IdentityServer сферы идентификации. Команда .NET не является экспертами по OAuth и OIDC, поскольку они сосредоточены на предоставлении строительных блоков для вашего приложения. Создание и поддержка сервера аутентификации - это полноценная задача. И у Microsoft уже есть команда и продукт в этой области - Azure Active Directory, который позволяет бесплатно использовать 500 000 объектов. Команда ASP.NET считает, что управляемое облачное решение остается лучшим практическим вариантом для разработчиков: безопасность поддерживается, учётные данные не хранятся локально, что сопряжено с риском, а новые функции, такие как аутентификация без пароля, легко внедрить в рабочий процесс. Однако понятно, что облачное решение может быть невозможно для некоторых клиентов из-за проблем с нормативными требованиями или суверенностью данных.
Для .NET 6 Microsoft продолжит поставлять IdentityServer в шаблонах проектов, используя новую лицензию RPL. IdentityServer по-прежнему рассматривается как наиболее зрелый вариант для создания самостоятельно развёртываемой, локально размещённой службы токенов в ASP.NET Core. Требования к лицензированию будут отдельно описаны, если вы используете шаблон, который включает Duende IdentityServer. Новый Duende IdentityServer по-прежнему имеет открытый исходный код, но теперь имеет двойную лицензию. Эта лицензия позволяет использовать его бесплатно для разработки, тестирования и обучения, бесплатно для некоммерческих программ с открытым исходным кодом и бесплатно для использования в коммерческих условиях, если компания зарабатывает менее 1 миллиона долларов США в год. В других случаях лицензия требует платы за использование в коммерческих целях. Предыдущая версия IdentityServer будет по-прежнему поддерживаться, пока поддерживается .NET 5, примерно до февраля 2022 года.
Для .NET 7 вопрос создания инструментов, позволяющих разрабатывать и тестировать приложения с поддержкой OIDC (OpenID Connect), пока открыт. Вы всегда сможете выбрать любую систему идентификации, которая лучше всего подходит для вашей среды, обновив всего несколько строк кода.
Про лицензирование IdentityServer, кстати, говорили в недавнем выпуске подкаста .NET Rocks «Open Source in the Enterprise with Rocky Lhotka». Вообще обсуждалась проблема использования открытого кода в энтерпрайз приложениях. Какие риски возникают в связи с этим, как правильно использовать открытые лицензии, и что будет, если, к примеру, какой-то из используемых модулей перестанет поддерживаться (как это случалось неоднократно). В разрезе IdentityServer, по словам авторов подкаста, история была в том, что компании просили сделать платную лицензию, чтобы была постоянная возможность обращаться в техподдержку, а у создателей IdentityServer соответственно обязательство оперативно решать проблемы клиентов, которого не может возникать при использовании открытого кода.
Источник: https://devblogs.microsoft.com/aspnet/asp-net-core-6-and-authentication-servers/
ASP.NET Core 6 и Серверы Аутентификации
Начиная с .NET 3.0 IdentityServer4 поставляется как часть шаблона приложения для поддержки выпуска токенов JWT в приложениях SPA и Blazor. Через некоторое время выпуска продукта команда IdentityServer сделала объявление об изменении лицензии для будущих версий IdentityServer на взаимную общественную лицензию (RPL), в которой код по-прежнему является открытым, но, если он используется в коммерческих целях, необходимо покупать платную лицензию. Такой подход распространён в мире открытого исходного кода, где трудно поддерживать доход, поскольку ваш проект становится вашей работой на полную ставку.
Причинами для выпуска IdentityServer было четко выраженное желание сообщества не конкурировать с существующим проектом с открытым исходным кодом и глубокое понимание командой IdentityServer сферы идентификации. Команда .NET не является экспертами по OAuth и OIDC, поскольку они сосредоточены на предоставлении строительных блоков для вашего приложения. Создание и поддержка сервера аутентификации - это полноценная задача. И у Microsoft уже есть команда и продукт в этой области - Azure Active Directory, который позволяет бесплатно использовать 500 000 объектов. Команда ASP.NET считает, что управляемое облачное решение остается лучшим практическим вариантом для разработчиков: безопасность поддерживается, учётные данные не хранятся локально, что сопряжено с риском, а новые функции, такие как аутентификация без пароля, легко внедрить в рабочий процесс. Однако понятно, что облачное решение может быть невозможно для некоторых клиентов из-за проблем с нормативными требованиями или суверенностью данных.
Для .NET 6 Microsoft продолжит поставлять IdentityServer в шаблонах проектов, используя новую лицензию RPL. IdentityServer по-прежнему рассматривается как наиболее зрелый вариант для создания самостоятельно развёртываемой, локально размещённой службы токенов в ASP.NET Core. Требования к лицензированию будут отдельно описаны, если вы используете шаблон, который включает Duende IdentityServer. Новый Duende IdentityServer по-прежнему имеет открытый исходный код, но теперь имеет двойную лицензию. Эта лицензия позволяет использовать его бесплатно для разработки, тестирования и обучения, бесплатно для некоммерческих программ с открытым исходным кодом и бесплатно для использования в коммерческих условиях, если компания зарабатывает менее 1 миллиона долларов США в год. В других случаях лицензия требует платы за использование в коммерческих целях. Предыдущая версия IdentityServer будет по-прежнему поддерживаться, пока поддерживается .NET 5, примерно до февраля 2022 года.
Для .NET 7 вопрос создания инструментов, позволяющих разрабатывать и тестировать приложения с поддержкой OIDC (OpenID Connect), пока открыт. Вы всегда сможете выбрать любую систему идентификации, которая лучше всего подходит для вашей среды, обновив всего несколько строк кода.
Про лицензирование IdentityServer, кстати, говорили в недавнем выпуске подкаста .NET Rocks «Open Source in the Enterprise with Rocky Lhotka». Вообще обсуждалась проблема использования открытого кода в энтерпрайз приложениях. Какие риски возникают в связи с этим, как правильно использовать открытые лицензии, и что будет, если, к примеру, какой-то из используемых модулей перестанет поддерживаться (как это случалось неоднократно). В разрезе IdentityServer, по словам авторов подкаста, история была в том, что компании просили сделать платную лицензию, чтобы была постоянная возможность обращаться в техподдержку, а у создателей IdentityServer соответственно обязательство оперативно решать проблемы клиентов, которого не может возникать при использовании открытого кода.
Источник: https://devblogs.microsoft.com/aspnet/asp-net-core-6-and-authentication-servers/
День восемьсот семьдесят шестой. #ЧтоНовенького #ЗаметкиНаПолях
Работа с PriorityQueue в .NET 6
Я недавно писал про новый класс PriorityQueue, предложенный в .NET 6.
В отличие от обычной очереди, работающей по принципу FIFO (первым пришёл - первым ушёл), очередь с приоритетом не имеет красивого акронима. Заданный пользователем приоритет определяет, какой элемент является «первым».
Очереди с приоритетом имеют много применений, но чаще всего их можно увидеть при работе с «обходом графа», поскольку вы можете быстро идентифицировать узлы, которые имеют самую высокую, либо самую низкую «стоимость».
Источник: https://khalidabuhakmeh.com/working-with-dotnet-six-priorityqueue
Работа с PriorityQueue в .NET 6
Я недавно писал про новый класс PriorityQueue, предложенный в .NET 6.
В отличие от обычной очереди, работающей по принципу FIFO (первым пришёл - первым ушёл), очередь с приоритетом не имеет красивого акронима. Заданный пользователем приоритет определяет, какой элемент является «первым».
PriorityQueue
определяет приоритет значений с помощью реализации интерфейса IComparer
. Очереди с приоритетом имеют много применений, но чаще всего их можно увидеть при работе с «обходом графа», поскольку вы можете быстро идентифицировать узлы, которые имеют самую высокую, либо самую низкую «стоимость».
PriorityQueue
принимает два аргумента типа: тип значения и тип приоритета. Конструктор также может принимать экземпляр IComparer
, но это не обязательно, поскольку большинство примитивных типов в .NET уже имеют реализацию компаратора по умолчанию. Давайте рассмотрим небольшой пример. Мы добавим супергероев в новую PriorityQueue
по их величию:PriorityQueue<string, Greatness> heroesЗдесь величие определяется в перечислении
= new(new GreatnessComparer());
heroes.Enqueue("Captain America", GOAT);
heroes.Enqueue("Spider-Man", Great);
heroes.Enqueue("Dr. Strange", Good);
heroes.Enqueue("Thor", Great);
heroes.Enqueue("Iron Man", Ok);
heroes.Enqueue("Hulk", Good);
while (superheroes.TryDequeue(out var hero, out var greatness))
Console.WriteLine($"{hero} ({greatness})");
public enum GreatnessДля него реализован компаратор:
{
Ok, Good, Great, GOAT
}
public class GreatnessComparer
: IComparer<Greatness>
{
// от большего к меньшему
public int Compare(Greatness x, Greatness y) => y - x;
}
PriorityQueue
будет определять приоритет наших супергероев, используя реализацию интерфейса IComparer
. Запустив программу, мы должны увидеть следующий вывод:Captain America (GOAT)Заметьте, что элементы с одинаковым приоритетом не следуют порядку FIFO. На самом деле, порядок их выдачи не определён, т.к. «под капотом» в
Spider-Man (Great)
Thor (Great)
Hulk (Good)
Dr. Strange (Good)
Iron Man (Ok)
PriorityQueue
лежит дерево элементов.Источник: https://khalidabuhakmeh.com/working-with-dotnet-six-priorityqueue
День восемьсот семьдесят седьмой. #ЧтоНовенького
Асинхронные Потоки в EF Core и ASP.NET Core 6
Давней проблемой в ASP.NET была невозможность обрабатывать возврат больших файлов JSON без использования большого количества памяти. По умолчанию фреймворк выполняет буферизацию всего вывода сразу, конвертирует его весь в JSON, а затем начинает передавать результаты клиенту. Это может привести к нехватке памяти, если объём данных достаточно велик.
Однако потоковая передача результатов не была проблемой для ASP.NET. При работе с более простыми форматами, такими как CSV, разработчик всегда имел возможность писать прямо в поток результатов.
Начиная с ASP.NET Core 5, класс Utf8JsonWriter может использоваться для достижения того же эффекта. Возникнет несколько сложностей, таких как необходимость явного отключения буферизации, но код сможет работать, если вы, например, последуете совету Александра Васильева.
ASP.NET Core 6 упрощает нашу жизнь, напрямую поддерживая
Один из способов получить
В объявлении №463 разработчики были проинформированы о том, что новое поведение
В большинстве случаев приложение не отслеживает отсутствие буферизации. Однако некоторые сценарии могли непреднамеренно полагаться на семантику буферизации для правильной сериализации. Например, возврат
Чтобы вернуться к предыдущему поведению, разработчикам необходимо явно вызвать
Источник: https://www.infoq.com/news/2021/06/ASP-Net-Core-6-IAsyncEnumerable/
Асинхронные Потоки в EF Core и ASP.NET Core 6
Давней проблемой в ASP.NET была невозможность обрабатывать возврат больших файлов JSON без использования большого количества памяти. По умолчанию фреймворк выполняет буферизацию всего вывода сразу, конвертирует его весь в JSON, а затем начинает передавать результаты клиенту. Это может привести к нехватке памяти, если объём данных достаточно велик.
Однако потоковая передача результатов не была проблемой для ASP.NET. При работе с более простыми форматами, такими как CSV, разработчик всегда имел возможность писать прямо в поток результатов.
Начиная с ASP.NET Core 5, класс Utf8JsonWriter может использоваться для достижения того же эффекта. Возникнет несколько сложностей, таких как необходимость явного отключения буферизации, но код сможет работать, если вы, например, последуете совету Александра Васильева.
ASP.NET Core 6 упрощает нашу жизнь, напрямую поддерживая
IAsyncEnumerable
. Если IAsyncEnumerable
возвращается функцией, платформа интерпретирует его как запрос на асинхронную потоковую передачу данных клиенту без буферизации.Один из способов получить
IAsyncEnumerable
- использовать Entity Framework Core. Фактически, эта функция присутствовала, начиная с EF Core 3, но до сих пор её полезность на веб-серверах была ограничена. ASP.NET Core не поддерживал результаты типа IAsyncEnumerable
до версии 5, но даже в этом случае результаты буферизовались.В объявлении №463 разработчики были проинформированы о том, что новое поведение
IAsyncEnumerable
следует рассматривать как критическое изменение.В большинстве случаев приложение не отслеживает отсутствие буферизации. Однако некоторые сценарии могли непреднамеренно полагаться на семантику буферизации для правильной сериализации. Например, возврат
IAsyncEnumerable<>
, который поддерживается запросом EF для типа с отложенной загрузкой свойств, может привести к параллельному выполнению запроса, который может не поддерживаться поставщиком.Чтобы вернуться к предыдущему поведению, разработчикам необходимо явно вызвать
ToListAsync()
:// До ASP.NET Core 6Кроме того, для решения проблемы можно отключить отложенную загрузку.
public IActionResult Get()
{
return Ok(dbContext.Blogs);
}
// Начиная с ASP.NET Core 6
public async Task<IActionResult> Get()
{
return Ok(await dbContext.Blogs.ToListAsync());
}
Источник: https://www.infoq.com/news/2021/06/ASP-Net-Core-6-IAsyncEnumerable/
День восемьсот семьдесят восьмой. #Оффтоп #Здоровье
Сегодня не про программирование, но тема не менее важная – здоровье. Как всегда случайно наткнулся в ютубе на занятное видео про поддержание здоровья и продуктивности при нашем сидячем образе жизни. Там даётся 10 советов. Не могу сказать, что со всеми согласен, на некоторые, вроде регулируемого по высоте стола, придётся заметно потратиться. Но некоторые вещи, например, сидение на фитболе и режим работы 25-5 пробовал.
Давайте обсудим. Что из этого использовали вы? Что понравилось, что нет? Используете ли вы какие-нибудь другие приёмы?
Сегодня не про программирование, но тема не менее важная – здоровье. Как всегда случайно наткнулся в ютубе на занятное видео про поддержание здоровья и продуктивности при нашем сидячем образе жизни. Там даётся 10 советов. Не могу сказать, что со всеми согласен, на некоторые, вроде регулируемого по высоте стола, придётся заметно потратиться. Но некоторые вещи, например, сидение на фитболе и режим работы 25-5 пробовал.
Давайте обсудим. Что из этого использовали вы? Что понравилось, что нет? Используете ли вы какие-нибудь другие приёмы?
YouTube
Рабочее место программиста БЕЗ БОЛЕЙ В СПИНЕ // Девайсы для здоровья и продуктивности работы из дома
Миша делится девайсами, которые помогли ему избавиться от болей в спине и повысить концентрацию внимания во время работы за компьютером.
✈️ 🇺🇸 РЕЛОКЕЙТ в США со мной — https://ocitizens.com/ (uDevs Inc.)
⏱ ТАЙМИНГ:
0:00 - Почему этот выпуск необычный
1:07…
✈️ 🇺🇸 РЕЛОКЕЙТ в США со мной — https://ocitizens.com/ (uDevs Inc.)
⏱ ТАЙМИНГ:
0:00 - Почему этот выпуск необычный
1:07…
День восемьсот семьдесят девятый. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
89. Используйте Правильные Алгоритмы и Структуры Данных
Большой банк с множеством филиалов жаловался, что новые компьютеры, которые он закупил для кассиров, слишком медленные. Это было ещё до того, как все начали использовать онлайн банки, а банкоматы не были так широко распространены, как сейчас. Люди ходили в банк гораздо чаще, а из-за медленных компьютеров выстраивались очереди. Тогда банк пригрозил разорвать контракт с поставщиком.
Поставщик направил специалиста по анализу производительности и настройке, чтобы определить причину задержек. Вскоре он обнаружил, что на терминале работала одна конкретная программа, которая потребляла почти всю мощность процессора. Используя профилировщик, специалист нашёл функцию, на которую приходилась большая часть нагрузки:
Не должен ли был программист постараться чуть лучше, чем выдать код, который без необходимости выполнялся за квадратичное время? Каждый вызов
Всем известна поговорка «сначала заставь это работать, а потом заставь работать быстро», чтобы избежать ошибок микрооптимизации. Но предыдущий пример почти заставляет вас поверить, что программист скорее следовал подходу «сначала заставьте это работать медленно».
С таким легкомыслием вы можете сталкиваться довольно часто. И это не просто принцип «не изобретайте велосипед». Иногда начинающие программисты просто начинают печатать, не особо задумываясь, и внезапно «изобретают» пузырьковую сортировку. Они могут даже хвастаться этим.
Другой стороной выбора правильного алгоритма является выбор структуры данных. Это может иметь большое значение: использование связанного списка для коллекции из миллиона элементов, по которым вы хотите выполнить поиск (по сравнению с хешированной структурой данных или бинарным деревом) будет иметь большое влияние на оценку пользователем вашего продукта.
Программистам не следует изобретать велосипед и следует по возможности использовать существующие библиотеки. Но чтобы избежать проблем, подобных проблеме банка, они также должны знать об алгоритмах и способах их масштабирования. Многие говорят, что повторное использование кода в программировании имеет первостепенное значение. Однако прежде всего программисты должны знать, когда, что и как использовать повторно. Для этого они должны знать проблемную область, а также алгоритмы и структуры данных.
Хороший программист также должен знать, когда можно использовать даже отвратительный алгоритм. Например, если заранее известно, что элементов не может быть больше пяти, вы знаете, что вам всегда нужно отсортировать не более пяти элементов. В этом случае пузырьковая сортировка может оказаться наиболее эффективным способом. Всему своё время и место.
Так что читайте умные книги и разбирайтесь в том, что там написано. А если вы действительно прочитали Дональда Кнута «Искусство программирования» и смогли найти ошибку у автора, то можете получить один из его шестнадцатеричных долларов.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Jan Christiaan “JC” Van Winkel
97 Вещей, Которые Должен Знать Каждый Программист
89. Используйте Правильные Алгоритмы и Структуры Данных
Большой банк с множеством филиалов жаловался, что новые компьютеры, которые он закупил для кассиров, слишком медленные. Это было ещё до того, как все начали использовать онлайн банки, а банкоматы не были так широко распространены, как сейчас. Люди ходили в банк гораздо чаще, а из-за медленных компьютеров выстраивались очереди. Тогда банк пригрозил разорвать контракт с поставщиком.
Поставщик направил специалиста по анализу производительности и настройке, чтобы определить причину задержек. Вскоре он обнаружил, что на терминале работала одна конкретная программа, которая потребляла почти всю мощность процессора. Используя профилировщик, специалист нашёл функцию, на которую приходилась большая часть нагрузки:
for (i=0; i<strlen(s); ++i) {При этом строка s в среднем состояла из тысяч символов. Код (написанный банком) был быстро исправлен, и с тех пор кассиры жили долго и счастливо…
if (… s[i] …) …
}
Не должен ли был программист постараться чуть лучше, чем выдать код, который без необходимости выполнялся за квадратичное время? Каждый вызов
strlen
проходил по всем тысячам символов в строке, чтобы найти завершающий нулевой байт. При этом строка в цикле не изменялась. Заранее определив её длину, программист мог бы сэкономить тысячи вызовов strlen
:n=strlen(s);*Замечание: понятно, что пример взят из конкретного языка и старого компилятора. Сейчас большинство таких проблем компилятор может оптимизировать, а нахождение длины строки или размера коллекции далеко не всегда требует пересчёта всех элементов. Но всё же, это не значит, что за подобными вещами не стоит следить.
for (i=0; i<n; ++i) {
if (… s[i] …) …
}
Всем известна поговорка «сначала заставь это работать, а потом заставь работать быстро», чтобы избежать ошибок микрооптимизации. Но предыдущий пример почти заставляет вас поверить, что программист скорее следовал подходу «сначала заставьте это работать медленно».
С таким легкомыслием вы можете сталкиваться довольно часто. И это не просто принцип «не изобретайте велосипед». Иногда начинающие программисты просто начинают печатать, не особо задумываясь, и внезапно «изобретают» пузырьковую сортировку. Они могут даже хвастаться этим.
Другой стороной выбора правильного алгоритма является выбор структуры данных. Это может иметь большое значение: использование связанного списка для коллекции из миллиона элементов, по которым вы хотите выполнить поиск (по сравнению с хешированной структурой данных или бинарным деревом) будет иметь большое влияние на оценку пользователем вашего продукта.
Программистам не следует изобретать велосипед и следует по возможности использовать существующие библиотеки. Но чтобы избежать проблем, подобных проблеме банка, они также должны знать об алгоритмах и способах их масштабирования. Многие говорят, что повторное использование кода в программировании имеет первостепенное значение. Однако прежде всего программисты должны знать, когда, что и как использовать повторно. Для этого они должны знать проблемную область, а также алгоритмы и структуры данных.
Хороший программист также должен знать, когда можно использовать даже отвратительный алгоритм. Например, если заранее известно, что элементов не может быть больше пяти, вы знаете, что вам всегда нужно отсортировать не более пяти элементов. В этом случае пузырьковая сортировка может оказаться наиболее эффективным способом. Всему своё время и место.
Так что читайте умные книги и разбирайтесь в том, что там написано. А если вы действительно прочитали Дональда Кнута «Искусство программирования» и смогли найти ошибку у автора, то можете получить один из его шестнадцатеричных долларов.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Jan Christiaan “JC” Van Winkel
День восемьсот восьмидесятый. #BestPractices #CodeReview
Лучшие Практики для Эффективных Обзоров Кода. Начало
Обзор кода, если проведён правильно, позволяет разработчикам предоставлять оптимальный исходный код, одновременно узнавая больше об эффективном написании и отладке кода.
Процесс написания кода требует больших умственных усилий и концентрации, что очень затрудняет достижение безупречного результата. Однако важно помнить, что идеального кода не бывает. Программисты должны стремиться к созданию «лучшего» кода, который можно постоянно улучшать. Проверка работы автора кода не может гарантировать предотвращение всех ошибок, но может защитить пользователей от их возникновения. Вот почему интеграция обзоров кода в процесс разработки помогает предоставлять высококачественные приложения.
Обзор кода - это систематическая проверка исходного кода ПО, используемая для выявления ошибок на ранних стадиях, отслеживания возможных упущений и повышения общего качества и согласованности кода. Этот процесс помогает коду оставаться более удобным для сопровождения. Анализ кода, проводимый коллегами-программистами и специалистами по обеспечению качества, направлен на ускорение и оптимизацию процесса разработки ПО.
Важно убедиться, что все члены команды понимают правила и рекомендации по проведению обзора кода в компании. Взаимная проверка кода - это объединение усилий для повышения производительности, а не конкуренция.
1. Знайте, что искать
Разработчики должны точно знать, какие аспекты им следует охватить: дизайн, функциональность, стиль, логику, структуру, согласованность, покрытие тестами, сложность кода и т.д. Некоторые из вышеупомянутых характеристик могут быть проверены автоматически благодаря статическим анализаторам кода (например, структура, логика или покрытие тестами), в то время как другие (например, дизайн и функциональность) требуют проверки вручную.
Чтобы сделать процесс проверки более эффективным, рецензенты должны сосредоточиться на следующих вопросах:
- Можно ли чётко понять, что делает код?
- Код работает так, как ожидалось?
- Соответствует ли код нормативным требованиям?
Если они могут ответить на эти вопросы с уверенностью «да», код можно считать хорошим.
2. Автоматизируйте перед проверкой
Стоит обратить внимание на непрерывную интеграцию, то есть на выполнение серии автоматических тестов при сборке и тестировании кода каждый раз, когда происходит изменение. Перед экспертной оценкой должна проводиться непрерывная интеграция. Когда серия автоматических тестов проходит, разработчики получают код с меньшим количеством ошибок, а процесс ручной проверки становится более плавным и быстрым, что экономит время разработчиков.
3. Ограничьте время обзора
Эффективная проверка может быть проведена только тогда, когда разработчики на 100% сосредоточены на выполняемой задаче. Большинство исследований показывают, что, когда люди занимаются какой-либо деятельностью, требующей высокой концентрации, их эффективность снижается через 60 минут. При проверке кода не нужно торопиться. Лучше разбить этот процесс на короткие сеансы, что даст разработчикам возможность отдохнуть и тем самым улучшить качество проверки.
4. Проверяйте не больше 400 строк кода в час
Одна неправильно рассмотренная строка кода может иметь плохие последствия для всей системы. Вот почему попытка проверить как можно больше строк за один сеанс может привести к провалу всей команды разработчиков. Обзор кода нельзя делать в спешке, иначе он теряет смысл. Попытка сосредоточиться максимум на 400 строках для каждого сеанса проверки приведёт к более тщательному и эффективному процессу проверки.
Окончание следует…
Источник: https://dzone.com/articles/9-best-practices-for-effective-code-review
Лучшие Практики для Эффективных Обзоров Кода. Начало
Обзор кода, если проведён правильно, позволяет разработчикам предоставлять оптимальный исходный код, одновременно узнавая больше об эффективном написании и отладке кода.
Процесс написания кода требует больших умственных усилий и концентрации, что очень затрудняет достижение безупречного результата. Однако важно помнить, что идеального кода не бывает. Программисты должны стремиться к созданию «лучшего» кода, который можно постоянно улучшать. Проверка работы автора кода не может гарантировать предотвращение всех ошибок, но может защитить пользователей от их возникновения. Вот почему интеграция обзоров кода в процесс разработки помогает предоставлять высококачественные приложения.
Обзор кода - это систематическая проверка исходного кода ПО, используемая для выявления ошибок на ранних стадиях, отслеживания возможных упущений и повышения общего качества и согласованности кода. Этот процесс помогает коду оставаться более удобным для сопровождения. Анализ кода, проводимый коллегами-программистами и специалистами по обеспечению качества, направлен на ускорение и оптимизацию процесса разработки ПО.
Важно убедиться, что все члены команды понимают правила и рекомендации по проведению обзора кода в компании. Взаимная проверка кода - это объединение усилий для повышения производительности, а не конкуренция.
1. Знайте, что искать
Разработчики должны точно знать, какие аспекты им следует охватить: дизайн, функциональность, стиль, логику, структуру, согласованность, покрытие тестами, сложность кода и т.д. Некоторые из вышеупомянутых характеристик могут быть проверены автоматически благодаря статическим анализаторам кода (например, структура, логика или покрытие тестами), в то время как другие (например, дизайн и функциональность) требуют проверки вручную.
Чтобы сделать процесс проверки более эффективным, рецензенты должны сосредоточиться на следующих вопросах:
- Можно ли чётко понять, что делает код?
- Код работает так, как ожидалось?
- Соответствует ли код нормативным требованиям?
Если они могут ответить на эти вопросы с уверенностью «да», код можно считать хорошим.
2. Автоматизируйте перед проверкой
Стоит обратить внимание на непрерывную интеграцию, то есть на выполнение серии автоматических тестов при сборке и тестировании кода каждый раз, когда происходит изменение. Перед экспертной оценкой должна проводиться непрерывная интеграция. Когда серия автоматических тестов проходит, разработчики получают код с меньшим количеством ошибок, а процесс ручной проверки становится более плавным и быстрым, что экономит время разработчиков.
3. Ограничьте время обзора
Эффективная проверка может быть проведена только тогда, когда разработчики на 100% сосредоточены на выполняемой задаче. Большинство исследований показывают, что, когда люди занимаются какой-либо деятельностью, требующей высокой концентрации, их эффективность снижается через 60 минут. При проверке кода не нужно торопиться. Лучше разбить этот процесс на короткие сеансы, что даст разработчикам возможность отдохнуть и тем самым улучшить качество проверки.
4. Проверяйте не больше 400 строк кода в час
Одна неправильно рассмотренная строка кода может иметь плохие последствия для всей системы. Вот почему попытка проверить как можно больше строк за один сеанс может привести к провалу всей команды разработчиков. Обзор кода нельзя делать в спешке, иначе он теряет смысл. Попытка сосредоточиться максимум на 400 строках для каждого сеанса проверки приведёт к более тщательному и эффективному процессу проверки.
Окончание следует…
Источник: https://dzone.com/articles/9-best-practices-for-effective-code-review
День восемьсот восемьдесят первый. #BestPractices #CodeReview
Лучшие Практики для Эффективных Обзоров Кода. Окончание
Начало
5. Давайте конструктивную обратную связь
Взаимная проверка кода направлена на повышение производительности команды, а не на разжигание конкуренции между автором кода и рецензентом. В любом случае код необходимо проверять. И если разработчики воспринимают это как процесс обучения, а не критику своей работы, это способствует общему успеху проекта. Получение конструктивной обратной связи побудит разработчиков учиться на своих ошибках и расширять свои возможности. Рецензенты могут оставлять комментарии с префиксом «Nit:» (от «nitpicking» - придирки). Это означает, что такие вещи не обязательно должны исправляться, а имеют образовательную цель и помогают разработчикам постоянно совершенствовать свои навыки. Например:
Если цели процесса обзора кода определены заранее, гораздо проще измерить эффективность кода и решить, приносит ли проверка пользу и помогает ли достичь ожидаемых результатов. Настройка внешних и внутренних показателей позволяет разработчикам улучшить качество кода. Примерами внешних показателей могут быть «уменьшение процента дефектов, сообщаемых конечными пользователями» или «уменьшение количества дефектов, обнаруженных до запуска продукта».
Внутренние показатели включают:
- Скорость проверки.
- Дефектность: среднее количество ошибок, обнаруженных за один сеанс.
- Плотность дефектов: среднее количество ошибок на строку кода.
7. Комментируйте код для рецензента
Комментарии предоставляет информацию о том, что пытается выполнить каждая строка или раздел кода. Они также могут показать рецензенту, какие изменения были внесены, какие методы модификации кода использовались и почему это было полезно. Эта практика способствует более глубокому пониманию кода рецензентом и упрощает общий процесс проверки кода. Например:
Разработчик – человек, поэтому может упустить из виду некоторые аспекты кода. Чек-лист сделает процесс проверки более последовательным, поскольку будет постоянно напоминать о том, что следует проверять. Он особенно полезен для рецензента, поскольку помогает проводить проверку по конкретным критериям. Однако существует и такое понятие, как личный чек-лист. Если автор кода знает о своих типичных ошибках и недостатках в работе, он может составить чек-лист, чтобы постоянно улучшать качество своего кода. Кроме того, чек-листы проверки кода очень важны для выявления упущений, которые труднее всего проверять, потому что сложно обнаружить отсутствие чего-либо.
Вот некоторые вопросы для чек-листа:
- Легко ли понять код?
- Соответствует ли форматирование кода соглашению по проекту?
- Достаточно ли модульная структура кода?
- Соответствует ли выбранное решение требованиям?
- Проверена ли вся логика и все ошибки?
- Есть ли проблемы в безопасности?
- Как дела с производительностью? (Есть ли очевидные моменты для оптимизации?)
- Весь ли код покрыт тестами?
- Насколько эффективно и информативно описание пул реквеста?
9. Включайте всех
Чем больше будет глаз, тем легче найти ошибку. Люди, как правило, работают лучше, если знают, что их работа будет проверена. Неважно, какой уровень квалификации у программиста - каждый должен участвовать в процессе обзора кода. Младшие разработчики могут обучаться новым или альтернативным методам выполнения чего-либо у своих старших коллег, а старшие могут совершенствовать свои навыки программирования, написав код, понятный и читаемый для всех.
Источник: https://dzone.com/articles/9-best-practices-for-effective-code-review
Лучшие Практики для Эффективных Обзоров Кода. Окончание
Начало
5. Давайте конструктивную обратную связь
Взаимная проверка кода направлена на повышение производительности команды, а не на разжигание конкуренции между автором кода и рецензентом. В любом случае код необходимо проверять. И если разработчики воспринимают это как процесс обучения, а не критику своей работы, это способствует общему успеху проекта. Получение конструктивной обратной связи побудит разработчиков учиться на своих ошибках и расширять свои возможности. Рецензенты могут оставлять комментарии с префиксом «Nit:» (от «nitpicking» - придирки). Это означает, что такие вещи не обязательно должны исправляться, а имеют образовательную цель и помогают разработчикам постоянно совершенствовать свои навыки. Например:
var file = app != null && !string.IsNullOrEmpty(app.FilePath);6. Установка целей и сбор метрик
// Nit: может быть заменено на
// !string.IsNullOrEmpty(app?.FilePath);
Если цели процесса обзора кода определены заранее, гораздо проще измерить эффективность кода и решить, приносит ли проверка пользу и помогает ли достичь ожидаемых результатов. Настройка внешних и внутренних показателей позволяет разработчикам улучшить качество кода. Примерами внешних показателей могут быть «уменьшение процента дефектов, сообщаемых конечными пользователями» или «уменьшение количества дефектов, обнаруженных до запуска продукта».
Внутренние показатели включают:
- Скорость проверки.
- Дефектность: среднее количество ошибок, обнаруженных за один сеанс.
- Плотность дефектов: среднее количество ошибок на строку кода.
7. Комментируйте код для рецензента
Комментарии предоставляет информацию о том, что пытается выполнить каждая строка или раздел кода. Они также могут показать рецензенту, какие изменения были внесены, какие методы модификации кода использовались и почему это было полезно. Эта практика способствует более глубокому пониманию кода рецензентом и упрощает общий процесс проверки кода. Например:
// Начинаем с 1, чтобы 0 был недопустимым8. Используйте чек-листы
// и это можно было проверять при передаче параметра извне
public enum SupplierStatsType {
All = 1, General = 2, Custom = 3
}
Разработчик – человек, поэтому может упустить из виду некоторые аспекты кода. Чек-лист сделает процесс проверки более последовательным, поскольку будет постоянно напоминать о том, что следует проверять. Он особенно полезен для рецензента, поскольку помогает проводить проверку по конкретным критериям. Однако существует и такое понятие, как личный чек-лист. Если автор кода знает о своих типичных ошибках и недостатках в работе, он может составить чек-лист, чтобы постоянно улучшать качество своего кода. Кроме того, чек-листы проверки кода очень важны для выявления упущений, которые труднее всего проверять, потому что сложно обнаружить отсутствие чего-либо.
Вот некоторые вопросы для чек-листа:
- Легко ли понять код?
- Соответствует ли форматирование кода соглашению по проекту?
- Достаточно ли модульная структура кода?
- Соответствует ли выбранное решение требованиям?
- Проверена ли вся логика и все ошибки?
- Есть ли проблемы в безопасности?
- Как дела с производительностью? (Есть ли очевидные моменты для оптимизации?)
- Весь ли код покрыт тестами?
- Насколько эффективно и информативно описание пул реквеста?
9. Включайте всех
Чем больше будет глаз, тем легче найти ошибку. Люди, как правило, работают лучше, если знают, что их работа будет проверена. Неважно, какой уровень квалификации у программиста - каждый должен участвовать в процессе обзора кода. Младшие разработчики могут обучаться новым или альтернативным методам выполнения чего-либо у своих старших коллег, а старшие могут совершенствовать свои навыки программирования, написав код, понятный и читаемый для всех.
Источник: https://dzone.com/articles/9-best-practices-for-effective-code-review
День восемьсот восемьдесят второй. #ЧтоНовенького
Горячая Перезагрузка и Другие Обновления ASP.NET Core в .NET 6 Preview 5
Горячая Перезагрузка (Hot Reload) - долгожданная функциональность, позволяющая разработчикам вносить изменения в код во время отладки, которые мгновенно отражаются в работающем приложении без необходимости перезапуска - была представлена на конференции разработчиков May Build. Она поддерживалась в ранней неполной форме в Visual Studio 2019 версии 16.11 Preview 1. С тех пор были добавлены дополнительные улучшения.
Для ASP.NET Core основное улучшение Hot Reload затрагивает
Больше не нужно указывать hotReloadProfile в launchSettings.json. .NET Hot Reload с соответствующим поведением проекта теперь включена по умолчанию. Когда вносится изменение, которое не может быть перезагружено горячим способом («грубое» изменение), dotnet watch теперь спросит, хотите ли вы перезапустить приложение, чтобы применить изменение. «Грубые» изменения в приложениях Blazor WebAssembly будут применены при обновлении браузера или при загрузке приложения в отдельной вкладке или новом окне браузера.
Размеры загружаемых файлов Blazor WebAssembly были уменьшены с помощью функции, известной как повторное связывание (relinking). Она позволяет исключить ненужную логику выполнения - такую как глобализация - из загрузки.
Другие новинки ASP.NET Core .NET 6 Preview 5:
- Шаблоны ASP.NET Core SPA обновлены до Angular 11 и React 17
- Использование синтаксиса Razor в элементах SVG foreignObject
- Настраиваемый порог буфера перед записью на диск в Json.NET
- Подкатегории для лучшей фильтрации журналов Kestrel
- Более быстрое получение и установка заголовков HTTP
- Настраиваемый размер входящего буфера для IIS
Пока существуют известные проблемы с использованием ASP.NET Core в .NET 6 Preview 5:
1. Начиная с .NET 6 Preview 1, существует проблема с запуском приложений Blazor WebAssembly с использованием сервера IIS Express во время разработки в Visual Studio. Чтобы обойти это, рекомендуется использовать Kestrel во время разработки.
2. Начиная с .NET 6 Preview 3, изменения представлений Razor не будут обновляться во время инкрементных сборок. Чтобы обойти это, вы можете:
- Осуществлять сборку из командной строки
- Настроить VS, чтобы всегда вызывать MSBuild при сборке проектов
- Очищать и собирать проекты, чтобы изменения отражались
3. Начиная с .NET 6 Preview 5, при использовании обработчика JWT Bearer в часовом поясе выше, чем UTC (например, UTC+2), вы можете наблюдать исключение
Вы можете обойти это, всегда предоставляя ненулевое и не минимальное значение для параметра
Источник: https://visualstudiomagazine.com/articles/2021/06/18/aspnet-core-updates.aspx
Горячая Перезагрузка и Другие Обновления ASP.NET Core в .NET 6 Preview 5
Горячая Перезагрузка (Hot Reload) - долгожданная функциональность, позволяющая разработчикам вносить изменения в код во время отладки, которые мгновенно отражаются в работающем приложении без необходимости перезапуска - была представлена на конференции разработчиков May Build. Она поддерживалась в ранней неполной форме в Visual Studio 2019 версии 16.11 Preview 1. С тех пор были добавлены дополнительные улучшения.
Для ASP.NET Core основное улучшение Hot Reload затрагивает
dotnet watch
- инструмент командной строки (CLI), который выполняет команду .NET Core при изменении исходных файлов и обновляет браузер при обнаружении изменений в наблюдаемых файлах. Это позволяет перезагружать проекты ASP.NET Core в реальном времени.Больше не нужно указывать hotReloadProfile в launchSettings.json. .NET Hot Reload с соответствующим поведением проекта теперь включена по умолчанию. Когда вносится изменение, которое не может быть перезагружено горячим способом («грубое» изменение), dotnet watch теперь спросит, хотите ли вы перезапустить приложение, чтобы применить изменение. «Грубые» изменения в приложениях Blazor WebAssembly будут применены при обновлении браузера или при загрузке приложения в отдельной вкладке или новом окне браузера.
Размеры загружаемых файлов Blazor WebAssembly были уменьшены с помощью функции, известной как повторное связывание (relinking). Она позволяет исключить ненужную логику выполнения - такую как глобализация - из загрузки.
Другие новинки ASP.NET Core .NET 6 Preview 5:
- Шаблоны ASP.NET Core SPA обновлены до Angular 11 и React 17
- Использование синтаксиса Razor в элементах SVG foreignObject
- Настраиваемый порог буфера перед записью на диск в Json.NET
- Подкатегории для лучшей фильтрации журналов Kestrel
- Более быстрое получение и установка заголовков HTTP
- Настраиваемый размер входящего буфера для IIS
Пока существуют известные проблемы с использованием ASP.NET Core в .NET 6 Preview 5:
1. Начиная с .NET 6 Preview 1, существует проблема с запуском приложений Blazor WebAssembly с использованием сервера IIS Express во время разработки в Visual Studio. Чтобы обойти это, рекомендуется использовать Kestrel во время разработки.
2. Начиная с .NET 6 Preview 3, изменения представлений Razor не будут обновляться во время инкрементных сборок. Чтобы обойти это, вы можете:
- Осуществлять сборку из командной строки
- Настроить VS, чтобы всегда вызывать MSBuild при сборке проектов
- Очищать и собирать проекты, чтобы изменения отражались
3. Начиная с .NET 6 Preview 5, при использовании обработчика JWT Bearer в часовом поясе выше, чем UTC (например, UTC+2), вы можете наблюдать исключение
ArgumentOutOfRangeException
, если токен JWT не содержит значение nbf
(Действует с). Проблема отслеживается здесь и будет исправлена в .NET 6 Preview 6.Вы можете обойти это, всегда предоставляя ненулевое и не минимальное значение для параметра
notBefore
при использовании System.IdentityModel.Tokens.Jwt.JwtSecurityToken или поле 'nbf
' при использовании другой библиотеки JWT.Источник: https://visualstudiomagazine.com/articles/2021/06/18/aspnet-core-updates.aspx
День восемьсот восемьдесят третий. #DesignPatterns #Microservices
Микросервисная Архитектура и Паттерны Проектирования
Существует множество определений микросервисной архитектуры. Вот одно из них:
Микросервисная архитектура представляет собой вертикальное разделение больших сложных систем (по функциональным или бизнес-требованиям) на более мелкие подсистемы, которые являются отдельными процессами (следовательно, могут развёртываться независимо), и эти подсистемы взаимодействуют друг с другом через лёгкие, не зависящие от языка сетевые вызовы либо синхронным (например, через REST, gRPC) или асинхронным (через обмен сообщениями) способом.
Компонентное представление бизнес-веб-приложения с микросервисной архитектурой представлено на рисунке ниже.
Характеристики:
- Всё приложение разделено на отдельные процессы, каждый из которых может содержать несколько внутренних модулей.
- В отличие от модульных монолитов или сервисно-ориентированной архитектуры, микросервисное приложение разделено по вертикали (в соответствии с бизнес-потребностями или доменами).
- Границы микросервисов внешние, то есть микросервисы взаимодействуют друг с другом через сетевые вызовы (RPC или сообщения).
- Поскольку микросервисы являются независимыми процессами, их можно развёртывать независимо.
- Они общаются легко и не нуждаются в каком-то хитром канале связи.
Преимущества:
- Лучшее масштабирование разработки.
- Более высокая скорость разработки.
- Поддерживается итеративная или инкрементная модернизация.
- Возможность использовать преимущества современной экосистемы разработки ПО (облако, контейнеры, DevOps, бессерверная среда).
- Поддерживается как горизонтальное, так и гранулярное масштабирование (возможность масштабировать отдельные микросервисы).
- Благодаря меньшему размеру, снижается нагрузка на разработчиков, которым не приходится держать в голове большую систему.
Недостатки:
- Большее количество элементов (сервисы, базы данных, процессы, контейнеры, фреймворки).
- Сложность переходит от кода к инфраструктуре.
- Большее количество вызовов RPC и сетевого трафика.
- Управление безопасностью всей системы является сложной задачей.
- Проектировать всю систему сложнее.
- Возникают сложности распределённых систем.
Варианты использования:
- Разработка веб-приложений.
- Разработка корпоративных приложений, когда над приложением работают несколько команд.
- В случаях, когда долгосрочный эффект предпочтительнее краткосрочного.
- В команде есть архитекторы ПО, способные разработать микросервисную архитектуру.
Источник: https://towardsdatascience.com/microservice-architecture-and-its-10-most-important-design-patterns-824952d7fa41
Микросервисная Архитектура и Паттерны Проектирования
Существует множество определений микросервисной архитектуры. Вот одно из них:
Микросервисная архитектура представляет собой вертикальное разделение больших сложных систем (по функциональным или бизнес-требованиям) на более мелкие подсистемы, которые являются отдельными процессами (следовательно, могут развёртываться независимо), и эти подсистемы взаимодействуют друг с другом через лёгкие, не зависящие от языка сетевые вызовы либо синхронным (например, через REST, gRPC) или асинхронным (через обмен сообщениями) способом.
Компонентное представление бизнес-веб-приложения с микросервисной архитектурой представлено на рисунке ниже.
Характеристики:
- Всё приложение разделено на отдельные процессы, каждый из которых может содержать несколько внутренних модулей.
- В отличие от модульных монолитов или сервисно-ориентированной архитектуры, микросервисное приложение разделено по вертикали (в соответствии с бизнес-потребностями или доменами).
- Границы микросервисов внешние, то есть микросервисы взаимодействуют друг с другом через сетевые вызовы (RPC или сообщения).
- Поскольку микросервисы являются независимыми процессами, их можно развёртывать независимо.
- Они общаются легко и не нуждаются в каком-то хитром канале связи.
Преимущества:
- Лучшее масштабирование разработки.
- Более высокая скорость разработки.
- Поддерживается итеративная или инкрементная модернизация.
- Возможность использовать преимущества современной экосистемы разработки ПО (облако, контейнеры, DevOps, бессерверная среда).
- Поддерживается как горизонтальное, так и гранулярное масштабирование (возможность масштабировать отдельные микросервисы).
- Благодаря меньшему размеру, снижается нагрузка на разработчиков, которым не приходится держать в голове большую систему.
Недостатки:
- Большее количество элементов (сервисы, базы данных, процессы, контейнеры, фреймворки).
- Сложность переходит от кода к инфраструктуре.
- Большее количество вызовов RPC и сетевого трафика.
- Управление безопасностью всей системы является сложной задачей.
- Проектировать всю систему сложнее.
- Возникают сложности распределённых систем.
Варианты использования:
- Разработка веб-приложений.
- Разработка корпоративных приложений, когда над приложением работают несколько команд.
- В случаях, когда долгосрочный эффект предпочтительнее краткосрочного.
- В команде есть архитекторы ПО, способные разработать микросервисную архитектуру.
Источник: https://towardsdatascience.com/microservice-architecture-and-its-10-most-important-design-patterns-824952d7fa41
👍1
День восемьсот восемьдесят четвёртый. #DesignPatterns #Microservices
Паттерны в Микросервисах
1. База Данных на Микросервис
Когда компания заменяет большую монолитную систему множеством мелких микросервисов, самое важное решение, с которым она сталкивается, - это база данных. В монолитной архитектуре используется большая централизованная база данных. Многие архитекторы предпочитают сохранять базу данных как есть, даже при переходе на микросервисную архитектуру. Хотя это даёт некоторую краткосрочную выгоду, это анти-шаблон, особенно в крупной системе, поскольку микросервисы будут тесно связаны на уровне базы данных. Весь смысл перехода на микросервисы (расширение возможностей команды, независимая разработка) потеряется.
Лучший подход - предоставить каждому микросервису собственное хранилище данных, чтобы не было сильной связи между службами на уровне базы данных (см. рисунок ниже). Здесь термин «база данных» используется, чтобы показать логическое разделение данных, то есть микросервисы могут совместно использовать одну и ту же физическую базу данных, но они должны использовать отдельную схему/коллекцию/таблицу. Это также гарантирует, что микросервисы правильно разделены в соответствии с предметно-ориентированным проектированием (DDD).
Плюсы
- Полное владение данными для каждого сервиса.
- Слабая связь между командами, разрабатывающими сервисы.
Минусы
- Обмен данными между службами становится проблематичным.
- Предоставление транзакционной гарантии ACID для приложения становится намного сложнее.
- Разделение монолитной базы данных на более мелкие части требует тщательного проектирования и является сложной задачей.
Когда использовать:
- В крупномасштабных корпоративных приложениях.
- Когда команде необходимо полное владение своими микросервисами для масштабирования и скорости разработки.
Когда не использовать:
- В небольших приложениях.
- Если одна команда разработает все микросервисы.
Поддержка
Все базы данных SQL и NoSQL предлагают логическое разделение данных (например, отдельные таблицы, коллекции, схемы, базы данных).
Подробнее:
- Microservices Pattern: Database per service
- Распределённые данные
Источник: https://towardsdatascience.com/microservice-architecture-and-its-10-most-important-design-patterns-824952d7fa41
Паттерны в Микросервисах
1. База Данных на Микросервис
Когда компания заменяет большую монолитную систему множеством мелких микросервисов, самое важное решение, с которым она сталкивается, - это база данных. В монолитной архитектуре используется большая централизованная база данных. Многие архитекторы предпочитают сохранять базу данных как есть, даже при переходе на микросервисную архитектуру. Хотя это даёт некоторую краткосрочную выгоду, это анти-шаблон, особенно в крупной системе, поскольку микросервисы будут тесно связаны на уровне базы данных. Весь смысл перехода на микросервисы (расширение возможностей команды, независимая разработка) потеряется.
Лучший подход - предоставить каждому микросервису собственное хранилище данных, чтобы не было сильной связи между службами на уровне базы данных (см. рисунок ниже). Здесь термин «база данных» используется, чтобы показать логическое разделение данных, то есть микросервисы могут совместно использовать одну и ту же физическую базу данных, но они должны использовать отдельную схему/коллекцию/таблицу. Это также гарантирует, что микросервисы правильно разделены в соответствии с предметно-ориентированным проектированием (DDD).
Плюсы
- Полное владение данными для каждого сервиса.
- Слабая связь между командами, разрабатывающими сервисы.
Минусы
- Обмен данными между службами становится проблематичным.
- Предоставление транзакционной гарантии ACID для приложения становится намного сложнее.
- Разделение монолитной базы данных на более мелкие части требует тщательного проектирования и является сложной задачей.
Когда использовать:
- В крупномасштабных корпоративных приложениях.
- Когда команде необходимо полное владение своими микросервисами для масштабирования и скорости разработки.
Когда не использовать:
- В небольших приложениях.
- Если одна команда разработает все микросервисы.
Поддержка
Все базы данных SQL и NoSQL предлагают логическое разделение данных (например, отдельные таблицы, коллекции, схемы, базы данных).
Подробнее:
- Microservices Pattern: Database per service
- Распределённые данные
Источник: https://towardsdatascience.com/microservice-architecture-and-its-10-most-important-design-patterns-824952d7fa41
День восемьсот восемьдесят пятый. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
90. Навыки, Необходимые Сеньору, Помимо Программирования
Сегодня вашему вниманию несколько шуточный список навыков, которыми должен обладать старший разработчик или тимлид. Предлагайте свои варианты в комментариях.
1. Как провести собрание. И нет, больше всего говорить на собрании, не то же самое, что проводить его.
2. Как написать проектную документацию, получить отзывы и довести её до решения в разумные сроки.
3. Как подсказать товарищу по команде, начинающему карьеру, инженеру в середине карьеры, новому менеджеру, которому нужен технический совет.
4. Как говорить со старшим менеджером о технических вещах, в которых он на самом деле ничего не понимает, не закатывая глаза и не заставляя его чувствовать себя глупо.
5. Как объяснить техническую концепцию важному начальнику, который стесняется признаться, что он её не понимает.
6. Как убедить другую команду использовать ваше решение вместо написания собственного.
7. Как заставить другого инженера сделать что-то для вас, попросив о помощи таким образом, чтобы он почувствовал, что его ценят.
8. Как вести проект, даже если вы не управляете никем из людей, работающих над ним.
9. Как заставить других инженеров прислушиваться к вашим идеям, не заставляя их чувствовать в вас угрозу.
10. Как прислушиваться к идеям других инженеров и не чувствовать в них угрозы.
11. Как отказаться от своего ребёнка (от проекта, который вы превратили во что-то существенное), чтобы заняться чем-то другим.
12. Как научить другого инженера заботиться о том, что вас действительно волнует (операции, форматирование, тестирование, качество кода, производительность, простота и т.д.).
13. Как правильно сообщать о статусе проекта инвесторам.
14. Как убедить руководство в том, что им нужно инвестировать в нетривиальный технический проект.
15. Как создавать программное обеспечение, привнося при этом дополнительную ценность в процессе.
16. Как составить проектное предложение, разрекламировать его и получить поддержку для его реализации.
17. Сколько раз достаточно повторить, чтобы люди начали слушать.
18. Как выбрать правильных бойцов в команду.
19. Как помочь кому-то продвинуться по службе.
20. Как получить информацию о том, что на самом деле происходит (как сплетничать, как найти подход к разным людям).
21. Как найти интересную работу самостоятельно, а не ждать, пока кто-то её вам принесет.
22. Как сказать кому-то, что он неправ, не унизив его.
23. Как правильно воспринимать отрицательные отзывы.
Источник: https://skamille.medium.com/an-incomplete-list-of-skills-senior-engineers-need-beyond-coding-8ed4a521b29f
Автор оригинала – Camille Fournier
97 Вещей, Которые Должен Знать Каждый Программист
90. Навыки, Необходимые Сеньору, Помимо Программирования
Сегодня вашему вниманию несколько шуточный список навыков, которыми должен обладать старший разработчик или тимлид. Предлагайте свои варианты в комментариях.
1. Как провести собрание. И нет, больше всего говорить на собрании, не то же самое, что проводить его.
2. Как написать проектную документацию, получить отзывы и довести её до решения в разумные сроки.
3. Как подсказать товарищу по команде, начинающему карьеру, инженеру в середине карьеры, новому менеджеру, которому нужен технический совет.
4. Как говорить со старшим менеджером о технических вещах, в которых он на самом деле ничего не понимает, не закатывая глаза и не заставляя его чувствовать себя глупо.
5. Как объяснить техническую концепцию важному начальнику, который стесняется признаться, что он её не понимает.
6. Как убедить другую команду использовать ваше решение вместо написания собственного.
7. Как заставить другого инженера сделать что-то для вас, попросив о помощи таким образом, чтобы он почувствовал, что его ценят.
8. Как вести проект, даже если вы не управляете никем из людей, работающих над ним.
9. Как заставить других инженеров прислушиваться к вашим идеям, не заставляя их чувствовать в вас угрозу.
10. Как прислушиваться к идеям других инженеров и не чувствовать в них угрозы.
11. Как отказаться от своего ребёнка (от проекта, который вы превратили во что-то существенное), чтобы заняться чем-то другим.
12. Как научить другого инженера заботиться о том, что вас действительно волнует (операции, форматирование, тестирование, качество кода, производительность, простота и т.д.).
13. Как правильно сообщать о статусе проекта инвесторам.
14. Как убедить руководство в том, что им нужно инвестировать в нетривиальный технический проект.
15. Как создавать программное обеспечение, привнося при этом дополнительную ценность в процессе.
16. Как составить проектное предложение, разрекламировать его и получить поддержку для его реализации.
17. Сколько раз достаточно повторить, чтобы люди начали слушать.
18. Как выбрать правильных бойцов в команду.
19. Как помочь кому-то продвинуться по службе.
20. Как получить информацию о том, что на самом деле происходит (как сплетничать, как найти подход к разным людям).
21. Как найти интересную работу самостоятельно, а не ждать, пока кто-то её вам принесет.
22. Как сказать кому-то, что он неправ, не унизив его.
23. Как правильно воспринимать отрицательные отзывы.
Источник: https://skamille.medium.com/an-incomplete-list-of-skills-senior-engineers-need-beyond-coding-8ed4a521b29f
Автор оригинала – Camille Fournier
День восемьсот восемьдесят шестой. #ЗаметкиНаПолях
Начиная с .NET 5 Изменение Значений в Dictionary в Foreach не Выбрасывает Исключения
Давно известно, что внутри цикла
System.InvalidOperationException: Collection was modified; enumeration operation may not execute. (Коллекция изменена; операция перечисления не может быть выполнена.)
Однако, начиная с .NET 5, он выполняется без проблем. Что случилось?
В исходный код
Удаление из словаря с помощью метода Remove также больше не влияет на перечисление. Это, однако, существует с .NET Core 3.0 и соответствующим образом упоминается в документации метода
«Только .NET Core 3.0+: Этот метод изменения может быть безопасно вызван без аннуляции активных перечислителей экземпляра Dictionary<TKey,TValue>. Но это не подразумевает потокобезопасность.»
Несмотря на то, что вышеупомянутое изменение значений при перечислении просят внести в документацию, на момент выхода этого поста, этого пока не сделано.
Источник: https://stackoverflow.com/questions/66939923/what-changed-in-net-5-that-makes-it-not-throw-when-changing-dictionary-values-i
Начиная с .NET 5 Изменение Значений в Dictionary в Foreach не Выбрасывает Исключения
Давно известно, что внутри цикла
foreach
нельзя изменять элементы коллекции. Однако, рассмотрим следующий код:var d = new Dictionary<string, int>
{ { "a", 0 }, { "b", 0 }, { "c", 0 } };
foreach (var k in d.Keys)
{
d[k]+=1;
}
В .NET Core 3.1 и ранее этот код выдавал ожидаемое исключение:System.InvalidOperationException: Collection was modified; enumeration operation may not execute. (Коллекция изменена; операция перечисления не может быть выполнена.)
Однако, начиная с .NET 5, он выполняется без проблем. Что случилось?
В исходный код
Dictionary<TKey, TValue>
было внесено изменение, позволяющее обновлять значения по существующим ключам во время перечисления. Убрали обновление внутреннего поля _version при изменении элементов. Поле _version (которое используется для обнаружения изменений) теперь обновляется только при определённых условиях, но не при изменении значения по существующему ключу.Удаление из словаря с помощью метода Remove также больше не влияет на перечисление. Это, однако, существует с .NET Core 3.0 и соответствующим образом упоминается в документации метода
Remove
:«Только .NET Core 3.0+: Этот метод изменения может быть безопасно вызван без аннуляции активных перечислителей экземпляра Dictionary<TKey,TValue>. Но это не подразумевает потокобезопасность.»
Несмотря на то, что вышеупомянутое изменение значений при перечислении просят внести в документацию, на момент выхода этого поста, этого пока не сделано.
Источник: https://stackoverflow.com/questions/66939923/what-changed-in-net-5-that-makes-it-not-throw-when-changing-dictionary-values-i
День восемьсот восемьдесят седьмой. #DesignPatterns #Microservices
Паттерны в Микросервисах
2. Источники Событий (Event Sourcing)
В микросервисной архитектуре, особенно с использованием паттерна «База данных на микросервис», микросервисы должны обмениваться данными. Для отказоустойчивых, высокомасштабируемых и отказоустойчивых систем они должны обмениваться данными асинхронно, обмениваясь Событиями. В этом случае вам может понадобиться выполнить атомарные операции, например, обновить базу данных и отправить сообщение. Если у вас есть базы данных SQL и вы хотите иметь распределённые транзакции для большого объема данных, вы не можете использовать двухфазную блокировку (2PL), поскольку она не масштабируется. Если вы используете базы данных NoSQL и хотите иметь распределённую транзакцию, вы не можете использовать 2PL, поскольку многие базы данных NoSQL не поддерживают двухфазную блокировку.
В таких сценариях используйте архитектуру на основе событий. В традиционных базах данных бизнес-объект с текущим «состоянием» сохраняется напрямую. В Event Sourcing любое событие, изменяющее состояние, или другие важные события сохраняются вместо сущностей. Это означает, что изменения бизнес-объекта сохраняются в виде серии неизменяемых событий. Состояние бизнес-объекта высчитывается путём повторной обработки всех событий этого бизнес-объекта в заданное время. Поскольку данные сохраняются в виде серии событий, а не через прямые обновления в хранилищах данных, различные службы могут воспроизводить события из хранилища событий, чтобы вычислить необходимое состояние соответствующих хранилищ данных. См. картинку ниже.
Плюсы
- Обеспечение атомарности высокомасштабируемым системам.
- Автоматическое сохранение истории сущностей, включая функционал «путешествий во времени».
- Возможность создания слабосвязанных микросервисов, управляемых событиями.
Минусы
- Чтение сущностей из хранилища событий становится сложной задачей и обычно требует дополнительного хранилища данных (паттерн CQRS)
- Общая сложность системы возрастает, и обычно требуется доменно-ориентированный дизайн.
- Система должна обрабатывать повторяющиеся события (идемпотентные) или отсутствующие события.
- Миграция схемы событий становится сложной задачей.
Когда использовать:
- Высокомасштабируемые транзакционные системы с базами данных SQL.
- Транзакционные системы с базами данных NoSQL.
- Высоко масштабируемая и устойчивая микросервисная архитектура.
- Типичные системы, управляемые сообщениями или событиями (системы электронной коммерции, бронирования и резервирования).
Когда не использовать:
- Слабо масштабируемые транзакционные системы с базами данных SQL.
- В простой микросервисной архитектуре, где микросервисы могут синхронно обмениваться данными (например, через API).
Поддержка
Хранилища: EventStoreDB, Apache Kafka, Confluent Cloud, AWS Kinesis, Azure Event Hub, GCP Pub/Sub, Azure Cosmos DB, MongoDB, Cassandra, Amazon DynamoDB.
Фреймворки: Lagom, Akka, Spring, akkatecture, Axon, Eventuate
Подробнее:
- Microservices Pattern: Event sourcing
- Шаблон источников событий
Источник: https://towardsdatascience.com/microservice-architecture-and-its-10-most-important-design-patterns-824952d7fa41
Паттерны в Микросервисах
2. Источники Событий (Event Sourcing)
В микросервисной архитектуре, особенно с использованием паттерна «База данных на микросервис», микросервисы должны обмениваться данными. Для отказоустойчивых, высокомасштабируемых и отказоустойчивых систем они должны обмениваться данными асинхронно, обмениваясь Событиями. В этом случае вам может понадобиться выполнить атомарные операции, например, обновить базу данных и отправить сообщение. Если у вас есть базы данных SQL и вы хотите иметь распределённые транзакции для большого объема данных, вы не можете использовать двухфазную блокировку (2PL), поскольку она не масштабируется. Если вы используете базы данных NoSQL и хотите иметь распределённую транзакцию, вы не можете использовать 2PL, поскольку многие базы данных NoSQL не поддерживают двухфазную блокировку.
В таких сценариях используйте архитектуру на основе событий. В традиционных базах данных бизнес-объект с текущим «состоянием» сохраняется напрямую. В Event Sourcing любое событие, изменяющее состояние, или другие важные события сохраняются вместо сущностей. Это означает, что изменения бизнес-объекта сохраняются в виде серии неизменяемых событий. Состояние бизнес-объекта высчитывается путём повторной обработки всех событий этого бизнес-объекта в заданное время. Поскольку данные сохраняются в виде серии событий, а не через прямые обновления в хранилищах данных, различные службы могут воспроизводить события из хранилища событий, чтобы вычислить необходимое состояние соответствующих хранилищ данных. См. картинку ниже.
Плюсы
- Обеспечение атомарности высокомасштабируемым системам.
- Автоматическое сохранение истории сущностей, включая функционал «путешествий во времени».
- Возможность создания слабосвязанных микросервисов, управляемых событиями.
Минусы
- Чтение сущностей из хранилища событий становится сложной задачей и обычно требует дополнительного хранилища данных (паттерн CQRS)
- Общая сложность системы возрастает, и обычно требуется доменно-ориентированный дизайн.
- Система должна обрабатывать повторяющиеся события (идемпотентные) или отсутствующие события.
- Миграция схемы событий становится сложной задачей.
Когда использовать:
- Высокомасштабируемые транзакционные системы с базами данных SQL.
- Транзакционные системы с базами данных NoSQL.
- Высоко масштабируемая и устойчивая микросервисная архитектура.
- Типичные системы, управляемые сообщениями или событиями (системы электронной коммерции, бронирования и резервирования).
Когда не использовать:
- Слабо масштабируемые транзакционные системы с базами данных SQL.
- В простой микросервисной архитектуре, где микросервисы могут синхронно обмениваться данными (например, через API).
Поддержка
Хранилища: EventStoreDB, Apache Kafka, Confluent Cloud, AWS Kinesis, Azure Event Hub, GCP Pub/Sub, Azure Cosmos DB, MongoDB, Cassandra, Amazon DynamoDB.
Фреймворки: Lagom, Akka, Spring, akkatecture, Axon, Eventuate
Подробнее:
- Microservices Pattern: Event sourcing
- Шаблон источников событий
Источник: https://towardsdatascience.com/microservice-architecture-and-its-10-most-important-design-patterns-824952d7fa41
👍4
Конференция по .NET-разработке DotNext ищет спикеров 🎙
Вам есть о чем рассказать и что обсудить с коллегами по цеху? Тогда вам нужно подать заявку на участие в конференции!
Осенью DotNext пройдет 18-21 октября, онлайн (гибридный формат решили отложить из-за непредсказуемости ввода ограничений на офлайн мероприятия).
Темы, которые ждут больше всего:
✔️ Internals;
✔️ Architecture;
✔️ Security;
✔️ Performance;
✔️ DevOps & Tools.
Но не ограничивайте себя этим списком — вы можете подать заявку с любой темой из области .NET-разработки.
Если все-таки сомневаетесь, то программный комитет всегда готов обсудить актуальность темы и помочь выбрать правильный вектор доклада. Плюс, ребята помогут с прокачкой ваших ораторских навыков, если у вас мало опыта в публичных выступлениях.
✅ Подать заявку и узнать подробности можно на сайте.
❓Вопросы присылайте на почту [email protected]
Вам есть о чем рассказать и что обсудить с коллегами по цеху? Тогда вам нужно подать заявку на участие в конференции!
Осенью DotNext пройдет 18-21 октября, онлайн (гибридный формат решили отложить из-за непредсказуемости ввода ограничений на офлайн мероприятия).
Темы, которые ждут больше всего:
✔️ Internals;
✔️ Architecture;
✔️ Security;
✔️ Performance;
✔️ DevOps & Tools.
Но не ограничивайте себя этим списком — вы можете подать заявку с любой темой из области .NET-разработки.
Если все-таки сомневаетесь, то программный комитет всегда готов обсудить актуальность темы и помочь выбрать правильный вектор доклада. Плюс, ребята помогут с прокачкой ваших ораторских навыков, если у вас мало опыта в публичных выступлениях.
✅ Подать заявку и узнать подробности можно на сайте.
❓Вопросы присылайте на почту [email protected]
День восемьсот восемьдесят восьмой. #TypesAndLanguages
4. Проблема Алмаза. Начало
Проблема Алмаза, иногда называемая Смертельным Алмазом Смерти, возникает, когда мы наследуем одно и то же через несколько базовых сущностей. Если вы думаете, что «проблема есть в C++, но её не существует в Java или C#», то вы слишком сосредотачиваетесь на технической части.
Наследование
Обычно мы говорим, что в Java или C# существует одиночное наследование и множественная реализация интерфейсов. Это правда, но за этим скрывается гораздо более широкая картина.
Наследование позволяет наследовать характеристики и функции от базовой сущности (в большинстве случаев от класса или объекта). Есть много вещей, которые мы можем унаследовать, или много уровней наследования:
1. Наследование сигнатуры
В интерфейсе объявлен метод, мы наследуем его и предоставляем реализацию. Сигнатура здесь означает, что это только «заголовок» метода, без тела. Важно понимать, что эта «сигнатура наследования» не обязательно должна совпадать с «сигнатурой вызова». Например, вы не можете изменить тип возвращаемого значения при реализации интерфейса в C#, но тип возвращаемого значения не является частью «сигнатуры вызова». Java допускает это, но это детали реализации. Когда мы говорим о «наследовании сигнатуры», мы имеем в виду только заголовок метода, который мы получаем от базовой сущности.
2. Наследование реализации
При наследовании реализации мы получаем не только сигнатуру, но и всё тело метода. Это не так давно стало доступно в Java или C# через реализации интерфейса по умолчанию. Это можно рассматривать как типажи (traits). И хотя между наследованием реализации и трейтами есть некоторые различия, они довольно близки друг к другу.
3. Наследование состояния
Это наследование полей. При наследовании состояния мы получаем поле из базовой сущности, которое мы можем использовать в подклассе. В некоторой степени это похоже на примеси (mixins). Также стоит отметить, что у нас может быть наследование состояния без наследования реализации, но в большинстве случаев эти два аспекта объединяются.
4. Наследование идентичности
Можно считать «наследованием конструктора» (не вдаваясь в теорию типов). Разница между миксином и наследованием от класса сводится к конструктору. Вы можете создать экземпляр и получить новую идентичность. Обычно мы получаем идентичность, создавая базовую сущность и «удерживая» её внутри подобъекта.
Наследование в C# и Java
C++ имеет множественное наследование и не делает различий между классом и интерфейсом. В C# и Java запрещено всё, кроме наследования сигнатур. Однако важно понимать, что утверждение, что «в C# и Java не существует множественного наследования», неверно. Существует множественное наследование для сигнатур и одиночное наследование для всего остального.
Однако позже создатели языков поняли, что это может быть не лучшая идея, и была добавлена реализация интерфейса по умолчанию, которая по сути является «наследованием реализации».
Продолжение следует…
Источник: https://blog.adamfurmanek.pl/2021/02/06/types-and-programming-languages-part-4/
4. Проблема Алмаза. Начало
Проблема Алмаза, иногда называемая Смертельным Алмазом Смерти, возникает, когда мы наследуем одно и то же через несколько базовых сущностей. Если вы думаете, что «проблема есть в C++, но её не существует в Java или C#», то вы слишком сосредотачиваетесь на технической части.
Наследование
Обычно мы говорим, что в Java или C# существует одиночное наследование и множественная реализация интерфейсов. Это правда, но за этим скрывается гораздо более широкая картина.
Наследование позволяет наследовать характеристики и функции от базовой сущности (в большинстве случаев от класса или объекта). Есть много вещей, которые мы можем унаследовать, или много уровней наследования:
1. Наследование сигнатуры
В интерфейсе объявлен метод, мы наследуем его и предоставляем реализацию. Сигнатура здесь означает, что это только «заголовок» метода, без тела. Важно понимать, что эта «сигнатура наследования» не обязательно должна совпадать с «сигнатурой вызова». Например, вы не можете изменить тип возвращаемого значения при реализации интерфейса в C#, но тип возвращаемого значения не является частью «сигнатуры вызова». Java допускает это, но это детали реализации. Когда мы говорим о «наследовании сигнатуры», мы имеем в виду только заголовок метода, который мы получаем от базовой сущности.
2. Наследование реализации
При наследовании реализации мы получаем не только сигнатуру, но и всё тело метода. Это не так давно стало доступно в Java или C# через реализации интерфейса по умолчанию. Это можно рассматривать как типажи (traits). И хотя между наследованием реализации и трейтами есть некоторые различия, они довольно близки друг к другу.
3. Наследование состояния
Это наследование полей. При наследовании состояния мы получаем поле из базовой сущности, которое мы можем использовать в подклассе. В некоторой степени это похоже на примеси (mixins). Также стоит отметить, что у нас может быть наследование состояния без наследования реализации, но в большинстве случаев эти два аспекта объединяются.
4. Наследование идентичности
Можно считать «наследованием конструктора» (не вдаваясь в теорию типов). Разница между миксином и наследованием от класса сводится к конструктору. Вы можете создать экземпляр и получить новую идентичность. Обычно мы получаем идентичность, создавая базовую сущность и «удерживая» её внутри подобъекта.
Наследование в C# и Java
C++ имеет множественное наследование и не делает различий между классом и интерфейсом. В C# и Java запрещено всё, кроме наследования сигнатур. Однако важно понимать, что утверждение, что «в C# и Java не существует множественного наследования», неверно. Существует множественное наследование для сигнатур и одиночное наследование для всего остального.
Однако позже создатели языков поняли, что это может быть не лучшая идея, и была добавлена реализация интерфейса по умолчанию, которая по сути является «наследованием реализации».
Продолжение следует…
Источник: https://blog.adamfurmanek.pl/2021/02/06/types-and-programming-languages-part-4/