.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
День семьсот восемьдесят восьмой. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
82. Тестируйте во Сне и в Выходные
Расслабьтесь. Я не говорю о рабском труде или даже о сверхурочной работе по выходным или ночью. Скорее, я хочу обратить ваше внимание на то, сколько вычислительных мощностей имеется в вашем распоряжении. В частности, как много всего мы не используем, чтобы немного облегчить свою программистскую жизнь. Вам постоянно не хватает времени или вычислительных ресурсов в течение рабочего дня? Если да, то почему бы не запускать тесты в нерабочее время?

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

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

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

Слишком много вариантов для проверки вручную? Во многих случаях ваш продукт предназначен для работы на различных платформах. Например, как в 32-, так и в 64-битных системах Linux, MacOS или Windows, или просто в разных версиях одной и той же операционной системы. Что ещё хуже, многие современные приложения используют множество различных транспортных механизмов и протоколов (HTTP, gRPC, SOAP и т.п.). Ручное тестирование всех этих вариантов занимает очень много времени и, скорее всего, выполняется незадолго до выпуска продукта из-за нехватки ресурсов. Увы, это может быть слишком поздно, чтобы отловить и исправить некоторые неприятные ошибки. Автоматизированные тесты, выполняемые в ночное время или в выходные дни, гарантируют, что все эти варианты будут проверяться чаще. Немного разобравшись в сценариях, вы можете запланировать несколько назначенных заданий, чтобы начать тестирование ночью и на выходных. Есть также много инструментов для тестирования, которые могут помочь. Некоторые организации создают матрицы серверов, объединяющие сервера различных отделов и команд в общий пул для более эффективного их использования. Если это доступно в вашей организации, вы можете отправлять туда наборы тестов для выполнения ночью или в выходные дни.

Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Rajith Attapattu
День семьсот восемьдесят девятый. #ЗаметкиНаПолях
Мои любимые ошибки с IDisposable. 1/3
System.IDisposable - фундаментальный интерфейс, используемый в большинстве программ .NET. Его основная цель - предоставить механизм для высвобождения «неуправляемых» ресурсов: файловых потоков, подключений к базам данных, сетевых сокетов и т.д.
public interface IDisposable {
void Dispose();
}
Что может быть проще? Кроме того, для него есть специальный синтаксис - оператор using:
using(var stream=File.OpenText("…")) {
// неуправляемый ресурс stream
// живёт внутри этого блока
}
// здесь stream удаляется
Красиво и просто!

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

1. IDisposable вам врёт
Кажется, интерфейс легко реализовать: всего один метод void, и готово! Но IDisposable обманывает. К нему предъявляются некоторые требования, которые нельзя выразить посредством простого объявления интерфейса:
- взаимодействие со сборщиком мусора через финализаторы,
- взаимодействие с подклассами,
- обработка повторных вызовов Dispose.
Для решения всех этих проблем мы используем паттерн Dispose. Это настолько распространенная проблема, что IDE и статические анализаторы могут подсказывать вам, как правильно реализовать IDisposable.

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

К сожалению, это обычное дело. Например:
- В IEquatable<T>, вы также должны переопределить базовые реализации Equals(Object) и GetHashCode().
- В IComparable<T>, вы должны перегрузить op_GreaterThan, op_GreaterThanOrEqual и т.п.
- Класс, реализующий IFormattable, должен поддерживать формат «G» (общий)…

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

2. Разработчики IDisposable могут вам врать
Мы уже знаем, что нам нужно использовать шаблон Dispose для наших реализаций IDisposable. А что насчёт использования чужих реализаций? Например, правильно ли SqlConnection использует шаблон Dispose? У нас нет другого способа узнать это, кроме как читать документацию.

