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

Для связи: @SBenzenko

Поддержать канал:
- https://boosty.to/netdeveloperdiary
- https://patreon.com/user?u=52551826
- https://pay.cloudtips.ru/p/70df3b3b
Download Telegram
День 1527. #TipsAndTricks #Git
Некоторые Малоизвестные Приемы в Git
Сегодня несколько полезных советов при работе с Git для любителей консоли.

1. Изменение последнего коммита
Когда вы делаете коммит в репозитории Git, вы создаёте новый снимок своего кода. Иногда вы можете обнаружить, что забыли включить файл, допустили опечатку в сообщении коммита или внесли другие небольшие изменения, которые хотели бы включить в последний коммит. Git позволяет изменить последний коммит с помощью флага --amend:
# изменить последний коммит новым сообщением
git commit --amend -m "New message"

# изменить, не меняя сообщения
git commit --amend --no-edit

2. Reflog
Git отслеживает все изменения, которые вы вносите в репозиторий, включая коммиты, слияния и другие операции. Reflog — это журнал всех изменений в репозитории Git, включая все коммиты, изменения веток и другие операции. Вы можете использовать журнал ссылок для восстановления потерянных коммитов, возврата к предыдущему состоянию или отмены перебазирования.
Чтобы просмотреть журнал ссылок, запустите:
git reflog

# возврат к предыдущему состоянию
git reset HEAD@{N}

3. Интерактивное перебазирование
Это мощный инструмент, который позволяет редактировать, изменять порядок или удалять коммиты перед их слиянием с основной веткой. Это особенно полезно, когда вы работаете над функциональной веткой и хотите очистить историю коммитов перед её слиянием с основной веткой:
git rebase -i HEAD~N

# изменить сообщение коммита
pick 1234567 Old message
reword 2345678 New message

# изменить порядок коммитов
pick 1234567 First commit
pick 2345678 Second commit
pick 3456789 Third commit

# удалить коммит
pick 1234567 First commit
drop 2345678 Second commit
pick 3456789 Third commit

4. Git-псевдонимы
Псевдонимы Git позволяют создавать собственные ярлыки для команд Git. Это может сэкономить ваше время и объём ввода, особенно для часто используемых команд:
git config --global alias.ci commit

# использование
git ci -m "Commit message"

5. Git Stash
Git stash позволяет временно сохранять изменения, которые вы ещё не готовы зафиксировать, без создания новой ветки:
git stash

# применить последние сохранённые изменения
git stash apply

# применить выбранные сохранённые изменения
git stash apply stash@{N}

# список всех изменений
git stash list

Больше консольных команд Git в этом посте.

Источник: https://dev.to/atordvairn/some-secret-git-tricks-that-come-in-handy-2k8i
👍17
День 1528. #Карьера
Решение Проблем — Это не Навык

Самое главное, когда дело касается программирования, это конкретные знания, необходимые для решения задачи.

Меня всегда беспокоила мысль, что программирование — это просто решение проблем. Я думаю, потому что так обычно говорят в контексте карьерного совета в сфере разработке ПО, и это типичный ответ на вопрос «Как стать лучше в программировании?»

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

Но многие люди, кажется, повторяют, что программирование — это просто решение проблем, потому что легче сказать это, чем дать конкретный совет. Только когда я наткнулся на этот пост Скотта Янга «Cognitive Load Theory», я понял, почему идея о том, что решение проблем является основным мета-навыком программирования, казалась мне подозрительной.

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

Другими словами, чтобы решить задачу в программировании, вам нужно иметь определённые знания в области, позволяющие её решить. Конечно, Шерлок Холмс с его способностью к дедукции и логическому мышлению мог бы придумать что-то близкое к псевдокоду для решения FizzBuzz, но, если он не знает, как писать на языке программирования, он не сможет действительно решить задачу. Ему нужно знать разницу между чётными и нечётными числами (я уверен, что знает), а также специфический синтаксис языка программирования, например операторы if и что делает оператор деления по модулю %.

Проблема при приравнивании программирования к решению проблем, заключается в том, что это одна из тех идей, которые приятно слышать. Потому что все хороши в решении проблем, по крайней мере, некоторых типов проблем. Кто-то хорош в кроссвордах, кто-то в судоку, кто-то в шахматах, кто-то чинит машины, а кто-то готовит кофе. Но эти навыки не обязательно применимы к программированию.

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

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

Источник: https://betterprogramming.pub/problem-solving-isnt-a-skill-a32c22b71602
Автор оригинала: Jay Cruz
👍11👎4
День 1529. #TipsAndTricks
9 Советов по Fluent Assertions, Которые Сэкономят Вам Время. Начало
Хороший программист всегда думает о будущем ПО, о том, как написать код, который будет легко читать и понимать.

Один из лучших способов улучшить читаемость юнит-тестов — использовать Fluent Assertions https://fluentassertions.com/ — набор методов расширения для утверждений, делающий их более читаемыми и понятными. Fluent API означает, что библиотека полагается на цепочку методов. Вы комбинируете несколько методов в одном операторе без необходимости сохранять промежуточные результаты в переменных. Вот несколько примеров.

1. Идентификация субъекта – Be()
Первый пример простой. Мы хотим проверить, равно ли целое число 5:
int number = 5;
number.Should().Be(5);

Можно добавить сообщение. Отличительной особенностью сообщений Fluent Assertions, является то, что вы добавляете объяснение в середину сообщения:
int number = 6;
number.Should().Be(5,
"because that is the correct amount");

В итоге получается следующее сообщение:
Expected number to be 5 because that is the correct amount, but found 6. (Ожидалось, что number будет 5, потому что это правильное количество, но найдено 6.)

2. Основные утверждения
Для всех ссылочных типов:
sut.Should().BeNull();
….NotBeNull();
….BeOfType<Customer>();
// для сравнения используется Equals
….Be(otherCustomer);

Для строк:
"string".Should().BeNullOrEmpty();
….BeNullOrWhiteSpace();
….NotBeNullOrEmpty();
….NotBeNullOrWhiteSpace();

Для логических типов доступны BeTrue и BeFalse.

