unit-тест, который требует, чтобы перед запуском были

advertisement
Антипаттерны (antipatterns) — это классы наиболее
часто внедряемых плохих решений проблем.
Ухудшается переносимость кода - чтобы
перенести функционал в другой проект, нужно искать
все скопированные участки кода и переносить их по
отдельности
• Понижается качество кода - программист может
забыть внести требуемые изменения в скопированный
код
• Усложняется поддержка кода - ошибки, присутствующие
в изначальном варианте кода при копировании
переносятся в другие участки кода и на их устранение
требуется больше времени
• Ухудшается читаемость программы - объем кода
программы возрастает без видимой значительной
выгоды и роста производительности труда
•
•
Избежать данного антипаттерна можно путем
планирования действий на этапе анализа задачи,
написание решений, которые можно использовать
несколько раз
•
•
•
•
Слабо структурированная и плохо спроектированная
система, запутанная и очень сложная для понимания
В ООП спагетти-код может быть представлен в виде
небольшого количества объектов с огромными, по
размеру кода, методами
Термин применяется не только к случаям
злоупотребления GOTO, но и к любому коду, в котором
один и тот же небольшой фрагмент исполняется в
большом количестве различных ситуаций и несет очень
много функций
Решением проблемы является рефакторинг кода или его
полное переписывание
•
Применение одного решения (чаще всего какого-либо
одного паттерна проектирования) для любых задач
Для каждой задачи имеется не одно, а
несколько оптимальных решений
• Выбор решения для каждой задачи должен быть
обоснованным с точки зрения удобства и
легкости применения какой-либо технологии для
решения конкретной задачи
•
•
•
•
•
Константа, использованная в коде для чего либо (чаще
всего — идентификации данных), само число не несёт
никакого смысла без соответствующего комментария
Программист, который не является автором такого кода,
с трудом сможет объяснить, как это работает, а со
временем и автор кода не сможет объяснить что-либо
Числа затрудняют понимание кода и его рефакторинг
Необходимо объявлять все числовые константы в
качестве переменных или констант
int a(int i, char с)
{
if (c== "m")
if (i< 1000)
return 0;
else
if(i< 10000)
return 500;
else
return 1200;
else
return 1300;
}
•
•
•
•
Внедрение различных данных об окружении в
реализацию, например — различные пути к файлам,
имена процессов, устройств и так далее
Этот анти-паттерн тесно связан с магическими числам
Непереносимость - в системе разработчика код будет
исправно работать до перемещения или
переименования файлов, изменения конфигурации
устройств; на любой другой системе код может не
заработать сразу же.
Как правило, программист практически сразу забывает
где и что он "захардкодил", что делает выявление и
локализацию данного антипаттерна очень сложной
•
•
•
Настраивается абсолютно всё, что делает конфигурацию
невероятно сложной и непрозрачно
При разработке много ресурсов уходит на реализацию
возможности настроек абсолютно всего
Развёртывание такой системы повлечет так же
дополнительные затраты
Каждый раз, предлагая
опцию, вы просите
пользователя сделать
выбор
• Заставляя
пользователя делать
выбор за себя,
дизайнер усложняет
жизнь пользователя,
подписывается в своей
некомпетентности
•
•
•
•
Заумность решения - ненужные проверки, части кода,
продуцированные мягким кодированием, отсутствие
какой-либо оптимизации
Приводит к усложнению понимания кода, понижению
скорости работы приложения
o Симплтон – это жутко навороченный паттерн,
используемый для решения самых примитивных
задач. Он является точным показателем
профессионального уровня тех, кто его использует
Для решения данной проблемы применяется
рефакторинг кода
•
•
•
•
Сохранение неиспользуемых частей системы, которые
остались после оптимизации или рефакторинга
Так же некоторые части кода могут быть оставлены «на
будущее»
Такой код только усложняет системы, не неся абсолютно
никакой практической ценности
Борьба с данным видом антипаттерна происходит с
помощью рефакторинга кода и удаления ненужных
частей, а также с помощью планирования процесса
разработки
•
Разработка собственного решения задачи, для которой
уже существуют решения, чаще лучшие, чем
придуманное программистом
o
•
Reinventing the square wheel - создание своего плохого решения, при
существовании лучшего (время тратится на изобретение и
реализацию собственного решения, а затем на его замену на
существующее более оптимальное решение)
Приводит к потере времени и понижению эффективности
работы программиста — так как найденное решение
может неоптимальным или вообще не найдено
o
o
С другой стороны, полный отказ от возможности
самостоятельного решения задачи приводит к программированию
"копипастом"
Чтобы выбрать между готовым решением и написанием
собственного, необходимо понимать поставленную задачу, оценить
затраты ресурсов на каждое из решений и возможную выгоду от их
применения
•
•
Недостаточная проверка корректности входных данных,
исправления ошибки или результатов работы кода
Программист думает, что его код всегда будет в
идеальных условиях, никогда не выдаст ошибки и не
получит неверных входных данных или данных
неверного типа
o Фактор невероятности (Improbability factor) предположение о невозможности того, что сработает
известная ошибка
•
•
Решение задач методом перебора значений входных
параметров, порядка вызова функций без понимания
сути алгоитма решения задачи
Если программист не понимает происходящего, то он не
сможет предусмотреть все варианты развития событий и
обязательно о чём-то забудет, он потратит время на
подбор работающего для него решения и позднее
потратит время для переделки этого решения
•
•
•
•
Объект берет на себя слишком много функций и/или
хранит в себе практически все данные
Непереносимость и трудность понимания кода
Подобный код сложно поддерживать, поскольку вся
система зависит практически только от него
Решением является разбитие задачи, выполняемой
объектом на несколько подзадач и соответствующее
разделение объекта
•
•
•
•
Программист сначала рисует пользовательский
интерфейс, а затем пишет бизнес-логику в
автоматически созданных методах.
Код обработчиков элементов интерфейса
неконтролируемо растёт
Изменение пользовательского интерфейса (или
добавление нового интерфейса) становится сложным
Усложняется тестирование кода
•
Поддерживание нежелательного (избыточного или
низкокачественного) кода потому, что удаление его либо
слишком дорого, либо имеет непредсказуемые
последствия
•
Класс-потомок, созданный в соответствии с этим
антипаттерном, выдает по запросу все данные классапредка, независимо от степени их сокрытия
class foo
{
protected:
bool bar;
}
class morozov : public foo
{
public:
bool getBar()
{
return bar;
}
}
•
Характеризует обработку исключительных ситуаций.
Логика выглядит стройной, но если кто-либо
побеспокоиться протестировать приложение либо
наступит исключительная ситуация, вся обманчивость
этой логики вылезает наружу.
•
•
Попытка разработать работающую модель приложения
на скорую руку
Естественное желание – переписать код, учитывая
полученные из него уроки, однако сроки поджимают
•
Паттерн Сыр – полон дыр. Этот паттерн состоит из
мелких убогих фокусов, которые в итоге сводят на нет
переносимость приложения. Чем старше Сыр, тем
лучше “пахнет”
// for all browsers
div{min-height: 150px;}
// only for IE 5 and 6
* html div {height: 150px;}
•
•
Встречается в коде, написанном бывшими сотрудниками
компании. Так много старых проблем заключено в таком
коде, что теперешние сотрудники могут защитить свои
наработки от обвинений, утверждая, что именно чужой
код – причина всех возникающих ошибок
Также известен под именем "Это-Не-Моя-Правка"
•
Имеет место в приложениях, созданных инженерами,
которые впоследствии получили продвижение по
службе. Несмотря на изобилие ошибок в программе,
вклад этого инженера слишком велик, чтобы позволить
кому-либо начать переписывать этот код
•
Паттерн Гость Из Преисподней сродни отсутствию
проверки на выход за границы массива во время
выполнения. По крайней мере один контрольный цикл
для системы неизбежно вызовет Гостя Из Преисподней,
который обязательно затрёт жизненно важные данные
•
•
•
Перфекционизм, ненужная оптимизация и оттачивание
деталей
Приводит к ненужным затратам средств, времени
Зачастую, излишнее внимание уделяется неосновным
функциям продукта
•
•
•
В сложном модуле для пользователя закрыты простые,
но нужные функции
В результате пользователю приходится писать простую
функциональность, надстраивая её над сложной, иногда
с использованием недокументированных возможностей
и побочных эффектов, в то время когда она уже
написана
Уменьшается скорость программы, увеличиваются
расходы памяти
•
Unit-тест, который успешно выполняет все кейсы и
выглядит работающим правильно, но на самом деле он
не тестирует то, что должен
•
•
•
Тест, который требует тяжелой работы по
инициализации прежде чем начать собственно
тестирование.
Иногда сотни строк вызываются для одного
единственного теста, создавая при этом множество
объектов.
Сложно удостовериться, что именно тестируется
•
Unit-тест состоит из несколькиз тысяч строк кода и
содержит слишком много кейсов
o Это может служить признаком того, что тестируемая
система представляет из себя антипаттерн God
Object.
•
В случае, когда unit-тест содержит настолько много
mocks, заглушек (stubs) и фейков (fakes), что часть
системы остается непротестированной
•
•
Unit-тест, который нарушает инкапсуляцию в попытке
достичь 100% покрытия кода (code coverage) и при этом
знает слишком много о тестируемой системе
При рефакторинге системы такой тест слишком часто
ломается и требует исправлений
•
•
Один unit-тест создаёт данные, которые где-то
сохраняются, а другой тест их потом использует
Если первый тест будет по какой-то причине вызван
позже или пропущен, то тест, использующий его данные,
не пройдёт
•
•
Unit-тест, который проверяет весь результат работы, в то
время как на самом деле важна только его малая часть
В результате приходится часто обновлять тест, чтобы
отражать изменения в незначительных вещах
Тест, который зависит от чего-то специфичного для
данного окружения
• В результате тест успешно проходит у конкретного
разработчика, но не выполняется у других
o Скрытая Зависимость (Hidden Dependency) - unitтест, который требует, чтобы перед запуском
были заполнены какие-то данные. Если эти данные
отсутствуют, то тест падает, оставляя мало
информации о причине проблемы
•
•
Unit-тест, который тестирует множество второстепенных
(и, как правило, простых) мелочей, но не тестирует
основное поведение программы
•
Кейс, который не относится к unit-тесту, в котором он
расположен. Он на самом деле тестирует совершенно
другой объект
•
•
Тест, который был написан для того, чтобы пройти
успешно, а не для того, чтобы сначала провалиться
(принцип fail first)
Недостаточно глубокое тестирование и успешное
прохождение там, где правильный тест должен упасть
•
•
Тест, который из-за общих ресурсов может видеть
данные других тестов и может упасть, даже если
тестируемая система полностью валидна
Типичным примером может служить использование
статических полей для хранения коллекций. Если они не
очищаются должным образом, то возможны
неожиданные побочные эффекты в других тестах
•
•
Unit-тест, который выполняется крайне медленно
Возможно разработчик не станет дожидаться
завершения тестирования
•
•
•
Изменение существующих или появление новых
требований к продукту в процессе фазы тестирования
Новые требования поступают не от заказчика продукта,
а как отчеты о найденных ошибках от команды тестеров
В результате этого обычно происходит невыполнение
планов разработки и сдвиг сроков выпуска и снижение
качества продукта
•
•
•
•
Руководитель не способен оценить сложность
решаемых задач, эффективность способов их решения
и реальное состояние проекта
Постоянные негативные оценки прогресса проекта: "Все
плохо" ©
Раздувание недостатков до глобальных размеров
Постоянная публичная критика участников команды и
жалобы вышестоящему руководству на
некомпетентность исполнителей
•
•
•
•
Удержание работников в неинформированном и
постоянно занятом состоянии
Замыкание всех внешних и внутренних потоков
информации на себя
Фильтрация и искажение информации в личных
интересах
Зависимость исполнителей от более информированного
начальника
•
Неоправданное внимание и затраты времени/ресурсов
на стадию анализа
•
Встречается в программах, которые настолько трудно
тестировать и поддерживать, что это выливается в
постоянные превышения бюджета
•
В случае, когда на этапе разработки требований
изначально не были определены все требования
заказчика к продукту и сроки выполнения рабты, при
приближении к дате сдачи продукта начинают
призводиться попытки создания баланса между сроками
разработки и качеством продукта. В результате
получается посредственное приложение – и всё равно с
опозданием
Группа участников объединяется при плохом или
некомпетентном руководстве
• Излишняя сложность, неполнота, логические
противоречия, банальность и отсутствие целостной
структуры
• Изначальная задача, базовые спецификации и
технические критерии отступают на второй план перед
самомнением и личными интересами отдельных
участников комитета
• Создатели этих отдельных модулей продукта не
задумываются о качественном взаимодействии с
другими участниками проекта
•
•
Уделение избыточного внимания численным критериям
управления, когда они неважны или стоимость их
получения слишком высока
Download