.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
День 1001. #юмор
Да, да, именно так.
День 1002. #ProjectManagement
Почему Плохое ПО Случается с Хорошими Людьми. Начало
Плохое ПО - одна из немногих вещей, которую нельзя решить с помощью денег. У огромных авиакомпаний приложения для поиска рейсов часто уступают студенческим проектам. Корпоративные ИТ-системы - это монстры с огромными бюджетами, создаваемые в течение многих лет. Как бы то ни было, причина плохого ПО не в недостатке финансирования.

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

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

1. Повторное использование ПО
ПО легко копировать как на уровне кода, так и на уровне модулей. Современное ПО почти никогда не создается с нуля. Даже самые инновационные приложения создаются с использованием существующего ПО, которое было объединено и модифицировано для достижения нового результата.

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

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

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

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

Источник:
https://www.csc.gov.sg/articles/how-to-build-good-software
День 1003. #ProjectManagement
Почему Плохое ПО Случается с Хорошими Людьми. Окончание
Начало

2. ПО ограничено сложностью
Полезность ПО обычно ограничивается его сложностью, а не объемом ресурсов, вложенных в его создание.

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

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

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

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

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

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

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

Источник: https://www.csc.gov.sg/articles/how-to-build-good-software
День 1004. #NetBasics
Чем Отличается SDK от Runtime?
Официальная страница .NET предлагает 2 опции для скачивания:
- SDK (Software Development Kit) – комплект для разработки ПО со средой исполнения,
- Runtime – только среду исполнения.

Среда исполнения — это то, что должно быть установлено на машине конечного пользователя или сервере для запуска приложения .NET. SDK - это набор инструментов для разработки ПО, который позволяет программистам разрабатывать приложения .NET. Проще говоря, SDK — это то, что создаёт исполняемые файлы, а среда исполнения — это то, что может их запускать.

Разработчикам ПО нужно скачивать .NET SDK, чтобы создавать приложения .NET, но веб-сервер или компьютер конечного пользователя могут иметь только среду исполнения .NET, которая гораздо меньше по размеру.

Ещё один момент — это слабая взаимосвязь между разными языками .NET. Как видно на картинке ниже, C#, F# и VB.NET находятся на разных этапах своей жизни и, следовательно, имеют разные версии. Языки могут развиваться независимо и вводить новые языковые функции по своему усмотрению до тех пор, пока связанный компилятор переводит исходный код в действительный IL.

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

Для справки: не для каждого языка программирования требуется SDK и среда исполнения. Например, такие языки, как Rust или Go, которые напрямую компилируются в собственный машинный код, не требуют среды исполнения. Для этих языков доступен только один вариант загрузки, который обычно представляет собой SDK для создания ПО. .NET же похож, например, на Java, в которой также есть JDK (Java Development Kit) для создания программного обеспечения и JRE (Java Runtime Environment) для исполнения кода.

Источник:
https://dusted.codes/dotnet-basics
1005.png
286.5 KB
День 1005. #NetBasics
Очень понравилась картинка, поэтому решил её перевести. Надеюсь, Кокоса не будет против. Все ссылки на авторство сохранил.

Источник: https://goodies.dotnetos.org/
День 1006. #Testing
Видимое и Невидимое в Модульном Тестировании
В экономике существует понятие «видимого и невидимого», что означает, что при реализации какой-либо политики необходимо сосредоточить внимание на обеих его сторонах:
- Желаемые результаты, которые являются видимой частью.
- Непредвиденные последствия - невидимая часть.

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

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

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

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

Видимая часть модульного тестирования - насколько хорошо ваши тесты защищают вас от ошибок. Невидимая - сколько вам стоит эта защита. Компонент затрат состоит из двух основных подкомпонентов:
- Ремонтопригодность (сколько усилий нужно, чтобы тест оставался работоспособным).
- Устойчивость к рефакторингу (сколько шума генерирует этот тест).

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

Есть и эффекты второго порядка: вы начинаете терять доверие к своим тестам, что приводит к меньшему количеству рефакторингов и, в итоге, к ухудшению кода.

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

