Текст выпуска 16: Старый код борозды не испортит?

podcast_16_800x800Одна отекстовка стоит тысячи аудиозаписей
(кажется, какая-то пословица?)

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

За кропотливую работу по конвертации звука в текст мы благодарим Ольгу Русакову (Parallels, London)!

Алексей Виноградов: Добрый день, всем привет! Снова в эфире RadioQA со мной, ведущим этого выпуска, Алексеем Виноградовым. Сегодня мы поговорим про тестирование ПО с легаси-кодом и и постараемся ответить на вопрос, может ли старый код испортить борозду. Сегодня у нас много интересных гостей – это Алексей Борисович Петров, директор по качеству в Mail.ru, он уже был на одной из наших передач.

Алексей Петров: Привет!

Алексей Виноградов: … Василий Никишин — руководитель группы автоматического тестирования в Parallels из Таллина.

Василий Никишин: Всем привет!

Алексей Виноградов: Привет, Василий. В этот раз у нас два Алексея и два Василия, второй — Василий Курков — software validation engineer в Intel (Новосибирск)

Василий Курков: Всем привет!

Алексей Виноградов: Различать Василиев мы, наверное, будем по городам, один – из Таллина (Parallels), второй – из Новосибирска (Intel). И еще один участник команды RadioQA – это Макс Михайлов, ведущий тестировщик в General Electric, написано Санкт-Петербург?

Максим Михайлов: Ну, это так, ничего не поменялось с прошлого раза.

Алексей Виноградов: Привет, Макс!

Максим Михайлов: Привет!

Алексей Виноградов: Давайте сразу погружаться в тему. Вот первый вопрос, который записан у меня в повестке (сразу беру быка, или, в нашем случае, коня за рога): откуда берется «исторический» код, почему разработчики его часто не трогают и не обновляют, почему к нему нужно относиться осторожно. Может быть, сегодня мы даже услышим примеры из компаний, которые представляют участники и какую-то статистику. Один из соорганизаторов этого выпуска — компания Parallels, которую представляет Василий из Таллина, и поэтому я предлагаю сразу дать ему слово.

Василий Никишин: Прежде чем начать говорить, хорош или плох легаси-код, хотелось бы определиться, кто и что понимает под этим. Обычно используют два определения: первое — это код, который не покрыт тестами. С точки зрения автоматического тестирования весь код не покрыт тестами. Но сегодня я бы не стал употреблять именно в данном контексте такое определение. Скорее всего, во всяком случае, для меня, легаси-код – это код, который достался мне по наследству. Когда мне нужно понять, как он работает, но мне не у кого спросить. И приходится самостоятельно с ним работать.

Алексей Виноградов: Ребята, у кого-то есть другие мысли? Давайте я сразу вклинюсь, я тоже примерно согласен со вторым определением. Если бы меня спросили, что я понимаю под легаси-кодом, я бы тоже сказал – это тот код, который написан до меня людьми, которых уже нельзя достать. Практически у этого термина есть негативный оттенок: это написали не профессионалы кода, а теперь я сижу на саппорте и должен это поддерживать. Но в данном контексте это не обязательно легаси-код, так часто бывает и когда нам нужно что-то создать, а у нас есть какие-то библиотеки, куски кода или просто готовое приложение, которое, как считается, написано в более плохом качестве, чем то, что мы собираемся сделать. В таком случае программисты обычно говорят, что сейчас мы сядем и напишем, как надо. А еще у нас в тусовке Software Craftmanship слово «легаси-код» используется как неприличное ругательство без конкретных значений.

Василий Курков: Я бы мог еще добавить, что, помимо того, что легаси-код воспринимается кодом, про работу которого нельзя у кого-то спросить, это еще и код без внятных качественных спецификаций. Потому что если код хорошо описан, есть база знаний и отсутствует человек, который его писал – это не так страшно. А вот если нет ни человека, ни описания и, упаси господи, нет еще и различного рода тестов, ручных или автоматизированных, к этому куску кода – вот это настоящий легаси и самая большая головная боль, по крайней мере, в моем представлении.

Василий Никишин: То есть все-таки легаси-код – это с таким негативным оттенком.

Алексей Петров: Всегда. Это не легендарный код, как говорит небезызвестный герой.

Алексей Виноградов: Да, Legendary. Откуда он берется?

Максим Михайлов: Из класса ада

Василий Никишин: Если посмотреть на перевод, то это всегда наследство, которое может быть и хорошим, и плохим. Можно получить особняк и жить в свое удовольствие, а можно – лачугу, к которой и подойти страшно. И налог на недвижимость на нее такой же, как на дворец. Поэтому нужно смотреть на то, что досталось. Может, ведь, и повезти. Например, бывает, что нам достаётся код, с которым мы никогда не работали, но на него приятно смотреть и даже есть чему поучиться. Даже если с первого раза ты его не понимаешь. А бывает, что понимаешь сразу – лучше бы ты этого не понимал. С точки зрения моей деятельности: мы тоже работаем с легаси-кодом, потому что некоторые продукты в Parallels разрабатываются в течение 10 лет и даже больше – например, Parallels Desktop. Некоторые разработчики уже ушли, но код остается. Хорошо, если он уже покрыт тестами, тогда никаких особых проблем нет. А если нет, то возникает тот самый легаси «с душком». В нем надо разбираться, его надо покрывать тестами. Второй вариант – это сами наши тесты. Я сейчас руковожу командой по тестированию, которой досталось в наследство более 20 тысяч тестов и сама инфраструктура, которая их запускает. И мне в них сейчас приходится разбираться. При этом я бы не сказал, что это то легаси, которое я бы хотел просто выбросить. Нет, это вполне рабочие тесты и вполне рабочая инфраструктура. Проблемы возникают именно в тот момент, когда нужно глубоко погрузиться в предмет, а спросить не с кого – нет не только людей, но и описаний. Тогда приходится каким-то образом тестировать даже тесты, которые нам необходимо запускать на рабочем коде. Все зависит от того, кто этот код писал, а его писали в течение 10 лет разные люди. И ты радуешься, находя какие-то перлы, которые можно взять в качестве примера для будущих тестов. А иногда находишь что-то и думаешь – лучше бы этого не писали вообще, я бы сейчас это заново написал. Но в большей части (более чем на 60-70%) Parallels Desktop покрыт тестами, и эти тесты вполне рабочие, и как наследство я это вполне могу принять. В итоге я могу заняться новыми продуктами, новыми фичами, и сосредоточиться именно на них. Вот это наследство я считаю вполне приемлемым: то, что можешь использовать в дальнейшем. То же самое с инфраструктурой, которая у нас обеспечивает запуск всех автотестов. Она тоже была написана под один проект (у нас сейчас 5-6 продуктов, а был лишь один). Проблема в том, что если для одного продукта она хорошо работает, то с трудом расширяема для других. Здесь мы применяем такой же подход: нельзя выбрасывать то, что работает. Лучшее – враг хорошего, потому что если система удовлетворяет пользователя приемлемым качеством, то нужно дать ей поработать. Нужно создавать что-то новое – создавай. Если же нужно что-то расширять, а оно не расширяется, то нужно строить что-то рядом, давая возможность старому «пахать». А когда у тебя уже будет что-то новое, и ты это отладишь и запустишь – тогда можно отказаться от легаси.

