.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
День восемьсот двенадцатый. #ЧтоНовенького
Visual Studio 2022
Этим летом выйдет первая предварительная версия Visual Studio 2022. Её обещают сделать более быстрой, доступной, легкой и впервые в истории 64-разрядной. Пользовательский интерфейс будет более чистым, интеллектуальным и ориентированным на продуктивность.

64-битная VS 2022 больше не будет ограничена 4ГБ памяти для основного процесса devenv.exe. Теперь вы сможете открывать, редактировать, запускать и отлаживать даже самые большие и сложные решения, не исчерпывая памяти. Хотя Visual Studio переходит на 64-разрядную версию, это не меняет типа или разрядности приложений, которые вы создаёте с её помощью.

Разработка современных приложений
Azure
VS 2022 позволит быстро и легко создавать современные облачные приложения в Azure. Для начала работы вы сможете использовать большое количество репозиториев, описывающих общие шаблоны, используемые в современных приложениях. Эти репозитории состоят из проверенного кода, показывающего эти шаблоны в действии, ресурсов Azure, а также предварительно настроенных рабочих процессов и действий GitHub, подготавливающих для вас полноценное решение CI/CD сразу при создании проекта. Кроме того, в репозитории будет определена необходимая среда разработки, чтобы вы могли сразу приступить к кодированию и отладке.

.NET
Visual Studio 2022 будет иметь полную поддержку .NET 6 и его единой платформы разработки веб-, клиентских и мобильных приложений как для Windows, так и для Mac. Это включает в себя .NET MAUI для кроссплатформенных клиентских приложений в Windows, Android, macOS и iOS. Вы также можете использовать веб-технологии ASP.NET Blazor для написания настольных приложений через .NET MAUI. Кроме того, для большинства типов приложений вы сможете использовать .NET Hot Reload для применения изменений кода без необходимости перезапуска и без потери состояния приложения.

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

Сотрудничество в реальном времени
Live Share представит интегрированный текстовый чат, чтобы вы могли быстро обсуждать свой код без переключений контекста. У вас будет возможность запланировать повторяющиеся сеансы с повторным использованием одной и той же ссылки, что упростит совместную работу с вашими частыми контактами. Чтобы лучше поддерживать Live Share в организациях, также появятся политики сеансов, содержащие любые требования для совместной работы.
VS 2022 также будет включать новую мощную поддержку Git и GitHub. Появится много встроенной логики и контрольных точек, которые помогут вам эффективно пройти процесс слияния и проверки.

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

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

Источник: https://devblogs.microsoft.com/visualstudio/visual-studio-2022/
День восемьсот тринадцатый. #МоиИнструменты
Обработка Изображений в Вашем Репозитории GitHub
ImgBot - удобный бот, который вы можете добавить в свой репозиторий GitHub. Он бесплатный для проектов с открытым исходным кодом. Его задача - сжимать изображения, чтобы они были оптимизированы для отображения в интернете (то есть ваш сверхширокий снимок экрана размером 8МБ, который должен отобраться на странице блога с разрешением 600x200, не сожрёт много трафика).

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

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

Настройка
Добавьте ImgBot в свой GitHub репозиторий, используя GitHub Marketplace и настройте план (бесплатный для проектов с открытым исходным кодом). Как только вы предоставите ImgBot доступ к своему репозиторию, он просканирует его и отправит вам серию пул реквестов. По умолчанию он использует сжатие без потерь, поэтому не беспокойтесь, что он испортит ваши красивые изображения.

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

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

Источник: https://ardalis.com/add-imgbot-to-github-repository/
День восемьсот четырнадцатый. #ЗаметкиНаПолях #GC
Топ Вопросов о Памяти в .NET. Начало 1-4
Вчера в нашем чате поделились интересной ссылкой на тест по организации памяти в .NET. Кому интересно попробовать свои силы перед тем, как читать дальше - https://quiz.dotnetmemoryexpert.com/

1. Что чаще всего вызывает сборку мусора в приложении .NET?
Наиболее распространённой причиной является случай, когда вы выделяете объект, и (грубо говоря) для него не хватает места. Таким образом, если приложение не выделяет новых объектов, есть небольшая вероятность, что сборки мусора вообще произойдёт. Вот почему вы могли слышать о zero-allocation коде. Такой код имеет хорошую производительность не только потому, что он не использует аллокации, но также значительно снижает вероятность сборки мусора и связанных с этим накладных расходов. А знать о том, когда происходит выделение памяти и избегать ненужных выделений - один из наиболее важных навыков при написании требовательного к памяти и производительности кода.

Другой, менее распространенный триггер сборки мусора - когда операционная система замечает нехватку доступной памяти. Она передаёт так называемое «уведомление о нехватке памяти», и различные программы могут реагировать на него (или игнорировать его). Среда выполнения .NET реагирует запуском сборки мусора, а также переключением в «режим низкого потребления памяти», что приводит к более агрессивному освобождению памяти.

Очевидно, что вызов GC.Collect может (или не может, в зависимости от его параметров) запускать сборку мусора. Но такие вызовы довольно редки, как и другие, менее распространённые триггеры.

2. В .NET 5 и Blazor (WebAssembly) одинаковые алгоритмы сборки мусора?
Blazor WebAssembly, начиная с .NET 5, работает на Mono (изначально написанном на C), но компилируется в WebAssembly. Таким образом, поскольку среда выполнения совершенно другая, она имеет и другой сборщик мусора. Хотя в будущем всё может измениться, потому что Mono интенсивно развивается и активно экспериментирует (например, в использовании «основного сборщика мусора» .NET).

