Procedury, procedury funkcyjne, metody

advertisement
Obiektowe języki zapytań
Wykładowca: Kazimierz Subieta
Polsko-Japońska Wyższa Szkoła
Technik Komputerowych, Warszawa
[email protected]
Wykład 14:
Procedury,
procedury funkcyjne,
metody
Instytut Podstaw Informatyki PAN,
Warszawa
[email protected]
© K.Subieta. Obiektowe języki zapytań 14, Folia 1
czerwiec 2004
Krótka charakterystyka procedur
 Imperatywne języki programowania, w tym języki obiektowe, są
wyposażone w mechanizmy procedur.
 Ich istotą jest to, że:
•
•
•
•
Hermetyzują dowolnie skomplikowane obliczenia,
Ich wnętrze jest niedostępne z zewnątrz,
Mogą być wywoływane z wielu miejsc,
Ich przystosowanie do konkretnego celu następuje poprzez określenie
parametrów lub poprzez efekty uboczne (czyli korzystanie ze stanu spoza
danej procedury lub zmiany tego stanu).
 Procedury mogą być dalej podzielone na:
• Procedury właściwe i procedury funkcyjne (zwane też funkcjami);
• Procedury i metody;
• Procedury znajdujące się po stronie programu aplikacyjnego i
przechowywane w bazie danych.
 Procedury właściwe nie zwracają wyniku, nie mogą więc być użyte jako
składniki wyrażeń, zaś procedury funkcyjne zwracają wynik i przez to ich
wywołania są szczególnymi przypadkami wyrażeń.
© K.Subieta. Obiektowe języki zapytań 14, Folia 2
czerwiec 2004
Procedury a metody
 Jeżeli chodzi o podział na procedury i metody, różnica dotyczy miejsca
logicznego ulokowania kodu procedur oraz sposobu ich wywołania.
 Procedury są zwykle ulokowane w określonych jednostkach programu,
np. w modułach,
 Metody są ulokowane logicznie w klasach.
• Dodatkowo, niejawnym (pośrednim) parametrem metody jest obiekt, na
którym ta metoda działa.
• Metodę funkcyjną (zwracającą wynik) nazywa się niekiedy atrybutem
wirtualnym.
• Poza tym, różnice pomiędzy procedurami i metodami są drugorzędne
• wbrew twierdzeniom niektórych zwolenników obiektowych języków
programowania.
 Popularne w obiektowości „wysyłanie komunikatu do obiektu” jest
dokładnie tym samym co wywołanie procedury/metody działającej na
tym obiekcie.
• Inne interpretacje są nad-interpretacjami lub niekompetencją.
© K.Subieta. Obiektowe języki zapytań 14, Folia 3
czerwiec 2004
Procedury pierwszej i drugiej kategorii program.
 Tradycyjnie, procedury po kompilacji są nierozerwalną częścią danego
programu aplikacyjnego (są drugiej kategorii programistycznej),
 W związku z czym nie można ich podczas czasu wykonania usunąć,
wstawić, zmienić, itd.
 W systemach BD pojawił się inny typ procedury, zwany zapamiętaną
procedurą (stored procedure) lub procedurą bazy danych (database
procedure).
•
•
•
•
Są pierwszej kategorii programistycznej, wiązane dynamicznie.
Można je dynamicznie tworzyć, usuwać lub zmieniać.
Są pisane w specjalnym interpretowanym języku, np. w PL/SQL.
Nie mogą być pisane w klasycznych lub obiektowych językach
programowania takich jak C++ lub Java.
 Możliwa jest dowolna kombinacja tych opcji.
• Np. w systemie Oracle występują zapamiętane metody, czyli kombinacja
procedur bazy danych i metod.
• Znane z SQL perspektywy (views) można uważać za zapamiętane procedury
funkcyjne.
© K.Subieta. Obiektowe języki zapytań 14, Folia 4
czerwiec 2004
Efekty uboczne procedur/metod
 Efekt uboczny jest to działanie procedury na innym środowisku niż
własne lokalne środowisko.
• Pasywny efekt uboczny – procedura korzysta z innego środowiska.
• Aktywny efekt uboczny – procedura dokonuje zmian w zewnętrznym
środowisku.
 Efekty uboczne są podstawą technik programistycznych.
