Rational Rose для розробників. Частина 3, CASE-засоби (моделювання), Програмування, статті

Частина 2

“Сім раз виправ, – десять налагодити …” –
улюблене заняття розробника …


Загальне


У попередніх частинах статті ми досить багато часу приділили такому потужному інструменту як Rational Rose, причому намагалися розгледіти даний продукт очима розробника (постановника). Досить докладно розглянули процес проектування як прямого, так і зворотного на мові С + +. Природно, що не вдалося покрити повністю всі можливості пакета, так як в цьому випадку довелося б писати цілу книгу. На жаль, під час написання третьої частини цієї статті (такий же описової як і всі попередні) вийшла в світ російською мовою чудова книга з проектування та кодогенераціі (“UML і Rational Rose “. У. Боггс, М. Боггс. Дану книгу можна придбати в нашому магазині www.itshop.ru). Стало бути 3 частина буде останньою описовою частиною …


Інші частини плануються вже не в описовому форматі, а в проблематичному; кожна стаття буде заснована на конкретній проблемі проектування або аналізу, а також взаємодії Rational Rose з іншими продуктами компанії Rational. Наприклад, в одній з найближчих частин ми торкнемося інтеграцію Rose з ClearCase і Requisite Pro. Також чекає свого низка стаття по інтеграції з Visual Studio.


Складні матерії


Тут ми вже не будемо так прискіпливо проводити кодогенерацію, як у попередніх частинах. Основний упор буде поставлений на образотворчі можливості інструменту при моделюванні, оскільки функція спадкування (Річ сама по собі дуже цікава) досить банальна сама по собі і не вимагає особливого розуміння і підходу. Проста річ – просте дію. Давайте спробуємо торкнутися більш складні маніпуляції з класами.

Для початку коротко проаналізуємо можливості Rational Rose в генерації і візуалізації різних асоціацій, зв’язків і класів.


Односпрямовані асоціації


Для створення подібної зв’язку Rose генерує спеціальні атрибути. Природно, що при подібній асоціації зв’язок генерується тільки для одного класу. При цьому Rose генерує закритий атрибут (Private). В іншому генерація відбувається так само як і у спадкуванні (зв’язок показується стрілкою Unidirectional Association). Нижче показана картинка відносини і код, що згенерував Rose (далі в статті також буде використовуватися такий самий підхід: опис зв’язку, малюнок зв’язку, згенерований файл заголовка).

Рисунок 1
ФАЙЛ NEWSTRING.H

//## begin module%1.3%.codegen_version preserve=yes
// Read the documentation to learn more about C++ code generator
// versioning.
//## end module%1.3%.codegen_version
//## begin module%39FD296801A9.cm preserve=no
// %X% %Q% %Z% %W%
//## end module%39FD296801A9.cm
//## begin module%39FD296801A9.cp preserve=no
//## end module%39FD296801A9.cp
//## Module: NewString%39FD296801A9; Pseudo Package specification
//## Source file: C:Program FilesRational2RoseC++sourceNewString.h
#ifndef NewString_h
#define NewString_h 1
//## begin module%39FD296801A9.additionalIncludes preserve=no
//## end module%39FD296801A9.additionalIncludes
//## begin module%39FD296801A9.includes preserve=yes
//## end module%39FD296801A9.includes
// String
#include “String.h”
//## begin module%39FD296801A9.additionalDeclarations preserve=yes
//## end module%39FD296801A9.additionalDeclarations
//## begin NewString%39FD296801A9.preface preserve=yes
//## end NewString%39FD296801A9.preface
//## Class: NewString%39FD296801A9
//## Category: <Top Level>
//## Persistence: Transient
//## Cardinality/Multiplicity: n
class NewString
{
//## begin NewString%39FD296801A9.initialDeclarations preserve=yes
//## end NewString%39FD296801A9.initialDeclarations
public:
//## Constructors (generated)
NewString();
NewString(const NewString &right);
//## Destructor (generated)
~NewString();
//## Assignment Operation (generated)
NewString & operator=(const NewString &right);
//## Equality Operations (generated)
int operator==(const NewString &right) const;
int operator!=(const NewString &right) const;
//## Get and Set Operations for Associations (generated)
//## Association: <unnamed>%39FD2A2602A7
//## Role: NewString::<the_String>%39FD2A270212
const String * get_the_String () const;
void set_the_String (String * value);
// Additional Public Declarations
//## begin NewString%39FD296801A9.public preserve=yes
//## end NewString%39FD296801A9.public
protected:
// Additional Protected Declarations
//## begin NewString%39FD296801A9.protected preserve=yes
//## end NewString%39FD296801A9.protected
private:
// Additional Private Declarations
//## begin NewString%39FD296801A9.private preserve=yes
//## end NewString%39FD296801A9.private
private: //## implementation
// Data Members for Associations
//## Association: <unnamed>%39FD2A2602A7
//## begin NewString::<the_String>%39FD2A270212.role preserve=no public: String { -> RHN}
String *the_String;
//## end NewString::<the_String>%39FD2A270212.role
// Additional Implementation Declarations
//## begin NewString%39FD296801A9.implementation preserve=yes
//## end NewString%39FD296801A9.implementation
};
//## begin NewString%39FD296801A9.postscript preserve=yes
//## end NewString%39FD296801A9.postscript
// Class NewString
//## Get and Set Operations for Associations (inline)
inline const String * NewString::get_the_String () const
{
//## begin NewString::get_the_String%39FD2A270212.get preserve=no
return the_String;
//## end NewString::get_the_String%39FD2A270212.get
}
inline void NewString::set_the_String (String * value)
{
//## begin NewString::set_the_String%39FD2A270212.set preserve=no
the_String = value;
//## end NewString::set_the_String%39FD2A270212.set
}
//## begin module%39FD296801A9.epilog preserve=yes
//## end module%39FD296801A9.epilog
#endif


