Эффект последней строки, или К чему приводит копипаст
9К открытий9К показов
Рассказывает автор блога HOW NOT TO CODE
Я повидал много ошибок, связанных с методом «Копировать-вставить», и из всех них извлек один вывод: в большинстве случаев ошибка допускается в последнем копипастном фрагменте. Я ни разу не видел описания этого феномена в книгах и поэтому дал ему название сам — «эффект последней строки».
Введение
В процессе анализа всевозможных проектов найденные там баги я сохранял вместе с фрагментами кода в специальной базе. На нее может взглянуть любой желающий вот здесь.
Эта база по-своему уникальна. В ней содержится около 1500 всевозможных ошибок, которые могут стать хорошим уроком для начинающих программистов.
Я не проводил особо сложного анализа этих материалов, однако один паттерн ошибок просматривается настолько четко, что я не могу о нем не рассказать. В своих статьях я всегда повторяю: «Последнюю строку кода нужно печатать». Сейчас я объясню, почему.
Эффект последней строчки
При написании кода программистам часто приходится писать серии одинаковых конструкций. Писать почти одно и то же несколько раз подряд утомительно и неэффективно. Именно потому люди и используют метод копирования-вставки: фрагмент кода копируется и вставляется несколько раз подряд, а потом немного редактируется. Любой понимает опасности этого метода: легко можно забыть внести нужные изменения, что повлечет за собой ошибку. К сожалению, вменяемой альтернативы этому методу в таком случае я не знаю.
Теперь поговорим о закономерности, которую я обнаружил. Я обратил внимание на то, что большинство ошибок допускается в последнем скопированном и вставленном участке кода.
Вот простой пример:
Обратите внимания на строчку z += other.y;
. Программист забыл исправить y
на z
.
Можно подумать, что это искусственный пример, но нет. Я взял его из реального приложения. В этой статье я собираюсь доказать, что на самом деле это очень распространенная и важная ошибка. Программисты чаще всего ошибаются в самом конце последовательности однотипных действий.
Где-то я слышал, что альпинисты часто срываются на последних десятках метров своего восхождения. Не потому, что они устали: они просто слишком обрадованы тем, что вершина почти достигнута — они уже чувствуют сладкий вкус победы, теряют концентрацию и совершают фатальную ошибку. Я думаю, что с программистами случается примерно то же самое.
Вот еще примеры.
Пролистывая свою базу багов, я нашел 84 фрагмента кода, ошибки в которых вызваны многострадальным копипастом. Из них в 41 фрагменте ошибки содержатся где-то в середине блока скопированных и вставленных строк:
Длина строки "THREADS="
равна 8
, а не 6
.
В остальных 43 случаях ошибки находились в последней строке.
Да, число 43 выглядит не слишком большим в сравнении с 41. Но тут важно учитывать: однородных блоков много. Во всем 41 случае они могут находиться в первом, втором, пятом или десятом блоке. Получается, что мы получаем относительно равномерное распределение ошибок по всей длине блока и резкий пик в конце.
Допустим, что длина нашего однородного блока равна 5. Получается, что в первых четырех блоках будет 41 ошибка — в среднем по 10 на блок. И только на один последний блок придется 43 ошибки!
Итак, какую закономерность мы вывели:
Вероятность совершить ошибку в последнем блоке в 4 раза больше, чем в любом из предыдущих.
Я не раздуваю из этого грандиозных выводов. Это просто очень интересное наблюдение, о котором следует знать по практическим причинам — во время копипаста последней строки нужно быть максимально внимательным.
Примеры
Теперь осталось только доказать вам, что эти выводы — не просто мое заблуждение, а настоящая тенденция. Чтобы подтвердить свою позицию, представлю вам немного примеров. Конечно, не все — только самые простые или наиболее характерные.
Source Engine SDK
В конце должна была быть вызвана функция SetW()
.
Chromium
Последний блок идентичен предпоследнему.
Multi Theft Auto
Последняя строка была вставлена чисто механически — в этом блоке должно было быть только 3 строчки.
Source Engine SDK
Программист забыл в конце заменить BackgroundColor.y
на BackgroundColor.z
.
Trans-Proteomic Pipeline
В последнем условии программист забыл заменить prob > max6
на prob > max7
.
SeqAn
ReactOS
Переменная mjstride
окажется всегда равной 1
. Вот как должна была выглядеть последняя строчка:
Mozilla Firefox
Строка с ftp в конце лишняя — она уже повторялась выше.
Quake-III-Arena
В последней строке должно быть dir[2]
.
Clang
В самом конце блока выражение SM.getExpansionColumnNumber(ContainerREnd)
сравнивается с самим собой.
Выводы
Из этой статьи вы узнали, в чем опасность метода копипаста — ошибка чаще всего совершается в самом конце. Я думаю, причина этого кроется в человеческой психологии, а не профессиональных навыках. То, что вы увидели выше, написали не новички, а высокопрофессиональные разработчики проектов вроде Clang или Qt.
Надеюсь, мои наблюдения пригодятся вам и помогут снизить число багов, пополняющих мою коллекцию.
9К открытий9К показов