• Projektanci języków nie ograniczają możliwości dostępu do zasobów
zewnętrznych, w tym danych globalnych i danych z bazy danych, oraz
aktualizacji tych zasobów.
• Niestety styl specyfikacji procedur często ignoruje fakt, że mogą one mieć
efekty uboczne.
 W oryginalnej propozycji Parnasa dotyczącej modułów efekty uboczne
były uwzględnione w postaci tzw. list importowych.
• Rozwiązanie to zostało zastosowane w języku Modula-2 (następca Pascala).
• Brak specyfikacji i kontroli efektów ubocznych w popularnych językach
programowania, takich jak C++ i Java jest zwiększaniem skłonności
oprogramowania do błędów (katastrofą rakiety Ariane-5 była spowodowany
brakiem wyspecyfikowanych efektów ubocznych)
© K.Subieta. Obiektowe języki zapytań 14, Folia 5
czerwiec 2004
Procedury/metody rekurencyjne
 Procedury/metody mogą być rekurencyjne, co implikuje konieczność
stosowania dyscypliny w zakresie komunikowania parametrów oraz
mechanizmu kontrolującego zakresy obowiązywania nazw użytych w
ciałach procedur oraz wiązania tych nazw.
 Mechanizmy te są oparte o ten sam stos środowiskowy znany nam z
poprzednich wykładów.
 Dalej pokażemy w jaki sposób ten stos będzie przystosowany do
wspomagania wszelkiego rodzaju procedur (w tym metod).
 Będziemy przy tym przyjmować, że zarówno parametry procedur jak i
wynik procedur funkcyjnych będą określone poprzez zapytania.
© K.Subieta. Obiektowe języki zapytań 14, Folia 6
czerwiec 2004
Parametry procedur
 Procedury mogą mieć parametry.
 W odróżnieniu od funkcji matematycznych, gdzie w zasadzie nie mówi
się o sposobach komunikowania parametrów, w językach programowania
wykształciło się kilka dobrze rozpoznanych metod komunikowania
parametrów o istotnych różnicach semantycznych.
 Dalej podamy krótki ich przegląd.
 Niektóre z tych metod będą omówione dla przypadku parametrów
będących zapytaniami.
 Możliwe są nowe metody nie spotykane lub rzadko spotykane w
literaturze.
• Przykładem jest wołanie, w którym każdy parametr aktualny jest skojarzony z
nazwą parametru formalnego.
• Umożliwia to przy wywołaniu dowolną kolejność parametrów oraz pomijanie
parametrów (zastępowanie ich wartościami domyślnymi).
© K.Subieta. Obiektowe języki zapytań 14, Folia 7
czerwiec 2004
Wołanie poprzez wartość (call-by-value)
 Jest to technika przekazywania argumentu procedury (lub metody) do jej
wnętrza, w której przekazywana jest wartość argumentu obliczona przed
przekazaniem sterowania do wnętrza procedury.
 Jeżeli argumentem jest referencja, to dokonuje się automatycznie
dereferencji.
 W niektórych językach (C/C++) tworzy się lokalną zmienną zawierającą
kopię wartości przekazanej jako argument.
 Zmienna ta ma nazwę parametru formalnego i można ją aktualizować tak
jak zwykłą lokalną zmienną.
 W innych językach (Pascal, Modula-2) taka aktualizacja takiej zmiennej
jest zabroniona, gdyż parametr w ciele procedury jest inaczej traktowany
niż zmienna.
© K.Subieta. Obiektowe języki zapytań 14, Folia 8
czerwiec 2004
Wołanie poprzez referencję (call-by-reference)
 Technika przekazywania argumentu procedury (lub metody) do jej
wnętrza, w której przekazywana jest referencja do obiektu.
 Dzięki temu wewnątrz procedury można dokonać zmiany stanu
(aktualizacji) obiektu zewnętrznego w stosunku do tej procedury.
 Wołanie przez referencję jest kojarzone z własnością zmienności
(mutability).
 Obiekt przekazywany poprzez referencję jest dostępny w ciele procedury
nie pod swoją nazwą, lecz pod nazwą jej odpowiedniego parametru
formalnego.
 Wołanie przez referencję musi być odróżnione od innych sposobów
wołania poprzez składnię.
• W językach Pascalo-podobnych jest to słowo kluczowe var.
• W innych językach (np. IDL CORBA) są to słowa kluczowe inout oraz out;
drugie z nich oznacza, że komunikowany obiekt (zmienna) może nie być
zainicjowany, wobec czego nie wolno go czytać.
• Dla symetrii, w takich systemach wołanie przez wartość oznacza się słowem
kluczowym in.
© K.Subieta. Obiektowe języki zapytań 14, Folia 9
czerwiec 2004
Ścisłe wołanie przez wartość (strict-call-by-value)
 W technice tej nie występuje zróżnicowanie na wołanie przez wartość i