Самый большой нарушитель, с которым я столкнулся, - это HttpClient. Обычно мы хотим освободить наши неуправляемые ресурсы как можно скорее. Реализуя IDisposable, HttpClient посылает нам сигнал о том, что он хочет находиться в блоке using:
using(var client = new HttpClient()) {
// выполняем запрос
}
Но использование HttpClient таким образом всё испортит. В документации мы находим следующий перл:
HttpClient предназначен для однократного создания и повторного использования в течение всего жизненного цикла приложения. Создание экземпляра класса HttpClient для каждого запроса при больших нагрузках исчерпает количество доступных сокетов.

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

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

Источник:
https://www.lazy-electron.com/2021/03/06/favorite-idisposable-bugs.html
Автор оригинала - Ryan Davis
День семьсот девяностый. #ЗаметкиНаПолях
Мои любимые ошибки с IDisposable. 2/3
Начало

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

Давайте возьмём простой пример и воспользуемся Console.WriteLine, чтобы увидеть, как проявляется ошибка. Нам понадобится реализация IDisposable и несколько вспомогательных функций, чтобы реализовать неявный вызов. Сначала рассмотрим рабочий код:
https://dotnetfiddle.net/WwiN0r

Когда мы выполняем этот код, мы получаем ожидаемый результат:
start
connected
querying
dispose
result: 1
done

Все операции расположены в правильном порядке, и мы очищаем наши ресурсы сразу после использования. Заменим вывод метода Query в строке 17 на yield return:
https://dotnetfiddle.net/sfF1Au

Теперь результат довольно странный:
start
connected
dispose
querying
result: 1
done
Наш запрос выполняется ПОСЛЕ очистки ресурсов! Заметьте, что в реальном приложении вы получите ошибку при обращении к несуществующему ресурсу. Что происходит?

Мы просто добавили yield return, но компилятор «под капотом» проделал намного больше работы. Он создал класс с уникальным именем, реализующий IEnumerable<int>. Наш запрос к FakeResource возвращает экземпляр этого класса, но мы не выполняем собственно запроса, пока не начнёт исполняться цикл foreach. У Джона Скита есть отличный разбор всех внутренностей реализации. А подробнее про особенности выражения yield return, вы можете почитать на канале. Поищите посты по строке "Выражение yield return".

Главное отличие здесь в том, что мы перешли от немедленного оценивания выражения к ленивому, и это изменило реальный порядок действий: мы покинули блок using перед запуском нашего кода в Query(FakeResource).

Эта ошибка замечательна, потому что yield return и using могут быть в совершенно разных частях проекта. А чтобы столкнуться с этой ошибкой, нам достаточно хотя бы одного уровня косвенного доступа, и это довольно распространённое явление. При этом изменение на yield return само по себе выглядит невинно, и компилятор всем доволен.

Этот вид ошибки также может быть создан с помощью async и await; мы можем покинуть блок using, пока задача всё ещё хочет использовать наш IDisposable (см. этот пост).

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

Источник:
https://www.lazy-electron.com/2021/03/06/favorite-idisposable-bugs.html
Автор оригинала - Ryan Davis
День семьсот девяносто первый. #ЗаметкиНаПолях
Мои любимые ошибки с IDisposable. 3/3
Начало
Продолжение

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

Совет на этот случай: если вы вызываете new, вы должны вызывать и Dispose. Если вы не вызывали new, вы не обязаны вызывать Dispose.

Рассмотрим эту функцию:
void Save(IDbConnection conn) {
using(conn) {
//…
}
}
Разработчик пытается поступить правильно и очистить ресурсы после использования. Но теперь вызов Save имеет побочный эффект закрытия соединения. Это может привести к ошибке в другом месте:
using(var cn = new SqlConnection("…")) {
Save(cn);
Update(cn); // ошибка
}
Мы получим исключение в Update, потому что функция Save закрыла наше соединение. Эта ошибка может быть довольно коварной: исключение будет выброшено из Update, поэтому поиск ошибки начнётся не в том месте. В зависимости от размера кодовой базы может потребоваться много времени, чтобы обнаружить, что обновление завершается ошибкой только при вызове после сохранения. Эта ошибка может тихо жить в кодовой базе в течение многих лет и проявиться, когда кто-то добавит вызов Update.

