.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
День 1041. #ЧтоНовенького
Новый редактор Razor в Visual Studio 2022
С выпуском Visual Studio 2022 версии 17.0.2 вы можете использовать новый редактор Razor.

Преимущества перехода на Language Server Protocol
Новый редактор Razor для проектов ASP.NET Core основан на протоколе языкового сервера (LSP). Это протокол с открытым исходным кодом, который определяет стандартный способ включения функций редактором или IDE. Модель LSP позволила добавить в Razor гораздо больше функций редактирования C# и другие функции для повышения продуктивности, специфичные для Razor.

Что доступно в новом редакторе Razor?
1. В редакторе Razor теперь поддерживается наиболее часто используемый рефакторинг Add missing usings (Добавить недостающие директивы using).

2. Также добавлено несколько функций, специфичных для Razor. Например, Extract block to code behind (Извлечь блок в файл кода) позволяет вам извлечь блок кода в отдельный файл кода, если вы не хотите держать его в одном файле с разметкой. Другие добавленные функции включают:
- Add usings for component (Добавить директивы using для компонента),
- Fully qualify component (Полностью определить компонент),
- Create component (Создать компонент).

2. Улучшена навигация. Одной из наиболее часто используемых функций навигации в Visual Studio является Go to Definition (Перейти к определению). Она помогает быстро перемещаться по файлам и лучше понимать код. Например, нажатие F12 на теге компонента теперь переместит вас прямо в код компонента.

3. Опыт горячей перезагрузки также улучшен, благодаря LSP.

4. В новом редакторе Razor обновлены цвета по умолчанию. Основным отличием является то, что код больше не подсвечивается серым фоном, как это было в предыдущих версиях.

5. Новый редактор обеспечивает улучшенное форматирование, которое лучше справляется с изменениями, помогая коду оставаться визуально согласованным. Поддерживаются более умные дополнения синтаксиса Razor, такие как завершение <text> и автозаполнение. Новый редактор также изменяет способ диагностики, чтобы гарантировать отображение только наиболее важных диагностических сообщений.

6. Razor теперь полностью поддерживает Visual Studio Live Share.

Известные проблемы и дорожная карта
Razor накопил большое количество запросов на добавление функций и исправлений ошибок. Решение этих проблем в устаревшем редакторе Razor было трудным и дорогостоящим. Новый редактор позволит быстрее предоставлять исправления ошибок и новые функции. Есть ещё несколько функциональных пробелов, которые необходимо устранить в следующих выпусках:
- Поддержка сниппетов (с помощью Tab)
- Горячая клавиша «Обернуть в div» - Shift+Alt+W
- Ctrl+щелчок мыши для перехода к определению
- Сворачивание кода в #region
- Встроенное форматирование JavaScript
- Поддержка перетаскивания файлов HTML, CSS и JavaScript
- Улучшения производительности и надёжности
- Поддержка горячей перезагрузки для проектов Blazor Web Assembly при отладке

Следить за дорожной картой вы можете на GitHub.

Если вы обнаружите, что ваша продуктивность в новом редакторе ограничена, вы можете вернуться к предыдущей версии редактора, перейдя в Tools > Options > Text Editor > HTML > Advanced (Инструменты > Параметры > Текстовый редактор > HTML > Дополнительно) и выбрав True в раскрывающемся списке рядом с пунктом Use legacy Razor editor for ASP.NET Core (Использовать устаревший редактор Razor для ASP.NET Core). Имейте в виду, что старый редактор Razor будет иметь ограниченную функциональность и не будет включать улучшения, описанные выше.

Источник: https://devblogs.microsoft.com/visualstudio/introducing-the-new-razor-editor-in-visual-studio-2022/
👍1
День 1042. #Карьера
Чему Можно Научиться из Книг «Программист-прагматик» и «Идеальный программист». Часть 2
Часть 1

3. Командная Работа – Работа Мечты
Работая в команде, вы должны быть «командным игроком», часто общаться, следить за своими товарищами по команде и максимально эффективно выполнять свои обязанности.

Команды должны быть небольшими, не более 10-12 человек, где все знают и доверяют друг другу. Такую командную среду сложно создать, поэтому, как только вы её получите, вам придётся заботиться о ней, изменяя проекты, над которыми работает команда, а не её участников.

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

