C++ a ObjectivityDB

Download Report

Transcript C++ a ObjectivityDB

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.
Procesor DDL (2)
Pliki użytkownika:
Pliki generowane przez DDL:
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’.
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 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
ptrn.ddl
ptrn.cpp
ptrn.h
ptrn_ref.h
ptrn_ddl.cpp
Book.ddl
Book.cpp
book.h
book_ref.h
book_ddl.cpp
lmMain.cpp
lm.h
Loan.ddl
Loan.cpp
loan.h
loan_ref.h
loan_ddl.cpp
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ę:
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
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;
}
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)
Przykład wykorzystania ‘Active Schema’ do przeglądania dziedziczenia:
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)";
}
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
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.