Алексей Виноградов: На каких языках вы пишете? Например, Parallels Desktop?

Василий Никишин: Python

Алексей Виноградов: Интересно, продолжай

Василий Никишин: В общем, есть три вида легаси, с которым приходится работать – легаси-код разработки, легаси самих тестов, их достаточно много, и легаси-инфраструктура. Но у нас в Parallels всегда работали грамотные, квалифицированные инженеры, поэтому все это я воспринимаю как рабочее наследие. Оно трудится, и я могу посвятить свое время и время команды на то, чтобы разрабатывать что-то новое. А также параллельно создавать новую инфраструктуру для запуска автотестов уже на современных инструментах.

Алексей Петров: Я серьезно шокирован, что, Parallels Desktop написан на Python?!

Василий Никишин: Да нет, мы же говорим сейчас о QA

Алексей Петров: Я-то спрашивал, на чем вы пишете Parallels Desktop

Василий Никишин: На С++

Алексей Виноградов: Ну слава богу!

Василий Никишин: Мы же раз начали говорить о QA.

Алексей Виноградов: Мы и говорим о QA, как о процессе, который помогает софту достичь какого-то качества, ты считаешь, что программирование тут вообще не при чем?

Василий Никишин: Нет, просто вопрос был «На чем вы программируете», а мы в команде автоматического тестирования тоже программируем, это тоже относится к разработке. Когда меня спрашивают, на чем, я понимаю как вопрос «а что мы в команде используем». И там основной язык – Python. А основной язык, на котором пишут продукт – С++.

Алексей Виноградов: Ок. Понятно. То есть вы пишете автотесты через интерфейс? Потому что писать юнит-тесты на Python…

Василий Никишин: Нет, юнит-тесты пишут разработчики. Мы пишем основную механику, функциональные и acceptance-тесты.

Алексей Виноградов: Через графический интерфейс или не только, если не секрет?

Василий Никишин: Графический интерфейс мы используем достаточно редко, работаем через API

Алексей Виноградов: Ок, то есть тестируете API с помощью Python.

Василий Никишин: Да.

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

Василий Курков: Традиционно Intel воспринимают как производителя железа, и очень часто люди удивляются, что у нас есть и программные продукты. Тем не менее, у нас в Новосибирске расположен отдел разработки компиляторов для языков С, С++ и Fortran, и я занимаюсь их тестированием. Они разрабатываются достаточно давно, счёт идёт на многие-многие годы, и у нас накопилось достаточно большое количество кода. Так как компания большая, то зачастую люди уходят в другие проекты или даже из компании, и не всегда удается передать дела так, чтобы можно было все перенять. Причем это касается не только кода самого компилятора, но и тестов. И я согласен в этом смысле с Василием, что действительно нужно рассматривать понятие «легаси» в тех самых трех аспектах: код, тесты для этого кода и инфраструктура. И все озвученные проблемы у нас тоже актуальны. Я предлагаю подробнее обсудить момент, который Василий упомянул: связку легаси-кода с востребованностью у пользователя. Если мы начнем говорить о причинах, почему код не трогают, то мы рано или поздно придем к тому, что мы должны связать его с востребованностью этих фич у пользователя. И получится, скорее всего, так: либо код написан идеально, и в нем ничего не нужно менять, либо написан плохоо, но пользователю эта фича не нужна, он ее не использует, соответственно, и баги не репортятся. Что вы думаете на эту тему?

Максим Михайлов: Я бы только добавил, что речь не всегда идет только о том, чтобы изменять код под воздействием баг-репортов, иногда необходимо написать какую-то новую фичу, связанную с тем куском, который написали до тебя. Это то, что лично мы называем легаси-кодом.

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

Максим Михайлов: Да, в том числе.

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

Алексей Петров: Я хотел бы добавить еще такой ньюанс: в моей работе эпизодически случаются ситуации (и в текущей компании, и на предыдущих местах работы), когда нет физической возможности избавиться от легаси-кода на протяжении достаточно длительного времени. Представьте себе ситуацию, что у вас есть клиент, который не обновляется принудительно, и он априори работает, предположим, со старым PPI. В нашем случае так часто бывает с мобильными приложениями: у вас есть мобильное приложение на клиентской стороне — на мобильном телефоне пользователя и совсем не обязательно, что обновляется: оно может использовать легаси-код, и мы никак не можем заставить пользователя отказаться от этого. Более того, если мы применим самый простой способ – уничтожение легаси-кода – мы просто потеряем часть аудитории. И когда речь идет о многомиллионной аудитории, к сожалению, такой вариант очень и очень печально скажется на имидже компании. Поэтому не всегда можно прибегнуть к тому, чтобы просто вырезать кусок кода, который мы считаем устаревшим, иногда приходится поддерживать и старый, и новый код.

