интересно
Предыдущая | Содержание | Следующая

Особенности реализации конструктора моделей gem

Конструктор создан для работы под управлением Windows 95/98/NT и использует удобные диалоговые средства, предоставленные графическим интерфейсом этих операционных систем.

Модель с точки зрения конструктора Pilgrim можно представить как набор следующих компонентов:

граф модели;

параметры инициализации модели;

переменные модели;

включенные в модель фрагменты программного кода на языке C++.

Кратко рассмотрим каждый из перечисленных компонентов.

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

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

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

Параметры инициализации модели - это набор переменных, включенных в функции инициализации модели modbeg и завершения модели modend.

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

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

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

Основное достоинство конструктора Pilgrim заключается в том, что он позволяет:

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

представлять каждый уровень структурной детализации в виде графического слоя;

автоматически генерировать программный текст модели.

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

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

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

Рассмотрим пример на рис. 5.2, где в плоскости 1 имеется последовательность узлов Клапан_1->Действие_1->Очередь_1.

Узел Действие_1 является узлом типа parent и содержит детализирующую плоскость 11. Плоскость 11 содержит цепочку Оче-редь_2->Сервер_2.

В плоскости 11 стрелка, направленная из левого, верхнего угла экрана в узел Очередь_2, обозначает, что этот узел является входом на плоскость, а стрелка из узла Сервер_2 в правый верхний угол -что это выход с плоскости. При запуске генерации программного файла получим следующую цепочку: Клапан_1->Очередь_2-> Сер-вер_2-Ючередь_1, т. е. узел Действие_1 является лишь средством реализации многоуровневости и будет обработан генератором как узел Pilgrim.

Иногда при построении модели может возникнуть необходимость выделения некоторых типовых действий по обработке данных. Это могут быть запросы на выполнение бухгалтерской проводки, требования выделения моделируемого ресурса или какие-либо другие действия. При возникновении такой задачи удобно обозначить подпрограммы, обращение к которым было бы возможно из любого места модели. Для этого используются узлы типа pay, rent, down. Такие узлы, так же как и parent, содержат переход на более низкий уровень модели, однако имеют несколько иной механизм действия и область применения. Если с помощью узла типа parent можно создавать иерархические модели, имеющие на любой сколько угодно глубоко вложенной плоскости новые узлы parent, то с помощью узлов типа pay, rent, down возможно лишь реализовать подпрограммы на двух слоях модели и невозможно построить общую иерархию уровней.

Рассмотрим принцип работы таких узлов на примере узла pay (рис. 5.3). -На плоскости 1 находится узел типа pay, содержащий обращение к подпрограмме, расположенной в плоскости 12. Входом плоскости 12 является узел с названием Расчетный счет фирмы, а выходом - узел с именем Бухгалтерия. При генерации программного файла а узле Бухгалтерия в качестве параметра, определяющего номер следующего узла, на который переходит транзакт, будет указано не конкретное значение, а специальный параметр транзакта updown. При этом предполагается, что каждый транзакт, попадающий в выходной узел плоскости, содержит в параметре updown номер узла, на который следует выполнить переход. Параметр транзакта updown инициализируется в узле типа pay, т.е. в нашем случае в узле с названием Плата поставщику.

Аналогичным образом реализуется переход на подпрограмму с использованием узлов типа rent и down. Они также инициализируют переменную транзакта updown. Из вышеизложенного можно сделать вывод о невозможности использовать узлы типа pay, rent и down для реализации иерархических моделей по следующей причине: на уровне подпрограммы узла одного из перечисленных типов нельзя размещать никакой из узлов типа pay, rent, down, так как каждый из этих узлов заново выполнит инициализацию параметра транзакта updown, т.е. заменит значение updown, установленное уровнем выше, организуя циклическую ссылку (это приведет к семантической ошибке).

Чтобы защитить пользователя от совершения таких ошибок, конструктор не позволяет создавать в текущей плоскости узлы типа pay, rent, down, если управление передано с более высокого уровня через узел перечисленного типа. Однако узлы обращения к подпрограмме имеют одно важное преимущество перед узлом parent. Оно состоит в том, что транзакт сам помнит, куда ему необходимо вернуться; поэтому из нескольких узлов (или слоев) можно обращаться к общей плоскости, содержащей детальное выполнение типового действия.

Обратимся еще раз к примеру, приведенному на рис. 5.3. Предположим, что имеется некоторая организация, имеющая собственный расчетный счет и выполняющая ряд операций по перечислению средств; часть операций необходимо смоделировать. В плоскости 12 создана подпрограмма Плата поставщику, выполняющая бухгалтерскую проводку по перечислению средств со счета фирмы. Если возникает необходимость смоделировать аналогичную ситуацию с перечислением средств (например, возврат кредита), то можно создать новый узел типа pay и указать ему в качестве подпрограммы плоскость 12.

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

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