Главная » Статьи » Моделирование и ООП - программирование.   Печатная форма страницы

Моделирование и ООП - программирование.

Глава 11: Моделирование и ООП - программирование.

Когда компания Borland хотела обеспечить UML (Unified Modeling Language — унифицированный язык моделирования) — решение разработки для редакций Enterprise и Architect версии Delphi 7, она решила связать его с ModelMaker, разработанным голландской компанией ModelMaker Tools (www.ModelMakertools.com). ModelMaker — это высококачественное средство UML - разработки, с возможностью интеграции в IDE Delphi. Но помере знакомства с ModelMaker в ходе этой главы вы поймете, что ModelMaker — это не только средство составления UML-схем. Мы, конечно, рассмотрим эту возможность, но помимо нее также познакомимся и с множеством других особенностей этого средства. Кроме того, будет представлен концептуальный обзор продукта, который позволяет добиваться еще большего.

ModelMaker появился почти вместе со средой Delphi и со временем накопил параметры поддержки почти всего языка Delphi, а также множество удобных для программистов функций. Как результат — громадный набор возможностей, которые на первый взгляд могут испугать. Интерфейс пользователя ModelMaker содержит более 100 форм и без соответствующей подготовки неподготовленный человек может оказаться в замешательстве. Положитесь на меня и скоро вы сможете смело пользоваться ModelMaker.

Хотя ModelMaker обычно относят к средству построения UML-схем, я предпочитаю воспринимать его как настраиваемый, предназначенный для использования в Delphi, расширяемый инструмент составления UML- и CASE-схем полного цикла. Я называю его «Delphi-инструментом», поскольку он предназначен для обработки программного кода Delphi. Например, при работе со свойствами диалоговые окна ModelMaker представляют параметры, которые специфичны для ключевых слов Delphi и самой концепции. «Настраиваемым» я называю ModelMaker по-тому, что генерацией программного кода Delphi на основе построенной объектной модели могут управлять сотни параметров. ModelMaker является «расширяемым», потому что имеющийся API-интерфейс OpenTooLs обеспечивает создание встраиваемых экспертов, расширяющих функциональность продукта. ModelMaker характеризуется как «средство полного цикла» ввиду того, что он предлагает функциональные возможности, используемые на всех этапах стандартного цикла разрабо-тки. И, наконец, ModelMaker может рассматриваться как «CASE-средство», поскольку автоматически может генерировать ясный, даже с некоторой избыточностью программный код, требуемый для объявления классов Delphi, оставляя вам возможность лишь пре-доставить операционный код классов.

ПРИМЕЧАНИЕ

Эта глава написана совместно с Робертом Лии (Robert Leahey), благодаря его глубоким познаниям и богатому опыту работы с ModelMaker. В мире программного обеспечения Роберт Лии является разработчиком, программистом, автором и лектором. Как музыкант он профессионально занимается музыкой более 20 лет и закончил Северо-техасский университет (University of North Texas) в области теории музыки. Через свою компанию Thoughtsmithy (www.thoughtsmithy.com) Роберт предлагает услуги по обучению, консультированию по вопросам коммерческого программного обеспеченней аудиопродукции и крупномасштабной скульптуры из конструктора LEGO. Он живет в северном Техасе со своей женой и дочерьми.

В этой главе рассматриваются следующие вопросы:
  • понятие ModelMaker;
  • моделирование и UML;
  • особенности генерации кода в ModelMaker;
  • документация и макросы;
  • регенерация программного кода из составляющих;
  • реализация шаблонов.
Оглавление:
  1. Понятие внутренней модели ModelMaker
  2. Моделирование и UML
  3. Схемы последовательности действий
  4. Использование CASE- и других схем
  5. Прочие схемы
  6. Общие элементы схем
  7. Особенности составления программного кода в ModelMaker
  8. Интеграция Delphi/ModelMaker
  9. Управление моделью кода
  10. Редактор Unit Code Editor
  11. Редактор Method Implementation Code Editor
  12. Представление Difference
  13. Event Types View
  14. Документация и макросы
  15. Документация по сравнению с комментариями
  16. Работа с макросами
  17. Регенерация программного кода
  18. Применение шаблонов дизайна
  19. Шаблоны программного кода
  20. Малоизвестные изюминки
Понятие внутренней модели ModelMaker

Перед тем как перейти к рассмотрению поддержки UML в ModelMaker и других особенностей, необходимо чтобы вы обязательно поняли саму концепцию: как ModelMaker управляет программным кодом модели. В отличие от Delphi и других редакторов, ModelMaker не выполняет непрерывного анализа файла исходного кода для визуального представления его содержания. Рассмотрим Delphi: любая удобная функция IDE, используемая для изменения программного кода, осуществляет не посредственное изменение содержания файла исходного кода (который для закрепления этих изменений впоследствии может быть сохранен). В отличие от него, ModelMaker обслуживает внутреннюю модель, представляющую ваши классы, программный код, документацию и т.д., а потом на основании этой модели в дальнейшем генерирует файлы исходного кода. Когда с помощью различных редакторов продукта ModelMaker осуществляется редактирование модели, изменения применяются только к внутренней модели, а не к внешним файлам исходного программного кода; по крайней мере, до тех пор, пока вы не скажете ModelMaker сгенерировать внешние файлы. Это различие должно вызвать некоторое разочарование.

Еще один необходимый для понимания момент заключается в том, что ModelMaker может представить в пользовательском интерфейсе одну модель программ ного кода множеством различных видов (представлений). Эта модель может просматриваться и редактироваться, например, как иерархия классов, или как список модулей, содержащих классы. Члены классов могут сортироваться, фильтроваться, группироваться и редактироваться различными способами. Любое количество видов может быть представлено во множестве надстроек, доступных для ModelMaker Но наиболее важный для рассмотрения — редактор UML-схем, который сам по себе является еще одним вариантом просмотра модели. При визуализации элементов модели (классов или модулей) в схемах создается визуальное представление элементов модели кода; если со схемы удалить какое-либо обозначение (symbol), это не обязательно приводит к удалению элемента из модели — вы просто удаляете его представление в схеме.

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

Моделирование и UML

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

Моя цель посмотреть на UML-схемы с точки зрения Delphi-программиста, использующего ModelMaker. Углубленное изучение ModelMaker выходит за рамки данной главы.

Схемы классов