Алексей Виноградов: Вы, я так понимаю, больше говорите в контексте того, что легаси-код – это какая-то единица функционала, которая используется пользователями или другими системами. Я видел в своей практике ужасные паттерны. Это может относиться не только к коду, но и, как вы уже говорили, к инфраструктуре, и к просто написанными руками тест-кейсами для мануального ручного воспроизведения. Я находил куски кода, про которые никто не знал – зачем они, что они делают и кому вообще нужны. Когда я пару раз (на двух разных проектах) предложил – давайте мы это удалим, то прибежали люди, которые вспомнили, что за этот кусок кода и тест-кейсы полгода назад заплатили огромную кучу денег, и меня чуть не съели за предложение удалить. Я считаю, это абсолютное непонимание сути программного обеспечения. Если есть такой продукт жизнедеятельности мамонта, который никому не нужен, то зачем его оставлять только потому, что за него когда-то заплатили, и кто-то над этим год работал. У вас такого не бывало?

Алексей Петров: Это здорово, если получается вспомнить. Именно поэтому в моей практике и в повседневной борьбе за качество продуктов я настоятельно всем рекомендую бороться с хотфиксом. Ибо половина костылей, которые потом превращаются в мавзолей и продукты жизнедеятельности мамонта, появляются именно во время хотфикса, когда мы делаем что-то быстренько. Это случается, когда нужно зафиксить что-то так, чтобы у пользователя это не падало, но это, как правило, не документируется, делается конкретным разработчиком в режиме аврала чуть ли не 3 часа ночи, выставляется и потом благополучно забывается. И мы эпизодически натыкаемся на артефакты в коде, закомментрированном «Я не знаю как это работает, но, пожалуйста, не удаляйте, иначе все сломается». И нет никакой отсылки к конкретной документации. Поэтому, к сожалению, чаще всего, по крайней мере мне, приходилось сталкиваться с такими кусками легаси-кода, которые были написаны здесь и сейчас 5-6 лет назад. Я даже встречался с такими фрагментами, которые не удаляли чисто из-за авторитета: например, нынешний генеральный директор в одной из компаний, где я работал, и был в свое время рядовым программистом, техническим директором и сам писал код. И никто не удаляет его код, потому что невозможно удалить код его святейшества. И давайте не будем его трогать, пусть он там висит, там только какая-то хромая виртуалочка и крутится пара воркеров.

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

Алексей Петров: Могу сказать за себя, мы как раз не практикуем удаление легаси-кода, то есть стараемся его плавно обходить. Так как есть часть функциональных и инфраструктурных единиц, которые нельзя упразднить из-за того, что они отвечают за обеспечение жизнедеятельности продуктов для определенной аудитории.

Максим Михайлов: Обходить понятно. А изменять приходится?

Алексей Петров: Да, в том числе и изменять. Возникает двойственная сложность поддержки. Например, если взять нашу почту, то у нас есть так называемый легаси API, и есть новый. Новый перспективный, с хорошей документацией, более 50% разработчиков, которые прилагали к нему руки, по-прежнему работают в компании. Это хорошо поддерживаемый код, удобный, комфортный. Мы стараемся поэтапно на него переходить. Но есть и условный темный чулан, где заперт небольшой семирукий монстр в виде легаси-кода и мы вынуждены его поддерживать, а видоизменять стараемся по минимуму. Если необходимость там что-то изменить, то мы делаем это в новом API, а в старом оставляем как есть. А для пользователей это подается таким образом: если вы хотите какую-то новую функциональность, то, пожалуйста, обновите свое мобильное или десктопное приложение. Не хотите обновляться по ряду причин, например, из-за производительности, безопасности, отсутствия прав на обновление – то, к сожалению, у вас будет урезанная функциональность. Проблема, с которой нам приходится сталкиваться – это когда мы внутри компании вынуждены поддерживать и старый, и новый API, причем и старый и новый код идет в параллели и даже выполняет одни и те же функции.

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

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

Алексей Петров: Нужно определить, какие условия. Если у тебя, предположим, есть какой-то кусочек, из-за которого 50% фронтов уходят в астрал, условно говоря, дата-центр падает и есть кусок кода. И к этому куску кода был сделан хотфикс, чтобы вернуть ему жизнеспособность и ресурс, причем практически в тот же самый момент, когда произошла такая проблема. Такой кусок кода никто не документирует, и бывают ситуации, когда в нормальных обычных условиях, когда приходят пользователи, один или два фронта вываливаются из нагрузки, а этот код не задействуется. Вот такие мавзолеи очень сложно найти, более того, в большинстве случаев их потому и не трогают, что боятся – если это когда-то было написано, то не зря, и стопроцентно отловить именно мертвый, именно никому не нужный кусок кода не всегда можно.

Василий Никишин: Есть анекдот про мальчика, у которого на пупке гаечка была, а потом зад отвалился. Чтобы найти, с чем была связана эта гаечка, мы бы потратили столько времени, что уже полпродукта можно было написать. Все упирается в ресурсы: есть ли они на исследование, изменение и прочее. Но в своей практике я не сталкивался, чтобы мне выделяли временные и инженерные ресурсы на то, чтобы прошерстить весь код продукта, который пишется более 10 лет.

Алексей Виноградов: Да, возникают ситуации, когда какие-то методы были когда-то нужны, чтобы решить какую-то конкретную проблему, потом они перестали быть нужны, но их оставляют в коде просто на всякий случай. И через некоторое время уже никто не помнит, для чего они были нужны и когда могут пригодиться. На мой чисто интуитивный взгляд эти вещи лучше удалять, чем сохранять. Грубо говоря, у вас есть метод, название которого имеет какой-то смысл – вы читаете и думаете: ок, возможно, я бы мог его для чего-то использовать. Современные IDE помогают разобраться, вызывается ли код, или, как Алексей рассказывал, вызывается только в каких-то очень редких определенных случаях. Есть люди, которые хотят оставить такой код просто потому, что он был когда-то нужен. Я придерживаюсь более строгого варианта: мы должны понять, для чего он когда-то вызывался, документировать, чтобы знать, когда мы его должны включить, или удалить, потому что он будет только мешать понимать другой код и отвлекать внимание. Мы будем все время об него спотыкаться и спрашивать: для чего же он нужен на самом деле. Это один из аспектов.

Максим Михайлов: То есть при описании кода помимо того, что описывается случай, когда он необходим, и для чего написаны функция или метод, хорошо бы еще добавлять описание, при каких условиях можно удалить этот метод, чтобы сэкономить на анализе. Например, «удалить после 2015 года».

