190 likes | 299 Views
Marcin Michalak s1744. C++ w Objectivity. Pomocne pakiety:. Data Definition Language (DDL). Standard Template Library (STL). Active Schema. Data Definition Language (DDL).
E N D
Marcin Michalak s1744 C++ w Objectivity
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’a • Zawiera: • - 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.
Pliki użytkownika: Pliki generowane przez DDL: Procesor DDL (2)
Przykładowe możliwości DDL (1) Klasa bez trwałości. Klasa z trwałością. Można wykorzystywać klasy nie obsługujące trwałości w plikach ‘ddl’.
Pliki użytkownika. Pliki generowane przez DDL. Przykładowe możliwości DDL (2) Możliwe jest dziedziczenie z klas obsługujących trwałość.
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 fields inline 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 Book inline ostream& operator << ( ostream& os, ooHandle(Book)& book) { return book->print( os ); }
Przykład aplikacji ‘Biblioteka’ (3) Pliki powstałe po przetworzeniu plików ‘ddl’: Przed: lib.ddl lib.cpp Book.ddl Book.cpp Loan.ddl Loan.cpp ptrn.ddl ptrn.cpp lm.h lmMain.cpp makefile Po: lib.ddl lib.cpp lib.h lib_ref.h lib_ddl.cpp Book.ddl Book.cpp book.h book_ref.h book_ddl.cpp Loan.ddl Loan.cpp loan.h loan_ref.h loan_ddl.cpp ptrn.ddl ptrn.cpp ptrn.h ptrn_ref.h ptrn_ddl.cpp lmMain.cpp lm.h makefile 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) Przykładowe operacje na obiektach: 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 // 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życzenie library->checkoutBook(book, patron, "10/30/93"); cout << "Book checked out:\n" << book; }else cout << "Book: ISBN# 2345678901 not found\n\n"; // wydruk stanu biblioteki cout << "Exiting Library Information System:\n" << library;
Przykład aplikacji ‘Biblioteka’ (5) Wynik wygenerowany przez aplikację: [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 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 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
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. Przykład wykorzystania: 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; … };
Standard Template Library (STL) (1) cd. Kod źródłowy do przykładu użycia STL: #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
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ą iteratora int_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.
Przykład wykorzystania ‘Active Schema’ do przeglądania dziedziczenia: Active Schema (2) void showInheritance(const d_Class &aClass) { // Print parent classes, if any inheritance_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 parents cout << endl; } else { // End if any parents
Active Schema (2) cd. cout << aClass.name() << " has no parent classes"; cout << endl << endl; } // End else no parents // Print child classes, if any itr = 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 classes cout << endl; } else { // End if any child classes cout << 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.