Одной из самых используемых UML-схем, поддерживаемых ModelMaker, является схема класса (class diagram). Схемы классов могут выводить всевозможные отношения классов, но в самом простом варианте этот тип схем изображает набор классов или объектов, а также статические отношения между ними. Например, на рис. 11.1 представлена схема класса, содержащая классы из примера NewDate, представленного в главе 2. Если при импортировании этих классов в ModelMaker и создания собственной схемы вы получите другой результат, вспомните о множестве параметров, про которые я говорил чуть ранее. Визуальным представлением классов управляет множество настроек. Можно открыть файл ModelMaker (МРВ-файл), используемый для получения рис. 11.1 из соответствующей папки исходного кода текущей главы.

Рис. 11.1. Схема классов в ModelMaker

Ранее я упоминал, что редактор схем ModelMaker — это просто еще один вариант представления внутренней модели. Некоторые обозначения в схеме непосредственно отображаются на элементы модели кода, а другие — нет. На низкоуровневой схеме, такой как схема класса, большинство обозначений представляют действительные элементы модели кода. Манипулирование этими обозначениями может привести к изменению программного кода, генерируемого ModelMaker. С другой стороны диапазона, в case-схеме, большинство (если не все) обозначений не имеют представления в модели кода. С помощью схемы класса в модель можно добавлять новые классы, интерфейсы, поля, свойства и даже документацию. Более того, с помощью схемы можно изменять наследование класса в модели. В то же время в схему класса можно добавлять ряд обозначений, не имеющих логического представления в модели кода.

Схемы классов в ModelMaker также позволяют создавать программный код для работы с интерфейсами, т.е. работать на высшем уровне абстракции. На рис. 11.2 представлены отношения классов и интерфейсов сложного примера использования интерфейса IntfDemo. Этот пример рассмотрен в электронной книге (см. Приложение В), а его фрагменты представлены в примерах данной главы.

Рис. 11.2.Схема класса с интерфейсами, классами и предоставлением интерфейса

При использовании интерфейсов в схеме классов имеется возможность указать отношения реализации интерфейсов между классами и интерфейсам, и эти реализации будут добавлены в модель кода. Добавление реализации интерфейса в схему проявляется во внешнем виде одной из искусных особенностей ModelMaker: мастере Interface Wizard (рис. 11.3). Активизация Interface Wizard значительно упрощает задачу реализации интерфейса. Мастер перечисляет методы и свойства класса, необходимые для реализации данного интерфейса (или интерфейсов), он добавит в реализацию класса все необходимые члены. Обратите внимание, что для всех методов, добавленных в класс, вам необходимо лишь предоставить значимый программный код. На рис. 11.3 мастер оценивает TAthlete для его интерпретации IWalker и IJumper, а также предлагает изменения, которые необходимы для правильной реализации этих интерфейсов.

рис. 11.3.Мастер Interface Wizard

Схемы последовательности действий

Схемы последовательности действий (sequence diagrams) модели взаимодействия объектов выполняются в виде представления объектов и сообщений, передаваемых им в течение времени. В типичной схеме последовательности действий (последовательной схеме) объекты, взаимодействующие с системой, выстраиваются вдоль оси X, а время откладывается сверху вниз по оси Y. Сообщения представляются в виде стрелок между объектами. Пример самой обычной схемы последовательности действий можно увидеть на рис. 11.4. Последовательные схемы можно создавать на различных уровнях абстракции, позволяя представлять высокоуровневые взаимодействия с системой, состоящие всего из нескольких сообщений, либо низкоуровневые взаимодействия со множеством сообщений.

рис. 11.4. Последовательная схема для обработчика событий примера NewDate

Совместно со схемой классов схемы последовательности действий относятся к поддерживаемым ModelMaker UML-схемам, наиболее близко связанным с моделью программного кода. В ModelMaker можно создать ряд схем, в которых обозначения схемы не имеют непосредственной связи с моделью кода, но составление последвательной схемы напрямую влияет на программный код, поскольку вы моделируете классы и их методы. Например, при создании обозначения для сообщения между объектами имеется возможность выбрать метод из списка методов, принадлежищих объекту-получателю; либо можно выбрать и добавить в объект новый метод, а этот новый метод будет добавлен в модель кода.

Обратите внимание, что (я уже говорил об этом) ModelMaker не может автоматически создавать схему последовательности действий из импортируемого программного кода; вам необходимо будет создать ее самому.

Использование CASE- и других схем

Сначала я познакомил вас с двумя UML-схемами самого низкого уровня, но Model Maker поддерживает и высокоуровневые схемы, предназначенные для обеспечения перехода от высокоуровневого моделирования взаимодействий пользователя с использованием case-схем к низкоуровневым схемам класса и схемам последовательности действий. Наряду с широко используемыми схемами можно использовать и case-схемы невзирая на то, что их схемные обозначения не имеют никакого отношения к элементам модели кода. Эти схемы предназначены для моделий, на основе которых предполагается создавать программное обеспечение. Для использования их в ходе согласования с заказчиками они являются достаточно ясными и не требуют объяснений.

Простое использование case-схем основывается на существовании субъектов (actors) (пользователей или подсистем приложений) и случаев использования (use cases) (то, что делают субъекты). Один из самых часто задаваемых вопросов, связанных с использованием use cases, касается обработки текстов use cases в ModelMaker. Текст для use cases — это просто следующий шаг, определяемый в ходе предварительного анализа. Например, use cases — короткое описание действий, которые может предпринять субъект («Выполнить предварительный просмотр отчета продаж» или «Изменить размер окна»); текст use case — более длинный и представляет более подробное описание. ModelMaker не имеет специальной поддержки длинных текстов use cases; необходимо либо использовать условные знаки в схеме, связанной с обозначением use cases, либо связать обозначение use cases в внешним файлом, содержащим текст use cases. Более подробно эти технологии будут рассмотрены далее в этой главе.

Кроме того, ModelMaker поддерживает и следующие UML-схемы:
Collaboration Diagrams (Схемы сотрудничества)

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

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

Activity Diagrams (Схемы деятельности)
Схема, содержащая описание потока работы системы. Она особенно удобна для визуализации параллельной обработки.

Component and Deployment Diagrams (Схемы компонентов и расположения)
Также известны как «схемы реализации». Это схемы, которые позволяют моделировать отношения между компонентами (модулями, а фактически — исполняемыми файлами, СОМ-объектами, DLL и т. д.), либо в случае схем размещения — физическими ресурсами, называемым узлами (nodes).