Для числовых типов:
number.Should().Be(1);
….NotBe(10);
….BePositive();
….BeNegative();
….BeGreaterThanOrEqualTo(88);
….BeGreaterThan(66);
….BeLessThanOrEqualTo(56);
….BeLessThan(61);
….BeInRange(1, 5);
….NotBeInRange(6, 9);

3. BeEquivalentTo — сравнение графов объектов
BeEquivalentTo — позволяет сравнить, имеют ли два объекта одинаковые свойства с одинаковыми значениями. Два объекта не обязательно должны быть одного типа. Вот примечание к этому методу от авторов:
Объекты эквивалентны, когда оба графа объектов имеют свойства с одинаковыми именами и одинаковыми значениями, независимо от типа этих объектов. Два свойства также равны, если один тип может быть преобразован в другой, и результат равен. Тип свойства коллекции игнорируется до тех пор, пока коллекция реализует System.Collections.Generic.IEnumerable’1 и все элементы коллекции структурно одинаковы. Обратите внимание, что фактическое поведение определяется глобальными значениями по умолчанию, управляемыми FluentAssertions.AssertionOptions.

Довольно часто встречаются классы с одинаковыми свойствами. Это особенно актуально, когда методы API обычно принимают DTO в качестве параметра:
customer.Should()
.BeEquivalentTo(customerDto);

Разница между Be и BeEquivalentTo в том, что Be сравнивает два объекта на основе реализации System.Object.Equals(System.Object). BeEquivalentTo сравнивает свойства и требует, чтобы свойства имели одинаковые имена, независимо от фактического типа свойств.

4. Цепочки утверждений - And
Чтобы связать несколько утверждений, вы можете использовать ограничение And. Пример:
collectionToTest.Should().Contain("first")
.And.HaveElementAt(2, "third");

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

Источник: https://methodpoet.com/fluent-assertions/
👍17
День 1530. #TipsAndTricks
9 Советов по Fluent Assertions, Которые Сэкономят Вам Время. Продолжение
Начало

5. Методы расширения коллекции
var coll = new List<string>
{ "first", "second" };
var coll2 = new List<string>
{ "first", "second" };

Методов расширения для коллекций множество. Думаю, имена говорят сами за себя:
coll.Should().NotBeEmpty();
….HaveCount(2);
….Equal(coll2);
….Equal("first", "second");
….BeEquivalentTo(coll2);
….NotBeEquivalentTo(
new List<string> { "1", "2" });

….OnlyHaveUniqueItems();
….HaveCountGreaterThan(1);
….HaveCountGreaterThanOrEqualTo(2);
….HaveCountLessThanOrEqualTo(5);
….HaveCountLessThan(5);
….NotHaveCount(1);

….StartWith("first");
….StartWith(
new List<string> { "first" });
….EndWith("second");
….EndWith(
new List<string> { "first", "second" });
….Contain("first")
.And.HaveElementAt(1, "first");

….BeEmpty();
….BeNullOrEmpty();
….NotBeNullOrEmpty();
….ContainInOrder(
new List<string> { "first", "second" });
….NotContainInOrder(
new List<string> { "1", "2", "3" });

….BeInAscendingOrder();
….BeInDescendingOrder();
….NotBeInAscendingOrder();
….NotBeInDescendingOrder();

6. Утверждения даты и времени
DateTime date = new DateTime(2022, 2, 7);

date.Should().Be(7.February(2022).At(0,0));
….BeAfter(6.February(2022).At(23,59));
….BeBefore(8.February(2022).At(0,1));
….BeSameDateAs(7.February(2022));

….NotBe(6.February(2022));
….NotBeAfter(8.February(2022).At(10, 28));
….NotBeBefore(1.January(2022));
….NotBeSameDateAs(27.February(2022));

7. Область действия утверждений - AssertionScope
Вы можете использовать AssertionScope для объединения нескольких утверждений в одно исключение. Это делает код чище и позволяет проверить сразу все утверждения, вместо завершения теста после первой неудачи:
int numberOfDocuments = 5;
using (new AssertionScope())
{
numberOfDocuments.Should().Be(6);
"First Name".Should().Be("Last Name");
}

В примере выше будут отображены оба сбоя и возникнет исключение в момент удаления AssertionScope:
Expected numberOfDocuments to be 6, but found 5.
Expected string to be "Last Name" with a length of 9, but "First Name" has a length of 10, differs near "Fir" (index 0).
(Ожидалось, что numberOfDocuments будет равно 6, но найдено 5.
Ожидалось, что строка будет «Last Name» длиной 9, но «First Name» имеет длину 10 и отличается рядом с «Fir» (индекс 0)
).

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

Источник:
https://methodpoet.com/fluent-assertions/
👍10
День 1531. #TipsAndTricks
9 Советов по Fluent Assertions, Которые Сэкономят Вам Время. Окончание
Начало
Продолжение

8. Проверка исключений
Теперь проверим, что метод выдаёт исключение:
Action act = () => sut.BadMethod();
act.Should().Throw<ArgumentException>();

И наоборот:
Action act = () => sut.GoodMethod();
act.Should()
.NotThrow<NullReferenceException>();

Также поддерживаются асинхронные версии:
Func<Task> act = () => sut.iss.onethodAsync();

await act.Should()
.ThrowAsync<ArgumentNullException>();

await act.Should().NotThrowAsync();

9. Создание утверждений
Вы можете написать свои утверждения, которые проверяют ваши классы и терпят неудачу, если условие не выполняется. Следующее утверждение ищет символ @ в поле адреса электронной почты. Переменная email представляет собой строку, поэтому создадим метод расширения для StringAssertions:
public static class EmailStringExtensions
{
public static AndConstraint<StringAssertions>
ContainAtSign(
this StringAssertions email,
string because = "",
params object[] becauseArgs)
{
Execute.Assertion
.BecauseOf(because, becauseArgs)
.ForCondition(email.Subject.Contains('@'))
.FailWith(
"Expected email to contain @{reason}.");

return new AndConstraint<StringAssertions>(email);
}
}

Использование:
string email = "[email protected]";
email.Should()
.ContainAtSign("because that’s valid email");

Также можно создавать утверждения для ваших классов, наследуя от ReferenceTypeAssertions.