Источник: https://enterprisecraftsmanship.com/
Автор оригинала: Vladimir Khorikov
День 1007. #TipsAndTricks
Как не Стоит Читать Строку из Потока UTF-8
Пост возник после код ревью. Следующий код читает из потока строку в кодировке UTF-8. В реальном контексте код сложнее, здесь только суть:
string ReadString(Stream stream)
{
var sb = new StringBuilder();
var buf = new byte[4096];
int readCnt;
while ((readCnt = stream.Read(buf)) > 0)
{
var s = Encoding.UTF8
.GetString(buffer, 0, readCnt);
sb.Append(s);
}

return sb.ToString();
}

Проблема в том, что в некоторых случаях возвращаемая строка отличается от закодированной. Например, иногда смайлик превращается в 4 неизвестных символа:
В потоке: 😊
В результате: ????

UTF-8 может использовать от 1 до 4 байт для представления символа, но метод Stream.Read может возвращать байты от 1 до buffer.Length. Это означает, что буфер может содержать неполный символ UTF-8. В результате Encoding.UTF8.GetString может иметь недопустимую строку UTF-8 для преобразования, поскольку последний символ в буфере может быть неполным. Следующий код имитирует это поведение:
var bytes = Encoding.UTF8.GetBytes("😊");
// bytes = new byte[4] { 240, 159, 152, 138 }

var sb = new StringBuilder();
// Симулируем побайтовое чтение
for (var i = 0; i < bytes.Length; i++)
{
sb.Append(Encoding.UTF8.GetString(bytes, i, 1));
}

Console.WriteLine(sb.ToString());
// "????" вместо "😊"

Encoding.UTF8.GetBytes(sb.ToString());
// new byte[12] { 239, 191, 189, 239, 191, 189, 239, 191, 189, 239, 191, 189 }

Есть несколько способов исправить код.

Один из них - преобразовать массив байт в строку только тогда, когда у вас есть все данные:
string ReadString(Stream stream)
{
using var ms = new MemoryStream();
var buf = new byte[4096];
int readCnt;
while ((readCnt = stream.Read(buf)) > 0)
ms.Write(buf, 0, readCnt);

return
Encoding.UTF8.GetString(ms.ToArray());
}

Вы также можете обернуть поток в StreamReader с правильной кодировкой:
string ReadString(Stream stream)
{
using var sr =
new StreamReader(stream, Encoding.UTF8);
return sr.ReadToEnd();
}

Источник: https://www.meziantou.net/how-not-to-read-a-string-from-an-utf-8-stream.htm
День 1008. #ProjectManagement
3 Принципа Хорошей Разработки ПО. Начало
Понимание особенностей ПО не может гарантировать хороших результатов, но помогает выяснить, почему так много проектов дают плохие результаты. Также они помогают сформулировать некоторые основные принципы работы, которые могут значительно повысить шансы на успех. Хотя необходимо учитывать множество более тонких факторов, следующие принципы образуют основу, позволяющую приступить к созданию хорошего ПО.

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

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

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

2. Нанимайте лучших инженеров
Ключ к хорошей инженерии - это хорошие инженеры. В Google, Facebook, Amazon, Netflix и Microsoft, как известно, одни из самых избирательных процессов собеседований, при этом они ведут ожесточённую борьбу за набор самых сильных кандидатов и платят работникам сильно выше рынка. Этому есть причина. И Стив Джобс, и Марк Цукерберг заявили, что лучшие инженеры как минимум в 10 раз производительнее инженера среднего уровня. Не потому, что они пишут код в 10 раз быстрее, а потому, что они принимают лучшие решения.

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

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

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

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

Источник:
https://www.csc.gov.sg/articles/how-to-build-good-software
День 1009. #ProjectManagement
3 Принципа Хорошей Разработки ПО. Окончание
Начало

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

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

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

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

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

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

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

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

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

Источник: https://www.csc.gov.sg/articles/how-to-build-good-software
👍1
День 1010.
Ну что ж, время подводить итоги раздачи кружек. Всех желающих отобрал и записал в общий список в порядке появления комментариев. Для выбора победителей использовал простую случайную сортировку.