wołanie przez referencję.
 Jeżeli komunikowana jest wartość, to jest ona przekazywana do ciała
procedury tak jak w wołaniu przez wartość.
 Jeżeli komunikowana jest referencja (pointer), to bez żadnych zmian
przekazywany jest on do wnętrza procedury, tak jak w wołaniu przez
referencję.
 Przykładem zastosowania tej techniki jest język C.
© K.Subieta. Obiektowe języki zapytań 14, Folia 10
czerwiec 2004
Wołanie poprzez wartość ze zwrotem (call-by-value-return)
 Wołanie poprzez referencję, w którym wewnątrz ciała procedury tworzy
się lokalną kopię obiektu (zmiennej), którego referencja jest przekazana
jako parametr.
 Wszelkie operacje na parametrze wewnątrz ciała procedury następują na
tej lokalnej kopii, a nie na oryginalnej zmiennej (różnica z wołaniem
przez referencję).
 W momencie zakończenia procedury wartość tego lokalnego obiektu
podstawia się z powrotem na obiekt, którego referencja jest przekazana
jako parametr.
 Technika ma duże znaczenie w systemach rozproszonych, gdzie
komunikowana referencja może dotyczyć obiektu znajdującego się poza
przestrzenią adresową pamięci operacyjnej danego komputera.
 Technika nie jest w pełni semantycznie „czysta”, gdyż umożliwia
nałożenie się dwóch lub więcej aktualizacji w ramach tego samego
programu.
© K.Subieta. Obiektowe języki zapytań 14, Folia 11
czerwiec 2004
Wołanie poprzez nazwę (call-by-name)
 Technika przekazywania parametrów (po raz pierwszy zastosowana w
języku Algol-60) polegająca na tym, że parametru nie oblicza się w
momencie wołania metody/procedury, ale przekazuje się go w postaci
kodu (tekstu) wyrażenia będącego parametrem aktualnym.
 Tekst ten zastępuje wszystkie wystąpienia parametru formalnego w ciele
metody/procedury (parametr jest traktowany jak makro).
 Specyfiką tej techniki jest to, że środowisko, w którym taki parametr jest
ewaluowany, jest środowiskiem wywołania tej metody/procedury, a nie jej
środowiskiem lokalnym (co jest konieczne z semantycznego punktu
widzenia);
 Technika nie jest semantycznie „czysta” - może powodować efekt, w
którym obliczane wartości parametru w poszczególnych miejscach ciała
metody/procedury nie są identyczne ze względu na zmianę stanu.
 Technika ta jest powszechnie stosowana w przypadku parametrów makr.
• Może mieć również znaczenie dla technik optymalizacyjnych (optymalizacji
zapytań) opartych na przepisywaniu (rewriting).
© K.Subieta. Obiektowe języki zapytań 14, Folia 12
czerwiec 2004
Wołanie poprzez potrzebę (call-by-need)
 Technika przekazywania parametrów określana także jako leniwa
ewaluacja (lazy evaluation).
 Oznacza opóźnienie wyliczania wartości parametru aktualnego do
momentu, kiedy będzie on rzeczywiście potrzebny wewnątrz ciała
metody/procedury.
 Parametr jest ewaluowany tylko raz (różnica z wołaniem przez nazwę), w
środowisku wywołania metody/procedury.
 Technika ma na celu optymalizację czasu wykonywania i może być
kombinowana z innymi metodami (call-by-value, call-by-reference, itd.).
 Podobnie do wołania przez nazwę, technika ta nie jest semantycznie
„czysta”, gdyż może prowadzić do efektu, w którym wartość wyliczonego
parametru jest inna niż wartość, która byłaby wyliczona w momencie
wołania metody/procedury.
© K.Subieta. Obiektowe języki zapytań 14, Folia 13
czerwiec 2004
Procedury w SBQL
 Przyjmiemy następującą składnię deklaracji procedury (nie
uwzględniającą kontroli typologicznej):
procedura ::= procedure nazwaProc {instrukcje}
procedura ::= procedure nazwaProc( ) {instrukcje}
procedura ::= procedure nazwaProc ( parFormalne) {instrukcje}
nazwaProc ::= nazwa
parFormalne ::= parFormalny | parFormalny; parFormalne
parFormalny ::= nazwa | in nazwa | out nazwa
instrukcja ::= return [zapytanie]
 Wywołanie procedury:
