.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
День 1144. #ЗаметкиНаПолях #AsyncTips
Неизменяемые стеки и очереди

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

Решение
Неизменяемые стеки и очереди из пространства имён System.Collections.Immutable по поведению очень близки к стандартным коллекциям Stack<T> и Queue<T> и обладают практически такой же временной сложностью. Впрочем, в простых сценариях с частым обновлением стандартные стеки и очереди работают быстрее.

Неизменяемый стек
var stack = ImmutableStack<int>.Empty;
stack = stack.Push(13);
stack = stack.Push(7);

// Выводит "7", затем "13".
foreach (int item in stack)
Console.WriteLine(item);

stack = stack.Pop(out int last);
// last == 7

В этом примере многократно перезаписывается локальная переменная stack. Неизменяемые коллекции возвращают обновлённую коллекцию, а ссылка на исходную остаётся без изменений. Это означает, что, если имеется ссылка на экземпляр неизменяемой коллекции, она никогда не изменится:
var stack = ImmutableStack<int>.Empty;
stack = stack.Push(13);
var biggerStack = stack.Push(7);

// Выводит "7", затем "13".
foreach (int item in biggerStack)
Console.WriteLine(item);

// Выводит только "13".
foreach (int item in stack)
Console.WriteLine(item);

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

Неизменяемая очередь
var queue = ImmutableQueue<int>.Empty;
queue = queue.Enqueue(13);
queue = queue.Enqueue(7);
// Выводит "13", затем "7".
foreach (int item in queue)
Console.WriteLine(item);

queue = queue.Dequeue(out int next);
// Выводит "13".
Console.WriteLine(next);

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

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

Неизменяемые коллекции идеально подходят для хранения общего состояния. С другой стороны, в качестве коммуникационного канала они работают не так хорошо. В частности, неизменяемые очереди не следует использовать для передачи данных между потоками; очереди «производитель/потребитель» подходят для этой цели намного лучше.

Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 9.
👍7
День 1145. #ЗаметкиНаПолях
Использование Встроенных Файлов в dotnet core
Мы хотим прочитать файл JSON с диска. Мы не хотим полагаться на абсолютные пути к файлам, параметрам среды, копировать файлы в выходной каталог и т.п. Файл JSON выглядит следующим образом:
file.json
{
"data": true
}

Можно использовать функцию EmbeddedResource. Тогда при сборке проекта файл json будет включён в dll. Чтобы пометить файл как EmbeddedResource, вы просто добавляете его в свой .csproj следующим образом:
<ItemGroup>
<EmbeddedResource Include="Data\file.json" />
</ItemGroup>

Теперь посмотрим, как можно прочитать этот файл. При работе со встроенными файлами нам понадобится сборка, в которой мы будем искать встроенные ресурсы. Рассмотрим следующий интерфейс, содержащий методы для чтения встроенных ресурсов тремя различными способами
public interface IEmbeddedResourceQuery
{
// изнутри сборки
Stream? Read<T>(string resource);
// из заданной сборки
Stream? Read(Assembly a, string resource);
// из сборки по имени сборки
Stream? Read(string name, string resource);
}

Для получения потока для чтения ресурса можно использовать метод GetManifestResourceStream сборки. Ещё одна важная деталь — это то, как строится путь для чтения ресурса. Нам нужно указать имя сборки (MyLibrary), а затем использовать запись пути через точку:
Assembly_name.Folder.Filename
Например, для файла file.json в папке Data путь будет:
MyLibrary.Data.file.json

public class EmbeddedResourceQuery
: IEmbeddedResourceQuery
{
public Stream? Read<T>(string resource)
{
var a = typeof(T).Assembly;
return ReadInternal(a, resource);
}

public Stream? Read(
Assembly a, string resource)
{
return ReadInternal(a, resource);
}

public Stream? Read(
string name, string resource)
{
var a = Assembly.Load(name);
return ReadInternal(a, resource);
}

internal static Stream? ReadInternal(
Assembly a, string resource)
{
return assembly
.GetManifestResourceStream(
$"{a.GetName().Name}.{resource}");
}
}

Использование
var q = new EmbeddedResourceQuery();

// изнутри сборки
var s1 = q.Read<MyType>("Data.file.json ");

// из заданной сборки
var a = Assembly.Load("MyLibrary");
var s2 = q.Read(a, "Data.file.json ");

// из сборки по имени сборки
var s3 = q.Read("MyLibrary", "Data.file.json");