Алексей Виноградов: Я часто это делаю для тест-кейсов. А чаще всего получается наоборот: вставляется какой-нибудь костыль, потому что софт работает как-то не так, но сам софт должен быть исправлен в течение месяца-двух. Я ставлю тогда напоминалку (в код, а не себе в календарь), что после такого-то числа его нужно перепроверить, пофиксить или удалить.

Алексей Петров: Это классика жанра, когда неожиданно на продакшене могут оказаться какие-то куски дебаг-кода, которые сделали специально для того, чтобы потестировать и отладить его, потом забыли кусочек, и он в скрытой менюшке выдает вам версию продукта. А через некоторое время через нее какой-нибудь ушлый безопасник находит возможность сделать эксплойт и поломать всю вашу систему. Кстати, Леша, ты сказал про тест-кейсы, но еще в самом начале мы затронули вопрос, что легаси-код действительно может быть как в продукте, с которым мы работаем и тестируем, так и в коде, который есть у нас на вооружении – в автотестах, скриптах для тестирования производительности и в ряде других тестов, которые сопряжены с автоматизированными проверками. Вот в таких случаях, наверное, выкосить кажущийся ненужным код несколько проще, потому что, по сути, и под угрозу ставим только качество работы наших тестов и можем словить, например, падение 300 наших тестов, хотя этого не должно было происходить. И тут же мы поймем, что это не костыль, а необходимый код. К сожалению, на продакшене такие вещи делать очень сложно. Когда хочешь выкосить какой-то непонятный мавзолей, который находится в сложной архитектуре – речь не об одном простом приложение с бэкендом и фронтендом, а о сложносоставном приложении, состоящем из шестидесяти или сотне компонентов, то там метод «а давайте отключим и посмотрим, что сломается» очень сложно применять. А в контексте наших продуктов – например, мы даже не можем выбрать условный минимум активности наших пользователей, потому что у нас аудитория такая, что пользователи из Дальнего Востока и Калининграда будут по сути круглосуточно пользоваться нашим ресурсом. И мы не можем себе позволить в перерыве с 3 часов ночи до 4 утра проводить испытания по включению и выключению легаси-кода. Это чревато последствиями. А для тестов это более чем применимая практика. Коллеги со мной могут согласиться, если так или иначе пользуются этим.

Василий Никишин: С Алексеем я согласен – автотесты это вещь атомарная, а код продукта как правило комплексный и там много взаимосвязанных объектов, и если вы пытаетесь во время рефакторинга удалить какую-то функцию, которая вам кажется в ближайшее время в модуле не используется, это не значит, что она не используется на другом компоненте опосредованно. Поэтому чтобы что-то выкосить – надо поднять всю инфраструктуру, а если это облачный продукт, то это не так просто. Автотесты можно быстренько проверить и убрать, ничего страшного, чем более, что это на продукте опосредованно не отражается. С точки зрения продукта все гораздо сложнее – здесь как раз возникает эта проблема легаси: код устаревший и спросить не у кого. Одно дело, когда ты знаешь, что именно этот разработчик написал эту функцию, видишь, что она не используется и спрашиваешь: может, выкинуть ее? А в легаси и спросить не у кого, а если еще и не задокументировано, то придется потратить достаточно много времени, чтобы выяснить, что это никак не влияет на весь продукт, либо смириться с тем, что он присутствует, есть не просит и пока никак не мешает.

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

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

Алексей Виноградов: Есть еще другой момент, я недавно слушал очень интересный доклад руководителя компании TestLab из США по поводу избыточного покрытия, в котором он на пальцах объяснял, почему это плохо. Например, у вас есть полная хорошая пирамида автотестов, есть юнит-тесты, есть интеграционные тесты, UI-тесты. И если одно и то же место тестируется 15 раз юнит-тестом, 5 раз интеграционным и еще 2 раза UI-тестом, то любое изменение этого места вызовет огромные затраты на поправку самих тестов. Это сравнительно новая интересная концепция, доклад был в конце 2015 года. Я об этом никогда раньше не задумывался, но это мне показалось очень убедительным. Действительно, можно удалять не только плохие тесты, но и хорошие работающие тесты, которые действительно делают то, что они должны делать, чтобы сократить расходы по поддержке. Одно место должно в идеале быть протестировано один раз. К сожалению, Алексей Петров нас сейчас покинет.

Алексей Петров: Да, к сожалению, вынужден покинуть нашу беседу, но обязательно дослушаю запись.

Максим Михайлов: И обязательно возвращайся в какой-нибудь другой раз.

Алексей Виноградов: Да, спасибо большое, Леша.

Алексей Петров: И вам спасибо, всем желаю поменьше легаси, а если легаси все-таки появляется в вашей жизни, то пусть это будет нефтяная вышка или замок с хорошей винодельней. Всем удачи и хороших выходных!

Все: Спасибо, пока!

Максим Михайлов: По поводу удаления тестов, Леша, я бы тоже согласился с тобой. Мое личное мнение: тесты, как и любая другая живая субстанция, рано или поздно должны погибать. Один из критериев важности теста – его ценность. А именно та информация, которую он приносит, когда мы его запускаем. Если мы определяем, что запуск теста не несет совершенно никакой информации, то в большинстве случаев действительно поддержание этого теста в какой-то момент становится намного дороже, чем та информация, которую он преподносит. Поэтому в этом случае его можно и удалить.

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

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

Василий Никишин: Согласен, что если тесты не ловят багов, это не значит, что их нужно реже запускать. Это просто значит, что этот код в данный момент не приносит багов – но в любой момент может принести. Если срок будет месяц, то за месяц разработчики столько накоммитят, что потом уже будет трудно найти причины этого.

Василий Курков: Для этого есть автоматические системы для поиска, что же именно привело к регрессии.

Алексей Виноградов: А зачем мы пишем автотесты, ели не для того, чтобы они могли автоматизированно запускаться так часто, как нам удобно?

Василий Курков: Это хорошо, когда тестов приемлемое количество, когда речь идет о большом количестве тестов, все-таки приходится приоритезировать: что-то пускать чаще, что-то реже.

Алексей Виноградов: Не понимаю. Могу понять, что если слишком много автоматизированных тестов, которые бегают перед релизом или коммитом, то чтобы дать ок или не ок, ты реально должен ждать несколько часов. Расширяйте системы.

Василий Никишин: Тем более что железо дешевое или можно вообще распределять в облако.

