суббота, ноября 28, 2009

Искусство отладки: как предупредить появление багов

Очень хочется придушить все баги накорню. Совсем все придушить не получится, а вот сильно уменьшить их число - вполне.

Но тут не существует волшебного набора правил. Я не могу выдать вам список из N пунктов, соблюдая которые можно познать дзен. Тут надо думать, анализировать и действовать по обстановке.

Для начала - самое простое. Если программисты устали, если команда деморализована, то багов будет больше. Программисты хуже работают в душных и шумных помещениях. Багов будет больше, если программистов дергать с задачи на задачу и таскать по совещаниям.

В предупреждении багов помогают продуманная архитектура и читаемый код ( Джоэл Спольски в своем блоге называл его "самодокументируемый" ). И отношение тут не бинарное: плохая архитектура - хорошая архитектура. Читайте, разбирайтесь, пробуйте и постепенно архитектура у вас будет получаться все лучше и лучше. Классно сделанная архитектура не только не провоцирует появление багов, но и сопротивляется их внесению. Про архитектуру кода можно говорить долго, это отдельная большая тема, поэтому я просто дам несколько терминов со ссылками: слабо связный код, борьба со сложностью, Defensive programming. Еще стоит почитать хорошие книги об организации кода.

Сильно помогает понятный дебагный вывод. Вы должны четко понимать что происходит. А лучше - видеть, что происходит.

Не забывайте про автоматическое тестирование. Добавляйте его где возможно.

Вообще написали что-то - проверьте. Не надо надеяться, что багов в вашем коде нет. Потому что они там есть. И чем раньше вы их поймаете, тем лучше. Сейчас, прямо после написания кода, вы хорошо его помните, это не займет много времени. Это гораздо быстрее чем прогонять код через команду тестирования и получить от них баги в багтрак через пару дней. Если нетривиальный кусок кода заработал сразу - это повод для беспокойства, значит вы что-то пропустили. Тут я очень советую почитать прекрасную статью написаннию тестером специально для программистов: Testing for developers.

Написав код, остановитесь, подумайте. Что будет если? Если числа выйдут за заданный диапазон? Что если мне здесь придет нулевой указатель? Как можно сломать мой код? Хотя если вы сейчас в кранче, то наверное не стоит тратить время на медитацию над этими вопросами. Однако, если время есть, то ответы на них спасут вам недели времени.

Хорошо помогает code review. Когда кто-то из ведущих программистов просматривает код остальных. Но осложняется человеческим фактором "как же так, кто-то будет проверять и править мой гениальный код?!". Поэтому code review может привести к боязни коммита и конфликтам в команде. Статья про code review: Your Code Sucks and I Hate You: The Social Dynamics of Code Reviews.

Постоянная бдительность! Паранойя в разумных пределах есть благо. Наряду с вопросом "что будет если?" задавайтесь вопросом "почему?". Мы практически ничего не меняли в последнее время, а размер дистрибутива вырос, почему? Мы не меняли данные, однако SVN подсвечивает их как измененные, почему?

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

На сегодня, пожалуй, все. В следущий раз - основная тема. Как всё исправить.

Байки:
Про Блицкриг 2
Про четырехмесячный дебаг

Ссылки:
Отладка. Несколько советов.
Программистское: статистическая и доказательная стратегии защиты от ошибок (Тут есть бонусная байка про наковальню)

11 коммент.:

Big 40wt Svetlyak комментирует...

Лучший способ предупредить появление багов — не писать код.

Евгений Охотников комментирует...

По поводу архитектуры маленькое дополнение. Даже хорошая архитектура со временем будет портиться, поскольку нельзя заранее предугадать все. Поэтому, если проект "долгоиграющий" (скажем, от 5 лет и дальше), нужно закладывать в него ресурсы на пересмотр архитектуры. Если этого не делать, то разработчики будут вынуждены навешивать на старую архитектуру все новые и новые костыли, а это обязательно приведет к увеличению количества багов.