Эта ошибка также может быть выражена объектно-ориентированным образом, и отладка становится ещё более мутной, когда мы получаем наш IDisposable через внедрение зависимости (DI):
public class Saver : IDisposable {
readonly IDbConnection _conn;

public Saver(IDbConnection conn) {
_conn = conn;
}
public void Save() {…}
public void Dispose() {
_conn.Dispose();
}
}
Опять же, разработчик пытается поступить правильно и очистить ресурсы после использования, но мы вводим неожиданные побочные эффекты в IDbConnection. Можно написать такой правильный код:
using(var cn = new SqlConnection("…")) {
using(var sv = new Saver(cn)) {
sv.Save();
}
using(var upd = new Updater(cn)) {
upd.Update(); // ошибка
}
}
И опять трассировка стека приведет нас в Update. А если здесь ещё использовать контейнер DI для внедрения IDbConnection, то найти связь между методами сохранения и обновления может быть почти невозможно.

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

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

Источник: https://www.lazy-electron.com/2021/03/06/favorite-idisposable-bugs.html
Автор оригинала - Ryan Davis
👍1
День семьсот девяносто второй. #юмор
День семьсот девяносто третий.
Как Просканировать NuGet Пакеты на Наличие Уязвимостей
Открытый исходный код есть везде. Для организаций и частных лиц вопрос сегодня не в том, используете ли вы открытый код или нет, а в том, какой открытый код вы используете и в каком объёме.

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

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

Что такое CVE/GHSA?
NuGet получает информацию об уязвимостях непосредственно из централизованной базы данных GitHub Advisory. База данных предоставляет два основных списка уязвимостей:
1. CVE (Common Vulnerabilities and Exposures) - список публично раскрытых общих уязвимостей и недостатков.
2. GHSA (GitHub Security Advisory) - это рекомендации по безопасности от GitHub. Подробности можно почитать тут.

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

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

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

dotnet CLI
Вы можете вывести список всех известных уязвимостей в зависимостях ваших проектов и решений с помощью команды
dotnet list package --vulnerable

Команда выдаст список уязвимостей в пакетах верхнего уровня, версию пакета, в которой она исправлена и ссылку на рекомендации. Если вы хотите увидеть уязвимости в дочерних пакетах, используйте параметр --include-transitive.

Чтобы найти уязвимости в своих проектах, загрузите .NET SDK 5.0.200, Visual Studio 2019 16.9 или Visual Studio 2019 для Mac 8.8, который включает .NET SDK.

Источник: https://devblogs.microsoft.com/nuget/how-to-scan-nuget-packages-for-security-vulnerabilities/
День семьсот девяносто четвёртый. #ЧтоНовенького #CSharp10
3 Потенциальных Новинки в C# 10
10я версия языка не за горами, пора потихоньку знакомиться с тем, что нас ждёт. Сразу дисклеймер: следующие функции пока только в списке на включение в новую версию языка, но не факт, что они появятся и именно в описанном виде.

