Download - C++ w Objectivity
C++ w Objectivity
Marcin Michalak s1744
Pomocne pakiety:
Data Definition Language (DDL).
Standard Template Library (STL).
Active Schema.
Data Definition Language (DDL)
W pierwszym kroku rozwijania obiektowo-orientowanej aplikacji definiujemy klasy, które mają zamodelować budowę i zachowania aplikacji. Takie definicje klas powstają z logicznego modelu problemu. W logicznym modelu określamy klasy których instancje będą trwałe i zachodzące pomiędzy nimi relacje. W Objectivity opisywane jest to poprzez schematy (schema). Język definiowania danych (Data Definition Language (DDL)) jest narzędziem które ma to ułatwić. Za jego pomocą możemy:
- Określać klasy z trwałością (persistence-capable classes).
- Definiować powiązania (asocjacje).
- Modyfikować już istniejące klasy.
-Dodawać nowe klasy.
Zaletą DDL jest współdziałanie z c++.
Definicje klas zapisujemy w jednym lub wielu plikach z rozszerzeniem ‘ddl’. Schemat tworzymy przetwarzając te pliki za pomocą „procesora DDL”.
Procesor DDL (1)Procesor DDL dodaje informacje do bazy danych o naszym schemacie. Dodatkowo dla każdego przetwarzanego pliku ‘file.ddl’ generuje pliki źródłowe z kodem w c++:
- Główny plik nagłówkowy:‘file.h’ – zawiera deklaracje i definicje z oryginalnego ‘ddl’ niezbędne dla istnienia opisywanego obiektu.
- Plik nagłówkowy referencji:‘file_ref.h’ – zawiera dodatkowe definicje i klasy niezbędne do obsługi referencji (asocjacji).
- Plik z implementacją metod:‘file_ddl.cpp’ dla Windows’a‘file_ddl.c’ dla UNIX’aZawiera:- Definicje nie włączanych bezpośrednio ‘non-inline’ funkcji
deklarowanych w plikach nagłówkowych. - Kod pozwalający łączyć informacje przetrzymywane jako schemat z obiektami w bazie danych.- Kod odpowiedzialny za rejestrowanie trwałych obiektów.
Procesor DDL (2)Pliki generowane przez DDL:Pliki użytkownika:
Przykładowe możliwości DDL (1)
Można wykorzystywać klasy nie obsługujące trwałości w plikach ‘ddl’.
Klasa z trwałością.
Klasa bez trwałości.
Przykładowe możliwości DDL (2)
Możliwe jest dziedziczenie z klas obsługujących trwałość.
Pliki użytkownika. Pliki generowane przez DDL.
Przykład aplikacji ‘Biblioteka’ (1)
Na podstawie poniższego diagramu została utworzona prosta aplikacja przechowująca obiekty wraz z powiązaniami:
Przykład aplikacji ‘Biblioteka’ (2)Tworzenie schematu poprzez przenoszenie logicznego modelu do plików ‘ddl’:class Book : public ooObj {
private: ooVString author; ooVString title; ooVString subject; char isbn[12]; // isbn is a fixed size
~Book() {}; // books are never deleted
public: Book( const char* title, const char* subject,
const char* author, const char* isbn );
ooHandle(Loan) inLoan <-> hasBook; ooHandle(Library) fromLibrary <-> allBooks[];
// access fns for Book fields const char* get_author() const; const char* get_title() const; const char* get_subject() const; const char* get_isbn() const;
// print fns for Book ostream& print( ostream& = cout ) const; ostream& printInfo( ostream& = cout ) const; ostream& printCheckout( ostream& = cout ) const;};
// access fns for Book fieldsinline const char* Book::get_author() const { return author; }inline const char* Book::get_title() const { return title; }inline const char* Book::get_subject() const { return subject; }inline const char* Book::get_isbn() const { return isbn; }
// ostream operator for Bookinline ostream& operator << ( ostream& os, ooHandle(Book)& book) { return book->print( os ); }
Przykład aplikacji ‘Biblioteka’ (3)
lib.ddllib.cpplib.hlib_ref.hlib_ddl.cpp
Book.ddlBook.cppbook.hbook_ref.hbook_ddl.cpp
Loan.ddlLoan.cpploan.hloan_ref.hloan_ddl.cpp
lib.ddllib.cpp
Book.ddlBook.cpp
Loan.ddl Loan.cpp
ptrn.ddlptrn.cpp
lm.hlmMain.cpp
makefile
ptrn.ddlptrn.cppptrn.hptrn_ref.hptrn_ddl.cpp
lmMain.cpplm.h
makefile
Pliki powstałe po przetworzeniu plików ‘ddl’:
Przed: Po:
Przed przetwarzaniem:-Pliki ‘ddl’ składają się na opis schematu.-Pliki ‘cpp’ zawierają implementacje metod.-Pliki ‘lm.h’ i ‘lmMain.cpp’ składają się na aplikacje.-Plik ‘makefile’ zawiera reguły kompilacji.
Przykład aplikacji ‘Biblioteka’ (4)
ooHandle(Library) library; ooHandle(Book) book; ooHandle(Patron) patron;
// tworzenie nowej biblioteki cout << "Starting Library Information System. New Library:\n"; library = new Library("Campus", "1 Campus Way", "x123"); cout << library->printInfo(cout) << endl;
// dodawanie ksiazki do biblioteki book = new Book("Moby Dick", "Fiction", "Melville", "1234567890"); cout << "Adding Book record to library:\n" << book; library->add_allBooks(book); // add to allBooks relation
book = new Book("The Galloping Gourmet", "Cooking", "Kerr", "2345678901"); cout << "Adding Book record to library:\n" << book; library->add_allBooks(book); // add to allBooks relation
Przykładowe operacje na obiektach:
// dodawanie osoby do biblioteki patron = new Patron("Joe Cool", "Main Dorm #32", "x340"); cout << "Adding Patron record to library:\n" << patron; library->add_hasPatrons(patron); // add to hasPatrons relation
patron = new Patron("Jane Doe", "Campus Apartments #232", "345-6789"); cout << "Adding Patron record to library:\n" << patron; library->add_hasPatrons(patron); // add to hasPatrons relation
// wyszukiwanie książki po ISBN book = library->findBookByISBN("2345678901"); if (book != 0) {
// wypożyczenielibrary->checkoutBook(book, patron, "10/30/93");cout << "Book checked out:\n" << book;
}elsecout << "Book: ISBN# 2345678901 not found\n\n";
// wydruk stanu biblioteki cout << "Exiting Library Information System:\n" << library;
Przykład aplikacji ‘Biblioteka’ (5)
Starting Library Information System. New Library: Name: Campus Address: 1 Campus Way Phone: x123
Adding Book record to library:[Book] Title: Moby Dick Subject: Fiction Author: Melville ISBN: 1234567890 Not checked out.
Adding Book record to library:[Book] Title: The Galloping Gourmet Subject: Cooking Author: Kerr ISBN: 2345678901 Not checked out.
Adding Patron record to library:[Patron] Name: Joe Cool Address: Main Dorm #32 Phone: x340 No Loans
Adding Patron record to library:[Patron] Name: Jane Doe Address: Campus Apartments #232 Phone: 345-6789 No Loans
Book checked out:[Book] Title: The Galloping Gourmet Subject: Cooking Author: Kerr ISBN: 2345678901 Due Date: 10/30/93
Exiting Library Information System:[Library] Name: Campus Address: 1 Campus Way Phone: x123
[Patrons] Name: Joe Cool Address: Main Dorm #32 Phone: x340
Name: Jane Doe Address: Campus Apartments #232 Phone: 345-6789
[Holdings] Title: Moby Dick Subject: Fiction Author: Melville ISBN: 1234567890
Title: The Galloping Gourmet Subject: Cooking Author: Kerr ISBN: 2345678901
[Loans] Name: Jane Doe Address: Campus Apartments #232 Phone: 345-6789 Title: The Galloping Gourmet Subject: Cooking Author: Kerr ISBN: 2345678901 Due Date: 10/30/93
Wynik wygenerowany przez aplikację:
Standard Template Library (STL) (1)
Objectivity/C++ Standard Template Library jest rozszerzeniem elementu ObjectSpace Standards<Toolkit>, wchodzącego w skład pakietu ANSI/ISO C++ Standard Template Library, o trwałość. Umożliwia to przechowywanie pojemników (containers) i stringów STL w Objectivity/DB.
Plik lista.ddl#include <d_list.h>
template class d_list_node<int>;
class SpliceList : public ooObj { public: // Konstruuje _list aby przechowywala wszystkie elementy // z zakresu [’first’, ’last’) SpliceList(const int* first, const int* last) : _list(first, last) {} // atrybut d_list < int, d_allocator<int> > _list; …};
Przykład wykorzystania:
Standard Template Library (STL) (1) cd.
#include <iostream.h>#include „lista.h" // Wygenerowane z lista.ddl{
typedef d_list< int, d_allocator<int> > int_list;
const int myArray1[] = { 2, 8 };const int myArray2[] = { 4, 9 };ooHandle(ooContObj) contH;ooHandle(SpliceList) sourceList, targetList;… // Otwarcie bazy danych i stworzenie nowego
kontenera // contH jest uchwytem do kontenera targetList = new ( contH )
SpliceList(myArray1, myArray1+2);sourceList = new ( contH )
SpliceList(myArray2, myArray2+2);… // Sprawdzenie czy obiekty zostały
utworzone
Kod źródłowy do przykładu użycia STL:
Standard Template Library (STL) (1) cd.
// Wyjęcie elementów z sourceList z zakresu// [sourceList->_list.begin(), sourceList-
>_list.end())// i wstawienie ich na pozycji targetList-
>_list,begin()targetList->_list.splice(
targetList->_list.begin(), sourceList->_list,sourceList->_list.begin(),sourceList->_list.end()
);// Wypisywanie zawartości targetList, za pomocą
iteratoraint_list::const_iterator i;for ( i = targetList->_list.begin(); i !=
targetList->_list.end(); ++i){cout << *i << " ";
}cout << endl;
}
Wynik:4 9 2 8
Active Schema (1)
Pakiet ‘Active Schema’ umożliwia tworzenie narzędzi takich jak przeglądarki klas i obiektów. Aplikacje korzystające ‘Active Schema’ mogą:-Uzyskać opis klas zapisanych w schemacie.-Pobrać i modyfikować trwałe obiekty używając opisów ich klas uzyskiwanych dynamicznie.-Modyfikować ‘schema’ poprzez dodawanie nowych klas i zmianę opisów istniejących.-Dodawać trwałe obiekty do bazy danych (federated database), włączając instancje nowo dodanych klas.-Dokonywać konwersji trwałych obiektów, aby były zgodne ze zmienionym opisem (evolved schema) ich klas.
Active Schema (2)
void showInheritance(const d_Class &aClass) {// Print parent classes, if anyinheritance_iterator itr =
aClass.base_class_list_begin();if (itr != aClass.base_class_list_end()) {
cout << "Parent classes of " << aClass.name();
cout << ":" << endl;while (itr !=
aClass.base_class_list_end()) {const d_Inheritance &curInh = *itr;const d_Class &curParent =
curInh.derives_from();cout << curParent.name();d_Access_Kind access =
curInh.access_kind();if (access == d_PROTECTED) {
cout << " (protected)";}else if (access == d_PRIVATE) {
cout << " (private)";}cout << endl;++itr;
} // End while more parentscout << endl;
} else { // End if any parents
Przykład wykorzystania ‘Active Schema’ do przeglądania dziedziczenia:
Active Schema (2) cd.
cout << aClass.name() << " has no parent classes";
cout << endl << endl;} // End else no parents// Print child classes, if anyitr = aClass.sub_class_list_begin();if (itr != aClass.sub_class_list_end()) {
cout << "Child Classes of " << aClass.name();
cout << ":" << endl;while (itr != aClass.sub_class_list_end())
{const d_Inheritance &curInh = *itr;const d_Class &curChild =
curInh.inherits_to();cout << curChild.name() << endl;++itr;
} // End while more child classescout << endl;
} else { // End if any child classescout << aClass.name() << " has no
subclasses";cout << endl << endl;
} // End else no child classes} // End showInheritance
Podsumowanie:Pisanie programów dla Objectivity w C++ jest bardzo pracochłonne. Tworzy się znaczne ilości kodu, który bardzo często się powtarza. Dlatego potrzebne są narzędzia aby ukryć przed użytkownikiem proces generacji niskopoziomowego kodu i pozwolić mu zająć się tylko kodowaniem samego modelu.