С качеством связан значительный человеческий фактор. Каждый желает делать свою работу хорошо и каждый работает существенно лучше, если чувствует, что он делает свою работу хорошо. Если же вы намеренно жертвуете качеством, возможно, в первое время ваша команда действительно будет работать быстрее, однако в скором времени вступит в действие деморализация. На людей начнет давить ощущение, что они заняты производством бракованного продукта. Если вы откажетесь от тестирования или от пересмотра кода или от соответствия стандартам, возможно, на некоторое время вы добьетесь некоторого преимущества, однако в дальнейшем вы можете потерять его за счет человеческого фактора.
Множество людей хорошо знает, что такое затраты, качество и время, и как с их помощью контролируется процесс производства программного обеспечения, однако при этом многие из них не признают четвертую переменную – объем работ. Объем работ, связанный с производством программного продукта, – это наиболее важная переменная, с которой приходится иметь дело в производстве программного продукта. В большинстве случаев как программисты, так и бизнесмены обладают весьма туманными представлениями о том, что является наиболее ценным в разрабатываемом программном продукте. Однако если вы активно управляете показателем объема работ, вы можете предоставить менеджерам и заказчикам контроль над затратами, качеством и временем.
Отличительной чертой этого показателя является то, что объем работ – сильно изменяющаяся переменная. В течение десятилетий программисты привыкли жаловаться: Заказчики не могут сказать нам, чего они хотят. Когда мы даем им то, о чем они нас просили, они говорят, что им это не нравится. И это абсолютная горькая правда всей индустрии производства программного обеспечения. В самом начале работы над проектом требования заказчика никогда не бывают четкими и ясными. Заказчики никогда не могут сказать вам, что именно они хотят.
После разработки некоторого фрагмента программного продукта требования к нему изменяются. Как только заказчики видят первую версию продукта, они понимают, что они хотят увидеть во второй версии... или что они на самом деле хотели увидеть в первой версии. И это достаточно важный процесс познания, так как во многих случаях заказчики просто не могут сформулировать требования к продукту, которого в реальности пока что не существует. Зачастую не возможно четко и полностью сформулировать техническое задание на основе только лишь беспочвенных абстрактных размышлений и предположений. Многие важные умозаключения и выводы делаются заказчиками на основе опыта. Однако заказчики не имеют возможности получить свой опыт в одиночку. Они нуждаются в людах, которые умеют программировать. И эти люди должны быть не просто советчиками, они должны быть компаньонами.
Что, если посмотреть на нечеткость требований не как на проблему, а как на удобную возможность? В этом случае мы можем обнаружить, что показатель объема работ является наиболее удобной в управлении переменной из тех четырех переменных, о которых я говорил ранее. Так как этот показатель наименее четко очерчен, мы можем формировать его в соответствии с нашими собственными предпочтениями и предпочтениями заказчика – немного в эту сторону, немного в ту сторону. Если время поджимает и надо выпускать очередную версию продукта, у нас всегда будет что-то, что мы можем отложить до следующей версии. Однако если мы будем стараться не втискивать в рамки одной версии слишком много работы, то сохраним возможность выпустить продукт требуемого качества в указанные сроки.
Если мы создадим дисциплину разработки программного обеспечения на основе описанной модели, то получим возможность контролировать дату выпуска, качество и стоимость любого фрагмента программного продукта. Вначале мы можем рассматривать объем работ как функцию от первых трех переменных, однако в дальнейшем мы получаем возможность постоянно корректировать объем работ с учетом складывающихся условий.
Разрабатываемая нами дисциплина должна подразумевать низкую стоимость внесения изменений в проект, так как предполагается, что направление развития проекта будет меняться достаточно часто. Не стоит тратить деньги на разработку программного продукта, который в дальнейшем не будет использоваться. Не стоит тратить деньги на асфальтирование дороги, по которой вы все равно не будете ездить, так как вам придется свернуть на ближайшем повороте. Чтобы в подобной ситуации добиться желаемых результатов, вы должны использовать методику, в рамках которой стоимость внесения в проект изменений будет приемлемой в течение всего времени жизни системы.
Если вы будете отказываться от реализации важной функциональности в конце каждого очередного периода работы над очередной версией продукта, заказчик в скором времени разочаруется в вашей работе. Чтобы избежать этого, ХР использует две стратегии.
1. В процессе работы, приступая к реализации очередной части проекта, вы постоянно делаете предположение относительно того, сколько времени и усилий вам потребуется для того, чтобы реализовать эту часть проекта. В дальнейшем вы сравниваете реально затраченное время с вашими предварительными оценками. Таким образом вы тренируете свою способность правильно оценивать свои силы и снижаете вероятность отказа от реализации ранее запланированной функциональности.
2. В первую очередь вы реализуете те требования заказчика, которые являются наиболее важными для него. Таким образом, если на завершающем этапе работы над очередной версией системы приходится отказываться от реализации какой-либо функциональности, эта функциональность оказывается менее важной, чем та функциональность, которая уже присутствует в системе.
Глава 5
Стоимость внесения изменений
При определенных условиях экспоненциально растущую относительно времени стоимость внесения изменений в систему можно сгладить. Если кривая роста стоимости внесения изменений в систему сглаживается, старые правила, определяющие наилучшие методики разработки программного обеспечения, перестают быть верными.
Одно из общепринятых фундаментальных правил, определяющих традиционную стратегию разработки программного обеспечения, утверждает, что по мере работы над проектом стоимость внесения изменений в разрабатываемый программный продукт увеличивается экспоненциально. Я помню, как, будучи студентом колледжа, сидел в огромной аудитории, пол которой был покрыт блестящим линолеумом, и смотрел, как профессор рисует на доске кривую, изображенную на рис. 1.
Затраты, связанные с исправлением проблемы, обнаруженной внутри программного продукта, растут экспоненциально с течением времени, – говорил профессор. – Проблема, для решения которой в процессе анализа требований потребовался бы доллар, может стоить вам нескольких тысяч долларов, если вы обнаружите ее в момент, когда система уже будет в производстве.
Тогда, в той аудитории я раз и навсегда решил для себя, что я никогда не позволю проблемам оставаться в разрабатываемых мною программах до самого производства. Ни за что! Я обязательно буду устранять проблемы так быстро, как только это возможно. Я буду бороться с проблемами, которые даже еще не возникли, а только могут возникнуть. Я буду постоянно и беспрерывно пересматривать и проверять мой код. Ни под каким видом я не позволю себе допустить ошибку, которая в будущем будет стоить моему нанимателю сотни тысяч долларов.
Однако проблема состоит в том, что на самом деле кривая, изображенная на рис. 1, больше не соответствует действительности. Говоря точнее, благодаря использованию новых технологий и специальных методик программирования можно добиться того, что кривая стоимости внесения изменений в программный продукт будет выглядеть прямо противоположно. Теперь становятся возможными истории, подобные следующей, которая случилась со мной относительно недавно, во время работы над системой управления контрактами страхования жизни:
17.00 – я обнаруживаю, что некоторая встроенная в нашу систему возможность – способность в рамках одной трансакции хранить несколько дебетов с нескольких учетных записей и несколько кредитов для нескольких учетных записей – в процессе функционирования системы, по сути дела, не используется. Каждая трансакция извлекает средства только с одной учетной записи и переносит их только на одну учетную запись. У меня в голове возникает вопрос: можно ли упростить систему, как показано на рис. 2?
17.02 – я обращаюсь к Массимо и прошу его, чтобы он подошел ко мне и сел рядом для того, чтобы помочь мне разобраться в ситуации. Мы пишем запрос. Выясняется, что из всех 300 000 трансакций в системе ни одна не использует более одной учетной записи для снятия денег и более одной учетной записи для переноса денег. Каждой из трансакций соответствует только одна дебетная учетная запись и только одна кредитная учетная запись.
17.05 – если мы хотим исправить систему, как мы можем этого достичь? Мы можем изменить интерфейс компонента Transaction, а также изменить реализацию. Мы переписываем четыре требуемых метода и приступаем к тестированию.
17.15 – все тесты (более чем 1000 модульных и функциональных тестов) по-прежнему выполняются на 100% отлично. Мы не можем придумать ситуацию, в которой внесенные нами изменения могут стать причиной неработоспособности системы. Мы приступаем к работе над кодом миграции базы данных.
17.20 – мы завершаем программирование процедур миграции, которая должна быть выполнена в течение ночи. Также мы выполняем резервное копирование базы данных. После этого мы устанавливаем новую версию кода и инициируем процесс миграции.
17.30 – мы запускам несколько проверочных тестов. Все, что мы могли предусмотреть, работает великолепно. Не в состоянии придумать чтолибо важное, о чем мы могли позабыть, мы уходим домой.
Следующий день – журнал ошибок пуст. Никаких жалоб от пользователей не поступает. По всей видимости, внесенные нами изменения отлично работают.
В течение нескольких следующих недель мы обнаружили, что в связи с использованием новой структуры разрабатываемую нами систему можно упростить еще больше. При этом мы получаем возможность внести в бухгалтерский раздел нашей программы совершенно новую удобную функциональность. Таким образом мы делаем систему проще, чище и менее избыточной.
В течение последних нескольких десятилетий сообщество людей, работающих в области разработки программного обеспечения, приложило огромные усилия для того, чтобы снизить стоимость внесения изменений. Для этой цели были разработаны более совершенные языки программирования, более совершенные технологии баз данных, более эффективные методики кодирования, улучшенные среды и инструменты разработки, новые правила.
Что, если все эти инвестиции не пропали даром? Что, если вся эта суета с новыми языками программирования и новыми базами данных не была напрасной? Что, если теперь стоимость внесения изменений не растет экспоненциально, как раньше, а увеличивается более медленно, со временем приближаясь к асимптоте? Что, если завтра профессор, преподающий студентам основы разработки программного обеспечения, нарисует на доске линию, изображенную на рис. 3?
Именно это является одним из основных предположений ХР. Это техническое предположение ХР. Если стоимость внесения в систему изменений со временем растет достаточно медленно, стратегия разработки программы должна быть совершенно другой, отличной от той, которая используется в случае, если стоимость внесения в систему изменений современем растет экспоненциально. В подобной ситуации вы можете откладывать решение важных задач на более поздние сроки. Вы получаете возможность принимать важные решения настолько поздно, насколько это возможно. Это делается для того, чтобы осуществлять связанные с этим затраты как можно позже. Кроме того, если вы откладываете решение важных вопросов на более поздний срок, тем самым вы повышаете вероятность того, что выбранное вами решение окажется правильным. Другими словами, сегодня вы должны реализовать только то, без чего сегодня не обойтись, при этом вы можете рассчитывать на то, что проблемы, решение которых вы отложили до завтра, развеются сами собой, то есть перестанут быть актуальными. Вы можете добавлять в дизайн новые элементы только в случае, если эти новые элементы упрощают код или делают написание следующего фрагмента кода более простым.
Если пологая кривая роста затрат делает ХР возможным, то экспоненциальная кривая роста затрат делает ХР невозможным. Если изменение обойдется вам в кругленькую сумму, вы сойдете с ума, пытаясь предугадать, каким образом это изменение повлияет на работу системы. Если же изменение обходится вам дешево, вы всегда можете рискнуть и проверить, что будет, если вы тем или иным образом измените код, – позже вы всегда можете изменить систему так, как это будет лучше. В подобной ситуации, внеся изменения в систему, вы через короткое время получаете ответную информацию о том, насколько полезны данные изменения для системы.
Но как поддерживать невысокую стоимость изменений на протяжении всего времени работы над проектом? Сохранение низкой стоимости изменений – это не какой-то магический трюк, оно достигается не просто так, а в результате применения технологий и методик, которые позволяют сделать программный продукт податливым и легко модернизируемым.
С технологической точки зрения ключевой технологией, позволяющей добиться этого, являются объекты. Обмен сообщениями между объектами позволяет существенно расширить спектр возможностей по изменению разрабатываемой системы. Каждое сообщение становится потенциальной точкой для внесения в систему грядущих модификаций, модификаций, которые могут вносится в систему, не затрагивая при этом существующий код.
Объектные базы данных переносят эту гибкость в пространство постоянной памяти. Благодаря использованию объектной базы данных вы получаете возможность с легкостью переносить информацию об объектах из одного формата в другой, так как в объектных базах данных код соединен с данными, а не отделен от них, как это было в более ранних базах данных. Даже если вы не можете найти способ выполнить миграцию объектов, вы можете обеспечить в рамках одной системы сосуществование двух разных реализаций.
Я вовсе не хочу сказать, что вы обязаны использовать объекты для того, чтобы получить гибкость. Лично я познакомился с основами ХР, когда наблюдал, как мой отец пишет на ассемблере управляющий код процесса реального времени. Он разработал стиль, который позволил ему постоянно обновлять дизайн его программ. Все же мой опыт подсказывает мне, что стоимость изменений увеличивается в большей степени в случае, если вы не используете объекты, чем в случае, если вы основываете свой проект на объектно-ориентированном подходе.
Я также не хочу сказать, что объекты – это все, что вам потребуется для снижения стоимости затрат. Я видел (и даже, по правде сказать, сам написал) немало кодов, заниматься изменением которых я не пожелал бы и врагу.
Чтобы упростить модификацию вашего кода даже спустя несколько лет после начала работы над проектом, вы должны учитывать следующие факторы:
• простой дизайн, в котором отсутствуют лишние элементы, – никаких идей, которые на текущий момент не используются, однако предположительно могут использоваться в будущем;
• автоматические тесты – благодаря им всегда с легкостью можно узнать о том, что в результате внесения в систему изменений ее поведение изменилось;
• постоянная практика в деле модификации дизайна системы – когда приходит время менять систему, вы не почувствуете страха перед этим.
Если мы заложим в основу нашей работы три перечисленных элемента – простой дизайн, автоматические тесты и опыт постоянного видоизменения системы, мы увидим, что кривая расходов, связанных с внесением в систему изменений, станет пологой, как на рис. 3. Изменение, для осуществления которого до начала кодирования потребовалось бы несколько минут, через два года работы над системой потребует от вас не более 30 минут. Однако я сталкивался с проектами, в которых на принятие и предварительное обдумывание подобных решений тратятся дни и даже недели, хотя вместо этого проблему можно решить уже сейчас, а завтра, если это потребуется, можно будет с легкостью все переделать на новый лад.
Теперь, когда мы кардинально пересмотрели наши изначальные предположения относительно стоимости внесения в систему изменений, у нас появляется возможность применить совершенно иной подход к разработке программного обеспечения. Как и любые другие подходы, разрабатываемый нами подход строг, он не терпит нарушения определяемых в его рамках правил, однако его строгость лежит в несколько иных измерениях. Вместо того чтобы заботиться о принятии важных решений как можно раньше и менее значительных решений – позже, мы с вами планируем разработать подход, в рамках которого каждое решение принимается быстро, при этом оно надежно защищается с использованием автоматических тестов. Помимо этого, в рамках нового подхода вы должны быть готовыми к изменению дизайна системы в случае, если вы понимаете, что существует более удачный дизайн, чем тот, который реализован вами на текущий момент.
Создание такого подхода – далеко не простая задача. Мы должны будем заново проанализировать и пересмотреть принятые нами ранее предположения о том, какая методика разработки программного обеспечения является хорошей, а какая – нет. Мы будем двигаться в сторону цели поэтапно. А начнем мы с рассказа, который будет притягивать к себе все остальное, чем мы будем заниматься.
Глава 6.
Обучение управлению автомобилем
Управляя разработкой программного продукта, мы должны совершать множество незначительных преобразований и воздействий. Мы должны избегать применения нескольких существенных модернизаций. Другими словами, управление разработкой программной системы в некотором смысле должно напоминать управление едущим автомобилем. Это означает, что у нас должна быть обратная связь для того, чтобы вовремя узнать о том, что мы несколько отклонились от желаемого направления движения. Мы должны обладать самыми широкими возможностями по внесению в проект изменений, кроме того, мы должны обладать возможностью вносить эти изменения ценой приемлемых для нас затрат.
Теперь у нас есть общая формулировка проблемы – угрожающе огромная цена риска и возможность управлять этим риском при помощи вариантов, кроме того, мы обладаем ресурсом, который потребуется нам для формирования решения: свобода вносить изменения позже, не увеличивая при этом связанные с этим затраты. Теперь мы должны сконцентрировать усилия на поиске решения. Самая первая вещь, которая нам для этого потребуется, – это метафора – образно оформленный рассказ, к которому мы могли бы обращаться время от времени в случае стресса или для поддержки.
Я отлично помню тот день, когда впервые начал учиться водить машину. Я и моя мать сели в машину и выехали на автостраду Interstate 5 вблизи Чико (Chico) в штате Калифорния. Это прямой как стрела пустынный участок шоссе, выходящий из-под колес машины и, подобно натянутой струне, устремляющийся вдаль – к линии горизонта. Моя мать позволила мне пересесть в водительское кресло, а сама села на место переднего пассажира. И мы поехали. В начале я с осторожностью изучил, как именно движение рулевого колеса влияет на направление движения автомобиля, затем, освоившись, я позволил себе несколько расслабиться. Управлять машиной надо так, – учила меня моя мама, – направь машину строго по середине дороги и езжай по этой дороге прямо в направлении горизонта.
Мы ехали достаточно долго, и где-то посередине нашего путешествия что-то отвлекло мое внимание. Машина стала смещаться в сторону края дороги. Моя мать несколько обеспокоилась...
Когда колеса зашуршали по гравию на обочине, я немедленно опомнился. Моя мама (сейчас ее тогдашнее хладнокровие кажется мне ошеломляющим) плавно поправила руль так, чтобы машина вернулась на центр дороги. После этого она дала мне наиболее важное наставление относительно того, как следует управлять автомобилем:
Это наставление является парадигмой для ХР. В рамках ХР не существует такой вещи, как прямое направление движения. Даже если вам кажется, что дела идут замечательно, вы не должны отрывать ваших глаз от дороги. Неизменными остаются только сами изменения. Всегда будьте готовы к тому, чтобы изменить направление чуть-чуть в одну сторону, затем чуть-чуть в другую сторону. В некоторых ситуациях вам придется менять направление так, что вы начнете движение в совершенно другую сторону. Такова жизнь программиста.
Абсолютно все в мире программного обеспечения меняется. Требования заказчиков меняются. Дизайн меняется. Бизнес видоизменяется. Технологии меняются. Команда разработчиков меняется. Члены команды разработчиков меняются. Сама по себе проблема остается неизменной, так как изменение рано или поздно должно произойти. На самом деле проблема состоит в том, что когда происходит изменение, люди не в состоянии с ним справиться.
Шофером программного проекта является заказчик. Если программа не делает того, чего заказчик от нее хочет, – это ваша неудача. Конечно же, заказчик не может сказать точно, чего именно он хочет от программы. Именно поэтому разработка программного продукта должна напоминать управление автомобилем. Редко когда кто-либо едет на машине, стараясь, чтобы автомобиль ни на миллиметр не отклонился от желаемой жестко заданной прямой. Обычно люди стараются обеспечить движение в заданном направлении, слегка подправляя направление движения при помощи рулевого колеса. Как программисты мы должны предоставить заказчику рулевое колесо, а также обеспечить обратную связь, как можно чаще сообщая ему, в каком именно месте дороги находится наш автомобиль.
Рассказ об управлении автомобилем также определяет мораль процесса ХР. Описанные в следующей главе четыре ценности – коммуникация, простота, обратная связь и храбрость – дают представление о том, как должен выглядеть процесс разработки программного обеспечения. Однако методики, благодаря которым это достигается, будут отличаться для разных мест, разного времени и разных людей. Управляя процессом разработки, вы используете простой набор методик и стараетесь сформировать этот процесс так, как это описывается далее. По мере того как разработка продолжается, вы постоянно следите за тем, какие из методик требуют улучшения, а какие методики плохо соответствуют поставленной цели. Каждая методика – это эксперимент, который необходимо проводить до тех пор, пока не станет ясно, что он неадекватен.
Глава 7.
Четыре ценности
Мы сможем успешно решить стоящую перед нами проблему, если сформулируем стиль, который направлен на прославление каждой из согласующегося набора ценностей, которые служат как человеческим, так и коммерческим требованиям: коммуникация, простота, обратная связь и храбрость.
Прежде чем на основе рассказа об управлении автомобилем сформировать набор методик разработки программного обеспечения, мы должны найти некоторый критерий, благодаря которому сможем узнать о том, что движемся в правильном направлении. Согласитесь, что было бы плохо, если бы мы создали стиль разработки, а потом узнали, что этот стиль нам не нравится или что он не срабатывает.
Краткосрочные индивидуальные цели часто конфликтуют с долгосрочными социальными целями. Общество решает эту проблему при помощи набора ценностей, подкрепленных мифами, ритуалами, наказаниями и наградами. Без уважения к этим ценностям люди забывают о социальных нуждах и стремятся реализовать свой собственный индивидуальный краткосрочный интерес.
Четыре ценности для ХР – это:
• коммуникация (communication);
• простота (simplicity);
• обратная связь (feedback);
• храбрость (courage).
Первая ценность ХР – это коммуникация. Проблемы, которые возникают в процессе работы над проектом, почти всегда связаны с тем, что кто-то не сказал кому-то о чем-то важном. Иногда программист не сообщает кому-то о важном изменении в дизайне. Иногда программист не задает заказчику важного вопроса, и в результате важное принятое им решение оказывается неправильным. Иногда менеджер не задает программисту важного вопроса, в результате у него складывается неполное, а иногда и неправильное представление о состоянии проекта.
Плохая коммуникация – это не случайность. Существует огромное количество предпосылок, которые ведут к нарушению коммуникации. Например, программист сообщает менеджеру плохие новости и менеджер наказывает программиста. Заказчик сообщает программисту нечто важное, а программист делает вид, что не понял или просто проигнорирует эту информацию.
Дисциплина ХР нацелена на обеспечение непрерывной, постоянно осуществляемой коммуникации между участниками проекта. В рамках ХР используются многие методики, которые невозможно реализовать без коммуникации. Эти методики направлены на достижение краткосрочных целей, например, тестирование модулей, программирование парами, а также оценка сложности задачи. В процессе тестирования, программирования парами и формирования предварительных оценок программисты, заказчики и менеджеры вынуждены тесно взаимодействовать.
Это не означает, что излишние разговоры мешают работе. Люди часто попадают в ситуацию, когда они сомневаются, делают ошибки, отвлекаются. В рамках ХР существует специальное ответственное лицо – инструктор (coach), в чьи обязанности входит следить за тем, чтобы люди общались тогда, когда это надо. Если инструктор замечает, что люди перестают общаться, он стимулирует коммуникацию.
Вторая ценность ХР – это простота. Инструктор ХР спрашивает команду: Какова самая простая вещь, которая скорее всего сработает? (эта фраза является часто употребляемым выражением, в определенном смысле девизом, так что в мире ХР даже существует специальная аббревиатура – Do The Simplest Thing That Could Possibly Work[4],
Простота – это далеко не так просто. Напротив, это очень даже сложно – не обращать внимания на вещи, которые вы намерены реализовать завтра, на следующей неделе, в следующем месяце. Вы должны понимать, что если вы намеренно пытаетесь предугадать, как в будущем будет развиваться проект, это значит, что вы боитесь экспоненциального роста стоимости изменений. Программист боится, что завтра ему придется тратить массу усилий для исправления ошибок, которые он сделает сегодня, в результате он зачастую делает код более сложным. Время от времени инструктор должен мягко напоминать программистам, работающим над проектом, что вместо того, чтобы заниматься решением текущих задач, они пытаются прислушаться к собственным внутренним страхам. Если ты пытаешься заставить работать это динамически сбалансированное бинарное дерево, значит, ты умнее, чем я. У меня складывается впечатление, что в данном случае можно обойтись обычным линейным поиском.
Грег Хатчинсон (Greg Hatchinson) пишет:
Один человек, которого я консультировал, пришел к выводу, что для отображения текста нам потребуется универсальное диалоговое окно. Мы обсудили интерфейс этого диалога и как он будет работать. Программист решил, что диалог должен быть достаточно совершенным, он должен автоматически менять собственный размер и количество символов переноса строки в отображаемом тексте в зависимости от размера шрифта и других факторов. Я поинтересовался у него, какое количество других программистов, так же как он, нуждается в подобном диалоговом окне. Он ответил, что на текущий момент такое диалоговое окно нужно только ему. Я предложил не делать диалоговое окно столь интеллектуальным и ограничиться более узким набором возможностей. В этом случае диалоговое окно можно было бы реализовать минут за двадцать. Мы могли бы сделать класс с известным интерфейсом, а затем, когда появится такая необходимость, мы всегда могли бы усовершенствовать наше окно так, как этого потребует конкретная ситуация. К сожалению, я не смог убедить его, в результате он потратил два дня на реализацию своей идеи. На третий день условия задачи, для решения которой требовалось данное диалоговое окно, изменились и надобность в подобном диалоговом окне полностью отпала. Таким образом, два человеко-дня ушло на то, чтобы решить проблему, которая сразу же после этого перестала быть актуальной. Все же если вы сможете найти применение для данного кода, сообщите мне об этом.
ХР делает свою ставку. Предполагается, что лучше сделать простую вещь сегодня и заплатить чуточку больше завтра для того, чтобы модифицировать ее (если в этом возникнет необходимость), чем разработать более сложный код сегодня, а потом узнать, что этот код больше не нужен.
Простота и коммуникация обладают замечательной взаимоподдерживающей связью. Чем больше вы общаетесь, тем яснее для вас становится, что именно вы должны сделать, и тем больше вы уверены в том, чего делать не надо. Чем проще система, тем меньше тем для обсуждения, а значит, тем полнее становится общение, особенно если вы упрощаете систему настолько, что для работы над ней требуется меньшее количество программистов.
Третья ценность в ХР – это обратная связь. Инструктор ХР часто произносит:
Обратная связь работает в разных временных масштабах. Во-первых, обратная связь работает в масштабе минут и дней. Программисты пишут тесты для всей логики в системе. Любой из этих тестов может не сработать. Так программист получает обратную связь, которая ежеминутно обеспечивает его сведениями о состоянии системы. Когда заказчик пишет новые истории (описания возможностей системы), программисты немедленно оценивают их, благодаря чему заказчик получает обратную связь, которая обеспечивает его сведениями о качестве его историй. Человек, который следит за своевременным решением задач в рамках проекта, обеспечивает всех членов команды сведениями о том, какова вероятность того, что запланированный объем работ будет реализован в установленные сроки.
Обратная связь также работает в масштабе недель и месяцев. Заказчики и те, кто обеспечивает функциональное тестирование системы, разрабатывают функциональные тесты для всех историй (говоря иначе – упрощенных тестовых случаев), реализованных в рамках системы. Таким образом они обладают обратной связью, которая обеспечивает их информацией о текущем состоянии используемой ими системы. Заказчики пересматривают график работ каждые две или три недели для того, чтобы убедиться, что скорость выполнения работ соответствует плану. В случае необходимости план пересматривается. Эксплуатация системы в реальных производственных условиях начинается, как только система становится способной решать хотя бы небольшую часть возлагаемых на нее обязанностей. В результате бизнес получает возможность на практике оценить, как именно выглядит система и в каком направлении ее лучше всего развивать в дальнейшем.
О том, что к эксплуатации системы следует приступать как можно раньше, следует рассказать подробнее. Одной из стратегий в процессе планирования является правило, в соответствии с которым наиболее полезные для заказчика истории реализуются программистами и начинают эксплуатироваться как можно раньше. Благодаря этому программисты получают обратную связь, которая обеспечивает их сведениями о качестве принятых ими решений. Процесс разработки начинает напоминать управление автомобилем – программисты прилагают усилия для того, чтобы проект развивался в направлении, удобном для заказчика, при этом колеса должны всегда оставаться на асфальте. Некоторые программисты занимаются разработкой системы длительное время до того, как она начнет эксплуатироваться в реальных рабочих условиях. Откуда же они могут узнать о том, что выполняемая ими работа действительно качественна и необходима?
В большинстве проектов используется прямо противоположная стратегия. Многие рассуждают так: Как только система начинает использоваться на реальном производстве, в нее нельзя будет внести «интересных» изменений, поэтому система должна находится в стадии разработки настолько долго, насколько это возможно.
В ХР делается прямо противоположное. В разработке – это временное состояние, в котором система находится в течение очень небольшого времени своей жизни. Будет значительно лучше, если система будет жить самостоятельной жизнью независимо от разработки. Необходимо позволить ей дышать и действовать самостоятельно. Необходимо поддерживать функционирование системы в условиях реального производства и одновременно с этим, разрабатывать новую функциональность. Необходимо обеспечить параллельную разработку и эксплуатацию, и чем раньше вы этого добьетесь, тем лучше.
Обратная связь работает совместно с коммуникацией и простотой. Чем более исчерпывающей является обратная связь, тем легче осуществлять коммуникацию. Когда кто-то недоволен написанным вами кодом и передает вам тестовый случай, который указывает на ошибку, это заменяет вам тысячу часов пространных дискуссий на тему эстетики программного дизайна. Если вы хорошо осуществляете коммуникацию, вы лучше знаете, что следует тестировать в системе. Простые системы тестировать проще. Разработка теста концентрирует ваше внимание на том, насколько простой может быть система; до тех пор, пока тест не сработает, вы не можете считать работу завершенной, а когда срабатывают все тесты, можно считать, что вы решили поставленную перед вами задачу.
В контексте первых трех рассмотренных ранее ценностей – коммуникации, простоты и обратной связи – необходимо действовать с максимально возможной скоростью. Если вы работаете со скоростью, которая не является абсолютно максимальной, это будет делать вместо вас кто-то другой, в результате этот кто-то прибежит к финишу первым и съест ваш обед вместо вас.
Я расскажу вам о том, как храбрость срабатывает в реальной жизни. В середине восьмой итерации включающего в себя 10 итераций рабочего графика (25 из 30 недель) первой версии первого крупного ХР-проекта команда обнаружила фундаментальную ошибку в архитектуре системы. Поначалу функциональные тесты указывали на хорошее качество разрабатываемой системы, однако позже количество набранных нами очков резко снизилось. В результате исправления одного дефекта обнаруживался другой дефект. Количество дефектов увеличивалось. Проблема была в архитектурном изъяне.
Для любопытных скажу, что мы работали над системой начисления выплат. Для хранения долгов компании перед сотрудниками использовались поля данных с названием Entitlement (жалованье), а для хранения долгов сотрудников перед другими людьми использовались поля с названием Deduction (вычет). Для некоторых людей использовалось отрицательное жалованье, в то время как вместо этого надо было использовать положительный вычет.
Команда поступила так, как должна была поступить. Когда все поняли, что путь вперед закрыт, они исправили архитектурный изъян. При этом половина всех используемых в отношении системы тестов перестала срабатывать. Однако в течение нескольких дней напряженных усилий по исправлению ситуации тесты снова начали срабатывать и качество системы, оцениваемое при помощи функциональных тестов, повысилось. Однако для того, чтобы поступить описанным образом, потребовалась отвага.
Еще один смелый ход – отказ от ранее разработанного кода. Представьте, что в течение всего рабочего дня вы работаете над реализацией некоторой функциональности. Работа идет неплохо, но когда вы близки к ее завершению, компьютер зависает. На следующее утро вы приходите на работу и в течение получаса восстанавливаете то, над чем работали весь предыдущий день, однако на этот раз код получается более чистым и более простым.
Используйте это. Если приближается конец рабочего дня и код все еще не поддается контролю, выбросьте его. Может быть, следует сохранить тестовые случаи, если вам понравился разработанный вами интерфейс. Однако это не обязательно. Возможно, следующим утром будет легче начать с нуля.
Возможно, перед вами три варианта дизайна. Вы можете потратить по одному дню на реализацию каждой из альтернатив для того, чтобы почувствовать, как они будут вести себя на практике. Затем выбросьте код и начните с нуля развивать тот вариант дизайна, который показался вам наиболее многообещающим.
Стратегия проектирования в ХР напоминает алгоритм взбирания на холм (hill climbing). Вы делаете простой дизайн, затем вы делаете его более сложным, далее вы его упрощаете, потом опять усложняете. Проблема подобных алгоритмов состоит в том, что вы ищете локальный оптимум, – при этом никакое незначительное изменение не может улучшить ситуацию, однако улучшения можно достичь, используя значительное изменение.
Достигнув локального оптимума вы, возможно, упускаете более эффективный вариант дизайна. Что поможет вам избежать этого? Как только у кого-нибудь из вашей команды возникает сумасшедшая идея, в результате реализации которой сложность всей системы существенно уменьшится, он обязательно попробует реализовать свою идею, если конечно, у него хватит храбрости. Иногда это срабатывает. Если у вас хватит храбрости, вы приступите к эксплуатации новой версии системы в промышленных условиях. Считайте, что теперь вы забираетесь на совершенно новый холм.
Если у вас нет остальных трех ценностей, храбрость сама по себе является обычным взломом (в самом уничижительном смысле этого слова). Однако в сочетании с коммуникацией, простотой и надежной обратной связью храбрость становится чрезвычайно полезной.
Коммуникация идет на пользу храбрости, так как благодаря коммуникации вы обретаете возможность для осуществления более рискованных и более заманчивых экспериментов. Тебе это не нравится? Я просто ненавижу этот код! Давай вместе посмотрим, в какой мере мы сможем переделать его сегодня днем. Простота идет на пользу храбрости, так как, обладая более простой системой, вы сможете позволить себе более смелые действия в ее отношении. Маловероятно, что вы нарушите ее функционирование по неизвестным причинам. Храбрость способствует простоте, ведь как только вы видите способ упростить систему, вы немедленно пробуете его реализовать. Надежная обратная связь идет на пользу храбрости, так как в процессе серьезной модернизации кода вы чувствуете себя значительно увереннее, если вы можете щелкнуть на кнопке и увидеть, что в результате тестирования все тесты показывают зеленый цвет. Если зеленым цветом окрашиваются не все тесты, вы переделываете или просто выкидываете свой код.