instrukcja ::= nazwaProc | nazwaProc( ) | nazwaProc ( parAktualne )
zapytanie ::= nazwaProc | nazwaProc( ) | nazwaProc ( parAktualne )
parAktualne ::= parAktualny | parAktualny ; parAktualne
parAktualny ::= zapytanie
© K.Subieta. Obiektowe języki zapytań 14, Folia 14
czerwiec 2004
Semantyka procedur (1)
 Nie rozróżniamy procedur właściwych i procedur funkcyjnych.
 Procedura funkcyjna musi zawierać wewnątrz instrukcję return, z
parametrem będącym zapytaniem.
• Instrukcja ta kończy działanie procedury.
• Taka procedura może być wywołana jako zapytanie.
• Jeżeli procedura funkcyjna jest wywołana jako instrukcja (poza zapytaniem),
wówczas zwracany przez nią wynik jest ignorowany.
• Jeżeli napotkana instrukcja return nie ma parametru w postaci zapytania, to
jej wykonanie kończy działanie procedury, ale nic ona nie zwraca (wobec
czego nie jest procedurą funkcyjną).
 Przyjęliśmy, że formalne parametry procedury mogą być pozbawione
kwalifikatora; wówczas oznacza to ścisłe wołanie przez wartość (strictcall-by-value).
 Kwalifikator in oznacza zwykłe wołanie przez wartość, zaś kwalifikator
out oznacza wołanie przez referencję.
• Semantyka tych metod transmisji parametrów zostanie objaśniona dalej.
© K.Subieta. Obiektowe języki zapytań 14, Folia 15
czerwiec 2004
Semantyka procedur (2)
 Istotne jest jak i gdzie procedura będzie zapamiętana.
 Najczęstszym rozwiązaniem jest uwzględnienie deklaracji procedury w
środowisku rozwoju oprogramowania.
• Miejsce ulokowania procedury wynika wtedy z innych czynników, np.
miejscem jest moduł lub klasa, jeżeli dana procedura jest składową kodu
źródłowego tego modułu lub klasy.
 W przypadku baz danych procedury są bytami pierwszej kategorii
programistycznej, wobec tego mogą być potrzebne specjalne
udogodnienia administracyjne dla ich tworzenia, wstawiania w
odpowiednie miejsce składu obiektów, kompilowania, usuwania,
zabezpieczania, optymalizacji, itd.
 W systemie Loqis przyjęliśmy, że procedury są składowymi modułów
źródłowych lub klas, które po kompilacji stają się modułami lub klasami
bazy danych.
 Procedury takie mogą być przenoszone pomiędzy modułami lub klasami
poprzez instrukcję insert.
© K.Subieta. Obiektowe języki zapytań 14, Folia 16
czerwiec 2004
Gzie procedurę można zapamiętać?
 Procedurę można zapamiętać w dowolnym środowisku składu obiektów,
w szczególności:
• W bazie danych po stronie serwera na najwyższym poziomie hierarchii
obiektów.
• W środowisku lokalnym sesji użytkownika, po stronie klienta, czyli programu
aplikacyjnego i środowiska jego wykonania.
• Wewnątrz dowolnego obiektu, w szczególności, modułu bazy danych, o ile
takie pojęcie będzie wprowadzone.
• Wewnątrz klasy, zarówno umieszczonej po stronie serwera bazy danych, jak i
po stronie aplikacji klienta. Umieszczenie procedury wewnątrz klasy
powoduje, że staje się ona tym, co powszechnie jest określane w
obiektowości jako „metoda”.
• Wewnątrz specjalnej biblioteki procedur po stronie serwera, lub pewnej
struktury takich bibliotek.
 Zależnie od miejsca umieszczenia procedur w składzie, bindery
zawierające referencje do procedur i ich nazwy muszą być umieszczone w
odpowiednich sekcjach stosu ENVS.
• W ten sposób nazwy procedur będą dostępne do wiązania.
© K.Subieta. Obiektowe języki zapytań 14, Folia 17
czerwiec 2004
Semantyka wywołania procedur (1)
 Najpierw wiąże się jej nazwę występującą w zapytaniu/programie na stosie
