Dział „deweloperów”

Absolwent Wydziału Elektrycznego Politechniki Poznańskiej. Od 1993 roku jest pracownikiem Instytutu Informatyki
Politechniki Poznańskiej. Zainteresowania naukowe obejmują m.in. optymalizację zapytań w systemach baz
danych, problemy modelowania danych, inżynierię oprogramowania i narzędzia CASE. Doświadczenia zawodowe
obejmują m.in. projektowanie i budowę dużych systemów informatycznych (kierownik projektu rozproszonego systemu informatycznego dla wyższej uczelni – Dziekanat96) i administrowanie RDBMS Oracle. Od lipca 1997 roku opiekuje się działem dla twórców aplikacji w Oracle’owych PLOUG’tkach.

Nowy dział gazetki – nowa tematyka

Otwieramy w tym numerze PLOUG-tek nowy dział dla tzw. „developerów”, poświęcony wszystkiemu co wiąże się z budową aplikacji baz danych, pojedynczych aplikacji lub całych
systemów, za pomocą narzędzi Oracle i nie tylko. Będziemy poruszać problemy projektowania baz danych i
aplikacji, ich implementacji, testowania i wdrażania, zagadnienia natury ogólnej lub konkretne problemy
związane z używaniem konkretnych narzędzi Oracle. Mam nadzieję, że nie zabraknie opisów praktycznych
problemów zgłaszanych przez naszych czytelników oraz opisów ich rozwiązań. W tym numerze gazetki
znajdziecie Państwo inaugurację trzech sekcji działu. W sekcji pierwszej „Problemy projektowe…” piszemy o tym jak modelować historyczne wersje danych.
Chciałbym w tym miejscu zachęcić wszystkich (również Ciebie!) do pisania artykułów dotyczących wspomnianej wyżej tematyki, do zgłaszania swoich problemów napotkanych podczas budowy aplikacji lub choćby do przesyłania uwag dotyczących zawartości działu, która w głównej mierze będzie zależeć od naszych Czytelników.

Maciej Matysiak
matys@cs.put.poznan.pl


Dział dla „developerów”, czyli kogo?

Pierwszym problemem, który chciałbym poruszyć, to nie problem techniczny, czy metodyczny, ale problem językowy. Skoro mamy wspólnie rozmawiać na temat budowy aplikacji, to musimy posługiwać się tym samym językiem i używać zrozumiałych dla nas słów. Można ostatnio spotkać sformułowania typu: „narzędzia dla developerów„, „on pracuje jako developer„, „konferencja developerska„. Nie uważam się za purystę językowego, ale słowo DEVELOPER ma według mnie dwie negatywne cechy. Po pierwsze jest niejednoznaczne, bo nie wiadomo dokładnie kim jest „developer” i czym on się zajmuje, ale znaczenie samego słowa możemy sobie zdefiniować tak, aby było wiadomo, że jeśli mówimy o „developerze” to mamy na myśli… Po drugie, brzmi dosyć obco, a w języku polskim – oczywiście, nie ma w ogóle takiego słowa. Nie jest to powodem aby takiego słowa nie wprowadzić do naszego języka, ale może jest jakieś inne – prostsze, polskie i bardziej zrozumiałe? To my „developerzy” – m.in. czytelnicy tego działu – możemy zadecydować jak chcemy sami siebie nazywać.
Ogłaszam zatem konkurs na znalezienie nazwy dla osoby zajmującej się budową i rozwojem aplikacji; projektowaniem, implementacją, testowaniem, wdrażaniem, ich utrzymywaniem i modyfikowaniem. Można również głosować na samo słowo „developer”. Może wystarczy tylko zamienić „v” na „w” i używać „deweloper” (wygląda trochę mniej obco). A oto kilka innych, mniej lub bardziej zabawnych propozycji: budowniczy, rozwojowiec, rozwijacz, narzędziowiec, twórca aplikacji lub po prostu – użytkownik narzędzi rozwojowych J. Uruchom swój ulubiony program do mailowania (teraz!) i prześlij swoją propozycję (zajmie Ci to nie więcej niż 3 minuty) albo napisz trochę więcej, co sądzisz na ten temat (mailto:matys@cs.put.poznan.pl.). Wyniki głosowania zostaną opublikowane w naszych PLOUG-tkach.

Maciej Matysiak
matys@cs.put.poznan.pl


Problemy projektowe…

Modelowanie wersji danych

