Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Стили и методы программирования. Учебное пособие для СПО
.pdf
К примеру, для обратного алгоритма с пометками-рекомендациями
схема программы агента, пришедшего в город, сводится к следующему:
1. Выждать время, необходимое для перемещения из
местоположения в данный город (фактически, это означает лишь
соответствующую перестановку себя в управляющем списке,
сопровождающуюся приостановкой процесса);
2. Если данный город уже посещался (в городе имеется пометка-
рекомендация), то ликвидировать себя, т.е. завершить процесс;
3. Сделать пометку-рекомендацию в данном городе, используя
местоположение, из которого пришел агент;
4. Если данный город есть A, то построить путь, используя пометки
рекомендации, и завершить процесс;
5. Для каждой дороги, ведущей в данный город, породить процесс
нового агента, в качестве параметра которого задается данный
город. Назначить активизацию нового процесса непосредственно
после прекращения активности родительского процесса;
6. Завершить процесс.
Рис. 15.3. Управляющий список
На рис. 15.3
изображено начало последовательности состояний
Стили и методы программированияНепейвода Н.Н.
261

управляющего списка, которая получается при выполнении алгоритма с
данными, представленными на рис. 15.2
с. В верхней части рисунка
изображена модель времени: на горизонтальной оси отмечены
моменты, когда состояние агентов меняется ( - функция времени
перемещения между городами; a, b, c и d - моменты для дальнейшего
пояснения). В нижней части рисунка показана последовательность
изменений управляющего списка (его состояния выделены
прямоугольными блоками, в которых для наглядности вертикальные
стрелки обозначают связи процессов, назначенных на одно и то же
время, а горизонтальные стрелки - упорядоченность процессов по
модельному времени ).
Разбредание агентов начинается с порождения процессов A1 и A2, что
соответствует двум дорогам, ведущим в город B. Это момент модельного
времени, помеченный как a. Моменту b соответствуют четыре
состояния, сменяющие друг друга, c соответствуют три, а d - одно
состояние. Из сопоставления рисунков 15.2
a и 15.2b видно, что
никакого специального моделирования времени, а тем более задержек
не требуется: время изменяется "мгновенно", когда все события,
назначенные к более ранним срокам, отработали и в голове
управляющего списка появляется событие, назначенное на более
поздний срок. В принципе, здесь не требуется даже атрибут времени достаточно отношения порядка между событиями.
Даже зацикливание некоторых агентов не помешает выполнению
алгоритма, если только вместимость управляющего списка будет
достаточной.
Необходимо подчеркнуть ряд важных моментов:
1. Реального параллелизма в системе с дискретными событиями нет,
но есть эффект параллелизма, который лишен многих самых
неприятных особенностей, требующих специальной заботы о
синхронизации.
2. Изначально в каждый момент набор одновременно действующих
агентов упорядочен частично, он становится упорядоченным
полностью за счет соответствующей расстановки в управляющем
списке.
3. Управляющий список - общая структура данных для агентов-
Стили и методы программированияНепейвода Н.Н.
262

процессов, но ее нельзя считать глобальной, так как явного
доступа управляющий список не имеет.
В качестве хорошего изложения современного состояния дел в технике
практического параллельного программирования можно рекомендовать
книгу [14]
. В частности, и система MPI, описанная в указанной книге, и
ныне весьма широко и необоснованно рекламируемая система Open MP
включают в себя средства квазипараллельного исполнения
параллельных программ, отличные от системы с дискретными
событиями. Эти средства мы не описываем, поскольку для реальных
программ они нужны лишь как метод отладки параллельных программ
на машине с недостаточной конфигурацией (причем метод, не
вызывающий особых восторгов).
1)
Имеются и другие случаи нарушения целостности данных, мы
показали лишь простейший из возникающих при совместной работе.
2)
Поведение русских абсолютно противоположное.
3)
Поскольку здесь мы переходим от сравнительно идеальных к
низкоуровневым понятиям, такая задача избавления от совместности
методологически и практически правильно поставлена, в отличие от
задачи распараллеливания.
4)
В данном случае для подчеркивания специфики экземпляры
объектов лучше называть так.,
5)
По крайней мере, с заведомо большим, чем нужно для данной
задачи.
6)
Когда математику приносят задачу о расчете устойчивости стола с
четырьмя ножками, он быстро выдает результаты для стола с одной и с
бесконечным числом ножек, а затем долго пытается точно решить
конкретную задачу.
7)
Вспомните, что в системах с дискретными событиями целостность
данных должна гарантироваться лишь в момент между шагами
процесса.
Стили и методы программированияНепейвода Н.Н.
263