Источник: https://josef.codes/using-embedded-files-in-dotnet-core/
👍11
День 1146.
Улучшаем Производительность Сборки в Visual Studio. Начало
Время — ваш самый ценный актив, и медленная сборка занимает первое место в списке убийц продуктивности разработчиков. При медленной сборке теряется не только время на саму сборку, но часто и вы сами отвлекаетесь на другие задачи, такие как проверка почты, кофе, социальные сети… Таким образом, борьба за сокращение времени сборки имеет важное значение.

Измерение
Прежде чем улучшать, нужно сначала измерить. Расширение Visual Studio Build Timer отображает статистику и водопадную диаграмму вашей сборки в Visual Studio. Инструмент доступен в меню View > Other Windows > Build Timer (Вид > Другие окна > Таймер сборки) и позволяет увидеть, какие проекты собираются дольше, а какие быстрее, какие проекты ждут сборки других и т.п.

Фильтры решений
Обычно мы обычно работаем только с несколькими проектами из решения. Поэтому можно вручную выгружать ненужные проекты, чтобы добиться более быстрой компиляции. Процесс выгрузки набора проектов можно значительно улучшить, определив файл фильтра решения (.slnf). Чтобы его создать, просто выгрузите несколько проектов, щёлкните правой кнопкой мыши на решении и выберите в меню Save as Solution Filter (Сохранить как фильтр решения).

VS рассматривает файлы фильтров решений (.slnf) как файлы решений (.sln). Файл фильтра представляет собой текстовый файл, который можно легко редактировать. Загрузка фильтра решения загружает целевые проекты и полностью игнорирует другие: они даже не отображаются как выгруженные. Выгрузка/загрузка проектов в открытом фильтре вызывает подсказку, предлагающую обновить фильтр.

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

Инкрементная сборка
В контексте VS MSBuild проверяет актуальность выходных данных проекта, чтобы определить, нужно ли его компилировать. Эта функция называется Incremental Build и необходима для значительного сокращения количества компилирующихся проектов для ускорения сборки.

Основные причины неактуальности проекта:
- Один из файлов, используемых в качестве входных данных проекта (исходный файл, файл ресурсов…), имеет более новую временную метку, чем временная метка выходного файла проекта (.dll, .pdb, .xml…).
- Проект зависит как минимум от одного устаревшего проекта.

Инкрементальные проверки сборки не могут быть идеальными, особенно когда используются некоторые нетривиальные функции. Например, если в одном из файлов проекта для свойства Copy to Output Directory (Копировать в выходной каталог) установлено значение Copy Always (Копировать всегда), проект никогда не будет считаться актуальным. Такая причина не очевидна. Чтобы это обнаружить перейдите в Options > Projects and Solutions > SDK-Style Projects (Параметры > Проекты и решения > Проекты SDK) измените для параметра Logging Level значение с None на Minimal. Теперь в окне Output при сборке можно заметить строку:
1>FastUpToDate: Item … has CopyToOutputDirectory set to 'Always', not up to date.

Это поможет понять, что заставляет проект перекомпилироваться каждый раз. Чтобы избавиться от этого, просто установите Copy to Output Directory на Copy if Newer (Копировать, если новее).

Чтобы узнать, есть ли у вашего решения такая проблема: сначала выполните Build > Rebuild Solution, а затем Build > Build Solution. Если какие-то проекты перекомпилируются второй раз, исследуйте проблему.

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

Источник:
https://blog.ndepend.com/improve-visual-studio-build-performance/
👍10
День 1147.
Улучшаем Производительность Сборки в Visual Studio. Окончание
Начало

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

2. В окне Options > Projects and Solutions > Build and Run (Параметры > Проекты и решения > Сборка и запуск):
- Убедитесь, что вы используете параллельные сборки.
- Убедитесь, что отмечен флажок Only Build Startup and Dependencies on Run (Собирать только стартовый проект и зависимости при запуске).

3. По умолчанию Visual Studio компилирует каждый проект в отдельный каталог .\bin\Debug и копирует туда все сборки, на которые ссылается проект. Это было настоящим убийцей производительности сборки в старых версиях VS. Надеюсь, это было исправлено. Тем не менее, если на проект P ссылаются N других проектов, существует N+1 файлов сборки P. Мало того, что это трата ресурсов, но также может быть, что версии станут рассинхронизированы, например, из-за того, что некоторые проекты были выгружены в обозревателе решений. Это может привести к неожиданному поведению во время выполнения, например к возникновению MissingMethodException. Поэтому лучше установить, чтобы все проекты решения (кроме тестовых) использовали один и тот же выходной каталог ..\bin\Debug. Таким образом, каждая сборка будет существовать в единственной версии.