Прочие схемы

ModelMaker также поддерживает еще три типа схем, которые не попадают под UML-стандарт, но являются очень полезными:

Схемы Mind-Map
Предложены Тони Базэн (Tony Buzan) в 60-х гг. XX в. Отличный метод «мозговой атаки», изучения вопросов ветвления или быстрой записи, связанной с мышлением. Я зачастую использую mind-map-cxeмы (Букв.: отображение сознания. — Примеч. перев.) для общего представления данных в ходе презентаций.

Unit Dependency Diagrams (Схемы зависимостей модулей)
Довольно часто представляют результаты работы мощного анализатора Unit Dependency Analyzer, входящего в состав ModelMaker. Эти схемы представляют ветвящиеся отношения модулей внутри Delphi-проекта.

Robustness Diagrams (Схемы устойчивости)
Вероятно, были упущены в UML-спецификации. Эти схемы помогают «залатать брешь» между case-моделированием, относящимся только к интерфейсному представлению, и схемами последовательности действий, специализированными на реализации. Схемы устойчивости могут помочь группе аналитиков проверить use cases и вникнуть в детали реализации.

Общие элементы схем

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

Обозначение Hyperlink позволяет вам добавлять в схему надпись, связаннун с другим элементом. На самом деле подавляющее большинство обозначений схем поддерживают эту возможность. Можно привязать другую схему (щелчок на связи приведет к открытию в редакторе связанной схемы), привязать элемент модели кода (будь то классом, модулем, методом, интерфейсом и т.д. — щелчок на связи приведет к открытию соответствующего редактора для связанного элемента) или привязать внешний документ (эта связь откроет связанный документ в соответствующем приложении).

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

Обозначение отношений или соединений по умолчанию производится прямыми линиями, однако имеется возможность переключить их на линии, изгибающиеся под прямыми углами (ортогональные линии), выбрав необходимое обозначение и нажав Ctrl+O. Помимо этого нажатием клавиши Ctrl и щелкнув на линии можно добавить узлы этих обозначений. ModelMaker постарается, насколько это возможно, сделать обозначения ортогональными.

ModelMaker также предлагает устойчивый набор визуальных стилей обозначений. Можно определить стили шрифта и цвета в соответствии с иерархией и применять их к обозначениям схемы, указывая наименования. Более подробно об этом можно прочитать в разделе «Style manager» онлайновой справочной системы.

И заключительной общей чертой является возможность иерархического упорядочивания списка схем (рис. 11.5). Для систематизации и «изменения родителя» можно добавлять папки. Для этого, удерживая нажатой клавишу Ctrl, необходимо перетащить схему на ее нового предка.

рис. 11.5. Возможности структуризации вида схем

Построение схем ModelMaker включает обширный набор возможностей; после некоторого изучения этого набора вы сможете признать, что он перевернул вам весь процесс разработки. Для Delphi-разработчиков активная двухсторонняя сущность редактора Diagram Editor обеспечивает более динамичный опыт построения схем, чем большинство UML-редакторов, которые лишь обеспечивают генерацию красивых статических картинок.


Особенности составления программного кода в ModelMaker

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

Прежде чем мы подберемся к этим вопросам, сначала мы рассмотрим, как сотрудничают Delphi н ModelMaker.

Интеграция Delphi/ModelMaker

  После установки ModelMaker добавляет в меню IDE Delphi соответствующим образом оформленный пункт ModelMaker:

Если у вас отсутствует это меню, необходимо настроить в реестре DLL-мастер ModelMaker (см. вставку «Установка новых DLL-мастеров» в конце главы 1). С помощью этого меню можно управлять ModelMaker и быстро импортировать программный код в проекты ModelMaker.

Большинство пунктов меню доступны только при запущенном ModelMaker. После запуска ModelMaker (либо обычным образом, либо с помощью пункта Run ModelMaker) станут доступными и остальные пункты. Меню интеграции имеет несколько различных возможностей переноса программного кода в модель. Пункты Add to Model, Add Files to Model, Convert to Model и Convert Project to Model приведут к импортированию указанных модулей: пункты Add... импортируют модули в загруженную в текущий момент модель ModelMaker, а пункты Convert... создают новую модель и импортируют в нее модули.

Лучше всего начинать с Convert Project to Model. Когда в Delphi открыт ваш проект, не забудьте сделать резервную копию программного кода, а затем выберите этот пункт меню. Весь проект будет импортирован в новую модель ModelMaker.

Где VCL? Импортирование и наследование в ModelMaker

При исследовании только что импортированного в ModelMaker программного кода можно отметить, что импортируются только модули, являющиеся частью проекта. ModelMaker «не умеет» автоматическим импортировать модули, содержащиеся в разделе uses проекта. Это привело бы к созданию неоправданно большого количества моделей с лишними импортированными классами. Однако многие из приятных особенностей ModelMaker, относящихся к наследованию, требуют, чтобы в кодовой модели существовал класс-предок. (Например, при установке свойства изменения класса-предка будут автоматически распространяться на всех перекрывающих наследников.)

К счастью, при импортировании имеется множество настроечных параметров. Хотя импортирование может выполняться с помощью интегрированного в Delphi меню ModelMaker (или путем перетаскивания в ModelMaker модулей из проводника Windows), наиболее удобный способ заключается в использовании одной из кнопок Import панели инструментов ModelMaker. Использование преимущества их параметров позволяет импортировать часть VCL в качестве классов-«заполнителей», что позволяет более эффективно использовать средства наследования ModelMaker без «раздувания» модели.

Кроме того, в меню интеграции имеется пункт Refresh in Model, обеспечивающий повторный импорт текущего модуля. Теперь самое время рассмотреть одно из последствий особенности модели внутреннего кода ModelMaker, о которой я упоминал ранее. Поскольку ModelMaker работает с собственным внутренним программным кодом, а не с внешними файлами исходного кода (пока вы не сгенерируете эти файлы), можно отметить, что могут редактироваться как модель, так и ваши файлы. Это возможно благодаря тому, что модель не синхронизирована с исходными файлами. Когда изменены исходные файлы, а не модель, последнюю можно синхронизировать повторной загрузкой исходных файлов модулей. Но если изменены как модель, так и файлы, ситуация становится более запутанной. К счастью, ModelMaker предлагает солидный набор средств обработки проблем потери синхронности. Более подробно они рассмотрены в разделе «Представление Difference».