Формировать команды под каждый проект неверно в принципе: группы просто не успеют «притереться». Люди участвуют в проекте только короткое время и поэтому никогда не узнают, как взаимодействовать друг с другом. Команды строить сложнее, чем проекты. Слаженная команда может вести сразу несколько проектов и распределять работу в соответствии со своими предпочтениями, квалификацией и способностями участников.
- Идеальный программист

Более того, отличные команды будут решать проблемы вместе, и каждый из них приложит максимум усилий.

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

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

4. Разработка методом трассирующих пуль
Трассирующие пули отмечают пройденный путь, чтобы стрелок мог лучше прицелиться в следующий раз. Таким образом, основная цель разработки методом трассирующих пуль - «добавить» основные функции в проект и получить быструю обратную связь, чтобы лучше «нацелиться» на следующие изменения.

Разработка методом трассирующих пуль согласуется идеей, что проект никогда не кончается: всегда будет потребность в изменениях и добавлении новых функций. Это — инкрементный подход.
- Программист-прагматик

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

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

Этот подход не следует путать с прототипированием. Код прототипов не должен быть частью проекта, а код «трассирующих пуль» не выбрасывается. Он работает и улучшается с каждой итерацией.

При прототипировании генерируется временный код. Код «трассирующей пули» скуден, но полноценен и составляет часть скелета окончательной системы. Думайте о прототипировании как о сборе разведданных, который происходит до того, как будет выпущена первая «трассирующая пуля».
- Программист-прагматик

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

Источник:
https://www.freecodecamp.org/news/lessons-learned-from-the-pragmatic-programmer-and-the-clean-coder/
👍1
День 1043. #ЗаметкиНаПолях #AsyncTips
Использование LINQ с асинхронными потоками
Создание асинхронных потоков
Потребление асинхронных потоков

Задача: обработать асинхронный поток с использованием чётко определенных и хорошо протестированных операторов. Либо использовать LINQ, когда предикат является асинхронным, например, необходимо провести поиск каждого элемента в базе данных или API, чтобы узнать, должен ли он быть включен в итоговую последовательность.

Решение
Допустим, у нас есть метод, производящий асинхронную последовательность:
async IAsyncEnumerable<int> GetAsyncRange()
{
for (int i = 0; i < 10; i++)
{
await Task.Delay(100);
yield return i;
}
}

IAsyncEnumerable<T> включает поддержку LINQ в NuGet-пакете System.Linq.Async. Заметьте, что при этом в коде нужно использовать
using static System.Linq.AsyncEnumerable;

Операторы LINQ можно применять к асинхронным потокам. Доступны все знакомые операторы: Where, Select, SelectMany, Join и т.д. Результат представляет собой асинхронный поток:
IAsyncEnumerable<int> values =
GetAsyncRange().Where(value => value % 2 == 0);

await foreach (int result in values) {
Console.WriteLine(result);
}

Но что, если нам нужно передать в Where асинхронный предикат? Where их не поддерживает. Но есть подходящий оператор WhereAwait:
IAsyncEnumerable<int> values = 
GetAsyncRange().WhereAwait(
async value => {
// Асинхронная работа для определения,
// должен ли элемент быть включён в результат
await Task.Delay(10);
return value % 2 == 0;
});

Методы LINQ для асинхронных потоков можно использовать и для обычных перечисляемых объектов, вызвав ToAsyncEnumerable() для любого IEnumerable<T>. Результат можно использовать с WhereAwait, SelectAwait и другими операторами, принимающими асинхронные делегаты.

Операторы LINQ для асинхронных потоков могут оканчиваться суффиксами Async и Await. Операторы, заканчивающиеся суффиксом Async, возвращают обычное значение, допускающее ожидание. Операторы с суффиксом Await получают асинхронный делегат. Т.е. Await в имени подразумевает, что они используют await внутри переданного делегата.

Пример WhereAwait был приведёт выше.

Суффикс Async применяется только к операторам терминации (termination operators), которые извлекают некоторое значение или выполняют некоторые вычисления и возвращают асинхронное скалярное значение. Пример такого оператора — CountAsync, версия Count для асинхронного потока, которая может подсчитать количество элементов, соответствующих некоторому предикату:
int count = await GetAsyncRange()
.CountAsync(value => value % 2 == 0);

Предикат может также быть асинхронным. В этом случае используется метод CountAwaitAsync, поскольку он получает асинхронного делегата и производит одно терминальное значение:
int count = await GetAsyncRange().CountAwaitAsync(
async value => {
await Task.Delay(10);
return value % 2 == 0;
});

