Rozdział 22
Poza granice modelu dwuwarstwowego
Gdy architektura klient/serwer weszła po raz pierwszy w modę, wydawało się
w miarę pewne, że rozwój tej technologii zmierzał będzie w kierunku zapełnienia
owej szerokiej luki, jaka istniała między kliencką a serwerową stroną „równania”.
Reguły logiki aplikacji (business rules) można było co prawda konstruować na
serwerze, lecz wbudowanie istniejących po stronie serwera reguł logiki aplikacji
w realizowane po stronie klienta aplikacje okazało się trudnym zadaniem -
zwłaszcza na wczesnym etapie rewolucji związanej z architekturą klient/serwer.
Spodziewano się, że pewnego dnia serwery i klienci zaczną współpracować ze
sobą na tyle dobrze, iż ograniczenia takie zostaną pokonane i użytkownicy
końcowi otrzymają w pełni spójne aplikacje.
Na nieszczęście, w miarę jak coraz więcej producentów przechodziło na
technologię klient/serwer, cel ów stawał się coraz bardziej odległy. Programiści,
rozczarowani brakiem integracji między serwerami baz danych i narzędziami do
programowania aplikacji, zaczęli standardowo wbudowywać reguły logiki
aplikacji do programów. Nader często spotykało się systemy z regułami i więzami
(constraint) umieszczonymi całkowicie po stronie klienta i z żadnymi lub
przynajmniej niewieloma na serwerze bazy danych.
Chociaż było to najlepszym sposobem na zaopatrywanie użytkowników
końcowych we w pełni dopracowane aplikacje, to jego wada polegała na tym, że
zrealizowanych po stronie klienta więzów nie było bynajmniej łatwo
współużytkować w jednocześnie kilku narzędziach ani też przenosić na inne
platformy tak, jak więzów po stronie serwera. W
efekcie programiści
implementacje tych samych reguł logiki aplikacji musieli konstruować
wielokrotnie - dla każdego narzędzia programistycznego, jakiego używali, i dla
każdej platformy, jaką wspierali. Ostatecznym rezultatem było mnóstwo
straconego czasu i tyle samo błędów powstałych przy przepisywaniu reguł logiki
aplikacji z jednego miejsca do drugiego.
Rozwiązaniem dla problemu tego i jeszcze paru innych, których istnienia we
wczesnym okresie rozwoju technologii klient/serwer nawet nie podejrzewano,
okazał się model wielowarstwowy (multi-tier). Zamiast tylko dwóch poziomów -
klienta i serwera - podejście wielowarstwowe dopuszcza ich wiele. W systemie
wielowarstwowym pomiędzy klientem a serwerem może być kilka poziomów,
z których każdy pełni specyficzną rolę.
642
Część IV
Delphi umożliwia programowanie aplikacji wielowarstwowych dzięki swym
czterem kluczowym technologiom:
brokerowi zdalnych danych - Remote Data Broker,
brokerowi wiêzów - Constraint Broker,
wsparciu przetwarzania aktówkowego - Briefcase computing,
wsparciu dla częściowych pakietów danych - Partial data package.
Każdą z nich omówię oddzielnie i pokażę, jak korzystać z nich w prawdziwych
aplikacjach.
Broker danych zdalnych
Istniejąca w Delphi technologia Brokera danych zdalnych (Remote Data Broker)
pozwala budować aplikacje typu „chudego” klienta, nie wymagające wsparcia
obsługi baz danych (database engine) i sterowników na komputerze klienta.
Aplikacje te bowiem komunikują się poprzez sieć z
serwerem aplikacji,
zawierającym komponenty
TTable
,
TQuery
i
TStoredProc
niezbędne do
uzyskania dostępu do serwera bazy danych. W serwerze aplikacji można
ustanowić więzy i reguły logiki aplikacji, które mogą być współużytkowane przez
te programy, które poprzez serwer aplikacji uzyskują dostęp do serwera bazy
danych. Zapewnia to centralizację reguł logiki aplikacji i jednocześnie pozwala
każdej aplikacji klienta funkcjonować tak, jakby w niej samej mieściły się reguły
logiki aplikacji.
UWAGA:
Chociaż prawdą jest, że model „chudego” klienta pozwala budować aplikacje, nie
wymagające dołączania do nich obsługi bazy danych Borlanda, to aplikacje typu
chudego klienta wymagają jednak jakiegoś rodzaju mechanizmu do
komunikowania się z serwerem aplikacji. Funkcja taka znajduje się w pliku
DBCLIENT.DLL
, który trzeba dystrybuować wraz z samą aplikacją chudego
klienta. Wydaje się, że
DBCLIENT.DLL
potrzebny jest tylko wtedy, gdy aplikacja
ta dokonuje zmian w danych i zmiany te wysyła do serwera, lecz by zabezpieczyć
się z każdej strony, najlepiej plik ten dołączać do każdej aplikacji omawianego
typu.
Aby zbudować Brokera danych zdalnych, należy wykonać następujące operacje:
1. Sprawdź, czy serwer bazy danych InterBase pracuje.
2. Uruchom Eksplorator baz danych (Database Explorer) i zdefiniuj nowy alias
BDE
o nazwie
IB
_
EMPLOYEE
, skojarzony z bazą danych
EMPLOYEE.GDB
,
Rozdział 22 Poza granice modelu dwuwarstwowego
643
dostarczaną wraz z Delphi (standardowo baza ta jest w
C:\Program
Files\Borland\IntrBase\Examples
).
3. Nowy alias kliknij prawym klawiszem myszy i wybierz
Import
to
Dictionary
.
Spowoduje to importowanie ograniczeń bazy danych oraz innych informacji
słownika danych z bazy InterBase do słownika danych Delphi.
4. Wyjdź ze Eksploratora baz danych i powróć do Delphi.
5. Kliknij opcję menu
File
\
New
Application
, aby rozpocząć nową aplikację
Delphi.
6. Kliknij opcję menu
File\New
i w oknie dialogowym
New
Items
kliknij
dwukrotnie opcję
Remote
Data
Module
.
7. W kreatorze
Remote
Dataset
Wizard
podaj nazwę klasy (
Class
Name
) dla
Brokera danych zdalnych.
8. Na formularzu brokera umieść komponent
TTabel
, komponent
Database
i komponent
Session
.
9. Właściwość
AutoSessionName
komponentu
Session
ustaw na
True
.
10. Właściwość
AliasName
komponentu
Database
ustaw na
IB_EMPLOYEE
,
a jego właściwość
DatabaseName
na
IB_EMPLOYEE
. Właściwość
LoginPrompt
ustaw na
False
i w polu edycyjnym właściwości
Params
wpisz
dwa następujące parametry:
USER NAME=SYSDBA PASSWORD= masterkey
11. Jego właściwość
HandleShared
ustaw na
True
.
12. Właściwość
DatabaseName
komponentu
Table
ustaw na
IB_EMPLOYEE
,
a właściwość
TableName
na
DEPARTMENT
.
13. Prawym klawiszem myszy kliknij komponent
Table
i
wybierz opcję
Export...from data module
.
14. Zapisz projekt na dysku.
Unit2
zachowaj jako
RDB01
.
PAS
,
Unit1
jako
RDB00.PAS
, a cały projekt jako
RDB.DPR
.
15. Teraz uruchom aplikację RDB, aby zarejestrować jej serwer COM. Zaraz po
załadowaniu można ją na powrót zamknąć.
Po utworzeniu brokera danych jesteśmy już gotowi do utworzenia korzystającej
z niego aplikacji. Zbudujemy zatem aplikację klienta danych zdalnych (RDC,
Remote Data Client), wykonując następujące czynności:
1. Rozpocznij nową aplikację Delphi, klikając
File\New Application
.
2. Na domyślnym formularzu umieść
ClientDataSet
,
RemoteServer
i
DataSource
.
644
Część IV
3. Dodaj jeszcze do formularza komponent
DBGrid
.
4. Właściwość
ServerName
komponentu
RemoteServer
ustaw na
RDB.RemoteDataBroker
.
5. Właściwość
RemoteServer
komponentu
ClientDataSet
ustaw na
RemoteServer1
, zaś jego
ProviderName
na
Table1
(
Table1
odwołuje
się do tablicy
DEPARTMENT
w naszej aplikacji RDB).
6. Właściwość
DataSet
komponentu
DataSource
ustaw tak, by wskazywała na
komponent
ClientDataSet
, a
właściwość
DataSource
komponentu
DBGrid
tak, by wskazywała
DataSource1
.
7. Otwórz komponent
ClientDataSet,
ustawiając na
True
jego właściwość
Active
.
Powinniśmy teraz w
DBGrid
zobaczyć dane z tabeli DEPARTMENT. Jeśli tak, to
nasze gratulacje - Czytelnik utworzył właśnie Brokera danych zdalnych (Remote
Data Broker) i aplikację kliencką.
Zanim pójdziemy dalej, zapamiętajmy nasz projekt na dysku. Moduł
Unit1
zapiszmy jako RDC00.PAS, a projekt jako RDC.DPR („RDC” oznacza Remote
Data Client, czyli klient danych zdalnych).
Broker więzów
Prócz pośredniczenia w uzyskiwaniu danych, dostępny w Delphi komponent
modułu danych zdalnych może również pośredniczyć w realizowaniu więzów.
Może na przykład użyć informacji o więzach, importowanych z serwera bazy
danych, by uchronić nas przed samym nawet wysłaniem niepoprawnych danych do
serwera. Redukuje to ruch w sieci i przyspiesza pracę aplikacji. By przekonać się,
jak coś takiego działa, wykonajmy następujące czynności:
1. Ponownie załaduj aplikację RDB do Delphi.
2. Dwukrotnie klikając komponent
Table
wywołaj edytor pól i, aby dodać nowe
pola, naciśnij CTRL+A. Następnie dodaj do formularza wszystkie pola tabeli
DEPARTMENT naciskając
OK
.
3. Kliknij pole
Budget
w edytorze pól. W Inspektorze obiektów powinieneś
zobaczyć odpowiadający mu
ImportedConstraint
.
4. Zamknij edytor pól, zapisz aplikację i zrekompiluj ją.
5. Następnie aplikację RDC ponownie otwórz i uruchom.
Rozdział 22 Poza granice modelu dwuwarstwowego
645
6. Gdy aplikacja pojawi się na ekranie, zacznij redagować tabelę DEPARTMENT
przy pomocy kontrolki
DBGrid
i spróbuj wprowadzić niepoprawną wartość do
kolumny Budget (niepoprawna jest każdą wartość mniejsza od 10001).
Zobaczymy, że wartość ta zostanie natychmiast odrzucona, nawet bez wysyłania
jej do serwera. Broker więzów (Constraint Broker) implementuje bowiem swą
własną wersję więzów z serwera i przechwytuje wszystkie niepoprawne wartości
danych jeszcze zanim zostaną wysłane do serwera. Zwróćmy uwagę na włączenie
więzów do tekstu wyświetlonego komunikatu.
Wsparcie dla przetwarzania aktowkówego
Prócz pośrednictwa w przekazywaniu danych tam i z powrotem pomiędzy
aplikacją a serwerem aplikacji, Delphi może również przechowywać dane lokalnie.
Pozwala to na autonomiczną (off-line) pracę z danymi z serwera, z użyciem
techniki „aktówkowej”. By zobaczyć, jak metoda ta działa w praktyce, wykonajmy
następujące kroki:
1. Zakończ aplikację RDC, o ile jeszcze działa.
2. Na głównym formularzu RDC umieść trzy komponenty
Button
,.
3. Pierwszy przycisk nazwij
btSave
, drugi
btLoad
, trzeci
btSend
.
4. Właściwość
Caption
przycisku
btSave
ustaw na ‘
&Save locally
’,
przycisku
btLoad
na ‘
&Load local data
’, zaś przycisku
btSend
na ‘
Send
changes to server
’.
5. Tak zmodyfikuj wymiary przycisków, by ich napisy widoczne były w całości.
6. Kliknij dwukrotnie
bdSave
i
jego zdarzenie
OnClik
ustaw na:
ClientDataSet1.SaveToFile(‘C:\TESTLOCAL.DAT’);
7. Kliknij dwukrotnie
bdLoad
i
jego zdarzenie
OnClik
ustaw na:
ClientDataSet1.LoadFromFile(‘C:\TESTLOCAL.DAT’);
8. Kliknij dwukrotnie
bdSend
i
jego zdarzenie
OnClik
ustaw na:
ClientDataSet1.ApplyUpdates(0);
9. Zapisz aplikacje na dysku, po czym uruchom ją.
10. Gdy aplikacja ukaże się na ekranie, kliknij
btSave
.
11. Następnie odszukaj aplikację RDB (która została uruchomiona przez
mechanizm automatyzacji) i zamknij ją. Zignoruj komunikat o błędzie, który
zostanie wyświetlony, i kliknij
Yes
, aby zamknąć serwer aplikacji.
646
Część IV
12. Powróciwszy do RDC zauważysz, że możesz nadal pracować z załadowanym
zestawem danych. Dokonaj w nich kilku zmian, a następnie zapamiętaj je
lokalnie klikając przycisk
btSave
.
13. Zamknij aplikację RDC, a następnie uruchom ją raz jeszcze. Spowoduje to
ponowne otwarcie serwera aplikacji RDB. Zauważ, że dokonane zmiany
zostały utracone, ponieważ dane zostały na powrót pobrane z serwera bazy
danych.
14. Kliknij przycisk
btLoad
, aby załadować lokalną kopię danych. Teraz
powinieneś zobaczyć swoje modyfikacje.
15. Kliknij przycisk
btSend
, aby dokonane zmiany znalazły odzwierciedlenie
w serwerze. Jeśli teraz wyjdziesz z aplikacji i ponownie ją załadujesz, to
spostrzeżesz, że zmiany, które pierwotnie zapamiętane były lokalnie, zostały
przeniesione do kopii danych na serwerze. I to jest właśnie to, co mamy na
myśli używając metafory „aktówki” - dane mogą być początkowo zapisywane
zewnętrznie i dopiero później, w dogodnej chwili, przenoszone, a mimo to
przez cały czas możemy pracować z nimi w sposób ciągły.
Częściowe pakiety danych
Inną, wielce użyteczną cechą zaimplementowanej w Delphi technologii brokera
danych jest możliwość ściągania (download) do aplikacji klienckiej częściowych
pakietów danych. Zamiast ładować cały zestaw danych rezultatu zapytania,
projektant aplikacji może zdecydować się na pobieranie za jednym razem tylko
małego podzbioru rekordów. Jest to szczególnie i w pierwszym rzędzie korzystne
w tych aplikacjach, które zwykle otrzymują jedynie niewielkie zestawy danych,
takich jak aplikacje typu pozycja główna/szczegóły (master/detail). By zobaczyć,
jak cecha ta uwidacznia się w praktyce, wykonajmy następujące kroki:
1. Zakończ aplikację RDC, jeśli jeszcze działa.
2. Umieść na formularzu komponent
TStatusBar
, który automatycznie
„doklei” się do dolnej krawędzi formularza.
3. Jego właściwość
SimplePanel
ustaw w Inspektorze obiektów na
True
.
4. Kliknij komponent
DataSource
, a
następnie w
Inspektorze obiektów
dwukrotnie jego zdarzenie
OnDataChange
.
5. Do zdarzenie
OnDataChange
wpisz następujący kod:
With DataSource1.DataSet do
StatusBar1.SimpleText :=
Format(‘%d / %d’, [RecNo, RecordCount]);
Rozdział 22 Poza granice modelu dwuwarstwowego
647
6. Właściwość
PacketRecords
komponentu
ClientDataSet
ustaw
w Inspektorze obiektów na
5
. Spowoduje to, że z serwera pobieranych będzie
po pięć wierszy na raz. Ustawienie jej na
-1
(domyślne) spowoduje pobieranie
wszystkich wierszy, natomiast
0
pobiera jedynie informacje ze słownika
danych.
7. Uruchom swoją aplikację. Podczas przewijania rekordów w komponencie
DBGrid zauważysz, że aplikacja pobiera pięć nowych wierszy za każdym
razem, gdy przekroczysz wielokrotność pięciu dotychczas wyświetlanych. Ten
poziom sterowania pozwala w pełni określić, jaka część zestawu rezultatów
będzie sprowadzana do klienta za jednym razem. Może to mieć decydujący
wpływ na szybkość działania, zwłaszcza przy pracy z bardzo dużymi tablicami
lub przy sięganiu do danych poprzez WAN.
Na rysunku 22.1 pokazano, jak powinna wyglądać aplikacja RDC.
Rysunek 22.1.
Nasza aplikacja
klienta danych
zdalnych w fazie
wykonania.