Итого
Недостаточно знать, как писать юнит-тесты, необходимо писать читаемые тесты. Один из лучших способов — использовать Fluent Assertions. Эта библиотека позволяет писать чётко определённые утверждения, которые позволяют любому, кто читает ваши тесты, понять, что именно они тестируют. Я представил лишь небольшую часть функциональных возможностей Fluent Assertions, их гораздо больше (см. документацию).

Источник: https://methodpoet.com/fluent-assertions/
👍19
День 1532. #ЧтоНовенького
Улучшения Аутентификации и Идентификации в
ASP.NET Core 8
Команда ASP.NET Core совершенствует проверку подлинности, авторизацию и управление идентификацией в .NET 8.

Для аутентификации в ASP.NET Core сейчас есть несколько вариантов:
1. ASP.NET Core Identity.
2. Azure Active Directory (Azure AD).
3. Различные сторонние решения в виде пакетов, контейнеров и облачных сервисов.

Сегодня существуют ограничения на использование ASP.NET Core Identity в SPA-приложениях. Традиционный способ настройки страниц, связанных с идентификацией, заставляет приложение вернуться к серверным веб-страницам, а также использовать внешние (сторонние) пакеты для поддержки аутентификации на основе токенов.

Поэтому планируется устранить зависимость от Duende IdentityServer из шаблонов SPA в .NET 8. IdentityServer остается отличным вариантом для self-hosting сценариев и остаётся бесплатным, если вы соответствуете требованиям community edition. Но существует множество других вариантов, включая OpenIddict или Keycloak. Теперь шаблон приложения будет содержать ссылку на страницу документации с пояснением вариантов реализации аутентификации. Кстати, про Keycloack вчера был доклад на Ozon Tech Meetup.

Многим не нужны сложности OAuth/OpenID Connect, а просто нужна возможность проверки личности пользователя через вход в систему и доступ к ресурсам на основе разрешений. Эта поддержка встроена в платформу ASP.NET Core Identity с момента её выпуска. Она обеспечивает стандартную аутентификацию на основе файлов cookie.

Вот области, которые планируется улучшить в ASP.NET Core 8:
1. Расширить существующую аутентификацию на основе cookie для поддержки настройки в приложениях SPA. Сейчас, чтобы настроить вход в систему, нужно переопределить серверные страницы Identity. Это приводит к непоследовательному взаимодействию с клиентами: переходу от одностраничного веб-приложения к серверному. Команда добавит конечные точки API, которые позволят разработчикам «оставаться внутри SPA».
2. Добавить поддержку аутентификации на основе токенов. Хотя существующее решение на основе cookie работает, решения для аутентификации на основе токенов в наши дни стали гораздо более гибкими. Аутентификация на основе токенов в основном будет соответствовать возможностям и функциональности cookie-решения, но инкапсулировать данные аутентификации в токен, что позволит работать в сценариях, где файлы cookie неуместны или неоптимальны.

Кроме того, для .NET 8 планируется переработка документации: создание единой точки для изучения доступных вариантов, .NET Auth, которая объединит ссылки на учебные пособия и примеры и будет содержать конкретные рекомендации. Например, SPA без внешних зависимостей предъявляет требования к аутентификации отличные от бизнес-приложения с серверной частью, базой данных, сторонними API-зависимостями и входом через социальные сети.

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

Источник: https://devblogs.microsoft.com/dotnet/improvements-auth-identity-aspnetcore-8/
👍19
День 1533. #Курсы
.NET Day
Сегодня пройдёт онлайн митап .NET Day. Желающие узнать что-то новое, регистрируйтесь здесь. А вот программа митапа.

11:00 – 11:45 (Мск.)
Райнер Стропек «Изучение новейших возможностей .NET и C# через создание игры»
Быть в курсе событий важно для разработчиков ПО, но это не должно быть скучно. На этом занятии Райнер Стропек продемонстрирует интересные возможности последних выпусков .NET и C#, создав небольшую игру на основе Skia. Вы узнаете о новостях, связанных с десериализацией JSON, сопоставлением по шаблону, записями, file-scoped типами и многими другими новыми функциями языка. На этом сеансе будет только код, без слайдов. Райнер предполагает, что у вас уже есть хорошие навыки работы с C# и .NET, и вы хотели бы узнать о последних изменениях в платформе.

12:00 – 12:45 (Мск.)
Флориан Раппл «Микрофронтенды с Blazor»
Микрофронтенды стали полезным инструментом для разбиения пользовательского интерфейса на более мелкие фрагменты, которые могут разрабатываться и развёртываться независимыми командами. В настоящее время приложения Blazor по-прежнему разрабатываются в основном в виде монолита. Хотя библиотеки и компоненты могут разрабатываться независимо, их развёртывание по-прежнему осуществляется централизованно. В долгосрочной перспективе это становится узким местом. В этом докладе эксперт по микрофронтендам Флориан Раппл представляет устоявшуюся архитектуру для создания модульных фронтенд-приложений. Он покажет, как эту архитектуру можно реализовать на Blazor для создания динамичного взаимодействия с пользователем.

13:00 – 13:45 (Мск.)
Денни Деклерк «Основы специальных возможностей»
Вы хотите научиться делать доступные веб-сайты для всех людей в мире, включая миллиард людей с ограниченными возможностями, с помощью Blazor? Тогда этот доклад определённо стоит посмотреть. Денни Деклерк расскажет, как создавать интерфейсы PWA и веб-сайтов с помощью Blazor, как сделать веб-сайты, соответствующие WCAG, действительными для всех известных групп инвалидов. Помимо Blazor, вы познакомитесь с основами семантического HTML и ARIA, узнаете о важности ALT-текста для изображений, использовании цвета, веб-сайтах доступных для программ чтения с экрана, а также о веб-сайтах, которые должны быть понятными и не сбивать пользователей с толку.