Двонаправлені асоціації


Це ускладнений аналог попередньої зв’язку, під час виконання якої генеруються посилання на обидва використовуваних класу. Візуально асоціація показується простий лінією Association.

Рисунок 2


Нижче показані тільки фрагменти двох класів, з упором на сгенерированную асоціацію.


ФАЙЛ STRING.h


*
*
*
private: //## implementation
// Data Members for Associations
//## Association: <unnamed>%39FD2E8E00AA
//## begin String::<the_NewString>%39FD2E8E0399.role preserve=no public: NewString { -> RHN}
NewString *the_NewString;
//## end String::<the_NewString>%39FD2E8E0399.role
// Additional Implementation Declarations
//## begin String%39FD295103B9.implementation preserve=yes
//## end String%39FD295103B9.implementation
*
*
*


ФАЙЛ NEWSTRING.h


*
*
*
private: //## implementation
// Data Members for Associations
//## Association: <unnamed>%39FD2E8E00AA
//## begin NewString::<the_String>%39FD2E8E03A3.role preserve=no public: String { -> RHN}
String *the_String;
//## end NewString::<the_String>%39FD2E8E03A3.role
// Additional Implementation Declarations
//## begin NewString%39FD296801A9.implementation preserve=yes
//## end NewString%39FD296801A9.implementation
*
*
*


Асоціація “один до багатьох”


Даний вид асоціацій також представляє особливу цінність при проектуванні класів. Множинність асоціації задається в властивостях зв’язку (пункти Role A Detail і Role B Detail. Де крім ролей можна задати і специфічні атрибути конкретної асоціації, ну, скажімо, дати їй назву. Рис. 3 показує скріншот даного вікна). Рисунок 4, в свою чергу, демонструє зовнішній вигляд даної асоціації. ФАЙЛ STRING.h

Рисунок 3

Рисунок 4


Як видно з фрагментів коду, ми отримали як і в попередніх випадках, посилання на клас, в той той час як для іншого класу був використаний контейнер. За замовчуванням Rational Rose не надає реалізацію контейнерного класу. Замість нього генерується код з UnboundedSetByReference як контейнерного. Вказівка ​​ж конкретного контейнерного класу – справа самого розробника.


ФАЙЛ STRING.h


*
*
*
private: //## implementation
// Data Members for Associations
//## Association: <unnamed>%39FD300C00A9
//## begin String::<the_NewString>%39FD300C033E.role preserve=no
public: NewString {n -> 1RHN}
NewString *the_NewString;
//## end String::<the_NewString>%39FD300C033E.role
// Additional Implementation Declarations
//## begin String%39FD295103B9.implementation preserve=yes
//## end String%39FD295103B9.implementation
*
*
*


ФАЙЛ NEWSTRING.h


*
*
*
private: //## implementation
// Data Members for Associations
//## Association: <unnamed>%39FD300C00A9
//## begin NewString::<the_String>%39FD300C0348.role preserve=no
public: String {1 -> nRHN}
UnboundedSetByReference<String> the_String;
//## end NewString::<the_String>%39FD300C0348.role
// Additional Implementation Declarations
//## begin NewString%39FD296801A9.implementation preserve=yes
//## end NewString%39FD296801A9.implementation
*
*
*


Зв’язок “багато до багатьох”


Даний приклад практично аналогічний попередньому з тією лише різницею, що генерується подвійний зв’язок: контейнерні класи на обох кінцях.


Асоціації з обмеженою множинністю