3. Что означает так называемая «полная» сборка мусора?
При полной сборке мусора сборщик обрабатывает все поколения в SOH, а также LOH и POH (добавленной в .NET 5). Поэтому такую сборку следует воспринимать как самую «дорогую» с точки зрения загрузки памяти и процессора. В хорошо работающем приложении это должно происходить заметно реже, чем сборка в поколениях 0 и 1.

В настоящее время существует 2 варианта полной сборки мусора: параллельная и уплотняющая. Может выполняться один из вариантов, но не оба вместе. Параллельная (или фоновая) является наиболее распространённой и предпочтительной, поскольку приводит к коротким паузам, что не сильно влияет на поведение приложения. Но память при этом не сжимается, что приводит к фрагментации: свободному пространству, которое не всегда можно использовать повторно. Если фрагментация станет сильной, может начаться уплотняющая полная сборка мусора, которая может привести к длительным паузам в работе приложение. В противном случае процесс будет потреблять всё больше и больше памяти.

4. Что такое «кризис среднего возраста»?
Под «кризисом среднего возраста» мы понимаем нарушение так называемых гипотез поколений, на которых построены все «поколенческие» сборщики мусора (в том числе и .NET). Они подразумевают, что большинство объектов умирают молодыми, и что существует небольшая группа объектов, живущих долго. «Если объект молодой, он, вероятно, скоро умрёт. Если он живет долго, он, вероятно, проживет ещё дольше».

Поэтому объект, живущий достаточно долго, чтобы считаться «старым», а затем умирающий, нарушает это правило. Это негативно влияет на поведение сборщика мусора, которое настроено на противоположное поведение: чаще собирать мусор в молодых поколениях и реже в старых. «Кризис среднего возраста» - одна из наиболее распространённых проблем с памятью .NET, которая вызывает более высокую загрузку процессора и паузы.

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

Источник:
https://dotnetmemoryexpert.com
День восемьсот пятнадцатый. #ЧтоНовенького
.NET 6: Улучшения в Асинхронности
Из более, чем сотни изменений, предложенных для выпуска в .NET 6 сегодня рассмотрим наиболее существенные, относящиеся к асинхронному программированию.

Новые методы WaitAsync
Хотя в идеале все асинхронные функции подразумевают возможность отмены операции, иногда эта возможность не предоставляется. Для этих случаев в классы Task и Task<TResult> были добавлены три новых метода WaitAsync:
public Task WaitAsync(CancellationToken cancellationToken);
public Task WaitAsync(TimeSpan timeout);
public Task WaitAsync(TimeSpan timeout, CancellationToken cancellationToken);

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

На заметку: Microsoft теперь считает ошибкой значения таймаута в виде целых миллисекунд. В дальнейшем все значения таймаута должны быть выражены исключительно как TimeSpan.

Многоразовый CancellationTokenSource
Когда запускается операция, инициируемая извне, например веб-запрос, часто требуется создать CancellationTokenSource. Это позволяет обработчику запросов прерываться, если запрашивающая сторона отменяет запрос, разрывается соединение и т. д. Однако в большинстве случаев запрос не отменяется, то есть CancellationTokenSource не используется.

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

Новый метод CancellationTokenSource.TryReset исправляет это, отключая все старые токены от CancellationTokenSource. Таким образом, любая отмена новой операции не сможет повлиять на предыдущие операции. Старые токены будут существовать, но не смогут получать сообщения от этого CancellationTokenSource.

Название TryReset использовано из-за того, что повторно использовать можно будет только неиспользованный объект CancellationTokenSource. То есть, если на этом объекте уже была вызвана отмена операции, придётся создать новый. Использование будет примерно таким:
if (!cts.TryReset())
cts = new CancellationTokenSource();

События отмены
Один из способов определить, что была запрошена отмена, - зарегистрировать делегат через CancellationToken.Register. Он будет выполнен при отмене, либо немедленно, если к моменту регистрации токен уже в состоянии отмены. Иногда этому делегату требуется доступ к используемому токену. Новая перегрузка CancellationToken.Register предложит эту возможность:
public CancellationTokenRegistration Register<T>(Action<T, CancellationToken> callback, T state);
public CancellationTokenRegistration UnsafeRegister<T>(Action<T, CancellationToken> callback, T state);
UnsafeRegister отличается тем, что не захватывает контекст исполнения.

Источник: https://www.infoq.com/news/2021/04/Net6-Async/
👍1
День восемьсот шестнадцатый.
FluentAssertions
Сегодня предлагаю вам посмотреть второе видео из серии Open-Source Power-Ups про популярные проекты с открытым исходным кодом в сообществе .NET.
Запись вебинара «OSS Power-Ups: FluentAssertions».

FluentAssertions - это обширный набор методов расширения, который позволяет более естественно описывать ожидаемый результат модульных тестов в стиле TDD или BDD. Деннис Думен, создатель этой библиотеки, поможет вам начать работать с FluentAssertions, а также расскажет о некоторых не самых известных нюансах использования.
День восемьсот семнадцатый. #ЗаметкиНаПолях
Тестирование Исключений с Помощью xUnit и Action
Когда вы пишете модульные тесты для метода, рекомендуется тестировать различные условия отказа («печальные пути») в дополнение к проверке того, что всё работает («счастливого пути»). В частности, если у вас есть метод, который может генерировать исключения, особенно если это пользовательские типы исключений, специфичные для вашего домена, вы должны быть уверены, что тестируете это поведение. Другой распространённый источник исключений - это защитные предложения, которые используются для поддержания чистоты вашего метода и обеспечения того, чтобы входные данные соответствовали ожиданиям метода.