Алексей Виноградов: Это к тому моменту, что если у нас есть 10 тестов, которые тестируют одно и то же…

Василий Никишин: Соглашусь, что избыточность всегда вредна, потому что тогда есть оверхед на поддержку. Может быть, где-то это и нужно – в космических технологиях, там запас прочности намного выше, чем в обычном коммерческом программировании, может быть, там все слои должны быть оттестированы, независимо от того, повторяются тесты или нет.

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

Алексей Виноградов: Про что сейчас речь идет, про компиляторы, Фортран?

Василий Курков: Да, но даже не обязательно Фортран, в С++ тоже есть приложения, которые ты долго компилируешь, потом оно само по себе долго отрабатывает, так как обрабатывается какая-то информация или ресурсоемкие задачи. Это может работать несколько часов.

Алексей Виноградов: Это юнит-тесты в компиляторах, или интеграционные, UI?

Василий Курков: Фактически интеграционные тесты, но у тебя в качестве теста – реальное приложение – open source или любезно предоставленное компанией. И ты пытаешься скомпилировать своим свежим компилятором.

Алексей Виноградов: Получается перекомпилирование заново других приложений, потом возможно их функциональное тестирование?

Василий Курков: Да.

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

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

Алексей Виноградов: Наверняка всегда есть случаи, где методы, которые в общем могут казаться странными и нелогичными, именно для этого случая необходимы. Особенно если у вас такой вариант. В целом я хочу заметить, сама идея, что если тест не находит багов, то он ненужный – не совсем правильная, потому что информация о том, что тест прошел – это тоже информация. Если мы тест не запускали, то у нас нет информации. А если тест запускается месяцами и не находит ошибок – это не значит, что он нам не помогает. Он помогает тем, что подтверждает то, что он не падает.

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

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

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

Василий Никишин: Я бы не сказал, что легаси-код в этом плане отличается от вновь написанного: правила те же самые, особенно если это касается функциональных, интеграционных тестов, acceptance-тестов. Особенно если есть понимание, что должно быть на входе и на выходе, то всегда можно написать тесты на том же самом Python. Но, конечно, есть большая проблема для непокрытого юнит-тестами кода: если у вас это легаси-код, то это тяжелый случай. Тут нужно потихоньку подходить, использовать тот же самый TDD-метод, хотя тут особо девелопмента нет, но в любом случае если вы делаете рефакторинг как часть девелопмента. Тут тоже можно писать тест, делать изменения, если тест не проходит – откатывать изменения, снова возвращаться, снова делать изменения, и только вот таким вот кусочным методом что-то можно менять в легаси-коде. А с точки зрения функциональных тестов – мне кажется, нет разницы между легаси и новым кодом.

Алексей Виноградов: Есть ли какие-то специализированные инструменты тестирования легаси? Я не слышал.

Василий Никишин: Для легаси я не знаю, я уже сказал, что для меня в принципе этот код получается одинаковым, если б не юнит-тесты. Мы используем Python или специфические инструменты, если это UI или вебовский тест, но они не различают, легаси ли это код.

Алексей Виноградов: Да, я могу, в принципе, для конкретного случая порекомендовать инструменты вроде Sikuli, который тестирует на основе скриншотов, и с его помощью вы можете протестировать end-приложение, к коду которого у вас вообще нет доступа и которое запускается в каких-то редких системах. Вы можете запустить в виртуалке ваше приложение, в этой виртуалке будет Фортран и какие-нибудь старые DEC юниксовские системы. Sikuli будет работать в Windows и в чем угодно, в хостовой системе, и тестировать по тому, что он видит. Но это само по себе тестирование через скриншоты – это довольно муторная вещь, хотя иногда это может быть единственным способом писать автотесты.

Василий Никишин: Да, но мы его используем и для GUI-тестов. Совсем необязательно, чтобы это был легаси, но в принципе да, если другого подхода к легаси нет, то единственный способ. Но это не инструмент для тестирования легаси-кода, а все-таки инструмент для тестирования продукта через UI.

Алексей Виноградов: Ну да. А вы используете Sikuli?

Василий Никишин: Да, так как у нас есть графика, то есть и тесты, использующие Sikuli

Алексей Виноградов: А вы сейчас, если не секрет, новую Sikuli Х используете, или она еще не готова, есть вообще разница между Sikuli Х и Sikuli?

Василий Никишин: Нет, новую еще не смотрели.

Алексей Виноградов: Она, к сожалению, мне кажется, за последние 2-3 года практически не развивается.

Василий Никишин: Самое тяжелое – это тестировать через UI. Конечно, мы пытаемся всегда взаимодействовать с разработчиками, чтобы они нам предоставляли API. А тестирование через UI оставляем уже для ручного тестирования.

Алексей Виноградов: Пока что, я считаю, только для веб-приложения есть хорошее решение и, возможно, для мобильных приложений, с которыми у меня личного опыта нет – это Appium, например, и всякие такие вещи, которые позволяют тестировать приложение в iOS и Android. Их работа очень сходна с тем, как мы сейчас тестируем веб-приложение – уже, в приницпе, жить можно.

Василий Никишин: У нас тоже есть тестирование приложений – мобильных на Android и iOS, и это, как правило, тесты, которые требуют постоянного вмешательства. Либо изменения в коде продукта приводят к тому, что эти тесты ломаются, либо там еще какие-то проблемы возникают. Я именно с этой точки зрения говорю. Есть и вебовские тесты, которые используют именно UI – они достаточно сложные в поддержке. Если есть выбор между API и UI, то конечно мы всегда склоняемся к API. И по максимуму используем именно API-конструкции.

Алексей Виноградов: У вас есть и веб-приложение, которое вы тестируете?

Василий Никишин: У нас есть веб-сайт и облачные продукты, у которых есть свой свой фронтенд.

Алексей Виноградов: Selenium используете?

Василий Никишин: Да

Алексей Виноградов: А Selenide используете? Слышали про такое?

Василий Никишин: Нет

Алексей Виноградов: Ай-яй-яй, стыдно! Его же в Таллине производят.

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

Алексей Виноградов: Мы где-то через пару дней выпустим Selenide новую версию, и скоро Selenium будет легаси. Шучу. Я просто участвую в разработке продукта Selenide, очень рекомендую, если вы используете Selenium, берите сразу Selenide. Selenide построен на Selenium и решает основные проблемы, которые встречаются в тестировании современных ajax-приложений.

