I.
Wprowadzenie do  języków zapytań (1)
II.
Wprowadzenie do  języków zapytań (2)
III.
Pojęcia obiektowości w bazach danych (1)
  Wstęp
  1. Co to jest obiektowość?
  2. Obiekt
  3. Metody związane z obiektem
  4. Obiekt złożony
  5. Relatywizm obiektów
  6. Zasada wewnętrznej identyfikacji
  7. Powiązania pomiędzy obiektami
  8. Hermetyzacja i ukrywanie informacji
  9. Mechanizm komunikatów
  Podsumowanie
  Zadania
IV.
Pojęcia obiektowości w bazach danych (2)
V.
Podstawy semantyczne języków zapytań
VI.
Modele składu obiektów
VII.
Stos środowisk, rezultaty zapytań, funkcja nested
VIII.
Język SBQL (Stack-Based Query Language) (1)
IX.
X.
Dalsze własności SBQL
XI.
Operatory order by i group by
XII.
Przetwarzanie struktur nieregularnych
XIII.
Rozszerzenie języków zapytań o konstrukcje imperatywne
XIV.
Procedury, procedury funkcyjne, metody, reguły zakresu
XV.
Parametry procedur i metod, procedury rekurencyjne, optymalizacja poprzez modyfikację zapytań

 

9. Mechanizm komunikatów

Komunikat jest wyrażeniem językowym skierowanym do obiektu. Mechanizm komunikatów polega na wywoływaniu jednej z metod skojarzonej z tym obiektem. Nazwa użyta w komunikacie jest nazwą uaktywnianej metody. Źródłem komunikatu jest aktualnie działający program, w szczególności, może to być aktualnie wykonywana metoda. Komunikat może mieć zero, jeden lub więcej parametrów. Obiekt otrzymujący komunikat wykonuje odpowiednią metodę, a ta z kolei może zmienić jego stan.

Po wykonaniu metody obiekt, który otrzymał komunikat, może zwrócić odpowiedź do obiektu lub programu, który go wysłał. Odpowiedź ta nie jest komunikatem. Może się zdarzyć, że obiekt otrzyma komunikat, któremu nie odpowiada żadna ze skojarzonych z nim metod; w tym przypadku obiekt ignoruje komunikat, sygnalizuje błąd lub powoduje uruchomienie mechanizmu wyjątków.


9.1.
Komunikat a wołanie procedury

Czytelnik znający podstawy programowania z łatwością dostrzeże, że komunikat jest w zasadzie tym samym, co wołanie procedury. W istocie, pojęcia są podobne, ale występują też różnice, na które chcielibyśmy zwrócić uwagę. Przy wołaniu procedury działającej na obiekcie, obiekt musi być przekazany poprzez parametr:

nazwa_procedury( obiekt_adresat, parametr1, parametr2,...)
P3.4.

Wypłać( KontoKowalskiego, 1000 );

W przypadku komunikatu składnia jest nieco inna: obiekt_adresat poprzedza wywołanie metody i jest wyłączony z zestawu jej parametrów:

obiekt_adresat . nazwa_metody( parametr1, parametr2,...)
P3.5.

KontoKowalskiego . Wypłać( 1000 );

Istotna różnica dotyczy jednak nie składni, lecz semantyki. W odróżnieniu od procedury, komunikat nie określa, która konkretnie metoda ma być wywołana. Komunikat jest kierowany do obiektu i dopiero wtedy podejmowana jest decyzja odnośnie do wywoływanej metody. Będzie nią metoda skojarzona z danym obiektem posiadająca nazwę określoną przez komunikat.

Wybór metody jest więc dynamiczny, w czasie wykonania. W przypadku wołania procedury jest ona określana statycznie, czyli w czasie kompilacji. Ta różnica ma doniosłe konsekwencje dla modelowania pojęciowego i ponownego użycia; przedyskutujemy to bardziej szczegółowo przy omawianiu pojęcia polimorfizmu. Zwrócimy tu uwagę, że niekiedy metoda może być również określona już podczas kompilacji programu, ale jest to traktowane raczej jako zabieg optymalizacyjny. Zasadą jest wybór metody w czasie wykonania.

