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