ENVS. Wynikiem jest referencja do procedury.
 Następuje uruchomienie procedury, czego skutkiem jest pojawienie się na stosie
ENVS sekcji z binderami (zwanej zapisem aktywacyjnym).
 Zapis aktywacyjny zawiera trzy rodzaje bytów:
• bindery aktualnych parametrów procedury;
• bindery do lokalnych obiektów procedury;
• ślad powrotu, umożliwiający przekazanie sterowania do kodu wywołującego
procedurę po zakończeniu jej działania. Ślad ten w tym kroku jest wstawiany do
zapisu aktywacyjnego.
 Jeżeli procedura była umieszczona wewnątrz klasy (tj. była metodą), to poniżej
zapisu aktywacyjnego umieszcza się sekcję z binderami do wszystkich
prywatnych własności tej klasy.
 Następuje ewaluacja zapytań będących parametrami procedury; wynik tej
ewaluacji znajduje się na QRES.
 Po ewaluacji parametrów tworzy się z nich bindery i wstawia do sekcji ENVS
zawierającej zapis aktywacyjny procedury. Parametry te usuwa się z QRES.
© K.Subieta. Obiektowe języki zapytań 14, Folia 18
czerwiec 2004
Semantyka wywołania procedur (2)
 Jeżeli procedura miała zadeklarowane obiekty, to są one tworzone w
składzie, zaś ich bindery są umieszczone wewnątrz zapisu aktywacyjnego.
 Sterowanie jest przekazywane do ciała procedury.
 Przy wiązaniu nazw wewnątrz ciała procedury wszystkie sekcje procedur,
które wywołały bezpośrednio lub pośrednio daną procedurę (wraz z
towarzyszącymi im sekcjami obiektów, zapytań, klas, itd.) są niedostępne
do wiązania.
 Jeżeli sterowanie osiągnie końcowy nawias ciała procedury, lub napotka
instrukcję return, to procedura kończy swoje działanie.
• Jeżeli instrukcja return miała parametr w postaci zapytania, to ewaluuje się je
w środowisku tej procedury, jak zwykle.
• Wynik, jak zwykle, znajdzie się na wierzchołku QRES jako wynik działania
procedury funkcyjnej.
 Zakończenie działania procedury oznacza zdjęcie ze stosu wszystkich
sekcji, które były tam włożone w momencie jej startu, usunięcie
zadeklarowanych lub utworzonych lokalnych obiektów, oraz powrót
sterowania do programu wywołującego, zgodnie ze śladem powrotu.
© K.Subieta. Obiektowe języki zapytań 14, Folia 19
czerwiec 2004
Przykład procedury (1)
 Procedura ZmieńDział zmienia dział dla pracowników komunikowanych
jako parametr P na dział komunikowany jako parametr D.
procedure ZmieńDział( P; out D ) {
delete Dział.Zatrudnia where Prac  P;
for each P as p do {
p.PracujeW := ref D
insert D, create ref p as Zatrudnia }}
 Wywołanie procedury: przenieś wszystkich analityków do działu
kierowanego przez Nowaka:
ZmieńDział(
Prac where Stan = ”analityk”;
Dział where (Szef.Prac.Nazwisko) = ”Nowak” )
 Jeżeli system respektowałby automatyczną aktualizację bliźniaczych
pointerów (PracujeW i Zatrudnia), to procedura zostałaby uproszczona:
procedure ZmieńDział( P; out D ) {
for each P do PracujeW := ref D }}
© K.Subieta. Obiektowe języki zapytań 14, Folia 20
czerwiec 2004
Przykład procedury (2)
 Procedura funkcyjna MałoZarabiający zwraca nazwisko, zarobek i nazwę
działu dla pracowników określonych stanowisk zarabiających mniej niż
średnia. Wynik jest strukturą z nazwami N, Z, D.
procedure MałoZarabiający ( in Stanowiska ) {
create avg( Prac.Zar ) as Średnia;
create ref (Prac where Stan  Stanowiska
and Zar < Średnia) as Mało;
return Mało.Prac.(
Nazwisko as N, Zar as Z,
(PracujeW.Dział.Nazwa) as D) };
• Podaj nazwiska i zarobek dla mało zarabiających piekarzy i stolarzy z działu
produkcji.
(MałoZarabiający( bag(”piekarz”,”stolarz”))
where D = ”produkcja”). (N, Z)
• Podwyższ o 100 zarobek wszystkim mało zarabiającym programistom z
działu konserwacji.
for each MałoZarabiający( ”programista”) )
where D = ”Konserwacja” do Z := Z+100;
© K.Subieta. Obiektowe języki zapytań 14, Folia 21
czerwiec 2004
Procedury funkcyjne a perspektywy (1)
 Procedura BogatyPrac zwraca informacje o pracownikach, który zarabiają