Результаты на картинке. Поздравляю победителей:
- Dmitriy Bobrovskiy (@RebelionTheGrey)
- Max Kaverin (@Kamaew)
- 𝕾𝖊𝖗𝖌𝖊𝖏 (@Xx_dexter_xX)
- Oleksandr Savchuk (@san_d0)
- Vasily Vasily (@Vasily26031988)
- Matviiv Andriy (@matviiv_a)
- Alexey Chernyaev (@FixGN)
- Georgy Levchenko (@FoxTes)
- Амир Хисматуллин (@ikeima)

Пожалуйста, отпишитесь мне в личку, куда прислать кружки.
День 1011. #Оффтоп
Давненько вам не рекомендовал видео. Поэтому сегодня в качестве компенсации нечто эпическое. Интервью Сергея Теплякова подкасту DotNet&More:
- Про собеседования
- Какие скилы сейчас важны?
- Работа в команде
- Будущее C#
- SOLID и прочие паттерны. Надо ли оно сейчас?
и про многое другое аж 2,5 часа.

Наслаждайтесь.

https://youtu.be/W7HqDCnQTkU
День 1012. #ЗаметкиНаПолях #AsyncTips
Обработка исключений из методов async Task

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

Решение
Исключения можно перехватывать конструкцией try/catch, как для синхронного кода:
async Task ThrowExceptionAsync()
{
await Task.Delay(TimeSpan.FromSeconds(1));
throw new InvalidOperationException("Test");
}

async Task TestAsync()
{
try {
await ThrowExceptionAsync();
}
catch (InvalidOperationException) {…}
}

Исключения, выданные из методов async Task, помещаются в возвращаемый объект Task. При использовании await с задачей, в которой произошёл отказ, первое исключение этой задачи выдаётся повторно. При этом исходная трассировка стека будет правильно сохранена.

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

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

Async Void
Что если имеется метод async void и требуется обработать исключения, распространённые из этого метода.

Хорошего решения не существует. Если возможно, измените метод так, чтобы он возвращал Task вместо void. Если вам требуется использовать метод async void, рассмотрите возможность упаковки всего кода метода в блок try/catch.

Существует и другой возможный способ. Когда метод async void распространяет исключение, это исключение выдаётся в контексте SynchronizationContext, активном на момент начала выполнения метода async void. Если среда выполнения предоставляет SynchronizationContext, то обычно она предоставляет механизм обработки этих высокоуровневых исключений на глобальном уровне. Например, WPF предоставляет Application.DispatcherUnhandledException, а ASP.NETUseExceptionHandler.

Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 2.
День 1013. #ЧтоНовенького
Новые Способы Организовать Вкладки в VS 2022
В Visual Studio 2022 появилась возможность раскрашивать вкладки по проектам, чтобы было легче ориентироваться в открытых файлах. Для этого перейдите в Tools > Options > Tabs & Windows (Инструменты > Параметры > Вкладки и Окна) и выберите Colorize tabs (Раскрасить вкладки). Есть возможность раскрашивать по проектам и скоро появится возможность раскрашивать по типам файлов.

Вертикальные вкладки
Чтобы включить эту функцию, щёлкните правой кнопкой мыши любую вкладку и выберите Set Tab Layout > Place Tabs on the Left (Расположение Вкладок > Разместить Слева).

Гибкая настройка
Также добавили параметры, чтобы выделить активную вкладку жирным шрифтом, изменить максимальную/минимальную ширину вкладки и добавить дополнительную кнопку закрытия вверху документа. Это также можно сделать в Tools > Options > Tabs & Windows (Инструменты > Параметры > Вкладки и Окна).

Источник: https://devblogs.microsoft.com/visualstudio/personalize-docs/
День 1014. #ЧтоНовенького
.NET 6
Вчера состоялся релиз .NET 6. На канале уже было (и ещё будет) много постов про новинки. Здесь будет некоторое саммари. А в 19 по Москве стартует .NET Conf 2021, посвящённая .NET 6.