Alex Ott комментирует...

хорошие советы, жаль что не так уж много мест где им следуют...
code review можно делать анонимным, тогда можно избежать конфликтов...

2Евгений: да, это бывает очень полезно - иначе после нескольких циклов разработки, архитектура начинает ограничивать развитие

max.lapshin комментирует...

Алена, мне кажется что людей вида «как же так, кто-то будет проверять и править мой гениальный код» надо вышвыривать из конторы сразу.

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

vokineberg комментирует...

Познавательно, спасибо!

afanasiy комментирует...

Здравствуйте, Алёна!
Я давно читаю Ваш блог, очень интересно. Когда-то начинал учиться программировать на С++ в среде Visual C++ 6.0, но потом забросил. Сейчас хочу снова начать, не посоветуете, в какой среде лучше писать программы? И какие книги читать? У меня есть Visual Studio 2005, говорят, там есть разница в синтаксисе.

Алёна комментирует...

2afanasiy:

Сейчас хочу снова начать, не посоветуете, в какой среде лучше писать программы? И какие книги читать?

Вот тут я давала список книг для начинающих: http://alenacpp.blogspot.com/2006/09/blog-post_19.html

У меня есть Visual Studio 2005, говорят, там есть разница в синтаксисе.

Угу, с каждой новой версией правятся баги. Visual Studio 6.0 уже сильно устарела. Visual Studio 2005 - нормальный выбор, можно начать с нее.

markoval комментирует...

При написании юнит тестов быть готовым к тому, что их код будет вдвое больше, чем проверяемый.
Всякие проверщики типа qac.
На уровне менеджемента - обязательный код ревью, обязательный прогон тестов перед комитом, обязательное добавление тестов на новый код. Скучно? Зато промышленно! :-)

dtjurev комментирует...

Вот всё-таки непонятно, откуда эта боязнь аккуратности. :) Если программист правит баги вместо того, чтобы разобраться с причиной - это не старательность. Это безолаберность, несистемность, безынициативность, непрофессионализм, наконец :)

Алёна комментирует...

2dtjurev:

Вот всё-таки непонятно, откуда эта боязнь аккуратности. :)

Я много раз наблюдала один и тот же паттерн. Программисты на полном серьезе считают, что аккуратность - это серебряная пуля в деле борьбы с багами. И когда лезут баги они не пытаются остановиться и подумать, они начинают активнее фигачить. 14 часов в день, 16, ночи напролет. Безумие какое-то.

Если программист правит баги вместо того, чтобы разобраться с причиной - это не старательность. Это безолаберность, несистемность, безынициативность, непрофессионализм, наконец :)

Непрофессионализм, да. Ну так с этого все начинают, это нормально.

Marat комментирует...

Если программист правит баги вместо того, чтобы разобраться с причиной - это не старательность. Это безолаберность, несистемность, безынициативность, непрофессионализм

Т.е. можно "править баг", не разбираясь в его причинах? Можно конечно (и я такое видел), но я не думаю, что кто-либо из комментаторов назвал бы это "исправлением бага".

"Аккуратность" очень нужна программисту (особенно на C++ - Java-программист всегда сможет обвинить во всем JVM :). Но 100%-ную гарантию человек дать не может по определению, можно лишь свести появление багов к какой-то малой вероятности. Сейчас, кажется, популяризируется мнение, что "софта без багов" не бывает. Отчасти, это правда. И потому, если разработчик нашел баг и исправляет его, то это значит, всего лишь, что он с Вами честен. Все остальное можно понять лишь заглянув глубже (доходя иногда до кода).

Но все это не отменяет ни грамотного проектирования, ни методик программирования (шаблоны, проверка типов, ошибки компиляции вместо ошибок исполнения, "xитрости-премудрости" на вроде "if (1 == a)" ), ни тестирования (unit, нагрузочное и т.п.) как средств уменьшения хаоса и вероятности багов.