Далеко не все программисты гении, и далеко не каждая программа идеальна — рано или поздно ее приходится переделывать, что, однако, всегда связано с риском нарушения ее работоспособности. Учитывая, что сбой рабочей системы может затрагивать доходы, собственность, а иногда и жизни людей, то и в программировании, как и в медицине, актуально правило «не навреди». Следование определенным правилам, применяемым на каждом конкретном этапе жизненного цикла ПО, поможет сохранить работоспособность программы.

Разработка

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

Придерживайтесь стандартов оформления кода. Разнобой в оформлении ухудшает читаемость и затрудняет редактирование, но еще хуже пренебрежение стандартами кодирования, которое может стать причиной серьезных огрехов в проекте. Беспорядок в чужом коде может «расслабить» программиста, подтолкнув его к безответственности. Поэтому выясните стандарты оформления, которым принято следовать в вашей организации, и тщательно их придерживайтесь. Если такие правила не задокументированы, то сделайте выводы исходя из самого кода. А если вы видите код со стилевыми недочетами, согласуйте с коллегами способ их устранения (но заниматься этим надо в итерации, отдельной от внесения других изменений).

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

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

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

Тестирование

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

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

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

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

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

Внедрение

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

Предусмотрите план отката. Даже самое аккуратное развертывание тщательно протестированной системы может обернуться катастрофой. Разработайте план по быстрому изъятию новой системы из рабочей эксплуатации на случай, если возникнут неполадки. Испытайте свой план в действии и не колеблясь отменяйте развертывание при первых признаках проблем. Разработчики нередко слишком оптимистичны, считая, что их код всегда верный, а проблемы, возникающие при развертывании, — это всего лишь неизбежная боль при прорезывании зубов. Определив по объективным критериям, что пришло время отменять установку, вы предотвратите необходимость принимать непопулярные меры в стрессовой ситуации.

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

Развертывайте обновления во внепиковые периоды. Программисты, работающие в телекоммуникационной отрасли связи, проводят масштабные обновления в 4 утра, но все равно получают звонки от разгневанных абонентов, которые жалуются на простои. А представьте, что будет в час пик! Неудачное время обновления может привести к «завалу» службы поддержки, озлобить заказчиков и ухудшить вашу способность принимать трезвые решения. Чтобы не поддаться соблазну или требованию развернуть систему в пиковый период, попробуйте заранее расписать времена суток и периоды года, в которые можно и нельзя осуществлять новые внедрения.

Координируйте свои действия с командой по технической поддержке. Сообщайте всем, кто участвует в сопровождении вашего ПО, о планах развертывания и отката, внесенных вами изменениях и контактных лицах, к которым можно будет обратиться в случае, если что-то пойдет не так. Рассказывайте о ваших планах на общем собрании, согласовывайте их со всеми и отвечайте на все вопросы, которые возникнут у специалистов по поддержке.

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

***

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

Диомидис Спинеллис (dds@aueb.gr) — профессор менеджмента, Афинский университет экономики и бизнеса (Греция).

Diomidis Spinellis, First, Do No Harm. IEEE Software, Septmber/October 2014, IEEE Computer Society. All rights reserved. Reprinted with permission.