14:00 – 14:45 (Мск.)
Саймон Пейнтер «По Орегонскому пути с функциональным C#»
В 1971 году трое студентов подумали, что могут оживить лекцию по истории, создав компьютерную игру, в которую студенты могли бы играть, и после нескольких дней работы на HP Time Share BASIC они придумали то, что оказалось важной вехой в истории компьютерных игр - Oregon Trail. Однако в этом докладе акцент будет сделан не столько на исторических компьютерных играх, сколько на .NET и функциональном программировании. Задача, которую автор доклада поставил перед собой, состоит в том, чтобы переработать Oregon Trail на C#, используя следующие ограничения:
- Почти 100% покрытие модульными тестами,
- Никакие переменные не могут менять состояние после его установки,
- Никаких операторов (for, foreach, if, where и т. д.), если только их буквально невозможно избежать.
Кроме того, Саймон продемонстрирует несколько приёмов, которые может предложить функциональное программирование, например функции высшего порядка, функциональные потоки с простыми монадами и хвостовую рекурсию.

Кстати, об этом и о других предстоящих событиях я узнал из календаря предстоящих мероприятий, любезно предоставленного PVS-Studio.
👍5
День 1534. #ЧтоНовенького
DotNetIsolator
Вам когда-нибудь требовалась изолированная песочница для запуска кода? Мне тоже нет, но вдруг когда-нибудь пригодится. Сегодня порекомендую вам видео от разработчика Microsoft Стива Сандерсона. Он описывает новый экспериментальный пакет для создания такой изолированной среды – DotNetIsolator.

Пакет позволяет вашему коду .NET легко запускать другой код .NET в изолированной среде. Вы можете создать столько сред, сколько хотите. Каждая из них на самом деле является песочницей WebAssembly. Дело в том, что внутри WebAssembly мы можем исполнять код .NET. Но и сам .NET может создавать и управлять средой WebAssembly. DotNetIsolator соединяет две эти концепции.

Каждая среда имеет совершенно отдельное пространство памяти и не имеет прямого доступа к диску/сети/ОС/и т. д. хоста. Вы можете из .NET создавать экземпляры IsolatedRuntime и осуществлять вызовы в ней, создавать экземпляры IsolatedObject в этих средах выполнения и вызывать их методы, либо просто вызывать лямбда-методы внутри среды напрямую. Вы можете передавать/захватывать/возвращать произвольные значения через границу сред.

Подробное объяснение с несколькими примерами в видео https://youtu.be/5u1UaqkPZbg

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

В общем, для производственного кода он явно не подходит, но поиграться, кому интересно, можно.
День 1535. #ЗаметкиНаПолях
LINQ на Стероидах с SIMD
В этом посте рассмотрим использование SIMD-инструкций для ускорения запросов LINQ и посмотрим, как это работает совместно с «обобщённой математикой» в C# 10.

Допустим, у нас есть список чисел, и мы хотим найти сумму. Самый быстрый способ — использовать SIMD-инструкции (Single Instruction Multiple Data), которые позволяют выполнять одну и ту же операцию с несколькими значениями данных одновременно. Внимание: есть две ловушки, связанные с этим:
- Это гораздо сложнее, чем простой цикл или использование LINQ.
- Не рекомендуется для небольших наборов данных и когда производительность не критична.

Точкой входа в SIMD-операции является тип Vector<T>. T может быть любого числового типа. Тип Vector<T> имеет свойство Count, которое сообщает, сколько элементов он может содержать. Это важно, потому что, если мы, например, складываем два вектора друг с другом, мы делаем это за "одну" операцию. Результатом будет вектор с тем же количеством элементов, что и входные векторы. Чем больше элементов мы можем хранить, тем быстрее будет работать код. Это зависит от вашей архитектуры. В вашем процессоре есть SSE: «Streaming SIMD Extensions» - набор инструкций, позволяющих выполнять SIMD-операции. Размер векторов зависит от версии SSE, которую поддерживает ЦП: SSE2 – 2 элемента, SSE4.1 – 4 и так далее.

С появлением C# 10 и «обобщённой математики», мы можем использовать операции SIMD для любого числового типа, не создавая функцию для каждого типа в отдельности.

Идея состоит в том, что мы разбиваем нашу проблему на более мелкие подзадачи, которые будут решаться за одну операцию. Например, функция Min: разбиваем весь массив на мелкие фрагменты и ищем в каждом наименьшее значение.
public static T Min<T>(this Span<T> span)
where T : unmanaged, IMinMaxValue<T>, INumber<T>

Для простоты мы используем Span<T>. Нам нужна непрерывная память, так как блоки памяти передаются в процессор SIMD, который не может обрабатывать произвольные адреса памяти.
- INumber<T> — означает, что тип является числом.
- IMinMaxValue<T> — тип имеет минимальное и максимальное значение.
- unmanaged - тип является типом значения и не содержит ссылочных типов внутри себя. Таким мы можем использовать stackalloc, и запрещать сценарии, в которых структура со ссылочным типом внутри даёт неожиданные результаты.

Сначала создаём вектор с максимальным значением типа и приводим Span непосредственно к вектору:
var spanAsVectors = 
MemoryMarshal.Cast<T, Vector<T>>(span);
Span<T> vector =
stackalloc T[Vector<T>.Count];
vector.Fill(T.MaxValue);
var min = new Vector<T>(vector);

Далее сравниваем каждую запись вектора с каждым другим вектором, чтобы получить минимум:
foreach (var v in spanAsVectors)
min = Vector.Min(v, min);

В итоге получим вектор с n элементами, один из которых является минимальным. НО! MemoryMarshal.Cast<T, Vector<T>>(span) имеет большой недостаток: если у нас Vector<T>.Count = 4, а всего элементов 9, функция вернёт только 2 вектора. Поэтому мы должны выделить и сравнить «остаток»:
var remain = span.Length % Vector<T>.Count;
if (remain > 0)
{
Span<T> last =
stackalloc T[Vector<T>.Count];
last.Fill(T.MaxValue);
span[^remain..].CopyTo(last);
min = Vector.Min(min, new Vector<T>(last));
}

Теперь получим минимальное значение из вектора:
var minVal = T.MaxValue;
for (var i = 0; i < Vector<T>.Count; i++)
minVal = T.Min(minVal, min[i]);

return minVal;

Результаты бенчмарка для 100000 случайных чисел float впечатляют:
Method     Mean    Ratio
Linq 67.41us 1.00
For 55.58us 0.82
LinqSIMD 10.78us 0.16