Даний вид асоціацій представляє логічне продовження попереднього типу асоціацій, але на відміну від нього має строго обмежена кількість зв’язків (обмеження по діапазону). Рисунок 5 показує модель подібного взаємини класів

Рисунок 5


Код виходить таким: ФАЙЛ STRING.h


//## begin module%1.3%.codegen_version preserve=yes
// Read the documentation to learn more about C++ code generator
// versioning.
//## end module%1.3%.codegen_version
//## begin module%39FD295103B9.cm preserve=no
// %X% %Q% %Z% %W%
//## end module%39FD295103B9.cm
//## begin module%39FD295103B9.cp preserve=no
//## end module%39FD295103B9.cp
//## Module: String%39FD295103B9; Pseudo Package specification
//## Source file: C:Program FilesRational2RoseC++sourceString.h
#ifndef String_h
#define String_h 1
//## begin module%39FD295103B9.additionalIncludes preserve=no
//## end module%39FD295103B9.additionalIncludes
//## begin module%39FD295103B9.includes preserve=yes
//## end module%39FD295103B9.includes
// NewString
#include “NewString.h”
//## begin module%39FD295103B9.additionalDeclarations preserve=yes
//## end module%39FD295103B9.additionalDeclarations
//## begin String%39FD295103B9.preface preserve=yes
//## end String%39FD295103B9.preface
//## Class: String%39FD295103B9
//## Category: <Top Level>
//## Persistence: Transient
//## Cardinality/Multiplicity: 1
class String
{
//## begin String%39FD295103B9.initialDeclarations preserve=yes
//## end String%39FD295103B9.initialDeclarations
public:
//## Constructors (generated)
String();
String(const String &right);
//## Destructor (generated)
~String();
//## Assignment Operation (generated)
String & operator=(const String &right);
//## Equality Operations (generated)
int operator==(const String &right) const;
int operator!=(const String &right) const;
//## Get and Set Operations for Associations (generated)
//## Association: <unnamed>%39FD300C00A9
//## Role: String::<the_NewString>%39FD300C033E
const NewString * get_the_NewString () const;
void set_the_NewString (NewString * value);
// Additional Public Declarations
//## begin String%39FD295103B9.public preserve=yes
//## end String%39FD295103B9.public
protected:
// Additional Protected Declarations
//## begin String%39FD295103B9.protected preserve=yes
//## end String%39FD295103B9.protected
private:
// Additional Private Declarations
//## begin String%39FD295103B9.private preserve=yes
//## end String%39FD295103B9.private
private: //## implementation
// Data Members for Associations //## Association: <unnamed>%39FD300C00A9
//## begin String::<the_NewString>%39FD300C033E.role preserve=no
public: NewString {n -> 1RHN}
NewString *the_NewString;
//## end String::<the_NewString>%39FD300C033E.role
// Additional Implementation Declarations
//## begin String%39FD295103B9.implementation preserve=yes
//## end String%39FD295103B9.implementation
};
//## begin String%39FD295103B9.postscript preserve=yes
//## end String%39FD295103B9.postscript
// Class String
//## Get and Set Operations for Associations (inline)
inline const NewString * String::get_the_NewString () const
{
//## begin String::get_the_NewString%39FD300C033E.get preserve=no
return the_NewString;
//## end String::get_the_NewString%39FD300C033E.get
}
inline void String::set_the_NewString (NewString * value)
{
//## begin String::set_the_NewString%39FD300C033E.set preserve=no
the_NewString = value;
//## end String::set_the_NewString%39FD300C033E.set
}
//## begin module%39FD295103B9.epilog preserve=yes
//## end module%39FD295103B9.epilog

#endif


ФАЙЛ NEWSTRING.h