W prawie każdym systemie informatycznym istnieje potrzeba modelowania danych, które zmieniają się w czasie oraz potrzeba odpowiadania na zapytania o wartości tych danych w przeszłości. W sytuacji, gdy nie korzystamy z temporalnej bazy danych, musimy rozwiązać problem, jak w sposób jawny zamodelować wersje tych danych.
Na przykład, wśród danych o pracownikach, które będziemy przechowywać w naszej bazie danych, znajduje się również atrybut Wynagrodzenie. Wiemy, że wynagrodzenie dla każdego pracownika może się zmieniać w czasie (ma charakter dynamiczny), dlatego wartość tego atrybutu opisuje tylko stan aktualny – teraźniejszy, lub innymi słowy, wyłącznie aktualne wynagrodzenie pracownika. Na podstawie tej danej, nie jesteśmy w stanie odpowiedzieć na pytanie dotyczące przeszłości, na przykład: „Ile zarabiał Kowalski
na początku roku?”. To tylko jeden z możliwych przypadków, kiedy istnieje potrzeba jawnego
zamodelowania historycznych wersji danych.
W ogólności, elementy czasowe opisujące ważność
pewnej informacji w czasie mogą być umieszczone w modelu w sposób jawny lub niejawny. Jawne elementy
czasowe są nazywane zegarami fizycznymi lub stemplami czasowymi i zawierają albo pojedynczą wartość czasu (dzień, godzina lub jedno i drugie), która wskazuje pewien punkt na osi czasu, albo przedział czasu opisany za pomocą dwóch stempli czasowych – początkowego i końcowego. Niejawne elementy czasowe nazywane są zegarami logicznymi. Przykładami takich zegarów logicznych mogą być: semestr, okres rozrachunkowy, rok akademicki lub okres płatności. Wersje danych zmieniających się w czasie można powiązać z zegarem logicznym, który opisany jest zazwyczaj za pomocą kilku atrybutów, wśród których znajduje się albo jawny element czasowy, albo odwołanie do innego zegara logicznego.
Wersjowanie danych, zarówno z wykorzystaniem zegarów fizycznych jak i logicznych, może być stosowane do różnych elementów budowanego schematu bazy danych. Wersjowaniu podlegać mogą atrybuty, związki lub całe encje. Złożenie technik wersjowania atrybutów, związków i encji pozwala na wersjowanie całych fragmentów diagramów.

Wersjowanie atrybutów
Rozważmy ponownie przykład z pracownikiem i jego wynagrodzeniem. Statyczny model, od którego rozpoczniemy rozważania, przedstawiony jest na rysunku 1.

Rys. 1. Brak wersjowania atrybutu – znana tylko wartość aktualna.

Z oczywistych względów, wynagrodzenie pracownika może się zmienić. Potrzeba pamiętania poprzednich wersji wynagrodzenia powoduje, że musimy je jawnie zamodelować. Modelowanie historycznych wersji wybranego atrybutu realizuje się poprzez dodanie nowej encji i nowego związku typu jeden do wielu (1:M). Nowa encja zawiera zegar fizyczny lub odwołanie do zegara logicznego. Wykorzystanie zegara fizycznego pokazano to na rysunku 2.

Rys. 2. Wersjowanie atrybutu za pomocą zegara fizycznego.

Dodana encja reprezentuje zbiór wszystkich historycznych wersji wynagrodzenia. Przetwarzanie danych wygląda następująco: nowy pracownik wstawiany jest jako wystąpienie encji PRACOWNIK wraz z aktualnym wynagrodzeniem i datą zatrudnienia, którą można interpretować jako
początek okresu ważności wynagrodzenia. W tym momencie encja HISTORYCZNE WYNAGRODZENIE nie zawiera jeszcze wystąpień dotyczących tego pracownika. W chwili zmiany wynagrodzenia pracownika, do encji HISTORYCZNE WYNAGRODZENIE jest wstawiane nowe wystąpienie, które zawiera kopię dotychczasowego wynagrodzenia i datę, do kiedy obowiązywała ta wersja. Atrybut od OD_DNIA jest opcjonalny i może być zastosowany dla uproszczenia zapytania SQL dotyczącego historycznych wersji danych, ale odbywa się to kosztem bardziej złożonego wstawiania rekordów (niezbędne odszukanie daty poprzedniej modyfikacji) i redundancji danych, ponieważ koniec każdego okresu czasu pokrywa się z początkiem następnego.
W przypadkach gdy wiadomo, że w tych samych momentach czasowych będzie tworzonych wiele wersji danych, wygodniej jest zastosować zegar logiczny, który jest wówczas współdzielony pomiędzy wszystkie nowe wersje powstałe w tym czasie. Przykład wersjowania wynagrodzenia pracownika za pomocą zegara logicznego pokazuje rysunek 3. Encja PODWYZKI_WYNAGRODZENIA pełni rolę zegara logicznego, do której wystąpień są dowiązywane historyczne wersje wynagrodzeń poszczególnych pracowników.