1. Пространства имён на уровне файла
Пространства имён – удобная вещь для логического разделения ваших классов. Единственный их недостаток – лишний уровень отступов и лишние фигурные скобки вокруг их содержимого. Предлагается объявлять пространство имён в начале файла, чтобы оно действовало на весь файл.
namespace HelloWorld;
public class Hello {

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

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

2. Обобщённые атрибуты
Этому предложению уже несколько лет, но, похоже, сейчас за него решили-таки взяться. И действительно, IL позволяет их использовать, почему бы не добавить эту функциональность в C#. Например, вместо:
[TypeConverter(typeof(X))]
использовать
[TypeConverter<X>]

3. «Необработанные» строки
Обычно использовать строковые литералы в коде, особенно длинные, - довольно муторное занятие. Нужно экранировать все кавычки, слеши и переводы строки. дословные (verbatim) строки серьёзно упростили жизнь при использовании URL или регулярных выражений, но всё равно приходится экранировать кавычки, которые в некоторых случаях, например, в коде XML или JSON, используются довольно часто.

Необработанные (raw) строки предлагают вам использовать строковые литералы «как есть». Они используют новый маркер начала и конца строки – несколько кавычек и новая строка в начале, новая строка и столько же кавычек в конце. Между ними просто вставляйте блок текста, который будет трактоваться как одна строка. Проще показать на примере:
string xml = """
<part number="1976">
<name>Windscreen Wiper</name>
<description>The "Windscreen wiper" automatically removes rain from your windscreen. It has a rubber <ref part="1977">blade</ref>, which can be ordered separately.</description>
</part>
""";
Если вам нужно использовать в тексте тройные кавычки, можете обозначить начало и конец строки четырьмя кавычками и т.д.

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

Источник: https://medium.com/young-coder/c-10-3-candidate-features-that-could-make-the-final-cut-3b46f4a62284
День семьсот девяносто пятый. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
83. Тестирование – Это Строгость в Разработке Программного Обеспечения
И снова о тестировании.

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

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

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

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

Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Neal Ford
День семьсот девяносто шестой. #ЗаметкиНаПолях #SQL
Ограничение Результатов с Помощью Оконных Функций
Оконные (window) аналитические функции давно присутствуют в SQL, однако многие до сих пор не умеют их применять.

Окно (window) - это набор строк таблицы, которые можно анализировать или применить к ним функцию. Строки должны быть как-то связаны. Иногда они связаны с конкретной строкой, т.е. строки могут быть выше или ниже друг друга или в пределах заданного диапазона. Либо связь может быть основана на отдельных группах данных в наборе.

Все оконные функции следуют определенному синтаксису.
<название функции>(<выражение>) OVER (
<окно>
<сортировка>
)

Сначала идёт название функции, а за ним следует предложение OVER. Оно определяет область действия окна, указывая набор строк, к которым будет применяться функция. Предложение OVER является обязательной частью оконной функции. Остальной синтаксис является необязательным, и зависит от желаемой области действия:
- Выражение PARTITION BY можно использовать для разделения набора данных на отдельные группы (аналогично GROUP BY).
- Выражение ORDER BY используется для упорядочивания строк в каждой группе.

В качестве оконных можно использовать простые агрегатные функции, вроде SUM(), COUNT(), AVG() и т.п. Но есть и несколько специальных.

Номера и ранг строк
Простейший вариант применения оконной функции – вывести номера строк результата (см. пример 1 на картинке ниже). Здесь «окном» является весь набор, а функция ROW_NUMBER() выводит номер строки по порядку.
Мы можем разделить набор данных на группы, используя PARTITION BY. В примере 2 на картинке ниже тот же набор разделён по полю name, а внутри каждой такой группы упорядочен по полю course.

Кроме этого две функции RANK() и DENSE_RANK() выводят ранг строки. Они отличаются от ROW_NUMBER() тем, что при равенстве результатов задают строкам одинаковые значения. При этом DENSE_RANK() продолжает нумерацию, например, 1,1,2,2,3. А RANK() использует следующий номер строки по порядку, оставляя разрывы в нумерации: 1,1,3,3,5. В примере 3 на картинке ниже приводится сравнение этих функций на том же наборе данных. Здесь использована сортировка всего набора по полю name, без разбиения на группы.

Заметьте, что выражение ORDER BY внутри оконной функции никак не связано с выражением ORDER BY всего запроса. Оно влияет только на результаты оконной функции. В предыдущем примере мы могли бы добавить ORDER BY ко всему запросу и изменить порядок строк в запросе, но результаты функций ROW_NUMBER(), RANK() и DENSE_RANK() в строках не изменились бы.

Первое и последнее значение
Эти функции позволяют вывести первое или последнее соответственно значение столбца в группе. В отличие от функций, описанных выше, для каждой группы будет выведена только одна строка. Например, если использовать LAST_VALUE(course) на наборе данных из примера 2(последний по алфавиту курс для каждого студента), то будет выведено 3 строки:
Jason Economics
Lucy Health Science
Martha Biology
.

Предыдущие и последующие строки
Часто бывает полезно сравнивать строки с предыдущими или последующими, особенно если данные упорядочены (например, хронологически). Для этого используются функции LAG(), которая извлекает значения из предыдущих строк, и LEAD(), которая извлекает значения из последующих строк. В примере 4 на картинке ниже мы получаем значение суммы из предыдущего месяца с помощью функции LAG(sales,1). В функцию, помимо названия столбца, передаётся целое число, означающее количество строк, которые нужно отсчитать от текущей (в нашем случае 1). Для первой строки, очевидно, нет предыдущего значения, поэтому функция возвращает NULL.

Источник: https://app.pluralsight.com/library/courses/combining-filtering-data-postgresql
День семьсот девяносто седьмой. #Шпаргалка
20 Команд Git, Которые Надо Знать
Git был выпущен в 2005 году. Несмотря на то, что сейчас появилось много программ с графическим интерфейсом для управления репозиторием, труЪ программеры используют консоль. Поэтому ловите 20 наиболее полезных команд Git, которые понадобятся любому разработчику. Подробности о работе Git см. начиная с этого поста.

1. Вывести конфигурацию
git config -l
Эта команда отображает список информации о вашей конфигурации git, включая имя пользователя, адрес электронной почты, редактор кода по умолчанию и т.д.

2. Изменить ваше имя пользователя
git config --global user.name "<ваше имя>"

3. Изменить ваш email
git config --global user.email "[email protected]"

4. Создать репозиторий
git init
Эта команда инициализирует репозиторий в текущей папке.

5. Добавить файл в staging
git add my_file

6. Добавить все файлы в staging
git add .

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

8. Commit
git commit
Эта команда создаст коммит. В этом варианте откроется текстовый редактор, куда вам нужно будет записать сообщение коммита.

9. Commit с сообщением
git commit -m "Ваше сообщение"

10. Просмотр истории
git log

11. Список веток
git branch

12. Создание ветки
git branch my_branch
Заметьте, что Git не переключится на эту ветку автоматом. Для этого см. пункт 14.

13. Удаление ветки
git branch -d my_branch
Обратите внимание на флаг -d.

14. Переключение между ветками
git checkout my_branch

15. Создание ветки и переключение на неё
Пункты 12 и 14 можно объединить в одну команду:
git checkout -b branch_name

16. Добавление удалённого репозитория
git add remote https://repo_url

17. Публикация в удалённый репозиторий
git push

18. Обновление из удалённого репозитория
git pull

19. Временное сохранение изменений
git stash
Эта команда временно сохранит неподтверждённые изменения и вернёт ваш репозиторий в состояние последнего коммита.

20. Получение временно сохранённых изменений
git stash pop
Эта команда применит сохранённые ранее изменения обратно к вашему репозиторию.

Источник: https://www.c-sharpcorner.com/article/20-git-commands-you-should-know/
День семьсот девяносто восьмой. #юмор
Ооо, это про меня.
День семьсот девяносто девятый. #ЗадачиНаСобеседовании
Сегодня предложу вам к просмотру ещё один минисериал от Nick Chapsas на тему заданий на собеседовании. На этот раз Ник разбирает задачу интеграции API сервиса.

Смысл задачи в том, что вам дан REST API (в данном случае API сети ресторанов), вам нужно создать клиента этого API, отвечающего определённым требованиям.

Все подробности задачи Ник объясняет в видео, поэтому не буду их пересказывать.

В первой части https://youtu.be/_Pjjk4fOh8s довольно подробно описывается создание консольного клиента API. Что хотелось бы отметить из решения – это пакеты, которые Ник использует (помимо стандартных):
1. RefitClient – пакет, который создаёт код клиента API на основе интерфейса.
2. CommandLineParser – о нём я уже писал.
3. OneOf – пакет для объединения различных типов в один тип OneOf<T0,T1,…Tn>. Ник использует его для возврата из метода обобщённого объекта с результатом либо ошибкой. Вызывающий код может использовать методы Match() или Switch(), чтобы выполнять действия в зависимости от типа ответа. Не могу сказать, что мне нравится такой подход, но упоминания он заслуживает.
4. Microsoft.Extensions.Http.Polly – Polly на канале уже тоже упоминался, и не раз. Это, насколько я понимаю, версия от Mirosoft, доступная в .NET 5.

Вторая часть https://youtu.be/NPAK94ZCxD4 посвящена тестированию. И помимо обычных модульных тестов Ник описывает приёмочное (acceptance) тестирование: близкое к человеческому языку описание теста, которое парсится в коде и проверяется автоматически. «Ничего не понятно, но очень интересно»))) Кстати, подробно о приёмочном тестировании есть и третье видео https://youtu.be/qWEDkHGNhvk
День восьмисотый.
Как Измерить Время Исполнения Программ в PowerShell
Командная строка используется всё чаще для запуска сценариев, сборки и других задач, вроде docker и docker-compose. Когда вы запускаете команду, например, dotnet build или dotnet test, она обычно сообщает вам о том, сколько времени потребовалось для выполнения. Но когда у вас есть сценарий, состоящий из нескольких шагов, часто хочется проверить, сколько времени он выполняется. Чтобы оптимизировать его или сравнить время на разных машинах.

Вы можете это сделать с помощью команды Measure-Command:
Measure-Command { ./SomeScript.ps1 }

Она запустит скрипт и предоставит отчет о том, сколько времени он занял. Также можно запускать произвольные команды CLI:
Measure-Command { dotnet build }

Но по умолчанию вы не получаете никакого вывода от выполняемой команды. Чтобы видеть его, нужно добавить параметр вывода (см. картинку):
Measure-Command { dotnet build | Out-Default }

Источник: https://ardalis.com/measure-command-line-script-time-elapsed/
День восемьсот первый.
Как Улучшить Свои Навыки Отладки. Начало
Независимо от того новичок вы или опытный разработчик, время от времени в вашем коде появляются ошибки. Все мы иногда делаем ошибки. В конце концов, невозможно перестать быть человеком. Есть три основных способа борьбы с ошибками:
1. Пред-отладка: снижение вероятности возникновения ошибок.
2. Отладка: выявление, исправление и удаление ошибок после их обнаружения.
3. Пост-отладка: анализ исправленных ошибок и отслеживание непредвиденных ошибок.

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

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

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

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

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

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

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

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

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

Источник:
https://www.freecodecamp.org/news/how-to-improve-your-debugging-skills/
День восемьсот второй.
Как Улучшить Свои Навыки Отладки. Окончание
Начало

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

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

2. Анализ и понимание причин возникновения ошибки
После обнаружения ошибки нужно выяснить, почему код ведёт себя именно так. Это поможет вам построить более эффективную систему. Вместо этого многие разработчики просто гуглят и используют ответы со StackOverflow. Иногда этого достаточно, но лучше понять причину ошибки и почему найденное решение работает. Понимание причины ошибки - важный шаг на пути к её исправлению.

3. Исправление ошибки
После обнаружения и понимания причины ошибки мы должны исправить её. Иногда, если вы понимаете, в чём ошибка, вы быстро найдёте решение. Однако бывают случаи, когда даже понимание не даёт решения, как бы мы ни старались. Не тратьте слишком много времени на раздумья, поищите подходящее решение в интернете по коду или сообщению об ошибке или другому подходящему запросу. Также можно спросить коллегу, или задать вопрос на форуме, на StackOverflow, в чате, где-угодно (но только после того, как вы самостоятельно обдумали проблему!). Люди склонны видеть вещи по-разному, взгляд на проблему со стороны может помочь. Иногда даже само объяснение проблемы другому человеку помогает найти решение.

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

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

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

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

Источник: https://www.freecodecamp.org/news/how-to-improve-your-debugging-skills/
День восемьсот третий. #ВопросыНаСобеседовании
Попробую новый вид постов на тему вопросов на собеседовании. Подписчик прислал набор вопросов, которые ему недавно задали на собеседовании и попросил оценить. Попробую сам ответить и прокомментировать, а также жду комментариев от вас. Как по поводу ответов, так и по поводу, как вам вопросы и как вообще такой формат.

Поехали!

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

Внутренности .NET
1) Есть класс Object. У него определенны Equals и GetHashCode. Если вы переопределите Equals, но не переопределите GetHashCode для какого-нибудь класса, компилятор выдаст вам Warning. Почему?
Методы Equals и GetHashCode связаны в том смысле, что GetHashCode должен выдавать одинаковый результат у объектов, для которых Equals выдаёт true. Поэтому переопределение Equals скорее всего потребует и переопределения GetHashCode.
Подробнее об Equals
Подробнее о GetHashCode