Василий Никишин: Спасибо за консультацию, ок. Алексей, ты говоришь, это делают в Таллине – ты тоже каким-то образом связан с таллиннской командой?

Алексей Виноградов: Почти весь фреймворк написал Андрей Солнцев из Codeborn (Таллин) как единственный разработчик. Они используют этот фреймворк для своих проектов и уже давно, им уже 4 года. Он выставлен в open source, абсолютно свободен для использования, и сейчас количество пользователей растет. Я с удовольствием применял это в серьёзных проектах – очень приятно с ним работать.

Василий Никишин: Раз ты рекомендуешь, то брось ссылочку на проект.

Алексей Виноградов: Конечно. Я, честно говоря, в каждом втором выпуске этого подкаста рекомендую. Скину ссылочку, да.

Максим Михайлов: У нас в чате интересный вопрос от Евгения: Что посоветуете начинающему автоматизатору, чтобы собственный код не становился легаси для будущего поколения. Это применимо, наверное, и для программистов.

Алексей Виноградов: Я еще добавлю вопрос «А если в ходе тестирования вы нашли костыль, о котором все благополучно забыли, что можно с этим сделать и нужно ли?» Мне кажется, это немножко связано, ведь это может быть ваш костыль или чужой. От себя скажу, мне кажется очень важным и полезным документировать тот код, который вы пишете. Причем не на уровне «вот я написал e=5, прокомментировал и присвоил е значение 5», а документировать так, чтобы тому, кто хочет пользоваться вашим кодом, методами и классами, было понятно, как их в первую очередь использовать. Потому что тогда становится понятнее, почему они работают именно так. Мне это кажется важнее, чем объяснять алгоритм, работающий внутри кода, и объяснять, зачем вообще этот метод и что он делает. Вашим последователям будет проще смотреть на код и понять: ок, он должен делать то-то и то-то, а если код этого не делает, то будет проще сориентироваться, в какую сторону его менять.

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

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

Алексей Виноградов: Аж двое?

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

Алексей Виноградов: В этом как раз я вижу проблему: это популярное мнение, которое мне кажется опасным. Объясню почему. Документируемый код имеет такую проблему: когда ты написал код, в котором абсолютно понятно, что он делает, а твой метод, например, вызывается по-другому, то есть вызывается так, что он не отражает то, что на самом деле делает. Тогда возникает вопрос: неправильно назван метод или неправильно назван код. Если ты хорошо пишешь код, то каждому понятно, что он делает, но абсолютно не понятно, делает ли он именно то, что ты задумал. Переформулирую: то есть у тебя есть задание, и ты это задание неправильно понял. Ты его имплементировал абсолютно идеально с инженерной точки зрения, и понятным языком описал, но ты решил не то задание. И последователь пытается выяснить: ты решил правильное задание, но неудачно сформулировал, или решил не то задание? Против этого я хочу бороться вот чем: нужно обязательно комментировать не строчки кода, а что твой метод должен был делать. Понимаете, к чему я веду?

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

Алексей Виноградов: Естественно. Поэтому я еще раз подчёркиваю, что писать понятный код, который легко читать – это важно, я абсолютно не хочу этому или противоречить. Я считаю, что, во-первых, этого недостаточно, во-вторых, я предлагаю вот что: писать комментарии к методам. Но это не означает дополнительно комментировать строчки кода. Если ты написал код, который хорошо читается, в котором понятно, что он делает на самом деле, то тебе не нужно его документировать в том смысле, что еще раз записывать, что этот код делает. Но, грубо говоря, в шапке метода (я с Java в основном работаю) в Java-доке ты пишешь, что этот метод должен делать. Не как он именно работает, а что он должен делать. Если ты потом код меняешь, и метод делает что-то другое, ты просто обязан поменять эту документацию. Это не так сложно, как искать все эти длинные методы и короткие комментарии, и их менять. Я вообще считаю, что людям гораздо важнее знать, как пользоваться твоим методом, чем понимать, что же он делает внутри.

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

Алексей Виноградов: Я комментирую те методы, те единицы, которые вызываются. Грубо говоря, если у тебя все это локальное и вызывается только у тебя, то это часто можно не комментировать. А то, что у тебя хотят вызывать другие, нужно обязательно комментировать.

Василий Никишин: Особенно как в С++, там в хедерах обычно обязан быть комментарий к каждому методу, объясняющий, что он делает, потому что этим хедером, как правило, в API пользуются сторонние разработчики.

Алексей Виноградов: Важная разница, на мой взгляд – описывать, что он делает, а не как он это делает.

Василий Никишин: При разработке интерфейсе должно быть описано, что именно делается. А в имплементации ты уже комментируешь, как это должно выглядеть.

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

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

Алексей Виноградов: Какая квалификация, умения нужны тестировщику на проектах с легаси-кодом?

Максим Михайлов: Если речь именно о коде, то тестирование whitebox. Если мы говорим о том, что легаси-код, как и любой другой, является для тестировщика просто черным ящиком, то не нужны какие-то специфические навыки подготовки, чтобы просматривать легаси-код: он будет на него смотреть, как и на все остальное.

Василий Никишин: Такой момент: считается, что легаси-код может быть только в разработке, но, например, в тестовой среде тоже случается, когда приходит новый человек и начинает работать с легаси-кодом. И вот тут уже нужны специфические навыки: как минимум, хорошее знание языка, на котором написан код, чтобы понять, как он работает. Особенно, если приходится его изменять. И знание специфики продукта, потому что, как правило, в каждом продукте прописана какая-то бизнес-логика, поэтому этот бизнес-процесс нужно тоже хорошо себе представлять.

