День семьсот девяностый. #ЗаметкиНаПолях
Мои любимые ошибки с IDisposable. 2/3
Начало
3. Проблемы using и yield
Давайте возьмём простой пример и воспользуемся
https://dotnetfiddle.net/WwiN0r
Когда мы выполняем этот код, мы получаем ожидаемый результат:
https://dotnetfiddle.net/sfF1Au
Теперь результат довольно странный:
Мы просто добавили
Главное отличие здесь в том, что мы перешли от немедленного оценивания выражения к ленивому, и это изменило реальный порядок действий: мы покинули блок
Эта ошибка замечательна, потому что
Этот вид ошибки также может быть создан с помощью
Окончание следует…
Источник: 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. Чрезмерная очистка
Во многих случаях мы передаём экземпляр
Совет на этот случай: если вы вызываете
Рассмотрим эту функцию:
Эта ошибка также может быть выражена объектно-ориентированным образом, и отладка становится ещё более мутной, когда мы получаем наш
Помимо вводящих в заблуждение исключений, действительно делает эту ошибку замечательной то, что она возникает, когда мы прилагаем дополнительные усилия, пытаясь поступить правильно. Моей внутренней реакцией на это будет раздражение и пассивно-агрессивное отношение к программе:
«Мне очень жаль, что я пытался очистить неуправляемые ресурсы, и это привело к ошибке. Я больше никогда так не буду делать.»
Итого
На первый взгляд
- почаще читая документацию,
- подключая анализаторы кода для отслеживания вещей, которые компилятор не может уловить,
- следуя политике очистки, в которой тот, кто вызвал
Источник: 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
Вы можете вывести список всех известных уязвимостей в зависимостях ваших проектов и решений с помощью команды
Чтобы найти уязвимости в своих проектах, загрузите .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/
Как Просканировать 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. Пространства имён на уровне файла
Пространства имён – удобная вещь для логического разделения ваших классов. Единственный их недостаток – лишний уровень отступов и лишние фигурные скобки вокруг их содержимого. Предлагается объявлять пространство имён в начале файла, чтобы оно действовало на весь файл.
Небольшое изменение, но иногда от таких мелких улучшений больше всего пользы.
2. Обобщённые атрибуты
Этому предложению уже несколько лет, но, похоже, сейчас за него решили-таки взяться. И действительно, IL позволяет их использовать, почему бы не добавить эту функциональность в C#. Например, вместо:
Обычно использовать строковые литералы в коде, особенно длинные, - довольно муторное занятие. Нужно экранировать все кавычки, слеши и переводы строки. дословные (verbatim) строки серьёзно упростили жизнь при использовании URL или регулярных выражений, но всё равно приходится экранировать кавычки, которые в некоторых случаях, например, в коде XML или JSON, используются довольно часто.
Необработанные (raw) строки предлагают вам использовать строковые литералы «как есть». Они используют новый маркер начала и конца строки – несколько кавычек и новая строка в начале, новая строка и столько же кавычек в конце. Между ними просто вставляйте блок текста, который будет трактоваться как одна строка. Проще показать на примере:
Так же, как и с дословными строками, все пробелы и разбиение на строки сохраняются. Необработанные строки не призваны заместить собой дословные строки. Они просто будут ещё одним вариантом использования, когда вам нужно вставить блок кода в строку, как есть, и не переживать по поводу форматирования его.
Источник: https://medium.com/young-coder/c-10-3-candidate-features-that-could-make-the-final-cut-3b46f4a62284
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
97 Вещей, Которые Должен Знать Каждый Программист
83. Тестирование – Это Строгость в Разработке Программного Обеспечения
И снова о тестировании.
Разработчики обожают использовать сложные метафоры, пытаясь объяснить, что они делают, членам семьи, супругам и просто гуманитариям. Мы часто используем в качестве примера строительство мостов и другие реальные инженерные конструкции. Однако все эти метафоры быстро рушатся, если вы заходите слишком далеко в объяснения. Оказывается, разработка программного обеспечения не похожа на разработку реальных объектов во многих важных аспектах.
Разработку ПО можно было бы сравнить со сложной инженерией, только если бы стратегия строительства моста заключалась в том, чтобы построить мост, а затем пустить по нему тяжёлую технику. Если мост выдержит, это хороший мост. Если нет, то… возвращаемся к чертежам. За последние несколько тысяч лет инженеры далеко продвинулись в математике и физике, которые они могут использовать для создания рабочего решения, без необходимости строить что-то вслепую и проверять это на практике. В программировании нет ничего подобного и, возможно, никогда не будет, потому что программирование на самом деле сильно отличается от создания чего-то материального.
Тестировать материальные вещи сложно, потому что нужно физически построить то, что вы хотите протестировать. Не очень заманчиво строить что-то только для того, чтобы посмотреть, что произойдет. Но процесс создания программного обеспечения обходится значительно дешевле. Мы разработали целую экосистему инструментов, которые упрощают это: модульное тестирование, mock-объекты, платформы для тестирования и многое другое. Инженеры из других областей могут только мечтать иметь возможность что-то построить и протестировать в реальных условиях. Как разработчики ПО, мы должны рассматривать тестирование как основной (но не единственный) механизм проверки программного обеспечения. Вместо того, чтобы производить какие-то предварительные расчёты поведения программы, в нашем распоряжении уже есть инструменты для реализации лучших практик разработки. То есть у нас есть противоядие против менеджеров, которые говорят: «У нас нет времени на тестирование». Строитель моста никогда не услышит от своего начальника: «Не беспокойтесь о проведении структурного анализа этого объекта - у нас очень сжатые сроки». Признание того, что тестирование - это действительно путь к воспроизводимости и качеству программного обеспечения, позволяет нам, разработчикам, отвергать аргументы против тестирования, как непрофессиональные и безответственные.
Тестирование требует времени, как и структурный анализ. Оба вида деятельности обеспечивают качество конечного продукта. Разработчикам программного обеспечения пора взять на себя ответственность за то, что они производят. Одного тестирования недостаточно, но оно необходимо.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Neal Ford
День семьсот девяносто шестой. #ЗаметкиНаПолях #SQL
Ограничение Результатов с Помощью Оконных Функций
Оконные (window) аналитические функции давно присутствуют в SQL, однако многие до сих пор не умеют их применять.
Окно (window) - это набор строк таблицы, которые можно анализировать или применить к ним функцию. Строки должны быть как-то связаны. Иногда они связаны с конкретной строкой, т.е. строки могут быть выше или ниже друг друга или в пределах заданного диапазона. Либо связь может быть основана на отдельных группах данных в наборе.
Все оконные функции следуют определенному синтаксису.
- Выражение
- Выражение
В качестве оконных можно использовать простые агрегатные функции, вроде
Номера и ранг строк
Простейший вариант применения оконной функции – вывести номера строк результата (см. пример 1 на картинке ниже). Здесь «окном» является весь набор, а функция
Мы можем разделить набор данных на группы, используя
Кроме этого две функции
Заметьте, что выражение
Первое и последнее значение
Эти функции позволяют вывести первое или последнее соответственно значение столбца в группе. В отличие от функций, описанных выше, для каждой группы будет выведена только одна строка. Например, если использовать
Предыдущие и последующие строки
Часто бывает полезно сравнивать строки с предыдущими или последующими, особенно если данные упорядочены (например, хронологически). Для этого используются функции
Источник: https://app.pluralsight.com/library/courses/combining-filtering-data-postgresql
Ограничение Результатов с Помощью Оконных Функций
Оконные (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. Вывести конфигурацию
2. Изменить ваше имя пользователя
4. Создать репозиторий
5. Добавить файл в staging
8. Commit
9. Commit с сообщением
13. Удаление ветки
14. Переключение между ветками
Пункты 12 и 14 можно объединить в одну команду:
20. Получение временно сохранённых изменений
Источник: https://www.c-sharpcorner.com/article/20-git-commands-you-should-know/
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_file6. Добавить все файлы в staging
git add .7. Проверить статус
git statusЭта команда покажет статус текущего репозитория, включая текущую ветку, и файлы как в staging, так и не добавленные туда.
8. Commit
git commitЭта команда создаст коммит. В этом варианте откроется текстовый редактор, куда вам нужно будет записать сообщение коммита.
9. Commit с сообщением
git commit -m "Ваше сообщение"10. Просмотр истории
git log11. Список веток
git branch12. Создание ветки
git branch my_branchЗаметьте, что Git не переключится на эту ветку автоматом. Для этого см. пункт 14.
13. Удаление ветки
git branch -d my_branchОбратите внимание на флаг
-d
.14. Переключение между ветками
git checkout my_branch15. Создание ветки и переключение на неё
Пункты 12 и 14 можно объединить в одну команду:
git checkout -b branch_name16. Добавление удалённого репозитория
git add remote https://repo_url17. Публикация в удалённый репозиторий
git push18. Обновление из удалённого репозитория
git pull19. Временное сохранение изменений
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 – пакет для объединения различных типов в один тип
4. Microsoft.Extensions.Http.Polly – Polly на канале уже тоже упоминался, и не раз. Это, насколько я понимаю, версия от Mirosoft, доступная в .NET 5.
Вторая часть https://youtu.be/NPAK94ZCxD4 посвящена тестированию. И помимо обычных модульных тестов Ник описывает приёмочное (acceptance) тестирование: близкое к человеческому языку описание теста, которое парсится в коде и проверяется автоматически. «Ничего не понятно, но очень интересно»))) Кстати, подробно о приёмочном тестировании есть и третье видео https://youtu.be/qWEDkHGNhvk
Сегодня предложу вам к просмотру ещё один минисериал от 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
Командная строка используется всё чаще для запуска сценариев, сборки и других задач, вроде
Вы можете это сделать с помощью команды Measure-Command:
Как Измерить Время Исполнения Программ в 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. Отладка: выявление, исправление и удаление ошибок после их обнаружения.
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/
Как Улучшить Свои Навыки Отладки. Окончание
Начало
Что такое отладка?
Отладка лежит в основе программирования, и при кодировании она занимает большую часть вашего времени. Отладка включает три основных этапа:
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
2) В классе Dictionary, когда происходит поиск по ключу. Какая сложность? А в List при вызове FirstOrDefault()?
В
Подробнее
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() какого типа поток?
Совсем не понял вопроса. Начнём с того, что нет метода
8) Task.Run(t => File.ReadAll()) и File.ReadAllAsync() это эквивалентные вызовы? Объясните.
Отвлечёмся от того, что снова указаны несуществующие методы. Здесь, если выполнить так, как написано, то, насколько я понимаю,
9) Есть строковая переменная, в ней написано название типа, я хочу создать объект этого типа. Как мне это сделать? Корректировка: Тип ты не знаешь в Compile Time.
Использовать
Как вам вопросы? Что скажете о моих ответах? Стоит ли продолжать выпускать такие посты?
Попробую новый вид постов на тему вопросов на собеседовании. Подписчик прислал набор вопросов, которые ему недавно задали на собеседовании и попросил оценить. Попробую сам ответить и прокомментировать, а также жду комментариев от вас. Как по поводу ответов, так и по поводу, как вам вопросы и как вообще такой формат.
Поехали!
Дисклеймер: вопросы буду приводить в том виде, как они мне были присланы. Я постараюсь не гуглить правильные ответы, а приведу свои мысли. Поэтому мои ответы не обязательно будут правильными. Если что, поправляйте в комментариях.
Внутренности .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.
Можно добавить в нужное место кода
А что насчёт Debugger.Break()?
Этот метод также использовался для начала отладки. Но, как говорится в документации Microsoft, начиная с .NET Framework 4, если не выбран отладчик, то не гарантируется, что метод
Если же отладчик уже подключен,
Когда Debugger.Launch не работает
В очень редких случаях
Этот код можно обернуть в конструкцию
Источник: https://dotnetcoretutorials.com/2021/04/03/i-wish-i-knew-about-debugger-launch-earlier/
Что такое 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
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 – это если решите посмотреть все конференции сезона 😉
DotNext 2021 — 20-23 апреля, онлайн.
4 дня, несколько десятков докладов и воркшопов от авторов популярных технологий и инструментов, живое общение со спикерами и коллегами и многое другое.
А еще возможность пообщаться со спикерами и коллегами в дискуссионных Zoom-комнатах, возможность вернуться к записям эфира и куча других кайфовых штук.
✅ Посмотреть всю программу и купить билет со скидкой можно на https://bit.ly/3dYUGJk
Промокод на Personal-Standard билет: netdevdiary2021JRGpc
Промокод на Full Pass билет: JugRuCommunityBonus – это если решите посмотреть все конференции сезона 😉
День восемьсот седьмой.
FluentValidation
Сегодня предлагаю вам посмотреть полезное видео - запись вебинара «OSS Power-Ups: FluentValidation». Это первый вебинар из серии Open-Source Power-Ups про популярные проекты с открытым исходным кодом в сообществе .NET.
FluentValidation - это библиотека для создания строго типизированных правил валидации, пользующаяся огромной популярностью и имеющая более 50 миллионов загрузок на NuGet. Джереми Скиннер, поддерживающий проект, поможет нам начать работу с некоторыми базовыми примерами, написанием пользовательских валидаторов, локализацией сообщений об ошибках и интеграцией валидации в ASP.NET Core.
FluentValidation
Сегодня предлагаю вам посмотреть полезное видео - запись вебинара «OSS Power-Ups: FluentValidation». Это первый вебинар из серии Open-Source Power-Ups про популярные проекты с открытым исходным кодом в сообществе .NET.
FluentValidation - это библиотека для создания строго типизированных правил валидации, пользующаяся огромной популярностью и имеющая более 50 миллионов загрузок на NuGet. Джереми Скиннер, поддерживающий проект, поможет нам начать работу с некоторыми базовыми примерами, написанием пользовательских валидаторов, локализацией сообщений об ошибках и интеграцией валидации в ASP.NET Core.
YouTube
OSS Power-Ups: FluentValidation
This is the start of our series of OSS Power-Ups, where we want to put a spotlight on open-source .NET projects. FluentValidation is a library for building strongly-typed validation rules, with amazing popularity, and over 50 million downloads on NuGet. Jeremy…
День восемьсот восьмой. #ЗаметкиНаПолях
Как Посмотреть Параметры Конфигурации в ASP.NET
Существует простой способ раскрыть конфигурацию приложения как конечную точку в вашем приложении ASP.NET Core.
Рассмотрим пример «стандартного» вывода метода GetDebugView():
1. Параметры конфигурации выдаются в алфавитном порядке ключей.
2. Формат строки:
- Ключ
- Ключ
3. Строка отформатирована по разделам, что видно по ключу
4. Прочие провайдеры конфигурации:
-
-
-
Заметьте, что значения одного провайдера могут переписывать значения другого (например, значения из
Применение
Информация, предоставляемая
Один из очевидных подходов - предоставить конечную точку в приложении ASP.NET Core, где вы можете запросить это представление. В следующем примере использован метод
Как Посмотреть Параметры Конфигурации в ASP.NET
Существует простой способ раскрыть конфигурацию приложения как конечную точку в вашем приложении ASP.NET Core.
GetDebugView()
- это метод расширения IConfigurationRoot
, который возвращает строку, описывающую конфигурацию приложения. В этой строке отображаются все ключи конфигурации в вашем приложении, связанное значение и источник значения.Рассмотрим пример «стандартного» вывода метода GetDebugView():
AllowedHosts=* (JsonConfigurationProvider for 'appsettings.json' (Optional))Некоторые особенности вывода:
applicationName=temp (Microsoft.Extensions.Configuration.ChainedConfigurationProvider)
ASPNETCORE_ENVIRONMENT=Development (EnvironmentVariablesConfigurationProvider)
ASPNETCORE_URLS=https://localhost:5001;https://localhost:5000 (EnvironmentVariablesConfigurationProvider)
Logging:
LogLevel:
Default=Information (JsonConfigurationProvider for 'appsettings.json' (Optional))
MySecretValue=TOPSECRET (JsonConfigurationProvider for 'secrets.json' (Optional))
…
1. Параметры конфигурации выдаются в алфавитном порядке ключей.
2. Формат строки:
Ключ=значение (источник значения)Например:
- Ключ
AllowedHosts
имеет значение *
и предоставлен из файла appsettings.json
провайдером JsonConfigurationProvider
.- Ключ
MySecretValue
имеет значение TOPSECRET
и предоставлен из файла пользовательских секретов secrets.json
.3. Строка отформатирована по разделам, что видно по ключу
Logging
, содержащему раздел LogLevel
, в котором находится ключ Default
.4. Прочие провайдеры конфигурации:
-
ChainedConfigurationProvider
– первоначальные значения конфигурации, задаются хостом,-
EnvironmentVariablesConfigurationProvider
– переменные среды,-
CommandLineConfigurationProvider
– параметры командной строки.Заметьте, что значения одного провайдера могут переписывать значения другого (например, значения из
appsettings.json
заменяются значениями из секретных данных или переменных среды). В выводе GetDebugView()
будет присутствовать только конечное значение.Применение
Информация, предоставляемая
GetDebugView()
, может быть очень полезной, когда вам нужно отладить проблему конфигурации в вашем приложении. Возможность точно увидеть, откуда берется значение конфигурации, крайне важно, когда что-то работает не так, как вы ожидаете.Один из очевидных подходов - предоставить конечную точку в приложении ASP.NET Core, где вы можете запросить это представление. В следующем примере использован метод
MapGet
для предоставления простой конечной точки:app.UseEndpoints(endpoints => {Источник: https://andrewlock.net/debugging-configuration-values-in-aspnetcore/
if(env.IsDevelopment()) {
endpoints.MapGet("/debug-config", ctx => {
var config =
(Configuration as IConfigurationRoot)
.GetDebugView();
return ctx.Response.WriteAsync(config);
});
}
});