2) В классе Dictionary, когда происходит поиск по ключу. Какая сложность? А в List при вызове FirstOrDefault()?
В Dictionary поиск по ключу происходит со сложностью O(1) из-за хеширования ключей. В List – первый элемент выберется за O(1), но если до этого будет поиск по индексу, то O(n).
Подробнее

3) Есть конструкция async/await. Как она работает? Когда добавляю async и await, что там меняется относительно того, если бы я не добавлял.
Создаётся конечный автомат для сохранения состояния. Все инструкции после строки с await добавляются в функцию продолжения, которая вызывается после завершения ожидания инструкции, следующей за await.
Подробнее

4) У меня была операция File.ReadAll(), я заменил ее на File.ReadAllAsync() какая из этих операций будет быстрее?
Странный вопрос, на мой взгляд, о сферическом быстродействии в вакууме. Тут столько неизвестных, что определённо ответить на этот вопрос просто невозможно. Скорее всего разницы в быстродействии не будет заметно, т.к. время на чтение файла будет на порядок превышать затраты на асинхронность.

5) Если синхронные методы работают быстрее чем асинхронные, зачем нам нужная асинхронная модель?
Опять какое-то теоретизирование о быстродействии синхронных и асинхронных методов. Быстродействие надо измерять в каждом конкретном случае. А вообще асинхронные методы используются для исключения блокировки UI потока, а также для операций, не использующих процессор, вроде чтения/записи файлов, обращения к БД или сетевых вызовов.