Еще одним интересным пунктом меню интеграции является Jump to ModelMaker. При его выборе ModelMaker пытается найти текущее место программного кода в загруженной на его основе модели, активизируя ModelMaker.

Хотя ModelMaker может управляться из Delphi, интеграция является двунаправленной. Так же как и меню ModelMaker в IDE Delphi, в ModelMaker существует меню Delphi. В этом меню представлены команды, позволяющие переходить с выбранного в настоящий момент элемента на соответствующее место в файле исходного программного кода, а также команды, «заставляющие» Delphi выполнить синтаксическую проверку, компиляцию или компоновку. Таким образом можно редактировать, генерировать и компилировать программный код, не выходя из ModelMaker.

Управление моделью кода

А сейчас рассмотрим реальный механизм кодирования с помощью ModelMaker. Благодаря объектной природе модели внутреннего кода ModelMaker редактирование элементов модели кода обычно становится более наглядным процессом, чем в Delphi. Например, редактирование свойств класса выполняется посредством диалогового окна Property Editor (рис. 11.6). Это является одним из самых лучших примеров автоматизации в ModelMaker. При добавлении нового свойства не нужно беспокоиться о проблемах добавления частных полей состояния, методах read и write или даже объявлении свойства. Все, что необходимо сделать, — это выбрать соответствующие настройки в редакторе, a ModelMaker создаст необходимые члены класса. Выигрыш здесь даже больше, чем от использования функции Class Completion в IDE Delphi.

рис. 11.6. Property Editor

Обратите внимание, что атрибуты свойства, которые обычно приходится вводить вручную, представлены в диалоговом режиме различными элементами управления. Спецификации Visibility, Type, Read, Write и т.д. управляются редактором. Преимущество имеется и в области регенерации (не говоря уже об избавлении от выполнения повторяющихся задач ввода). Например, поскольку ModelMaker в своей модели кода управляет свойством как объектом, любое изменение в свойств (изменение его типа, например) также приведет к тому, что ModelMaker применит это изменение к любым ссылкам, которые он знает. Если позже возникнет необходимость изменить доступ чтения из поля в метод, эти изменения можно произвести в редакторе, a ModelMaker позаботится о добавлении get-метода и изменении объявления свойства. И самое замечательное: если вы решите переименовать свойство или переместить его в другой класс, а это свойство владеет собственными членами классами, то и они будут автоматически переименованы или перемещены.

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

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

Редактор Unit Code Editor

ModelMaker включает два редактора: редактор, реализующий методы классов (рассматриваемый ранее), и редактор Unit Code Editor (редактор кода модуля), который требует некоторого пояснения. ModelMaker является средством, ориентированным на классы/объекты. Его удобные функциональные возможности относятся к управлению программным кодом уровня класса. Когда он становится программным кодом, не относящимся к классу (объявлением типов, не являющихся классами, объявлением метаклассов, методами модуля, переменными и т.д.), ModelMaker использует неэлегантный подход. При импортировании модуля все, что может войти в модель кода, обрабатывается, а то, что выходит за эти рамки, помещается в Unit Code Editor. (Зачастую, особенно у новичков, сюда попадает и документация (Особый вид комментариев, осуществляющий более подробное описание.), не помещенная в реализацию методов, но ModelMaker может также обратно воспроизвести документацию. Об этом чуть позже.)

Вот пример того, что может оказаться в редакторе Unit Code Editor:
unit <!UnitName!>;

interface

uses
  SysUtils, Windows, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, Dates, StdCtrls;

type
MMWIN: CLASSINTERFACE TDateForm; ID=37;

var
  DateForm: TDateForm;

implementation

[:$R *.DFM:]

MMWIN:CLASSIMPLEMENTATION TDateForm; ID=37;

end.

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

В рассматриваемом примере обычный текст (plain text) попадается в первой же строке: unit. ModelMaker выдаст это строчное значение «как есть». Следующим идентификационным знаком в этой строке является макрос: <!UnitName!>. Более подробно мы рассмотрим макросы далее. А сейчас достаточно усвоить, что ModelMaker может выполнять подстановку. Б этом случае макрос представляет имя модуля и будет выдан этот текст.

И, наконец, вот пример тега генерации кода, следующий непосредственно за ключевым словом type:
MMWIN: CLASSINTERFACE TDateForm; ID=37;

Здесь тег сообщает ModelMaker о необходимости в данном месте модуля кода «раскрыть» интерфейс класса TDateForm.

Таким образом, при редактировании кода в Unit Code Editor вы видите гибрид управляемого вами кода и код, обслуживаемый ModelMaker. Будьте внимательны при редактировании этого кода: не распространяйте код, обслуживаемый ModelMaker, за исключением того случая, когда вы четко представляете, что делаете. Это аналогично редактированию кода в DPR-файле, обслуживаемом Delphi (при неосторожности можно быстро столкнуться с проблемами). Тем не менее это именно то место, где вы могли бы добавить объявления типов, не являющихся классам. Это делается так же, как и в среде Delphi, добавлением объявления типа в раздел type этого модуля:

unit <!UnitName!>;

interface

uses
  SysUtils, Windows, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, Dates, StdCtrls;

type
  TmyWeekday = (wdSunday, wdMonday, wdTuesday, wdWednesday,
    wdThursday, wdFriday, wdSaturday);

MMWIN: CLASSINTERFACE TDateForm; ID=37;

var
  DateForm: TDateForm;

implementation

[:$R *.DFM:]

MMWIN:CLASSIMPLEMENTATION TDateForm; ID=37;
end.

В этом примере ModelMaker выдаст объявление типа точно так же, как вы ввели его (в виде обычного текста), а затем «раскроет» объявление класса TDateForm.

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

Редактор Method Implementation Code Editor

Редактор Method Implementation Code Editor (редактор программного кода реализации методов) (рис. 11.7) несколько отличается от Unit Code Editor. Этот редактор занимает до 2/3 экрана. В данном примере я добавил вымышленное свойство с именем MyNewProperty и позволил ModelMaker сгенерировать поле состояния и методы доступа read и write. Метод write в редакторе является активным. Справа от редактора программного кода можно видеть два интересных окна. Расположенное выше «дерево» является «проводником» локального кода: здесь можно управлять локальными переменными и локальными процедурами. Ниже располагается Section List (Список разделов). ModelMaker позволяет разбивать программный код реализации метода на несколько разделов. Частично — это организационное удобство, но, что более важно, оно позволяет управлять определенными разделами кода. Также как ModelMaker может иметь собственные части модели (например, автоматически сгенерированный метод доступа к свойству), он может также иметь собственные разделы кода в пределах метода. Наиболее часто это происходит при использовании ModelMaker для генерации программного кода read или write в методе доступа к свойству. Обратите внимание, что в этом примере первый, третий и пятый разделы имеют пунктирный, красный с белым левый отступ, указывающий то, что они принадлежат ModelMaker. При генерации этого метода программный код будет выдан в указанном здесь порядке, раздел за разделом.