Итого
- Операторы без суффиксов (Where, Select) получают синхронные делегаты и выдают асинхронную последовательность.
- Операторы, которые получают асинхронные делегаты, имеют суффикс Await (WhereAwait, SelectAwait), и выдают асинхронную последовательность.
- Операторы, возвращающие терминальное значение, имеют суффикс Async (CountAsync), а также могут иметь суффикс Await, если получают асинхронный делегат (CountAwaitAsync).

Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 3.
День 1044. #ЗаметкиНаПолях #ExploringNET6
Исследуем .NET 6. Часть 1
В этой серии статей рассмотрим подробно некоторые из новых функций, которые появились в .NET 6.

Заглянем в ConfigurationManager
ConfigurationManager был добавлен для поддержки новой модели WebApplication в ASP.NET. Однако он во многом является деталью реализации.

В .NET5 двумя основными типами конфигурации:
- IConfigurationBuilder - для добавления источников конфигурации. Вызов Build() считывает каждый из источников конфигурации и строит окончательную конфигурацию.
- IConfigurationRoot - представляет собой окончательную «построенную» конфигурацию.

Поставщики конфигурации обычно включают методы расширения (например, AddJsonFile() и AddAzureKeyVault()), которые добавляют источник конфигурации в список источников. IConfigurationRoot в свою очередь объединяет все значения из каждого источника конфигурации, чтобы дать окончательное представление всех значений.

Проблема "частичной сборки конфигурации" в .NET 5
Основная проблема с этим подходом проявляется, когда вам нужно построить конфигурацию «частично». Это распространённая проблема, когда вы храните свою конфигурацию в таком сервисе, как Azure Key Vault, или в базе данных. Рекомендуемый подход состоит в следующем:
- Добавить «начальные» значения конфигурации.
- Создать «частичный» результат конфигурации, вызвав IConfigurationBuilder.Build()
- Получить необходимые значения конфигурации из построенного IConfigurationRoot
- Использовать эти значения, чтобы добавить оставшиеся источники конфигурации
- Фреймворк неявно вызывает IConfigurationBuilder.Build(), генерируя окончательный IConfigurationRoot и используя его для окончательной конфигурации приложения.

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

Менеджер Конфигурации в .NET 6
В .NET 6 добавлен новый тип конфигурации, ConfigurationManager. Он реализует как IConfigurationBuilder, так и IConfigurationRoot, позволяя оптимизировать сценарий, описанный выше.
В ConfigurationManager, когда добавляется IConfigurationSource (например, когда вы вызываете AddJsonFile()), поставщик сразу загружается, и конфигурация обновляется. Это позволяет избежать загрузки источников конфигурации более одного раза в сценарии частичной сборки.

Однако ConfigurationManager оптимизирован для наиболее распространённого сценария – только добавление источников. Если какой-либо из источников изменится, ConfigurationManager должен удалить всё и начать заново, перебирая каждый из источников и перезагружая их.

Стоит ли вам беспокоиться о том, используете ли вы ConfigurationManager или ConfigurationBuilder? Скорее нет.

Новый WebApplicationBuilder, представленный в .NET 6, использует ConfigurationManager, оптимизированный для описанного выше случая, когда вам необходимо частично построить конфигурацию.

Однако WebHostBuilder или HostBuilder, представленные в более ранних версиях ASP.NET, по-прежнему поддерживаются в .NET 6, и они по-прежнему «за кулисами» используют типы ConfigurationBuilder и ConfigurationRoot.

Подробнее перевод статьи с примерами кода размещён на Хабре.

Источник: https://andrewlock.net/exploring-dotnet-6-part-1-looking-inside-configurationmanager-in-dotnet-6/
👍1
День 1045. #ЧтоНовенького
Сервис Azure Load Testing
Недавно Microsoft анонсировали превью сервиса Azure Load Testing. Он позволяет пользователям имитировать полноценную нагрузку на приложение с помощью сценариев Apache JMeter и получать полезные сведения, позволяющие выявлять и устранять узкие места производительности.

Ранее компания предлагала возможности нагрузочного тестирования в Visual Studio 2019 через функции веб-производительности и нагрузочного тестирования. Кроме того, также предлагался соответствующий облачный сервис нагрузочного тестирования в Azure DevOps. Ни то, ни другое больше не поддерживается, и теперь преемник Azure Load Testing с поддержкой Apache JMeter с открытым исходным кодом доступен в превью.