6) Есть I/O Bound потоки и CPU Bound потоки. Какая разница между ними?
Эти потоки различаются по типу нагрузки на ресурсы компьютера. I/O Bound поток больше нагружает диск (чтение/запись файлов), CPU Bound поток больше нагружает процессор (вычислительные операции).

7) File.ReadAllAsync() какого типа поток?
Совсем не понял вопроса. Начнём с того, что нет метода ReadAllAsync(), есть ReadAllBytesAsync(), возвращающий Task<byte[]>, и ReadAllTextAsync(), возвращающий Task<string>.

8) Task.Run(t => File.ReadAll()) и File.ReadAllAsync() это эквивалентные вызовы? Объясните.
Отвлечёмся от того, что снова указаны несуществующие методы. Здесь, если выполнить так, как написано, то, насколько я понимаю, Task.Run не возвратит результата.

9) Есть строковая переменная, в ней написано название типа, я хочу создать объект этого типа. Как мне это сделать? Корректировка: Тип ты не знаешь в Compile Time.
Использовать Activator.CreateInstance(). Подробности на память не помню, надо гуглить.

Как вам вопросы? Что скажете о моих ответах? Стоит ли продолжать выпускать такие посты?
👍4
День восемьсот четвёртый. #ЗаметкиНаПолях
Что такое Debugger.Launch?
Допустим, вы запускаете приложение (например, веб-приложение или службу Windows), в котором есть startup метод, который вы хотите отладить. Часто это может быть настройка внедрения зависимостей, раннее чтение файла конфигурации или что-то подобное. Допустим, вы не можете просто нажать F5 в Visual Studio и начать отладку. Вам нужно запустить приложение, а потом подключить отладчик. Для веб-приложений это иногда связано с тем, что вы используете IIS и переходите по URL-адресу своего приложения. А службу Windows, вы хотите отладить, когда она на самом деле исполняется как служба Windows.