Программирование от переиспользования
Что нужно для переиспользования? Необходимость математической
культуры. Если бы Билли остался математиком... Образцы, шаблоны и
фреймы.
Может показаться странным, что в обзоре стилей мы специально не
выделили модульное программирование. Однако очевидно, что
требование разрабатывать программы, в которых выделены
автономные и, соответственно, легко заменяемые другими фрагменты,
решающие логически замкнутые задачи, является общелогическим и
общетехнологическим, а не исключительным, присущим какой-либо
специальной методике.
Именно это требование обычно трактуется как модульность
программного изделия. Преимущества модульности, понимаемой в
общем смысле это возможности замены модуля без изменения всего
остального и повторного использования программных фрагментов.
Последнее уже можно рассматривать как особый стиль
программирования, для которого модульность является одним из
средств.
Средства поддержки модульности характеризуют даже не стиль, а
конкретный язык, поддерживающий этот стиль. Поэтому правомерно
говорить не о стиле, а о конкретном языке, в какой мере он
поддерживает модульное построение программ в рамках своего стиля.
Что нужно для переиспользования
Стиль от переиспользования характеризуется тем, что при составлении
программы стремятся максимально использовать то, что уже сделано самим программистом, его коллегами или же вообще где-либо. Давно
уже общепризнано, что в идеале на смену программированию как
кодированию алгоритмов должно прийти программирование как сборка
из заранее заготовленных блоков - сборочное программирование. Этот
термин введен в 1978 г. Г. С. Цейтин позднее отделил это понятие от
теоретических рассмотрений и представил его с программистской
стороны. Заметим, что математики уже давно отказались от построения
новых теорем (соответствующих в информатике программам) и новых
Стили и методы программированияНепейвода Н.Н.
264

понятий (соответствующих абстрактным типам данных) с пустого
места. В математике весьма профессионально переиспользуются ранее
полученные результаты. Здесь из-за концептуального единства системы
понятий и строгих критериев обоснованности не возникает проблемы
совместимости новых версий, которая зачастую губит попытки не
только переиспользования, но и просто использования старых
программ.
Тем не менее интересно проделать следующий мысленный
эксперимент: а что было бы, если математики работали бы примерно в
таких же условиях, как программисты?
Ну, ясно, что если бы математик, опубликовавший теорему, брал бы
деньги (а тем более требовал бы их заранее) за каждое ее
использование, то переиспользование сразу бы си-и-ильно
сократилось.
Даже если бы он не брал деньги за теорему саму по себе, но засекретил
бы ее доказательство и угрожал бы уголовным преследованием всякому,
кто осмелится понять (`дизассемблировать') написанный им текст,
ситуация пришла бы к той же мертвой точке (здесь эта калька
английского слова `deadlock' лучше русского слова `тупик').
Видимо, достаточно было бы оплачивать труд математиков на
повременной основе, проверяя обоснованность отчетов о затраченном
времени по числу строк написанного доказательного текста. Это, может
быть, не прекратило бы переиспользование полностью, но любой
математик (а не только жулики) при каждом удобном случае
переписывал бы чужие доказательства своими терминами и с
маленькими изменениями. Здесь к мертвой точке пришли бы
медленнее, но столь же неизбежно.
Как видите, мы можем сделать важный социальный и практический
вывод: единственным шансом на излечение нынешних подростковых
болезней программирования является работа сообществ открытого
программного обеспечения и открытой проектной документации [34]
.
Понятно, что при использовании готовых строительных блоков
возможны потери. Тем не менее потенциальная выгода за счет
переиспользования просто колоссальна. В математике, где имеются
Стили и методы программированияНепейвода Н.Н.
265