Горячая перезагрузка
Благодаря новой функции горячей перезагрузки .NET (ранее известной как Edit and Continue) цикл [написание кода — сборка — запуск — достижение состояния для тестирования — тестирование] сокращается, т.к. шаги [сборка — запуск — достижение состояния для тестирования] могут быть пропущены в многих сценариях редактирования (но не всегда).

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

Большую часть времени модификации исходного кода между двумя сборками представляют собой крошечную часть пересобираемого кода. Можно ожидать, что в будущем конвейер сборки сможет повысить производительность инкрементной сборки за счет внедрения модификаций кода в двоичный файл вместо пересборки всего файла. Но уже в Visual Studio 2022 можно включить горячую перезагрузку, чтобы ускорить выполнение тестов, пропуская дорогостоящие этапы сборки для поддерживаемых типов изменений. Обратите внимание, что эта функция все ещё является экспериментальной и работает только для .NET 6.

Источник: https://blog.ndepend.com/improve-visual-studio-build-performance/
👍2
День 1148.
Как Настроить Git для Улучшения Процесса Разработки
git config — мощная команда. Также вы можете использовать файл конфигурации. Он существует на уровне проекта, где инициализируется Git (/project/.git/config), или в корне (~/.gitconfig). Если конфигурация не указана, Git использует настройки по умолчанию. Рассмотрим некоторые полезные настройки, которые могут улучшить ваш процесс разработки.

1. Выбор редактора по умолчанию
Git по умолчанию открывает редактор vi. Он может быть сложен в использовании. Однако вы можете использовать предпочитаемый вами редактор для написания коммитов. В файл .gitconfig добавьте:
[core]
editor = code --wait
либо используйте команду:
git config --global core.editor "code --wait"

Это откроет редактор VSCode. Настройки для других редакторов можно посмотреть здесь.

2. prune при fetch
Если вы удалили ветку, например, после слияния её с основной, команда prune удалит устаревшие ссылки на удалённые ветки в вашем каталоге .git. Для этого вы можете выполнить
git fetch –prune

Либо задать это поведение по умолчанию в настройках. В файле конфигурации:
[fetch]
prune = true
либо командой:
git config --global fetch.prune true

3. Git-псевдонимы
В файле конфигурации Git вы можете добавить псевдонимы для тех длинных команд, которыми вы постоянно пользуетесь: commit, stash и т.п.
Допустим, вы хотите добавить псевдоним для добавления пустого коммита. В файле конфигурации:
[alias]
empty = git commit --allow-empty
либо командой:
git config --global alias.empty "git commit --allow-empty"

Теперь вы можете использовать такую команду:
git empty "Empty commit"

В псевдонимах вы можете использовать не только команды Git, но и любые другие команды терминала. Git просто выполнит всё, что указано в команде. Для этого добавьте ! в начало команды:
this = !git init && git add . && git commit -m \"Initial commit.\"

Теперь git this инициализирует репозиторий в папке, добавит все файлы под контроль git и выполнит первый коммит.

4. Ветка по умолчанию
При инициализации репозитория (git init) веткой по умолчанию является main (или master). Не обязательно использовать это имя. В файле конфигурации Git вы можете установить ветку по умолчанию при инициализации:
[init]
defaultBranch = default

Источник: https://www.freecodecamp.org/news/git-config-how-to-configure-git-settings/
👍5
День 1149. #Карьера
Чем Больше Ты Знаешь, Тем Больше Знаешь, Что Не Знаешь
На изображении ниже вы можете увидеть, как рост опыта влияет на уверенность. Первоначально ваша уверенность низка, так как вы знаете, что вы неопытны. Однако через некоторое время вы начинаете «что-то понимать» и попадаете в зону комфорта. В зависимости от того, насколько требовательна ваша среда, вы можете оставаться там в течение очень долгого времени, но, если вас подталкивают вперёд, вы, скорее всего, быстро упадёте в «долину отчаяния», когда поймёте, что есть гораздо больше того, чего вы не умеете делать или ещё не освоили. С этой точки, как правило, ваша уверенность растёт по мере увеличения вашего опыта. Это известно как эффект Даннинга-Крюгера.

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

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