С появлением обобщённой математики мы теперь можем выполнять SIMD-операции для пользовательских типов и для более широкого диапазона типов без использования дополнительного кода. Это огромный шаг вперёд для экосистемы .NET.
Код этого примера, а также других Linq функций можно найти в библиотеке LinqSIMDExtensions, которая также доступна в виде пакета nuget.

Источник: https://steven-giesel.com/blogPost/faf06188-bae9-484d-804d-a42d58d18cad
👍16
День 1536.
Сегодня порекомендую вам вебинар от JetBrains «Объектно-Ориентированное и Функциональное Программирование на C# и F#» https://youtu.be/vOcTPUiBQgc.

Урс Энцлер, архитектор ПО в Calitime AG с более чем 20-летним опытом в C#, рассказывает о сходствах и различиях между функциональным и объектно-ориентированным программированием на примерах C# и F#.

Современные языки программирования в значительной степени поддерживают оба подхода. В чем разница между ними, какие понятия используются, как мыслить в терминах ООП и ФП и где один более уместен, чем другой? Можно ли объединить эти две парадигмы программирования? Где в проектах обычных бизнес-приложений можно применять ООП, а где функциональное программирование? Какие функции каждого подхода поддерживаются в C# и F#?

PS: после доклада в секции Q&A Урс отвечает, как переписать систему с использованием F#, как перейти на использование F#, изучить синтаксис и т.п.
👍8
День 1537. #ЧтоНовенького
Новые Функции C#12. Начало
В недавно выпущенном превью 3 .NET 8 добавили несколько интересных новых функций C#.

1. Первичные конструкторы для классов и структур
Первичные конструкторы были введены для записей в C#9. C#12 распространяет их на все классы и структуры:
public class Student
(int id, string name, IEnumerable<decimal> grades)
{
public Student(int id, string name)
: this(id, name, Enumerable.Empty<decimal>()) { }

public int Id => id;
public string Name { get; set; }
= name.Trim();
public decimal GPA =>
grades.Any() ? grades.Average() : 4.0m;
}

Параметры первичного конструктора в классе Student доступны во всём теле класса. Один из способов их использования — инициализация свойств. В отличие от записей, свойства не создаются автоматически для параметров первичного конструктора в классах и структурах. Это отражает тот факт, что классы и структуры часто более сложны, чем записи, и объединяют как данные, так и поведение. В результате им часто требуются параметры конструктора, которые не следует раскрывать. Явное создание свойств делает очевидным, какие данные предоставляются в соответствии с обычным использованием классов. Первичные конструкторы помогают избежать шаблонного объявления закрытых полей и наличия тривиальных тел конструкторов, назначающих значения параметров этим полям.

Когда параметры первичного конструктора используются в методах или средствах доступа к свойствам (параметр grades в классе Student выше), их необходимо захватить, чтобы они оставались доступными после завершения выполнения конструктора. Это похоже на то, как параметры и локальные переменные захватываются в лямбда-выражениях. Для параметров первичного конструктора захват реализуется путём создания приватного резервного поля в классе или структуре. Поле имеет «непроизносимое» имя, что означает, что оно не будет конфликтовать с другими именами и не будет очевидно при использовании рефлексии. Подумайте, как назначать и использовать параметры первичного конструктора, чтобы избежать двойного хранения данных. Например, name используется для инициализации автоматического свойства Name, которое имеет собственное резервное поле. Если бы другой член напрямую ссылался на параметр name, оно также сохранялось бы в собственном резервном поле, что приводило к ненужному дублированию.

Класс с первичным конструктором может иметь дополнительные конструкторы. Дополнительные конструкторы должны использовать инициализатор this(…) для вызова другого конструктора того же класса или структуры. Это гарантирует, что первичный конструктор всегда вызывается и все данные, необходимые для создания класса, присутствуют. Структуры всегда имеют конструктор без параметров. Неявный конструктор без параметров не будет использовать инициализатор this() для вызова первичного конструктора. Поэтому для структур вы должны написать явный конструктор без параметров, если хотите, чтобы вызывался первичный конструктор.

Вы можете оставить отзыв о первичных конструкторах на GitHub в обсуждении Preview Feedback: C# 12 Primary constructors.

Чтобы попробовать новые функции, загрузите последнюю превью версию Visual Studio 17.6 или превью 3 .NET 8.

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

Источник:
https://devblogs.microsoft.com/dotnet/check-out-csharp-12-preview/
👍11
День 1538. #ЧтоНовенького
Новые Функции C#12. Окончание
В недавно выпущенном превью 3 .NET 8 добавили несколько интересных новых функций C#.
Начало. Первичные конструкторы

2. Директивы using для дополнительных типов
Добавлен ещё один вариант использования ключевого слова using. Теперь с помощью него можно объявить дополнительный тип:
using Measurement = (string, int);
using PathOfPoints = int[];
using DatabaseInt = int?;

Вы можете использовать псевдоним практически для любого типа. Можно создавать псевдонимы для обнуляемых типов-значений, однако нельзя использовать псевдонимы для обнуляемых ссылочных типов. Кортежи особенно интересны, потому что вы можете включать имена и типы элементов:
using Measurement = (string Units, int Distance);

Псевдонимы можно использовать так же, как любые типы:
public void F(Measurement x)
{ }

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

Вы можете оставить отзыв о первичных конструкторах на GitHub в обсуждении Preview Feedback: C# 12 Alias any type.

3. Значения по умолчанию для лямбда-выражений
Синтаксис такой же, как и для других параметров по умолчанию:
var addWithDefault = 
(int addTo = 2) => addTo + 1;
addWithDefault(); // 3
addWithDefault(5); // 6

Значение по умолчанию будет передано в метаданные и доступно через рефлексию как DefaultValue свойства ParameterInfo лямбда-метода:
addWithDefault.iss.onethod
.GetParameters()[0].DefaultValue; // 2

До C#12 нужно было использовать локальную функцию или громоздкое DefaultParameterValue из пространства имен System.Runtime.InteropServices, чтобы указать значение по умолчанию для параметров лямбда-выражения. Эти подходы по-прежнему работают, но их сложнее читать, и они несовместимы со значениями по умолчанию для методов. Теперь будет согласованный поиск значений параметров по умолчанию для методов, конструкторов и лямбда-выражений.