Можно добавить в нужное место кода Thread.Sleep(10000); и попытаться подключить отладчик, в течение этого времени. Но гораздо проще это сделать с помощью:
System.Diagnostics.Debugger.Launch();

Тогда, если вы запустите приложение (не через отладку из Visual Studio), то, когда исполнение дойдёт до этой строчки, появится диалоговое окно, где вам будет предложено выбрать отладчик для этого приложения. Можно выбрать Visual Studio, и приложение откроется в режиме отладки.

А что насчёт Debugger.Break()?
Этот метод также использовался для начала отладки. Но, как говорится в документации Microsoft, начиная с .NET Framework 4, если не выбран отладчик, то не гарантируется, что метод Break приведёт к вызову окна выбора отладчика. Вместо этого в систему отчётов об ошибках Windows (WER) направляется сообщение об ошибке. Таким образом, документация советует для старта отладчика использовать Debugger.Launch.

Если же отладчик уже подключен, Debugger.Break заставляет код останавливать выполнение так же, как и точка останова. Так что в некотором смысле это похоже на точку останова, которую могут использовать разработчики на разных машинах вместо ручной инструкции: «Поместите точку останова в строку XX файла YYY…». Это может показаться не очень полезным, кроме случая, который мы рассмотрим далее.

Когда Debugger.Launch не работает
В очень редких случаях Debugger.Launch не предлагает пользователю отладить код. Либо требуется отладка в приложении, не представленном во всплывающем окне. Тогда есть простое решение:
// Ждём подключения отладчика.
while(!System.Diagnostics.Debugger.IsAttached)
{
Thread.Sleep(100); //либо Task.Delay()
}
System.Diagnostics.Debugger.Break();

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