В отличие от NUnit и MSTest, которые в основном используют атрибуты для ожидаемых исключений, xUnit предоставляет метод Assert.Throws<T>, который используется для проверки ожидаемых исключений (в NUnit3 также появился аналогичный метод):
Customer customer = null;
Assert.Throws<NullReferenceException>(
() => customer.LastName);

Кроме того, метод возвращает пойманное исключение, которое можно обработать:
var ex = Assert.Throws<NameRequiredException>(
() => customer.UpdateName("", ""));
Assert.Equal("Имя не задано", ex.Message);

Arrange, Act, Assert и Исключения
Многие тесты используют шаблон тестирования AAA (Arrange, Act, Assert – Настройка, Действие, Утверждение). Проблема с предыдущим примером в том, что перехват исключения метода относится как к блоку Act, так и к блоку Assert. Кроме того, эта строка получается слишком длинной.

В этом случае для строгого следования шаблону AAA делегат для Assert.Throws можно выделить в отдельную переменную типа Action:
[Fact]
public void ThrowsExceptionGivenInvalidName {
// Arrange
var customer = new Customer();
// Act
Action act = () => customer.UpdateName("", "");
// Assert
var ex = Assert.Throws<NameRequiredException>(act);
Assert.Equal("Имя не задано", ex.Message);
}
Теперь блок Действие явно содержит нужную операцию, а строка Assert.Throws гораздо короче и понятнее.

Заметьте также, что имя теста явно говорит о том, что тест выбрасывает исключение и при каких условиях.

FluentAssertions
Об этой библиотеке подробно было рассказано во вчерашнем видео. Если вы используете её, то код утверждения будет выглядеть примерно так:
[Fact]
public void ThrowsExceptionGivenInvalidName {
// …

// Assert
action.Should()
.Throw<NameRequiredException>()
.WithMessage("Имя не задано");
}

Источник: https://ardalis.com/testing-exceptions-with-xunit-and-actions/
День восемьсот восемнадцатый. #ЧтоНовенького
Эпик Фейл при Демонстрации Горячей Перезагрузки в Blazor
Во время прямой трансляции мероприятия ASP.NET Community Standup на тему «Обновления ASP.NET Core в .NET 6 Preview 3» Дэниел Рот, главный программный менеджер ASP.NET столкнулся с неожиданной проблемой при демонстрации одного из самых ожидаемых нововведений - Blazor Hot Reload.

Около четырех минут на глазах тысяч зрителей Рот пытался победить подготовленный пример. Рот и ведущий Джон Гэллоуэй изучали новые функции ASP.NET Core, обещанные в .NET 6, выпуск которого запланирован на ноябрь.

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

Однако внезапно возникла странная ошибка невозможности записи файла, которую Рот и Гэллоуэй какое-то время пытались победить при помощи комментариев от публики. Рот даже зашёл в диспетчер задач и убил один из процессов .NET, пообещав, что «нам не придётся этого делать».

Всё веселье начинается на 43й минуте ролика (ссылка выше).

Помимо горячей перезагрузки, которую обещают распространить на все виды приложений .NET, Джон и Дэниэл рассматривают и другие нововведения в .NET 6:
- MAUI
- улучшения в производительности .NET
- нативную облачную разработку
- изменения в MVC (теперь рабочий сайт можно создать буквально в 3 строчки кода)
- одностраничные приложения
- улучшения в производительности Blazor Webassembly
и многое другое.

Источник: https://visualstudiomagazine.com/articles/2021/04/23/epic-fail.aspx?m=1
День восемьсот девятнадцатый. #TipsAndTricks
Когда-то давно я писал про горячие клавиши в Visual Studio. Кроме того по тегу #TipsAndTricks можете поискать другие полезные советы. А сегодня расскажу вам о некоторых фишках Visual Studio Code. В конце концов, это самый популярный редактор кода.

Горячие клавиши
- для Mac
- для Windows
- для Linux

Если вы фанат лигатур посмотрите на бесплатные Fira Code и Cascadia Code.

Полезные расширения
1. Emmet
Это плагин для многих популярных текстовых редакторов, позволяющий генерировать стандартные блоки HTML и CSS.

2. Quokka.js
Предпросмотр значений переменных и функций JS и TypeScript во время набора кода.

3. Bracket Pair Colorizer
Подсветка соответствующих скобок разными цветами.

4. Live Server
Локальный сервер для предпросмотра создаваемых веб-страниц.

5. Settings Sync
Позволяет синхронизировать настройки, темы, иконки, горячие клавиши и т.п. на разных машинах с помощью GitHub Gist.

6. Prettier Extension
Тонкая настройка форматирования кода на разных языках.

7. Polacode
Позволяет быстро делать скриншоты кода и обрабатывать их.

8. Better Comments
Выделяет разные типы комментариев: TODO, важные замечания, документацию и т.п.

9. Markdown Lint
Проверка оформления и стилей документов MarkDown.

10. VS Code Icons
Содержит несколько коллекций иконок.

Красивые темы
1. Cobalt 2
2. Night Owl
3. One Dark Pro
4. Dracula Official
5. Winter is Coming
6. Shades of Purple
7. Material Theme
8. Rainglow
День восемьсот двадцатый. #ЗаметкиНаПолях #GC
Топ Вопросов о Памяти в .NET. Продолжение 5-8
Начало 1-4

