Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

2920

.pdf
Скачиваний:
1
Добавлен:
15.11.2022
Размер:
2.61 Mб
Скачать

базе имеющегося исходного кода. Из этого следует самая главная возможность для разработчиков: повторное проектирование (Round-trip), когда разработчик описывает классы в Rose, генерирует код, дописывает необходимую полнофункциональную часть и снова закачивает в Rose, для представления того, что же система получила в результате его действий. Важнейшим свойством Rational Rose принято считать открытость архитектуры, что позволяет дополнять имеющийся в ней инструментарий новыми функциями. Например, в стандартном варианте Rose не поддерживает кодогенерацию на Ассемблере. Путем написания дополнительного модуля подобную проблему можно решить. Вот список включенных стандартных модулей: С++, ADA, CORBA, Visual Basic, XML, COM, Oracle). То есть Rational Rose способна проводить прямое и обратное проектирование в данных системах.

Подведем первые итоги того, что может делать Rational

Rose:

Проектировать системы любой сложности

Давать развернутое представление о проекте в сочетании со средствами документирования (SoDA)

Проводить кодогенерацию

Проводить обратное проектирование имеющихся систем

Имеет открытый для дополнений интерфейс

Интегрируется со средствами разработки (Visual Studio)

Поддержка языка UML

Наличие средств автоматического контроля, в том числе проверки соответствия двух моделей

Удобный для пользователя графический интерфейс

Многоплатформенность

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

21

управления требованиями (Requisite Pro), со средствами тестирования (SQA Suite, Performance Studio), со средствами конфигурационного управления (ClearCase, PVCS).

1.4. Технология COM

COM (Component Object Model — модель многокомпонентных объектов) — одна из базовых технологий Windows. Более того, все новые технологии Windows (Shell, Scripting, HTML и т. п.) реализуют свои прикладные программные интерфейсы (Application Program Interface, API)

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

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

22

загружаемая библиотека (Dynamic Link Library, DLL). В этом случае оба модуля содержатся в одном и том же адресном пространстве. Казалось бы, достаточно создать в DLL объект, а его методы вызвать из основного приложения — и задача решена. Чтобы попять, что это не так, рассмотрим небольшой пример. Определим метод IsFont в приложении:

procedure IsFont(0: TObject); begin if-0 is TFont then ShowMessage('Font')

el se ShowMessageC'Not font'); end;

procedure TForml.ButtonlClick(Sender: TObject); begin . IsFont(Font): end;

Вызовем этот метод из приложения. В качестве параметра метода Is Font используем свойство Font формы. Как и ожидалось, появится сообщение, что объект является шрифтом.

Теперь создадим динамически загружаемую библиотеку, поместим в нее функцию IsFont и объявим ее экспортируемой:

library FontLib:

uses

SysUtils, Dialogs. Graphics, Classes; procedure IsFont(0: TObject); begin

if 0 is TFont then ShowMessage("Font') else

ShowMessage('Not font') end;

exports

IsFont name 'IsFont'; begin end.

Пусть функция IsFont вызывается из библиотеки при щелчке на кнопке Button2 в вызывающем приложении: procedure IsF(O-.TObject): external 'FontLib.dll' name 'IsFont'; procedure TForml.Button2Click(Sender: TObject); begin

23

IsF(Font); end;

Результат этого действия окажется противоположным

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

Вторая проблема возникает при обобщении первой проблемы. В приведенном выше примере было известно заранее, какую функцию надо вызвать и каков список ее параметров. Соответственно, в приложении перед компиляцией программистом помещается строка кода: procedure IsF(0: TObject); external 'FontLib.dll' name 'IsFont ,

Эта строка определяет имя функции IsFont и список ее параметров 0: TObject, поэтому программисту, использующему эту библиотеку, потребуется документация — список функций со списком их формальных параметров. Их реализация "вручную" с большой вероятностью приведет к ошибкам. Для исправления ошибок потребуется время, причем без всякой гарантии, что все ошибки будут обнаружены. Хотелось бы, чтобы сам модуль мог информировать среду разработки о том, какие методы ей доступны и каковы списки их формальных параметров. Сложности работы с различными модулями этим не ограничиваются. Например, если в одном из модулей зарезервирована память для хранения данных, то в другом модуле без специальных мер нельзя ни освободить ее, ни изменить ее размер. Это связано с тем, что в каждом модуле имеется собственный менеджер памяти. Если один модуль выделяет память, то в менеджере памяти другого модуля это никак не фиксируется. Для реализации операций, связанных с применением в различных модулях общих областей памяти, необходимо наличие общего менеджера памяти. Для его создания в Delphi используется модуль ShareMem.

24

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

Можно выделить и другие проблемы, которые встречаются при традиционном программировании, например:

-поиск установленной копии приложения, реализующего требуемые сервисы, и корректная его инициализация;

-обеспечение корректной работы приложения-сервера одновременно с несколькими клиентами;

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

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

25

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

Основным понятием, на котором основана модель СОМ, является понятие интерфейса (interface). Без четкого понимания того, что такое интерфейс, невозможно успешное программирование СОМ-объектов.

Интерфейс является контрактом между программистом

икомпилятором:

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

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

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

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

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

Таким образом, необходимо понять следующее:

26

- Интерфейс — это не класс. Класс может выступать в роли реализации интерфейса, но класс содержит код методов на конкретном языке программирования, а интерфейс — нет.

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

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

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

2.УНИФИЦИРОВАННЫЙ ЯЗЫК МОДЕЛИРОВАНИЯ

UML

2.1.UML и Rational Rose

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

27

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

2.1.1. Пакеты

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

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

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

Графическое представление пакетов в языке UML показано на рис. 2.1. Такая нотация позволяет визуализировать группы элементов, с которыми можно обращаться как с единым целым, контролируя при этом видимость и возможность доступа к отдельным элементам.

28

Рис. 2.1. Пакеты

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

Рис. 2.2. Простой и расширенный пакеты

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

29

Пакет определяет свое пространство имен; это значит, что элементы одного вида должны иметь имена, уникальные в контексте объемлющего пакета. Например, в одном пакете не может быть двух классов Queue, но может быть один класс Queue в пакете Р1, а другой - в пакете Р2. Р1: : Queue и Р2 : : Queue имеют разные составные имена и поэтому являются различными классами.

Элементы различного вида могут иметь одинаковые имена в пределах пакета. Так, допустимо наличие класса Timer и компонента Timer. Однако на практике, во избежание недоразумений, лучше всем элементам давать уникальные имена в пакете.

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

Sensors: : Vis ion: : Camera. Лучше, однако, избегать слишком глубокой вложенности пакетов - два-три уровня являются пределом

2.1.2. Классы, атрибуты, операции

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

Многие языки программирования непосредственно поддерживают концепцию классов. И это замечательно,

30

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]