Алексей Виноградов: Хотелось бы обратиться, в первую очередь, к программистам и их менеджерам: все говорят, что писать юнит-тесты нужно и полезно, и все знают, что многие программисты их писать не любят. Одна из причин, на мой взгляд: в современном мире очень сильно занижается сложность написания юнит-тестов, их даже нет в требованиях к образованию программиста. На самом деле, их писать совсем не так просто, как кажется. Каждый программист знает кучу дизайн-паттернов для своей области, а знаете ли вы, что существует книжка страниц в 600, где расписаны дизайн-паттерны только для юнит-тестов? Об этом знают единицы. Я слышал заявления: программисты не хотят писать юнит-тесты, потому что они просто ленивые. Но отсутствие юнит-тестов означает только то, что некоторые к ним плохо относятся. На самом деле, мне кажется, они их не пишут в том числе потому, что не всегда знают, как их хорошо писать. Это наука, может быть, не такая сложная, как программирование в целом, но достаточно сложная для того, чтобы отнестись к этому серьёзно. Товарищи менеджеры, организуйте курсы, дополнительное образование для программистов, чтобы они писали хорошие юнит-тесты и тогда они сами поймут, что юнит-тесты полезны. Потому что плохой юнит-тест может быть действительно сложно писать и толку от него мало.

Василий Никишин: Я добавлю про свой опыт с юнит-тестами. Действительно, пока я работал разработчиком, то сначала я писал юнит-тесты после того, как написана функциональность. Когда ты пишешь их таким образом, то получается некий овехед твоей работы, и это действительно угнетает. Но когда у тебя есть метод, например, TDD, тогда все совсем по-другому. Тогда ты начинаешь тесты писать еще до того, как пишешь функциональность, и они становятся частью твоей функциональности. Тогда это тебе дорого, и это втыкает. Потом у тебя всегда есть тесты, и если ты какие-то изменения вносишь в код, то просто запускаешь тест и сразу получаешь результат. Поэтому очень важен именно метод, которым ты будешь эти тесты писать. Если ты будешь их писать постфактум, то получишь дополнительно временной оверхед, и чаще всего именно из-за этого разработчики не пишут тесты.

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

У меня ещё есть три конкретных вопроса по принципам улучшения легаси-кода, легаси-артефактов в целом в тестировании, программировании и вообще. Надеюсь от Василиев услышать какие-то советы, идеи по этому поводу. Допустим, у вас есть глючное приложение с легаси-кодом, которое однозначно желательно улучшить. И это приложение находится в режиме поддержки, то есть уже пользователями активно используется, они ругаются, плюются, ставят тикеты, но все уже live, в продакшене, и все уже хорошо. И вот к вам приходит руководство и говорит: вы получите все, что вам нужно, но нам нужно что-то улучшать. Что вы посоветуете? С чего будем начинать, первые две недели? Врасплох застал вопросом?

Василий Никишин: Всего две недели?

Алексей Виноградов: Нет, у вас приложение, которое будет еще пять лет использоваться, например. Долгосрочное.

Василий Никишин: У нас нет вариантов, кроме как заняться улучшением функциональности или производительности данного легаси-кода?

Алексей Виноградов: Да, именно, вас направили это улучшить и говорят, что если вам нужны еще программисты, то мы их дадим, обеспечим полную поддержку от руководства. Они заметили, что тот код, которым сейчас пользуются пользователи, очень плохой, много жалоб и тикетов, на обработку уходит время, а мы не хотим не быстрее тикеты закрывать, а именно как-то улучшить код.

Василий Никишин: У меня, наверное, был бы такой подход: я бы взял метод типа TDD, выбрал бы после исследования кода какие-то ключевые методы или классы, каким-то образом оборачивал, делал бы тесты, пытался бы изменить. Изменил – получил зелёный свет – хорошо, заработало. Не получилось – откатился, снова изменил. И вот таким методом приближения я бы и действовал.

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

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

Максим Михайлов: Получается, по сути, глобальный рефакторинг.

Алексей Виноградов: Да. Мне, кстати, понравилась идея пока что не пытаться строить рядом соседнее приложение, а оборачивать текущее тестами и потом улучшать так, чтобы оно делало то, что должно было делать. Кажется, это интересная идея. Василий, у тебя есть, что добавить?

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

Алексей Виноградов: Есть ли разница между подходами? Сейчас мы рассматриваем приложение, с которым уже работают пользователи. А если мы пишем приложение, в котором тоже есть легаси и все довольно плохо, но у нас есть еще 12 месяцев до релиза или даже 2 года, в общем, много времени? Я сразу тогда и третий вопрос задам: а что, если до релиза дается небольшое время, скажем, 3 или 6 месяцев, и наш продукт еще пользователи не видели?

Василий Курков: Зависит от размера бедствия. Все равно легаси сначала нужно изучать – возможно, этот код неработоспособный, тогда 12 месяцев можно либо бамбук курить, либо заниматься этим легаси-кодом. Все зависит от того, какая функциональность и устраивает ли она пользователя. Если это действительно каша, которую надо разгребать, то возникает вопрос: через 12 месяцев мы должны выпустить то, что этот легаси уже делает, или за эти 12 месяцев мы должны еще написать кучу нового софта, свежую функциональность.

Алексей Виноградов: Конечно, но если до релиза остается 12 месяцев, то это еще не ознчает, что через 12 месяцев мы его выпустим. Как обычно бывает – проект был рассчитан на 2 года, прошел год, мы посмотрели, увидели, что написали 30% функциональности и при этом написали ее настолько ужасно, что есть смысл переделать.

Василий Никишин: Может и есть смысл, но нужно смотреть непосредственно на код: возможно, есть смысл за 12 месяцев все переписать.

Алексей Виноградов: С нуля? Конечно, если это одна и та же команда, то никакого смысла нет. Но ведь часто бывает, например, отдали на аутсорс, понадеялись, а потом получили промежуточный результат и вот сейчас думаем, а не начать ли нам с нуля с другой командой. Так бывает.

Василий Никишин: В любом случае, первой фазой все равно будет исследование кода: насколько он плох или хорош, и потом уже можно решать – получится из него сделать конфетку или нет. И вопрос, что нам через 12 месяцев нужно будет, в конечном итоге, получить. Нужно смотреть каждый конкретный случай, а вот 12 это месяцев или 3, это не меняет дела, потому что в любом случае надо сначала посмотреть и понять, что это за код. И какой он будет через 3 месяца или через 12 – все зависит от тебя.

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

Алексей Виноградов: А бывает в случаях, которые я описал: когда легаси-код произвела не ваша команда, а другие сторонние люди, и справились с ним не так уже хорошо. По-моему, довольно жизненная ситуация, может, не так часто встречается, но бывает. Ок, что у нас из вопросов осталось. Исторический код какой процент кодовой базы занимает?