точные оценки, показано, что длину доказательства (читай программы) можно сократить в БАШНЮ ЭКСПОНЕНТ РАЗ без
существенной потери эффективности лишь за счет введения лемм
(читай - использования уже построенных программ).
Рассмотрим две реальные ситуации, которые демонстрируют
разработку, не ориентированную и ориентированную на
переиспользование. В первой ситуации действует программист,
работающий с очень развитой системой, в которой есть все. Тем не
менее он пишет свою процедуру лексикографического упорядочивания
строк, потому что "легче самому написать, чем найти, а потом ведь еще
и подгонять придется". Вывод: во-первых, здесь начисто отсутствует
стремление к переиспользованию, а во-вторых, переиспользованию
могут препятствовать затруднения поиска того, что требуется включить
в составляемую программу, а также проблемы совместимости версий.
Вторая ситуация - другая крайность. Программисту на Java
потребовалось построить синтаксический анализ. На вопрос о том, как
он это делает, получен ответ: "Зачем это знать? У меня есть пакет
JavaCC, который все делает, как надо!" Вместе с тем, дальнейшие
расспросы показали, что этот программист не представляет себе даже
того, какого типа метод анализа поддерживает JavaCC, и,
следовательно, ничего не может сказать о том, как задание грамматики
для данного пакета связано с эффективностью анализа. Узнав
возможные варианты, программист призадумался, но ничего менять не
стал. Почему? Ответ простой: "Так ведь все уже работает!" Короче
говоря, качество использования готовых компонентов системы зависит
от знания о них.
Ситуация опять-таки та же самая, что в математике, особенно в
прикладной. Квалифицированное использование теоретических
результатов требует знания соответствующей теории, а порою и идей
доказательств результатов (поскольку в реальной ситуации
предположения теории никогда не выполняются точно). Глубина
требуемого знания различна: иногда достаточно общего представления,
как, например, при использовании математических функций, иногда
нужны сведения о принципах реализации, но всегда можно указать
необходимый уровень знакомства с переиспользуемым.
Стили и методы программированияНепейвода Н.Н.
266

Сравнение ситуаций показывает, что одних пожеланий и директивных
указаний для переиспользования мало. Необходимы знания о том, что
можно воспользоваться переносимыми компонентами и как именно.
Получение же знаний часто требует существенных трудозатрат. Нужно,
чтобы само переиспользуемое программное обеспечение было
приспособлено для этого, в частности, чтобы оно следовало
накопленной в математике хорошей практике, а не игнорировало ее как
чистую теорию.
Расшифровка предыдущего предложения позволит вдумчивому
читателю самому вывести все условия, необходимые для обеспечения
переиспользования в конкретной обстановке. Любые указания здесь
бесполезны (если человек еще не осознал предыдущее) либо вредны
(если он думает, что осознал, на самом деле ничего не понимая). Можно
дать лишь общий совет для тех, кто еще занимается (само)образованием.
В математике для программиста важны не столько конкретные
результаты (за ними можно обратиться и к справочной литературе),
сколько структура понятий и доказательств, способы введения
абстракций и применения исключительно абстрактных понятий в
частных ситуациях.
Иногда переиспользованию способствует применение развитых
языковых средств. В частности, C++ и Java довольно часто позволяют
переносить программы из одной операционной обстановки в другую
(перенос - одна из форм переиспользования). Но те, кто реально
занимался переносом программ, наверняка вспомнят при чтении
предыдущего предложения досадные несоответствия, выявлению и
предупреждению которых C++ и Java никак не помогают.
Переиспользованию способствует повышение уровня понятий языка,
хотя бы до второго-третьего типа (объектная ориентированность языка).
Иногда ООП помогает также возможностями наследования свойств и
методов объектов (но часто в самых критических ситуациях плохо
продуманная концепция наследования столь же сильно и мешает).
Все это - зародыши поддержки стиля программирования, нацеленного
на переиспользование. Но в основном сложившаяся практика в
значительной степени препятствует переиспользованию, а уровень
систем поддержки еще недостаточно высок и неадекватен общей задаче
Стили и методы программированияНепейвода Н.Н.
267

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