Можно расширить это представление, применив известную цитату Дональда Рамсфельда о «неизвестных неизвестных». Чем больше у вас опыта, тем больше вещей вы знаете. Также становится больше вещей, о которых вы знаете, что вы их не знаете. Но, кроме этого, есть множество вещей, о которых вы не знаете, что не знаете их. И несмотря ни на что, всегда будет большое (возможно, бесконечное) количество «неизвестных неизвестных».

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

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

Источник: https://ardalis.com/the-more-you-know-the-more-you-realize-you-dont-know/
👍9
День 1150. #Оффтоп
Сегодня будет полнейший оффтоп. На него меня вдохновил очередной твит одного из коллег программистов. Вопрос в нём был следующий:

Какая область (кроме ИТ) вдохновляет вас больше всего?

Это не обязательно может быть ваше личное хобби, может просто что-то, что вам интересно изучать или узнавать новости.

Расскажу о себе.
Для меня это авиация. Я сам, конечно, не летаю. Но я обожаю смотреть видео как об устройстве самолётов, так и о расследовании инцидентов и катастроф. Сотни и тысячи людей трудятся над тем, чтобы сделать этот вид транспорта более комфортным, более быстрым и более безопасным. Я больше воспринимаю визуальную информацию, поэтому у меня в приоритете видео.

Вот несколько каналов, которые я смотрю.
Mentour Pilot
Практикующий лётчик рассказывает об устройстве самолётов, аэропортов, о том, как составляется расписание, как работают пилоты, а также разбирает некоторые самые известные авиапроисшествия на основе официальных отчётов.

74 Gear
Канал второго пилота Боинга-747. Тематика похожая, но более неформальная. Он разбирает вирусные видео на тему авиации, смешные переговоры пилотов с диспетчерами, а также рассказывает байки из своей (и не только своей) практики.

Помимо этого, постоянно смотрю пару автомобильных каналов. На этот раз русскоязычных.

ИЛЬДАР АВТО-ПОДБОР
Ребята рассказывают, как ремонтируют, подбирают, а иногда дарят машины в рамках благотворительного проекта. Интересно, грамотно, с юмором.

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

Поделитесь в комментариях, что вас вдохновляет из не-ИТ мира? Не обязательно со ссылками на видео, может это книги, блоги или подкасты. То, что вы изучаете в свободное от программирования время.
👍3
День 1151.
Прекращение Поддержки .NET 5
Поддержка .NET 5.0 прекратится 8 мая 2022 г. После майских обновлений .NET Microsoft больше не будет предоставлять сервисные обновления, включая исправления безопасности или техническую поддержку, для .NET 5.0. Нужно обновить версию .NET до 6.0, чтобы продолжать получать обновления.

.NET 5.0 не является выпуском LTS (долговременной поддержки), поэтому он поддерживается в течение 18 месяцев или 6 месяцев после выпуска следующей версии. Приложения на .NET 5.0 продолжат работать. Тем не менее, прекратится выпуск обновлений безопасности для .NET 5.0, хотя он продолжится для .NET Core 3.1 и .NET 6.0. Это означает, что .NET 5.0 после 8 мая может стать потенциально небезопасной. Кроме того, прекратится техническая поддержка.

Обновление до .NET 6.0
Откройте файл проекта (файл .csproj, .vbproj или .fsproj).
Измените значение целевой платформы с net5.0 на net6.0.
Также посмотрите на критические изменения в версии 6.0.

Обновите среду разработки
На компьютере, который вы используете для разработки, может быть установлена .NET 5.0 — либо автономно, либо вместе с Visual Studio.

Начиная с сервисного обновления Visual Studio 2019 16.11 и 16.9 в июне 2022 г., компонент .NET 5.0 в Visual Studio будет изменён на неподдерживаемый и необязательный. Это означает, что компоненты Visual Studio могут быть установлены без установки .NET 5.0. Обратите внимание, что это не повлияет на существующие установки, и любые ранее установленные компоненты останутся установленными. Хотя вы сможете повторно выбрать этот необязательный компонент в Visual Studio и переустановить его, настоятельно рекомендуется использовать .NET 6.0 с Visual Studio 2022 для создания приложений, работающих в поддерживаемой среде выполнения .NET.

Версии SDK .NET 5.0 будут по-прежнему поддерживаться в VS 16.11 до декабря 2022 года, когда прекратится поддержка .NET Core 3.1, чтобы клиенты .NET Core 3.1 могли продолжать использовать 16.11 для разработки своих приложений. SDK .NET 5.0 не будет использовать среду выполнения .NET 5.0 при запуске сценариев командной строки и не будет поставляться как отдельный пакет SDK.