Rys. 3. Wersjowanie atrybutu za pomocą zegara logicznego

Przedstawione powyżej dwa rozwiązania wersjowania atrybutu nie są alternatywne. Wybór jednego z nich uzależniony jest od specyfiki modelowanego fragmentu rzeczywistości. Dla pełnego obrazu, można jeszcze wspomnieć o trzecim rozwiązaniu, które stosuje się gdy nie chcemy pamiętać wielu wersji atrybutu, a jedynie chcemy wiedzieć w jakim przedziale czasu wartość atrybutu (jedyna wersja) jest ważna. W takim przypadku wystarczy tylko dodanie fizycznego zegara do encji zawierającej ten atrybut (przykład z wynagrodzeniem byłby tutaj trochę mało rzeczywisty).

Wersjowanie związków
Podobnie jak w przypadku atrybutów, często istnieje potrzeba wersjowania związków kryjących w sobie pewną wiedzę, która może ulegać zmianie w czasie. Rozważmy przykład przedstawiony na rysunku 4, w którym każdy pracownik zatrudniony jest w jednym z działów firmy, a każdy dział zatrudnia jednego lub wielu pracowników.

Rys. 4. Brak wersjowania związku – znane tylko aktualne powiązanie.

Zakładamy, że pracownicy mogą zmieniać działy i ważną informacją jest, w
którym dziale pracował dany pracownik w określonym czasie w przeszłości. Musimy zatem pamiętać historyczne wersje każdego powiązania pracownika z działem. Modelowanie historycznych wersji związku
realizuje się poprzez dodanie nowej encji i dwóch nowych związków typu jeden do wielu (1:M). Nowa encja
zawiera zegar fizyczny lub odwołanie do zegara logicznego. Wykorzystanie zegara fizycznego pokazano to
na rysunku 5.

Rys. 5. Wersjowanie związku za pomocą zegara fizycznego.

Dodana encja reprezentuje zbiór wszystkich historycznych wersji powiązania
pracownika z działami, w których pracował. Nowy pracownik wstawiany jest jako wystąpienie encji PRACOWNIK wraz z dowiązaniem go do działu, w którym aktualnie pracuje. Datę zatrudnienia można
interpretować jako początek okresu ważności. W tym momencie encja HISTORYCZNY DZIAL PRACOWNIKA nie zawiera jeszcze wystąpień dotyczących tego pracownika. W chwili zmiany działu przez pracownika, do encji HISTORYCZNY DZIAL PRACOWNIKA jest wstawiane nowe wystąpienie, powiązane z dotychczasowym działem i data, do kiedy obowiązywała ta wersja związku. Atrybut od OD_DNIA, tak jak w przypadku wersjowania atrybutu, jest opcjonalny i może być zastosowany dla uproszczenia zapytania SQL kosztem bardziej złożonego wstawiania i redundancji danych.
Gdy wiadomo, że w tych samych momentach będzie tworzonych wiele wersji związków i te same okresy czasu dotyczyć będą wielu wersji związków, wygodniej jest zastosować zegar logiczny, współdzielony pomiędzy te wersje. Przykład wersjowania związku za pomocą zegara logicznego pokazuje rysunek 6. Encja OKRES pełni rolę zegara logicznego, do której wystąpień są dowiązywane historyczne wersje powiązań pracowników z działami firmy. Zegar logiczny jest szczególnie zalecany jeśli jest wykorzystywany do wersjowania wielu związków (i/lub atrybutów).

Rys. 6. Wersjowanie związków za pomocą zegara logicznego.

Wersjowanie encji
W poprzednich przykładach zakładaliśmy, że zmianie mogą ulegać wartości pojedynczych atrybutów lub związków. W pewnych sytuacjach istnieje potrzeba wersjowania całych encji wraz ze wszystkimi ich atrybutami i związkami. Sytuacja taka ma miejsce, gdy pewne wystąpienie encji opisujące
rzeczywisty obiekt (np. produkt wytwarzany w firmie) jest ważne tylko do pewnego momentu, a potem zaczyna być ważna nowa wersja tego obiektu. Jednak wszystkie dane na temat poprzedniej wersji obiektu są użytkownikowi potrzebne.
Ze względu na to, że związki dochodzące do encji komplikują znacznie ich
wersjowanie, rozważmy najpierw uproszczony przypadek wersjowania encji bez związków z rysunku 7.

Rys. 7. Encja PRODUKT bez związków przed wersjowaniem