5. Какие ограничения на размер занимаемой памяти у приложений .NET?
Ограничения размера приложения .NET такие же, как у любого процесса, ограниченного виртуальным адресным пространством - объемом памяти, который может быть выделен, исходя из разрядности приложения. И хотя в настоящее время подавляющее большинство операционных систем являются 64-битными, мы всё ещё можем компилировать/запускать наши программы и как 32-, и как 64-битные. То же самое относится к среде выполнения .NET, выполняющей наше приложение .NET. См. также про 64-битную VS 2022.

32-битному приложению может быть выделено до 4 ГБ памяти, но по умолчанию половина его предназначена для операционной системы Windows, а половина - для самого приложения. Таким образом, ограничение по умолчанию составляет 2 ГБ. Однако в случае 64-битной Windows мы можем запускать 32-битные приложения в так называемом режиме обработки больших адресов (Large Address Aware), который позволяет выделять больше памяти - около 3 ГБ. Этот флаг, например, используется при размещении 32-разрядных приложений ASP.NET Framework внутри IIS. В Linux действуют аналогичные ограничения. Таким образом, около 2 или 3 ГБ - это предел для 32-разрядного приложения .NET.

64-битному приложению теоретически можно выделить до 16 ЭБ (эксабайт!) памяти. В настоящее время большая часть оборудования использует только 48 бит для выделения верхних и нижних 128 ТБ всего адресного пространства (для операционной системы и приложения). Это предел для приложений .NET.

6. Что такое LOH (Large Object Heap)?
Куча больших объектов - это специальная часть управляемой кучи. С самого начала .NET порог по умолчанию для обработки объекта как «большого» составляет 85000 байт. Недавно добавилась возможность увеличить этот лимит. Каждый большой объект выделяется в LOH и остаётся там до тех пор, пока не будет собран мусор.

LOH отделён от SOH (Small Objects Heap – кучи малых объектов), потому что «большие» объекты имеют другие характеристики: их создание и перемещение (сжатие) памяти может повлечь за собой большие накладные расходы. Поскольку ожидается, что таких объектов будет немного, затраты на их размещение выше (включая очистку памяти и некоторые накладные расходы на многопоточную синхронизацию). Т.к. нет другого способа очистки LOH, кроме полной сборки мусора, если ваше приложение часто размещает большие объекты и приводит к нехватке памяти, оно может приводить к дорогостоящим полным сборкам мусора.

7. Для чего нужна утилита dotnet trace?
dotnet trace - это один из инструментов командной строки (CLI) для сбора различных «диагностических трассировок» процесса .NET. Вы можете использовать три предопределенных профиля:
- cpu-sampling - выборка профилировщика CPU для наблюдения за использованием процессора,
- gc-collect - отслеживание высокоуровневых данных сборщика мусора с очень низкими накладными расходами,
- gc-verbose – то же, что выше, плюс грубая выборка распределения объектов. Созданная трассировка может быть затем открыта в Visual Studio или в инструменте PerfView.

8. Для чего нужна утилита dotnet gcdump?
dotnet gcdump - еще один инструмент диагностики, который может запускать сборщик мусора и записывать специальные диагностические данные, выдаваемые во время него. Это позволяет создавать «gcdump» - не обычный дамп памяти, содержащий всю или часть памяти процесса, а «диагностический снимок» состояния управляемой памяти. Он включает информацию о том, какие управляемые объекты были обнаружены и собраны во время сборки мусора (без содержания этих объектов). Поэтому «gcdump» намного меньше, чем снимок всей памяти, потребляемой процессом. Его можно проанализировать в Visual Studio или PerfView (включая информацию об отношениях между объектами).

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

Источник:
https://dotnetmemoryexpert.com
День восемьсот двадцать первый. #ВопросыНаСобеседовании
4 Частых Ошибки на Собеседовании
Всех с предпраздничной пятницей, дорогие подписчики. На сегодня приготовил вам тему для обсуждения. Основан пост на недавно вышедшем видео Клемента Михайлеску, который какое-то время проработал интервьюером в Google. Его список ошибок основан на личном опыте. Понятно, что наш опыт может отличаться от тамошнего, поэтому добро пожаловать в комментарии. Продолжайте список того, чего не стоит делать на собеседовании.

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

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

2. Угадывание
Разновидность первой ошибки: если застрял - вываливать всё, что знаешь. То есть вместо объяснения, что конкретно вызывает затруднение, предлагать беспорядочный набор известных вам структур данных, алгоритмов, библиотек и т.п., которые могу иметь, но чаще всего не имеют никакого отношения к решению задачи.
Интервьюеру важнее понять, насколько вы можете мыслить логически. Его вряд ли впечатлит простой перебор всего, что вы знаете. Это скорее наведёт его на мысль, что вы вообще не понимаете, о чём говорите. Лучше выбрать хоть сколько-нибудь подходящий вариант решения и объяснить, почему вы его выбрали, даже если он в итоге окажется неверным.

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

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

Источник: https://youtu.be/nf6vrGcGDSI
День восемьсот двадцать второй. #Юмор

Помните эту шутку на первое апреля? Так вот, в Stack Overflow заморочились и решили реально посчитать, как часто люди копипастят код с их сайта. Получилось, что каждый четвертый посетитель сайта, копирует что-то в течение пяти минут после перехода на страницу.

Так что, перестаньте корить себя за копирование кода! Зачем изобретать велосипед, если всю тяжелую работу уже проделал кто-то другой? Этот сайт основан на повторном использовании знаний.

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

Источник: https://stackoverflow.blog/2021/04/19/how-often-do-people-actually-copy-and-paste-from-stack-overflow-now-we-know
День восемьсот двадцать третий.
Snoop

Сегодня предлагаю вам посмотреть третье видео из серии Open-Source Power-Ups про популярные проекты с открытым исходным кодом в сообществе .NET.