Основные нововведения в .NET 6:
- Эта версия .NET с долгосрочной поддержкой (LTS) – 3 года.
- Унифицированная платформа для браузера, облака, настольных компьютеров, Интернета вещей и мобильных приложений, использующих одни и те же библиотеки .NET и возможность легко обмениваться кодом.
- Производительность значительно улучшена по всем направлениям и, в частности, для файлового ввода-вывода.
- C# 10 предлагает улучшения языка, такие как записи-структуры, новые асинхронные методы, неявные директивы using, новые возможности LINQ и коллекций. В компилятор добавлены новые генераторы кода.
- Горячая перезагрузка позволяет пропустить пересборку и перезапуск приложения. Просмотр изменений возможен во время работы приложения. Поддерживается в Visual Studio 2022 и из .NET CLI для C# и Visual Basic.
- Облачная диагностика была улучшена с помощью OpenTelemetry и dotnet monitor, которые теперь поддерживаются в производственной среде и доступны в сервисе приложений Azure.
- API JSON более функциональны и имеют более высокую производительность с использованием генераторов кода для сериализатора.
- Минималистические API представлены в ASP.NET Core, чтобы упростить начало работы и повысить производительность сервисов HTTP.
- Компоненты Blazor можно динамически отрисовать из JavaScript и интегрировать в существующие приложения на основе JavaScript.
- Появилась AOT-компиляция WebAssembly для приложений Blazor WebAssembly (Wasm), а также поддержка повторного связывания времени выполнения и нативных зависимостей.
- Одностраничные приложения, созданные с помощью ASP.NET Core, теперь используют более гибкий шаблон, который можно использовать с Angular, React и другими популярными JavaScript фреймворками.
- Добавлена поддержка HTTP/3, чтобы ASP.NET Core, HttpClient и gRPC могли взаимодействовать с клиентами и серверами через HTTP/3.
- File IO теперь поддерживает символические ссылки и значительно улучшил производительность благодаря переписанному с нуля FileStream.
- Безопасность улучшена за счёт поддержки OpenSSL 3, схемы шифрования ChaCha20Poly1305 и средств глубокой защиты во время выполнения.
- Однофайловые приложения можно публиковать для Linux, macOS и Windows (ранее только для Linux).
- Тримминг IL теперь более функционален и эффективен с новыми предупреждениями и анализаторами для обеспечения правильных конечных результатов.
- Были добавлены генераторы и анализаторы кода, которые помогают создавать лучший, безопасный и производительный код.

Более подробно обо всех нововведениях и улучшениях см. в источнике ниже.

Источник: https://devblogs.microsoft.com/dotnet/announcing-net-6/
День 1015. #Карьера
Как Среднему Программисту Опережать Конкурентов
Код – это не вся моя жизнь. Я также не являюсь экспертом в структурах данных и алгоритмах. По сравнению с талантами в индустрии ПО я считаю себя средним программистом. Однако даже со средними навыками я никогда не прекращал расти. Быть средним программистом само по себе не мешает карьерному росту. Вы можете перерасти своих конкурентов, если будете готовы приложить усилия в правильном направлении.

1. Изучите домен компании
Хард скилы необходимы, чтобы быть разработчиком. Как средний программист, вы уже лучше многих. Всё, что нужно сделать, это добавить функциональные знания к своему инвентарю навыков. Интересуйтесь бизнес-целями каждого куска кода, который пишете. Знание примеров реального использования помогает писать наиболее простой код, отвечающий требованиям. Приложите максимум усилий для получения комплексных знаний о бизнес-логике.
Этого легко добиться, если вы работаете над приложением с первых дней. Если же вы присоединились к проекту по ходу, множество нюансов предметной области приходится изучать самостоятельно. База данных - лучшее место для начала (поскольку это наименее изменяющаяся часть). Следующим шагом будет понимание роли, которую данные играют в приложении и для компании. Вы будете поражены количеством бизнес-задач, которые можно эффективно решить, если вы знаете, что представляют собой функциональные сущности.