Рис. 11.7. ModelMaker с активной вкладкой Implementation

ВНИМАНИЕ

Большим недостатком создания программного кода с помощью окна Implementation является отсутствие каких-либо форм функции Code Completion, предлагаемых IDE Delphi.


Представление Difference

Как я уже упоминал ранее, можно легко спровоцировать ситуацию, когда модель не синхронизирована с вашими файлами исходного кода. Если редактируются как модель, так и исходные файлы, имеется возможность восстановить файлы на основе модели, перезаписав изменения в исходных файлах. Более того, после этого можно повторно импортировать модули из страха потерять изменения в модели. К счастью, ModelMaker представляет собой один из самых надежных инструментом которые я видел. При обнаружении асинхронности модели пора перейти на вкладку Difference (Разница) (рис. 11.8).

ModelMaker предлагает множество различных способов просмотра отличий. Можно увидеть стандартное сравнение текстовых файлов, отличия во временных отметках или даже сравнение двух выделенных классов модели. Я предпочитаю просматривать структурные отличия (рис. 11.8). ModelMaker временно импортирует исходный фай (представляя его как внутреннюю модель кода) и вместо текста сравнивает импортированный файл с таким же модулем и классами, представленным в модели на уровне объектов и атрибутов. В результате производится более быстрое и более точное сравнение.

Рис. 11.8. Представление Difference

Обратите внимание на значки в «дереве», которые отмечают различия. Красивые угловые скобки (<>), что как модель, так и файл содержат указанный член класса (в данном примере: GetText), но два различных экземпляра. Отличающийся программный код выводится в МЕМО-полях справа. Зеленый плюс (+) сообщает, что указанный член класса существует только в модели и отсутствует в дисковом файле, Синий минус (-) — член класса существует только на диске, но отсутствует в модели. Имея эту информацию, можно выбрать два варианта синхронизации модели. Один из них заключается в использовании возможности повторного импорта выбранного метода (а не всего модуля) из окна Difference.

Этот подход дает понять, что очень важно знать, когда модель стала несинхронной, для того чтобы не перекрывать изменения на диске при повторной генерации исходных файлов. К счастью, ModelMaker предлагает несколько гарантий, которые могут предотвратить такую ситуацию. Одной из них является использование Design Critic (см. раздел «Малоизвестные изюминки» далее в этой главе). При активизации этой функции вкладка Message будет предупреждать об изменении дискового файла:

 


Event Types View

ModelMaker разрешает управление типами событий в представлении Events. Здесь можно редактировать объявления типов событий. Но не забывайте, что новый тип события может существовать во внутренней модели кода ModelMaker и будет отсутствовать в файле исходного кода до тех пор, пока вы не добавите в модуль объявление нового типа события. Наипростейший способ управления этим процессом включается в «перетаскивании» объявления типа события из представления Events в список Unit и помещении пункта в модуль.


Документация и макросы

ModelMaker может стать очень полезным в поддержке документирования программного обеспечения. Вам необходимо усвоить важную концепцию, предшествующую осуществлению этого действия (к счастью, несложного): понятие «документация» в ModelMaker не приравнивается к понятию «комментарий». Не бойтесь, можно делать усложненные комментарии в исходном коде. Для того чтобы заставить Model Maker выдать (или импортировать) эти комментарии, необходимо выполнить ряд шагов. Практически каждый элемент модели (класс, модуль, член, обозначение схемы и т.д.) могут иметь документацию, но ввод документации не приведет к автоматической выдаче этой документации в исходном программном коде. Этот текст будет присоединен к элементу в модели, но чтобы заставить ModelMaker сгенерировать комментарий к исходному программному коду, содержащему эту документацию, требуется приложить дополнительные усилия.


Документация по сравнению с комментариями

Каждый элемент модели программного кода ModelMaker может иметь два типа документации: стандартный, большой блок текста документации, и короткий, строчный (рис. 11.9). В контексте ModelMaker эти тексты могут служить многим целям и, как уже отмечалось ранее, вовсе не тождественны комментариям исходного программного кода, хотя на их основе могут быть произведены такие комментарии.

Рис. 11.9. Вкладка Documentation идентификатора Class Symbol

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

Обратитесь к диалоговому окну параметров проекта, выбрав пункт Project Options в меню Options (Параметры), а затем перейдите на вкладку Source Doc Generation. Здесь вы найдете много параметров, касающихся генерации комментариев исходного программного кода на основе документации ModelMaker. (Подробности см. в онлайновой справочной системе ModelMaker.) Для просмотра процесса добавления комментариев в исходный код установите параметр Before Declaration (Перед объявлением) в разделе Method Implementation (Реализация метода) в группе In Source Documentation Generation. Теперь любые методы, содержащие документацию, для генерации комментариев исходного программного кода будут использовать стандартный макрос.

ModelMaker также может импортировать комментарии от исходного модуля и связывать их с соответствующими элементами модели программного кода. Для этого необходимо указать ваши комментарии с помощью Documentation Import Signature (вкладка Source Doc Import диалогового окна Project Options) и сообщить ModelMaker, какие строки надо импортировать в модель. Таким образом, если реализация метода имеет комментарии, подобные представленным ниже, то вы можете заставить ModelMaker игнорировать первые пять строк и импортировать только действительный текст комментария:

[:****************************************************
TyClass: DoSomething
Returns: String
Visibility: Public
Coment:
Это действительный комментарий, который мы хотим импортировать в ModelMaker. Первые пять строк этого блока комментария не должны импортироваться в модель.:]

При настройке ModelMaker на комментирование исходного кода важно избежать сдвига комментариев (comment creep). Это может произойти при неточном совпадении настроек импорта и экспорта строк. Например, если макрос, контролирующий исходный комментарий, для импортирования в текст документации берет 6 строк, а настройки импорта допускают только 5 строк, то каждый цикл импорта/генерации будет добавлять в комментарий лишнюю строку.