Azure Load Testing позволяет пользователям создавать крупномасштабные нагрузки без необходимости управления сложной инфраструктурой. Он интегрируется с Azure Monitor, включая Application insights и Container insights, для сбора метрик из сервисов Azure (см. картинку ниже). Кроме того, пользователи могут включать нагрузочное тестирование в свои рабочие процессы непрерывной интеграции и доставки (CI/CD) и потенциально находить проблемы с производительностью до того, как они появятся в производственной среде.

В Azure Marketplace пользователи могут найти сервис Azure Load Testing, который можно использовать для интеграции в конвейер CI/CD в значимых точках жизненного цикла разработки. Эти конвейеры могут быть либо GitHub Actions, либо Azure Pipelines. Впоследствии в настройках тестов можно указать правила прохождения и отказа, чтобы отловить снижение производительности. И, наконец, при запуске конвейера сервис может автоматически прерывать запуск нагрузочных тестов в случае определённых условий (ошибок), что помогает защититься от выполнения ненужных нагрузочных тестов и дополнительных расходов.

Наряду с нагрузочным тестированием в Marketplace пользователи также могут создать ресурс Azure Load Testing на портале Azure в качестве централизованного места для просмотра планов и результатов тестирования и других связанных артефактов, а также для управления ими. После подготовки ресурса Azure Load Testing можно настроить роли идентификации и доступа для тестов, загрузить пользовательские сценарии JMeter и создать нагрузочные тесты.

Подробности и руководство доступны на этой странице.

Источник: https://www.infoq.com/news/2021/12/azure-load-testing-preview/
День 1046. #Оффтоп
Доброй субботы, дорогие подписчики. Сегодня порекомендую вам полуразвлекательное видео для просмотра холодным зимним вечером (или днём). Олимпийские игры по сортировке. Участвуют 7 наиболее популярных алгоритмов сортировки в трёх дисциплинах:
- спринт (сортировка массива целых чисел от 2х до 11 элементов),
- средняя дистанция (от 60 до 250 элементов),
- марафон (от 100 тыс. до 200 тыс. элементов).

Участники:
- Сортировка выбором (Selection),
- Быстрая сортировка (Quick),
- Сортировка вставками (Insertion),
- Пузырьковая сортировка (Bubble),
- Поразрядная сортировка (Radix),
- Сортировка Шелла (Shell),
- Стандартная сортировка в C++ (STD) – функция sort().

Все алгоритмы обозначены разноцветными кружками, и проходят «трассу», где время, затраченное на достижение каждого следующего поворота, соответствует времени сортировки массива с определённым количеством элементов. Например, в спринте: от старта до 1го поворота – сортировка массива из 2х элементов, от 1го до 2го – из 3х элементов, и т.д., от предпоследнего до финиша – 11 элементов. В марафоне: от старта до 1го – сортировка 100тыс. элементов, от 1го до 2го – 110 тыс., от предпоследнего до финиша – 200 тыс.

Довольно увлекательное «соревнование». Интриги придаёт то, что автор не раскрывает, какая сортировка каким цветом обозначена, и предлагает вам догадаться.

Смотрим и «болеем»: https://youtu.be/FNAUuYmkMPE

Пишите в комментариях, сколько алгоритмов вы угадали.

Если покажется мало, вот серия из 3х видео, с объяснениями принципов работы алгоритмов:
- Часть 1
- Часть 2
- Часть 3 (пример на C++, и замеры времени такие себе, но, думаю, основной посыл будет понятен).
День 1047. #Карьера
Чему Можно Научиться из Книг «Программист-прагматик» и «Идеальный программист». Часть 3
Часть 1
Часть 2

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

Во-первых, проясним, что означает оценка определением оценки из книги «Идеальный программист»:

Оценка — это не число. Оценка — это распределение вероятностей успешного завершения.
— Идеальный программист

То есть, например, вероятность завершить задачу во 2й день – 10%, во 3й – 50%, в 4й – 20%, в 5й – 10%, в 6й – 5% и т.д, и даже в 10й – 1% (закона Мерфи ещё никто не отменял).

Один из основных способов делать точные оценки — это хорошо знать, что вы оцениваете.

Первой частью любого упражнения в составлении оценки является понимание сути заданного вопроса. <…> вам необходимо осознать масштаб предметной области.
— Программист-прагматик

Не оценивайте в одиночку, общайтесь с другими людьми, чтобы быть как можно более точными.

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