2. Постепенно укрепляйте уверенность
Уверенность в себе творит чудеса. Обучение, выполнение заданий, создание чего-то нового – всё это поможет вам укрепить веру в свои способности. Продолжайте искать возможности правильно использовать своё время.
Вам понадобится немного уверенности в себе, чтобы мотивировать вас, когда вы чувствуете себя плохо. Оно убедит вас в том, что вы можете делать всё, что вам нравится. Пет-проекты могут помочь вам отвлечься, когда работа в офисе становится слишком однообразной.

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

4. Предлагайте решения, а не просто озвучивайте проблемы
Ваше отношение к вызовам окажет гораздо более значительное влияние на ваш карьерный рост, чем навыки программирования. Люди ценят вовлечённость. Средний программист, преданный делу, может быть ценнее, чем отличный программист, который повсюду видит проблемы. Работая в команде, вы обязательно столкнётесь с проблемами: неэффективные рабочие процессы, коллеги, которые не выкладываются на полную, и т.п. Сосредоточьтесь на решении проблем, а не просто озвучивайте их. Однако имейте в виду, что, даже если есть разумные решения, не все проблемы можно решить в одночасье. Следовательно, разработчику нужно иметь много терпения, чтобы иметь дело с неэффективными людьми и процессами.

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

Источник: https://betterprogramming.pub/how-to-stay-ahead-of-the-competition-as-an-average-programmer-f76853677490
Автор оригинала: Lokajit Tikayatray
День 1016. #ЗаметкиНаПолях
Основы DDD с Помощью Пиццы
Предметно-ориентированное проектирование (Domain Driven Design) не предоставляет практических способов реализации архитектуры ПО, но фокусируется на нескольких основных принципах, которые могут помочь в создании поддерживаемого ПО. Чтобы понять эти концепции, мы возьмем реальный пример пиццерии. Для начала рассмотрим несколько терминов.

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

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

Модели
Строительные блоки домена. Различные части, которые объединяются для решения проблемы. В нашем случае это люди в их различных ролях, ингредиенты, пицца, мебель, машины и т.д.

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

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

Принципы DDD
1. ПО моделируется вокруг бизнес домена
Бизнес домен является основой всех архитектурных решений. Бизнес-модели и программные компоненты должны быть сопоставлены друг с другом. Независимо от того, используется ли термин разработчиком или руководителем компании, он должен означать одно и то же. Окончательная версия ПО - это отражение того, как работает бизнес.
Если владелец магазина использует термины маленькая, средняя и большая, рекомендуется, чтобы кассир использовал те же термины вместо размера пиццы в сантиметрах. Это упрощает понимание разговора для обеих сторон.

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

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

Преимущества DDD
1. Облегчает общение – все разговоры ведутся экспертами в предметной области.
2. Повышает гибкость – возможность каждой подсистеме развиваться независимо.
3. Снижает недопонимание за счет использования единых формулировок и терминов.
4. Улучшает координацию в команде из-за сужения областей контекстов.
5. Способствует появлению более чистой архитектуры, поскольку разделение задач снижает риск раздувания программных компонентов.

DDD не следует использовать, когда:
1. Не ожидается быстрого роста системы.
2. Первоначальная стоимость должна быть низкой.
3. Время на разработку ограничено.

Источник: https://dev.to/abh1navv/understanding-domain-driven-design-with-some-pizza-4gkn
День 1017. #ЧтоНовенького
Изменения в Структурах в C# 10
C# 10 представляет функции для структур, которые обеспечивают лучшее соответствие структур и классов.

Конструкторы без параметров и инициализаторы полей
До C# 10 каждая структура имела неявный общедоступный конструктор без параметров, который устанавливал для полей структуры значения по умолчанию. Создание конструктора без параметров для структуры было ошибкой.

Теперь вы можете добавлять конструкторы структур без параметров. Они должны быть публичными и не могут быть частичными. Если вы его не добавите, будет предоставлен неявный конструктор без параметров, устанавливающий для всех полей значения по умолчанию.
public struct Address {
public Address() {
City = "<unknown>";
}
public string City { get; init; }
}