Załóżmy, że w firmie powstaje nowa wersja pewnego produktu, posiadająca nieco inną nazwę i być może inną cenę. Istnieje pewien moment czasowy, kiedy zaczyna obowiązywać nowa wersja, a stara staje się nieaktualna (robimy założenie, że firma nie zajmuje się równocześnie dwiema wersjami tego samego produktu). W celu wersjowania encji dodajemy do modelu dwie nowe encje. Pierwsza z nich reprezentuje historyczne wersje wystąpień encji, a druga reprezentuje wszystkie wystąpienia encji – aktualne i historyczne. Wersjowanie encji PRODUKT bez związków, za pomocą zegara fizycznego llogicznego, pokazują rysunek 8 i 9.

Rys. 8. Wersjowanie encji bez związków za pomocą zegara fizycznego.
Rys. 9. Wersjowanie encji bez związków za pomocą zegara logicznego.

Odpowiednikiem encji PRODUKT z rysunku 7 jest encja o tej samej nazwie na rysunku 8 i 9, która kryje w sobie aktualne wersje produktów. Encja STARA WERSJA PRODUKTU nie wymaga komentarzy. Encja PRODUKT FIRMY reprezentuje wszystkie produkty, o których firma chce przechowywać informacje, zarówno wersje aktualne jak i historyczne. Związek typu wiele-do-jednego od encji STARA WERSJA PRODUKTU do PRODUKT FIRMY oznacza, że stara wersja może być poprzednią wersją aktualnego produktu lub jeszcze starszą wersją już starej wersji. Należy tu podkreślić, że model ten oddaje dokładnie semantykę modelowanej rzeczywistości i nie determinuje liczby tabel, które będą utworzone w bazie danych. Ten fragment diagramu można przetransformować do jednej, dwóch lub trzech tabel, w zależności od rozłożenia atrybutów oraz szacowanej liczby wystąpień aktualnych i starych wersji.
Każda encja posiada związki prowadzące do innych encji. Zatem, wersjowanie wystąpień encji wymaga również wersjowania powiązań tych wystąpień. Rozważmy przykład, w którym wersjowana encja PRODUKT związana jest z encją DZIAL, tak jak pokazano na rysunku 10. Zakładamy tutaj, że każdy produkt produkowany jest przez jeden z działów firmy. Aby uzasadnić konieczność wersjowania związków dochodzących do wersjowanej encji chciałbym wspomnieć, że różne wersje tego samego produktu mogą być produkowane przez różne działy.

Rys. 10. Encja ze związkiem przed wersjowaniem

Nowe wystąpienie encji PRODUKT FIRMY jest wprowadzane do bazy danych zawsze jako wystąpienie encji podrzędnej (specjalizacji) PRODUKT i wiązane z pewnym działem firmy. Wstawienie nowej wersji istniejącego produktu wiąże się z przesunięciem aktualnego produktu jako wystąpienie encji STARA WERSJA PRODUKTU i powiązanie jej z aktualną wersją za pomocą związku STARA WERSJA PRODUKTU dotyczy. Aktualne powiązanie produktu z działem, który go produkuje wprowadzane jest jako kolejne wystąpienie encji HISTORYCZNY DZIAL PRODUKTU. Kontrowersyjne wydawać się może powiązanie encji HISTORYCZNY DZIAL PRODUKTU z encją PRODUKT FIRMY zamiast z encją STARA WERSJA PRODUKTU. Wynika to z faktu, że wystąpienia encji HISTORYCZNY DZIAL PRODUKTU mogą być wprowadzane do bazy danych nie tylko podczas wersjowania całych produktów, ale również wersjowania wyłącznie samego związku PRODUKT jest produkowany przez, gdy produkcja przenoszona jest do innego działu.

Rys. 11. Wersjowanie encji ze związkiem za pomocą zegara logicznego

Wersjowanie encji ze związkiem za pomocą zegara logicznego wymaga by wprowadzenia tylko drobnej poprawki polegającej na usunięciu stempla czasowego z encji HISTORYCZNY DZIAL PRODUKTU i powiązania jej z zegarem logicznym.

Podsumowanie
Modelowanie wersji danych niezbędne jest wszędzie tam, gdzie dane mają charakter dynamiczny i istnieje potrzeba udzielania odpowiedzi na zapytania dotyczące wartości tych danych w przeszłości. W ogólności, historyczne wersje danych modelowane są za pomocą dodatkowych encji powiązanych związkami typu wiele do jednego (M:1) z aktualnymi wersjami danych. Wersjowanie poszczególnych elementów diagramu, takich jak atrybuty, związki i całe encje, może być wykonywane niezależnie. Oznacza to, że można dokonywać superpozycji modelu wersji atrybutu z modelem wersji związku lub modelem wersji encji, otrzymując w ten sposób złożone modele wersjowania danych.

Maciej Matysiak
matys@cs.put.poznan.pl