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