Главная хитрость оценки, которая всегда даёт хорошие результаты: спросите того, кто уже делал это.
— Программист-прагматик

Когда вас попросят дать оценку, выберите единицы, которые лучше отражают точность, которую вы собираетесь передать. Эта шкала времени оценки из книги «Программист-прагматик» может вам помочь:
1–15 дней   - Дни
3–6 недель - Недели
8–20 недель - Месяцы
20+ недель - Хорошо подумайте, перед тем, как оценивать

Хотя бизнесу нравится рассматривать оценки как обязательства, помните, что оценка — это всего лишь предположение, поэтому никаких обязательств не подразумевается.

Обязательство — нечто такое, что вы обязаны сделать. Если вы обязуетесь сделать что-то к определённой дате, то к этой дате «что-то» должно
быть готово. <…> Профессионалы не принимают на себя обязательств, если только они не уверены в возможности их выполнения. <…> Нарушение обязательств обернется огромным ущербом для вашей репутации; это проявление непорядочности, лишь немногим лучшее открытой лжи.
— Идеальный программист

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

Чтобы свести к минимуму проблемы, связанные с отставанием, помните о двух важнейших аспектах: раннем обнаружении и прозрачности. Будьте по возможности честны в своих оценках. Оптимизму в них не место!
— Идеальный программист

Не изобретайте велосипед, используйте известные методики оценивания задач. Вот некоторые техники оценки, упомянутые в этих книгах:
- PERT
- Широкополосный дельфийский метод
- Метод быстрого голосования
- Покер планирования
- Аффинная оценка
- Анализ по трем переменным
- Закон больших чисел

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

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

Источник:
https://www.freecodecamp.org/news/lessons-learned-from-the-pragmatic-programmer-and-the-clean-coder/
День 1048. #ЗаметкиНаПолях #ExploringNET6
Исследуем .NET 6. Часть 2
В этой серии статей рассмотрим подробно некоторые из новых функций, которые появились в .NET 6.
Часть 1

WebApplicationBuilder
В .NET появился новый способ «по умолчанию» для создания приложений, используя WebApplication.CreateBuilder(). Во всех предыдущих версиях ASP.NET Core конфигурация разделена на 2 файла: Program.cs и Startup.cs (см. рисунок ниже). В .NET 6 добавлено множество изменений в C#, BCL и ASP.NET Core, и теперь всё может быть в одном файле.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();

var app = builder.Build();
app.UseStaticFiles();
app.MapGet("/", () => "Hello World!");
app.MapRazorPages();
app.Run();

WebApplicationBuilder
Для начала рассмотрим WebApplicationBuilder.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();

Он отвечает за 4 основные вещи:
1. Добавление конфигурации с помощью builder.Configuration. Он предоставляет тип ConfigurationManager для добавления новых источников конфигурации, а также для доступа к значениям конфигурации, как я описал в предыдущем посте.

2. Добавление сервисов с помощью builder.Services. Предоставляет доступ к IServiceCollection напрямую для добавления сервисов в контейнер DI.

3. Аналогично для журнала с помощью builder.Logging. Вы можете использовать, Например:
builder.Logging.AddFile();

4. Общая конфигурация IHostBuilder и IWebHostBuilder. Для тех точек расширения, которые напрямую зависят от IHostBuilder или IWebHostBuilder, WebApplicationBuilder предоставляет свойства Host и WebHost соответственно. Например, настройка Serilog для ASP.NET Core подключается к IHostBuilder. С помощью WebApplicationBuilder вы можете вызвать UseSerilog() на свойстве Host:
builder.Host.UseSerilog();

Фактически, WebApplicationBuilder – это то место, где вы выполняете всю настройку, кроме конвейера промежуточного ПО.

WebApplication
После того, как вы настроили всё необходимое в WebApplicationBuilder, вы вызываете Build() для создания экземпляра WebApplication:
var app = builder.Build();

WebApplication реализует несколько различных интерфейсов:
- IHost – для запуска и остановки хоста.
- IApplicationBuilder – для создания конвейера промежуточного ПО.
- IEndpointRouteBuilder – для добавления конечных точек.

Два последних пункта во многом связаны. В ASP.NET Core 3.x и 5 IEndpointRouteBuilder используется для добавления конечных точек путем вызова UseEndpoints() и передачи ему лямбды, например:
public void Configure(IApplicationBuilder app)
{
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}