#endif

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

Источник: https://dotnetcoretutorials.com/2021/04/03/i-wish-i-knew-about-debugger-launch-earlier/
День восемьсот пятый.
Microsoft Azure Virtual Training Day: DevOps with GitHub
Рекомендую посетить очередной бесплатный вебинар из серии Microsoft Azure Virtual Training Day. На нём расскажут, как использовать GitHub для управления рабочими процессами и сокращения цикла разработки. Пошаговые инструкции по добавлению элементов управления качеством и безопасностью в процесс сборки, а также по улучшению уведомлений и ответов для обеспечения согласованной и повторяемой автоматизации.

Темы мероприятия:
- Использование GitHub для улучшения совместной работы и производительности команды.
- Интеграция средств контроля безопасности и качества в конвейеры автоматизации, непрерывной интеграции и непрерывной доставки (CI/CD) и среды выполнения.
- Внедрение передовых методов, чтобы помочь удаленным командам разработчиков повысить отказоустойчивость программного обеспечения.

Вебинар пройдёт в 2 дня:
Среда, 21 апреля 2021, 11:00-13:55 Мск.
Четверг, 22 апреля 2021, 11:00-13:10 Мск.
Язык: Английский, доступны русские субтитры.

Регистрация по ссылке: https://mktoevents.com/microsoft+event/247969/157-gqe-382
День восемьсот шестой. #юмор
Большая техническая конференция о .NET-разработке начинается уже на следующей неделе.

DotNext 2021 — 20-23 апреля, онлайн.

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

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

Посмотреть всю программу и купить билет со скидкой можно на https://bit.ly/3dYUGJk

Промокод на Personal-Standard билет: netdevdiary2021JRGpc
Промокод на Full Pass билет: JugRuCommunityBonus – это если решите посмотреть все конференции сезона 😉