Источник: https://devblogs.microsoft.com/dotnet/dotnet-5-end-of-support-update/
👍3
День 1152. #ЧтоНовенького
Автосохранение Кода в VS 2022
IDE — это инструмент, который объединяет множество систем, необходимых разработчику для создания приложения. Однако, это всё равно не единственный инструмент в наборе разработчика.

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

Начиная с 17.2 Preview 1 в этом поможет новая функция автосохранения. Она находится в меню Tools > Options > Environment > Documents (Инструменты > Параметры > Cреда > Документы).

Если установлен флажок Automatically save files when Visual Studio is in the background (Автоматически сохранять файлы, когда Visual Studio находится в фоновом режиме), то каждый раз, когда VS теряет фокус (обычно при переключении на другое приложение), VS будет пытаться сохранить все несохранённые документы в IDE: файлы проекта, файлы решения и даже прочие файлы, которые не являются частью проекта или решения. Если по какой-либо причине сохранить файл не удастся (например, файл доступен только для чтения), VS сохранит ваши изменения в редакторе и просто оставит файл «грязным».

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

Стоит отметить, что люди, которые используют функцию Code Cleanup on Save (Очистка кода при сохранении), обнаружат, что автосохранение не запускает очистку кода. Разработчики утилиты решили, что это будет слишком затратно, если будет происходить слишком часто. Очистка кода при сохранении срабатывает только в том случае, если вы явно сохраняете файл через Ctrl+S, либо неявно в процессе сборки проекта.

Источник: https://devblogs.microsoft.com/visualstudio/suffer-from-ctrls-fatigue-we-have-a-feature-for-you/
День 1153.
30 и 31 марта 2022 пройдёт онлайн конференция .NET Beyond.
На ней вы посмотрите, как некоторые из самых умных людей в сообществе .NET используют его для разработки для предприятия — и в масштабе.
Независимо от того, в какой области .NET вы работаете, вы гарантированно научитесь чему-то, чего ещё не знаете.

Вот программа конференции (время московское):
30 марта
18:00 The History of .NET (Richard Campbell)
19:00 Scalability and Security with K8s and Azure Active Directory (Christos Matskas)
20:00 Getting to DDD: Pragmatic or Principled? (Julie Lerman)
21:00 Why F# Works in the Enterprise (Phillip Carter)
22:00 Introducing MongoDB and .NET: SQL is Not the Only Way (Luce Carter)
23:00 Kubernetes Made Easy with VMware Tanzu Application Platform (John Bush)
00:00 Mobile DevOps at Scale (Rodney Littles II)

31 марта
12:00 REST, GraphQL, and gRPC: A Comparison (Poornima Nayar)
13:00 Messaging for .NET Developers (Ian Cooper)
14:00 The Hand That Feeds: How to Misuse Kubernetes (Lewis Denham-Parry)
15:00 From Monolith to Service Orientated and Beyond (Stacy Cashmore)
16:00 ASP.NET Basics for Experts (Jakub Pilimon, Layla Porter)
17:00 Observability for .NET Applications (Hananiel Sarella)
18:00 Simplifying Microservice Security with YARP (Andrew Stakhov)
19:00 Your Enterprise Open Source Journey (Jeff Fritz)

Трансляция на YouTube

Источник: https://tanzu.vmware.com/developer/tv/dotnet-beyond
1154.png
1.8 MB
День 1154. #CodeReview
Пирамида Обзора Кода
В обзорах кода обычно много внимания и многословных дискуссий уделяется приземлённым аспектам, таким как форматирование и стиль кода, в то время как важные аспекты (делает ли изменение то, что должно делать, является ли оно производительным, является ли он обратно совместимым для существующих клиентов и многие другие), как правило, привлекают меньше внимания.

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

Основной принцип: Нижние части пирамиды должны лежать в основе код-ревью и занимать его большую часть.

Источник: https://www.morling.dev/blog/the-code-review-pyramid/
👍5
День 1155. #ЗаметкиНаПолях
Тип .NET для Персональных Данных. Начало
Персональные данные (Personally identifiable information - PII) — это любая информация, относящаяся к идентифицированному или идентифицируемому физическому лицу (т.е. позволяющая идентифицировать лицо прямо или косвенно, в частности, через имя, идентификационный номер, email, дату рождения, данные о местоположении и т.п.).