WebApplication значительно упрощает этот шаблон:
app.UseStaticFiles();
app.MapRazorPages();

Это явно намного проще, хотя немного обманчиво, поскольку различие между промежуточным ПО и конечными точками гораздо менее очевидно, чем в .NET 5.x. Вероятно, это просто дело вкуса, но такой подход несколько размывает концепцию важности порядка настройки (которая относится к промежуточному ПО, но не к конечным точкам).

Подробнее перевод статьи с примерами кода размещён на Хабре.

Источник: https://andrewlock.net/exploring-dotnet-6-part-2-comparing-webapplicationbuilder-to-the-generic-host/
День 1049. #ВопросыНаСобеседовании
Сегодня поделюсь с вами шикарным, на мой взгляд, видео из двух частей с конференции DotNext, которая прошла в конце октября. Однако, это не обычный доклад, как мы все привыкли, а более неформальное общение или, как назвали авторы, реалити-шоу, «Собеседование».

Александр Кугушев из EPAM и Артём Акуляков из OCS.Lab играют в реальное собеседование. Артём задаёт вопросы, Александр отвечает, затем они обсуждают, почему такие вопросы задаются, какие ответы получаются, и что ответ может сказать о кандидате.

Тут всё, что мы любим:
- Какая у вас была самая сложная/интересная задача?
- SOLID
- Сборка мусора
- Параллельный и асинхронный код
- Ссылочные и значимые типы
- Коллекции
- Сложность алгоритмов
- Код ревью

Часть 1
Часть 2
День 1050. #ЗаметкиНаПолях #AsyncTips
Асинхронные потоки и отмена
Создание асинхронных потоков
Потребление асинхронных потоков
Использование LINQ с асинхронными потоками

Задача: требуется механизм отмены асинхронных потоков.

Решение
Не всем асинхронным потокам необходима отмена. Перечисление может быть просто остановлено при достижении условия. Если это единственная разновидность «отмены», реально необходимая в программе, то полноценная отмена не нужна, как показывает следующий пример (см. код метода GetAsyncRange здесь):
await foreach (int result in GetAsyncRange())
{
Console.WriteLine(result);
if (result >= 8)
break;
}

Часто бывает полезно отменять сами асинхронные потоки, передав маркер отмены потоку-источнику. Async метод, возвращающий IAsyncEnumerable<T>, может получать маркер отмены, который должен быть помечен атрибутом EnumeratorCancellation. После этого маркер можно использовать естественным образом:
async IAsyncEnumerable<int> GetAsyncRange(
[EnumeratorCancellation] CancellationToken ct = default)
{
for (int i = 0; i < 10; i++)
{
await Task.Delay(100, ct);
yield return i;
}
}

using var cts = new CancellationTokenSource(500);
CancellationToken token = cts.Token;
await foreach (int result in GetAsyncRange(token)) {
Console.WriteLine(result);
}

В этом примере CancellationToken передается непосредственно методу, возвращающему асинхронный перечислитель. Это самый распространенный вариант использования.

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

async Task ConsumeSequence(IAsyncEnumerable<int> items)
{
using var cts = new CancellationTokenSource(500);
CancellationToken ct = cts.Token;
await foreach (int item
in items.WithCancellation(ct))
{
Console.WriteLine(item);
}
}

await ConsumeSequence(GetAsyncRange());

Примечания:
1. Заметьте, что GetAsyncRange() вызывается без токена отмены. При наличии атрибута EnumeratorCancellation компилятор автоматически обеспечит передачу маркера из WithCancellation параметру метода GetAsyncRange, помеченному атрибутом EnumeratorCancellation.
2. В нынешнем виде отменённое перечисление выбрасывает TaskCanceledException, которое нужно обработать в клиентском коде.
3. Метод расширения WithCancellation не препятствует ConfigureAwait(false). Оба метода расширения могут быть объединены в цепочку:
items.WithCancellation(ct).ConfigureAwait(false))

Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 3.
День 1051. #ЧтоНовенького
Быстрое Обновление Проектов с Помощью .NET Upgrade Assistant
Инструмент Upgrade Assistant предлагает пошаговые инструкции для обновления проектов и решений до .NET 6.

Установка
Здесь и далее предполагаем, что на вашем компьютере уже установлен пакет SDK для .NET 6 и среда выполнения. Выполните команду:
dotnet tool install -g upgrade-assistant

