16.10.2003/51
Проектирование для программиста
Моделирование поведения системы - двойная работа
Наверное, каждый, кто впервые начинал проектировать программную систему на CASE-инструментах, задавался вопросом - почему проектирование модели классов возможно в графическом представлении, а для кодирования функций необходимо переходить к текстовому редактору и писать по старинке, вручную? Неужели нельзя автоматизировать этот процесс или хотя бы сделать его более наглядным?
Проблема обнаруживается, когда вы, создав классы в CASE-инструменте, пытаетесь описать взаимодействие между ними. CASE-инструменты предлагают вам довольно широкие возможности по описанию поведения классов - это и диаграммы взаимодействия, и диаграммы последовательности, и графы переходов, и графические алгоритмы.
Однако, против ваших ожиданий, даже досконально описав все действия будущей системы, вы не получите готовое приложение. Вам придется потратить уйму времени, наполняя исходный код синтаксически правильными операторами, выверяя последовательность действий по диаграммам и отлаживая синхронность операций.
Когда же вам потребуется изменить поведение системы и внести изменения в код - в силу изменившихся требований или из-за первоначально неправильного проектирования, - вы будете вынуждены параллельно вручную отражать все изменения в соответствующих диаграммах CASE-средств.
Суть проблемы
Давайте разберем следующую задачу: "Найти элемент в наборе данных, максимально удовлетворяющий некоему условию".
Не правда ли, знакомая задача? О, да. А теперь ответьте, как вы ее решите практически? Знаю, знаю - вы скажете, что решение зависит от того, что это за набор данных, каковы его элементы, и как проверяется данное условие.
В каждой более-менее сложной программной системе встречаются подобные задачи. Тривиальной ее разновидностью является поиск максимального значения. Алгоритм для поиска максимума на языках высокого уровня, например C, будет выглядеть примерно так:
maxElement = 0; for( i = 0; i < count ; i++) if (maxElement < array[i]) maxElement = array[i];
Та же задача на языке SQL записывается гораздо проще:
SELECT max(NumField) FROM ArrayTable
Получается, что одинаковая задача решается с помощью четырех операторов на одном языке программирования и всего одним оператором на другом языке. Причем в случае с C нам пришлось завести дополнительные переменные и явно указать порядок перебора операторов.
Аналогично, описывая этот алгоритм в модели поведения, вы должны постоянно иметь в виду некий целевой язык, на котором будет реализовываться целевая система. И, соответственно, использовать алгоритмические конструкции, подходящие для целевого языка.
Но ведь цель моделирования поведения системы состоит не в том, чтобы в деталях описать простейшие алгоритмы! Все, что действительно показать модели, содержится в самом определении задачи - "Найти элемент в наборе ...". А работу по конкретному воплощению задачи хотелось бы оставить автоматическим средствам разработки, и не забивать себе этим голову.
Но, увы, даже современные CASE-средства не настолько умны, чтобы самим думать за человека.
Поиск решения проблемы
Теперь я расскажу вам приятные новости.
В 1998 году некоммерческий консорциум Object Management Group (OMG), работающий над стандартизацией и развитием объектно-ориентированного подхода, предложил членам консорциума проработать вопросы описания на языке UML действий системы, причем так, чтобы описание не зависело от программной платформы.
Над этой задачей работали компании, занимающие заметное положение на рынке CASE-средств, такие как Project Technology, Rational, Telelogic и еще несколько компаний. Результатом работы стал документ Action Semantics for UML. Этот двухсотстраничный документ весьма тщательно определяет семантику элементов, добавляемых в стандарт языка UML для моделирования действий системы.
К сожалению, документ Action Semantics for the UML стандартизирует лишь семантику языка, и не определяет его синтаксис. С практической точки зрения кто означает, что собственно язык моделирования действий системы так и не был разработан. Участники проекта лишь приняли соглашение о принципах разработки такого языка.
Отсутствие стандартного синтаксиса, тем не менее, не помешало нескольким участникам проекта разработать собственный инструментарий моделирования поведения.
Принцип решения проблемы - отчуждение модели системы от реализации
Давайте запишем нашу задачу в виде выражения:
(array, condition) | findBetter > founded
Данное выражение не содержит ничего нового, просто компактно описывает условие задачи. Собственно искомое решение задачи находится в реализации процесса findBetter.
Так вот, идея в том, что если у нас есть некий преобразователь таких выражений для соответствующей платформы, мы можем преобразовать выражение в операторы обычного языка программирования. И скомпилировать в исполняемый код.
Более того, взяв преобразователь и компилятор для другого языка программирования или для другой платформы, мы можем легко перенести то же самое выражение в совершенно новую среду выполнения.
Понятно, что для успешного решения задачи искомый процесс findBetter либо придется описать в терминах таких же выражений и скомпилировать из элементарных процессов, либо преобразователь должен уже уметь реализовать процесс findBetter для своей платформы как элементарный.
Далее, описав модель поведения системы в виде машины состояний и/или в виде совокупности алгоритмов, мы можем в дальнейшем использовать кусочки этой модели в будущих системах, причем не важно, на каких платформах они будут реализованы.
Запись нашей задачи в виде текстового выражения приведена лишь для примера. Точно так же ту же задачу можно записать графически.
На этом рисунке прямоугольник со словом findBetter означает наше искомое действие. Маленькие белые квадратики на его верхней границе обозначают входные контакты в это действие. Черный квадратик на нижней границе findBetter - это, соответственно, выходной контакт действия. Входные и выходные контакты действия (input pins и output pins), по определению Action Semantics for the UML, это точка подключения связи, по которой в данное действие (или из действия) передаются необходимые значения или сигналы. Входные и выходные контакты - это вроде разъемов на задней стенке компьютера, а линия, соединяющая их - это как кабели между разъемами. Так же, как вы не можете напрямую подключить клавиатуру ко входу звуковой карты, точно так же вы не можете соединить контакты, имеющие разный тип передаваемых данных.
Графическая запись имеет перед текстовой некоторые плюсы: она нагляднее, сама обеспечивает синтаксис, в ней проще проводить проверку целостности описания. И, главное, при правильном проектировании графическое представление не накладывает излишних ограничений по последовательности обработки данных.
Таким образом, имея достаточно "умный" преобразователь, мы можем получить готовую систему с параллельной обработкой данных.
Предыдущий рисунок похож на диаграмму деятельности UML (Activity Diagram). В самом деле, что нам мешает записать алгоритм вычисления в следующем виде:
Однако заметьте, здесь нам вновь пришлось принудительно указать распараллеливание процесса вычисления, также пришлось описать дополнительные переменные для хранения промежуточных результатов. Произошло это потому, что стрелками на диаграмме деятельности обозначается передача управления, а не передача сигналов к следующей операции вычисления. Каждое действие на диаграмме деятельности как бы живет своей самостоятельной жизнью, не зная, откуда передано ей управление, и не зная, имеются ли значения, необходимые для выполнения этого действия.
Action Semantic определяет, что действия взаимодействуют в потоке данных (data flow), и, в отличие от потока управления (control flow), без необходимости на диаграммах не указывается порядок исполнения действий. В каждый момент времени могут выполнятся все действия, имеющие достаточно данных для их выполнения. Вы можете заметить, что диаграммы Action Semantic в таком случае будут очень похожи на диаграммы в нотации DFD (data flow diagrams).
И это справедливо. Вообще говоря, значение нотации DFD долгие годы незаслуженно принижалось апологетами UML. Но Action Semantic имеет существенное отличие от DFD. Правила Action Semantic предполагают, что каждое действие имеет четко определенное количество входов и выходов. Каждый вход и выход может, соответственно, принимать или передавать сигналы только одного типа. Соответствие типов сигналов можно проверить уже в тот момент, когда вы протягиваете в графическом редакторе стрелочку от выхода одного действия к входу другого. В нотации же DFD тип данных, передаваемых от одного процесса к другому, указывается в одном месте - на самой связи, и не имеет образца для проверки. Различие в этих нотациях происходит из целей их создания - DFD создавалась для понятного, но упрощенного моделирования и проектирования систем - так, чтобы диаграммы DFD можно было рисовать на бумаге. А язык Action Semantic создавался специально для использования в инструментальных средах, позволяющих более или менее автоматически сгенерировать по модели исходный код системы.
Executable UML
На сегодняшний день на рынке имеются несколько CASE-инструментов, позволяющих транслировать модель поведения системы в исходный код. Вот некоторые из них:
- * Rational Rose RealTime, производства фирмы Rational Software Corporation (теперь IBM);
- * BridgePoint Development Suite, производства фирмы Project Technology, Inc.;
- * iUML, производства фирмы Kennedy-Carter;
- * Kabira Visual Design Center, производства фирмы Kabira Technologies, Inc.;
- * Telelogic Tau, производства фирмы Telelogic AB.
Надо заметить, хотя все эти фирмы активно участвовали в создании документа Action Semantics for the UML, каждая из них реализует свой подход к описанию и трансляции модели поведения.
Так, например, продукт фирмы Rational. Rational Rose RealTime, сокращенно RoseRT, весьма похож на Rational Rose. Специально для моделирования поведения системы в нем создан новый тип классов, называемый капсулой. Капсула - это точно такой же класс, но имеющий выводы (порты) для подключения других капсул с помощью нового вида связи, называемого протоколам. Капсулы по протоколу передают друг другу сигналы. На получение капсулой сигнала можно назначить триггер, переводящий капсулу в следующее состояние в соответствии с диаграммой состояний капсулы. Таким образом, капсула - это обособленная машина состояний, реагирующая на внешние сигналы и посылающие сигналы другим капсулам.
Второе отличие RoseRT от Rose заключается в том, что спроектированную модель поведения можно скомпилировать и даже отладить. Вы можете прямо на экране во встроенном в RoseRT отладчике увидеть, как передаются сигналы и как капсулы переходят из одного состояния в другое. В качестве компилятора используются внешние компиляторы третьих фирм.
И, наконец, третье главное отличие RoseRT от Rose. Rational Rose RealTime все-таки остается несовместимой с Rose в части генерации кода. RoseRT построена на совершенно других OLE-объектах, и, следовательно, add-in от Rose не будет работать в среде RoseRT. Поэтому, работая с RoseRT, вы можете выбрать любой язык, если только он будет C или C++ (недавно к этому списку добавилась Java), и любую платформу, если для нее есть компилятор с языков C или C++. А если вам понадобится смоделировать и сгенерировать структуру базы данных, вам придется воспользоваться Rose.
К сожалению, для записи кода действий в RoseRT используется те же C и C++, а не абстрактный язык, как предполагается в Action Semantics for UML. Это приводит к снижению уровня абстракции обратно до конкретного языка программирования.
Kabira Visual Design Center, производства фирмы Kabira Technologies, Inc., сделан как расширение (add-in) к Rational Rose (не Rose RealTime). В противоположность RoseRT, в Kabira Design Center для записи действий используется абстрактный язык, соответствующий Action Semantics for UML. Получившийся исполнимый код может выполняться в виртуальной среде выполнения Kabira Infraserver Switch, также генерятся скрипты SQL и файлы с описанием интерфейсов для CORBA.
Пакет Telelogic Tau, похоже, ближе всего подошел к идее, описанной в Action Semantics for UML. В Tau каждый класс может иметь порты, похожие на порты в капсулах RoseRT. Действия в Tau описываются на абстрактном языке, соответствующем Action Semantics for UML. По модели генерируется код на языках C или C++ и компилируется внешним компилятором.
Перспективы
Консорциум OMG после принятия документа Action Semantics for UML продолжил работу над созданием языка описания действий. Предполагается, что новый язык войдет в качестве составной части в стандарт UML 2.0, который уже вот-вот должен быть принят. Фирмы-участники консорциума уже предоставили свои предложения по новому стандарту. И как ранее, фирмы-участники создают инструменты, не дожидаясь официального принятия стандарта UML 2.0.
С распространением этой технологии открываются очень интересные перспективы.
Во-первых, большая часть работы по кодированию системы будет выполняться уже на этапе проектирования. Или можно сказать иначе - кодирование системы будет в большей части состоять из ее проектирования.
Во-вторых, поскольку сама модель становится исходным кодом, то от концепции повторно используемого кода мы приходим к концепции повторно используемых моделей. Это означает, что единожды спроектированные таким образом системы становится возможным интегрировать в другую, более сложную систему, а также легко перенести на другую архитектуру, например, с технологии клиент-сервер на трехзвенную архитектуру, не нарушая при этом ни одного принципа, заложенного в системе.
В-третьих, отлаживать подобные системы уже сейчас возможно на другой платформе, что может быть важно для встроенных систем. И отлаживать систему станет легче, поскольку при появлении ошибки вы сразу будете знать - что пошло не так и что надо подправить.
Но программистам-кодировщикам тоже будет чем заняться. Для кодировщиков появляется задача разработки трансляторов с языка моделирования в исходный код на языке программирования или прямо в машинный код. Поскольку задача эффективной трансляции весьма неоднозначна, то для истинных кодировщиков открывается очень широкое поле деятельности.
Ссылки
1. Current Unified Modeling Language (UML) specification - http://www.omg.org/technology/documents/formal/uml.htm 2. Action Semantics Consortium - http://www.kc.com/as_site/home.html 3. Action Semantics for UML - Request For Proposal (RFP) - http://www.projtech.com/pubs/xuml/rfp.pdf 4. Action Semantics for UML - Submitted a response to the Request for Proposal (RFP) http://www.kc.com/as_site/download/ActionSemantics.zip 5. Executable UML: Diagrams for the Future by Gerry Boyd - http://www.webbuildermag.com/uml/Article/10717 6. Precise Action Specification for UML - http://www.projtech.com/pubs/xuml/uml98.pdf 7. Executable UML: A Foundation for Model-Driven Architecture - http://www.projtech.com/pubs/books/xumlmda/index.html 8. UML 2.0 Submissions - http://www.u2-partners.org/artifacts.htm
Сергей Шмаков
Статья была опубликована в журнале "Технология клиент-сервер" N2'2003 Обсуждение статьи |