Можно инициализировать поля в конструкторе без параметров, как выше, либо через инициализаторы полей или свойств:
public struct Address {
public string City { get; init; } = "<unknown>";
}

Структуры, созданные через ключевое слово default или при определении массива, игнорируют явные конструкторы без параметров и всегда устанавливают для членов значения по умолчанию.

Структуры-записи
Начиная с C# 10, записи можно определять как структуры:
public record struct Person
{
public string FirstName { get; init; }
public string LastName { get; init; }
}
Вы можете продолжить определять записи как классы либо просто по слову record, либо через record class для ясности.

Структуры и так сравниваются по значению. Структуры-записи добавляют поддержку IEquatable<T> и оператор ==, а также включают переопределение ToString().

Также поддерживается позиционная запись:
public record struct Person (string FirstName, string LastName);

Параметры первичного конструктора становятся публичными свойствами структуры-записи. В отличие от классов-записей, неявно созданные свойства доступны для чтения и записи.

Это упрощает преобразование кортежей в именованные типы. Изменение типов возвращаемых значений с кортежа, вроде (string FirstName, string LastName), на именованный тип Person, может очистить ваш код и гарантировать согласованные имена членов.

Чтобы создать неизменяемую структуру записи, добавьте readonly в определение структуры или отдельных свойств. Инициализаторы объектов являются частью этапа построения, на котором можно установить свойства только для чтения, поэтому следующая инициализация сработает и для readonly-структур:
var person = new Person { FirstName = "Mads", LastName = "Torgersen"};

Модификатор sealed для ToString() в классах-записях
Теперь метод ToString() может включать модификатор sealed, который не позволит его переопределять в производных типах записей.

Выражение with в структурах и анонимных типах
C# 10 поддерживает выражение with для всех структур, включая структуры-записи, а также для анонимных типов:
var person2 = person with {LastName = "Kristensen"};

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

Источник: https://devblogs.microsoft.com/dotnet/welcome-to-csharp-10/
День 1018. #ProjectManagement
Почему Надо Выбирать Простую Веб-архитектуру
Координация команды разработчиков — тяжелая работа! Когда команда предлагает вам варианты, не всегда легко понять, что выбрать и почему.

Почему стоит выбрать более простой вариант?
1. Экономия.
ПО требует денег на создание, улучшение и поддержку. Решения влияют на бюджет в долгосрочной перспективе. Чем сложнее веб-архитектура, тем больше нужно будет потратить в долгосрочной перспективе на запуск продукта, обеспечение безопасности и улучшения.
2. Обслуживаемость. У руководителей много различных забот и мало времени. Менее сложное ПО будет легче поддерживать в будущем, что сэкономит время и нервы.
3. Доступность. Более сложные архитектуры, такие как одностраничные приложения, могут быть менее доступны по умолчанию и требуют дополнительной работы для обеспечения доступности.
4. Производительность. Приложения, использующие сложные веб-архитектуры, зачастую дольше загружают даже относительно простые данные.

Более простой подход означает:
- Меньше уровней технологий
- Использование стабильных технологий вместо передовых
- По возможности меньше сложности

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

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

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

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

4. Если требуется сложная интерактивность на стороне клиента, может потребоваться одностраничное приложение (single-page application)
React, Angular, Vue.js или Blazor - все эти фреймворки используют JavaScript в браузере для предоставления пользователям функциональных возможностей. Для них часто требуются два набора приложений: на стороне клиента для интерактивности и на стороне сервера для доставки и хранения данных.
Когда это хороший выбор: одностраничные приложения предполагают компромиссы. Из-за нескольких уровней технологий их создание может быть более дорогостоящим и сложным в обслуживании. Часто требуется дополнительная работа, чтобы сделать приложение доступным. Безопасность может быть более сложной задачей. Одностраничные приложения могут быть правильным выбором, когда вы и ваша команда взвесили эти компромиссы и определили, что для предоставления основных функций приложения необходима интенсивная интерактивность на стороне клиента, автономность или отображение данных из публичного API.

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

Источник: https://18f.gsa.gov/2021/04/05/why_simplicity_choosing_a_web_architecture/