Проблема
Согласно законодательству многих стран, вы должны обращаться с PII особым образом. Например:
1. Шифровать или анонимизировать везде, где это возможно.
Для этого данные PII должны отображаться по-разному в зависимости от варианта использования. Например:
- обычный текст в UI;
- псевдоним в логах;
- зашифрованы в файле экспорта CSV.

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

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

На первый взгляд очевидно использование string для PII:
public class User
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Location { get; set; }
}
Однако не очевидно, как шифровать/анонимизировать эти значения в каждом конкретном случае. Кроме того, идентификация таких полей в исходном коде по запросу юристов компании может быть сложной задачей.

Решение
Ввести явный тип, например, PiiString. Он должен быть как можно более взаимозаменяемым со string, чтобы упростить рефакторинг существующего кода, использующего string. В приложении он должен вести себя как обычная строка, однако вне приложения, он должен быть закодирован/зашифрован/хеширован.
Заметьте, что ниже приведена упрощённая версия класса. Полная тут:
public class PiiString
{
private readonly string _string;

public PiiString(string str)
=> _string = str ??
throw new ArgumentNullException(nameof(str));

public override string ToString()
=> _string;
}

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

Источник:
https://gaevoy.com/2022/03/18/personally-identifiable-information-data-types.html
👍10
День 1156. #ЗаметкиНаПолях
Тип .NET для Персональных Данных. Окончание
Начало

Проверим PiiString на соответствие требованиям.

1. Шифрование или анонимизация PII
Значение PiiString может быть преобразовано в зависимости от используемой логики кодирования.
public interface IPiiEncoder
{
string ToSystemString(PiiString pii);
PiiString ToPiiString(string str);
}

PiiString как обычный текст:
public class PiiAsPlainText : IPiiEncoder
{
public string ToSystemString(PiiString pii)
=> pii.ToString();

public PiiString ToPiiString(string str)
=> new PiiString(str);
}

Анонимизированная PiiString через хэш SHA256:
public class PiiAsSha256 : IPiiEncoder
{
public string ToSystemString(PiiString pii)
{
var data = Encoding.UTF8.GetBytes(pii.ToString());
using var sha = SHA256.Create();
var hash = sha.ComputeHash(data);
return Convert.ToBase64String(hash);
}

public PiiString ToPiiString(string str)
=> throw new NotSupportedException();
}

PiiString в Entity Framework Core
public class PiiConverter 
: ValueConverter<PiiString, string>
{
public PiiConverter(IPiiEncoder encoder)
: base(
v => encoder.ToSystemString(v),
v => encoder.ToPiiString(v))
{}
}

2. Соглашение об обработке данных с третьими лицами
Обычно это сводится к тому, чтобы найти все места в исходном коде, где используется PII, а затем обработать эту информацию для юристов. В Visual Studio есть команда Find All References (Найти все ссылки), которая должна упростить задачу.

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

Итого
PiiString явно берёт на себя управление PII. Гораздо лучше, чем простые строки. Эта реализация не идеальна, например, кажется странным использовать PiiString для даты рождения или пола. Альтернативным способом является использование атрибута, но имейте в виду, что это подразумевает рефлексию, генераторы кода или нечто подобное, что чрезмерно усложнить реализацию.

Полный код классов с примерами шифрования Aes128, использования в System.Text.Json, Newtonsoft.Json, Nlog, Serilog и EFCore здесь.

Источник: https://gaevoy.com/2022/03/18/personally-identifiable-information-data-types.html
👍1
День 1157. #юмор
Сегодня порекомендую просто уморительное видео. Это доклад «The Worst Programming Language Ever» от Марка Рендла с конференции NDC Oslo 2021.

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

Поэтому особенно доклад оценят те, кому приходилось работать на разных языках, и кто прочувствовал всю боль работы с ними. От нестрогой типизации и неочевидной логики в JavaScript до обязательного обозначения переменных с $ и обращения к свойствам через => в PHP, от обратной логики исключений в Ruby до табов и пробелов в Python, ну и куда же без макросов и ручного управления памятью в С/С++.

Я лично многое из этого на себе испытал, поэтому некоторые флешбеки словил, но в то же время от души посмеялся.
👍4
День 1158. #ЧтоНовенького
GitHub Copilot Доступен в Visual Studio 2022
С тех пор, как в прошлом году была запущена предварительная версия GitHub Copilot, команда изучала полученные отзывы, а также расширяла охват как людей, имеющих доступ к ней, так и мест, где вы можете её использовать. Теперь она добавлена и в Visual Studio 2022.