Drugą ważną różnicą semantyczną jest udostępnienie wiązania nazw występujących wewnątrz ciała metody z komponentami (atrybutami) obiektu-adresata. Również sam obiekt-adresat jest udostępniony wewnątrz ciała metody poprzez standardowe nazwy (self w SELF i Smalltalk'u lub this w C++ i Java). Metody mogą mieć oczywiście dostęp do dowolnych publicznych własności bazy danych, środowiska danej aplikacji lub środowiska komputera.

Składnia wyrażenia zawierającego komunikat może być nieco różna w zależności od tego, czy mamy do czynienia z metodą w sensie procedury, czy też z metodą w sensie funkcji. Podany wyżej przykład odnosi się do przypadku, gdy metoda ma charakter procedury: KontoKowalskiego.Wypłać(1000) jest samodzielnym zdaniem języka programowania. Metody mogą mieć również charakter funkcji. Np. metoda WysokośćSalda podająca wysokość salda może być użyta w następującym wyrażeniu:

P3.6.

if KontoKowalskiego . WysokośćSalda( ) -ŻądanieWypłaty> 0 then ...

Inną charakterystyką metod jest powodowanie przez nie efektów ubocznych, czyli zmiany stanu na zewnątrz lokalnego środowiska danej funkcji. Istnieje tu kilka możliwości:

  • Metody "czysto" funkcyjne nie posiadające efektów ubocznych, takie jak funkcja Wiek dla obiektów Osoba. Takie metody są równoważne wirtualnym (wyliczanym, pochodnym) atrybutom obiektu.
  • Metody (proceduralne lub funkcyjne), których efekty uboczne są ograniczone do obiektu będącego adresatem komunikatu.
  • Metody (proceduralne lub funkcyjne), których efekty uboczne wykraczają poza obiekt będący adresatem komunikatu.


Dwie pierwsze możliwości można traktować jako realizację klasycznej koncepcji komunikatów i metod. Trzecia możliwość prowadzi do tego, że w wyniku komunikatu skierowanego do obiektu może zostać zmieniony stan zupełnie innego obiektu. Wielu autorów uważa taką sytuację za nieprawidłową, ale z drugiej strony, brak takich możliwości może poważnie ograniczyć elastyczność środków programowania. Większość języków i systemów dopuszcza metody posiadające dowolne efekty uboczne.


9.2. Komunikaty w obiektowych językach zapytań

Obiektowe języki zapytań, takie jak OQL lub SBQL, oprócz standardowej formy wysyłania komunikatu

obiekt_adresat . nazwa_metody( [parametr {, parametr}] )

mogą dopuszczać także inne formy. Wiąże się to z własnościami języków zapytań. Generalna zasada, która obowiązuje dla komunikatów, jest następująca: wszędzie tam, gdzie może być użyta nazwa atrybutu, może być użyte wołanie metody, czyli komunikat. W przypadku języków zapytań nazwy atrybutów mogą występować w różnych konstrukcjach, np. w zdaniu select, where, order_by itd. Aby to zilustrować, posłużymy się przykładami w SBQL. Załóżmy, że baza danych zawiera wiele obiektów PRACOWNIK, które oprócz standardowych atrybutów Nazwisko, Zarobek, RokUrodz itd. mają także metodę Wiek, która oblicza wiek pracownika. Metodę tę można wywołać poprzez następujące zapytania:

P3.7.

Podaj wiek Kowalskiego:

(Pracownik where Nazwisko = "Kowalski") . Wiek


P3.8.

Podaj nazwiska pracowników, którzy przekroczyli 45 lat:

(Pracownik where Wiek > 45) . Nazwisko

W ostatnim przykładzie wysłanie komunikatu Wiek występuje w warunku selekcji. W SBQL domyślnym adresatem komunikatu Wiek jest (jednocześnie lub kolejno) każdy z obiektów identyfikowanych przez zapytanie stojące przed klauzulą where. Jak pokażemy dalej przy omawianiu formalnej semantyki SBQL, w powyższych zdaniach komunikat Wiek występuje tylko raz, ale zostanie on wysłany wiele razy, do wszystkich pracowników.

P3.9.

Podaj listę pracowników uporządkowanych według wieku, a w ramach tego samego wieku według nazwisk:

Pracownik order by ( Wiek, Nazwisko )

W tym przypadku komunikat zostaje wysłany wewnątrz klauzuli ustalającej warunki sortowania. Rezultat tego komunikatu jest konkatenowany z wartością atrybutu Nazwisko, tworząc w ten sposób klucz sortowania.


9.3. Przesyłanie komunikatów a asynchroniczne przetwarzanie

Podane wyżej sytuacje pokazują, że komunikaty nie mogą być interpretowane poprzez zastosowanie powierzchownej analogii do porozumiewania się miedzy ludźmi (jak to czyni wielu autorów). Komunikaty i odpowiadające im metody są tworami formalnymi o precyzyjnej semantyce i zastosowaniach. Niestety, dosłowne tłumaczenie terminu "przesyłanie komunikatów" (message passing) bardzo często jest mylnie interpretowane. Niektórzy autorzy uważają paradygmat przesyłania komunikatów za postulat równoległego (lub "asynchronicznego") działania; tego błędu interpretacyjnego nie ustrzegli się twórcy języka Smalltalk. Zgodnie z ich niektórymi wypowiedziami, obiekty komunikują się ze sobą asynchronicznie i jednocześnie wykorzystując mechanizm komunikatów, zaś obiektowość postuluje taką równoległość lub wręcz ją rozwiązuje.

Wyraźnie musimy stwierdzić, że są to poglądy nieuzasadnione i naiwne. Są one oparte na budowaniu analogii ze światem rzeczywistym, gdzie obiekty posiadają własną autonomię i funkcjonują niezależnie od siebie, komunikując się między sobą w ramach swoich potrzeb. Obiektowość jednak nic takiego nie zakłada. Przetwarzanie równoległe lub asynchroniczne jest ważnym i trudnym problemem, ortogonalnym w stosunku do obiektowości, a w szczególności do mechanizmu przesyłania komunikatów.

Komunikat będziemy rozumieć wyłącznie jako obiektowy odpowiednik wołania procedury. Może się zdarzyć, i tak jest najczęściej, że to wołanie następuje z wnętrza pewnej metody mA związanej aktualnie z obiektem A i powoduje uruchomienie metody mB związanej z obiektem B. W takiej sytuacji mówi się, że obiekt A "wysłał komunikat" do obiektu B - ale jest to wyłącznie pewien skrót terminologiczny na oznaczenie sytuacji semantycznej. Nie może on być interpretowany w terminach języka potocznego. Jeżeli metoda mB jest funkcyjna, to zwraca ona wartość do tego fragmentu kodu metody mA, który ją wywołał na takiej samej zasadzie, jak dla procedur funkcyjnych. Jest oczywiste, że tego przekazywania informacji od B do A nie można mylić z komunikatem, gdyż jego zadaniem nie jest wywołanie metody wewnątrz A, lecz kontynuacja przetwarzania przez metodę mA.


9.4. Komunikat a zdarzenie

Kolejnym częstym nieporozumieniem jest utożsamianie pojęcia komunikatu z pojęciem zdarzenia. Chociaż istnieje tu spora zbieżność znaczeniowa, szczególnie na etapie analizy i projektowania, pojęcia te są różne i wzajemnie ortogonalne. Kryterium pozwalające je rozróżnić związane jest z przebiegiem sterowania programu. Komunikat (czyli wołanie procedury) jest elementem zdeterminowanego sterowania tym przebiegiem: programista wie, dlaczego i po co w danym miejscu programu pisze fragment kodu, w którym znajduje się klauzula wysłania komunikatu. Przykładowo, zadaniem komunikatu jest wywołanie metody obliczającej dochód pracownika, który to dochód następnie jest użyty do obliczenia podatku.

Zdarzenie ma całkowicie inną semantykę. Jest to pewien fakt (lub zmiana stanu) zarejestrowany w środowisku wewnętrznym lub zewnętrznym programu, występujący losowo w stosunku do sterowania programu i nie uwzględniany w tym sterowaniu explicite. Takim faktem może być naciśnięcie przez użytkownika klawisza Esc, co oznacza, że rezygnuje on z kontynuacji tego fragmentu programu. W większości przypadków nie byłoby rozsądne, aby programista w każdym miejscu sterowania programu badał, czy nie nastąpiło naciśnięcie klawisza Esc lub czy nie nastąpiły inne podobne zdarzenia.

Tego rodzaju sytuacje są obsługiwane przez specjalne konstrukcje języków programowania, zwane mechanizmem wyjątków. Wyjątek jest zdarzeniem, które przerywa normalną nitkę sterowania i przekazuje sterowanie do specjalnego fragmentu kodu przeznaczonego do obsługi tego wyjątku. Mechanizm takich zdarzeń i odpowiadających im fragmentów kodu służących do ich obsługi jest częścią zupełnie innego paradygmatu programowania (zwanym programowaniem zdarzeniowym (event-driven programming)), który jest ortogonalny  w stosunku do obiektowości i mechanizmu przesyłania komunikatów. Dodajmy, że dla wielu zastosowań jest to paradygmat bardzo atrakcyjny. Stanowi on o sukcesie języków czwartej generacji (Fourth Generation Languages, 4GL), narzędzi prototypowania (Rapid Software Prototyping, RAD) lub narzędzi programowania wizyjnego. Podobny paradygmat reakcji na losowo występujące zdarzenia występuje także w bazach danych w postaci tzw. aktywnych reguł (active rules), inaczej wyzwalaczy (triggers). Paradygmat ten dla niektórych zastosowań jest bardzo atrakcyjny, ale jest całkowicie ortogonalny w stosunku do obiektowości.

Na marginesie dodajmy, że mechanizm zdarzeń lub wyjątków może być różnie realizowany. W najprostszej realizacji jest równoważny instrukcji goto, czyli skokowi z danego miejsca programu do innego miejsca programu. Bardziej odpowiednia jest realizacja tego mechanizmu w postaci równolegle wykonywanych procesów lub wątków. Taka realizacja rodzi jednak szereg dalszych problemów, m.in. z modelowaniem pojęciowym, synchronizacją i wydajnością.

Copyrights © 2006 PJWSTK
Materiały zostały opracowane w PJWSTK w projekcie współfinansowanym ze środków EFS.