Работа с макросами

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

Этот процесс вы уже видели в действии в редакторе Unit Code Editor: <!UnitName!> во время генерации кода заменяется на действительное имя генерируемого модуля. Это пример объектного макроса, который всегда различный, и определяется в зависимости от того, какой модуль генерируется. Макрос UnitName является предопределенным, но результат всегда будет иной, в зависимости от контекста.

В состав ModelMaker входит множество предопределенных макросов (их полный список можно найти на с. 75 руководства пользователя в файле usermanual620.pdf, помещенном на компактдиске Delphi). С помощью вкладки Macros имеется возможность создавать собственные макросы различной сложности (даже вложенные). Кроме того, можно перекрывать некоторые расширенные макросы документирования. Например, если имеется документация реализации метода, но нет макроса, то для генерации комментариев ModelMaker будет использовать встроенный макрос. Однако если вы объявите и определите макрос с именем MemberImpDoc, то ModelMaker при генерации комментариев метода будет использовать именно этот макрос. (Список допускающих перекрытие макросов, используемых для генерации комментариев исходного программного кода, можно найти в онлайновой справочной системе в разделе «Documentation Macros».)

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


Регенерация программного кода

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

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

Отличным примером снова является свойство класса. Если имеется свойство, названное MyNewProperty c «обслуживающими» его методами чтения/записи (поддерживаемые ModelMaker и называемые GetMyNewProperty и SetMyNewProperty), а вам надо переименовать это свойство в MyProperty, то для этого необходимо выполнить лишь одну операцию: переименовать свойство. ModelMaker позаботится об остальном: методы доступа будут автоматическим переименованы в GetMyProperty и SetMyProperty. Если свойство представлено в схеме, то схема автоматически будет обновлена. Одна предосторожность: автоматически ModelMaker не ищет в коде экземпляры MyNewProperty. Это необходимо сделать самостоятельно с помощью глобального поиска и замены. Это простой пример, но он иллюстрирует, как ModelMaker упрощает задачу регенерации; как только вы переместите или переименуете элементы кода, ModelMaker выполнит обработку большинство деталей за вас. А теперь давайте рассмотрим некоторые особенности.

Simple Renaming

Simple Renaming (Простое переименование). Эта задача достаточно простая, и мы ее уже касались, но ее полезность невозможно переоценить. Изменения имен элементов модели программного кода распространяются ModelMaker посредством модели кода на все экземпляры элементов, о которых он знает.

Reparenting Classes

Reparenting Classes (изменение родственных связей классов). Этот до смешного простой процесс может быть выполнен несколькими различными способами. Самый распространенный: можно просто перетащить класс в представлении классов (Classes) из одного родительского узла в другой (это можно также выполнить на схеме классов перетаскиванием стрелки обобщения от старого родителя к новому) — теперь класс будет иметь нового родителя. При включенном ограничении наследования ModelMaker автоматически обновит унаследованные объекты дочерних классов для того, чтобы они соответствовали объявлениям нового родителя. В следующий раз, когда будет произведена генерация программного кода, эти изменения будут автоматически учтены.

Moving Classes between Units

Moving Classes between Units (перемещение классов между модулями). Также достаточно легко переместить класс в новый модуль. В представлении модулей (Units) перетащите класс из текущего места в новый модуль. Весь относящийся к этому классу код (объявления, реализации и комментарии) будут восстановлены в новом модуле.

Moving Members between Classes

Moving Members between Classes (Перемещение членов между классами). В контексте регенерации этот процесс известен как «перемещение возможностей (или ответственности) между объектами». Идея проста: по мере разработки может выясниться, что некоторые обязанности (реализуемые как методы класса) более разумно передать в другой класс. Это можно сделать с помощью технологии «drag and drop». В представлении Classes выберите из списка членов желаемый член класса и «перетащите» его в новый класс (для выполнения перемещения вместо копирования удерживайте нажатой клавишу Shift). Converting Members

Converting Members (Преобразование членов). Это одна из очень удачных функции регенерации. Щелчок правой кнопкой на члене в списке членов (Member List) выведет контекстное меню, содержащее пункт Convert То (Преобразовать в). Выбор одного из его подпунктов позволяет преобразовать существующий элемент класса из одного типа в другой. Например, если имеется частное поле FMylnteger, а вы предпочитаете преобразовать его в свойство, ModelMaker автоматически создаст public-свойство с именем Mylnteger, осуществляющее чтение и запись в FMylnteger. Более того, это поле можно преобразовать в метод: он станет частной функцией с именем Mylnteger, возвращающей целое значение.

Restricted Inheritance

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

Если у вас имеется опыт регенерации (или вы знакомы с последними версиями JRuilder), то данный набор функциональных возможностей может показаться не очень впечатляющим. Однако по сравнению с тем, что имеется в Delphi, это — прекрасная коллекция возможностей. Кроме того, API OpenTooLs продукта ModelMaker дают доступ к большинству моделей кода. Если вы не удовлетворены тем, что предлагает базовая поставка ModelMaker, вы можете расширить ее самостоятельно.

СОВЕТ

Помимо прочего, по секрету могу сказать, что я видел бета-версии (во время написания этих строк) будущих выпусков ModelMaker, содержащие набор новых средств. Большинство из них взяты из книги Мартина Фолера (Martin Fowler) и являются очень удачными.


Применение шаблонов дизайна

ModelMaker вкладывает все свое обаяние в поддержку шаблонов дизайна. (Полное описание шаблонов выходит за рамки данной главы, однако если вы не слишком хорошо знакомы с шаблонами, то для краткого ознакомления с ними предварительно прочитайте вставку «Design Patterns 101».) ModelMaker обеспечивает удобство применения шаблонов одним щелчком мыши. В зависимости от выбранного шаблона допускается большое разнообразие действий. Некоторые шаблоны перед добавлением программного кода запускают мастера, а другие просто добавляют свои члены в выбранный класс. Как я уже упоминал ранее, новые члены принадлежат ModelMaker и могут быть легко преобразованы в результат. Кроме того, если вы решите отказаться от использования шаблона, то ModelMaker удалит все члены добавленные в данный шаблон.

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

type
  TOneTimeData - class (TObject)
  private
    FGlobalCount: Integer;
    procedure SetGlobalCount(const Value: Integer);
  public
    property GlobalCount: Integer read FGlobalCount write SetGlobalCount;
  end;

