Такая стратегия проектирования повышает повторную используемость модулей. Еще важнее, что ее можно расширить, включая не только поставляемые продукты, но и последовательные промежуточные версии, созданные по стратегии инкрементируемых сборок. В этом случае продукт развивается через промежуточные стадии с минимумом возврата назад.
Подход Microsoft: «ежевечерняя сборка». Джеймс Маккарти (James McCarthy) описал мне процесс, использовавшийся им и другими в Microsoft. Это пошаговое наращивание, доведенное до логического конца. Он пишет:
Сделав первую поставку, новые версии мы поставляем с дополнительными функциями, по сравнению с существующим работающим продуктом. Почему должен быть иным процесс первоначальной сборки? С момента достижения нами первой вехи (у первой поставки три промежуточных вехи) мы каждый вечер заново собираем разрабатываемую систему (и прогоняем контрольные примеры). Цикл сборки становится ритмом жизни проекта. Каждый вечер одна или более бригад программистов, проводящих тестирование, регистрируют модули с новыми функциями. После каждой сборки у нас есть работающая система. Если сборка оказывается неудачной, мы останавливаем весь процесс, пока ошибка не будет найдена и исправлена. В любой момент все в группе знают положение дел.
Это действительно тяжело. Требуется выделение больших ресурсов, но это управляемый процесс, прослеживаемый и понятный. Он вызывает у команды доверие к себе. А доверие определяет мораль, эмоциональное состояние.
Такой процесс удивляет и даже шокирует разработчиков в других организациях. Один из них говорит: «Я взял себе за правило делать сборку каждую неделю, но ежедневная сборка, я думаю, потребует слишком много труда.» И это, возможно, верно. Например, в Bell Northern Research собирают систему, состоящую из 12 миллионов строк, раз в неделю.
Инкрементная сборка и быстрое макетирование. Поскольку инкрементная разработка позволяет рано начать тестирование реальными пользователями, в чем ее отличие от быстрого макетирования? Мне кажется, что они связаны, но различаются. Одним можно пользоваться без другого.
Харел дает полезное определение макета:
(версия программы, которая) отражает только проектные решения, принятые в процессе подготовки концептуальной модели, а не решения, вызванные соображениями реализации. [12]
Можно построить макет, который вовсе не является частью продукта, развивающегося в направлении поставки. Например, можно создать макет интерфейса, за которым стоит не реально работающая программа, а лишь конечный автомат, заставляющий его имитировать прохождение состояний. Можно даже макетировать и тестировать интерфейсы методом волшебника изумрудного города, когда спрятанный человек имитирует отклик системы. Такое макетирование может быть весьма полезным для быстрого получения обратной связи от пользователя, но оно находится совершенно в стороне от тестирования продукта, который готовится к поставке.
Аналогично, разработчики могут попробовать построить вертикальный срез продукта, в котором полностью реализован весьма ограниченный набор функций, чтобы заранее пролить свет на те места, где могут таиться опасности для производительности продукта. В чем состоит различие между сборкой на первой вехе в процедуре Microsoft и быстрым макетом? В функциях. Продукт с первой вехи может иметь такую ограниченную функциональность, что ни для кого не будет представлять интереса. Готовность продукта к поставке определяется завершенностью в предоставлении полезного набора функций и своим качеством, уверенностью в надежной работе.
В главе 7 я противопоставляю две точки зрения на то, в какой мере каждый участник команды может иметь право или поощряться к знанию проектов и текстов программ, созданных коллегами. Во время проекта Operating System/360 мы решили, что все программисты должны видеть весь материал, т.е. у каждого программиста была рабочая тетрадь проекта, которая к концу насчитывала свыше 10000 страниц. Харлан Миллз убедительно доказывал, что «программирование должно быть открытым процессом», что предоставление всей работы на общее обозрение способствует контролю качества как благодаря давлению со стороны коллег, заставляющему работать хорошо, так и благодаря тому, что коллеги действительно находят промахи и ошибки.
Этот взгляд резко противоречит мнению Дэвида Парнаса о том, что программные модули должны быть инкапсулированы, с хорошо определенными интерфейсами, а внутренность таких модулей должна быть частной собственностью программиста, невидимой снаружи. Программисты эффективнее всего работают, будучи ограждены от внутренностей чужих модулей. [13]
В главе 7 я заклеймил идею Парнаса как «рецепт катастрофы». Парнас был прав, а я ошибался. Сегодня я убежден, что ограничение информации, часто осуществляемое теперь методами объектного программирования, является единственным способом поднять уровень программных разработок.