Установка
Прежде всего, вам необходимо зарегистрироваться в списке ожидания, чтобы получить доступ к технической предварительной версии GitHub Copilot. Когда вы получите письмо от GitHub, подтверждающее, что у вас есть доступ, в Visual Studio 2022 перейдите в раздел Extensions > Manage Extensions (Расширения > Управление расширениями), найдите GitHub Copilot и установите его.

После установки снова откройте VS. Вам будет предложено авторизовать VS в сервисе GitHub Copilot. В открывшемся браузере вставьте код авторизации. Как только вы увидите сообщение, подтверждающее подключение, вы можете закрыть окно браузера и вернуться в Visual Studio. Теперь вы должны принять условия отправки телеметрии в GitHub Copilot.

Использование
По мере ввода кода GitHub Copilot автоматически предложит код, который, по его мнению, вам может понадобиться. Вы можете нажать клавишу Tab, чтобы принять его, или просто продолжать печатать, чтобы игнорировать, тогда Copilot предложит другие варианты, основываясь на том, что, по его мнению, вы делаете. Нажмите Esc, чтобы полностью удалить предложение, если оно вам мешает.

Хотя Copilot всегда будет показывать наилучшие рекомендации, вы можете использовать Ctrl+Alt+] и Ctrl+Alt+[ для навигации по вариантам, которые он сгенерирует.

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

Команда GitHub Copilot ждёт ваших отзывов тут.

Источник: https://github.blog/2022-03-29-github-copilot-now-available-for-visual-studio-2022/
👍7
UPD: Меня одобрили в программе предварительной оценки буквально вчера вечером. Сегодня с утра немножко поковырял фичу. Почему-то добиться эффекта полного решения по комментарию (как на картинке) не удалось, но вот более простые вещи выдаёт довольно быстро и точно.
День 1159. #Карьера
Как Превратить Синдром Самозванца в Преимущество
Прошли оценки эффективности, пришло время встретиться с менеджером. Я знал, что он скажет. Как ещё оценить программиста, который не пишет код?

Мой разум постоянно возвращался к последней ошибке, которую я должен был исправить. Я потратил целый день, в конце концов сдался и попросил помощи у коллеги. Он нашел её за 10 минут. Я явно не дотягивал.

Мой босс, похоже, заметил это и наверняка поэтому поручил мне помогать аудиторам анализировать наш код. Помогать? Я сам еле его понимал! Но это был сторонний проект. Если что-то не требует написания кода, зачем тратить время настоящих программистов? Я едва справлялся, постоянно спрашивал что-то у менеджера и как мог пытался объяснять это аудиторам. Короче, я был обречён.

«Поздравляю, вы получили повышение. Продолжайте в том же духе!»

Подождите… что? Он не заметил? Я не собирался указывать ему на его ошибку. Я был уверен, что скоро всё выяснится. Я не мог прятаться вечно. Следующие несколько лет я готовился к неизбежному, пытаясь работать над проектами, которые могли бы научить меня навыкам, привлекательным для рекрутёров.

Четыре года спустя я всё ещё не чувствовал себя особенным, но меня продолжали повышать. Я продолжал как-то их дурачить, бюрократизированный процесс проверки скрывал мои недостатки. Но я заметил кое-что ещё: люди стали приходить ко мне за советами. Я всё ещё не чувствовал, что знаю достаточно. Я просто рассказывал о том, над чем работал, иногда указывал молодым инженерам на лучшие практики. Это не казалось чем-то оригинальным, но люди считали это полезным. Было очень странно, когда старшие инженеры стали спрашивать меня о коде. Они помогали мне много лет. Разве они чего-то не знали?

Но всё же… это моя команда. Будут ли другие компании думать так же? Только один способ узнать: я стал ходить на собеседования. Я не мог поверить, когда получил несколько предложений о работе, в том числе от Google!

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

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

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

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

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

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

Я подозреваю, что синдром самозванца никогда полностью не исчезнет. Но сейчас я воспринимаю его как благо. Преимущество. Это признак того, что я расту.

Источник: https://www.zainrizvi.io/blog/the-impostors-advantage/
Автор оригинала: Zain Rizvi
👍23
День 1160. #ЗаметкиНаПолях
Автоматическое Обновление Времени Создания/Обновления/Удаления в Entity Framework.
В любой схеме базы данных очень часто встречаются поля Created, Updated и Deleted для сущностей. Они полезны для отладки, а поле Deleted позволяет реализовать «мягкое удаление». Есть довольно простой метод, заключающийся в переопределении поведения сохранения Entity Framework.

Во-первых, нужно определить «базовую модель», от которой могут наследоваться все сущности:
public abstract class Auditable
{
public DateTimeOffset Created { get; set; }
public DateTimeOffset? Updated { get; set; }
public DateTimeOffset? Deleted { get; set; }
}
Это абстрактный класс, т.к. не должно быть возможности создавать его экземпляры. И мы используем DateTimeOffset, чтобы не было путаницы с часовыми поясами.

Далее, мы наследуем сущности от этого класса:
public class Customer : Auditable
{
public int Id { get; set; }
public string Name { get; set; }
}

Теперь нужно, чтоб EF обновляла эти значения при сохранении. Есть несколько способов это сделать, но самый простой — переопределить метод сохранения SaveChangesAsync в классе контекста:
public override Task<int> 
SaveChangesAsync(CancellationToken ct = default)
{
foreach (var e in
ChangeTracker.Entries<Auditable>())
{
switch (e.State)
{
case EntityState.Added:
e.Entity.Created = DateTimeOffset.UtcNow;
break;
case EntityState.Modified:
e.Entity.Updated = DateTimeOffset.UtcNow;
break;
case EntityState.Deleted:
e.Entity.Deleted = DateTimeOffset.UtcNow;
e.State = EntityState.Modified;
break;
}
}

return base.SaveChangesAsync(ct);
}

Процесс использует обобщённый метод ChangeTracker.Entries<T>(), который получает все добавляемые сущности типа Auditable (и унаследованные от них), и в зависимости от состояния устанавливает дату создания, обновления или удаления. Также заметьте, что для удаляемых сущностей состояние изменяется на Modified. Наконец, вызывается базовый метод SaveChanges, который фактически выполняет сохранение.

Примечание: Начиная с EF Core 5.0, вместо переопределения SaveChanges можно использовать класс SaveChangesInterceptor.

Заметьте, что можно тем же образом обновлять и другие «автоматизированные» поля. Например, сохранять данные о пользователе, который создал, обновил и удалил объект.

Источник: https://dotnetcoretutorials.com/2022/03/16/auto-updating-created-updated-and-deleted-timestamps-in-entity-framework/
👍17
День 1161. #ЗаметкиНаПолях
Мягкое удаление в Entity Framework
При использовании мягкого удаления возникает проблема, что во всех запросах приходится отфильтровывать удалённые объекты:
dbSet.Where(x => x.Deleted == null);

И об этом нужно постоянно помнить.

Есть отличный способ решить эту проблему с помощью так называемых «глобальных фильтров запросов». В документации даже есть пример: https://docs.microsoft.com/en-us/ef/core/querying/filters.

Проблема в том, что в примере показано, как это сделать для отдельного объекта. Если в вашей базе данных много таблиц вам придется каждый раз не забывать добавлять конфигурацию. Придётся сделать кое-что посложнее в методе OnModelCreating контекста:
protected override void
OnModelCreating(ModelBuilder builder)
{
// остальные настройки

var entities = builder.Model
.GetEntityTypes()
.Where(e => e.ClrType.BaseType == typeof(Auditable))
.Select(e => e.ClrType);

Expression<Func<Auditable, bool>>
expression = del => del.Deleted == null;

foreach (var e in entities)
{
var p = Expression.Parameter(e);
var body =
ReplacingExpressionVisitor
.Replace(expression.Parameters.Single(),
p, expression.Body);

builder.Entity(entity)
.HasQueryFilter(
Expression.Lambda(body, p));
}

base.OnModelCreating(builder);
}
}

Сначала мы выбираем все сущности, которые наследуют от Auditable (см. предыдущий пост). Затем создаём выражение expression для фильтрации. Далее перебираем все выбранные сущности и создаём для каждого типа своё выражение путём замены параметра выражения expression на тип конкретной сущности. И наконец с помощью метода HasQueryFilter() добавляем глобальный фильтр.

Теперь все запросы в нашем приложении будут иметь фильтр и не включать мягко удалённые объекты. Если же для каких-то запросов (например, в блоке администрирования) всё-таки нужно получить все объекты, можно использовать метод IgnoreQueryFilters() в запросе.

Источник: https://dotnetcoretutorials.com/2022/03/17/using-ef-core-global-query-filters-to-ignore-soft-deleted-entities/
👍20