Шаблон Singleton дает поручение использовать только одну точку входа (функция класса Instance в реализации этого шаблона в ModelMaker) для получения доступа к единственному экземпляру класса. Если такого экземпляра не существует, он будет создан и предоставлен в качестве результата; в противном случае будет предоставлен существующий экземпляр. Поскольку Instance является точкой входа, вы должны запретить использование метода Create в отношении данного класса. После того как будет применен шаблон Singleton, ваш класс в ModelMaker npимет следующий вид:

type
  TOneTimeData = class (TObject)
  private
    FGlobalCount: Integer;
    procedure SetGlobalCount(const Value: Integer);
  protected
    constructor CreateInstance;
    class function AccessInstancetRequest: Integer): TOneTimeData;
  public
    constructor Create;
    destructor Destroy: override;
    class function Instance: TOneTimeData;
    class procedure ReleaseInstance;
    property GlobalCount: Integer read FG1obalCount write SetGlobalCount;
  end;

Я не буду приводить здесь реализации методов; их можно просмотреть либо самостоятельным применением шаблона, либо загрузив исходный код примера PatternDemo.

ВНИМАНИЕ

Программный код, используемый ModelMaker для реализации шаблона Singleton, основан на интересном использовании констант в методе для имитации данных класса. Этот программный код будет давать сбой при компиляции до тех пор, пока вы не включите параметр компилятора Assignable Typed Constants Delphi, который по умолчанию сброшен.

Design Patterns 101

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

Выполняя поиск различных проблем в конструкторских решениях различных людей, можно обратить внимание на схожесть и общность элементов. Шаблон — это знание таких общих конструкций, выраженное стандартизированным образом, и достаточно абстрактное, что позволяет применять его для множества различных ситуаций. Шаблон в большей степени связан с повторным использованием дизайна, а не с повторным использованием программного кода. Хотя готовые решения на основе шаблона могут вдохновить программиста, его реальная суть заключается в дизайне: даже если вам придется повторно переписать программный код, начиная с ясного и проверенного дизайна, это позволит сохранить массу времени. Шаблоны не охватывают первичные «строительные кирпичики» (такие, как равномерно распределенная таблица или связанный список) или проблемы, зависящие от конкретной прикладной области (чем занимаются анализаторы шаблонов).

Формальный автор механизма шаблонов был не разработчиком программного обеспечения, а архитектором, который обратил внимание на использование шаблонов в строениях. «Каждый шаблон описывает проблему, возникающую в среде снова и снова, а затем описывает ядро решения для этой проблемы таким образом, что это решение можно использовать миллионы раз, не повторившись ни разу». Основоположниками шаблонов в мире программирования были Эрик Гамма (Erich Gamma), Ричард Хэлм (Richard Helm), Ральф Джонсон (Ralph Johnson) и Джон Влиссайдс (John Vlissides), которые написали книгу Design Patterns: Elements of Reusable Object-Oriented Software (Addison-Wesley, 1995). Авторы часто использовали псевдоним «Gamma et al.», но более часто именовались как Gang of Four (Банда четырех) или просто GoF. В разговоре эта книга обычно упоминается как «GoF book».

В ней описаны идеи шаблонов программирования, указаны точные пути их описания и предоставлен каталог из 23 шаблонов, разделенных на три группы: создающие, структурные и поведенческие. Большинство шаблонов GoF реализованы на языке C++, а некоторые на языке Smalltalk, хотя они абстрагируются от языка и в той же мере пригодны для Java или Delphi.

В ядре структуры шаблона:
  • имя шаблона (pattern name) очень важно, с его помощью можно обращаться к имени шаблона при общении с другими программистами и разработчиками;
  • проблема (problem) определяет, когда применяется шаблон; в конечном счете включая контекст и условия;
  • решение (solution) определяет части элементов и их взаимоотношения. Оно не является реализацией, а лишь абстрактным описанием ответственности и сотрудничества классов.
  • выводы (consequences) — это результат и компромиссы применения шаблона, включая пространственные и временные ограничения.

В настоящее время нет других книг, охватывающих вопросы шаблонов с точки зрения Delphi. Однако имеется множество статей в Delphi-журналах (включая Delphi Informant и The Delphi Magazine). Классические шаблоны GoF, совместно с подробным обсуждением шаблонов в документации ModelMaker, послужили источником вдохновения для множества статей (загляните в Интернет).

Я не всегда согласен с Delphi-реализацией некоторых стандартных шаблонов. Фактически, я стремился сконцентрироваться на нижестоящем дизайне и том, как он может быть сохранен при переходе от GoF-реализации (как правило, на C++ или Java) к Delphi, и расширить специфические языковые возможности. Другие авторы стремятся к переносу программного кода, который является единственным способом реализации дизайна. Важность изучения шаблонов заключается в том, что они обеспечивают общий язык для общения с другими программистами, а также могут использоваться для изучения более удачных способов применения ОПП-технологий (особенно инкапсуляции и низкоуровневого связывания). В качестве заключительной подсказки примите во внимание, что большинство шаблонов в Delphi реализуются с помощью интерфейсов лучше, чем с помощью классов (что стремится сделать ModelMaker, следуя классическому подходу).

ModelMaker предлагает реализацию ряда дополнительных шаблонов, включая Visitor, Observer, Wrapper, Mediator и Decorator. Они жестко запрограммированы в ModelMaker и применяются строго определенным образом. Некоторые реализации оказались несколь-ко лучше, чем остальные. Это было точкой раздора между некоторыми разработчиками, и по этой причине (помимо прочих) ModelMaker поддерживает другое средство приме-нения шаблонов: шаблоны кода (будут рассмотрены в следующем разделе). Этот по-дход обеспечивает создание и настройку со стороны разработчика. Даже не учитывая расширенную поддержку со стороны ModelMaker; они довольно хороши, и предлагают фиксированную, цельную, рабо- тающую, основанную на Delphi реализацию основных проблем.

Шаблоны программного кода

Еще одной мощной функциональной возможностью ModelMaker (которая кажется потерянной, скрытой за миллиардами других удобств) являются шаблоны программного кода — технология, которая может использоваться для создания собственной реализации шаблонов дизайна. Шаблоны кода подобны снимку части класса, который может быть применен к другому классу. Другими словами, это коллекция членов класса, сохраненных в шаблоне, который может быть добавлен к другому классу. Кроме того, эти шаблоны могут иметь параметры (как макросы), которые могут относиться к классу. Будет появляться диалоговое окно, требующее заполнить некоторые значения, которые впоследствии будут применены к части шаблона.