brutto co najmniej 3000. Informacja zawiera nazwisko pracownika jako
Nazwisko, nazwisko jego szefa jako Szef oraz zarobek netto jako Zarobek.
procedure BogatyPrac {
return (Prac where Zar  3000). ( Nazwisko as Nazwisko,
(PracujeW.Dział.Szef.Prac.Nazwisko) as Szef, ZarNetto() as Zarobek) };
 Nazwiska i zarobki netto bogatych pracowników pracujących dla
Wilickiego:
(BogatyPrac where Szef = „Wilicki”) . (Nazwisko, Zarobek)
• Procedura BogatyPrac została użyta w taki sposób, że użytkownik może
rozumieć nazwę BogatyPrac jako nazwę obiektów posiadających trzy
atrybuty: Nazwisko, Szef i Zarobek.
• Są to obiekty „wirtualne”, istniejące w postaci definicji (i w wyobraźni
programisty), ale nieobecne w składzie danych.
 Procedura BogatyPrac przypomina więc pojęcie z baz danych znane jako
perspektywa (view).
© K.Subieta. Obiektowe języki zapytań 14, Folia 22
czerwiec 2004
Procedury funkcyjne a perspektywy (2)
 Jeżeli pominąć drugorzędne opcje, to klasyczne perspektywy np. w SQL
są procedurami funkcyjnymi zapamiętanymi w bazie danych.
• Ten fakt do dzisiaj nie dotarł do powszechnej świadomości społeczności baz
danych.
 Pozytywne konsekwencje tego założenia:
• Moc obliczeniowa i moc pragmatyczna takich perspektyw jest
nieograniczona.
• Semantyka oparta na stosie środowiskowym jest przygotowana do rekurencji.
• Perspektywy mogą posiadać parametry w postaci dowolnych zapytań.
• Wirtualne obiekty są automatycznie podłączone do klas, o ile funkcja zwróci
referencje do obiektów tych klas.
• Automatycznie dostarczone są środki do aktualizacji perspektyw, gdyż
procedury mogą zwrócić referencje do obiektów, atrybutów, itd.
 Ostatni punkt wymaga dłuższej dyskusji: ze względu na aktualizację
wyraźnie musimy rozróżnić procedury funkcyjne i perspektywy.
© K.Subieta. Obiektowe języki zapytań 14, Folia 23
czerwiec 2004
Aktualizacja wirtualnych obiektów
 Dotychczasowy wysiłek badawczy związany z aktualizacją witalnych
obiektów dotyczył dodatkowych ograniczeń na definicje perspektyw i ich
aktualizacje, aby zapobiec anomaliom aktualizacyjnym.
 Dla perspektyw obiektowych te ograniczenia są tak silne, że praktycznie
nie zezwalają na tworzenie czegokolwiek sensownego.
 Przyjmiemy następującą filozofię.
• Jeżeli programista lub projektant definiuje funkcję, to powinien być w pełni
świadomy, że jest to funkcja, a nie perspektywa.
• Jeżeli mimo tej świadomości decyduje się na aktualizację poprzez referencje
zwracane przez tę funkcję, to wolno mu to zrobić, ale ponosi za to
odpowiedzialność.
• Nie dopuszczamy w tym względzie żadnych protez, w rodzaju ograniczeń
znanych z systemu Oracle
 Jeżeli programista chce, aby funkcja była perspektywa o pełnych walorach
przezroczystości, wówczas musi stworzyć taką perspektywę explicite,
według koncepcji, która będzie przedstawiona w następnym semestrze.
 Koncepcja ta rozwiązuje problem aktualizacji perspektyw.
© K.Subieta. Obiektowe języki zapytań 14, Folia 24
czerwiec 2004
Metody w SBQL
 Metoda jest procedurą umieszczoną wewnątrz klasy i traktowaną jako inwariant
obiektów będących członkami tej klasy.
• Metoda w SBQL jest zawsze wywoływana w kontekście obiektu, na którym działa;
ten kontekst jest określony poprzez umieszczenie binderów do własności obiektu na
stosie ENVS i następnie wywołanie metody.
 Metoda ZarobekNetto umieszczona wewnątrz klasy Pracownik zwraca zarobek