Запись вебинара «OSS Power-Ups: Snoop»

Snoop - это швейцарский армейский нож, когда дело касается анализа пользовательского интерфейса в WPF. В отличие от диагностики XAML внутри Visual Studio, его можно легко установить и использовать на любом компьютере - даже на сайте заказчика - без сложной установки. Бастиан Шмидт, нынешний сопровождающий проекта, даст нам хорошее представление о нём. В видео показано, как просматривать и изменять значения свойств, проверять триггеры из стилей и шаблонов, диагностировать ошибки привязки представлений и другие распространенные ошибки в WPF, устранять неполадки в событиях и выяснять, где они обрабатываются, предварительно просматривать и масштабировать части пользовательского интерфейса (даже в 3D) и многое другое.
День восемьсот двадцать четвёртый. #ЗаметкиНаПолях
Как Обратиться к HttpContext в
ASP.NET Core
Как правило, переход от веб-форм или из MVC5 в ASP.NET Core требует значительного рефакторинга. Например, HttpContext.Current был удалён в ASP.NET Core. Доступ к текущему контексту HTTP из отдельной библиотеки классов – это один из примеров беспорядочной архитектуры, которых ASP.NET Core пытается избежать. Есть несколько способов получить текущий контекст запроса в ASP.NET Core.

Что такое HttpContext?
Это объект, содержащий информацию о текущем Http-запросе: авторизация, аутентификация, объекты запроса и ответа, сессию, текущего пользователя, отправленные данные формы и т.п. Каждый Http-запрос создаёт новый объект HttpContext с актуальной информацией.

1. Доступ к HttpContext из контроллера?
Контроллеры предоставляют свойство ControllerBase.HttpContext, чтобы мы могли напрямую обращаться к контексту текущего Http-запроса:
[HttpGet("/getDetails")]
public string GetDetails() {
var result =
"Method: " + HttpContext.Request.iss.onethod +
" Path: " + HttpContext.Request.Path;
return result;
}
Вывод:
Method: GET Path: /getdetails

2. Доступ к HttpContext из промежуточного ПО
Если вы пишете собственный вариант промежуточного ПО, то контекст текущего запроса передаётся в метод Invoke/InvokeAsync:
public async Task InvokeAsync (HttpContext context) {

}

3. Доступ к HttpContext из сервиса
Если нужно получить доступ к HttpContext в сервисе, мы можем сделать это с помощью интерфейса IHttpContextAccessor и его реализации по умолчанию HttpContextAccessor. Эту зависимость необходимо добавлять только в том случае, если мы хотим получить доступ к HttpContext в сервисе.

Шаг 1. Зарегистрируйте зависимость и сервис:
public void ConfigureServices
(IServiceCollection services) {

services.AddHttpContextAccessor();
// до .NET Core 2.2 используйте
//services
// .TryAddSingleton<IHttpContextAccessor,
// HttpContextAccessor>();

services.AddTransient<IUserService, UserService>();

}

Шаг 2: внедрите IHttpContextAccessor в конструктор сервиса:
public class UserService : IUserService {
private IHttpContextAccessor
_httpContextAccessor;

public UserService(IHttpContextAccessor hca)
{
_httpContextAccessor = hca;
}

public string GetLoginUserName() {
return _httpContextAccessor
.HttpContext.User.Identity.Name;
}
}

Источники:
-
https://www.telerik.com/blogs/how-to-get-httpcontext-asp-net-core
-
https://stackoverflow.com/questions/38571032/how-to-get-httpcontext-current-in-asp-net-core
👍1
День восемьсот двадцать пятый. #DeveloperPath
Новости проекта «Путь Разработчика»
О проекте

Очередная серия новостей проекта.
1. Релиз наладили, даже кое-какое CI/CD прикрутили.
2. Проект выложен, и даже получил домен https://www.developer-path.com/
Пока там ничего особо нет, только краткое описание и форма входа. Постепенно будем пилить UI. Так что, если есть веб-дизайнеры, желающие присоединиться, нарисовать лого, айдентику, интерфейс, вот это всё, будем очень признательны.
3. API тоже доступно публично, пока тут https://developerpathapi.azurewebsites.net/index.html
Пожалуйста, не ломайте ничего :)

Как уже писал раньше, задачи найдутся для самых разных специалистов. Если кто-то хочет поковыряться в .NET 5, C#9, Blazor, паттерне CQRS или веб-дизайне, милости просим.

Проект всё также на Azure DevOps: https://dev.azure.com/sbenzenko/DeveloperPath/
Он открытый, поэтому посмотреть, почитать можно и без регистрации. Авторизованные через аккаунт Microsoft или GitHub могут оставлять комментарии или добавиться в команду. Если вы ещё не в команде, пишите в личку или в комментарии свой e-mail, я вас приглашу.

Задачи можно посмотреть в Azure DevOps.

Помимо этого, вы, конечно, можете просто взять код проекта на GitHub и предложить что-то своё.

По всем вопросам добро пожаловать в комментарии сюда, либо в проект на Azure DevOps.
День восемьсот двадцать шестой. #ЗаметкиНаПолях #GC
Топ Вопросов о Памяти в .NET. Продолжение 9-12
Начало 1-4
Продолжение 5-8

9. Что обязательно будет содержать дамп памяти любого приложения .NET?
Забавный факт, который иногда может вводить в заблуждение при анализе дампов памяти: каждый процесс .NET заведомо выделяет экземпляры OutOfMemoryException и StackOverflowException. Просто на случай, если они понадобятся, что будет означать действительную нехватку памяти и отсутствие возможности их создать!
Кроме того, некоторые массивы object[] предварительно выделяются в LOH для ссылок на объекты, используемые «дескрипторами». Это важный механизм, используемый интернированием строк, статикой и локальной статикой потока. Так, например, даже если вы вообще не используете LOH, вы увидите там несколько массивов, ссылающихся на ваши статические объекты.

