День восемьсот пятьдесят второй.
Новые Бесплатные Расширения для VS 2019. Начало 1-4
Пока мы ждём выхода новой Visual Studio 2022, большая часть .NET разработчиков используют VS 2019. Сегодня рассмотрим полезные бесплатные расширения для студии. Замечу, что под «новыми» здесь понимаются не только недавно вышедшие, но и недавно обновлённые инструменты.
1. Unit Test Boilerplate Generator от RandomEngy - это бесплатный инструмент со средней оценкой 4,8 из 5. Он поможет создать шаблон модульного теста для класса C#, с mock-объектами для всех зависимостей. Наряду с двумя режимами внедрения зависимостей и поддержкой инфраструктуры тестирования VS, он поддерживает NUnit и xUnit, а для mock-объектов поддерживаются: FakeItEasy, JustMock, Moq + AutoMoq, NSubstitute, Rhino Mocks и
SimpleStubs.
2. Fine Code Coverage от Fortune Ngwenya было скачано почти 18 тысяч раз, получив почти идеальную оценку 4,9. Оно помогает разработчикам визуализировать покрытие кода модульными тестами в .NET Core (.NET 5) и даже в старой .NET Framework. В частности, функция визуализации позволяет программистам:
- Помечать код, для которого есть тесты и для которого их нет
- Помечать тестирующий код
- Получать отчёты о покрытии кода тестами
- Получить отчёт о проблемах на горячих путях
Расширение последний раз было обновлено в конце марта, а последний коммит в репозитории проекта недельной давности, то есть автор старается поддерживать его в актуальном состоянии.
3. Run Coverlet Report от Chris Dexter - еще одна утилита для упрощения демонстрации покрытия кода, цель которой - бесплатно дублировать функциональность Visual Studio Enterprise (прости, Microsoft). Run Coverlet Report основан на превосходных инструментах Coverlet и Report Generator, которые позволяют собирать результаты покрытия кода из модульных тестов. Это расширение запускает оба этих инструмента, а затем отображает файл отчёта в Visual Studio, а также использует вывод Coverlet для подсветки синтаксиса. Coverlet, поддерживаемый .NET Foundation, - это проект с открытым исходным кодом, обеспечивающий кроссплатформенную систему анализа покрытия кода для C#. Report Generator преобразует отчёты о покрытии кода, созданные Visual Studio и многими другими инструментами, в удобочитаемые отчёты в различных форматах. Ещё один инструмент с идеальными 5 из 5.
4. Debug Attach Manager от Viktor Karpach делает одно дело, но делает его хорошо: помогает присоединить отладчик Visual Studio к пулам веб-приложений, службам Windows и другим процессам. Фактически, вы можете искать процессы (например, относящиеся к пулу приложений IIS), а затем присоединяться к ним, автоматически сохраняя выбранные процессы между перезапусками Visual Studio. Вы также можете подключаться к нескольким процессам одновременно. Кстати, расширение работает с версиями VS, начиная аж с 2013, если вдруг у кого ещё остались такие.
Окончание следует …
Источник: https://visualstudiomagazine.com/articles/2021/05/07/testing-tools.aspx
Новые Бесплатные Расширения для VS 2019. Начало 1-4
Пока мы ждём выхода новой Visual Studio 2022, большая часть .NET разработчиков используют VS 2019. Сегодня рассмотрим полезные бесплатные расширения для студии. Замечу, что под «новыми» здесь понимаются не только недавно вышедшие, но и недавно обновлённые инструменты.
1. Unit Test Boilerplate Generator от RandomEngy - это бесплатный инструмент со средней оценкой 4,8 из 5. Он поможет создать шаблон модульного теста для класса C#, с mock-объектами для всех зависимостей. Наряду с двумя режимами внедрения зависимостей и поддержкой инфраструктуры тестирования VS, он поддерживает NUnit и xUnit, а для mock-объектов поддерживаются: FakeItEasy, JustMock, Moq + AutoMoq, NSubstitute, Rhino Mocks и
SimpleStubs.
2. Fine Code Coverage от Fortune Ngwenya было скачано почти 18 тысяч раз, получив почти идеальную оценку 4,9. Оно помогает разработчикам визуализировать покрытие кода модульными тестами в .NET Core (.NET 5) и даже в старой .NET Framework. В частности, функция визуализации позволяет программистам:
- Помечать код, для которого есть тесты и для которого их нет
- Помечать тестирующий код
- Получать отчёты о покрытии кода тестами
- Получить отчёт о проблемах на горячих путях
Расширение последний раз было обновлено в конце марта, а последний коммит в репозитории проекта недельной давности, то есть автор старается поддерживать его в актуальном состоянии.
3. Run Coverlet Report от Chris Dexter - еще одна утилита для упрощения демонстрации покрытия кода, цель которой - бесплатно дублировать функциональность Visual Studio Enterprise (прости, Microsoft). Run Coverlet Report основан на превосходных инструментах Coverlet и Report Generator, которые позволяют собирать результаты покрытия кода из модульных тестов. Это расширение запускает оба этих инструмента, а затем отображает файл отчёта в Visual Studio, а также использует вывод Coverlet для подсветки синтаксиса. Coverlet, поддерживаемый .NET Foundation, - это проект с открытым исходным кодом, обеспечивающий кроссплатформенную систему анализа покрытия кода для C#. Report Generator преобразует отчёты о покрытии кода, созданные Visual Studio и многими другими инструментами, в удобочитаемые отчёты в различных форматах. Ещё один инструмент с идеальными 5 из 5.
4. Debug Attach Manager от Viktor Karpach делает одно дело, но делает его хорошо: помогает присоединить отладчик Visual Studio к пулам веб-приложений, службам Windows и другим процессам. Фактически, вы можете искать процессы (например, относящиеся к пулу приложений IIS), а затем присоединяться к ним, автоматически сохраняя выбранные процессы между перезапусками Visual Studio. Вы также можете подключаться к нескольким процессам одновременно. Кстати, расширение работает с версиями VS, начиная аж с 2013, если вдруг у кого ещё остались такие.
Окончание следует …
Источник: https://visualstudiomagazine.com/articles/2021/05/07/testing-tools.aspx
День восемьсот пятьдесят третий.
Новые Бесплатные Расширения для VS 2019. Окончание 5-9
Начало 1-4
5. SpecFlow представляет собой комплексное предложение профессионального уровня, в котором есть ссылки на документацию, инструкции по началу работы, часто задаваемые вопросы и политика конфиденциальности. При этом оно по-прежнему бесплатное, и имеет впечатляющие 4,9 из 5. SpecFlow помогает группам разработчиков .NET определять, управлять и выполнять автоматизированные приёмочные тесты в виде удобочитаемых бизнес-ориентированных спецификаций. SpecFlow поддерживает концепции разработки Behavior Driven Development (BDD) и Acceptance Test Driven Development (ATDD). Про BDD и SpecFlow, кстати, есть видео у Nick Chapsas.
6. Azure DevOps Test Connector от MadeUpExtensions работает с вышеупомянутым SpecFlow, поддерживая создание тестов Specflow Scenario Outline. Он позволяет программистам использовать атрибуты для связи с тестовыми классами и файлами функций SpecFlow с планами/наборами тестов и кейсами Azure DevOps. Это позволяет инженеру по автоматизации тестирования быстро синхронизировать свои последние изменения в Visual Studio с Azure DevOps, экономя время за счёт автоматического создания и связывания планов тестирования, наборов тестов (как статических, так и основанных на требованиях).
7. «Обожаю работать со сложными регулярными выражениями» – любят говорить… примерно никто из программистов. Хотя, может, это только мой личный опыт, наверняка есть любители. Поэтому, если нечто подобное:
для вас как два пальца…, можете пропустить этот пункт. Для всех остальных Regex Editor от Георгия Лосенкова может помочь. Это ещё один нишевый инструмент, который:
- Помогает редактировать и тестировать регулярные выражения.
- Тестировать основные методы класса Regex: Match, Replace, Split.
- Генерировать образцы кода (C# и VB), используя введённые вами данные.
- Рассматривать входные данные как несколько выборок (по одной выборке в строке)
- Подсвечивать шаблоны, найденные группы и замещающие строки
Короче, это regex101.com внутри вашей студии. На данный момент он был установлен более 8 тысяч раз и имеет идеальные 5 из 5.
8. Telerik Testing Framework от известного производителя множества профессиональных платных инструментов .NET. Но это бесплатная среда для веб-тестирования, разработанная, чтобы помочь вам автоматизировать приложения HTML5, AJAX, Silverlight (помните?) и WPF. Среди достоинств инструмента богатый API, поддержка LINQ, абстракция браузера и другие.
9. Недавно было обновлено популярное расширение SonarLint от SonarSource. Оно использует Roslyn, чтобы помочь пользователям находить и исправлять ошибки и проблемы в файлах C#, VB.Net, C, C++ и JavaScript. В связи с ростом количества правил, которые теперь исчисляются сотнями, оно использует сопоставление с образцом и анализ потока данных для облегчения алгоритмов глубокого анализа кода. Оно даже помогает решить любые обнаруженные проблемы. Есть возможность подключения к серверу SonarQube или SonarCloud для совместного использования наборов правил, получения уведомлений о событиях и т.п.
Источник: https://visualstudiomagazine.com/articles/2021/05/07/testing-tools.aspx
Новые Бесплатные Расширения для VS 2019. Окончание 5-9
Начало 1-4
5. SpecFlow представляет собой комплексное предложение профессионального уровня, в котором есть ссылки на документацию, инструкции по началу работы, часто задаваемые вопросы и политика конфиденциальности. При этом оно по-прежнему бесплатное, и имеет впечатляющие 4,9 из 5. SpecFlow помогает группам разработчиков .NET определять, управлять и выполнять автоматизированные приёмочные тесты в виде удобочитаемых бизнес-ориентированных спецификаций. SpecFlow поддерживает концепции разработки Behavior Driven Development (BDD) и Acceptance Test Driven Development (ATDD). Про BDD и SpecFlow, кстати, есть видео у Nick Chapsas.
6. Azure DevOps Test Connector от MadeUpExtensions работает с вышеупомянутым SpecFlow, поддерживая создание тестов Specflow Scenario Outline. Он позволяет программистам использовать атрибуты для связи с тестовыми классами и файлами функций SpecFlow с планами/наборами тестов и кейсами Azure DevOps. Это позволяет инженеру по автоматизации тестирования быстро синхронизировать свои последние изменения в Visual Studio с Azure DevOps, экономя время за счёт автоматического создания и связывания планов тестирования, наборов тестов (как статических, так и основанных на требованиях).
7. «Обожаю работать со сложными регулярными выражениями» – любят говорить… примерно никто из программистов. Хотя, может, это только мой личный опыт, наверняка есть любители. Поэтому, если нечто подобное:
([^e]|e([^s]|s([^\.]|\.([^c]|c([^o]|o([^m]|m([^p]|p([^\.]|\.([^o]|o([^ +s]|s([^\.]|\.([^l]|l([^i]|i([^n]|n([^u]|u[^x])))))))))))))))
для вас как два пальца…, можете пропустить этот пункт. Для всех остальных Regex Editor от Георгия Лосенкова может помочь. Это ещё один нишевый инструмент, который:
- Помогает редактировать и тестировать регулярные выражения.
- Тестировать основные методы класса Regex: Match, Replace, Split.
- Генерировать образцы кода (C# и VB), используя введённые вами данные.
- Рассматривать входные данные как несколько выборок (по одной выборке в строке)
- Подсвечивать шаблоны, найденные группы и замещающие строки
Короче, это regex101.com внутри вашей студии. На данный момент он был установлен более 8 тысяч раз и имеет идеальные 5 из 5.
8. Telerik Testing Framework от известного производителя множества профессиональных платных инструментов .NET. Но это бесплатная среда для веб-тестирования, разработанная, чтобы помочь вам автоматизировать приложения HTML5, AJAX, Silverlight (помните?) и WPF. Среди достоинств инструмента богатый API, поддержка LINQ, абстракция браузера и другие.
9. Недавно было обновлено популярное расширение SonarLint от SonarSource. Оно использует Roslyn, чтобы помочь пользователям находить и исправлять ошибки и проблемы в файлах C#, VB.Net, C, C++ и JavaScript. В связи с ростом количества правил, которые теперь исчисляются сотнями, оно использует сопоставление с образцом и анализ потока данных для облегчения алгоритмов глубокого анализа кода. Оно даже помогает решить любые обнаруженные проблемы. Есть возможность подключения к серверу SonarQube или SonarCloud для совместного использования наборов правил, получения уведомлений о событиях и т.п.
Источник: https://visualstudiomagazine.com/articles/2021/05/07/testing-tools.aspx
День восемьсот пятьдесят четвёртый. #ЗаметкиНаПолях
Валидация Email и URL в .NET
Существует множество совершенно безумных способов проверки email в .NET. Недавно я наткнулся на войну между двумя разработчиками в пул-реквесте. Война велась вокруг «идеального» регулярного выражения для проверки email.
Посмотрите на этот ответ на Stack Overflow. Регулярное выражение в ответе приведено следующее:
Логика валидации довольно проста:
1. Значение – строка?
2. Есть ли в строке символ
3. Находится ли символ
Всё. Регулярное выражение не требуется!
Это идеальный валидатор? Конечно, нет, и, если он используется в списке рассылки, то письма будут отправляться на адреса, которые не совсем соответствуют спецификации RFC. Однако, такой валидации достаточно, чтобы поймать 99,99% ошибок. Тем более, что, например, при создании учётной записи вы, скорее всего, дополнительно «проверите» email, отправив на него письмо с подтверждением регистрации.
Аналогичный атрибут
Так что в следующий раз, когда люди будут спорить об идеальном регулярном выражении для проверки email или url, рассмотрите вариант вообще не использовать регулярное выражение.
Источник: https://dotnetcoretutorials.com/2021/05/16/validating-an-email-in-a-net-api
Валидация Email и URL в .NET
Существует множество совершенно безумных способов проверки email в .NET. Недавно я наткнулся на войну между двумя разработчиками в пул-реквесте. Война велась вокруг «идеального» регулярного выражения для проверки email.
[email protected]
, что может быть проще? Посмотрите на этот ответ на Stack Overflow. Регулярное выражение в ответе приведено следующее:
(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])Другой пример можно взять из валидации email в Angular. Тут также используется регулярное выражение:
^(?=.{1,254}$)(?=.{1,64}@)[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$Немного другой, но всё равно гигантский шаблон. Итак, учитывая эти параметры (и, вероятно, многие другие), какое же выражение нам выбрать для валидации нашей модели?
public class CreateAccountViewModelНа самом деле, ни то, ни другое. В .NET Core (и в .NET Framework) есть встроенный валидатор email:
{
[RegularExpression("SoMeCrAzYReGeX")]
public string Email { get; set; }
}
[EmailAddress]Красиво и просто, без лишних сложностей. Но тогда возникает вопрос, какое регулярное выражение использует .NET? Вообще-то тут в принципе не используется регулярное выражение!
public string Email { get; set; }
Логика валидации довольно проста:
1. Значение – строка?
2. Есть ли в строке символ
@
?3. Находится ли символ
@
в любой позиции, кроме первой или последней?Всё. Регулярное выражение не требуется!
Это идеальный валидатор? Конечно, нет, и, если он используется в списке рассылки, то письма будут отправляться на адреса, которые не совсем соответствуют спецификации RFC. Однако, такой валидации достаточно, чтобы поймать 99,99% ошибок. Тем более, что, например, при создании учётной записи вы, скорее всего, дополнительно «проверите» email, отправив на него письмо с подтверждением регистрации.
Аналогичный атрибут
[Url]
для валидации URL, просто проверяет, начинается ли строка с https://
, https://
или ftp://
.Так что в следующий раз, когда люди будут спорить об идеальном регулярном выражении для проверки email или url, рассмотрите вариант вообще не использовать регулярное выражение.
Источник: https://dotnetcoretutorials.com/2021/05/16/validating-an-email-in-a-net-api
День восемьсот пятьдесят пятый. #Оффтоп #КакСтатьСеньором
После некоторого перерыва продолжу серию #КакСтатьСеньором с простыми, но полезными советами.
Написание Кода
1. Legacy-код и следующий разработчик
Вы когда-нибудь смотрели на код и чувствовали, что тут что-то не так? Зачем они так сделали? В этом нет никакого смысла. Я имел счастье работать с устаревшей кодовой базой. С комментариями типа
То же относится к вам. Подумайте о следующем человеке, который прочитает ваш код. Код покажется ему странным? Обзор кода частично решает эту проблему. Это привело меня к идее контекста: осознавать контекст, в котором работает команда.
Если я забуду код, вернусь к нему позже и не смогу воссоздать контекст, в котором был написан код, я подумаю: «Какой дебил это написал? Тут нет никакого смысла… Ой, это же я написал». И здесь на помощь приходит документация и комментарии.
2. Документация и комментарии
Документация – головная боль для большинства команд разработчиков. Не только комментарии, но и описание процессов, связанных с кодом. Но они помогают сохранять контекст и делиться знаниями. Основная ценность программного обеспечения - это не созданный код, а знания, накопленные людьми, которые его создали.
У нас есть конечная точка клиентского API, которую, казалось, никто никогда не использовал. Просто удалим её? В конце концов, это технический долг. А что, если раз в год 10 человек отправляют свои отчёты на эту конечную точку? Как это проверить? Если документации нет, то никак. Мы удалили эту конечную точку. Через несколько месяцев наступило то самое время года. Пользователи не смогли отправить 10 важных отчетов, потому что конечной точки больше не существовала. Люди, знавшие продукт, давно покинули команду. Конечно, теперь в коде есть комментарии, объясняющие, для чего предназначена эта конечная точка.
3. Атомарные коммиты
Если вам придётся откатить ваши изменения (а вам рано или поздно придётся это сделать), что случится с приложением? Атомарен ли ваш коммит? То есть, переводит ли он приложение из одного стабильного состояния в другое (например, проект компилируется и до ваших изменений, и после)?
4. Уверенность в удалении плохого кода
Поначалу мне было очень неловко удалять плохой или устаревший код. Я считал священным то, что когда-то было написано, тем более не мной. Я размышлял так: «Когда это писали, они явно хотели этим что-то сказать». Это традиции и культура против рационального мышления. Отчасти такие мысли подкрепляются случаями, вроде удаления той конечной точки.
Я пытался во что бы то ни стало сохранить код, придумывая костыли для обхода, тогда как сеньор безропотно бы его удалил. Удаляйте. Блок if, который никогда не выполнится, функцию, которую не нужно вызывать. В противном случае вы просто увеличите сложность кода и технический долг. Следующему человеку будет ещё труднее понять, что тут происходит.
Правило: есть код, которого вы не понимаете, и код, который никогда будет достигнут. Удалите код, который не достигается, и будьте осторожны с кодом, который вы не понимаете.
5. Обзоры кода
Обзоры кода великолепны для обучения. Это внешний цикл обратной связи о том, как вы пишете код и как его пишут другие. В чем разница? Один способ лучше другого? Я задавал себе этот вопрос на каждом обзоре: «Почему они сделали это именно так?». Когда я не мог найти подходящего ответа, я приходил поговорить с коллегами.
По прошествии первого месяца я начал замечать ошибки в коде моих коллег (а они замечали мои). Рецензирование стало для меня намного интереснее. Это была игра, которую я с нетерпением ждал. Игра, которая улучшит моё восприятие кода.
Правило: не одобряйте код, пока не поймёте, как он работает.
Источник: https://neilkakkar.com/things-I-learnt-from-a-senior-dev.html
Автор оригинала – Neil Kakkar
После некоторого перерыва продолжу серию #КакСтатьСеньором с простыми, но полезными советами.
Написание Кода
1. Legacy-код и следующий разработчик
Вы когда-нибудь смотрели на код и чувствовали, что тут что-то не так? Зачем они так сделали? В этом нет никакого смысла. Я имел счастье работать с устаревшей кодовой базой. С комментариями типа
//Раскомментировать этот код, когда прояснится ситуация с МухамедомЧто это? Кто такой Мухамед?
То же относится к вам. Подумайте о следующем человеке, который прочитает ваш код. Код покажется ему странным? Обзор кода частично решает эту проблему. Это привело меня к идее контекста: осознавать контекст, в котором работает команда.
Если я забуду код, вернусь к нему позже и не смогу воссоздать контекст, в котором был написан код, я подумаю: «Какой дебил это написал? Тут нет никакого смысла… Ой, это же я написал». И здесь на помощь приходит документация и комментарии.
2. Документация и комментарии
Документация – головная боль для большинства команд разработчиков. Не только комментарии, но и описание процессов, связанных с кодом. Но они помогают сохранять контекст и делиться знаниями. Основная ценность программного обеспечения - это не созданный код, а знания, накопленные людьми, которые его создали.
У нас есть конечная точка клиентского API, которую, казалось, никто никогда не использовал. Просто удалим её? В конце концов, это технический долг. А что, если раз в год 10 человек отправляют свои отчёты на эту конечную точку? Как это проверить? Если документации нет, то никак. Мы удалили эту конечную точку. Через несколько месяцев наступило то самое время года. Пользователи не смогли отправить 10 важных отчетов, потому что конечной точки больше не существовала. Люди, знавшие продукт, давно покинули команду. Конечно, теперь в коде есть комментарии, объясняющие, для чего предназначена эта конечная точка.
3. Атомарные коммиты
Если вам придётся откатить ваши изменения (а вам рано или поздно придётся это сделать), что случится с приложением? Атомарен ли ваш коммит? То есть, переводит ли он приложение из одного стабильного состояния в другое (например, проект компилируется и до ваших изменений, и после)?
4. Уверенность в удалении плохого кода
Поначалу мне было очень неловко удалять плохой или устаревший код. Я считал священным то, что когда-то было написано, тем более не мной. Я размышлял так: «Когда это писали, они явно хотели этим что-то сказать». Это традиции и культура против рационального мышления. Отчасти такие мысли подкрепляются случаями, вроде удаления той конечной точки.
Я пытался во что бы то ни стало сохранить код, придумывая костыли для обхода, тогда как сеньор безропотно бы его удалил. Удаляйте. Блок if, который никогда не выполнится, функцию, которую не нужно вызывать. В противном случае вы просто увеличите сложность кода и технический долг. Следующему человеку будет ещё труднее понять, что тут происходит.
Правило: есть код, которого вы не понимаете, и код, который никогда будет достигнут. Удалите код, который не достигается, и будьте осторожны с кодом, который вы не понимаете.
5. Обзоры кода
Обзоры кода великолепны для обучения. Это внешний цикл обратной связи о том, как вы пишете код и как его пишут другие. В чем разница? Один способ лучше другого? Я задавал себе этот вопрос на каждом обзоре: «Почему они сделали это именно так?». Когда я не мог найти подходящего ответа, я приходил поговорить с коллегами.
По прошествии первого месяца я начал замечать ошибки в коде моих коллег (а они замечали мои). Рецензирование стало для меня намного интереснее. Это была игра, которую я с нетерпением ждал. Игра, которая улучшит моё восприятие кода.
Правило: не одобряйте код, пока не поймёте, как он работает.
Источник: https://neilkakkar.com/things-I-learnt-from-a-senior-dev.html
Автор оригинала – Neil Kakkar
День восемьсот пятьдесят шестой. #юмор
Доброй летней пятницы, дорогие подписчики.
Доброй летней пятницы, дорогие подписчики.
День восемьсот пятьдесят седьмой. #ЗаметкиНаПолях
Настройка Производительности в EF Core
Сегодня посоветую вам видео из серии EF Core Community Standup, посвящённое настройке производительности в Entity Framework. Для знающих SQL, вроде меня, советы могут показаться довольно очевидными, хотя интересно было узнать, что оптимизации можно делать не в SQL, а прямо в LINQ запросе к EF.
Для примера взято приложение книжного магазина. Есть основная сущность Books. Сущности Authors (авторы) и Tags (теги), которые относятся к Books как многие-ко-многим, а сущность Reviews (отзывы и оценки) – один-ко-многим.
Нам для отображения доступных книг нужно выбрать данные книги (название, цена, год публикации), авторов и теги для каждой книги, а также количество отзывов и среднюю оценку.
Очевидным вариантом запроса будет что-то вроде:
1. Добавить метод
2. Не загружать ненужные данные. Используйте проекцию в методе
4. По возможности выполнять вычисления на стороне БД. Например, для количества отзывов и средней оценки (заметьте, что требуется приведение к обнуляемому типу и тип зависит от конкретной СУБД):
Чтобы не загромождать запрос, все эти изменения можно разместить в методе расширения
В видео по ссылке ниже весь процесс оптимизации производительности описан более подробно и наглядно.
Источники:
- Видео https://youtu.be/VgNFFEqwZPU
- Текст https://www.thereformedprogrammer.net/five-levels-of-performance-tuning-for-an-ef-core-query/
Настройка Производительности в EF Core
Сегодня посоветую вам видео из серии EF Core Community Standup, посвящённое настройке производительности в Entity Framework. Для знающих SQL, вроде меня, советы могут показаться довольно очевидными, хотя интересно было узнать, что оптимизации можно делать не в SQL, а прямо в LINQ запросе к EF.
Для примера взято приложение книжного магазина. Есть основная сущность Books. Сущности Authors (авторы) и Tags (теги), которые относятся к Books как многие-ко-многим, а сущность Reviews (отзывы и оценки) – один-ко-многим.
Нам для отображения доступных книг нужно выбрать данные книги (название, цена, год публикации), авторов и теги для каждой книги, а также количество отзывов и среднюю оценку.
Очевидным вариантом запроса будет что-то вроде:
var books = context.BooksКак можно улучшить этот запрос:
.Include(book => book.AuthorsLink
.OrderBy(bookAuthor => bookAuthor.Order))
.ThenInclude(bookAuthor => bookAuthor.Author)
.Include(book => book.Reviews)
.Include(book => book.Tags)
.ToList();
1. Добавить метод
AsNoTracking()
для всех запросов, не предполагающих изменения данных.2. Не загружать ненужные данные. Используйте проекцию в методе
Select
для выбора только нужных полей:Books.Select(p => new BookListDto {3. Не включать зависимости, а выбирать только то, что надо из них. Например, нам нужны только имена авторов через запятую:
Title = p.Title,
Price = p.Price,
Published = p.Published,
…
AuthorsOrdered = string.Join(", ",
p.AuthorsLink.OrderBy(q => q.Order)
.Select(q => q.Author.Name)),
…
String.Join
будет выполняться на клиенте, но можно использовать пользовательские функции SQL (User-Defined Functions).4. По возможности выполнять вычисления на стороне БД. Например, для количества отзывов и средней оценки (заметьте, что требуется приведение к обнуляемому типу и тип зависит от конкретной СУБД):
ReviewsCount = p.Reviews.Count(),5. В конфигурации сущностей EF добавить индексы для каждого свойства сущности, по которому планируется производить сортировку или фильтрацию.
ReviewsAverageVotes =
p.Reviews.Select(y =>
(double?)y.NumStars).Average(),
…
Чтобы не загромождать запрос, все эти изменения можно разместить в методе расширения
MapBookToDto(this IQueryable<Book> books)
, таким образом сам запрос будет выглядеть примерно так:var booksQuery = _context.BooksЕсли эти советы всё равно не дают достаточной производительности, можно, например, денормализовать БД и включить столбцы с рассчитанными значениями количества отзывов и средней оценкой в таблицу Books. А при добавлении/удалении отзыва пересчитывать эти значения.
.AsNoTracking()
.MapBookToDto()
. …
В видео по ссылке ниже весь процесс оптимизации производительности описан более подробно и наглядно.
Источники:
- Видео https://youtu.be/VgNFFEqwZPU
- Текст https://www.thereformedprogrammer.net/five-levels-of-performance-tuning-for-an-ef-core-query/
День восемьсот пятьдесят восьмой. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
87. Две Ошибки Могут «Исправить» Друг Друга (и Это Трудно Обнаружить)
Код никогда не лжёт, но может сам себе противоречить. Иногда такие противоречия могут заставить схватиться за голову и воскликнуть: «Как это вообще может работать?»
В своём интервью главный разработчик ПО лунного модуля Аполлона-11 Аллан Клумпп рассказал, что ПО управления двигателями, содержало ошибку, которая должна была сделать посадочный модуль нестабильным. Однако эта ошибка компенсировалась другой, и ПО использовалось как для посадки на Луну, так и для Аполлона-11, прежде чем была обнаружена или исправлена.
Рассмотрим функцию, возвращающую статус завершения задачи. Представьте, что она возвращает
Или, например приложение, которое сериализует и сохраняет своё состояние для дальнейшего чтения и использования. Представьте, что одно из свойств неправильно названо как
Когда два дефекта в коде создают одну видимую ошибку, стандартный подход к исправлению ошибок может потерпеть неудачу. Разработчик получает отчёт об ошибке, находит дефект, исправляет его и повторно тестирует. Однако неисправность всё равно проявляется, потому что работает второй дефект. В итоге первое исправление удаляется и код анализируется дальше, пока не будет обнаружен второй дефект. Он исправляется, но из-за отмены исправления первого дефекта ошибка всё ещё проявляется, поэтому и второе исправление откатывается. Процесс повторяется, но теперь разработчик отклонил два возможных исправления, и пытается найти третий дефект, которого в реальности не существует…
Взаимодействие между двумя дефектами кода, которые проявляются как одна видимая ошибка, не только затрудняет решение проблемы, но и ведёт разработчиков в тупик, в котором, при благоприятном исходе, они могут обнаружить, что они пробовали правильные решения на раннем этапе.
Это происходит не только в коде: проблема также существует в документации и требованиях. И она может вирусно распространяться из одного места в другое. Ошибка в коде может компенсировать ошибку в документации.
Это также может распространяться на людей: пользователи узнают, что когда приложение говорит: «Налево», - это означает «Направо», поэтому они корректируют своё поведение соответствующим образом. Они даже передают этот опыт новым пользователям: «Помните, когда в приложении говорится «нажмите стрелку влево», это на самом деле означает «стрелку вправо». Исправьте ошибку - и пользователям потребуется переобучение.
Одиночные ошибки можно легко обнаружить и легко исправить. Труднее решить проблемы со множеством причин, требующие множественных изменений. Отчасти это связано с тем, что простые проблемы так легко решаются, что люди склонны решать их относительно быстро, а более сложные проблемы откладывают на потом.
Не существует простых советов, как устранять недостатки, возникающие из-за множественных проблем. Необходимо осознавать вероятность такого случая, ясно мыслить и быть готовым рассмотреть все возможные варианты.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Allan Kelly
97 Вещей, Которые Должен Знать Каждый Программист
87. Две Ошибки Могут «Исправить» Друг Друга (и Это Трудно Обнаружить)
Код никогда не лжёт, но может сам себе противоречить. Иногда такие противоречия могут заставить схватиться за голову и воскликнуть: «Как это вообще может работать?»
В своём интервью главный разработчик ПО лунного модуля Аполлона-11 Аллан Клумпп рассказал, что ПО управления двигателями, содержало ошибку, которая должна была сделать посадочный модуль нестабильным. Однако эта ошибка компенсировалась другой, и ПО использовалось как для посадки на Луну, так и для Аполлона-11, прежде чем была обнаружена или исправлена.
Рассмотрим функцию, возвращающую статус завершения задачи. Представьте, что она возвращает
false
, когда должна возвращать true
. Теперь представьте, что вызывающая функция не проверяет возвращаемое значение. Всё работает нормально, пока однажды кто-нибудь не заметит упущенную проверку и не добавит её.Или, например приложение, которое сериализует и сохраняет своё состояние для дальнейшего чтения и использования. Представьте, что одно из свойств неправильно названо как
TimeToLive
, вместо TimeToDie
, как указано в документации. Все выглядит нормально, пока код сериализации и код десериализации содержат одну и ту же ошибку. Но исправьте это в одном месте или добавьте новое приложение, читающее те же данные, и симметрия нарушится, как и работа кода.Когда два дефекта в коде создают одну видимую ошибку, стандартный подход к исправлению ошибок может потерпеть неудачу. Разработчик получает отчёт об ошибке, находит дефект, исправляет его и повторно тестирует. Однако неисправность всё равно проявляется, потому что работает второй дефект. В итоге первое исправление удаляется и код анализируется дальше, пока не будет обнаружен второй дефект. Он исправляется, но из-за отмены исправления первого дефекта ошибка всё ещё проявляется, поэтому и второе исправление откатывается. Процесс повторяется, но теперь разработчик отклонил два возможных исправления, и пытается найти третий дефект, которого в реальности не существует…
Взаимодействие между двумя дефектами кода, которые проявляются как одна видимая ошибка, не только затрудняет решение проблемы, но и ведёт разработчиков в тупик, в котором, при благоприятном исходе, они могут обнаружить, что они пробовали правильные решения на раннем этапе.
Это происходит не только в коде: проблема также существует в документации и требованиях. И она может вирусно распространяться из одного места в другое. Ошибка в коде может компенсировать ошибку в документации.
Это также может распространяться на людей: пользователи узнают, что когда приложение говорит: «Налево», - это означает «Направо», поэтому они корректируют своё поведение соответствующим образом. Они даже передают этот опыт новым пользователям: «Помните, когда в приложении говорится «нажмите стрелку влево», это на самом деле означает «стрелку вправо». Исправьте ошибку - и пользователям потребуется переобучение.
Одиночные ошибки можно легко обнаружить и легко исправить. Труднее решить проблемы со множеством причин, требующие множественных изменений. Отчасти это связано с тем, что простые проблемы так легко решаются, что люди склонны решать их относительно быстро, а более сложные проблемы откладывают на потом.
Не существует простых советов, как устранять недостатки, возникающие из-за множественных проблем. Необходимо осознавать вероятность такого случая, ясно мыслить и быть готовым рассмотреть все возможные варианты.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Allan Kelly
День восемьсот пятьдесят девятый. #ЧтоНовенького
.NET 6: Улучшения коллекций. Начало
1. Ёмкость списка, стека и очереди
Перед добавлением большого количества элементов в
Заметным исключением из этой группы является
Это не единственный недостаток
2. Изменяемые структуры и словари
Хотя и редко, разработчикам иногда приходится работать с изменяемыми структурами. Это может вызывать трудности, потому что легко случайно скопировать изменяемую структуру, в результате чего два значения больше не будут синхронизироваться.
Чтобы решить эту проблему, приходилось намеренно копировать структуру, вносить изменения, а затем копировать её обратно в исходное место. Для небольших конструкций это неплохо, но для больших может быть дорого. А так как производительность – чаще всего первопричина использования изменяемых структур, использование этого метода контрпродуктивно.
Чтобы избежать этих ненужных копий, изменяемые структуры обычно хранились в массивах. В отличие от свойства-индексатора в
В C# 7 были введены ссылочные возвращаемые значения (ref return). Это позволило индексаторам возвращать ссылку на объект, а не копию.
Чтобы предложить те же возможности для словарей, была создана новая функция под названием
1. Это не метод расширения. Разработчики опасались, что его будет слишком легко использовать неправильно, поэтому они намеренно сделали так, чтобы его было сложно найти. (Функцию
2. Существует внутренний метод
3. После вызова
Окончание следует…
Источник: https://www.infoq.com/news/2021/06/Net6-Collections/
.NET 6: Улучшения коллекций. Начало
1. Ёмкость списка, стека и очереди
Перед добавлением большого количества элементов в
Dictionary
или HashSet
полезно вызвать EnsureCapacity
с ожидаемым размером коллекции. Это позволяет коллекции выполнить одну операцию изменения размера заранее, избегая необходимости делать это несколько раз. Метод EnsureCapacity
был добавлен в классы List<T>
, Stack<T>
и Queue<T>
, также для повышения производительности.Заметным исключением из этой группы является
Collection<T>
. В отличие от других коллекций, Collection<T>
может при желании обернуть другую коллекцию, которая не обязательно предоставляет метод EnsureCapacity
. Её потомок, ObservableCollection<T>
, также не может предоставить метод EnsureCapacity
.Это не единственный недостаток
Collection<T>
и ObservableCollection<T>
. Отсутствие метода AddRange
давно раздражало разработчиков. А также им не хватает высокопроизводительного IEnumerator
на основе структур, который предлагает List<T>
.2. Изменяемые структуры и словари
Хотя и редко, разработчикам иногда приходится работать с изменяемыми структурами. Это может вызывать трудности, потому что легко случайно скопировать изменяемую структуру, в результате чего два значения больше не будут синхронизироваться.
Чтобы решить эту проблему, приходилось намеренно копировать структуру, вносить изменения, а затем копировать её обратно в исходное место. Для небольших конструкций это неплохо, но для больших может быть дорого. А так как производительность – чаще всего первопричина использования изменяемых структур, использование этого метода контрпродуктивно.
Чтобы избежать этих ненужных копий, изменяемые структуры обычно хранились в массивах. В отличие от свойства-индексатора в
List<T>
, доступ к элементам массива осуществляется напрямую.В C# 7 были введены ссылочные возвращаемые значения (ref return). Это позволило индексаторам возвращать ссылку на объект, а не копию.
public ref int this[int index] {Этот метод используется структурой
get { return ref _internalArray[index]; }
}
Span<T>
, начиная с .NET Core 2.1. Начиная с .NET 5, метод CollectionsMarshal.AsSpan
позволяет легко получить span-обёртку коллекции.Чтобы предложить те же возможности для словарей, была создана новая функция под названием
CollectionsMarshal.GetValueRefOrNullRef
. Есть несколько интересных фактов об этой функции:1. Это не метод расширения. Разработчики опасались, что его будет слишком легко использовать неправильно, поэтому они намеренно сделали так, чтобы его было сложно найти. (Функцию
AsSpan
также потенциально небезопасно использовать, поскольку размеры коллекции не могут быть изменены, пока существует Span<T>
.)2. Существует внутренний метод
Dictionary<TKey, TValue>.FindValue
. Он и используется в GetValueRefOrNullRef
:public static ref TValueFindValue сам по себе использует некоторые методы, которые не распространены в программировании на C#, вроде
GetValueRefOrNullRef<TKey, TValue>
(Dictionary<TKey, TValue> dictionary, TKey key)
where TKey : notnull
=> ref dictionary.FindValue(key);
goto
, включая обратные переходы.3. После вызова
GetValueRefOrNullRef
нужно использовать CompilerServices.Unsafe.IsNullRef
, чтобы проверить, является ли результат ссылкой на фактическое значение или на null
. Это связано с тем, что в C# нет синтаксиса для проверки того, является ли ссылка на структуру нулевой.Окончание следует…
Источник: https://www.infoq.com/news/2021/06/Net6-Collections/
День восемьсот шестидесятый. #ЧтоНовенького
.NET 6: Улучшения коллекций. Окончание
3. Улучшения сериализации для словарей
В то время как сериализация списочных коллекций довольно проста, коллекции, для которых требуется компонент хеширования, такие как
Поскольку подавляющее большинство этих проблем связано со строковыми ключами, было решено добавить два новых метода в
Однако это не полное решение. Поскольку ни XML, ни JSON не позволяют связывать свойства с коллекциями, сериализаторам всё равно нужно будет определять собственный способ хранения информации.
4. Очередь с приоритетом
Новый класс
Для
Чтобы гарантировать, что приоритет не может быть изменён, он хранится в очереди отдельно от объекта:
Ещё вопрос: разрешить ли перечисление очереди. На первый взгляд он может показаться странным. Почему бы не использовать
Первая проблема - это подразумеваемый контракт для
Можно сделать перечислитель неразрушающим, но в этом есть свои проблемы. Внутренне приоритетная очередь не обязательно упорядочена. Это означает, что перечислитель должен будет отслеживать, какие элементы он уже видел. Если по какой-то причине вам понадобится запустить несколько перечислений одновременно, каждый, по идее должен был бы получить полную копию очереди.
Таким образом, было решено, что класс
Если вы действительно хотите использовать
.NET 6: Улучшения коллекций. Окончание
3. Улучшения сериализации для словарей
В то время как сериализация списочных коллекций довольно проста, коллекции, для которых требуется компонент хеширования, такие как
Dictionary
и HashSet
, создают дополнительные проблемы. Одна из таких проблем - необходимость сериализации не только содержимого, но и используемого алгоритма сравнения. Чтобы десериализатор знал, должен ли он создавать коллекцию с порядковым компаратором, зависящим от языка и региональных параметров и чувствительным или нечувствительным к регистру.Поскольку подавляющее большинство этих проблем связано со строковыми ключами, было решено добавить два новых метода в
StringComparer
:public static bool IsWellKnownOrdinalComparer(Проверяя результат этих функций, сериализатор может собрать необходимую информацию для последующей десериализации. Хотя методы не охватывают всех сценариев, редко можно встретить настолько специализарованный компаратор, не основанный на известной культуре.
IEqualityComparer<string?>? comparer,
out bool ignoreCase);
public static bool IsWellKnownCultureAwareComparer(
IEqualityComparer<string?>? comparer,
[NotNullWhen(true)] out CompareInfo? compareInfo,
out CompareOptions compareOptions);
Однако это не полное решение. Поскольку ни XML, ни JSON не позволяют связывать свойства с коллекциями, сериализаторам всё равно нужно будет определять собственный способ хранения информации.
4. Очередь с приоритетом
Новый класс
PriorityQueue
разработан для сценариев, когда разработчику нужна очередь, в которой элементы помещаются в список на основе значения приоритета. Это можно реализовать несколькими способами, многие из которых зависят от вопроса: «Можно ли изменять приоритет элемента?».Для
PriorityQueue
было решено не допускать изменения приоритета. Создатели определили, что фиксированное значение приоритета приведёт к 2-3-кратному улучшению производительности.Чтобы гарантировать, что приоритет не может быть изменён, он хранится в очереди отдельно от объекта:
public void Enqueue(TElement element, TPriority priority);Следующий вопрос - стабильность. Если вы добавляете в очередь два элемента с одинаковым приоритетом, и они гарантированно извлекаются из очереди в том же порядке, то очередь считается стабильной. В .NET решили не предоставлять стабильную очередь, опять же во имя быстродействия.
Ещё вопрос: разрешить ли перечисление очереди. На первый взгляд он может показаться странным. Почему бы не использовать
foreach
для очереди?Первая проблема - это подразумеваемый контракт для
IEnumerable
. Большинство разработчиков предполагают, что вы можете дважды перечислить одну и ту же коллекцию и оба раза получить одинаковый результат. Это предположение встроено в общие шаблоны, где не всегда очевидно, что перечисление вообще происходит. Например, вызов метода Count()
может перечислить элементы, что приведёт к опустошению очереди. Что означает, что вызванный после этого foreach
увидит пустую очередь.Можно сделать перечислитель неразрушающим, но в этом есть свои проблемы. Внутренне приоритетная очередь не обязательно упорядочена. Это означает, что перечислитель должен будет отслеживать, какие элементы он уже видел. Если по какой-то причине вам понадобится запустить несколько перечислений одновременно, каждый, по идее должен был бы получить полную копию очереди.
Таким образом, было решено, что класс
PriorityQueue
не будет реализовывать IEnumerable<T>
. Это, в свою очередь, означает, что он также не может реализовать ICollection<T>
или другие подобные интерфейсы.Если вы действительно хотите использовать
PriorityQueue
в foreach
, можно добавить метод расширения:public static IEnumerable<TElement>Источник: https://www.infoq.com/news/2021/06/Net6-Collections/
GetDequeuingEnumerator<TElement, TPriority>(
this PriorityQueue<TElement, TPriority> queue)
{
while (queue.TryDequeue(out var item))
yield return item;
}
День восемьсот шестьдесят первый.
5 Инструментов для Обнаружения и Устранения Уязвимостей в Безопасности
Сканирование зависимостей
Своевременное обновление зависимостей - один из самых лёгких способов предотвращения уязвимостей в вашем коде.
1. Dependabot
Эта утилита GitHub имеет простой и понятный рабочий процесс: автоматически создаёт пулл реквесты для новых версий зависимостей и предупреждает об уязвимостях в зависимостях.
Dependabot позволяет настраивать частоту обновлений, метки, рецензентов и сообщения для коммитов, а также позволяет исключить зависимости, которые могут иметь критические изменения и конфликты при слиянии.
Включить обновления зависимостей можно в вашем репозитории на Github. Зайдите в Настройки > Безопасность и Анализ (Settings > Security & Analysis) и включите Обновления безопасности Dependabot (Dependabot security updates).
2. Renovate
Как и Dependabot, Renovate - это приложение GitHub, которое отслеживает ваши зависимости и открывает пул реквесты при появлении обновлений.
Главное преимущество Renovate в том, что он чрезвычайно настраиваемый. Он поддерживает обновления по расписанию, а также автоматическое слияние на основе правил, установленных в конфигурации.
Renovate также позволяет группировать обновления зависимостей в один пул реквест, а не создавать отдельные, что может значительно снизить трудозатраты для команды.
Анализаторы кода
3. Snyk
Synk - платный продукт, но в личных проектах его можно использовать бесплатно. Это, по сути, набор продуктов для поиска и устранения уязвимостей в ваших зависимостях, коде и контейнерах.
Snyk использует семантический анализ для обнаружения ошибок безопасности и производительности. И в создаваемом им отчете для каждой уязвимости вы получите классификатор серьёзности, подробное объяснение проблемы, анализ исправления и способы предотвращения ошибки в будущем.
4. GitGuardian
GitGuardian - это, по сути, сервис для автоматического обнаружения и исправления секретной информации в вашем коде. Он интегрируется с Github и работает как с общедоступными, так и с частными репозиториями. GitGuarding также может быть интегрирован с рабочим процессом CI/CD для получения обратной связи по каждому коммиту. Еще одна важная функция - это интеграция со Slack/Discord, PagerDuty, которая позволяет разработчикам оставаться в курсе предупреждений системы безопасности.
5. Webhint
Webhint - это настраиваемый инструмент линтинга с открытым исходным кодом, который помогает улучшить доступность вашего сайта, скорость, кроссбраузерность, безопасность и т.д.
Источник: https://dev.to/opinionatedpie/5-developer-tools-for-detecting-and-fixing-security-vulnerabilities-h1j
5 Инструментов для Обнаружения и Устранения Уязвимостей в Безопасности
Сканирование зависимостей
Своевременное обновление зависимостей - один из самых лёгких способов предотвращения уязвимостей в вашем коде.
1. Dependabot
Эта утилита GitHub имеет простой и понятный рабочий процесс: автоматически создаёт пулл реквесты для новых версий зависимостей и предупреждает об уязвимостях в зависимостях.
Dependabot позволяет настраивать частоту обновлений, метки, рецензентов и сообщения для коммитов, а также позволяет исключить зависимости, которые могут иметь критические изменения и конфликты при слиянии.
Включить обновления зависимостей можно в вашем репозитории на Github. Зайдите в Настройки > Безопасность и Анализ (Settings > Security & Analysis) и включите Обновления безопасности Dependabot (Dependabot security updates).
2. Renovate
Как и Dependabot, Renovate - это приложение GitHub, которое отслеживает ваши зависимости и открывает пул реквесты при появлении обновлений.
Главное преимущество Renovate в том, что он чрезвычайно настраиваемый. Он поддерживает обновления по расписанию, а также автоматическое слияние на основе правил, установленных в конфигурации.
Renovate также позволяет группировать обновления зависимостей в один пул реквест, а не создавать отдельные, что может значительно снизить трудозатраты для команды.
Анализаторы кода
3. Snyk
Synk - платный продукт, но в личных проектах его можно использовать бесплатно. Это, по сути, набор продуктов для поиска и устранения уязвимостей в ваших зависимостях, коде и контейнерах.
Snyk использует семантический анализ для обнаружения ошибок безопасности и производительности. И в создаваемом им отчете для каждой уязвимости вы получите классификатор серьёзности, подробное объяснение проблемы, анализ исправления и способы предотвращения ошибки в будущем.
4. GitGuardian
GitGuardian - это, по сути, сервис для автоматического обнаружения и исправления секретной информации в вашем коде. Он интегрируется с Github и работает как с общедоступными, так и с частными репозиториями. GitGuarding также может быть интегрирован с рабочим процессом CI/CD для получения обратной связи по каждому коммиту. Еще одна важная функция - это интеграция со Slack/Discord, PagerDuty, которая позволяет разработчикам оставаться в курсе предупреждений системы безопасности.
5. Webhint
Webhint - это настраиваемый инструмент линтинга с открытым исходным кодом, который помогает улучшить доступность вашего сайта, скорость, кроссбраузерность, безопасность и т.д.
Источник: https://dev.to/opinionatedpie/5-developer-tools-for-detecting-and-fixing-security-vulnerabilities-h1j
День восемьсот шестьдесят второй. #Оффтоп #КакСтатьСеньором
Тестирование
Я настолько полюбил тестирование, что мне неловко писать код без тестов.
Если ваше приложение выполняет всего одну задачу (как школьная лабораторная работа), то ручное тестирование ещё приемлемо. Раньше я так и делал. А что, если приложение выполняет сотню различных действий? Я не хочу тратить полчаса на тестирование всего функционала, а иногда и забывать, что мне нужно проверить.
Я думаю о тестировании как о документировании. Это документация, подтверждающая мои предположения о коде. Тесты говорят мне, что я ожидаю от работы кода, и сообщают мне обо всех случаях, когда что-то идёт не так.
Итак, когда я пишу тесты, я:
1. Демонстрирую, как использовать класс/функцию/систему, которую я тестирую.
2. Демонстрирую всё, что может пойти не так.
3. В большинстве случаев тестирую поведение (публичный API), а не реализацию.
Всё, что я пропустил в п. 2, – это источники ошибок. Поэтому, всякий раз, когда я обнаруживаю ошибку, я убеждаюсь, что исправление кода имеет соответствующий тест, чтобы задокументировать: «вот ещё один способ, как что-то может пойти не так».
Просто написание этих тестов не улучшает качество моего кода, в отличие от написания самого кода. Но понимание, которое я получаю от чтения тестов, помогает мне писать лучший код.
Но это не единственный вид тестирования.
Есть машины, на которых вы разрабатываете (источник всех мемов «Оно работает на моей машине!»). Есть машины, на которых вы тестируете (зачастую, это те же машины для разработки). И наконец, есть машины, на которых вы развёртываете приложение. Если существует несоответствие среды между тестовой и производственной машинами, у вас будут проблемы.
У нас есть локальная разработка, например, в докере на машине разработчика. Есть среда разработки, где установлен набор библиотек (и инструментов разработки). Туда мы устанавливаем код, который мы пишем, и там же проводим все тесты с другими зависимыми системами. Затем идёт среда бета (staging), которая в точности совпадает с производственной средой. Наконец, производственная среда, состоящая из машин, на которых выполняется код и обслуживает реальных клиентов.
Идея состоит в том, чтобы попытаться выявить ошибки, которые не удалось бы выявить при модульном и системном тестировании. Например, несоответствие API запрашивающей и отвечающей системы.
Думаю, всё было бы по-другому в личном проекте или в небольшой компании. Не у всех есть ресурсы для создания собственной инфраструктуры. Однако эта идея актуальна для облачных провайдеров, таких как AWS и Azure.
Вы можете настроить отдельные кластеры для разработки и производственной среды. AWS ECS использует для развёртывания образы докеров, поэтому в разных средах всё относительно единообразно. Сложность - это интеграция с другими облачными сервисами: вызывать нужную конечную точку из правильной среды.
Источник: https://neilkakkar.com/things-I-learnt-from-a-senior-dev.html
Автор оригинала – Neil Kakkar
Тестирование
Я настолько полюбил тестирование, что мне неловко писать код без тестов.
Если ваше приложение выполняет всего одну задачу (как школьная лабораторная работа), то ручное тестирование ещё приемлемо. Раньше я так и делал. А что, если приложение выполняет сотню различных действий? Я не хочу тратить полчаса на тестирование всего функционала, а иногда и забывать, что мне нужно проверить.
Я думаю о тестировании как о документировании. Это документация, подтверждающая мои предположения о коде. Тесты говорят мне, что я ожидаю от работы кода, и сообщают мне обо всех случаях, когда что-то идёт не так.
Итак, когда я пишу тесты, я:
1. Демонстрирую, как использовать класс/функцию/систему, которую я тестирую.
2. Демонстрирую всё, что может пойти не так.
3. В большинстве случаев тестирую поведение (публичный API), а не реализацию.
Всё, что я пропустил в п. 2, – это источники ошибок. Поэтому, всякий раз, когда я обнаруживаю ошибку, я убеждаюсь, что исправление кода имеет соответствующий тест, чтобы задокументировать: «вот ещё один способ, как что-то может пойти не так».
Просто написание этих тестов не улучшает качество моего кода, в отличие от написания самого кода. Но понимание, которое я получаю от чтения тестов, помогает мне писать лучший код.
Но это не единственный вид тестирования.
Есть машины, на которых вы разрабатываете (источник всех мемов «Оно работает на моей машине!»). Есть машины, на которых вы тестируете (зачастую, это те же машины для разработки). И наконец, есть машины, на которых вы развёртываете приложение. Если существует несоответствие среды между тестовой и производственной машинами, у вас будут проблемы.
У нас есть локальная разработка, например, в докере на машине разработчика. Есть среда разработки, где установлен набор библиотек (и инструментов разработки). Туда мы устанавливаем код, который мы пишем, и там же проводим все тесты с другими зависимыми системами. Затем идёт среда бета (staging), которая в точности совпадает с производственной средой. Наконец, производственная среда, состоящая из машин, на которых выполняется код и обслуживает реальных клиентов.
Идея состоит в том, чтобы попытаться выявить ошибки, которые не удалось бы выявить при модульном и системном тестировании. Например, несоответствие API запрашивающей и отвечающей системы.
Думаю, всё было бы по-другому в личном проекте или в небольшой компании. Не у всех есть ресурсы для создания собственной инфраструктуры. Однако эта идея актуальна для облачных провайдеров, таких как AWS и Azure.
Вы можете настроить отдельные кластеры для разработки и производственной среды. AWS ECS использует для развёртывания образы докеров, поэтому в разных средах всё относительно единообразно. Сложность - это интеграция с другими облачными сервисами: вызывать нужную конечную точку из правильной среды.
Источник: https://neilkakkar.com/things-I-learnt-from-a-senior-dev.html
Автор оригинала – Neil Kakkar
День восемьсот шестьдесят третий. #ЗаметкиНаПолях
Почему ASP.NET Приложение Такое Медленное? 10 Проблем с Производительностью и Их Решения
Проблемы с производительностью сервера могут возникать по разным причинам. Проблемы с памятью, медленные запросы к базе данных и слишком мало машин - вот лишь некоторые из них. В этой серии постов расскажу о 10 типах проблем, которые могут снижать производительность вашего сервера.
1. Медленные вызовы базы данных
Быстрое взаимодействие БД, вероятно, самое важное условие для хорошей производительности. По крайней мере, в большинстве приложений. К сожалению, есть много вещей, которые могут пойти не так, и даже невинно выглядящие реализации могут вызывать проблемы. Вот некоторые проблемы, которые могут приводить к медленным запросам к БД и снижать производительность вашего приложения:
- Плохой дизайн схемы
- Плохая стратегия индексации и выполнение действий в приложении, а не в БД (см. производительность в EF Core).
- БД находится далеко от сервера.
Лучше всего разместить БД географически близко к вашим серверам, оптимально в том же центре обработки данных.
- Использование БД способом, для которого она не была создана.
Не все базы данных одинаковы. Некоторые из них идеально подходят для хранения пар «ключ-значение», другие - для транзакций, третьи по-прежнему идеально подходят для хранения журналов. Используйте лучшую БД для ваших нужд. Например, документоориентированная БД, вроде MongoDB, плохо справляется с операциями JOIN, и их использование может снизить производительность. Но она отлично подходит для хранения документов с большим количеством данных. Таким образом, одним из решений может быть дублирование информации между документами вместо использования
- У БД недостаточно ресурсов.
Хотя очевидным решением будет масштабирование ваших серверов, не забывайте, что и базы данных должны масштабироваться. Например, в Azure SQL Server вам нужно будет следить за DTU (единицами транзакций базы данных). В других БД вам нужно следить за хранилищем, оперативной памятью, сетью и процессором. И не всегда система ясно предупреждает, когда вы приближаетесь к пределу. Всё просто начинает замедляться, и вы задаётесь вопросом, что, чёрт возьми, происходит.
- Неэффективные запросы всегда возможны. Если вы используете Entity Framework, сгенерированный SQL не всегда оптимален.
- Требуется каждый раз восстанавливать соединение. Если ваши соединения с БД не объединены в пул должным образом, возможно, соединение пересоздаётся для каждого запроса.
- Рассмотрите хранимые процедуры, когда сложный запрос занимает много времени.
- Плохая стратегия сегментирования.
Позаботьтесь о том, чтобы сгруппировать связанные данные в одном сегменте, иначе вы рискуете запрашивать несколько сегментов в одном запросе.
Самая сложная часть решения этих проблем - это изначально их идентифицировать. Есть много инструментов, чтобы увидеть, как ваши запросы работают в производственной среде. Обычно сама база данных может отображать отчёты о медленных запросах, проблемах с масштабированием, достижение сетью своих пределов и т.д. Решения вроде Application Insights очень хорошо это показывают. Также довольно просто добавить время выполнения запроса в журналы и автоматизировать отчёты на их основе.
Продолжение следует…
Источник: https://michaelscodingspot.com/slow-asp-net-server/
Почему ASP.NET Приложение Такое Медленное? 10 Проблем с Производительностью и Их Решения
Проблемы с производительностью сервера могут возникать по разным причинам. Проблемы с памятью, медленные запросы к базе данных и слишком мало машин - вот лишь некоторые из них. В этой серии постов расскажу о 10 типах проблем, которые могут снижать производительность вашего сервера.
1. Медленные вызовы базы данных
Быстрое взаимодействие БД, вероятно, самое важное условие для хорошей производительности. По крайней мере, в большинстве приложений. К сожалению, есть много вещей, которые могут пойти не так, и даже невинно выглядящие реализации могут вызывать проблемы. Вот некоторые проблемы, которые могут приводить к медленным запросам к БД и снижать производительность вашего приложения:
- Плохой дизайн схемы
- Плохая стратегия индексации и выполнение действий в приложении, а не в БД (см. производительность в EF Core).
- БД находится далеко от сервера.
Лучше всего разместить БД географически близко к вашим серверам, оптимально в том же центре обработки данных.
- Использование БД способом, для которого она не была создана.
Не все базы данных одинаковы. Некоторые из них идеально подходят для хранения пар «ключ-значение», другие - для транзакций, третьи по-прежнему идеально подходят для хранения журналов. Используйте лучшую БД для ваших нужд. Например, документоориентированная БД, вроде MongoDB, плохо справляется с операциями JOIN, и их использование может снизить производительность. Но она отлично подходит для хранения документов с большим количеством данных. Таким образом, одним из решений может быть дублирование информации между документами вместо использования
JOIN
.- У БД недостаточно ресурсов.
Хотя очевидным решением будет масштабирование ваших серверов, не забывайте, что и базы данных должны масштабироваться. Например, в Azure SQL Server вам нужно будет следить за DTU (единицами транзакций базы данных). В других БД вам нужно следить за хранилищем, оперативной памятью, сетью и процессором. И не всегда система ясно предупреждает, когда вы приближаетесь к пределу. Всё просто начинает замедляться, и вы задаётесь вопросом, что, чёрт возьми, происходит.
- Неэффективные запросы всегда возможны. Если вы используете Entity Framework, сгенерированный SQL не всегда оптимален.
- Требуется каждый раз восстанавливать соединение. Если ваши соединения с БД не объединены в пул должным образом, возможно, соединение пересоздаётся для каждого запроса.
- Рассмотрите хранимые процедуры, когда сложный запрос занимает много времени.
- Плохая стратегия сегментирования.
Позаботьтесь о том, чтобы сгруппировать связанные данные в одном сегменте, иначе вы рискуете запрашивать несколько сегментов в одном запросе.
Самая сложная часть решения этих проблем - это изначально их идентифицировать. Есть много инструментов, чтобы увидеть, как ваши запросы работают в производственной среде. Обычно сама база данных может отображать отчёты о медленных запросах, проблемах с масштабированием, достижение сетью своих пределов и т.д. Решения вроде Application Insights очень хорошо это показывают. Также довольно просто добавить время выполнения запроса в журналы и автоматизировать отчёты на их основе.
Продолжение следует…
Источник: https://michaelscodingspot.com/slow-asp-net-server/
День восемьсот шестьдесят четвёртый.
Почему ASP.NET Приложение Такое Медленное? 10 Проблем с Производительностью и Их Решения. Продолжение
Начало (1)
2. Давление на память (Memory pressure)
Одной из наиболее распространённых проблем на серверах с высокой нагрузкой является давление на память. В этом состоянии сборщик мусора не успевает частыми созданиями и уничтожениями объектов в памяти. Когда сборщик мусора находится под давлением, ваш сервер тратит больше времени на сборку мусора и меньше времени на выполнение кода.
Это может произойти в нескольких случаях. Самый распространенный случай - когда заканчивается память. Когда вы достигнете предела памяти, сборщик мусора «паникует» и начинает инициировать более частые полные сборки мусора (они самые дорогие). Но вопрос в том, почему это вообще происходит? Почему возникает нехватка памяти? Причиной этого обычно является плохое управление кэшем или утечки памяти. Это довольно легко выяснить с помощью профилировщика, сделав снимок памяти и проверив, что занимает место.
Как и в случае с БД, самое важное - понять, что проблемы именно с памятью. Самый простой способ узнать это - использовать счетчики производительности.
Подробнее о работе с памятью.
3. Неоптимальный режим GC
Сборщик мусора .NET имеет два разных режима: режим GC рабочей станции и режим GC сервера. Первый оптимизирован для быстрого ответа с минимальным использованием ресурсов, а второй - для высокой пропускной способности.
Среда выполнения .NET по умолчанию устанавливает режим рабочей станции в настольных приложениях и режим сервера на серверах. Это значение по умолчанию почти всегда подходит. В случае сервера сборщик мусора будет использовать гораздо больше машинных ресурсов, но сможет обрабатывать больше запросов. Другими словами, у процесса будет больше потоков, выделенных для сборки мусора, и он сможет освобождать больше байт памяти в секунду.
По какой-либо причине ваш сервер может работать в режиме рабочей станции, и переход в режим сервера повысит производительность. В редких случаях вам может потребоваться установить режим сборки мусора сервера на рабочую станцию, что может быть разумным, если вы хотите, чтобы сервер потреблял меньше машинных ресурсов.
Подробнее про сборщик мусора см. посты по тегу #GC.
4. Отсутствие кэширования
Кэширование может быть отличным методом оптимизации. Канонический пример: когда клиент отправляет запрос, сервер может сохранить результат в кэше. Когда клиент снова отправляет тот же запрос (это может быть другой клиент или тот же самый), серверу не нужно снова запрашивать базу данных или производить какие-либо вычисления для получения результата. Он просто извлекает его из кэша.
Простой пример этого - поиск чего-либо в Google. Если это что-то распространённое, то, вероятно, это запрашивают много раз в день. Нет смысла повторять всю магию Google, чтобы получить первую страницу с теми же 10 результатами. Её можно получить из кэша.
Компромисс в том, что кэш добавляет сложности. Во-первых, вам нужно время от времени аннулировать этот кэш. В случае поиска Google учтите, что при поиске новостей нельзя всегда возвращать один и тот же результат. Другая проблема с кэшем заключается в том, что при неправильном управлении он может раздуться и вызвать проблемы с памятью.
В ASP.NET, есть отличные реализации кеширования, которые делают большую часть работы за вас.
Продолжение следует…
Источник: https://michaelscodingspot.com/slow-asp-net-server/
Почему ASP.NET Приложение Такое Медленное? 10 Проблем с Производительностью и Их Решения. Продолжение
Начало (1)
2. Давление на память (Memory pressure)
Одной из наиболее распространённых проблем на серверах с высокой нагрузкой является давление на память. В этом состоянии сборщик мусора не успевает частыми созданиями и уничтожениями объектов в памяти. Когда сборщик мусора находится под давлением, ваш сервер тратит больше времени на сборку мусора и меньше времени на выполнение кода.
Это может произойти в нескольких случаях. Самый распространенный случай - когда заканчивается память. Когда вы достигнете предела памяти, сборщик мусора «паникует» и начинает инициировать более частые полные сборки мусора (они самые дорогие). Но вопрос в том, почему это вообще происходит? Почему возникает нехватка памяти? Причиной этого обычно является плохое управление кэшем или утечки памяти. Это довольно легко выяснить с помощью профилировщика, сделав снимок памяти и проверив, что занимает место.
Как и в случае с БД, самое важное - понять, что проблемы именно с памятью. Самый простой способ узнать это - использовать счетчики производительности.
Подробнее о работе с памятью.
3. Неоптимальный режим GC
Сборщик мусора .NET имеет два разных режима: режим GC рабочей станции и режим GC сервера. Первый оптимизирован для быстрого ответа с минимальным использованием ресурсов, а второй - для высокой пропускной способности.
Среда выполнения .NET по умолчанию устанавливает режим рабочей станции в настольных приложениях и режим сервера на серверах. Это значение по умолчанию почти всегда подходит. В случае сервера сборщик мусора будет использовать гораздо больше машинных ресурсов, но сможет обрабатывать больше запросов. Другими словами, у процесса будет больше потоков, выделенных для сборки мусора, и он сможет освобождать больше байт памяти в секунду.
По какой-либо причине ваш сервер может работать в режиме рабочей станции, и переход в режим сервера повысит производительность. В редких случаях вам может потребоваться установить режим сборки мусора сервера на рабочую станцию, что может быть разумным, если вы хотите, чтобы сервер потреблял меньше машинных ресурсов.
Подробнее про сборщик мусора см. посты по тегу #GC.
4. Отсутствие кэширования
Кэширование может быть отличным методом оптимизации. Канонический пример: когда клиент отправляет запрос, сервер может сохранить результат в кэше. Когда клиент снова отправляет тот же запрос (это может быть другой клиент или тот же самый), серверу не нужно снова запрашивать базу данных или производить какие-либо вычисления для получения результата. Он просто извлекает его из кэша.
Простой пример этого - поиск чего-либо в Google. Если это что-то распространённое, то, вероятно, это запрашивают много раз в день. Нет смысла повторять всю магию Google, чтобы получить первую страницу с теми же 10 результатами. Её можно получить из кэша.
Компромисс в том, что кэш добавляет сложности. Во-первых, вам нужно время от времени аннулировать этот кэш. В случае поиска Google учтите, что при поиске новостей нельзя всегда возвращать один и тот же результат. Другая проблема с кэшем заключается в том, что при неправильном управлении он может раздуться и вызвать проблемы с памятью.
В ASP.NET, есть отличные реализации кеширования, которые делают большую часть работы за вас.
Продолжение следует…
Источник: https://michaelscodingspot.com/slow-asp-net-server/
День восемьсот шестьдесят пятый.
Почему ASP.NET Приложение Такое Медленное? 10 Проблем с Производительностью и Их Решения. Продолжение
Начало (1)
Продолжение (2-4)
5. Ненужные клиентские запросы
Иногда удаётся значительно сократить количество клиентских запросов. Уменьшите это число, и вам потребуется будет меньше серверных машин или уменьшится нагрузка на существующие. Вот несколько способов сделать это:
- Тротлинг.
Рассмотрим механизм автозаполнения при поиске в Google. Когда вы начинаете вводить буквы, Google показывает раскрывающийся список с наиболее частыми поисковыми запросами, начинающимися с этих букв. Чтобы выдать эти данные автозаполнения, Google должен получить их с сервера. Допустим, вы набираете «Табуляция или пробелы». Google может отправить на свой сервер 15 запросов - на «Т», «Та», «Таб» и так далее. Но в этом нет необходимости. Лучше реализовать простой механизм тротлинга, который ожидает, пока вы не перестанете печатать, в течение 500 миллисекунд, а затем отправляет один запрос.
- Кэширование на стороне клиента.
Продолжая наш пример автозаполнения в поиске Google, есть много запросов, которые начинаются с одних и тех же слов. например, «Почему…», «Надо ли…», «Где…» и т. д. Вместо того, чтобы отправлять запросы для них каждый раз, Google может заранее сохранять наиболее распространённые результаты автозаполнения на стороне клиента, исключая ненужные запросы.
- Пакетная обработка.
Предположим на секунду, что Google шпионит за действиями пользователей, чтобы воспользоваться персонализированными данными… (предположим!). При использовании Gmail может потребоваться отправлять данные телеметрии каждый раз, когда вы читаете электронное письмо и наводите указатель мыши на определённое слово. Google может отправлять запрос для каждого такого случая, но будет более эффективным сохранить несколько таких случаев, а затем отправить их в одном запросе.
6. Зависание запросов
В определённых условиях запросы зависают. То есть вы отправляете запрос, но не получаете ответа. Или, скорее, вы в итоге получите ответ о тайм-ауте. Это может происходить, например, если возникла взаимная блокировка в коде, обрабатывающем запрос. Или, если у вас есть какой-то бесконечный цикл, который блокирует процессор. Или если вы бесконечно ждёте чего-то, что никогда не приходит - например, сообщения из очереди, длинного ответа базы данных или ответа от стороннего сервиса.
Под капотом, когда происходит зависание запроса, оно вешает один или несколько потоков. Но приложение продолжает работу, используя другие потоки для новых запросов. Если предположить, что это зависание воспроизводится при дополнительных запросах, со временем будет зависать всё больше потоков. Последствия зависят от причины зависания. Если это зависание процессора, например бесконечный цикл, мощности процессора довольно быстро исчерпаются, что приведёт к очень медленным ответам на запросы. В конце концов, IIS начнёт возвращать код ответа 503 (сервис недоступен). Если причиной является взаимная блокировка, то это постепенно приведёт к проблемам с памятью и производительностью, а в итоге - к тем же результатам - очень медленным ответам и ошибкам 503.
Таким образом, зависания запросов могут сильно сказаться на производительности вашего сервера, если они постоянно возникают.
Решение - устранить основную причину проблемы. Вам нужно сначала определить, что в реальности приводит к зависаниям, а затем предпринять шаги для их отладки.
7. Отсутствие масштабирования
Проблема очевидна, но я все же упомяну о ней. По мере того, как использование вашего приложения растёт, вы должны подумать, как организовать бОльшую пропускную способность.
Решение, конечно, в масштабировании. Это можно сделать двумя способами: вертикальное (также известное как scaling up - больше ядер CPU и памяти) и горизонтальное (также известное как scaling out - добавление большего количества машин). Облачные провайдеры обычно предлагают варианты простого автоматического масштабирования, которые стоит рассмотреть.
Окончание следует…
Источник: https://michaelscodingspot.com/slow-asp-net-server/
Почему ASP.NET Приложение Такое Медленное? 10 Проблем с Производительностью и Их Решения. Продолжение
Начало (1)
Продолжение (2-4)
5. Ненужные клиентские запросы
Иногда удаётся значительно сократить количество клиентских запросов. Уменьшите это число, и вам потребуется будет меньше серверных машин или уменьшится нагрузка на существующие. Вот несколько способов сделать это:
- Тротлинг.
Рассмотрим механизм автозаполнения при поиске в Google. Когда вы начинаете вводить буквы, Google показывает раскрывающийся список с наиболее частыми поисковыми запросами, начинающимися с этих букв. Чтобы выдать эти данные автозаполнения, Google должен получить их с сервера. Допустим, вы набираете «Табуляция или пробелы». Google может отправить на свой сервер 15 запросов - на «Т», «Та», «Таб» и так далее. Но в этом нет необходимости. Лучше реализовать простой механизм тротлинга, который ожидает, пока вы не перестанете печатать, в течение 500 миллисекунд, а затем отправляет один запрос.
- Кэширование на стороне клиента.
Продолжая наш пример автозаполнения в поиске Google, есть много запросов, которые начинаются с одних и тех же слов. например, «Почему…», «Надо ли…», «Где…» и т. д. Вместо того, чтобы отправлять запросы для них каждый раз, Google может заранее сохранять наиболее распространённые результаты автозаполнения на стороне клиента, исключая ненужные запросы.
- Пакетная обработка.
Предположим на секунду, что Google шпионит за действиями пользователей, чтобы воспользоваться персонализированными данными… (предположим!). При использовании Gmail может потребоваться отправлять данные телеметрии каждый раз, когда вы читаете электронное письмо и наводите указатель мыши на определённое слово. Google может отправлять запрос для каждого такого случая, но будет более эффективным сохранить несколько таких случаев, а затем отправить их в одном запросе.
6. Зависание запросов
В определённых условиях запросы зависают. То есть вы отправляете запрос, но не получаете ответа. Или, скорее, вы в итоге получите ответ о тайм-ауте. Это может происходить, например, если возникла взаимная блокировка в коде, обрабатывающем запрос. Или, если у вас есть какой-то бесконечный цикл, который блокирует процессор. Или если вы бесконечно ждёте чего-то, что никогда не приходит - например, сообщения из очереди, длинного ответа базы данных или ответа от стороннего сервиса.
Под капотом, когда происходит зависание запроса, оно вешает один или несколько потоков. Но приложение продолжает работу, используя другие потоки для новых запросов. Если предположить, что это зависание воспроизводится при дополнительных запросах, со временем будет зависать всё больше потоков. Последствия зависят от причины зависания. Если это зависание процессора, например бесконечный цикл, мощности процессора довольно быстро исчерпаются, что приведёт к очень медленным ответам на запросы. В конце концов, IIS начнёт возвращать код ответа 503 (сервис недоступен). Если причиной является взаимная блокировка, то это постепенно приведёт к проблемам с памятью и производительностью, а в итоге - к тем же результатам - очень медленным ответам и ошибкам 503.
Таким образом, зависания запросов могут сильно сказаться на производительности вашего сервера, если они постоянно возникают.
Решение - устранить основную причину проблемы. Вам нужно сначала определить, что в реальности приводит к зависаниям, а затем предпринять шаги для их отладки.
7. Отсутствие масштабирования
Проблема очевидна, но я все же упомяну о ней. По мере того, как использование вашего приложения растёт, вы должны подумать, как организовать бОльшую пропускную способность.
Решение, конечно, в масштабировании. Это можно сделать двумя способами: вертикальное (также известное как scaling up - больше ядер CPU и памяти) и горизонтальное (также известное как scaling out - добавление большего количества машин). Облачные провайдеры обычно предлагают варианты простого автоматического масштабирования, которые стоит рассмотреть.
Окончание следует…
Источник: https://michaelscodingspot.com/slow-asp-net-server/
День восемьсот шестьдесят шестой.
Почему ASP.NET Приложение Такое Медленное? 10 Проблем с Производительностью и Их Решения. Окончание
Начало (1)
Продолжение (2-4)
Продолжение (5-7)
8. Сбои сервера
Как и зависания запросов, сбои сервера могут проявляться как проблемы с производительностью. Когда во время запроса происходит обычное исключение, приложение не вылетает. Сервер возвращает ответ об ошибке 500, и всё продолжается как обычно. Но сбой может произойти, если исключение случится вне контекста запроса, например, в потоке, который вы запустили сами. Помимо этого, существуют катастрофические исключения, такие как
Когда приложение ASP.NET, размещённое в IIS, даёт сбой, сервер временно отключается. IIS выполняет перезапуск пула приложений, который перезапустит ваш сервер и вернётся к обычному режиму работы. Последствием для клиента будут временные медленные ответы или ошибки 503.
В зависимости от вашего приложения один сбой может не быть концом света, но повторяющиеся сбои сильно замедлят работу сервера, скрывая настоящую причину под проблемой с производительностью. Решением этой проблемы, конечно же, является устранение основной причины сбоя.
9. Чрезмерная функциональность для каждого запроса
Довольно часто ваши запросы украшают дополнительными функциями. Они могут иметь форму промежуточного ПО ASP.NET Core или фильтров действий. Эти функции могут включать в логирование, авторизацию, добавление заголовков ответов или что-то еще. Обратите особое внимание на эти фрагменты кода, потому что они выполняются для каждого запроса.
Например, промежуточное ПО, которое проверяет при каждом запросе, есть ли у пользователя действующая лицензия. Проверка состоит в отправке запроса на сервер идентификации и запросе к базе данных. Таким образом, каждый запрос должен ждать этих ответов, добавляя кучу времени и увеличивая нагрузку как на сервер идентификации, так и на базу данных. Решением является простой механизм кэширования, который сохраняет информацию о лицензии в памяти на некоторое время.
Если у вас есть аналогичные функции, кеширование может быть хорошим вариантом. Другой вариант - делать что-то партиями. Например, писать в лог каждые 1000 запросов, а не при каждом запросе. Или, возможно, помещать сообщения в очередь, превратив эту функцию в асинхронную.
10. Синхронность против асинхронности
Когда ваш сервер отправляет запрос какому-то сервису и должен дождаться ответа, возникает риск. Что, если этот другой сервис занят обработкой большой очереди запросов? Что, если у него есть проблема с производительностью, от которой вам тоже придётся временно страдать?
Популярный способ решения этой проблемы - изменить синхронный вызов на асинхронный. Обычно это делается с помощью сервиса очереди, такой как Kafka или RabbitMQ. Вместо того, чтобы отправлять запрос и ждать ответа, вы отправляете сообщение в такую очередь. Другой сервис извлекает эти сообщения и обрабатывает их.
А если вам нужен ответ, то сервис отправляет сообщение с ответом в ту же очередь. Вы также будете извлекать сообщения из очереди, и когда придёт ответ, сможете обработать его при необходимости, вне контекста исходного запроса. Если вам нужно отправить ответ клиенту, можно использовать push-уведомление, например, в SignalR.
Преимущество этого подхода в том, что системные компоненты никогда активно не ждут обслуживания. Всё обрабатывается асинхронно. Ещё одно преимущество в том, что сервисы могут быть слабо связаны друг с другом.
Недостаток в том, что это намного сложнее. Вместо простого запроса к сервису вам нужно создать очередь, отправлять и извлекать сообщения, а также работать с такими вещами, как сбой службы, когда сообщение было извлечено, но не обработано.
Источник: https://michaelscodingspot.com/slow-asp-net-server/
Почему ASP.NET Приложение Такое Медленное? 10 Проблем с Производительностью и Их Решения. Окончание
Начало (1)
Продолжение (2-4)
Продолжение (5-7)
8. Сбои сервера
Как и зависания запросов, сбои сервера могут проявляться как проблемы с производительностью. Когда во время запроса происходит обычное исключение, приложение не вылетает. Сервер возвращает ответ об ошибке 500, и всё продолжается как обычно. Но сбой может произойти, если исключение случится вне контекста запроса, например, в потоке, который вы запустили сами. Помимо этого, существуют катастрофические исключения, такие как
OutOfMemoryException
, ExecutionEngineException
и моё любимое StackOverflowException
. Они приводят к сбою процесса независимо от того, сколько блоков catch вы разместите.Когда приложение ASP.NET, размещённое в IIS, даёт сбой, сервер временно отключается. IIS выполняет перезапуск пула приложений, который перезапустит ваш сервер и вернётся к обычному режиму работы. Последствием для клиента будут временные медленные ответы или ошибки 503.
В зависимости от вашего приложения один сбой может не быть концом света, но повторяющиеся сбои сильно замедлят работу сервера, скрывая настоящую причину под проблемой с производительностью. Решением этой проблемы, конечно же, является устранение основной причины сбоя.
9. Чрезмерная функциональность для каждого запроса
Довольно часто ваши запросы украшают дополнительными функциями. Они могут иметь форму промежуточного ПО ASP.NET Core или фильтров действий. Эти функции могут включать в логирование, авторизацию, добавление заголовков ответов или что-то еще. Обратите особое внимание на эти фрагменты кода, потому что они выполняются для каждого запроса.
Например, промежуточное ПО, которое проверяет при каждом запросе, есть ли у пользователя действующая лицензия. Проверка состоит в отправке запроса на сервер идентификации и запросе к базе данных. Таким образом, каждый запрос должен ждать этих ответов, добавляя кучу времени и увеличивая нагрузку как на сервер идентификации, так и на базу данных. Решением является простой механизм кэширования, который сохраняет информацию о лицензии в памяти на некоторое время.
Если у вас есть аналогичные функции, кеширование может быть хорошим вариантом. Другой вариант - делать что-то партиями. Например, писать в лог каждые 1000 запросов, а не при каждом запросе. Или, возможно, помещать сообщения в очередь, превратив эту функцию в асинхронную.
10. Синхронность против асинхронности
Когда ваш сервер отправляет запрос какому-то сервису и должен дождаться ответа, возникает риск. Что, если этот другой сервис занят обработкой большой очереди запросов? Что, если у него есть проблема с производительностью, от которой вам тоже придётся временно страдать?
Популярный способ решения этой проблемы - изменить синхронный вызов на асинхронный. Обычно это делается с помощью сервиса очереди, такой как Kafka или RabbitMQ. Вместо того, чтобы отправлять запрос и ждать ответа, вы отправляете сообщение в такую очередь. Другой сервис извлекает эти сообщения и обрабатывает их.
А если вам нужен ответ, то сервис отправляет сообщение с ответом в ту же очередь. Вы также будете извлекать сообщения из очереди, и когда придёт ответ, сможете обработать его при необходимости, вне контекста исходного запроса. Если вам нужно отправить ответ клиенту, можно использовать push-уведомление, например, в SignalR.
Преимущество этого подхода в том, что системные компоненты никогда активно не ждут обслуживания. Всё обрабатывается асинхронно. Ещё одно преимущество в том, что сервисы могут быть слабо связаны друг с другом.
Недостаток в том, что это намного сложнее. Вместо простого запроса к сервису вам нужно создать очередь, отправлять и извлекать сообщения, а также работать с такими вещами, как сбой службы, когда сообщение было извлечено, но не обработано.
Источник: https://michaelscodingspot.com/slow-asp-net-server/
👍1
День восемьсот шестьдесят седьмой.
Работа с Текстом в .NET с Помощью Humanizer
Для передачи сообщений в UI нам довольно часто требуется работать с текстом. NuGet пакет Humanizer серьёзно упрощает эту работу, позволяя выполнять десятки различных преобразований с помощью вызова методов расширения на строках и числах. Например:
Пока не сильно впечатляет? Подождите, вот лишь некоторые функции, которые мне показались наиболее интересными:
-
-
-
-
-
-
-
-
-
-
-
Локализованные варианты пакета доступны более, чем на 15 языках, включая русский.
Подробнее читайте на страничке проекта в GitHub.
Источник: https://youtu.be/bLKXqJwRNSY
Работа с Текстом в .NET с Помощью Humanizer
Для передачи сообщений в UI нам довольно часто требуется работать с текстом. NuGet пакет Humanizer серьёзно упрощает эту работу, позволяя выполнять десятки различных преобразований с помощью вызова методов расширения на строках и числах. Например:
"hello_world".Humanize(); // hello worldПомимо этого, методу можно передать значение перечисления
LetterCasing
и сделать заглавной первую букву строки, первую букву каждого слова или все буквы. При этом он не трогает популярные аббревиатуры, вроде HTML. Возможно и обратное преобразование из предложения в PascalCase строку.Пока не сильно впечатляет? Подождите, вот лишь некоторые функции, которые мне показались наиболее интересными:
-
Truncate(n)
– обрезает строку до n символов и добавляет многоточие,-
Humanize()
, применённая к значению enum, выдаёт либо предложение из PascalCase имени значения, либо значение атрибута Description
, если он задан. Кроме того, если значение помечено атрибутом Display
с данными локализации (Description
и ResourceType
), Humanize()
выдаст локализованное описание.-
Humanize()
на значении типа DateTime
выдаст популярные в соцсетях строки о времени размещения поста: (минуту назад
, час назад
, вчера
и т.п.) – всё относительно текущего времени.-
Humanize()
на значении типа TimeSpan
распишет период с заданной точностью, вроде: 2 недели, 3 дня, 6 часов и 24 минуты
.-
ToQuantity(n)
– выдаст строку вида «n штук
» с правильным окончанием.-
Ordinalize()
на целом значении выдаст порядковый номер, вроде 1ый
, 2ой
и т.п.-
ToWords()
на числе выдаст число словами, например: сто двадцать три
.-
ToOrdinalWords()
на числе выдаст порядковый номер.-
ToOrdinalWords()
на дате выдаст полное написание даты в текущей культуре, например, January 1st, 2015
для en-US.-
ToRoman()
и FromRoman()
– перевод из арабских чисел в римские и наоборот.-
Seconds()
, Minutes()
, Hours()
,… позволяют использовать Fluent API для дат, например: DateTime.Now + 2.Days() + 3.Hours() - 5.Minutes()
- Bytes()
, Kilobytes()
, Megabytes()
,… - аналогично позволяют переводить размеры в байтах, а Humanize()
на результате выдаст «человеческое» представление размера, например:(.5).Gigabytes().Humanize(); // 512 MBИ это только некоторые функции, и только базовый вариант их использования. На самом деле, для каждой есть несколько параметров для тонкой настройки.
Локализованные варианты пакета доступны более, чем на 15 языках, включая русский.
Подробнее читайте на страничке проекта в GitHub.
Источник: https://youtu.be/bLKXqJwRNSY
День восемьсот шестьдесят восьмой. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
88. Убунту-программирование
Часто мы пишем код в изоляции, и этот код отражает нашу личную интерпретацию проблемы, а также наше индивидуальное видение решения. Мы можем быть частью команды, но мы изолированы от команды. Мы слишком легко забываем, что этот код, созданный в изоляции, будет выполняться, использоваться, расширяться и использоваться другими. Легко упустить из виду социальную сторону создания программного обеспечения. Создание программного обеспечения - это техническая задача, смешанная с социальной задачей. Нам просто нужно чаще поднимать голову, чтобы понять, что мы не работаем изолированно, и мы несём общую ответственность за повышение вероятности успеха для всех, а не только для команды разработчиков.
Вы можете писать качественный код изолированно, всё время находясь в себе. С одной стороны, это эгоцентричный подход (эго в смысле эгоизма, а в смысле личности). Этого же придерживается Дзен: когда вы создаёте код, всё крутится вокруг вас. Я всегда стараюсь жить настоящим моментом, потому что это помогает мне писать более качественно, но при этом я живу в собственном моменте. А как насчёт момента моей команды? Мой момент совпадает с моментом команды?
На зулусском языке философия Убунту формулируется как «Umuntu ngumuntu ngabantu», что примерно переводится как «Человек - это личность в глазах (других) личностей». Мне становится лучше, потому что ты делаешь меня лучше. Обратной стороной является то, что ты становишься хуже в том, что делаешь, когда я плох в том, что я делаю. Что касается разработчиков, мы можем сузить эту формулировку до «Разработчик - это разработчик в глазах (других) разработчиков». Или совсем узко: «Код - это код с точки зрения (другого) кода».
Качество кода, который я пишу, влияет на качество кода, который вы пишете. Что делать, если мой код некачественный? Даже если вы пишете очень чистый код, именно в тех местах, где вы используете мой код, качество вашего кода упадёт до уровня, близкого к качеству моего кода. Вы можете применить множество схем и приёмов, чтобы ограничить урон, но ущерб уже нанесён. Я заставил вас сделать больше, чем нужно, просто потому что я не думал о вас, когда я проживал свой момент.
Я могу считать свой код чистым, но я всё ещё могу улучшить его при помощи Убунту-программирования. Как выглядит Убунту-программирование? Это похоже на создание хорошего чистого кода. Но дело не в самом коде. Дело в создании этого кода. Программирование для ваших коллег, согласно философии Убунту, поможет команде разделить ваши ценности и принципы. Следующий человек, который каким-либо образом коснется вашего кода, станет лучше, как человек и как разработчик.
Дзен – это про личность. Убунту - это дзен для группы людей. Мы очень редко мы создаём код только для самих себя.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Aslam Khan
97 Вещей, Которые Должен Знать Каждый Программист
88. Убунту-программирование
Часто мы пишем код в изоляции, и этот код отражает нашу личную интерпретацию проблемы, а также наше индивидуальное видение решения. Мы можем быть частью команды, но мы изолированы от команды. Мы слишком легко забываем, что этот код, созданный в изоляции, будет выполняться, использоваться, расширяться и использоваться другими. Легко упустить из виду социальную сторону создания программного обеспечения. Создание программного обеспечения - это техническая задача, смешанная с социальной задачей. Нам просто нужно чаще поднимать голову, чтобы понять, что мы не работаем изолированно, и мы несём общую ответственность за повышение вероятности успеха для всех, а не только для команды разработчиков.
Вы можете писать качественный код изолированно, всё время находясь в себе. С одной стороны, это эгоцентричный подход (эго в смысле эгоизма, а в смысле личности). Этого же придерживается Дзен: когда вы создаёте код, всё крутится вокруг вас. Я всегда стараюсь жить настоящим моментом, потому что это помогает мне писать более качественно, но при этом я живу в собственном моменте. А как насчёт момента моей команды? Мой момент совпадает с моментом команды?
На зулусском языке философия Убунту формулируется как «Umuntu ngumuntu ngabantu», что примерно переводится как «Человек - это личность в глазах (других) личностей». Мне становится лучше, потому что ты делаешь меня лучше. Обратной стороной является то, что ты становишься хуже в том, что делаешь, когда я плох в том, что я делаю. Что касается разработчиков, мы можем сузить эту формулировку до «Разработчик - это разработчик в глазах (других) разработчиков». Или совсем узко: «Код - это код с точки зрения (другого) кода».
Качество кода, который я пишу, влияет на качество кода, который вы пишете. Что делать, если мой код некачественный? Даже если вы пишете очень чистый код, именно в тех местах, где вы используете мой код, качество вашего кода упадёт до уровня, близкого к качеству моего кода. Вы можете применить множество схем и приёмов, чтобы ограничить урон, но ущерб уже нанесён. Я заставил вас сделать больше, чем нужно, просто потому что я не думал о вас, когда я проживал свой момент.
Я могу считать свой код чистым, но я всё ещё могу улучшить его при помощи Убунту-программирования. Как выглядит Убунту-программирование? Это похоже на создание хорошего чистого кода. Но дело не в самом коде. Дело в создании этого кода. Программирование для ваших коллег, согласно философии Убунту, поможет команде разделить ваши ценности и принципы. Следующий человек, который каким-либо образом коснется вашего кода, станет лучше, как человек и как разработчик.
Дзен – это про личность. Убунту - это дзен для группы людей. Мы очень редко мы создаём код только для самих себя.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Aslam Khan
День восемьсот шестьдесят девятый. #ЗаметкиНаПолях
Различные Способы Проверки на Null в C#
В .NET существует несколько способов проверки на null. Но не все они равнозначны. Рассмотрим различные способы проверки:
1. object.ReferenceEquals(obj, null)
2. object.Equals(obj, null)
Equals аналогичен
3. obj == null
Оператор
Заметьте, что is null не работает со структурами, кроме обнуляемых:
Различные Способы Проверки на Null в C#
В .NET существует несколько способов проверки на null. Но не все они равнозначны. Рассмотрим различные способы проверки:
object obj = ...;Есть 3 основных способа:
// Основные проверки
obj == null;
object.Equals(obj, null);
object.ReferenceEquals(obj, null);
// Аналогичны ReferenceEquals(obj, null)
obj is null;
(object)obj == null;
// Аналогичны !ReferenceEquals(obj, null)
obj is not object;
obj is not {};
// Не работает, выдаёт NullReferenceException
obj.Equals(null);
1. object.ReferenceEquals(obj, null)
ReferenceEquals
возвращает true
, если экземпляры объекта являются одним и тем же экземпляром. В этом случае он возвращает true
, если obj
имеет значение null.2. object.Equals(obj, null)
Equals аналогичен
ReferenceEquals
, когда один аргумент имеет значение null. Однако логика этого метода сложнее, чем ReferenceEquals
, и немного медленнее, поскольку вызов метода не всегда встраивается.3. obj == null
Оператор
==
аналогичен ReferenceEquals
, если вы не определяете оператор равенства для класса. Если оператор определён, компилятор использует его вместо оператора по умолчанию. В этом случае логика сравнения настраивается, и она может и не учитывать проверку на null. Вы можете заставить компилятор использовать оператор ==
, определённый для object
, путём явного преобразования объекта к object
.Заметьте, что is null не работает со структурами, кроме обнуляемых:
MyStruct a = default;Заметьте, что хотя сопоставления с образцом
// Ошибка компиляции
_ = a is null;
// Работает, только если MyStruct
// определяет оператор ==
_= a == null;
Span<char> span = default;
// Ошибка компиляции
_ = span is null;
// Работает, т.к. Span определяет оператор ==
_ = span == null;
int? b = null;
// Аналогично !b.HasValue
_ = b is null;
is not null
, is object
и is {}
аналогичны одной и той же проверке на null (см. выше), использование их вместе с объявлением переменной различается:// Ошибка компиляцииИсточник: https://www.meziantou.net/null-check-in-csharp.htm
if (obj is not null x) { … }
// OK, х – типа object
if (obj is object x) { … }
// OK, x – того же типа, что и obj
if (obj is {} x) { … }
День восемьсот семидесятый. #Оффтоп
Добрейшей пятницы. Пока желающие качают превью Visual Studio 2022, вот вам развлечение на это время.
Давненько я не рекомендовал интересных YouTube каналов. И вот на днях попался мне канал Dave’s Garage. А конкретнее, видео «Software Drag Racing: C++ vs C# vs Python - Which Will Win?» Какой язык программирования быстрее? Что может быть более холиварной темой?
Автор канала – David Plummer, бывший инженер операционных систем в Microsoft, работавший ещё аж над MS DOS и Windows 95 (в частности, он создатель Диспетчера задач Windows). Так вот, он решил проверить, какой язык быстрее справится с алгоритмом нахождения всех простых чисел меньше заданного.
В видео рассказывается про собственно алгоритм (сильно оптимизированный, байто…черы оценят), его реализацию на Python, C# и C++, ну и, собственно, бенчмарк в виде количества выполнений алгоритма за 5 секунд.
Результаты спойлерить не буду, смотрите видео.
Кстати, в GitHub Дейва есть реализации алгоритма чуть менее, чем на всех популярных языках, с дальнейшими оптимизациями от контрибуторов, многократно превосходящими по производительности результаты из видео.
А вообще, канал очень понравился. Олдам зайдут и другие видео с байками, вроде Почему возникает синий экран смерти, и почему он синий, Почему перезагрузка решает все проблемы (и при чём тут ботинки) или Секретная история активатора Windows.
Единственное замечание: требуется хороший уровень восприятия американского английского, потому что автор говорит довольно быстро и не всегда чётко.
Добрейшей пятницы. Пока желающие качают превью Visual Studio 2022, вот вам развлечение на это время.
Давненько я не рекомендовал интересных YouTube каналов. И вот на днях попался мне канал Dave’s Garage. А конкретнее, видео «Software Drag Racing: C++ vs C# vs Python - Which Will Win?» Какой язык программирования быстрее? Что может быть более холиварной темой?
Автор канала – David Plummer, бывший инженер операционных систем в Microsoft, работавший ещё аж над MS DOS и Windows 95 (в частности, он создатель Диспетчера задач Windows). Так вот, он решил проверить, какой язык быстрее справится с алгоритмом нахождения всех простых чисел меньше заданного.
В видео рассказывается про собственно алгоритм (сильно оптимизированный, байто…черы оценят), его реализацию на Python, C# и C++, ну и, собственно, бенчмарк в виде количества выполнений алгоритма за 5 секунд.
Результаты спойлерить не буду, смотрите видео.
Кстати, в GitHub Дейва есть реализации алгоритма чуть менее, чем на всех популярных языках, с дальнейшими оптимизациями от контрибуторов, многократно превосходящими по производительности результаты из видео.
А вообще, канал очень понравился. Олдам зайдут и другие видео с байками, вроде Почему возникает синий экран смерти, и почему он синий, Почему перезагрузка решает все проблемы (и при чём тут ботинки) или Секретная история активатора Windows.
Единственное замечание: требуется хороший уровень восприятия американского английского, потому что автор говорит довольно быстро и не всегда чётко.
День восемьсот семьдесят первый.
Странное Разрешение Имён Перечислений в C#
Рассмотрим следующий код:
Почему он выбирает
Согласно документации для
Если несколько членов перечисления имеют одно и то же значение, метод GetName гарантирует, что он вернёт имя одного из этих членов перечисления. Однако он не гарантирует, что всегда будет возвращать имя одного и того же члена перечисления.
Так что формально могло бы возвратиться что угодно. Почему же всё-таки возвращается
За объяснением можно обратиться к реализации GetEnumName().
Чтобы ускорить работу алгоритма, используется бинарный поиск. А он начинает с середины коллекции. Вот почему он находит значение B, которое расположено как раз в середине упорядоченного списка. Обратите внимание, что список упорядочивается по значению перечисления, а не по имени, но в нашем случае он уже упорядочен, поскольку все значения одинаковы.
Источник: https://stackoverflow.com/questions/67091644/weird-enum-name-resolution-in-c-sharp
Странное Разрешение Имён Перечислений в C#
Рассмотрим следующий код:
using System;Странно, но этот код выдаёт строку
namespace Test
{
enum Foo {
A = 1, B = 1, C = 1
}
public static class Program
{
public static void Main()
{
Console.WriteLine("{0}, {1}, {2}",
Foo.A, Foo.B, Foo.C);
}
}
}
B, B, B
. Это поведение одинаково и в .NET Framework, и в .NET Core 3.x, и в .NET 5.Почему он выбирает
B
?Согласно документации для
Enum.GetName()
:Если несколько членов перечисления имеют одно и то же значение, метод GetName гарантирует, что он вернёт имя одного из этих членов перечисления. Однако он не гарантирует, что всегда будет возвращать имя одного и того же члена перечисления.
Так что формально могло бы возвратиться что угодно. Почему же всё-таки возвращается
B
?За объяснением можно обратиться к реализации GetEnumName().
Чтобы ускорить работу алгоритма, используется бинарный поиск. А он начинает с середины коллекции. Вот почему он находит значение B, которое расположено как раз в середине упорядоченного списка. Обратите внимание, что список упорядочивается по значению перечисления, а не по имени, но в нашем случае он уже упорядочен, поскольку все значения одинаковы.
Источник: https://stackoverflow.com/questions/67091644/weird-enum-name-resolution-in-c-sharp
День восемьсот семьдесят второй. #Оффтоп #КакСтатьСеньором
Проектирование
Почему я ставлю проектирование после написания кода и тестирования? Оно может идти и первым, но, если бы я не писал код и не тестировал его в среде, в которой я нахожусь (под средой тут понимается в том числе и стек технологий), я, вероятно, не смог бы спроектировать систему, которая учитывает особенности среды.
При проектировании системы нужно о многом подумать:
- Какая будет нагрузка?
- Сколько существует пользователей и каков их ожидаемый прирост? (Это может повлиять на размер БД)
- Какие могут быть подводные камни в будущем?
Всё это нужно преобразовать в контрольный список требований. Тут важно соблюсти баланс: какую часть вы можете спроектировать, прежде чем приступить к реализации? Когда имеет смысл нырять с головой в реализацию, а когда делать шаг назад?
Конечно, просто собрать требования - это еще не всё, о чем стоит подумать. Включение процессов разработки в проектирование также окупается:
- Как будет организовано написание кода, сборка, развёртывание и CI/CD?
- Как мы будем проводить сквозное и нагрузочное тестирование?
- Как мы будем управлять секретами?
Например, кто бы мог подумать, что управление секретами в производственной среде может оказаться таким сложным? Вы не можете поместить их в код, так как тогда их сможет увидеть любой.
Поместить их в переменные среды? Хорошая идея. Как их туда поместить и как ими управлять? Хранить файл секретов? Откуда он будет браться и как его изменять? И т.д., и т.п. Кроме того, мы не хотим, чтобы всё это выполнялось вручную. Можно рассмотреть базу данных, чтобы код получал секреты из базы при запуске. Опять же, подход может сильно отличаться при использовании облачного провайдера, где не нужно много думать о секретах, т.к. для этого есть специальный функционал.
Проектирование с учетом поддержки
Проектировать системы - это увлекательно. Поддерживать их – не очень. Рано или поздно задаёшься вопросом, почему и как системы деградируют?
Во-первых, проблема в нежелании выбрасывать старые вещи, всегда добавляя новые. Склонность к добавлению вместо удаления (есть за вами такой грешок?)
Вторая проблема — это проектирование с учётом конечной цели. Система, которая эволюционирует, добавляя функционал, который не был в неё изначально заложен, никогда не работает так же хорошо, как система, разработанная с нуля для этого функционала.
Есть как минимум три способа снизить скорость деградации:
1. Разделяйте бизнес-логику и инфраструктуру. Обычно быстрее деградирует инфраструктура: увеличивается нагрузка, фреймворки устаревают, появляются уязвимости и т.д.
2. Стройте процессы вокруг поддержки. Обновляйте как новый, так и устаревший код. Это предотвращает различие между новыми и старыми частями и сохраняет весь код «современным».
3. Убедитесь, что вы на постоянной основе избавляетесь от всех ненужных/устаревших вещей.
Источник: https://neilkakkar.com/things-I-learnt-from-a-senior-dev.html
Автор оригинала – Neil Kakkar
Проектирование
Почему я ставлю проектирование после написания кода и тестирования? Оно может идти и первым, но, если бы я не писал код и не тестировал его в среде, в которой я нахожусь (под средой тут понимается в том числе и стек технологий), я, вероятно, не смог бы спроектировать систему, которая учитывает особенности среды.
При проектировании системы нужно о многом подумать:
- Какая будет нагрузка?
- Сколько существует пользователей и каков их ожидаемый прирост? (Это может повлиять на размер БД)
- Какие могут быть подводные камни в будущем?
Всё это нужно преобразовать в контрольный список требований. Тут важно соблюсти баланс: какую часть вы можете спроектировать, прежде чем приступить к реализации? Когда имеет смысл нырять с головой в реализацию, а когда делать шаг назад?
Конечно, просто собрать требования - это еще не всё, о чем стоит подумать. Включение процессов разработки в проектирование также окупается:
- Как будет организовано написание кода, сборка, развёртывание и CI/CD?
- Как мы будем проводить сквозное и нагрузочное тестирование?
- Как мы будем управлять секретами?
Например, кто бы мог подумать, что управление секретами в производственной среде может оказаться таким сложным? Вы не можете поместить их в код, так как тогда их сможет увидеть любой.
Поместить их в переменные среды? Хорошая идея. Как их туда поместить и как ими управлять? Хранить файл секретов? Откуда он будет браться и как его изменять? И т.д., и т.п. Кроме того, мы не хотим, чтобы всё это выполнялось вручную. Можно рассмотреть базу данных, чтобы код получал секреты из базы при запуске. Опять же, подход может сильно отличаться при использовании облачного провайдера, где не нужно много думать о секретах, т.к. для этого есть специальный функционал.
Проектирование с учетом поддержки
Проектировать системы - это увлекательно. Поддерживать их – не очень. Рано или поздно задаёшься вопросом, почему и как системы деградируют?
Во-первых, проблема в нежелании выбрасывать старые вещи, всегда добавляя новые. Склонность к добавлению вместо удаления (есть за вами такой грешок?)
Вторая проблема — это проектирование с учётом конечной цели. Система, которая эволюционирует, добавляя функционал, который не был в неё изначально заложен, никогда не работает так же хорошо, как система, разработанная с нуля для этого функционала.
Есть как минимум три способа снизить скорость деградации:
1. Разделяйте бизнес-логику и инфраструктуру. Обычно быстрее деградирует инфраструктура: увеличивается нагрузка, фреймворки устаревают, появляются уязвимости и т.д.
2. Стройте процессы вокруг поддержки. Обновляйте как новый, так и устаревший код. Это предотвращает различие между новыми и старыми частями и сохраняет весь код «современным».
3. Убедитесь, что вы на постоянной основе избавляетесь от всех ненужных/устаревших вещей.
Источник: https://neilkakkar.com/things-I-learnt-from-a-senior-dev.html
Автор оригинала – Neil Kakkar