Вы можете оставить отзыв о первичных конструкторах на GitHub в обсуждении Preview Feedback: C# 12 Default values in lambda expressions.

Чтобы попробовать эти новинки, загрузите последнюю превью версию Visual Studio 17.6 или превью 3 .NET 8.

Источник: https://devblogs.microsoft.com/dotnet/check-out-csharp-12-preview/
👍16
День 1539. #ЗаметкиНаПолях
Чистые SQL-запросы в EF Core
В EF7 появилась поддержка возврата скалярных типов с помощью SQL-запросов. В EF8 появилась поддержка запросов несопоставленных (unmapped) типов с помощью чистого SQL. Это то, что Dapper предлагает по умолчанию, и приятно видеть, что EF Core догоняет его.

EF Core и SQL
В EF8 чистые SQL-запросы могут возвращать любой тип без необходимости включать его в модель EF. Вы можете запрашивать несопоставленные типы с помощью методов SqlQuery и SqlQueryRaw. Метод SqlQuery использует интерполяцию строк для параметризации запроса, защищая от атак SQL-инъекцией.

Вот пример запроса, возвращающего список OrderSummary:
var start = new DateOnly(2023, 1, 1);
var orders = await dbContext
.Database
.SqlQuery<Order>(
@$"SELECT * FROM Orders
AS o WHERE o.Created >= {start}")
.ToListAsync();

В БД будет отправлен следующий запрос:
SELECT * FROM Orders AS o WHERE o.Created >= @p0

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

SQL + LINQ
Интересной особенностью SqlQuery является то, что он возвращает IQueryable, который можно дополнить с помощью LINQ. Можно добавить оператор Where после вызова SqlQuery:
var orders = await dbContext
.Database
.SqlQuery<Order>(
"SELECT * FROM Orders AS o")
.Where(o => o.Created >= start)
.ToListAsync();
Однако, в результате получится неоптимальный запрос:
SELECT s.Id, s.CustomerId, s.Price, s.Created
FROM (
SELECT * FROM Orders AS o
) AS s
WHERE s.Created >= @p0

Также возможно добавить OrderBy, Skip и Take:
var orders = await dbContext
.Database
.SqlQuery<Order>(
@$"SELECT * FROM Orders AS o
WHERE o.Created >= {start}")
.OrderBy(o => o.Id)
.Skip(10)
.Take(5)
.ToListAsync();

Получим следующий запрос:
SELECT s.Id, s.CustomerId, s.Price, s.Created
FROM (
SELECT * FROM Orders AS o WHERE o.Created >= @p0
) AS s
ORDER BY s.Id
OFFSET @p1 ROWS FETCH NEXT @p2 ROWS ONLY

Производительность аналогична LINQ-запросам с проекцией с помощью Select.

SQL-запросы для модификации данных
Если вы хотите изменить данные в базе данных с помощью SQL, вы обычно пишете запрос, который не возвращает результата. Запрос может быть UPDATE, DELETE или вызовом хранимой процедуры. Для этого можно использовать метод ExecuteSql:
dbContext.Database.ExecuteSql(
@$"UPDATE Orders SET Status = 5
WHERE Created >= {start}");

ExecuteSql также защищает от SQL-инъекций путем параметризации аргументов, как и SqlQuery. В EF7 можно написать приведённый выше запрос с помощью LINQ и метода ExecuteUpdate. Также есть метод ExecuteDelete для удаления записей.

Источник: https://www.milanjovanovic.tech/blog/ef-core-raw-sql-queries
👍15
День 1540. #ЧтоНовенького
GitHub Представил Правила Репозитория
Правила для репозиториев — это следующая ступень эволюции защиты веток GitHub, которая поможет сделать репозитории более безопасными и совместимыми.

Правила позволяют легко определять средства защиты для веток и тегов в ваших репозиториях и, если вы являетесь клиентом GitHub Enterprise Cloud, применять их в своей организации. Кроме того, всем, кто работает с вашими репозиториями, проще узнать, какие правила действуют.

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

Страница набора правил — это центральное место для просмотра и управления всеми правилами репозитория. Она показывает действующие правила и позволяет добавлять новые наборы правил или редактировать существующие.

При создании набора правил вы определяете его статус: активный (active) или отключенный (disabled). Для слияния коммита, все активные наборы правил должны проходить, в то время как отключенные наборы правил не применяются. Отключенные наборы не будут препятствовать слияниям, но позволят администраторам создавать правила перед их применением. Клиентам Enterprise Cloud также доступен статус «оценка» (evaluate) для наборов правил: режим «пробного запуска» для понимания влияния новых правил до того, как они будут активны и применены.

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

Вы всегда можете узнать, какие правила действуют для репозитория. Любой, у кого есть доступ на чтение к репозиторию, может просматривать его правила и их значение. К обзору наборов правил можно перейти со страницы веток, щёлкнув на значок щита, а также из пулл-реквеста и из выходных данных Git CLI, когда правила блокируют отправку.

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

Кроме того, авторы ждут ваших отзывов в обсуждении.

Источник: https://github.blog/changelog/2023-04-17-introducing-repository-rules-public-beta/
👍5
День 1541. #МоиИнструменты
Обфускаторы в .NET
Распространенным подходом к защите интеллектуальной собственности является обфускация) символов и сокрытие кода IL. Веб-разработчики должны уделить особое внимание обфускации, поскольку код отправляется в браузер клиента.

На самом деле обфускаторов для .NET десятки и помимо перечисленных ниже. Многие из этих проектов так или иначе заброшены. Создание обфускатора для .NET — популярная и интересная задача, которую упростили библиотеки, такие как проект Mono.Cecil. Однако создать функциональный обфускатор, который должным образом запутывает код, не добавляя ошибок, сложно. Работающие обфускаторы .NET являются скорее исключением, чем нормой.

1. Preemptive Dotfuscator
Microsoft продвигала Dotfuscator как обфускатор для .NET, но, скорее всего, они никогда не собирались его предоставлять как утилиту. Разработчики, переходящие с C++ и VB6 на .NET, не осознавали, что их код может быть раскрыт, и это считалось недостатком новой платформы.
Несмотря на то, что Preemptive Dotfuscator является функциональным продуктом, недавно они на 50% увеличили плату за подписку, что вряд ли обосновано.

2. Eazfuscator.NET
Eazfuscator.NET имеет хорошую репутацию, доступные цены и множество поклонников в Интернете. Однако инструмент не предоставляет файлы сопоставления. Сопоставление файлов сборок, сгенерированных Dotfuscator, позволяет декодировать трассировки производственного стека, что необходимо для отслеживания проблем в производственном коде и их устранения. Eazfuscator.NET шифрует обфусцированные символы с помощью закрытого ключа. Таким образом, трассировки производственного стека могут быть декодированы и их возможно расшифровать, как показано в этой статье.

3. Obfuscar
Обфускатор с открытым исходным кодом. К сожалению, не всегда может генерировать код без ошибок из-за известных недостатков, таких как TypeLoadExceptions и невозможность обфусцировать все значения перечислений.

4. .NET Reactor
Понятный пользовательский интерфейс .NET Reactor, полный всплывающих подсказок и ссылок на обширную документацию, - то, что нужно для сложных инструментов, таких как обфускаторы. Полезно иметь описания функций, встроенные в UI, чтобы пользователям не приходилось снова и снова просматривать документацию или обращаться за поддержкой. Хотя поддержка у .NET Reactor быстрая и эффективная.

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

Источник: https://blog.ndepend.com/in-the-jungle-of-net-obfuscator-tools/
👍14
День 1542. #Книги
«Высоконагруженные приложения. Программирование, масштабирование, поддержка» (Клеппман М. — СПб.: Питер, 2022).

Осилил «кабанчика»! Многие называют эту книгу одной из обязательных к прочтению для разработчика ПО.

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

Затем, видимо, сказалось отсутствие опыта работы с распределёнными системами, потому что, когда разговор пошёл про репликации, секционирование, распределённые транзакции и консенсус, приходилось просто продираться сквозь главы. Я уже давно понял, что информация, которую я не могу соотнести со своим опытом, у меня усваивается очень тяжело. И если, читая первые главы, я постоянно думал: «Вот это мы используем, а вот это можно применить там-то», то дальше пошёл вакуум чисто теоретической информации, для которой не было контекста, да и особенных знаний предмета.

Третья часть книги рассказывает о пакетной и потоковой обработке. Тут было что-то среднее, потому что с MapReduce, Hadoop, RabbitMQ и Kafka я не работал, но хотя бы что-то о них слышал.

Итого
Книга действительно очень крутая, даёт теоретическую базу для множества аспектов разработки больших масштабируемых приложений, а также сотни ссылок на источники, в которых можно узнать детали. Однако совсем уж «мастридом» я бы её не назвал. Она, наверное, даже не для сеньоров, а для архитекторов ПО. Читать её кому-то уровнем ниже просто «для общего развития» я бы не советовал. Всё-таки, она скорее обо всём понемногу, поэтому вряд ли поможет, если вы хотите изучить какую-то конкретную область в конкретном стеке технологий.
Но это мой личный опыт. Кто читал, оставляйте мнения в комментариях.
👍30
День 1543. #Курсы
Сегодня порекомендую вам ютуб канал Зонара Хорвата (Zoran Horvat) Зоран - консультант, разработчик и архитектор ПО, автор на Pluralsight, Udemy и YouTube. На его канале вы найдёте советы по разработке и архитектуре, паттернах проектирования, чистом коде, новинкам языка C# и т.п.

Видео, которое попалось мне, вышло совсем недавно и называется Are Design Patterns Dead in C#? (Паттерны Проектирования в C# Умерли?) В нём Зоран на примере оригинальной книги «Паттерны Проектирования» банды четырёх рассуждает, полезна ли до сих пор информация о паттернах проектирования и применимы ли они в современной разработке в .NET.

Не буду спойлерить, смотрите до конца)))