10. Что означает выражение "stop the world" в контексте сборки мусора?
Каждый запуск сборки мусора в .NET имеет несколько коротких и длинных фаз, когда ожидается, что среда выполнения «приостановит» приложение. Эти паузы также известны как фазы «остановки мира» ("stop the world"). И в целом они явно нежелательны, так как влияют на скорость отклика и производительность приложения. Многие улучшения .NET GC делают эти паузы как можно короче.
Итак, «остановка мира» - это пауза на время выполнения сборки мусора (или её части), когда все управляемые потоки «приостановлены». Например, это позволяет получить единообразное представление о том, какие управляемые объекты используются. Неуправляемые потоки не приостанавливаются, поскольку в этом нет необходимости - по умолчанию они не обращаются к управляемым объектам, и даже если это так, они обращаются к «закреплённым» (pinned) объектам, которые обрабатываются особым образом.

11. Как работает параллельная сборка мусора в .NET 5?
Параллельная (фоновая) сборка мусора большую часть времени работает одновременно с управляемыми потоками, не создавая длительных пауз для «остановки мира». Это не означает, что пауз вообще не бывает. Требуется как минимум две паузы: в начале и где-то посередине, чтобы получить некоторое согласованное представление о состоянии памяти.
Более того, текущая реализация .NET GC не может сжимать память во время работы приложения. Таким образом, как полная сборка мусора, так и сборка в поколениях 0 и 1, должны работать в режиме «остановки мира», если требуется сжать память.
Работа над внедрением параллельного сжатия памяти определённо продолжается, и рано или поздно мы можем ожидать его добавления в экосистему .NET. Такие реализации успешно используются, например, в экосистеме JVM. Тем не менее, у них есть свои недостатки и компромиссы, поскольку ничего не даётся бесплатно.

12. Как параметры нужно учитывать, чтобы оценить потребление памяти вашей программой?
Чтобы иметь хорошее общее представление о потреблении памяти вашей .NET-программой, лучше всего знать как минимум три величины.
1. Сколько памяти выделено вашей программе в целом (частные байты - private bytes).
2. Сколько её физически потребляется в RAM («рабочий набор» - working set) - это позволит заметить случаи, когда страницы памяти выгружаются на диск.
3. В контексте .NET полезно знать, сколько памяти потребляется в управляемой куче (Managed Heap).

Что же касается виртуального адресного пространства (virtual address space), оно охватывает всё адресное пространство, которое может использоваться нашим приложением, и не связано напрямую с поведением приложения.

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

Источник:
https://dotnetmemoryexpert.com
День восемьсот двадцать седьмой. #ЧтоНовенького
.NET 6: Улучшения в LINQ. Начало 1/2
Продолжаем изучать, что нас ждёт в релизе .NET 6. На этот раз про LINQ.

Индексные операции в IEnumerable<T>
Первоначально IList<T> отличался от IEnumerable<T> наличием обращения по индексу. Идея заключалась в том, что только коллекции, поддерживающие быстрые операции с индексами ~O(1), могут реализовывать IList<T>. Теоретически индексные операции над IEnumerable<T> не поощрялись, поскольку считались медленными.

С появлением LINQ многие из этих предположений позабылись. Методы расширения, такие как Enumerable.Count() и Enumerable.ElementAt() доступны на любой коллекций, даже если в реальности они выполняются за O(N) время. Новые методы расширения для IEnumerable (ElementAt, ElementAtOrDefault и Take) продолжают этот тренд, позволяя использовать индексы и диапазоны:
var elements = source.Take(range: 10..^10);

Операции подсчёта в IEnumerable<T>
Когда на IEnumerable<T> вызывается Count(), происходят две вещи. Сначала библиотека LINQ пытается привести коллекцию к интерфейсу, который предоставляет свойство Count. Если это невозможно, метод выполняет итерацию по всей коллекции, считая элементы.

Для больших коллекций такой подсчет может быть очень дорогим, особенно для IQueryable при запросе к базе данных. Поэтому разработчики попросили «безопасную» функцию подсчета. Эта функция проверяет наличие быстрого свойства Count и, если не может его найти, ничего не возвращает:
public static bool TryGetNonEnumeratedCount(this IEnumerable<T> source, out int count);
Длинное имя TryGetNonEnumeratedCount как бы намекает, что вы делаете что-то не то. В идеале любой API, возвращающий список, должен возвращать либо коллекцию со строгим именем, либо интерфейс более высокого уровня, такой как IList<T> или IReadOnlyList<T>.

Трёхсторонний Zip
Метод расширения Zip объединяет две коллекции, перечисляя их одновременно. Например, если у вас есть список 1, 2, 3 и список A, B, C, то результирующая коллекция будет состоять из кортежей (1, A), (2, B), (3, C). Теперь предложено расширить метод для объединения трёх коллекций за раз.

Разбиение на партии
Часто требуется разбить коллекцию на несколько партий. Например, может оказаться, что вставка 100 строк в базу за раз быстрее, чем вставка по одной или всех сразу. Хотя этот код нетрудно написать самому, он, как правило, подвержен ошибкам. Легко ошибиться в последней партии, если количество строк не делится равномерно на размер партии. Для этого добавлен метод расширения Chunk для IEnumerable и IQueryable:
public static IEnumerable<T[]> Chunk(this IEnumerable<T> source, int size);
public static IQueryable<T[]> Chunk(this IQueryable<T> source, int size);

