Фредерик Брукс - Мифический человеко-месяц или как создаются программные системы
Но, вглядываясь в предстоящее десятилетие, мы не видим никакой серебряной пули. Нет ни одного открытия ни в технологии, ни в методах управления, одно только использования которых обещало бы хоть на порядок величин повысить производительность, надежность, простоту. В этой главе мы попытаемся увидеть, почему это так, исследуя природу задач программирования и свойства предлагаемых пуль.
Однако скептицизм — это не пессимизм. Хотя мы не видим ошеломляющих прорывов и действительно считаем их несвойственными природе программирования, происходит много вселяющих надежды нововведений. Дисциплинированные и последовательные усилия, направленные на их развитие, распространение и использование, действительно могут дать рост на порядок величин. Нет царского пути, но все же путь есть.
Первым шагом к лечению болезней стала замена представлений о демонах и «соках» в организме теорией бактерий. Сам этот шаг, обещавший надежду, опроверг все мечты о чудесном исцелении. Он подсказал исследователям, что прогресс будет осуществляться шажками, с большим трудом, и что постоянное и неослабное внимание нужно уделять санитарии. То же происходит сегодня с программной инженерией.
Неизбежны ли трудности? Трудности, вытекающие из сущности
Серебряных пуль не только не видно в настоящее время, но в силу самой природы программного обеспечения маловероятно, что они вообще будут найдены — не будет изобретений, способных повлиять на продуктивность создания, надежность и простоту программного обеспечения так, как электроника, транзисторы и интегральные схемы — на аппаратное обеспечение компьютеров. Не следует ожидать, что когда-либо в будущем каждые два года будет происходить двукратный рост.
Во-первых, следует считать необычным не то, что так медленно происходит прогресс в программировании, а то, что он так быстро идет в аппаратном обеспечении компьютеров. Ни одна другая технология за всю историю цивилизации не имела за 30 лет своего развития роста соотношения производительность/цена на шесть порядков. Ни одна другая технология не позволяет выбрать, какой выигрыш предпочесть: улучшить технические характеристики или снизить затраты. Оба эти выигрыша стали возможны благодаря переходу производства компьютеров из сборочного производства в обрабатывающее.
Во-вторых, чтобы посмотреть, какой скорости развития можно ожидать от программных технологий, полезно изучить имеющиеся в них трудности. Следуя Аристотелю, я делю их на сущности — трудности, внутренне присущие природе программного обеспечения, и акциденции — трудности, которые сегодня сопутствуют производству программного обеспечения, но не являются внутренне ему присущими.
Акциденции я рассматриваю в следующем параграфе. Сначала рассмотрим сущность.
Сущностью программного объекта является конструкция, состоящая из сцепленных вместе концепций: наборов данных, взаимосвязей между элементами данных, алгоритмов и вызовов функций. Эта сущность является абстрактной в том отношении, что концептуальная конструкция остается одной и той же при различных представлениях. Тем не менее она обладает высокой точностью и большим числом деталей.
Я считаю, что сложность создания программного обеспечения заключается в задании технических требований, проектировании и проверке этой концептуальной конструкции, а не в затратах, связанных с ее представлением и проверкой точности представления. Конечно, мы делаем синтаксические ошибки, но в большинстве систем они несущественны в сравнении с концептуальными ошибками.
Верно то, что создание программных систем всегда будет трудным. Серебряной пули нет по самой природе вещей.
Рассмотрим неотъемлемые свойства этой несократимой сущности современных программных систем: сложность, согласованность, изменяемость и незримость.
Сложность. Сложность программных объектов более зависит от их размеров, чем, возможно, для любых других создаваемых человеком конструкций, поскольку никакие две их части не схожи между собой (по крайней мере, выше уровня операторов). Если они схожи, то мы объединяем их в одну подпрограмму, открытую или закрытую. В этом отношении программные системы имеют глубокое отличие от компьютеров, домов и автомобилей, где повторяющиеся элементы имеются в изобилии.
Сами цифровые компьютеры сложнее, чем большинство изготавливаемых людьми вещей. Число их состояний очень велико, поэтому их трудно понимать, описывать и тестировать. У программных систем число возможных состояний на порядки величин превышает число состояний компьютеров.
Аналогично, масштабирование программного объекта — это не просто увеличение в размере тех же самых элементов, это обязательно увеличение числа различных элементов. В большинстве случаев эти элементы взаимодействуют между собой неким нелинейным образом, и сложность целого растет значительно быстрее, чем линейно.
Сложность программ является существенным, а не второстепенным свойством. Поэтому описания программных объектов, абстрагирующиеся от их сложности, часто абстрагируются от их сущности. Математика и физические науки за три столетия достигли больших успехов, создавая упрощенные модели сложных физических явлений, получая из этих моделей свойства и проверяя их опытным путем. Это удавалось благодаря тому, что сложности, игнорировавшиеся в моделях, не были существенными свойствами явлений. И это не действует, когда сложности являются сущностью.
Многие классические трудности разработки программного обеспечения проистекают их этой сложности сущности и ее нелинейного роста при увеличении размера. Сложность служит причиной трудности процесса общения между участниками бригады разработчиков, что ведет к ошибкам в продукте, превышению стоимости разработки, затягиванию выполнения графиков работ. Сложность служит причиной трудности перечисления, а тем более понимания, всех возможных состояний программы, а отсюда возникает ее ненадежность. Сложность функций служит причиной трудностей при их вызове, из-за чего программами трудно пользоваться. Сложность структуры служит причиной трудностей при развитии программ и добавлении новых функций так, чтобы не возникали побочные эффекты. Сложность структуры служит источником невизуализуемых состояний, в которых нарушается система защиты.
Сложность служит причиной не только технических, но и административных проблем. Из-за сложности трудно осуществлять надзор, а в результате страдает концептуальная целостность. Трудно найти и держать под контролем все свободные концы. Обучение и понимание становится колоссальной нагрузкой, из-за чего текучесть рабочей силы превращается в катастрофу.
Согласованность. Люди, связанные с программированием, не одиноки в проблемах сложности. Физика имеет дело с объектами чрезвычайной сложности даже на уровне элементарных частиц. Однако физик работает в твердой уверенности, что можно найти общие принципы, будь то кварки или общая теория поля. Эйнштейн неоднократно утверждал, что природа должна иметь простые объяснения, поскольку Богу не свойственны капризность и произвол.
У разработчика программного обеспечения нет такой утешительной веры. Сложность, с которой он должен совладать, по большей части является произвольной, необоснованно вызванной многочисленными человеческими установлениями и системами, которым должны удовлетворить его интерфейсы. Системы различаются интерфейсами и меняются во времени не в силу необходимости, а лишь потому, что были созданы не Богом, а разными людьми.
Во многих случаях программное обеспечение должно согласовываться, поскольку только что появилось на сцене. В других случаях оно должно согласовываться, поскольку есть ощущение, что его легче всего согласовать. Но во всех случаях значительная часть сложности происходит от согласования с другими интерфейсами, и это невозможно упростить только в результате перепроектирования программного обеспечения.
Изменяемость. Программные объекты постоянно подвержены изменениям. Конечно, это относится и к зданиям, автомобилям, компьютерам. Но произведенные вещи редко подвергаются изменениям после изготовления. Их заменяют новые модели, или существенные изменения включают в более поздние серийные экземпляры того же базового проекта. Отзывы у потребителей автомобилей на практике встречаются весьма редко, а изменения работающих компьютеров еще реже. То и другое случается значительно реже, чем модификация работающего программного обеспечения.
Отчасти это происходит потому, что программное обеспечение в системе воплощает ее назначение, а назначение более всего ощущает влияние изменений. Отчасти это происходит потому, что программное обеспечение легче изменить: это чистая мысль, бесконечно податливая. Здания тоже перестраиваются, но признаваемая всеми высокая стоимость изменений умеряет капризы новаторов.