Кстати, про паттерны проектирования вы можете почитать на канале по тегу #DesignPatterns.
👍17
День 1544. #ЧтоНовенького
Microsoft Представляет Нативный AOT для
ASP.NET Core
В новой версии .NET 8 Preview 3 Microsoft представила первоначальную поддержку нативной компиляции Ahead-of-Time (AOT) в компоненте веб-разработки ASP.NET Core. Хотя выбор варианта публикации AOT обеспечивает множество преимуществ в определенных сценариях, он также приводит к проблемам совместимости, поэтому команда разработчиков добавляет функциональные возможности постепенно.

В руководстве по развёртыванию Microsoft Native AOT объясняется, что поддержка AOT позволяет разработчикам создавать автономные приложения, скомпилированные с помощью AOT в машинный код, которые могут работать на компьютерах, где не установлена среда выполнения .NET, что приводит к преимуществам, в том числе сокращению времени запуска до 80 процентов и уменьшению размера приложения до 87 процентов.

Microsoft представила список преимуществ AOT:
1. Уменьшение занимаемого места на диске. AOT создаёт один исполняемый файл, содержащий программу вместе с подмножеством кода из внешних зависимостей, которые использует программа. Уменьшение размера исполняемого файла может привести к:
- Меньшему размеру образов контейнеров в сценариях контейнерного развертывания.
- Сокращению времени развертывания из-за меньшего размера образов.
2. Сокращение времени запуска. Отчасти из-за удаления JIT-компиляции. Это означает, что:
- Приложение будет быстрее готово обслуживать запросы.
- Улучшится развёртывание с помощью оркестраторов, которые управляют переходами от одной версии приложения к другой.
3. Снижение потребности в памяти. Нативные AOT-приложения могут иметь меньшую потребность в памяти в зависимости от работы, выполняемой приложением. Уменьшение потребления памяти может привести к большей плотности развертывания и улучшению масштабируемости.

Однако, поскольку не все функции ASP.NET Core или часто используемые библиотеки ASP.NET Core совместимы с нативным AOT (см. диаграмму), первоначальная работа сосредоточена на включении поддержки приложений, использующих минимальные API или gRPC и развёрнутых в облаке.

Таким образом, Preview 3 включает новый параметр Enable native AOT publish (Включить нативную публикацию AOT) в шаблоне проекта «ASP.NET Core gRPC Service», а также новый шаблон проекта «ASP.NET Core API», который также включает этот параметр для проектов, ориентированных на API в облаке.