Анализ
Если вы выполните команду
upgrade-assistant analyze
вам будут предоставлены инструкции по тому, как будет выглядеть обновление.

Инструкции включают в себя:
- Какую целевую платформу (TFM) следует использовать для проекта?
- Нужно ли обновлять какие-либо зависимости проекта?
- Необходимо ли внести существенные изменения в код для обновления?
- И многое другое!

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

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

Например, первым шагом является резервное копирование всех проектов. Если ваши проекты в Git, можно пропустить этот шаг. Также есть возможность предоставить более подробную информацию о каждом шаге. Если вы не уверены, будет ли этот этап дорогостоящим или вызовет нарушение работы кода, помощник по обновлению сообщит вам об этом.

FAQ
1. Он работает с решениями или только с отдельными проектами?
В решении помощник попросит указать точку входа для приложения. После этого он изучит все зависимости, их зависимости и наметит лучший способ выполнить обновление. Возможно, придётся повторить этот процесс для дополнительных точек входа для решения (приложение MVC, приложение функций Azure, API и т.п.).

2. Какие языки поддерживаются?
C# и Visual Basic полностью поддерживаются!

3. С чем ещё может помочь инструмент?
Upgrade Assistant может помочь со следующими типами проектов:
- ASP.NET MVC
- Windows Forms
- Windows Presentation Foundation (WPF)
- Консольные приложения
- Библиотеки классов

4. Что насчёт других типов проектов?
Вы, вероятно, заметили, что веб-формы ASP.NET отсутствуют в приведённом выше списке. Они входят в дорожную карту проекта вместе со многими другими функциями!

Источник: https://consultwithgriff.com/rapid-project-upgrades-with-dotnet-upgrade-assistant/
День 1052. #ЗаметкиНаПолях #ExploringNET6
Исследуем .NET 6. Часть 3
В этой серии статей рассмотрим подробно некоторые из новых функций, которые появились в .NET 6.
Часть 1
Часть 2

Рассматриваем код WebApplicationBuilder
Напомню стандартный шаблон нового минимального API приложения ASP.NET Core:
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);

// добавляем конфигурацию
builder.Configuration.AddJsonFile("sharedsettings.json");

// добавляем сервисы
builder.Services.AddSingleton<MyTestService>();
builder.Services.AddRazorPages();

// добавляем ведение журнала
builder.Logging.AddFile();

// строим!
WebApplication app = builder.Build();

app.UseStaticFiles();

// добавляем конечные точки
app.MapGet("/", () => "Hello World!");
app.MapRazorPages();

// запускаем!
app.Run();

Первым шагом является создание экземпляра WebApplicationBuilder с использованием статического метода класса WebApplication:
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);

Ниже приведены приватные и публичные члены класса WebApplicationBuilder:
public sealed class WebApplicationBuilder
{
private readonly HostBuilder _hostBuilder = new();
private readonly BootstrapHostBuilder _bootstrapHostBuilder;
private readonly WebApplicationServiceCollection _services = new();

public IWebHostEnvironment Environment { get; }
public IServiceCollection Services { get; }
public ConfigurationManager Configuration { get; }
public ILoggingBuilder Logging { get; }

public ConfigureWebHostBuilder WebHost { get; }
public ConfigureHostBuilder Host { get; }

public WebApplication Build()
}

Публичный API состоит из набора свойств только для чтения, и метода Build(), который создаёт WebApplication.

Многие из этих свойств используют стандартные типы из предыдущих версий:
- IWebHostEnvironment – используется для получения имени среды, пути к корню контента и подобных значений.
- IServiceCollection – используется для регистрации сервисов в контейнере DI. Обратите внимание, что это альтернатива методу ConfigureServices(), используемому универсальным хостом для достижения того же результата.
- ConfigurationManager – используется как для добавления новой конфигурации, так и для получения значений конфигурации. См. первый пост в серии, где обсуждается этот вопрос.
- ILoggingBuilder – используется для регистрации дополнительных поставщиков журналов, как и в случае с методом ConfigureLogging() в универсальном хосте.
- Свойства WebHost и Host интересны тем, что они предоставлены новыми типами ConfigureWebHostBuilder и ConfigureHostBuilder. Эти типы реализуют IWebHostBuilder и IHostBuilder соответственно и в основном представлены как замена для используемых ранее методов расширения.