всего, самодокументированию) переиспользуемых компонентов,
причем документация должна четко выделять существенные
особенности алгоритма, показывать имеющиеся призраки и
использованные подпорки, таким образом, она должна быть не
комментарием к тексту программы, а высокоуровневым
описанием идеи и того, что оказалось необходимым для ее
конкретной реализации;
требуется серьезный анализ того, что кандидаты на
переиспользование могут быть отнесены к типовым приемам
программирования, т.е. имеют достаточно широкую для
использования в дальнейшем область применимости
1)
;
нужно прорабатывать не только варианты полного
переиспользования компонентов as is, но и частичного их
переиспользования в виде шаблонов, готовых фрагментов и т. п.,
когда требуется настройка компонента;
необходимы спецификации как области адекватного применения
компонента, так и границ применимости (вторая часть почти
всегда отсутствует в нынешних спецификациях);
в спецификациях нужно четко отличать принципиальные
моменты от подпорок и выделять призраки;
необходима оценка эффективности применения компонента;
необходима специальная забота о публикации компонента для
потенциальных пользователей: они должны иметь возможность
услышать о нем.
Переиспользование и стили
В характеристиках обоих аспектов программирования от
переиспользования нет явного упоминания специфики традиционных
моделей вычислений. Поэтому они не зависят от стиля, в котором
написаны компоненты, и в значительной степени от особенностей
вычислительных систем, на которых они реализуются
2)
. Но компоненты
и модель вычислений выполняют роль фундамента, на котором
базируется надстройка переиспользования. А устойчивость здания и
даже его архитектура существенно зависят от качества фундамента.
Рассмотрим ранее представленные стили с точки зрения их
приспособленности к сочетанию со стилем переиспользования.
Стили и методы программированияНепейвода Н.Н.
269

Автоматное программирование явно связано с глобальным для каждой
программы понятием набора состояний, и использовать фрагмент
программы в отрыве от этого набора, вообще говоря, лишено смысла.
Это указывает на естественные рамки переиспользования для данного
стиля.
Во-первых, если фрагмент может быть выделен как черный ящик, т. е.
нас интересует лишь соотношение между его входными и выходными
данными, то он на уровне программы может рассматриваться как
самостоятельный узел переработки данных и тем самым получает
независимость от состояний программы. В свою очередь, именно это
позволяет использовать такой фрагмент, как самостоятельный узел
переработки другой программы - переиспользовать его. На этом
принципе строятся все библиотечные математические функции,
реализацию которых достаточно часто не требуется даже знать при
использовании.
Обычными единицами переиспользования при любом стиле
программирования являются процедуры. Именно они автономно
описываются, и если оказываются независимыми от общего с другими
компонентами контекста, то, по сути дела, становятся теми самыми
черными ящиками, о которых только что шла речь.
Еще один возможный случай, когда часть, ясно осознанная
программистом, состояний внешней программы может быть
интерпретирована как гомоморфный образ части (опять же, явно
выделенной) состояний компонента ( серый ящик ). Тогда компонент
можно даже модифицировать, т. е. возможно его переиспользование как
фрагмента либо шаблона. Однако приемы установления гомоморфизма
между состояниями - та высокоуровневая надстройка над автоматным
программированием, которая пока еще не создана, и поэтому здесь
программист в высшей степени зависит от качества содержательного
концептуального анализа.
Как ни странно, немногим лучше приспособлено к сочетанию со
стилем переиспользования структурное программирование. Требования
к структуре информационного пространства задачи и к согласованию с
ним других компонентов программы обеспечивают
регламентированные связи между подзадачами, а значит, облегчается
Стили и методы программированияНепейвода Н.Н.
270
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