Проверки анализатора
Когда сам API не может предотвратить неправильное использование кода разработчиками, авторы библиотек все чаще обращаются к анализаторам. Некоторые из них встроены в компилятор C#, другие добавляются через библиотеки, такие как NetAnalyzers и Roslynator.

Первый из новых анализаторов касается метода расширения OfType<T>. Он фильтрует входную коллекцию, возвращая только элементы указанного типа T. Если входной тип не может быть приведен к выходному типу, текущее поведение - просто вернуть пустую коллекцию. Предложено в этом случае выдавать предупреждение компилятора, чтобы избежать излишнего перебора коллекции.

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

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

Источник:
https://www.infoq.com/news/2021/04/Net6-Linq/
День восемьсот двадцать восьмой. #ЧтоНовенького
.NET 6: Улучшения в LINQ. Окончание 2/2
Начало

Операторы *By
Это методы DistinctBy, ExceptBy, IntersectBy, UnionBy¸ MinBy и MaxBy. Первые 4 позволяют работать с коллекциями как со множествами. Для них предусмотрен делегат keySelector, возвращающий ключ для сравнения. Методы позволят выполнять операцию сравнения на подмножестве данных, а не на всей коллекции. Их можно использовать для повышения производительности или для обеспечения настраиваемого поведения без потери исходных данных. Например, имея коллекции всех заказов и завершённых заказов:
IEnumerable<Order> all = GetAll();
IEnumerable<Order> completed = GetCompleted();
Получить незавершённые заказы можно с помощью ExceptBy, сравнивая элементы по свойству ID:
IEnumerable<Order> remaining =
all.ExceptBy(completed, o => o.ID);
В отличие от варианта с использованием Where, который менее интуитивно понятен и выполняется за квадратичное время (O(M*N)).

В MinBy и MaxBy вместо селектора ключей предоставляется селектор элементов. Они вернут элемент коллекции с наибольшим/наименьшим значением соответственно, в отличие от существующих Min и Max, которые возвращают само значение. Кроме того, в каждый из методов (в том числе и Min и Max) можно будет передать необязательный объект-компаратор.
Сигнатуры всех методов похожи, приведу для примера DistinctBy и MinBy с компаратором:
public static IEnumerable<TSource> 
DistinctBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector);

public static TSource
MinBy<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TResult> selector,
IComparer<TResult>? comparer);

Улучшение в *OrDefault
Вариант оператора *OrDefault используется для предоставления значения по умолчанию, когда Single, First или Last передаётся пустая коллекция. В этой функции теперь можно будет переопределить возвращаемое значение по умолчанию:
public static TSource 
SingleOrDefault<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate,
TSource defaultValue);

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

Источник:
https://www.infoq.com/news/2021/04/Net6-Linq/
День восемьсот двадцать девятый. #Testing
Несколько хороши ваши тесты? Протестируйте их с помощью мутатора Stryker
Вы взялись за новый проект и решили всё сделать правильно. Возможно даже разрабатывать через TDD. И вот, всё готово, все тесты зелёные, покрытие тестами полное, вы гордитесь своей работой. Затем от клиента приходит запрос на новый функционал. Вы что-то добавляете, также решаете что-то отрефакторить, т.к. лучше поняли домен и требования клиента, добавляете новые тесты, все тесты (и старые, и новые) проходят, всё прекрасно.

И тут приходит сообщение от клиента… В смысле «не работает»???

Внезапно вы находите ошибку, и не в новом функционале, а в исходной версии кода. Но как же так? Все тесты проходили. Оказывается, вы не охватили тестами все случаи, несмотря на 100% покрытие. Затем вы изменили кое-что здесь и там, и в результате функциональность уже не работает должным образом. Как снизить вероятность повторения такой ситуации?

Что такое мутационное тестирование?
Мутационное тестирование - это введение ошибок (мутантов) в ваш производственный код. Например, равенство заменяется неравенством, AND на OR и т.п. Затем выполняются тесты для каждого мутанта, и тесты должны провалиться! Неудача означает, что мутант убит. Если тесты проходят, мутант выжил, а значит, есть ложноположительные результаты.

Stryker делает всё это автоматически. Он поддерживает различные мутаторы, например арифметические операторы, равенство, логические операторы, мутации строк и даже LINQ. Вы можете посмотреть полный список доступных мутаторов в документации.

Stryker устанавливается как dotnet tool глобально или для каждого проекта в отдельности.
dotnet tool install dotnet-stryker
Затем он запускается из папки юнит-тестов
dotnet stryker
и создаёт HTML отчёт с результатами мутационного тестирования (см. в верхней части рисунка ниже). Как видите, только 3 «мутанта» были убиты, а 23 выжили, и мы получаем результат мутационных тестов всего в 11,54%. Это значит, что нам нужно добавить юнит-тестов в систему и покрыть тестами случаи, когда мутанты выживают. Можно «провалиться» в каждую папку и каждый отдельный файл из отчёта, и посмотреть, какие мутационные тесты были выполнены, и их результат. Например, в нижней части рисунка мы видим «выжившего мутанта». То есть, у нас нет теста, проверяющего случай, когда _orderStatusId не равен OrderStatus.Submitted.Id, и нам нужно его добавить.

Отдельный интересный пример – замена LINQ методов, например, First/Single на FirstOrDefault/SingleOrDefault и наоборот. Здесь проверяется случайное неверное использование. В случае пустой коллекции First/Single должны выбрасывать исключение, тогда как *OrDefault версии нет.