Microsoft перечислила некоторые ключевые требования совместимости для нативных AOT-приложений:
- Отсутствие динамической загрузки (например, Assembly.LoadFile)
- Отсутствие кодогенерации через JIT (System.Reflection.Emit)
- Отсутствие C++/CLI
- Отсутствие встроенного COM (для Windows)
- Обязательный тримминг, который имеет ограничения
- Компиляция в один файл (с известными проблемами совместимости)
- Приложения должны включать необходимые библиотеки среды выполнения, что приведёт к увеличению размера исполняемого файла по сравнению с приложениями, зависящими от наличия среды выполнения.

«Нативное развёртывание AOT подходит не для каждого приложения, но в сценариях, где преимущества, предлагаемые AOT, существенны, оно может оказать огромное влияние», — говорится в сообщении Microsoft, — «В будущих предварительных версиях мы поработаем над тем, чтобы включить больше функций ASP.NET Core и поддерживать в нативном AOT такие технологии, как аутентификация JWT, валидация параметров, доступ к данным ADO.NET для SQLite и PostgreSQL и OpenTelemetry. Мы также работаем над улучшением возможностей Visual Studio для настройки и работы над проектами ASP.NET Core, предназначенными для нативного AOT».

Источник: https://visualstudiomagazine.com/articles/2023/04/17/aot-aspnet-core.aspx?m=1
👍14
День 1545. #Microservices
12 Способов Улучшить Монолит Перед Переходом на Микросервисы. Начало
Вы наконец решили, что пришло время избавиться от старого, неуклюжего монолита. Над ним долго работали, но он стал настолько большим, что больше усилий тратится на его обслуживание, чем на добавление функций. Пришло время попробовать другой подход, например, микросервисы.

Совет: не списывайте со счетов монолит. При некоторой подготовке он может сослужить вам хорошую службу на протяжении всего перехода. Вот 12 советов, как сделать переход на микросервисы максимально плавным.

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

2. Составьте план
Старая система должна оставаться работоспособной во время перехода. Шаги миграции можно отслеживать с помощью тикетов. Это не только помогает придерживаться плана, но и даёт владельцам бизнеса прозрачность относительно вашего прогресса. При планировании необходимо:
- Распутать зависимости внутри монолита.
- Определить необходимые микросервисы.
- Разработать модели данных для микросервисов.
- Разработать метод переноса и синхронизации данных между базой данных монолита и базами данных микросервисов.
- Разработать API и спланировать обратную совместимость.
- Измерить базовую производительность монолита.
- Установить цели для доступности и производительности новой системы.

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

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

5. Убедитесь, что у вас достаточно тестов
Рефакторинг гораздо более эффективен и приносит больше удовлетворения, когда мы уверены, что в коде нет регрессий. Автоматизированные тесты дают уверенность в непрерывном выпуске обновлений. Отличным местом для начала является пирамида тестирования. Она может помочь разработать тесты для микросервисов. Старайтесь запускать тесты на локальном компьютере разработки так же часто, как и в конвейере непрерывной интеграции.

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

Источник:
https://semaphoreci.com/blog/monolith-microservices
👍9
День 1546. #Microservices
12 Способов Улучшить Монолит Перед Переходом на Микросервисы. Продолжение
Начало

6. Установите API-шлюз или обратный HTTP-прокси.
По мере развёртывания микросервисов необходимо разделять входящий трафик. Мигрированные функции предоставляются новыми сервисами, а старая функциональность обслуживается монолитом. Существует несколько способов маршрутизации запросов в зависимости от их характера:
- API-шлюз https://t.iss.one/NetDeveloperDiary/1106 позволяет перенаправлять вызовы API на основе таких условий, как аутентифицированность пользователя, файлы cookie, флаги функций или шаблоны URI.
- Обратный HTTP-прокси делает то же самое, но для HTTP-запросов.
В большинстве случаев монолит реализует пользовательский интерфейс, поэтому большая часть трафика будет идти туда, по крайней мере, поначалу.
Используйте API-шлюзы и обратные прокси для маршрутизации запросов к соответствующей конечной точке. Вы можете переключаться между монолитом и микросервисами на очень мелком уровне. После завершения миграции шлюзы и прокси-серверы останутся: они являются стандартным компонентом любого микросервисного приложения, поскольку обеспечивают переадресацию и балансировку нагрузки. Они также могут функционировать как автоматические выключатели, если сервис выходит из строя.

7. Рассмотрите паттерн «монолит в коробке» (monolith-in-the-box)
Это применимо только в том случае, если вы планируете использовать контейнеры или Kubernetes для микросервисов. В этом случае контейнеризация может помочь вам гомогенизировать вашу инфраструктуру. Паттерн «монолит в коробке» заключается в запуске монолита внутри контейнера.
Если вы никогда раньше не работали с контейнерами, это хорошая возможность познакомиться с этой технологией. Нужно многому научиться, поэтому спланируйте обучение:
1) Изучите Docker и контейнеры.
2) Запустите свой монолит в контейнере.
3) Разрабатывайте и запускайте микросервисы в контейнере.
4) После завершения миграции и освоения контейнеров изучите Kubernetes.
5) По ходу работы можно масштабировать микросервисы и постепенно переводить на них трафик.

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

9. Используйте флаги функций
Флаги функций — это программный метод изменения функциональности системы без её повторного развёртывания. Вы можете использовать флаги функций, чтобы включать и выключать части монолита по мере их миграции, экспериментировать с альтернативными конфигурациями или проводить A/B-тестирование. Типичный рабочий процесс для миграции с флагом функции:
1) Определите часть функциональности монолита для переноса на микросервис.
2) Оберните функциональность флагом функции. Повторно разверните монолит.
3) Создайте и разверните микросервис.
4) Протестируйте микросервис.
5) Когда всё будет готово, отключите функцию на монолите, выключив флаг.
6) Повторяйте, пока миграция не будет завершена.
Поскольку флаги функций позволяют развёртывать неактивный код в рабочей среде и включать/выключать его в любое время, мы можем отделить выпуски функций от фактического развёртывания. Это даёт разработчикам огромную степень гибкости и контроля.

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

Источник:
https://semaphoreci.com/blog/monolith-microservices
👍9