//## begin module%1.3%.codegen_version preserve=yes
// Read the documentation to learn more about C++ code generator
// versioning.
//## end module%1.3%.codegen_version
//## begin module%39FD296801A9.cm preserve=no
// %X% %Q% %Z% %W%
//## end module%39FD296801A9.cm
//## begin module%39FD296801A9.cp preserve=no
//## end module%39FD296801A9.cp
//## Module: NewString%39FD296801A9; Pseudo Package specification
//## Source file: C:Program FilesRational2RoseC++sourceNewString.h
#ifndef NewString_h
#define NewString_h 1
//## begin module%39FD296801A9.additionalIncludes preserve=no
//## end module%39FD296801A9.additionalIncludes
//## begin module%39FD296801A9.includes preserve=yes
//## end module%39FD296801A9.includes
// String
#include “String.h”
//## begin module%39FD296801A9.additionalDeclarations preserve=yes
//## end module%39FD296801A9.additionalDeclarations
//## begin NewString%39FD296801A9.preface preserve=yes
//## end NewString%39FD296801A9.preface
//## Class: NewString%39FD296801A9
//## Category: <Top Level>
//## Persistence: Transient
//## Cardinality/Multiplicity: n
class NewString
{
//## begin NewString%39FD296801A9.initialDeclarations preserve=yes
//## end NewString%39FD296801A9.initialDeclarations
public:
//## Constructors (generated)
NewString();
NewString(const NewString &right);
//## Destructor (generated)
~NewString();
//## Assignment Operation (generated)
NewString & operator=(const NewString &right);
//## Equality Operations (generated)
int operator==(const NewString &right) const;
int operator!=(const NewString &right) const;
//## Get and Set Operations for Associations (generated)
//## Association: <unnamed>%39FD300C00A9
//## Role: NewString::<the_String>%39FD300C0348
const UnboundedSetByReference<String> get_the_String () const;
void set_the_String (UnboundedSetByReference<String> value);
// Additional Public Declarations
//## begin NewString%39FD296801A9.public preserve=yes
//## end NewString%39FD296801A9.public
protected:
// Additional Protected Declarations
//## begin NewString%39FD296801A9.protected preserve=yes
//## end NewString%39FD296801A9.protected
private:
// Additional Private Declarations
//## begin NewString%39FD296801A9.private preserve=yes
//## end NewString%39FD296801A9.private
private: //## implementation
// Data Members for Associations
//## Association: <unnamed>%39FD300C00A9
//## begin NewString::<the_String>%39FD300C0348.role preserve=no
public: String {1 -> nRHN}
UnboundedSetByReference<String> the_String;
//## end NewString::<the_String>%39FD300C0348.role
// Additional Implementation Declarations
//## begin NewString%39FD296801A9.implementation preserve=yes
//## end NewString%39FD296801A9.implementation
};
//## begin NewString%39FD296801A9.postscript preserve=yes
//## end NewString%39FD296801A9.postscript
// Class NewString
//## Get and Set Operations for Associations (inline)
inline const UnboundedSetByReference<String> NewString::get_the_String
() const
{
//## begin NewString::get_the_String%39FD300C0348.get preserve=no
return the_String;
//## end NewString::get_the_String%39FD300C0348.get
}
inline void NewString::set_the_String (UnboundedSetByReference<String>
value)
{
//## begin NewString::set_the_String%39FD300C0348.set preserve=no
the_String = value;
//## end NewString::set_the_String%39FD300C0348.set
}
//## begin module%39FD296801A9.epilog preserve=yes
//## end module%39FD296801A9.epilog

#endif

Рисунок 6


Код спеціально наведений повністю, щоб можна було б оцінити розмах Rose в плані генерації складних зв’язків. Лаконічним завершення даного виду зв’язку можна вважати зв’язок один до …. У нашому випадку 1 до 6


При цьому код буде виглядати наступним чином:


ФАЙЛ NEWSTRING.h


*
*
*
private: //## implementation
// Data Members for Associations
//## Association: <unnamed>%39FD4614028A
//## begin NewString::<the_String>%39FD461502A0.role preserve=no
public: String {1 -> 6RHN}
String *the_String[6];
//## end NewString::<the_String>%39FD461502A0.role
// Additional Implementation Declarations
//## begin NewString%39FD296801A9.implementation preserve=yes
//## end NewString%39FD296801A9.implementation
*
*
*


Таким же чином можна згенерувати будь-який вид зв’язку. Скажімо, розробнику нічого не заважає визначити зв’язок 6 до 6 або 10 до 10. Код, згенерований системою, при цьому буде виглядати як “положено” …


Висновок


При кодогенераціі слід враховувати одне “але”. Все що відбувається за замовчуванням не завжди може влаштувати конкретного раработчіка. Навіть враховуючи те, що інструмент спочатку налаштований на генерацію правильного та якісного коду, все одно Rose вимагає додаткової підстроювання під конкретний проект (реліз.. і пр.)


Потужні виразні властивості в Rational Rose поєднуються з гнучкою системою підказок і налаштувань. Так, наприклад, Rose дозволяє проводити не тільки просту настройку інструментальної панелі (ця можливість стала давно тривіальною, і розглядати її як щось видатне немає необхідності), але і що дуже важливо – налаштовувати на свій розсуд зовнішній вигляд діаграм, для яких відсутня картинка.


Внутрішнє улаштування Rose дозволяє змінювати системний файл “defaultstereotypes.ini”, в якому містяться найменування зумовлених стереотипів з посиланнями на відповідні картинки. Так, якщо користувача не влаштовує картинка, то він спокійно може замінити посилання на свій графічний файл. Правда при цьому слід враховувати, що всі малюнки повинні зберігатися тільки в форматі WMF, і мати довжину не більше 512 байт.



Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*