Василий Никишин: Наверное, в каждом продукте свой процент. У нас, например, продукт развивается, и там есть определённая часть исторического кода, но вопрос, как это вообще оценивать, когда проект развивается. Здесь опять же возникает вопрос, который я пытался сформулировать: кому-то досталось в наследие и поверх этого надо настраивать систему. Тогда можно говорить, что мы написали миллион строчек кода, из них 666 тысяч – унаследованного кода. 60% получается. А по нашему продукту не могу этого сказать, у нас не было такого рода наследия, потому что продукт и код внутри него — весь рабочий. А если говорить конкретно о тех тестах, которые мы унаследовали для нашего продукта от другой команды, то это около 60%, а то и 80% — причем это тесты, которые сейчас работают на продукте. Сверху этого, может быть, 20-40% уже новых написали. Но я их считаю полностью своим продуктом, потому что меня устраивает тот легаси-код, который мне достался, ребята хорошо поработали. Он становится на 100% моим кодом, за который я отвечаю. Василий?

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

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

Алексей Виноградов: Ок, у нас пока вопросов не поступило, давайте потихоньку будем заканчивать новостями. Если вопросы появятся, то мы их еще зададим.

Максим Михайлов: Точнее, у нас одна новость.

Алексей Виноградов: Даже две есть!

Максим Михайлов: Две?! Родилась одна за период эфира?

Алексей Виноградов: Да нет, я записал, спрятана. Мы в прошлом выпуске плакались, что QAHelp закрыл свой сайт, на котором был форум вопросов и ответов, замечательная лента русскоязычных и англоязычных блогов про тестирование, где можно было регулярно получать свежую информацию в удобной форме. Так вот, QAHelp умер, да здравствует QAHelp! Сергей Нестеренко открыл в Facebook новую страницу с новостями, которая называется «Ку Новости» или «Мир Ку», мы дадим ссылочку. Ребята, все в Facebook есть? Макс, по-моему, не особо любит Facebook.

Максим Михайлов: Я там есть, но по необходимости, у меня не сложилось.

Алексей Виноградов: Заходите, подписывайтесь, сейчас лента блогов будет идти через страничку в Facebook. Другая хорошая новость – к выпуску этого подкаста из прямого эфира в запись, я надеюсь, группа, которая называется сейчас QAH, достигнет в Facebook 10 000 человек. Уже совсем близко к этой цифре. QAH – основная группа, которая называется сейчас, по-моему, Q-жизнь и там постятся всякие смешные, любопытные и поднимающие настроение вещи. Или наоборот, иногда, как нам пишут, хочется водки выпить, прочитав шутку про тесты, потому что в каждой шутке есть доля шутки. Подписывайтесь на паблик QAH, очень хорошая вещь, рекомендую.

И еще совсем свежая новость, на днях вышла новая версия Selenium 2.49, где исправлены некоторые баги, и добавлены новые, наверное. Версия Selenide, которая использует эту версию Selenium, будет уже на днях. В релизе будет несколько полезных функций, пользуйтесь на здоровье. Информация для тех, кто уже пользуется Selenide (если вы не знали): вы можете использовать любую версию Selenide с любой версией Selenium, не обязательно брать ту, что встроена в стандартный пакет Selenide. Если у вас есть какие-то проблемы с любой из версий Selenide, можно ее менять. Все для вас.

Сайт на Facebook с новостями называется facebook.com/qatimes. То есть как New York Times, только QA Times. Заходите, подписывайтесь. Давайте напоследок ответим на вопрос от Вадима: по каким параметрам можно понять, что код стал устаревшим?

Василий Никишин: Я в начале сформулировал: если я смотрю в код, и мне самому приходится с ним разбираться, не у кого спросить и негде прочитать, то это легаси-код.

Алексей Виноградов: Если вы видите в коде ижицу и некоторые другие буквы старославянского языка, то, возможно, код уже устарел. Какие еще варианты? Если вы видите команды типа move DX или GOTO 50, то, возможно, ваш код тоже устарел.

Василий Никишин: А кто был связан с Фортраном, Алексей?

Алексей Виноградов: Нет. А Фортран уже наверное – мега-легаси?

Василий Никишин: Я когда начинал на Фортран писать, тогда это было нормально использовать. Я, правда, не знаю, как сейчас.

Василий Курков: Ребята, вы будете удивлены, какое количество приложений все еще существует и новых пишется именно на Фортране.

Василий Никишин: Он как язык изменился за это время? Goto там уже не используется?

Василий Курков: Не знаю, как же без этого.

Максим Михайлов: Это же легаси-код Фортрана, его нельзя трогать.

Алексей Виноградов: У нас в Германии, между прочим, вполне нужны специалисты по Cobol, очень много кода на нем. А я думаю, что они с Фортраном погодки. Так что, ребята, если вы умеете программировать на Cobol и можете передвигаться без тросточки, то приходите, наверняка найдете работу в Германии. Я конечно шучу и утрирую, но действительно довольно много проектов на Cobol, естественно, нет никого, кто сейчас язык учит, то есть это все люди, которые учили его когда-то в свою молодость. Cobol, наверное, уже 30+ лет.

Василий Никишин: Да, это еще до меня было. Я начинал с Фортрана.

Алексей Виноградов: А я с Бейсика. Были такие машины ДВК.

Василий Никишин: Были, на них мы как раз и начинали программировать

Алексей Виноградов: Программировать наш легаси-код.

Василий Никишин: Можно посмотреть на код, который мы на ДВК писали.

Алексей Виноградов: Я, честно говоря, переписывал код из книжек, правда, немного изменял. Ну что, на этой оптимистической ноте мы завершим сегодняшний выпуск. С нами были: Алексей Борисович Петров, директор по качеству в Mail.ru, он ушел несколько раньше, Василий Никишин из Таллина, Parallels, Василий Курков, Intel (Новосибирск).

Василий Никишин: Спасибо, всем пока!

Василий Курков: До свидания, спасибо!

Алексей Виноградов: Макс Михайлов, General Electric, наш генеральный электрик.

Максим Михайлов: Всем до встречи!

Алексей Виноградов: И я, ведущий Алексей Виноградов из Германии. Спасибо всем слушателям за вопросы и поддержку в чате. До свидания!