В.Ш. Кауфман - Языки программирования - концепции и принципы (1990) (1160787), страница 4
Текст из файла (страница 4)
услуг), состоит в том, что самое сложное (и дорогое) в этом деле - не сами
компьютеры, а именно представление знаний в приемлемой для них форме. В наше
время аппаратура в компьютере по своей относительной стоимости иногда
сравнима с упаковкой, в которую "заворачивают" знания.
Знания, представленные в компьютерах, традиционно называют программами
(таким образом, под программой в широком смысле слова понимают не только
планы). Соотношение стоимости аппаратуры и программ (а также иные
соображения) во многих случаях дает основание абстрагироваться от
используемой аппаратуры и говорить об услугах, предоставляемых
непосредственно программами, а также о производстве программных услуг.
Подчеркнем, что пока далеко до полной независимости программ от
используемой аппаратуры. Проблема переноса программ (на исполнитель другого
типа) - одна из острейших проблем современного программирования. И тем не
менее обычно затраты на создание достаточно сложной программы определяются в
основном сущностью решаемой задачи (предоставляемой услуги), а не
используемой аппаратуры.
Правомерность абстракции от аппаратуры подчеркивает определенную
искусственность проблемы переноса программ. Если пока в значительной степени
безразлично, на чем программировать, то разнообразие и несовместимость
исполнителей вызваны не объективными, а социальными причинами.
Знания, представляемые в компьютерах, можно разделить на пассивные и
активные. Первые отражают факты, связи и соотношения, касающиеся
определенного вида услуг. Вторые - это рецепты, планы действий, процедуры,
непосредственно управляющие исполнителем.
Представление пассивного знания ориентировано в первую очередь на такой
ресурс компьютера, как память, а представление активного - на процессор.
Исторически самыми первыми сферами применения компьютеров оказались такие,
где главенствовало активное знание - эксплуатировалась не столько
способность ЭВМ много знать, сколько быстро считать.
Кстати, и память на первых ЭВМ была очень мала по сравнению со
скоростью работы процессора. Всю свою память они могли просмотреть (или
переписать) за десятую долю секунды. Недалеко ушли в этом отношении и
современные компьютеры (если говорить об оперативной памяти).
Соотношение между объемом оперативной памяти и скоростью процессоров
активно влияет на мышление программистов, инженеров, пользователей, а также
всех связанных с компьютерами людей. Изменение этого соотношения (а его
разумно ожидать) способно произвести революцию в практическом
программировании (см. далее о модифицированной модели Маркова и
функциональном стиле программирования (модель Бэкуса); есть и другие
перспективные модели, например, реляционная). Пока же программисты вовсю
экономят память, помещая новые значения на место старых, а преподаватели
учат искусству такого "эффективного" программирования. В "эффективных"
программах трудно восстановить процесс получения результата, трудно
объяснить неожиданный результат. Традиционный стиль программирования,
обусловленный бедностью ресурсов, затрудняет написание, понимание, проверку
и удостоверение правильности программ. Тенденция развития состоит в том, что
роли активного и пассивного знания в производстве программных услуг
становятся более симметричными, а забота об эффективности отступает перед
заботой о дружественности программы.
1.11. Производство программных услуг - основная цель программирования
Измерять эффективность того или иного производства разумно лишь по
отношению к его цели (конечному результату). Поэтому важно понимать, что
конечная цель программирования - не создание программ самих по себе, а
предоставление программных услуг. Другими словами, программирование в
конечном итоге нацелено на обслуживание пользователей. А настоящее
обслуживание должно руководствоваться известным принципом: "Клиент всегда
прав". В применении к программированию этот принцип означает, что программы
должны быть "дружественными" по отношению к пользователю. В частности, они
должны быть надежными, робастными и "заботливыми".
Первое означает, что в программе должно быть мало ошибок, второе - что
она должна сохранять работоспособность в неблагоприятных условиях
эксплуатации, третье - что она должна уметь объяснять свои действия, а также
ошибки пользователя.
Что значит "мало ошибок", зависит от назначения программы (ясно, что
программа обучения русскому языку и программа автопилота могут иметь
различную надежность). Под "неблагоприятными условиями" понимается
ограниченность выделяемых программе ресурсов (память, каналы ввода-вывода,
число процессоров), перегрузка (много пользователей, большие объемы данных),
ошибки пользователей, сбои и отказы аппаратуры, попытки намеренно вывести
программу из строя и т.п.
Сказанное относится к работе программы. Однако важно понимать, что
программная услуга - это не только услуга, оказываемая пользователю
непосредственно при работе компьютера под управлением программы, но и
проверка, оценка, продажа, подбор программ, их перенос на другой
исполнитель, сопровождение и аттестация (авторитетное подтверждение
качества) программ и т.п.
Когда производство программных услуг достигает некоторой степени
зрелости, из кустарного производства вырастает индустрия программных услуг и
обслуживающая ее потребности теория программирования. Как индустрия, так и
кустарное производство пользуются при этом той или иной технологией -
технологией производства программных услуг, т.е. технологией
программирования.
(О связи науки, искусства, теории и технологии в программировании см.
замечательную Тьюринговскую лекцию Дональда Кнута в Communication of the
ACM.- 1974.- V.12.- C.667-673).
1.12. Сложность как основная проблема программирования.
Итак, основная цель программирования - производство программных услуг.
Известно, что этот род человеческой деятельности в развитых странах уверенно
выходит на первое место среди всех других производств (скажем, в США
соответствующая отрасль хозяйства уже опередила недавних лидеров - нефтяную
и автомобильную отрасли). Вместе с тем известно, что создание программ и
предоставление других связанных с ними услуг остается слишком дорогим и
относительно длительным делом, в котором трудно гарантировать
высококачественный конечный результат. В чем же основная причина такого
положения? Связана ли она с самой природой программирования или носит
субъективный характер? В настоящее время краткий ответ можно сформулировать
так: "сложность - основная проблема программирования; связана с самой его
природой; можно надеяться на ее понижение для освоенных классов задач".
1.13. Источники сложности.
Попытаемся подробнее разобраться с тем, почему же сложность объектов, с
которыми приходится иметь дело - отличительная черта программирования
компьютеров. Найдя источники сложности, можно с большей надеждой на успех
искать пути ее преодоления.
Когда исполнители работают медленно, а действия, которые считаются
элементарными, специфичны для вида предоставляемых услуг, то планирование
деятельности исполнителя и критерии качества такого планирования существенно
зависят и от услуги, и от конкретного набора элементарных действий.
Вряд ли стоит поручать, скажем, заводскому технологу, специалисту по
обработке металлов резанием, планирование индивидуального пошива верхней
одежды. Для этого есть закройщики, которые, в свою очередь, вряд ли смогут
применить свое искусство при создании заводских технологических карт.
Другими словами, набор "элементарных" действий двух рассмотренных категорий
исполнителей считать эквивалентными неестественно.
Компьютеры работают быстро и наборы их команд в известном смысле
эквивалентны. Причем уже в течение многих лет сохраняется тенденция к
увеличению скорости и объема памяти при фиксированной цене (примерно на
порядок за десятилетие). В таких условиях возникает принципиальная
возможность настроить исполнитель на предоставление услуг из очень широкого
класса (во всяком случае, границы этого класса неизвестны). Для этого
достаточно снабдить исполнитель подходящим планом (написать программу).
Эта принципиальная возможность соблазняет настраивать компьютеры на
виды услуг, очень далеких от элементарных возможностей исполнителя. Более
того - таковы почти все практически значимые услуги. Поэтому в общем случае
план должен предусматривать огромное количество элементарных действий над
огромным количеством элементарных объектов. Но этого мало. Самое главное -
огромное количество связей между этими объектами. Поэтому и сами программы
становятся огромными (уже имеются программы из миллионов команд; например
для управления военными и космическими объектами).
Между тем способности человека работать с большим числом связанных
объектов, как хорошо известно, весьма ограничены. В качестве ориентира при
оценке этих способностей указывают обычно на так называемое "число Ингве",
равное семи (плюс-минус 2). Другими словами, человек обычно не в состоянии
уверенно работать с объектом, в котором более семи компонент с произвольными
допустимыми взаимными связями. До тех пор, пока программирование остается в
основном человеческой деятельностью, с указанным ограничением необходимо
считаться.
Таким образом, предоставив универсальность, скорость и потенциально
неограниченную память, создатели компьютеров, с одной стороны, соблазнили
человечество неслыханными возможностями, а с другой, поставили лицом к лицу
с проблемами невиданной потенциальной сложности (при попытке осуществить эти
гипотетические возможности).
В этой связи упомянем известный принцип "труд на юзера спихнуть" (user
- пользователь). Изобретатели компьютеров, предоставив в распоряжение
программистов исключительное по своим возможностям абстрактное устройство,
"спихнули" на них труд по настройке этого абстрактного устройства на
предоставление конкретных услуг. Но такая конкретизация оказалась далеко не
тривиальной. Программисты, в свою очередь, создавая "универсальные"
программы, "спихивают" труд по их применению в конкретных условиях на
потенциальных пользователей этих программ.
Итак, первый источник сложности в программировании - так называемый
семантический разрыв - разрыв между уровнем и характером элементарных
объектов и операций, с одной стороны, и потенциально возможных услуг - с
другой. Иными словами, это проблема согласования масштаба - ювелирными
инструментами предлагается сооружать города.
Именно этот источник имелся в виду, когда шла речь об объективном
характере присущей программированию сложности. Занимаясь определенным
классом услуг (задач) можно стремиться выделить характерный именно для этого
класса набор элементарных объектов и операций, построить соответствующий
исполнитель (аппаратным или программным способом) и программировать на таком
более подходящем исполнителе. Фактически это означает создать адекватный
выбранному классу услуг ЯП. На практике это самый распространенный способ
борьбы со сложностью и одновременно - основная причина роста проблемно-
ориентированных языков (ПОЯ).
Имеется еще один принципиально важный источник сложности, затрудняющий
"взаимопонимание" с компьютерами. Речь идет об отсутствии в современных
компьютерах модели реального мира, согласованной с представлениями о мире у
программистов и пользователей. Поэтому в общем случае компьютер не в
состоянии контролировать указания программиста или действия пользователя с
прагматической точки зрения (контролировать соответствие между действиями и
теми целями, ради которых эти действия совершаются - цели компьютеру
неизвестны).
Из-за этого самая "мелкая" с точки зрения создателя программы описка
может привести к совершенно непредсказуемым последствиям (широко известен
случай, когда из-за одной запятой в программе на Фортране взорвалась
космическая ракета, направлявшаяся на Венеру; пропали усилия, стоившие