Серебряной пули нет - сущность и акциденция в программной инженнерии
(глава 16 Брукс Ф. - Мифический человеко - месяц или Как создаются программные системы)

Брукс Ф., Мифический человеко - месяц или Как создаются программные системы.

http://www.lib.ru/

     Нет ни одного открытия ни в технологии, ни в методах управления,одно только использование которого обещало бы в течение ближайшегодесятилетия на порядок повысить производительность, надежность, простотуразработки программного обеспечения.

     Резюме1

     Создание программного обеспечения всегда включает в себя существенныезадачи - моделирование сложных концептуальных структур, составляющихабстрактный программный объект, и второстепенные задачи - созданиепредставлений этих абстрактных объектов с помощью языков программирования иотображение их в машинные языки с учетом ограничений по памяти и скорости. Впрошлом рост продуктивности программирования по большей части достигалсяблагодаря устранению искусственных преград, делавших второстепенные задачичрезмерно трудными, например, жестких аппаратных ограничений, неудобныхязыков программирования, нехватки машинного времени. Какая часть работыразработчиков программного обеспечения все еще связана со второстепенными, ане с существенными обстоятельствами? Если она занимает менее 9/10 всехзатрат, то, даже сведя все второстепенные затраты к нулю, мы не получимроста производительности на порядок величин.

     Поэтому, похоже, настало время обратиться к существенным задачампрограммирования, связанным с моделированием концептуальных структур большойсложности. Я предлагаю:

     - Использовать массовый рынок, чтобы избежать создания того, что можнокупить.

     - Использовать быстрое макетирование как часть запланированных итерацийдля установления технических требований к программному обеспечению.

     - Органично наращивать программы, добавляя к системам все большуюфункциональность по мере их запуска, использования и тестирования.

     - Выявлять и растить выдающихся разработчиков концепций новогопоколения.

     Введение

     Из всех монстров, которыми наполнены кошмары нашего фольклора, самымистрашными являются оборотни, поскольку нас пугает неожиданное превращениетого, что нам хорошо знакомо, в нечто ужасное. Мы ищем серебряные пули,которые могли бы волшебным образом уложить оборотней наповал.

     Хорошо знакомый программный проект напоминает таких оборотней (покрайней мере, в представлении менеджеров, не являющихся техническимиспециалистами) тем, что, будучи простым и невинным на вид, он может статьчудищем проваленных графиков работы, раздувшихся бюджетов и неработающихпродуктов.

     И мы слышим отчаянные крики с просьбами дать серебряную пулю - нечто,способное снизить стоимость программных продуктов так же резко, какснизилась стоимость компьютеров.

     Но, вглядываясь в предстоящее десятилетие, мы не видим никакойсеребряной пули. Нет ни одного открытия ни в технологии, ни в методахуправления, одно только использования которых обещало бы хоть на порядоквеличин повысить производительность, надежность, простоту. В этой главе мыпопытаемся увидеть, почему это так, исследуя природу задач программированияи свойства предлагаемых пуль.

     Однако скептицизм - это не пессимизм. Хотя мы не видим ошеломляющихпрорывов и действительно считаем их несвойственными природепрограммирования, происходит много вселяющих надежды нововведений.Дисциплинированные и последовательные усилия, направленные на их развитие,распространение и использование, действительно могут дать рост на порядоквеличин. Нет царского пути, но все же путь есть.

     Первым шагом к лечению болезней стала замена представлений о демонах и"соках" в организме теорией бактерий. Сам этот шаг, обещавший надежду,опроверг все мечты о чудесном исцелении. Он подсказал исследователям, чтопрогресс будет осуществляться шажками, с большим трудом, и что постоянное инеослабное внимание нужно уделять санитарии. То же происходит сегодня спрограммной инженерией.

     Неизбежны ли трудности? Трудности, вытекающие из сущности

     Серебряных пуль не только не видно в настоящее время, но в силу самойприроды программного обеспечения маловероятно, что они вообще будут найдены- не будет изобретений, способных повлиять на продуктивность создания,надежность и простоту программного обеспечения так, как электроника,транзисторы и интегральные схемы - на аппаратное обеспечение компьютеров. Неследует ожидать, что когда-либо в будущем каждые два года будет происходитьдвукратный рост.

     Во-первых, следует считать необычным не то, что так медленно происходитпрогресс в программировании, а то, что он так быстро идет в аппаратномобеспечении компьютеров. Ни одна другая технология за всю историюцивилизации не имела за 30 лет своего развития роста соотношенияпроизводительность/цена на шесть порядков. Ни одна другая технология непозволяет выбрать, какой выигрыш предпочесть: улучшить техническиехарактеристики или снизить затраты. Оба эти выигрыша стали возможныблагодаря переходу производства компьютеров из сборочного производства вобрабатывающее.

     Во-вторых, чтобы посмотреть, какой скорости развития можно ожидать отпрограммных технологий, полезно изучить имеющиеся в них трудности. СледуяАристотелю, я делю их на сущности - трудности, внутренне присущие природепрограммного обеспечения, и акциденции - трудности, которые сегоднясопутствуют производству программного обеспечения, но не являются внутреннеему присущими.

     Акциденции я рассматриваю в следующем параграфе. Сначала рассмотримсущность.

     Сущностью программного объекта является конструкция, состоящая изсцепленных вместе концепций: наборов данных, взаимосвязей между элементамиданных, алгоритмов и вызовов функций. Эта сущность является абстрактной втом отношении, что концептуальная конструкция остается одной и той же приразличных представлениях. Тем не менее она обладает высокой точностью ибольшим числом деталей.

     Я считаю, что сложность создания программного обеспечения заключается взадании технических требований, проектировании и проверке этойконцептуальной конструкции, а не в затратах, связанных с ее представлением ипроверкой точности представления. Конечно, мы делаем синтаксические ошибки,но в большинстве систем они несущественны в сравнении с концептуальнымиошибками.

     Верно то, что создание программных систем всегда будет трудным.Серебряной пули нет по самой природе вещей.

     Рассмотрим неотъемлемые свойства этой несократимой сущности современныхпрограммных систем: сложность, согласованность, изменяемость и незримость.

     Сложность. Сложность программных объектов более зависит от их размеров,чем, возможно, для любых других создаваемых человеком конструкций, посколькуникакие две их части не схожи между собой (по крайней мере, выше уровняоператоров). Если они схожи, то мы объединяем их в одну подпрограмму,открытую или закрытую. В этом отношении программные системы имеют глубокоеотличие от компьютеров, домов и автомобилей, где повторяющиеся элементыимеются в изобилии.

     Сами цифровые компьютеры сложнее, чем большинство изготавливаемыхлюдьми вещей. Число их состояний очень велико, поэтому их трудно понимать,описывать и тестировать. У программных систем число возможных состояний напорядки величин превышает число состояний компьютеров.

     Аналогично, масштабирование программного объекта - это не простоувеличение в размере тех же самых элементов, это обязательно увеличениечисла различных элементов. В большинстве случаев эти элементывзаимодействуют между собой неким нелинейным образом, и сложность целогорастет значительно быстрее, чем линейно.

     Сложность программ является существенным, а не второстепеннымсвойством. Поэтому описания программных объектов, абстрагирующиеся от ихсложности, часто абстрагируются от их сущности. Математика и физическиенауки за три столетия достигли больших успехов, создавая упрощенные моделисложных физических явлений, получая из этих моделей свойства и проверяя ихопытным путем. Это удавалось благодаря тому, что сложности, игнорировавшиесяв моделях, не были существенными свойствами явлений. И это не действует,когда сложности являются сущностью.

     Многие классические трудности разработки программного обеспеченияпроистекают их этой сложности сущности и ее нелинейного роста при увеличенииразмера. Сложность служит причиной трудности процесса общения междуучастниками бригады разработчиков, что ведет к ошибкам в продукте,превышению стоимости разработки, затягиванию выполнения графиков работ.Сложность служит причиной трудности перечисления, а тем более понимания,всех возможных состояний программы, а отсюда возникает ее ненадежность.Сложность функций служит причиной трудностей при их вызове, из-за чегопрограммами трудно пользоваться. Сложность структуры служит причинойтрудностей при развитии программ и добавлении новых функций так, чтобы невозникали побочные эффекты. Сложность структуры служит источникомневизуализуемых состояний, в которых нарушается система защиты.

     Сложность служит причиной не только технических, но и административныхпроблем. Из-за сложности трудно осуществлять надзор, а в результате страдаетконцептуальная целостность. Трудно найти и держать под контролем всесвободные концы. Обучение и понимание становится колоссальной нагрузкой,из-за чего текучесть рабочей силы превращается в катастрофу.

     Согласованность. Люди, связанные с программированием, не одиноки впроблемах сложности. Физика имеет дело с объектами чрезвычайной сложностидаже на уровне элементарных частиц. Однако физик работает в твердойуверенности, что можно найти общие принципы, будь то кварки или общая теорияполя. Эйнштейн неоднократно утверждал, что природа должна иметь простыеобъяснения, поскольку Богу не свойственны капризность и произвол.

     У разработчика программного обеспечения нет такой утешительной веры.Сложность, с которой он должен совладать, по большей части являетсяпроизвольной, необоснованно вызванной многочисленными человеческимиустановлениями и системами, которым должны удовлетворить его интерфейсы.Системы различаются интерфейсами и меняются во времени не в силунеобходимости, а лишь потому, что были созданы не Богом, а разными людьми.

     Во многих случаях программное обеспечение должно согласовываться,поскольку только что появилось на сцене. В других случаях оно должносогласовываться, поскольку есть ощущение, что его легче всего согласовать.Но во всех случаях значительная часть сложности происходит от согласования сдругими интерфейсами, и это невозможно упростить только в результатеперепроектирования программного обеспечения.

     Изменяемость. Программные объекты постоянно подвержены изменениям.Конечно, это относится и к зданиям, автомобилям, компьютерам. Нопроизведенные вещи редко подвергаются изменениям после изготовления. Ихзаменяют новые модели, или существенные изменения включают в более поздниесерийные экземпляры того же базового проекта. Отзывы у потребителейавтомобилей на практике встречаются весьма редко, а изменения работающихкомпьютеров еще реже. То и другое случается значительно реже, чеммодификация работающего программного обеспечения.

     Отчасти это происходит потому, что программное обеспечение в системевоплощает ее назначение, а назначение более всего ощущает влияние изменений.Отчасти это происходит потому, что программное обеспечение легче изменить:это чистая мысль, бесконечно податливая. Здания тоже перестраиваются, нопризнаваемая всеми высокая стоимость изменений умеряет капризы новаторов.

     Все удачные программные продукты подвергаются изменениям. При этомдействуют два процесса. Во-первых, как только обнаруживается пользапрограммного продукта, начинаются попытки применения его на грани или запределами первоначальной области. Требование расширения функций исходит, восновном, от пользователей, которые удовлетворены основным назначением иизобретают для него новые применения.

     Во-вторых, удачный программный продукт живет дольше обычного срокасуществования машины, для которой он первоначально был создан. Приходят еслине новые компьютеры, то новые диски, новые мониторы, новые принтеры, ипрограмма должна быть согласована с возможностями новых машин.

     Короче, программный продукт встроен в культурную матрицу приложений,пользователей, законов и машин. Все они непрерывно меняются, и их изменениянеизбежно требуют изменения программного продукта.

     Незримость. Программный продукт невидим и невизуализуем. Геометрическиеабстракции являются мощным инструментом. План здания помогает архитектору изаказчику оценить пространство, возможности перемещения, виды. Становятсяочевидными противоречия, можно заметить упущения. Масштабные чертежимеханических деталей и объемные модели молекул, будучи абстракциями, служаттой же цели. Геометрическая реальность схватывается в геометрическойабстракции.

     Реальность программного обеспечения не встраивается естественнымобразом в пространство. Поэтому у него нет готового геометрическогопредставления подобно тому, как местность представляется картой, кремниевыемикросхемы - диаграммами, компьютеры - схемами соединений. Как только мыпытаемся графически представить структуру программы, мы обнаруживаем, чтотребуется не один, а несколько неориентированных графов, наложенных один надругой. Несколько графов могут представлять управляющие потоки, потокиданных, схемы зависимостей, временных последовательностей, соотношенийпространства имен. Обычно они даже не являются плоскими, не то чтоиерархическими. На практике одним из способов установления концептуальногоконтроля над такой структурой является обрезание связей до тех пор, покаодин или несколько графов не станут иерархическими.2

     Несмотря на прогресс, достигнутый в ограничении и упрощении структурпрограммного обеспечения, они остаются невизуализуемыми по своей природе,тем самым лишая нас одного из наиболее мощных инструментов оперированияконцепциями. Этот недостаток не только затрудняет индивидуальный процесспроектирования, но и серьезно затрудняет общение между разработчиками.

     Прежние прорывы разрешили второстепенные трудности

     Если рассмотреть три наиболее плодотворных шага в произошедшемразвитии программных технологий, то обнаружится, что все они были сделаны внаправлении решения различных крупных проблем разработки программ, но этипроблемы затрагивали второстепенные, а не относящиеся к сущности трудности.Можно также видеть естественные пределы экстраполирования каждого их этихнаправлений.

     Языки высокого уровня. Конечно, наибольшее значение для ростапроизводительности, надежности и простоты имело все более широкоеиспользование языков высокого уровня. Большинство исследователей считает,что этим был достигнут, по крайней мере, пятикратный рост производительностипри одновременном выигрыше в надежности, простоте и легкости понимания.

     Что делает язык высокого уровня? Он освобождает программу отзначительной доли необязательной сложности. Абстрактная программа состоит изконцептуальных конструкций: операций, типов данных, последовательностей исвязи. Конкретная машинная программа связана с битами, регистрами,условиями, переходами, каналами, дисками и прочим. В той мере, в какой вязыке высокого уровня воплощены необходимые абстрактной программеконструкции и избегаются конструкции низшего порядка, он ликвидирует целыйуровень сложности, совершенно не являющийся необходимым свойством программы.

     Самое большее, что может сделать язык высокого уровня, - этопредоставить все конструкции, которые по замыслу программиста содержитабстрактная программа. Конечно, уровень утонченности наших представлений оструктурах данных, типах данных и операциях неуклонно растет, но с постоянноубывающей скоростью. И языки в своем развитии все больше приближаются кизощренности нашего мышления.

     Более того, с некоторого момента дальнейшая разработка языков высокогоуровня становится обузой, осложняющей, а не упрощающей интеллектуальныезадачи пользователя, редко использующего эзотерические конструкции.

     Разделение времени. Большинство исследователей считает, что благодаряработе в режиме разделения времени произошел большой рост производительноститруда программистов и качества создаваемых программных продуктов, хотя и нетакой значительный, как вызванный использованием языков высокого уровня.

     Разделение времени помогает решить совсем другую задачу. Благодаряразделению времени обеспечивается безотлагательность, и потому возможностьиметь общее впечатление о сложности. Из-за медленной оборачиваемости припакетной обработке мы неизбежно забываем мелочи, если не самое направлениенашей мысли, в тот момент, когда мы прервались и начали компиляцию ивыполнение программы. Этот обрыв мысли дорого обходится по времени,поскольку приходится восстанавливать ее в памяти. В худшем случае, можновообще потерять представление о том, что происходит со сложной системой.

     Медленная оборачиваемость, как и сложности машинных языков, являетсявторостепенной, а не существенной трудностью процесса программирования.Предельный вклад, вносимый

     разделением времени, определяетсянепосредственно. Главное - это сократить время отклика системы. По мереприближения его к нулю, оно переходит порог скорости человеческоговосприятия, составляющей около 100 миллисекунд. Дальше никакой выгодыполучить уже нельзя.

     Объединенные среды программирования. Считается, что Unix и Interlisp,первые широко распространенные интегрированные среды программирования,повысили производительность в несколько раз. Почему?

     Они направлены на преодоление второстепенных трудностей совместногоиспользования программ путем использования общих библиотек, унифицированныхформатов файлов, каналов и фильтров. В результате концептуальные структуры,которые, в принципе, всегда могут вызывать, обмениваться данными ииспользовать друг друга, получают возможность осуществлять это практически.

     Это достижение, в свою очередь, стимулировало развитие целыхинструментальных наборов, поскольку всякий новый инструмент мог применятьсяк любым программам, используя стандартные форматы.

     Благодаря этим успехам среды программирования стали предметом многихсегодняшних исследований в программной инженерии. В следующем параграфе мырассмотрим, что от них можно ожидать, и какие им присуще ограничения.

     Надежды на серебро

     Рассмотрим теперь те технические достижения, которые чаще всеговыдвигаются кандидатами на роль серебряной пули. К каким задачам ониобращаются? Задачам, относящимся к сущности, или остаткам наших акцидентныхсложностей? Предлагают ли они революционное развитие или пошаговоепродвижение?

     Ada и другие достижения языков высокого уровня. Одним из наиболеерекламируемых достижений последнего времени является язык программированияAda - язык высокого уровня общего назначения 80-х годов. Ada действительноне только отражает эволюционное развитие концепций языков, но и воплощаетчерты, поддерживающие современные идеи проектирования и модульности.Возможно, большим достижением является не язык Ada, а философия Ada какфилософия модульности, абстрактных типов данных, иерархическогоструктурирования. Ada, пожалуй перегружен возможностями, будучи естественнымпродуктом процесса, породившего требования, положенные в основу егоразработки. Это не смертельно, поскольку подмножества рабочих словарей могутрешить проблему изучения, а прогресс электроники даст нам дешевые миллионыопераций в секунду, решающие проблему компиляции. Развитиеструктурированности программных систем - это очень хорошее применение дляденег, которые мы тратим на приобретение все больших вычислительныхмощностей. Операционные системы, громко осуждавшиеся в 60-х годах задороговизну памяти и вычислений, оказались хорошим способом применениябыстродействия и дешевой памяти, полученных в результате быстрого развитияаппаратных средств.

     Тем не менее Ada не станет той серебряной пулей, которая уложит монстранизкой производительности производства программного обеспечения. В концеконцов это всего лишь еще один язык высокого уровня, а самую большую отдачуот применения таких языков мы уже получили при первом переходе отвторостепенной сложности машин к более абстрактной формулировке пошаговыхрешений. После устранения тех акциденций остались менее существенные, ивыгоды от их устранения будет, конечно, меньше.

     Я предвижу, что через десятилетие, когда оценят эффективность Ada,будет признан значительный вклад этого языка, но не благодаря какой-либоотдельной его возможности и даже не благодаря им всем вместе взятым. Нестанут причиной успехов и новые среды программирования на Ada. Наибольшимвкладом Ada явится то, что переход на этот язык послужит причиной изученияпрограммистами современных методов проектирования программного обеспечения.

     Объектно-ориентированное программирование. Многие, изучающие искусствопрограммирования, связывают с объектно-ориентированным программированиембольше надежд, чем с любыми другими современными техническими увлечениями.3Я принадлежу к их числу. Марк Шерман (Mark Sherman) из Дартмута замечает,что следует проводить отличие между двумя разными идеями, фигурирующими подэтим названием: абстрактных типов данных и иерархических типов, называемыхтакже классами. Понятие абстрактного типа данных состоит в том, что типобъекта определяется именем, множеством допустимых значений и множествомдопустимых операций, а не организацией хранения, которая должна быть скрыта.Примерами являются пакеты Ada (с защищенными типами) и модули в языкеModula.

     Иерархические типы, такие классы в Simula-67, позволяют определятьобщие интерфейсы, которые в дальнейшем можно уточнять с помощью подчиненныхтипов. Эти две концепции ортогональны: могут быть открытые иерархии искрытие без иерархий. Обе концепции действительно являются достижением вискусстве программирования.

     Каждая из них устраняет еще одну второстепенную сложность, позволяяразработчику выразить сущность своего проекта без использования большогоколичества синтаксического материала, не добавляющего нового информационногосодержания. Использование как абстрактных, так и иерархических типовустраняет второстепенные трудности более высокого порядка и позволяетвыразить проект на более высоком уровне.

     И все же такие достижения могут не более чем устранить второстепенныетрудности при выражении проекта. Существенна сложность самого проекта, начто решение таких задач никак не может повлиять. Добиться выигрыша напорядок величин с помощью объектно-ориентированного программирования можнолишь в том случае, если остающаяся сегодня в нашем языке программированиянеобязательная работа по спецификации типов сама по себе ответственна за9/10 усилий, затрачиваемых на проектирование программного продукта. В этом яне сомневаюсь.

     Искусственный интеллект. Многие ожидают, что успехи в областиискусственного интеллекта позволят осуществить революционный переворот,который принесет рост производительности разработки программного обеспеченияи его качества на порядки величин.4 Я этого не жду. Чтобы увидеть, почему,разберем, что понимается под "искусственным интеллектом", а затем посмотрим,какие возможны применения.

     Парнас внес ясность в терминологический хаос:

     Сегодня в ходу два совершенно разных определения ИИ. ИИ-1:использование компьютеров для решения задач, которые раньше могли бытьрешены только с помощью человеческого интеллекта. ИИ-2: использованиеспециальных приемов программирования, известных как эвристическое, илиоснованное на правилах, программирование. При таком подходе изучают действияэкспертов, чтобы определить, какими эвристиками и практическим правилами онипользуются при решении задач... Программа корректируется для решения задачтак, как, по-видимому, ее решает человек.

     У первого определения скользкий смысл... Кое-что укладывается сегодня вопределение ИИ-1, но как только мы видим работу программы и понимаем задачу,мы уже не думаем о ней, как о ИИ... К несчастью, я не вижу ядра методов,которые уникальны в этой области... По большей части методыпроблемно-ориентированны, и для их переноса требуются известные абстракция итворчество.5

     Я полностью согласен с этой критикой. Приемы, используемые дляраспознавания речи, выказывают мало сходства с методами распознаванияизображений, при этом в экспертных системах используются методы, отличные оттех и других. Я затрудняюсь сказать, к примеру, какое влияние распознаваниеизображений может оказать на методы программирования. То же самоесправедливо в отношении распознавания речи. При разработке программ труднорешить, что именно сказать, а не собственно сказать. Никакое облегчениевыражения не может дать больше, чем незначительные выгоды.

     Методы экспертных систем ИИ-2 заслуживают отдельного параграфа.

     Экспертные системы. Наиболее развитой и широко применяемой частьюискусственного интеллекта являются экспертные системы. Многие ученые вобласти программирования напряженно трудятся над применением этой технологиив средах разработки программного обеспечения.5 В чем состоит идея, и каковыперспективы?

     Экспертная система - это программа, содержащая обобщенный генераторвыводов и базу правил, предназначенную для приема входных данных и допущенийи исследования логических следствий через заключения, выводимые из базыправил, предоставляющая заключения и рекомендации и предлагающаяпользователю объяснение полученных результатов путем обратного прослеживаниясвоих рассуждений. Помимо чисто детерминированной логики, генератор выводовобычно может работать с нечеткими или вероятностными данными.

     Такие системы предоставляют некоторые явные преимущества передзапрограммированными алгоритмами решения тех же задач:

     - Технология генератора выводов разрабатывается независимо отприменения и используется затем во многих приложениях.

     - Изменяемые части специфических для приложения данных единообразнокодируются в базе правил. Обеспечивается инструментарий для разработки,изменения, проверки и документирования базы правил. Этим упорядочиваетсязначительная часть сложности самого приложения.

     Эдвард Фейгенбаум (Edward Feigenbaum) считает, что мощь таких системрастет не благодаря совершенствованию механизмов вывода, а скорее, благодаряпополнению базы знаний, все более точно отражающей реальный мир. Я считаю,что самое важное достижение этой технологии состоит в разделении сложностиприложения и самой программы.

     Как можно использовать экспертные системы при создании программногообеспечения? Различными способами: предложение правил интерфейсов,рекомендации по стратегии отладки, запоминание частоты ошибок каждого типа,подсказки по оптимизации и т.п.

     Представим себе, к примеру, некоего советчика по отладке. В самойзачаточной форме диагностическая экспертная система весьма напоминаетпамятку пилота, по сути, делая предположения относительно возможных причинзатруднений. По мере развития базы правил предположения становятся болееспецифичными, более изощренно учитывая симптомы проблемы. Можно представитьтакого помощника предлагающим сначала самые общие решения, но, по меревоплощения в базе правил все большей части структуры системы, становящегосявсе более разборчивым в генерируемых гипотезах и предлагаемых тестах. Такаяэкспертная система может решительно отличаться от обычных тем, что ее базаправил, вероятно, должна быть иерархически разбита на модули таким жеобразом, как соответствующий программный продукт. Поэтому при изменениимодульной структуры продукта изменяется также модульная структура базыдиагностических правил.

     Работа, которую необходимо проделать для создания диагностическихправил, в любом случае должна быть проведена при создании набора контрольныхпримеров для модулей и для системы. Если это делать достаточно общимобразом, с единообразной структурой правил и при наличии хорошего генераторавыводов, то можно действительно сократить объем работ при генерацииконтрольных примеров, а также пожизненном сопровождении и тестированиимодификаций. Такие же условия мы можем поставить и для других советчиков,используемых для других участников задачи создания программы. Возможно, онибудут многочисленны и иногда просты.

     На пути ранней реализации полезных экспертных советников дляразработчика программы стоит много препятствий. Решающей частью нашеговоображаемого сценария является разработка простых способов перехода отзадания структуры программы к автоматическому или полуавтоматическомусозданию диагностических правил. Еще более сложной и важной является двойнаязадача приобретения знаний: найти членораздельно выражающихся и способных ксамоанализу экспертов, понимающих, почему они делают то или другое действие,и разработать эффективные методы извлечения их знаний и превращения в базыправил. Чтобы построить экспертную систему, необходимо иметь эксперта.

     Наибольшим вкладом экспертных систем, несомненно, будет предоставлениенеопытному программисту опыта и всех знаний, накопленных лучшимипрограммистами. И это не мало. Разрыв между лучшими и средними приемамипрограммирования очень велик, возможно, он больше, чем в любой другойинженерной дисциплине. Поэтому средство распространения хороших приемов былобы очень важным.

     "Автоматическое" программирование. Почти 40 лет люди ждут и пишут об"автоматическом программировании" - генерации решающей задачу программы,исходя из формулировки спецификации этой задачи. Некоторые высказываютсясегодня так, будто ожидают от этой технологии грядущего переворота.7

     Парнас предполагает, что термин используется из-за эффектности, а несемантического содержания, утверждая:

     Короче, автоматическое программирование всегда было эвфемизмом дляпрограммирования на языке более высокого уровня, чем доступный программистув данный момент.8

     Он утверждает, в сущности, что в большинстве случаев нужно задатьспецификацию не задачи, а метода решения.

     Можно отыскать исключения. Метод создания генераторов является оченьмощным и повседневно с пользой применяется в программах сортировки.Некоторые системы интегрирования дифференциальных уравнений также позволялипрямую формулировку задачи. Система производила оценку параметров, выбиралаиз библиотеки методы решения и генерировала программы.

     У этих применений есть свойства, благоприятствующие автоматизации:

     - Проблемы легко описываются сравнительно небольшим числом параметров.

     - Известно много методов решения, что обеспечивает наличие библиотекиальтернатив.

     - Тщательный анализ привел к выработке явных правил выбора методоврешения в зависимости от параметров.

     Едва ли возможно обобщение таких методов на весь мир обычныхпрограммных систем, в котором ситуация с такими приятными свойствамиявляются исключениями. Трудно даже представить себе, как такой прорыв вобобщении мог бы произойти разумным образом.

     Графическое программирование. Излюбленной темой докторских диссертацийв программной инженерии является графическое, или визуальное,программирование - применение компьютерной графики в разработке программногообеспечения.9 Иногда перспективы такого подхода основываются на аналогии спроектированием СБИС, в котором компьютеры играют такую большую роль. Иногдатакой подход обосновывается, исходя из того, что блок-схемы являютсяидеальным материалом при проектировании программ. Имеются мощные средствадля создания таких блок- схем.

     Ничего убедительного и удивительного из этих попыток пока не вышло, - ия уверен, не выйдет.

     Во-первых, как я всюду доказываю, блок-схема является весьма слабойабстракцией структуры программы.10 Лучше всего это видно из попыток Беркса,фон Неймана и Гольдстайна снабдить свой предполагаемый компьютер крайненеобходимым управляющим языком высокого уровня. В том жалком виде - многиестраницы соединенных линиями прямоугольников, - в котором сегодняразрабатываются блок-схемы, они доказали, в сущности, свою бесполезность:программисты рисуют их после, а не до создания описываемых ими программ.

     Во-вторых, сегодняшние экраны имеют слишком мало пикселов, чтобыпоказать целиком и с достаточным разрешением сколько-нибудь подробную схемупрограммы. Так называемая "метафора рабочего стола" становится метафорой"сиденья самолета". Всякий, кому приходилось листать пачку бумаг, будучистиснутым двумя корпулентными соседями, почувствует разницу: одновременноможно увидеть очень немного. Настоящий рабочий стол позволяет обозревать ипроизвольно выбирать множество бумаг. Более того, в порыве творчества неодин программист или писатель предпочитал рабочему столу более вместительныйпол. Аппаратным технологиям нужно сделать очень большой наг, чтобыпредоставляемый экранами обзор был достаточным для задач проектированияпрограмм.

     Если обратиться к основам, программное обеспечение очень трудновизуализировать, как я доказывал это выше. Составляем ли мы схемыуправляющей логики, вложенных областей, видимости переменных, перекрестныхссылок переменных, потоков данных, иерархических структур данных или чего-тоеще, они отражают лишь одно изменение взаимодействующих запутанным образомчастей программной системы. Если наложить одна на другую эти схемы,отражающие взгляд с различных точек зрения, трудно извлечь из этогокакую-либо общую точку зрения. Аналогия с интегральными схемами вводит, всущности, в заблуждение: конструкция микросхемы представляет собоймногослойный двумерный объект, геометрия которого отражает сущность.Программная система не является таким объектом.

     Верификация программ. Много труда в современном программированиитратится на отладку и исправление ошибок. Может быть, мы найдем серебрянуюпулю, устранив все ошибки в самом начале, на этапе системногопроектирования? Можно ли радикально повысить производительность и надежностьпродукта, если следовать совершенно иной стратегии - обеспечить корректностьпроекта, прежде чем тратить огромные усилия на его реализацию итестирование?

     Не думаю, что мы обнаружим здесь чудеса. Верификация программ являетсяочень мощной концепцией, и она очень важна для таких вещей, как созданиенадежного ядра операционной системы. Эта технология не обещает, однако,экономии труда. Верификация требует столько работы, что весьма немногиезначительные программы вообще были верифицированы.

     Верификация программ не означает создания программ, лишенных ошибок. Издесь нет чудес. Математические доказательства тоже могут быть ошибочными.Поэтому хотя верификация может облегчить тестирование, она не может отменитьего.

     Более существенно, что даже самая совершенная верификация программыможет лишь определить, что программа отвечает своим спецификациям. Самаясложная задача программирования - получить полную и непротиворечивуюспецификацию, и сущность создания программы на практике во многом состоит вотладке спецификации.

     Среды программирования и инструменты. Какого еще выигрыша можно ожидатьот стремительно расширяющихся исследований по усовершенствованию средпрограммирования? Инстинктивно кажется, что задачи, которые сулилинаибольшую отдачу, были в числе первых, за которые взялись, и их уже решили:иерархические файловые системы, единообразные форматы файлов для полученияединообразных программных интерфейсов и обобщенных инструментов.Ориентированные на конкретные языки интеллектуальные редакторы пока не оченьраспространены, но большее, на что они способны, это устранениесинтаксических ошибок и мелких семантических.

     Возможно, наибольший выигрыш среда программирования сможет дать прииспользовании строенных систем баз данных для отслеживания мириадов деталей,которые каждый программист должен точно вспоминать, и которые должныхраниться в текущем состоянии в группе работающих над одной системой.

     Несомненно, что это работа заслуживает внимания и принесет некоторыеплоды как для производительности, так и для надежности. Но ввиду самой еесути отдача должна быть незначительной.

     Рабочие станции. Какой выигрыш может получить искусствопрограммирования от несомненного и быстрого роста мощности и объема памятиотдельной рабочей станции? Сколько миллионов операций в секунду можноплодотворно использовать? Составление и редактирование программ вполнеобеспечиваются сегодняшними скоростями. Компиляция может быть ускорена, нодесятикратное увеличение скорости машины, вне сомнения, сделает обдумываниеосновным занятием программиста в течение рабочего дня. Пожалуй, это так ужесейчас.

     Конечно, мы приветствуем увеличение мощности рабочих станций. Норассчитывать на связанные с этим чудеса мы не можем.

     Перспективные подходы к концептуальной сущности

     Хотя никакой прорыв в технологии не обещает таких волшебныхрезультатов, какие мы видим в аппаратной части компьютеров, в настоящеевремя делается много полезного, и есть надежды на неуклонный, хотя инеброский прогресс.

     Все технологические подходы к акциденциям процесса программированияпринципиально ограничены уравнением продуктивности:

     

     Если, как я полагаю, концептуальные составляющие задачи сейчас отнимаютбольшую часть времени, то никакая работа над составными частями задачи,являющимися просто выражением концепций, не даст большого выигрыша.

     Поэтому мы должны рассмотреть те направления, которые затрагивают самусущность проблемы программирования - формулировку этих сложныхконцептуальных структур. К счастью, некоторые из этих направлений весьмамногообещающи.

     Покупать, а не создавать. Наиболее радикальное возможное решение присоздании программ - вообще не создавать их.

     С каждым днем это становится все легче, поскольку все большее числопоставщиков предлагает все более многочисленные и лучшие программныепродукты для немыслимого разнообразия приложений. Пока мы,инженеры-программисты, трудились над совершенствованием методологиипроизводства, революция, произведенная персональными компьютерами, создалане один, а много массовых рынков программного обеспечения. В каждом газетномкиоске выставлены ежемесячные журналы, в которых, отсортированные по типаммашин, рекламируются и рецензируются десятки продуктов по ценам отнескольких долларов до нескольких сотен долларов. Более специализированныеиздания предлагают очень мощные продукты для рабочих станций и других рынковUnix. Даже инструменты и среды программирования могут быть куплены вкоробочном виде. Я где-то предложил базар для отдельных модулей.

     Любой такой продукт дешевле купить, чем создавать заново. Даже при цене100 000 долларов купленный продукт стоит примерно столько, сколько годовоесодержание программиста. И поставка немедленная! Немедленная, по крайнеймере, для реально существующих продуктов, проспект которых разработчик можетпослать счастливому пользователю. Более того, такие продукты обычно гораздолучше документированы и несколько лучше сопровождаются, чем доморощенныепрограммы.

     Развитие массового рынка является, по моему мнению, наиболее глубокойдолгосрочной тенденцией программной инженерии. Стоимость программногопродукта всегда определялась стоимостью разработки, а не тиражирования.Разделив эту стоимость даже на нескольких пользователей, мы коренным образомснижаем цену на одного пользователя. Взглянув на это с другой стороны, мывидим, что использование n копий программной системы фактически умножает наn производительность его разработчиков. Это рост производительности отраслии всей страны.

     Главным вопросом, конечно, является производительность. Смогу ли яиспользовать имеющийся коробочный продукт для решения своих задач? Здесьслучилась удивительная вещь. В 50-х и 60-х годах одно исследование за другимпоказывало, что пользователи не хотят использовать коробочные пакеты длярасчета зарплаты, управления складом, учета дебиторов по расчетам и т.д.Требования были слишком специальными, отклонения от случая к случаю слишкомбольшими. В 80-х годах мы обнаруживаем большой спрос на такие пакеты иширокое их использование. Что изменилось?

     Только не пакеты. Они стали несколько более общими и лучшенастраиваются, чем раньше, но не намного. И не область их применения. Вконце концов, сегодня потребности бизнеса и науки более разнообразны исложны, чем 20 лет назад.

     Резко изменилось соотношение стоимости компьютеров и программ. Тот, ктов 1960 году покупал машину за 2 миллиона долларов, считал, что можетпозволить себе потратить еще 250 000 долларов на заказную программу расчетазарплаты, которая легко и без ущерба вписалась бы во враждебную компьютерамсоциальную среду. Те, кто сегодня покупают машину для офиса за 50 000долларов, не могут, понятно, позволить себе заказные программы расчетазарплаты, поэтому они приспосабливают свои процедуры расчета зарплаты кимеющимся пакетам. Компьютеры сейчас столь обычны, если не столь любимы, чтоадаптация воспринимается как обычное дело.

     Есть яркие исключения из моего утверждения о том, что обобщенностьпрограммных пакетов за последние годы мало изменилась: электронные таблицы ипростые системы баз данных. Эти мощные инструменты, столь очевидные заднимумом и так поздно появившиеся, имеют бесчисленное множество применений, втом числе, весьма необычные. Есть масса статей и даже книг о том, как спомощью электронной таблицы решать неожиданные задачи. Большое число задач,для которых раньше были бы написаны заказные программы на Cobol или ReportProgram Generator, теперь шаблонно решается с помощью этих инструментов.

     Многие пользователи изо дня в день применяют свои компьютеры для разныхприложений, никогда не написав ни одной программы. На практике многие изэтих пользователей и не могут писать для своих машин новые программы, но темне менее приверженцы решению возникающих задач с их помощью.

     Я считаю, что сегодня для многих организаций самая правильная политикадля повышения производительности разработки программного обеспечения - этоустановить своим не имеющим компьютерных знаний работникам умственного трудакомпьютеры и хорошие общие программы для обработки текстов, рисования,работы с файлами и электронными таблицами и отпустить их в вольное плавание.Такая же политика в отношении распространенных математических истатистических пакетов, а также некоторых навыков программирования подойдетсотням ученых, работающих в лабораториях.

     Уточнение требований и быстрое макетирование. Самая трудная отдельнаязадача в разработке программной системы - это точно решить, чторазрабатывать. Ни одна другая задача работы над концепциями не являетсястоль трудной, как разработка подробных технических требований, включая всеинтерфейсы пользователей, машинные интерфейсы и интерфейсы к другимпрограммным системам. Ни одна другая часть работы не наносит такого ущербаготовой системе, если сделана неправильно. Ни одна другая часть неисправляется позднее с бoльшим трудом.

     Поэтому наиболее важной функцией, осуществляемой разработчиками длясвоих клиентов, является повторяющееся получение и уточнение требований кпродукту. Правда заключается в том, что клиенты не знают, чего хотят. Обычноони не знают, на какие вопросы нужно дать ответ, и почти никогда незадумывались над задачей настолько детально, как это нужно указать вспецификации. Даже простой ответ - "сделайте так, чтобы новая программнаясистема работала так, как наша старая ручная система обработки информации" -оказывается в действительности слишком упрощенным. Клиенты никогда не хотятэтого в точности. Более того, сложные программные системы действуют,движутся, работают. Динамику этого действия трудно себе представить. Поэтомупри планировании любых действий необходимо оставить резерв для многократноговзаимодействия между клиентом и проектировщиком при описании системы.

     Я пойду дальше и стану утверждать, что на практике клиенты, даже вместес инженерами-программистами, не в состоянии указать полно, строго икорректно точные требования к современному программному продукту, прежде чембудут созданы и опробованы какие-либо версии продукта, спецификации ккоторому они составляют.

     Поэтому одним из наиболее многообещающих современных направлений втехнологии, причем обращенных к сущности, а не к акциденциям проблемпрограммирования, является разработка подходов и инструментов для быстрогосоздания макетов систем как части итеративного процесса разработкиспецификаций.

     Макет программной системы моделирует главные интерфейсы и выполняетосновные функции предполагаемой системы, при этом не обязательно будучисвязан теми же ограничениями быстродействия компьютера, размера илистоимости. Обычно макеты выполняют основные задачи системы, но не пытаютсяобрабатывать исключительные ситуации, правильно реагировать на вводнедопустимых данных, корректно прерывать работу и т.д. Назначение макета -показать, как воплощается выбранная концептуальная структура, чтобы клиентмог проверить ее пригодность к использованию и непротиворечивость.

     Сегодня многие процедуры приобретения программного обеспеченияосновываются на предположении, что можно заранее задать техническиетребования для желаемой системы, рассмотреть предложения разработчиков,получить разработанную систему и установить ее. Я думаю, что такоепредположение в корне неверно, и из-за этой ошибки проистекают многиепроблемы при приобретении программ, поскольку эти проблемы нельзя устранитьбез пересмотра основ, для которого требуется интерактивная разработка испецификации макетов и продуктов.

     Пошаговая обработка: наращивать программу, а не строить сразу. Я до сихпор помню испытанный в 1958 году удар, когда впервые услышал, как мой другговорил о строительстве (building) программ в противоположность написанию(writing). В мгновение он расширил все мое представление о процессепрограммирования. Применение метафоры было сильным и точным. Сегодня мыпонимаем, что сходство существует между созданием программы и другимистроительными процессами, и свободно используем другие элементы метафоры,такие как спецификации (specifications), сборка компонентов (assembly ofcomponents), леса (scaffolding).

     Метафора строительства пережила свое время. Пора снова вноситьизменения. Если, как я считаю, создаваемые сегодня концептуальные структурыслишком сложны, чтобы их можно было точно специфицировать заранее, и слишкомсложны, чтобы строить без ошибок, тогда нужен радикально иной подход.

     Обратимся к природе и рассмотрим сложность живых созданий, а небезжизненных творений человека. Там мы обнаруживаем конструкции, сложностькоторых вселяет в нас ужас. Один только мозг настолько сложен, чтоневозможно составить его схему. Его мощь невозможно повторить, он богатсвоеобразием, способен к самосохранению и самообновлению. Секрет в том, чтомозг растет, а не строится.

     Так же должны создаваться наши программные системы. Несколько лет назадХарлан Миллз предложил наращивать программные системы путем пошаговойразработки.11 Это значит, что сначала систему надо заставить выполняться,даже если при этом она не делает ничего полезного, кроме вызова некоторогочисла фиктивных подпрограмм. Затем она понемногу обрастает мясом, причемподпрограммы, в свою очередь, разрабатываются сначала как вызовы пустыхфиктивных подпрограмм, находящихся на уровень ниже.

     Настаивая на применении этой технологии разработчиками проектов на моихлабораторных занятиях по программной инженерии, я стал свидетелемпоразительных результатов. За последнее десятилетие ничто другое не оказалостоль сильного влияния на мою собственную работу и ее эффективность. Этотподход предполагает нисходящее проектирование, поскольку это - нисходящеенаращивание программы. Он позволяет легко отслеживать работу в обратномнаправлении. Он предоставляет возможность раннего создания макетов. Каждаяновая функция или возможность работы с более сложными данными или условиямиорганически вырастают на того, что уже имеется.

     Воздействие на моральный дух ошеломительное. Когда есть хотя бы простаяработающая система, возрастает энтузиазм. Энергия удваивается, когда наэкране появляется картинка из новой графической программной системы, дажеесли это всего лишь прямоугольник. И на каждой стадии процесса разработкисуществует работающая система. Я считаю, что за одинаковые сроки командаможет нарастить значительно более сложный объект, чем построить.

     В больших проектах можно ощутить такие же выгоды, как и в моихмаленьких.12

     Выдающиеся проектировщики. Главная проблема совершенствования искусствапрограммирования заключена, как всегда, в людях.

     Мы можем добиваться хороших проектов, следуя хорошим, а не плохимпрактическим приемам. Хорошим приемам можно обучать. Программистыпринадлежат к наиболее интеллектуальной части общества, следовательно, они всостоянии изучать хорошие приемы. Поэтому важнейшим направлением вСоединенных Штатах является распространение хороших современных приемов.Новые курсы, новые издания, новые организации, такие как Институт инженеров-программистов (Software Engineering Institute) - все это вызвано к жизнистремлением повысить уровень наших практических приемов. Это совершенноправильно.

     Тем не менее, я считаю, что мы не сможем подняться еще на однуступеньку выше, действуя в этом направлении. Выбор правильного методапроектирования определяет различия между плохим и хорошим концептуальнымпроектом, но не между хорошим и выдающимся. Выдающиеся проекты создаютсявыдающимися проектировщиками. Создание программ является творческимпроцессом. Крепкая методология может придать силу и освободить творческийум, но она не может воспламенить или вдохновить того, кто занят нуднойработой.

     И разница немалая - это как Сальери и Моцарт. Одно исследование задругим показывают, что лучшие проектировщики создают структуры, которыебыстрее, меньше по размеру, проще, понятнее и разработаны меньшими усилиями.Различия между выдающимся и средним достигают порядка величины.

     Нетрудно проследить, что ряд хороших и полезных программных системпроектировался комиссиями и создавался с помощью проектов, состоявших измногих частей. Но программные системы, вызвавшие восхищение страстныхпоклонников, являются продуктом одного или небольшого числа выдающихсяпроектировщиков. Посмотрите на Unix, APL, Pascal, интерфейс Smalltalk и дажеFortran - с одной стороны, и Cobol, PL/I, Algol, MVS/370 и MS-DOS - с другой.

     Поэтому, высоко ценя нынешние программы передачи технологий и развитияобучения, я считаю, что наиболее важной программой, которую мы можемпредпринять, является развитие способов воспитания выдающихсяпроектировщиков.

     Ни одна занятая в программировании организация не может игнорироватьэту проблему. Хороших менеджеров, как бы мало их ни было, не меньше, чемхороших проектировщиков. Как выдающиеся проектировщики, так и выдающиесяменеджеры встречаются редко. В большинстве организаций значительные усилиятратятся на поиска и выращивание подающих надежды менеджеров. Я не слышал,чтобы кто- либо тратил такие же усилия на поиски и развитие выдающихсяпроектировщиков, от которых, в конечном счете, зависит техническоепревосходство продуктов.

     Первое мое предложение состоит в том, чтобы каждая занятая впрограммировании организация определила для себя и провозгласила, чтовыдающиеся проектировщики имеют для ее успеха такое же большое значение, каки выдающиеся менеджеры, и что они могут рассчитывать на такие же заботу ивознаграждение. Не только зарплата, но и атрибуты положения - размеры офиса,мебель, техническое оборудование, командировочные фонды, обеспеченностьсотрудниками - должны быть полностью равнозначны.

     Как растить выдающихся проектировщиков? Место не позволяет обсуждатьэто пространно, но вот некоторые очевидные шаги:

     - Систематически и как можно раньше выявлять первоклассныхпроектировщиков. Лучшие - не всегда самые опытные.

     - Назначить наставника, ответственного за рост перспективногопроектировщика и тщательно следить за его карьерой.

     - Разработать и осуществлять план служебного роста для каждогоперспективного проектировщика, включающий тщательно продуманное обучение упередовых проектировщиков, периоды дополнительного формального обучения,краткосрочные курсы, перемежающиеся с самостоятельным проектированием иназначением на руководящие технические должности.

     - Обеспечить возможности для взаимодействия и взаимного стимулированиярастущих проектировщиков.