.NET Разработчик
6.54K subscribers
442 photos
3 videos
14 files
2.12K links
Дневник сертифицированного .NET разработчика. Заметки, советы, новости из мира .NET и C#.

Для связи: @SBenzenko

Поддержать канал:
- https://boosty.to/netdeveloperdiary
- https://patreon.com/user?u=52551826
- https://pay.cloudtips.ru/p/70df3b3b
Download Telegram
День семьсот пятьдесят девятый. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
78. Шаг назад и автоматизация, автоматизация, автоматизация
Я работал с программистами, которые, когда их просили произвести подсчёт строк кода в модуле, вставляли все файлы в один текстовый редактор и использовали его функцию подсчёта строк. Затем они делали это снова на следующей неделе. И через неделю. Это было плохо.

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

Итак, почему люди выполняют одну и ту же задачу снова и снова, вместо того чтобы остановиться, сделать шаг назад и потратить время на её автоматизацию?

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

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

Распространённое заблуждение №3: чтобы автоматизировать это, мне нужно изучить экзотические инструменты
Вы можете пойти по длинному пути, используя полноценный консольный язык, например, bash или Power-Shell, и систему автоматизации сборки. Если же вам нужно взаимодействовать с веб-сайтами, можно использовать такие инструменты, как Selenium.

Распространённое заблуждение №4: я не могу автоматизировать эту задачу, потому что не могу работать с этим форматом файлов
Если для части вашего процесса требуются документы Word, электронные таблицы или изображения, это действительно может быть сложно автоматизировать. Но действительно ли это необходимо? Можете ли вы использовать обычный текст? CSV файлы вместо таблиц? XML/JSON? Часто небольшая подгонка процесса под автоматизацию может дать хорошие результаты и значительно снизить трудозатраты.

Распространённое заблуждение №5: у меня нет времени разбираться в этом
Вовсе не обязательно зазубрить все команды bash. Учитесь на ходу. Когда у вас есть задача, которую, по вашему мнению, можно и нужно автоматизировать, узнавайте об инструментах автоматизации ровно столько, сколько вам нужно. И делайте это на ранних этапах проекта, когда обычно легче найти время. Как только вы добьетесь успеха, вы (и ваш начальник) увидите, что имеет смысл инвестировать в автоматизацию.

Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Cay Horstmann
👍1
День семьсот шестьдесят девятый. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
79. Используйте Анализаторы Кода
Ценность тестирования - вот что вбивают в головы разработчикам ПО с ранних этапов их пути в программировании. В последние годы рост модульного тестирования, разработки, основанной на тестировании, и agile методов свидетельствует о всплеске интереса к максимальному использованию тестирования на всех этапах цикла разработки. Однако тестирование - это лишь один из многих инструментов, которые можно использовать для улучшения качества кода.

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

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

Более сложные инструменты, такие как Splint для C, Pylint для Python или анализаторы Roslyn для .NET настраиваются. То есть вы можете выбрать, какие ошибки и предупреждения будет выдавать инструмент, с помощью файла конфигурации, в командной строке или в вашей IDE. В некоторых случаях можно писать аннотации для анализатора прямо в коде.

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

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

Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Sarah Mount
День семьсот семьдесят четвёртый. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
80. Проверяйте Требуемое, а не Случайное Поведение
Распространённая проблема тестирования - предположение, что реализация делает именно то, на что вы хотите проверить. На первый взгляд, это скорее хорошо, чем плохо. Однако проблема становится очевидной, если перефразировать это предложение: распространённая ошибка при тестировании заключается в привязке тестов к особенностям реализации, когда эти особенности являются случайными и не имеют отношения к желаемой функциональности.

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

Например, для метода CompareTo(object obj) интерфейса IComparable, требования к результату заключаются в том, что:
- он отрицательный, если экземпляр класса стоит по порядку раньше, чем объект, переданный в аргументе метода,
- он положительный, если экземпляр класса стоит позже,
- он равен нулю если объекты считаются равными.
Этот стиль сравнения используется во многих API, включая компаратор для функций сортировки. И хотя конкретные значения –1 и +1 обычно используются в реализациях для обозначения отрицательного и положительного результатов, соответственно, программисты часто ошибочно предполагают, что эти значения и представляют фактическое требование, и, следовательно, пишут тесты, которые публично подтверждают это предположение.

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

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

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

Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Kelvin Henney
День семьсот восемьдесят первый. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
81. Тестируйте Точно и Конкретно
Важно проверять желаемое, существенное поведение кода, а не случайное поведение конкретной реализации. Но, помимо этого, тесты должны быть точными и конкретными.

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

Когда программистов спрашивают: «Что бы вы тут протестировали?», - наиболее частым ответом является что-то вроде: «Что в результате сортировки получается отсортированная последовательность элементов». Хотя это правда, это не вся правда. Если спросить, что ещё, то многие программисты добавят, что результирующая последовательность должна быть той же длины, что и исходная. И это тоже правильно, но всё равно недостаточно. Например, если взять последовательность:
3 1 4 1 5 9
То ответ ниже удовлетворяет обоим условиям (результат отсортирован и той же длины):
3 3 3 3 3 3

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

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

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

Как заметил Тони Хоар: «Есть два варианта проектирования ПО: сделать его настолько простым, чтобы в нём очевидно не было недостатков, либо сделать его настолько сложным, чтобы в нём не было очевидных недостатков.»

Использование конкретных примеров позволяет избавиться от случайной сложности и случайных ошибок. Например, для той же самой последовательности:
3 1 4 1 5 9
Результат сортировки будет:
1 1 3 4 5 9
Никакой другой ответ не годится!

Конкретные примеры помогают проиллюстрировать общее поведение доступным и однозначным образом. Результатом добавления элемента в пустую коллекцию является не просто то, что она не пуста: теперь в коллекции есть единственный элемент, и этот элемент является добавленным элементом. Два или более элементов будут удовлетворять условию непустой коллекции, но этот тест будет неверен. Один элемент с другим значением – тоже. Результатом добавления строки в таблицу заключается не просто то, что в таблице становится на одну строку больше. Нужно также проверить, что первичный ключ этой строки совпадает с первичным ключом строки, которую мы добавили. И так далее.

При определении поведения тесты должны быть не просто правильными: они также должны быть точными.

Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Kelvin Henney
День семьсот восемьдесят восьмой. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
82. Тестируйте во Сне и в Выходные
Расслабьтесь. Я не говорю о рабском труде или даже о сверхурочной работе по выходным или ночью. Скорее, я хочу обратить ваше внимание на то, сколько вычислительных мощностей имеется в вашем распоряжении. В частности, как много всего мы не используем, чтобы немного облегчить свою программистскую жизнь. Вам постоянно не хватает времени или вычислительных ресурсов в течение рабочего дня? Если да, то почему бы не запускать тесты в нерабочее время?

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

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

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

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

Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Rajith Attapattu
День семьсот девяносто пятый. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
83. Тестирование – Это Строгость в Разработке Программного Обеспечения
И снова о тестировании.

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

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

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

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

Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Neal Ford