Одним из примеров является свойство массива. Объявление свойства массива в ModelMaker достаточно простое, но его полная реализация требует нескольких шагов: необходимо иметь не только само свойство массива, но и TList, или наследников, для размещения элементов массива, а также средство, осуществляющее учет хранимых элементов. Даже в этом простом примере потребуется приложить некоторые усилия. Введите шаблон свойства массива. Откройте в ModelMaker модель (или создайте новую модель и добавьте в нее наследника класса TObject), а также выберите класс, в который вы хотели бы добавить новое свойство массива. Щелкните правой кнопкой в списке членов (Member List) и выберите пункт Code Templates (шаблоны кода). Должна появиться плавающая панель инструментов Code Templates (обратите внимание, что точно такая же панель доступна на вкладке Patterns). Щелкните на кнопке Apply Array Property Template (применить шаблон свойства массива) для открытия диалогового окна Code Template Parameters (параметры шаблона кода). Оно содержит список параметров, которые можно указать для применяемого шаблона (рис. 11.10). Можно выделить любой пункт в левом столбце и нажать клавишу F2 для редактирования значения этого параметра. Оставьте значения по умолчанию и щелкните на кнопке ОК.

Рис. 11.10. Диалоговое окно параметров шаблона кода ModelMaker

Теперь в вашем классе появятся следующие члены:
private
  FItems: TList;
protected
  function GetItemCount: Integer;
  function GetItems(Index: Integer): TObject;
public
  property ItemCount: Integer read GetItemCount;
  property Items[Index: Integer]: TObject read GetItems;

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

Для создания собственного шаблона кода начнем с существующего класса, который уже содержит члены, которые вы хотите включить в шаблон. Выберите этот класс, а затем в списке Member List выберите члены, которые вы хотите использовать (это могут быть члены любого типа). Щелкните правой кнопкой в Member List и выберите пункт Create Code Template; появится диалоговое окно Save Code Template. Оно похоже на стандартное окно Save As (и вы должны указать, куда сохранить шаблон), но вы также можете уточнить, как должен быть представлен шаблон. Укажите имя шаблона и страницу палитры шаблонов, на которой он должен быть размещен. Обратите внимание на появляющееся при этом сообщение подтверждения; при желании можно изменить значок.

Новый шаблон теперь доступен в палитре шаблонов; его можно добавлять в любой класс. Для задания параметров шаблона необходимо изменить PAS-фапл, который был создан при сохранении шаблона. Например, вот часть файла ArrayProp_List.pas шаблона Array Property:

unit ArrayProp_List;

//DEFINEMACRQ:Items=name of array property
//DEFINEMACRO:TObject=type of array property
//DEFINEMACRO:ItemCount-Method returning # items
//DEFINEMACRO:FItems=TList Field storing items

  TCodeTemplate = class (TObject)
  private
    <!FItems!>: TList;
  protected
    function Get<!ItemCount!>: Integer;
    function Get<!Items!>(Index; Integer): <!TObject!>;
  public
    property <!ItemCount!>: Integer read Get<!ItemCount!>;
    property <!Items!>[Index: Integer]: <!TObject!> read Get<!Items!>;
end;

Обратите внимание на строчки, которые начинаются с //DEFINEMACRO. Это то место, где должны быть определены ваши параметры; они будут представлены: в диалоговом окне Code Template Parameters, которое вы видели ранее. Каждая строчка — это пара имя/значение (Name/Value): элемент слева от знака = является редактируемым значением, а элемент справа — задаваемым вами объяснением преденазначения этого параметра.

После предоставления списка параметров они могут быть использованы в шаблоне кода в качестве макросов. Обратите внимание на строчки типа:

property <!Items!>[Index: Integer]: <!TObject!> read Get<!Items!>;

Когда это свойство будет добавлено в класс как часть шаблона, эти макросы (подобно <!Items!>) будут заменены значением соответствующего параметра. Таким образом можно использовать параметры для более глубокой настройки шаблонов программного кода.

Малоизвестные изюминки

И на прощание хотелось бы представить список интересных особенностей, с которыми вам, возможно, захотелось бы познакомиться более близко:

Rethink Orthogonal

С помощью сочетания клавиш Ctrl+O имеется возможность изменить используемые по умолчанию в редакторе схем прямые диагональные линии на вертикальные и горизонтальные ломаные. Также можно заставить ModelMaker попытаться найти кратчайшую ломаную, нажав Shift+Ctrl+O.

Visual Styles Manager

Этот диспетчер (доступный из контекстного меню представления схемы в пункте Visual style ► Style manager) достоин целого раздела. Не пожалейте некоторого времени, чтобы познакомиться с его работой. Вы можете определить широкое разнообразие иерархически связанных визуальных стилей для обозначений схемы и применять их «на лету». Кроме того, не забудьте также щелкнуть на кнопке Use Printing Style в редакторе схем (Diagram Editor) для разрешения вывода непечатаемых символов и просмотреть, как схема будет выглядеть на бумаге.

Design Critics

Design Critics — это выразительная QA-особенность в ModelMaker. Design Critics (критики дизайна) представляют собой небольшие корректоры, запускаемые в фоновом режиме и проверяющие ваш программный код. Для их использования убедитесь, что включено окно Show Messages (Shift+Ctrl+M), щелкните правой кнопкой на представлении Messages и выберите пункт Show Critics Manager. Я не рекомендую отключать design critic проверки временной отметки, поскольку он может предупредить вас в случае, если исходный файл на диске изменен не с помощью ModelMaker. Кроме того, с помощью API OpenTools продукта ModelMaker можно создать и собственные design critic.

Creational Wizard

Это еще одна замечательная возможность некоторой автоматизации для постоянно занятого Delphi-программиста. Мастер Creational Wizard (доступный с помощью кнопки Wizards списка Member List) проверяет модель на члены класса, которые нужны в настоящий момент или свободны, и добавляет их в соответствующий конструктор или деструктор. Кроме того, он выполнит и другую работу и представит предупреждения; для обращения к онлайновой справочной системе, находясь в мастере, нажмите F1.

API Open Tools

Так же как API Tools среды Delphi, эта функциональная возможность разрешает создание встраиваемых экспертов для ModelMaker. API-интерфейс является надежным и включает доступ к схемам, а также ко всей модели программного кода. Здесь возможности расширения ModelMaker неограничены.