Итого
Вы можете спросить: когда следует запускать мутационные тесты? В CI/CD, локально или время от времени?

Пока не понятно. Я всё ещё новичок в мутационном тестировании. На данный момент думаю, имеет смысл добавить его как часть разработки. То есть, начиная работу с некоторым кодом, запустить Stryker, чтобы посмотреть хорошо ли код покрыт тестами. Если да, можно уверенно работать с этим кодом. Если нет - то сначала сосредоточьтесь на увеличении охвата, а затем на развитии кода. Сделать Stryker частью вашего CI/CD также возможно.

Stryker и мутационное тестирование в целом - не серебряная пуля. Я бы скорее назвал его страховкой. Закончили кодирование функции или исправление ошибки? Сделайте одолжение себе и своей команде и проверьте, охватывают ли ваши тесты все возможные случаи. Да? Отлично. Нет? Просто исправьте это.

Источник: https://lukaszcoding.com/how-good-are-your-net-tests-test-your-tests-with-stryker-mutator/
👍2
День восемьсот тридцатый. #ЗаметкиНаПолях #GC
Топ Вопросов о Памяти в .NET. Продолжение 13-16
Начало 1-4
Продолжение 5-8
Продолжение 9-12

13. Что такое POH?
Куча закреплённых объектов (Pinned Object Heap) - это новый тип раздела управляемой кучи (помимо SOH и LOH), добавленный в .NET 5 и предназначенный для объектов, которые не будут перемещаться сборщиком мусора. Таким образом, POH никогда не уплотняется, что позволяет рассматривать все объекты в POH как «закреплённые» по умолчанию. Это полезно, потому что закрепление в SOH/LOH вводит некоторые накладные расходы и снижает гибкость сжатия памяти (что может привести к фрагментации). Наличие специального места для «закреплённых» объектов устраняет эту проблему.
Однако для аллокаций памяти был добавлен новый API, потому что теперь нам нужно указать, что мы выделяем объект, который необходимо немедленно закрепить. В настоящее время это можно сделать с помощью GC.AllocateUninitializedArray. То есть мы можем выделить там только массив типов, которые не являются ссылочными и не содержат ссылок (например, массив байтов). Хотя собственно POH не имеет таких ограничений.

14. Какую сборку мусора мы можем вызвать через API GC?
В .NET доступны API, позволяющие контролировать поведение сборщика мусора. Например, GC.Collect и его перегрузки позволяют нам запускать сборку мусора в поколениях 0, 1 или полную (с указанием, хотите ли вы, чтобы она была блокирующей и/или с уплотнением памяти). Однако из-за того, как работает сборка мусора в .NET, мы не можем запустить сборку только поколения 2 или только LOH. При сборке поколения (или LOH) всегда выполняется сборка мусора для всех младших поколений. Поэтому, когда мы запускаем сборку в поколении 2, мы запускаем полную сборку мусора. И нет API для запуска только сборки в LOH (в этом случае также будет запущена полная сборка).
С другой стороны, действительно есть возможность запустить сжатие LOH при следующей непараллельной полной сборке мусора вот таким способом:
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect();

15. Используются ли память и сборщик мусора разными .NET приложениями совместно?
Когда мы запускаем приложение .NET, оно выполняется средой выполнения .NET внутри обособленного процесса. Другими словами, каждое приложение .NET выполняется своим собственным экземпляром среды выполнения, и между ними нет ничего общего. Это позволяет нам настраивать и управлять жизненным циклом каждого приложения .NET отдельно. Это касается и сборщика мусора, и управляемой кучи. Каждый процесс имеет свой собственные кучу и сборщик мусора и не знает о существовании других. Сборщик мусора, запускаемый в одном приложении .NET, не влияет (и не запускает) сборщик мусора в другом приложении .NET.
При этом процессы, запущенные на одном компьютере, совместно используют некоторые ресурсы, такие как ЦП, память и диски. Очевидно, что на этом уровне может произойти некоторое совместное использование ресурсов.

16. Каково предназначение флага gcAllowVeryLargeObjects?
Если вы когда-либо достигали предела общего размера объекта в 2Гб - возможно, массива или строки, хорошей новостью для вас является то, что вы можете преодолеть это ограничение с помощью флага gcAllowVeryLargeObjects (по умолчанию отключен). Он позволяет создавать массивы размером более 2Гб, но применим только к массивам (то есть не применим к строкам или другим типам объектов) и только к общему размеру массива. Максимальное количество элементов в массиве (UInt32.MaxValue) не меняется. И хотя это, конечно, не самое распространённое требование, например, оно может быть полезно в приложениях, обрабатывающих огромные изображения или большие данные.

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

Источник: https://dotnetmemoryexpert.com
День восемьсот тридцать первый. #Юмор
9 Квинтиллионов Остановок
Пост немножко боян, но всё-таки, довольно смешно. Итак, в твиттере выложили скриншот приложения Journey Tracker, используемого в Англии, в котором показан путь поезда с 9,223,372,036,854,775,807 остановок. Как такое возможно?

Программисты, наверное, сразу попробуют сравнить это число со степенью двойки, и действительно, оно всего на 1 меньше 2^63, что очень похоже на 64-битное число со знаком. То есть имело место простое переполнение.

На самом деле на приведённой картинке был первый случай. Через пару лет случился похожий (который подробно описан в видео по ссылке ниже). Отдельно доставило, что на второй твит ответил один из разработчиков приложения: «Я думал, мы это пофиксили давным давно.»

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

Источник: https://youtu.be/48QQXpbTlVM