Работа над ошибками малой кровью
Joel on Software - Работа над ошибками малой кровью
Работа над ошибками малой кровью
Автор: Джоэл Сполски
Переводчик: Александр Башков
Редактор: Юрий Удовиченко
8 ноября 2000 года
Первые версии интерпретатора языка BASIC на компьютере TRS-80 позволяли заводить только две строковые переменные, A$ и B$. По его образу и подобию я был произведён на свет только с двумя ячейками для хранения информации об ошибках в голове. Одновременно я могу помнить информацию только о двух ошибках в программе. Если вы попросите меня запомнить третью, то какая-нибудь из трёх обязательно упадёт на пол, закатится под диван и затеряется там в реликтовых залежах пыли.
Ведение базы данных ошибок в программе - один из признаков хорошей программистской команды. Не перестаю удивляться тому, как редко разработчики прибегают к этому. Одно из типичных программистских заблуждений — это вера в то, что можно сведения о всех ошибках удержать в памяти или на отрывных листочках.
Если вы позволите мне отнять немного вашего времени, я расскажу вам о приятном, совершенно безболезненном способе отслеживать ошибки в программах в духе предыдущих статей: "графики работ малой кровью" и "спецификации малой кровью".
Прежде всего вам понадобится база данных (СУБД). Команда из двух человек, пописывающих чуть-чуть кода по выходным, вероятно, удовлетворится простым текстовым файлом. Более крупной команде уже потребуется настоящая система отслеживания ошибок. В настоящий момент продается несчётное количество подобных продуктов. (Беззастенчивая самореклама: одну из них — FogBUGZ — написали мы в Fog Creek Software. Это веб-ориентированная, несложная в использовании и достаточно мощная программа).
Давайте последим за какой-нибудь ошибкой от момента рождения до конца её бренного пути. Возьмём для примера ошибку 1203. Вот какую информацию о ней выдаёт база данных:
ID-Номер | 1203 | |
Проект | Bee Flogger 2.0 | |
Раздел | Ftp Клиент | |
Название | Загрузка файла роняет ftp сервер | |
Назначено | Закрыто | |
Статус | Закрыто-Решено-Исправлено | |
Важность | 2 - Необходимо исправить | |
Архитектура | 2.0 Alpha | |
Версия | Сборка 2019 | |
Компьютер | Макинтош iMac Джилл. MacOS 9.0, 128Mb ОЗУ, 1024x768, миллионы цветов | |
Описание | 1 ноября 2000 Открыто Джилл, очень-очень хорошим тестером.
* Запустить Bee Flogger 1 ноября 2000 Джилл, очень-очень хороший тестер, поручила работу над ошибкой Вилли, ведущему разработчику. 2 ноября 2000 (вчера) Решено - Исправлять не будем - Вилли, ведущий разработчик. Не наш код, Джилл. Это proftpd, входящий в поставку Linux. 2 ноября 2000 (вчера) Возобновлено (поручено Вилли, ведущему разработчику) Джилл, очень-очень хоршим тестером. Неубедительно. Мне никогда не удавалось уронить proftpd другими ftp клиентами. Наш же клиент роняет его каждый раз. Ftp серверы сами по себе не падают. 3 ноября 2000 (сегодня) Вилли, ведущий разработчик поручил работу над ошибкой Майку, простому программисту. Майк, взгляни-ка сюда. Может твой код в клиенте делает что-то не то? 3 ноября 2000 (сегодня) Решено - Исправлено. Майк, простой программист. Я думаю, что я передавал имя пользователя вместо пароля или что-то типа того... 3 ноября 2000 (сегодня) Реактивировано (поручено Майку, простому программисту) - Джилл, очень-очень хорошим тестером. Всё то же самое в 2001-й сборке. 3 ноября 2000 (сегодня) Отредактировано Майком, простым программистом. О как! Очень странно. Надо будет взглянуть внимательнее. 3 ноября 2000 (сегодня) Отредактировано Майком, простым программистом. Мне кажется это в MikeyStrCpy()... 3 ноября 2000 (сегодня) Решено - Исправлено Майком, простым программистом. Уфффф!!! Исправлено! 3 ноября 2000 (сегодня) Закрыто Джилл, очень-очень хорошим тестером. Похоже-таки исправлено в сборке 2022 - закрываю. |
Итак, вот что произошло.
Майк, простой программист, колдовал над новой возможностью своей превосходной программы для макинтошей: ftp клиентом. В один прекрасный момент из хулиганских побуждений он написал свою собственную функцию копирования строк. Вот им за их дурацкое требование повторного использования кода! Ха-ха-ха!
Беда приходит нежданно, Майк, когда ты не используешь повторно код! На этот раз никто не ждал, что Майк забудет завершить копируемую строку нулём. И ошибка осталась незамеченной, потому что при отладке строка копировалась в заранее обнулённую область памяти.
Позже на той же неделе, Джилл, очень-очень хороший тестер, терзала код, нажимая все клавиши подряд и выполняя другие, столь же коварные тесты. (По странному совпадению, практически всех хороших тестеров зовут Джилл или в крайнем случае Джиллиан). Внезапно произошло что-то очень странное — ftp сервер, на котором она проверяла клиента, упал! Да, я знаю, что это был Линукс, а компьютеры под Линуксом никогда не падают (только вот не надо фыркать, вы не на slashdot'е), но эта чёртова штука таки упала! А ведь Джилл даже не дышала на ftp сервер. Она просто пыталась загрузить на него файл, используя код для Mac-а, написанный Майком.
Поскольку Джилл была очень-очень хорошим тестером, она аккуратно вела запись всех своих действий. Она перезагрузила всё, что было можно. Начала повторять свои действия на чистой машине, и — гляньте-ка — это случилось снова! Ftp сервер опять упал! Дважды за один день! Вот тебе, Линус!
Джилл взглянула на запись своих действий. Там было порядка двадцати шагов. Некоторые из них, похоже, не имели отношения к проблеме. После некоторых экспериментов Джилл сократила число действий до четырёх, которые всегда вызывали ошибку. Теперь она была готова описать ошибку.
Джилл ввела информацию об ошибке в базу данных. Кстати, даже сам процесс записи информации об ошибке требует определенной дисциплины: бывают хорошие описания, а бывают и плохие.
Три составные части хорошего описания ошибки
И говорил Господь, и сказал Он: "Сначала следует тебе вынуть чеку святую. Затем следует сосчитать до трёх, не более и не менее. Три — число, до коего должен ты считать; и количество счёта твоего должно быть три. До четырёх не следует считать, а равно и до двух, кроме как ежели после двух последует три. Пять категорически исключается. И когда число три, будучи по счёту третьим числом, достигнуто будет, не сумняшеся метни Святую Гранату Антиохову во врага своего, который, будучи грешен передо Мною, ласты-то и склеит."
Монти Питон и Святой Грааль
Запомнить правила составления хорошего описания ошибки совсем нетрудно. Каждое хорошее описание ошибки должно содержать ровно три вещи:
- Какие шаги привели к ошибке.
- Что вы ожидали увидеть.
- Что вы в самом деле увидели.
Просто, да? Увы, нет. В бытность свою программистом я периодически получал описания ошибок, где отсутствовала та или иная часть.
Если вы не расскажете мне, как воспроизвести ошибку, я, наверное, просто не пойму, о чём вы вообще говорите. "Программа виснет и оставляет на столе дурно пахнущий объект, похожий на мешок навоза". Отлично, дорогой. Но я ничем не смогу тебе помочь, пока ты не расскажешь мне, что именно ты делал. Хочу отметить, что существуют две ситуации, в которых трудно точно воспроизвести действия, ведущие к ошибке. Бывает, что просто никак не вспомнить, какие именно шаги привели к ошибке, или, бывает, информацию об ошибке вам прислали из полевых условий. (Какие ж они полевые? Ни пшеницы, ни васильков. Ну да ладно.) Вторая ситуация — это когда ошибка воспроизводится не каждый раз. Но и тут стоит составить перечень действий, отметив, что ошибка происходит не всегда. В этих случаях бывает очень сложно локализовать ошибку, но попробовать можно.
Если вы не опишете, чего ожидали, я могу не понять, почему это, собственно, ошибка. На заставке следы крови. И что с того? Может быть я порезал палец, когда кодировал это место. А вы чего ожидали? А-а-а! Вы говорите, в спецификации написано "без крови"? Ну тогда понятно, почему вы решили, что это ошибка.
Часть три. Что вы в самом деле увидели. Если вы мне не расскажете об этом, я и не узнаю, в чём же ошибка. Ну, это и так понятно.
Вернемся к нашим баранам
Короче, Джилл ввела информацию об ошибке. В хорошей системе учёта ошибок работа над ошибкой автоматически поручается ведущему разработчику проекта. И в этом кроется вторая идея — ошибкой, пока она не закрыта, в каждый заданный момент времени должен заниматься только один человек. Ошибка подобна горячей картофелине — если она у вас, или сами ею занимайтесь, или перекиньте кому-нибудь ещё.
Вилли, ведущий разработчик, взглянул на описание ошибки и решил, что, вероятно, что-то не в порядке с ftp сервером, и пометил её как "исправить невозможно". В конце концов, не они же писали код ftp сервера.
Когда ошибка разрешена, она назначается обратно тому, кто открыл её. Это важный момент. Ошибка не исчезает только потому, что программист так решил. Золотое правило гласит, что закрыть ошибку может только тот, кто её открыл. Программист может только "решить" ошибку, в смысле — "ага, я думаю, ошибка исправлена", но реально закрыть ошибку и убрать её из списка может только человек, увидевший её впервые. Только он может подтвердить, что ошибка в самом деле исправлена, или согласиться с тем, что по каким-либо причинам исправить её невозможно.
Джилл получила е-мэйл: ошибка опять вернулась к ней. Она посмотрела комментарии Вилли. Что-то ей показалось неверным. Куча народа годами использует этот ftp сервер с различными приложениями, и он не падает. Это происходит только когда используется код Майка. Джилл реактивировала ошибку, объяснив своё решение, и вернула её на рассмотрение Вилли. Вилли поручил ошибку Майку для исправления.
Майк изучил ошибку, думал долго и упорно, но, тем не менее, сделал неверные выводы. Он исправил несколько несвязанных между собой ошибок и решил, что в их число попала ошибка Джилл.
Ошибка вернулась к Джилл с описанием "решена-исправлена". Джилл попробовала повторить шаги, ведущие к ошибке, и глядите-ка, ftp сервер опять упал. Она опять реактивировала ошибку и теперь поручила её исправление непосредственно Майку.
Майк был озадачен, но, в конце концов, он-таки нашёл источник ошибки. (Догадались, что это было? Я оставлю ответ на этот вопрос в качестве домашнего задания читателю. В тексте содержится достаточно подсказок). Он исправил её, проверил, и — эврика! Ftp сервер больше не падал. Опять он пометил ошибку как "решено-исправлено". Джилл тоже повторила все действия, приводившие к ошибке, и убедилась, что ошибка исправлена. После этого она с чистой совестью закрыла её.
Десять рекомендаций для успешного отслеживания ошибок
Если вы пишете код, пусть даже в одиночку, и не ведёте систематизированный учёт всех найденных в коде ошибок, вы обречены поставлять низкокачественный продукт. В хороших командах база данных учёта ошибок не просто используется, это становится привычкой. И программисты начинают её использовать для поддержки своих рабочих планов, список назначенных им ошибок делают стартовой страницей своего браузера. И в конце-концов, многие начинают мечтать о тех временах, когда можно будет поручить завхозу ликвидацию ошибки по отсутствию пива в ближайшем холодильнике.
В английском оригинале статья называется Painless Bug Tracking
Джоель Спольски - основатель Fog Creek Software, небольшой компании по
разработке программного обеспечения, расположенной в Нью-Йорке.
Окончил Йельский Университет, работал программистом и управляющим в
Microsoft, Viacom и Juno.
Всё содержимое Copyright ©1999-2005 by Joel Spolsky. All Rights Reserved.
FogBUGZ | CityDesk | Fog Creek Software | Joel Spolsky