Приватные члены класса содержат:
- вспомогательный класс BootstrapHostBuilder, который «запоминает» переданные ему делегаты конфигурации для последующего их вызова в правильном порядке при построении хоста. Кроме того, он вызывает знакомые нам по .NET 3.x/5 методы расширения CreateDefaultBuilder и ConfigureWebHostDefaults.
- HostBuilder – экземпляр универсального хоста, который является «внутренним» хостом в WebApplicationBuilder. WebApplicationBuilder действует как «адаптер» для универсального хоста _hostBuilder, предоставляя императивный API и сохраняя при этом ту же функциональность, что и универсальный хост.
См. рисунок ниже.

В методе Build() вся конфигурация, сделанная по умолчанию, а также добавленная пользователем в файле Program.cs, передаётся в _hostBuilder в правильном порядке, и возвращается новый экземпляр WebApplication, в конструктор которого передаётся построенный «внутренний» хост:
_builtApplication = new WebApplication(_hostBuilder.Build());

return _builtApplication;

Подробнее перевод статьи с примерами кода размещён на Хабре.

Источник:
https://andrewlock.net/exploring-dotnet-6-part-3-exploring-the-code-behind-webapplicationbuilder/
День 1053. #юмор
День 1054. #Карьера
Чему Можно Научиться из Книг «Программист-прагматик» и «Идеальный программист». Часть 4
Часть 1
Часть 2
Часть 3

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

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

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

Чтобы двигаться быстро и не нарушать сроков, в коде необходимо сохранять чистоту. Профессионал не поддаётся искушению устроить грязь в коде, чтобы быстро двигаться вперед. Грязно — всегда значит медленно!
— Идеальный программист

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

Если вы следуете методологии разработки через тестирование в обычное время, но отказываетесь от неё во время кризиса, значит вы не верите в полезность TDD. Если ваш код остаётся чистым в обычное время, а в кризис вы разводите в нем грязь, значит вы не верите, что грязь замедляет вашу работу. Если вы используете парное программирование во время кризиса, но не в обычной ситуации, значит вы полагаете, что парное программирование эффективнее индивидуального.
— Идеальный программист

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

Избегайте сюрпризов. Ничто не делает людей более злыми и менее рациональными, чем сюрпризы. Сюрпризы умножают давление на десять.
— Идеальный программист

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

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

Источник:
https://www.freecodecamp.org/news/lessons-learned-from-the-pragmatic-programmer-and-the-clean-coder/
День 1055. #ЗаметкиНаПолях
Следует ли Абстрагироваться от Базы Данных?
Мнение, что, имея слой абстракции, можно легко переключиться с одной БД на другую широко распространено среди многих программистов. Но даже при том, что оно довольно популярно, оно неверно. Это явление называется ложным мифом об абстрагировании от базы данных.

Давайте проанализируем его и посмотрим, что именно тут не так.

Привязка к поставщику
Основное преимущество абстрагирования вашей БД — это избежание привязки к поставщику. Другими словами, если по какой-либо причине вы захотите отказаться от текущей СУБД, вы легко сможете это сделать. Чтобы сделать возможным такой переход, вы должны спроектировать свой уровень доступа к данным так, чтобы он поддерживал несколько реализаций базы данных. Для этого вы вводите интерфейс, вроде IDataAccess, а затем предлагаете реализацию для вашей текущей СУБД.

Видимое и невидимое
Поначалу это звучит разумно, но, принимая решение, вы должны учитывать обе стороны:
- Желаемые результаты, которые являются видимой частью уравнения.
- Непредвиденные последствия, невидимая часть.

В контексте абстрагирования от базы данных:
- Видимая часть — это преимущества, которые даёт вам абстракция.
- Невидимая часть — это (часто скрытая) стоимость этой абстракции.

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

Но это дополнительное время огромно. Как говорится, «недели программирования могут сэкономить вам часы планирования». Именно это получается, когда кто-то хвастается, что сэкономил 2 дня при переходе на другую базу данных. Вероятно, им потребовалось несколько недель дополнительного времени, чтобы сделать это возможным. И в будущем это будет стоить дороже! Внедрение абстракции — не просто одноразовое действие, вам придётся поддерживать её на протяжении всего проекта, даже если больше никогда не придётся переключаться снова.

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

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

А если вам всё же нужно переключиться, подходите к процессу переключения не просто как к отказу от одной реализации IDataAccess в пользу другой, а как к портированию: вы портируете своё приложение с одной СУБД на другую.

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

Источник: https://enterprisecraftsmanship.com/posts/should-you-abstract-database/