netto dla pracownika, obliczając go według pewnej formuły:
procedure ZarNetto {
if exists(self.Zar) then {
return (if self.Zar < 500 then self.Zar
else if self.Zar < 1000 then 0.8 * (self.Zar - 500) + 500
else 0.7 * (self.Zar - 1000) + 900);}
else return 0; };
• Wywołania metody:
Podaj pracowników z zarobkiem netto mniejszym od 1000:
Prac where ZarNetto < 1000
Podaj średnią zarobków netto, z wyłączeniem pracowników, dla których funkcja
ZarNetto zwróci 0.
avg((Prac where ZarNetto > 0).ZarNetto)
© K.Subieta. Obiektowe języki zapytań 14, Folia 25
czerwiec 2004
Wyróżniona nazwa self (this)
 W przykładzie wykorzystaliśmy nazwę self zwracającą referencję do
aktualnie przetwarzanego obiektu.
 Tego rodzaju predefinowana nazwa (self, this, itp.) występuje w
większości obiektowych języków programowania.
 W naszym przypadku nie jest ona niezbędna.
 Z technicznego punktu widzenia, wszystkie bindery do wewnętrznych
własności przetwarzanego obiektu znajdują się w odpowiedniej sekcji
ENVS.
 Istnieją powody, dla których taką nazwę warto wprowadzić:
• Modelowanie pojęciowe: nazwa self pozwala programiście widzieć wyraźnie
w kodzie metody wszystkie odwołania do przetwarzanego obiektu.
• W niektórych sytuacjach (np. porównanie referencji) referencja do
przetwarzanego obiektu ułatwia napisanie metody.
 Z drugiej strony, jak zwykle w przypadku predefiniowanych nazw, w
niektórych sytuacjach predefinowana nazwa self może prowadzić do
niejednoznaczności i wymagać większej uwagi od programisty,
szczególnie w przypadku zmian już napisanego kodu.
© K.Subieta. Obiektowe języki zapytań 14, Folia 26
czerwiec 2004
Jak wprowadzić nazwę self:
• Taka nazwa mogłaby się przydać również w innych kontekstach.
 Nazwę self wprowadzimy poprzez poprawienie funkcji nested.
 Jeżeli argumentem tej
funkcji jest pojedyncza
referencja r do obiektu, który
jest podłączony do klasy, to
wynik tej funkcji, oprócz
binderów do pod-obiektów
tego obiektu, zawierać
będzie binder self(r).
 Sytuacja na ENVS w
momencie przetwarzania
metody ZarNetto dla obiektu
posiadającego identyfikator
i4 .
Klasa Osoba
Klasa Prac
i4 Prac
i5 Nazwisko ”Nowak”
i6 RokUr
i7 NrP
1944
8897865
i8 Stan "referent"
i9 Zar
2500
i10 PracujeW
Skład
© K.Subieta. Obiektowe języki zapytań 14, Folia 27
Lokalna sekcja wywołania metody
ZarNetto
Bindery do prywatnych własności klasy
Prac
Sekcja przetwarzanego obiektu:
self(i4), Nazwisko(i5), RokUr(i6), NrP(i7),
Stan(i8), Zar(i9), PracujeW(i10)
Bindery do publicznych własności klasy
Prac: ZmieńZar(..), ZarNetto(..),...
Bindery do publicznych własności klasy
Osoba: Wiek(..),...
.......
Sekcja sesji użytkownika
Sekcja bazy danych:
Osoba(..), Osoba(..), ..., Prac(..), Prac(..),
..., Dział(..), Dział(..)
Sekcja globalnych funkcji bibliotecznych
Sekcja zmiennych i funkcji środowiska
komputerowego
Stos ENVS
czerwiec 2004
Rozszerzenie SBQL w modelu M3
 Model M3 wprowadza listy eksportowe dzielące własności obiektów i klas na
publiczne i prywatne.
 Własności prywatne zarówno klasy K, jak i obiektów klasy K, są dostępne
