Две ошибки могут взаимокомпенсировать друг друга (и найти это - очень тяжело)
(В оригинале - Two Wrongs Can Make a Right (and Are Difficult to Fix))
Код никогда не лжет, но он может сам себе противоречить. Иногда такие противоречия заставляют воскликнуть «Как это вообще может работать?».
В своем интервью один из дизайнеров ПО лунного модуля Аполлон 11, Алан Кламп (Allan Klumpp) рассказал, что в ПО контроля двигателей была ошибка, из-за которой во время посадки могла возникнуть нестабильность. Однако другая ошибка скомпенсировала первую, в результате чего ПО было использовано при посадке на Луну на кораблях Аполлон 11 и 12 до того, как ошибки были обнаружены и исправлены.
Представьте себе функцию, возвращающую успешность выполнения. Представьте, что она возвращает false в ситуации, когда должна вернуть true. А теперь представьте, что вызывающая функция не проверяет возвращаемое значение. В результате все будет работать до тех пор, пока кто-нибудь не заметит отсутствие проверки и не добавит ее.
Или представьте приложение, сохраняющее свое состояние в документе XML. Представьте, что один из узлов ошибочно записан как TimeToLive
вместо TimeToDie
. И вновь все будет работать до тех пор, пока код записи состояния и код чтения состояния будут содержать эту ошибку. Но исправьте ее в одном месте (или добавьте еще одно приложение, читающее этот документ уже правильно), и вот уже нарушена и симметрия ошибок, и работоспособность.
Если же две ошибки в коде проявляются одинаковым образом, то даже методология поиска неисправностей может дать серьезный сбой. Разработчик получает отчет об ошибке, находит первое проблемное место в коде, исправляет его и повторяет тест. Ошибка по-прежнему проявляется, ведь второе проблемное место все еще в коде! Он отменяет коррекцию, продолжает поиски и находит второе проблемное место, исправляет его – и вновь никакого эффекта (ведь первый дефект был возвращен назад). И разработчик продолжает поиски дальше, однако поскольку он уже обнаружил оба дефекта, но ошибочно решил, что причина не в них, поиски третьего дефекта, в реальности не существующего, могут оказаться очень долгими…
Такое случается не только в коде. Проблема может быть и в документации постановки задачи. И даже более – ошибка в коде может компенсировать ошибку в спецификации.
Аналогичный сценарий может затронуть и людей. Пользователи запоминают, что когда приложение просит нажать левую кнопку, для корректной работы нужно нажать правую. Люди запоминают это и даже передают это дальше: «Запомните, левая кнопка на самом деле означает правую!». Исправьте эту ошибку – и множеству людей придется переучиваться.
Единичные ошибки легко обнаруживаются и легко устраняются. Серьезная проблема возникает в случае множественных ошибок, требующих для исправления более одной коррекции. Отчасти так происходит и потому, что простые проблемы обычно исправляются сразу, а сложные накапливаются «до лучших времен».
Нет единой универсальной рекомендации, что делать в случае множественных проблем. Осведомленность о возможности такой ситуации, ясный ум и готовность учитывать все возможности помогут вам найти решение.
Автор оригинала - Allan Kelly