wyłącznie z wnętrza ciała metod (publicznych i prywatnych) klasy tej samej K.
• Można to prosto zrealizować poprzez odpowiednie ustawienie sekcji stosu oraz
poprawkę do funkcji nested.
• Niech iK będzie identyfikatorem obiektu klasy K posiadającej listę eksportową
exportK.
• Lista ta zawiera nazwy własności klasy i obiektów tej klasy dostępnych publicznie.
• Funkcje nested_private oraz nested_public zmieniają definicję funkcji nested
uwzględniając listę eksportową:
nested_private(iK ) = {n(x) : n(x)  nested(iK ) and n  exportK}
nested_public(iK ) = {n(x) : n(x)  nested(iK ) and n  exportK}
 Dla argumentów nie będących identyfikatorami obiektów funkcje te są identyczne
z funkcją nested.
• Funkcje te podobnie jak poprzednio rozszerzamy na dowolne struktury.
© K.Subieta. Obiektowe języki zapytań 14, Folia 28
czerwiec 2004
Operator niealgebraiczny w modelu M3
 Rozpatrzmy zapytanie q1 q2, gdzie  jest operatorem nie-algebraicznym.
• Niech eval(q1) zwróci bag{ r1, r2,...}, gdzie r1, r2,... są referencjami do
obiektów będących członkami klasy K1, która jest pod-klasą K2, która jest
pod-klasą K3.
• Wiązana jest nazwa m występująca w q2, m nie jest nazwą metody.
• W takim przypadku sytuacja przypomina model M1, ale:
• Wykorzystana jest w tej sytuacji funkcja nested_public, zaś kolejne stany
stosu ENVS przy przetwarzaniu ri są następujące:
nested_public(ri)
Sekcje wkładane przy
przetwarzaniu ri przez
operator θ
Koniec przetwarzania
ri przez q2
nested_public(iK1)
nested_public(iK2)
nested_public(iK3)
Poprzedni stan ENVS
© K.Subieta. Obiektowe języki zapytań 14, Folia 29
Poprzedni stan ENVS
Poprzedni stan ENVS
czerwiec 2004
Przetwarzanie metod w M3
 Sytuacja jest nieco bardziej złożona, gdy wiązana jest nazwa m
występująca w q2 i m jest nazwą metody.
 Na stos ENVS muszą być również włożone prywatne własności klasy, do
której należy metoda m oraz prywatne własności obiektu przetwarzanego
przez tę metodę (którego referencja jest zwrócona przez q1).
Wywołanie
metody m
Sekcje wkładane
przy wywołaniu
metody m
Lokalne
środowisko metody
m
nested_private(ri)
nested_private(iK2)
Operator θ
Poprzedni
stan ENVS
Koniec
działania
metody m
nested_public(ri)
nested_public(ri)
nested_public(ri)
nested_public(iK1)
nested_public(iK1)
nested_public(iK1)
nested_public(iK2)
nested_public(iK2)
nested_public(iK2)
nested_public(iK3)
nested_public(iK3)
nested_public(iK3)
Poprzedni stan
ENVS
Poprzedni stan
ENVS
Poprzedni stan
ENVS
© K.Subieta. Obiektowe języki zapytań 14, Folia 30
Koniec
przetwarzania
ri przez q2
Poprzedni
stan ENVS
czerwiec 2004
Schemat bazy danych w modelu M3
 Plus oznacza własność publiczną, minus oznacza własność prywatną.
Osoba[0..*]
+ Nazwisko
- RokUr
+ Wiek
Prac[0..*] + PracujeW
- Zar
+ ZmieńZar
+ ZarNetto
© K.Subieta. Obiektowe języki zapytań 14, Folia 31
+ Zatrudnia[0..*] Dział[0..*]
+ Nazwa
+ Budżet
czerwiec 2004
Poprawne i niepoprawne konstrukcje w M3
Prac where Nazwisko = „Nowak”
Osoba where RokUr < 1975
(Prac where Nazwisko = „Nowak”).Zar
(Prac where Nazwisko = „Nowak”).Wiek
procedure Wiek { return BieżącyRok – RokUr }
procedure ZmieńZar( nowy ) { self.Zar := nowy }
Poprawna
Błędna
Błędna
Poprawna
Poprawna
Poprawna
procedure ZarNetto( )
{ return if RokUr > 1955 then 0.9 * Zar else 0.8 * Zar }
Błędna
procedure ZarNetto( )
return if Nazwa = “Marketing” then 0.9 * self.Zar
...
Prac where Dział (Budżet > 100 * ZarNetto)
Błędna
© K.Subieta. Obiektowe języki zapytań 14, Folia 32
else 0.8 * self.Zar }
czerwiec 2004
Download