22 rozdzial 21 JOMMG3PI6XBHLJOK Nieznany (2)

background image

Rozdział 21

Reguły logiki aplikacji w aplikacjach
Delphi

W rozdziale tym omawiamy aplikacyjną stronę udanej implementacji reguł logiki
aplikacji. Jak to już powiedziałem w rozdziale o regułach logiki aplikacji
bazujących na serwerze, w moim głębokim przekonaniu reguły te powinny być -
jeśli to tylko możliwe - implementowane po serwerowej stronie aplikacji. Jednak
w realnych aplikacjach nieuniknione będzie uzupełnianie reguł logiki aplikacji
zrealizowanych po stronie serwera regułami osadzonymi w oprogramowaniu
pośredniczącym lub klienta. Chciałbym wierzyć, że pewnego dnia między
serwerami baz danych, produktami middleware i narzędziami do tworzenia
oprogramowania zaistnieje taki synergizm, iż problem ten zniknie całkowicie
i programista przestanie zajmować się tym, gdzie jego reguły są
zaimplementowane, a skoncentruje się na tym, jak są one zaimplementowane.

Wśród programistów z długim stażem występuje skłonność do umieszczania
znacznej części reguł logiki aplikacji w

samej aplikacji. Świat narzędzi

programistycznych jest dla nich terytorium już „oswojonym”, natomiast
platformom DBMS tradycyjnie brakowało owych wyszukanych narzędzi do
wdrażania reguł logiki aplikacji, bez których aplikacje na wysokim poziomie nie
mogą się obejść.

Abstrahując jednak od wszelkich skłonności, przeniesienie reguł logiki aplikacji
hurtem do niej samej nie jest - jak już powiedziałem - żadnym rozwiązaniem.
Środowisko programistów powinno zmusić producentów DBMS i oprogramo-
wania pośredniczącego do stworzenia wszechstronnych interfejsów dla reguł
logiki aplikacji - czyli takich interfejsów, jakich potrzebują profesjonalne
aplikacje. Odpowiedzią nie może być zwykle „machnięcie ręką” i wyproduko-
wanie banalnego rozwiązania, bazującego na pośledniej technologii. Najlepszym
podejściem byłoby skłonienie producentów do tego, by wyszli na przeciw
potrzebom swych klientów - by dostarczyli takiego wsparcia reguł logiki aplikacji,
jakiego użyć można w prawdziwych aplikacjach. Zanim to nie nastąpi, systemy
klient/serwer będą nadal równie nieodporne na naruszenia reguł logiki aplikacji, co
ich niegdysiejsi plikowi odpowiednicy.

Ku chwale producentów DBMS i oprogramowania pośredniczącego przyznać
trzeba jednak, że w korygowaniu swych strategii reguł logiki aplikacji poczynili
ostatnio spore postępy. W przeszłości większość implementacji reguł logiki

background image

628

Część IV

aplikacji bazujących na serwerze charakteryzowała się całkowitą „hermetycz-
nością” - były bezpieczne - lecz dla programisty „nieprzyjazne”. Programiści mieli
na przykład problemy ze skłonieniem obiektów bazy danych i obiektów aplikacji
do bezkonfliktowej współpracy. Jeśli na przykład jako źródło wartości dla
wstawianego wiersza użyty został domyślny obiekt Sybase, to skąd aplikacja
mogłaby o tym wiedzieć i w jaki sposób miałaby wyświetlić na ekranie domyślne
wartości kolumn, gdyby użytkownik dodał nowy wiersz do tabeli? Programiście
pozostawał tylko wybór mniejszego zła - albo całkowite ignorowanie bazujących
na serwerze reguł logiki aplikacji i ponowne implementowanie ich w aplikacjach,
albo rezygnacja z

synchronizowania widoku aplikacji na ekranie z

jej

bazodanowymi partnerami. Żadna z tych możliwości nie była szczególnie
pociągająca i, jak zauważył kiedyś Jerry Garcia, „wybieranie mniejszego zła jest
także wybieraniem zła”.

Na szczęście w

ostatnich czasach producenci DBMS i

oprogramowania

pośredniczącego stają się coraz bardziej przyjaźni wobec użytkowników.
Rozsądne projektowanie reguł logiki aplikacji stało się obecnie łatwiejsze niż
kiedykolwiek. Jednocześnie narzędzia do projektowania aplikacji baz danych,
takie jak Delphi, stają się coraz bardziej świadome istnienia swych
„współrozmówców” w bazach danych i oprogramowaniu pośredniczącym i coraz
więcej o

nich wiedzą. W

rezultacie narzędzia programistyczne i

produkty

serwerowe zaczynają jednoczyć się w dążeniu do zaspokojenia potrzeb ludzi
W miarę, jak platformy DBMS, produkty middleware i narzędzia programistyczne
będą się uczyć ze sobą współpracować, implementowanie rozsądnej strategii reguł
logiki aplikacji będzie coraz łatwiejsze.

Jednak niezależnie od tego, w którą stronę zmierza postęp, na razie musimy
borykać się z tym, co dostępne jest tu i teraz. Aktualna sytuacja jest zaś taka, że
najprawdopodobniej będziemy musieli zaimplementować część reguł logiki
aplikacji w samej aplikacji. Jak już powiedziałem w rozdziale o regułach po
stronie serwera, podejście, jakie ja zwykle przyjmuję, jest następujące: na
platformie DBMS implementuję całą tę strategię reguł logiki aplikacji, którą mogę
tam zaimplementować,

a potem

w miarę potrzeby uzupełniam ją

w oprogramowaniu pośredniczącym (middleware) lub na kliencie. I nie ma tu
znaczenia, czy mamy do czynienia z

tabelami bazy Paradox, czy też

najprawdziwszą implementacją klient/serwer. To, czego nie mogę zaimplemento-
wać na serwerze, implementuję w middleware i w kliencie. Innymi słowy, tymi
konstrukcjami wypełniam luki w implementacji bazującej na serwerze.

Rozdział ten zajmuje się aplikacyjną stroną prawidłowej implementacji reguł
logiki aplikacji. Dokonuje przeglądu różnych sposobów planowania efektywnej
strategii reguł logiki aplikacji w naszym programie. Dowiemy się w nim na
przykład, że w Delphi są cztery główne poziomy projektowania bazujących na
oprogramowaniu reguł logiki aplikacji: poziom typu danych, poziom

background image

Rozdział 21 Reguły logiki aplikacji w aplikacjach Delphi

629

komponentów, poziom

TField

i poziom

TDataSet

. Każdy z nich omówię

szczegółowo, dzięki czemu Czytelnik bez trudu zrozumie, jak je stosować we
własnych aplikacjach.

Typy reguł logiki aplikacji

Reguły logiki aplikacji dzielą się na dwa wyraźnie odmienne typy: proste reguły
logiki aplikacji i złożone reguły logiki aplikacji. Proste zapewniają prostą
integralność encji. Gwarantują one na przykład, że dane liczbowe trafią do pola
liczbowego, kolumna dat zawierać będzie tylko daty i tak dalej. Proste reguły mają
zastosowanie niezależnie od tego, czym dana aplikacja jest lub do czego baza
danych jest używana.

Reguły złożone dotyczą bardziej zaawansowanych aspektów dostępu do bazy
danych - pozwalają one zapewnić integralność referencyjną. Zwykle są przy tym
specyficzne dla danej bazy danych lub nawet konkretnej tabeli.

W książce tej terminu reguły logiki aplikacji używam w jego najszerszym sensie.
Innymi słowy wszystko, o czym mówię, dotyczy zarówno reguł prostych, jak
i złożonych. Wszystko, począwszy od prostego sprawdzenia poprawności danych,
a na skomplikowanej integralności relacyjnej skończywszy, zmieści się pod
„parasolem” reguł logiki aplikacji. Chociaż z generalnego omówienia reguł logiki
aplikacji mógłbym wyłączyć techniki sprawdzania poprawności danych, to nie
widzę

żadnych korzyści z

takiego rozwiązania. Metody stosowane

w implementacji prostych reguł logiki aplikacji są takie same, jak metody używane
do tworzenia reguł złożonych. Dlatego moje podejście polega na omówieniu
efektywnego projektowania reguł logiki aplikacji z

perspektywy ogólnej.

Niezależnie od tego, czy są to reguły proste, czy złożone, wszystkie one zasługują
na jednakową uwagę.

Delphi dostarcza kilku sposobów konstruowania prostych reguł logiki aplikacji bez
żadnego kodowania i oferuje zgrabny komplet narzędzi do konstruowania reguł
złożonych z użyciem minimalnej ilości kodu. W rozdziale tym przeanalizujemy,
z perspektywy aplikacji, oba typy reguł.

Dwie zasady dla reguł logiki aplikacji

Pierwszym poziomem implementacji reguł logiki aplikacji po stronie klienta jest
poziom typu danych. Trzeba mieć zawsze na uwadze dwie podstawowe zasady
ilustrujące dobitnie doniosłość właściwego wyboru typu danych. Jeśli będziemy
ich przestrzegać, to zawczasu unikniemy wielu typowych problemów, jakie
niekiedy gnębią mniej doświadczonych programistów.

background image

630

Część IV

Zasada pierwsza

Pierwsza zasada ustanawiania reguł logiki aplikacji po stronie klienta brzmi:

Przede wszystkim używaj odpowiednich typów danych spośród dostępnych
w bazie.

VCL w Delphi narzuca kilka prostych, wbudowanych ograniczeń zależnych od
typu danych, jakie kolumna reprezentuje. Na przykład komponenty skojarzone
z danymi (data-aware) nie będą tolerować niepoprawnych dat w kolumnach o typie
„data”, znaków alfabetycznych w polach liczbowych, lub niewłaściwych wartości
w polach logicznych. By narzucić te ograniczenia, nie musimy tworzyć żadnego
kodu - Delphi zrobi to automatycznie. Po prostu trzeba od samego początku
używać odpowiednich typów danych.

Wśród programistów-weteranów zauważa się skłonność do nadużywania typów
łańcuchowych przy tworzeniu baz danych. Widziałem na przykład tabele
zawierające kolumny z datami, które były zdefiniowane z pomocą łańcuchowych
typów danych. Widziałem także dane liczbowe przechowywane w

polach

znakowych. Jeśli kolumna ma zawierać daty i tylko daty, to zdefiniujmy ją
korzystając z jakiegoś typu daty. Jeśli pole może zawierać tylko liczby, to
zdefiniujmy je przy pomocy numerycznego typu danych. Nie ma powodu, by
wartości numeryczne trzymać w kolumnach alfabetycznych.

Inna sytuacja, w której używanie właściwych typów danych ma dla poprawnego
projektowania reguł logiki aplikacji zasadnicze znaczenie, związana jest
z kolumnami zawierającymi wartości sekwencyjne. Choć niewątpliwie
moglibyśmy stworzyć system numerowania sekwencyjnego w kodzie Object
Pascal, to najlepiej będzie od razu użyć typów danych, które z samej swej natury
są sekwencyjne. Na przykład Sybase i Microsoft wspierają stosowanie kolumn
indentyfikacyjnych
(identity columns) - specjalnych kolumn, automatycznie
inkrementowanych przez serwer. Korzystając z autoinkrementowanych typów
danych unikamy konieczności samodzielnego generowania liczb sekwencyjnych
i zapewniamy sobie, że podstawowa reguła logiki aplikacji, o która nam chodzi -
liczby w kolumnie Y tablicy X muszą być sekwencyjne - zostanie zrealizowana
praktycznie bez żadnego wysiłku z naszej strony.

Zasada druga

Druga podstawowa zasada obowiązująca przy implementowaniu bazujących na
aplikacji reguł logiki aplikacji brzmi:

Używaj takich komponentów Delphi, które najlepiej odpowiadają bazowym typom
danych.

background image

Rozdział 21 Reguły logiki aplikacji w aplikacjach Delphi

631

Błędem, który w tej dziedzinie programiści robią najczęściej, jest zbyt szerokie
stosowanie komponentów do wprowadzania normalnego tekstu. Tego rodzaju
komponenty (takie jak

DBEdit

,

TEdit

i

TMaskEdit

) mogą umożliwić

wpisanie w pole wartości nieodpowiednich dla typu danej, z jaką komponent jest
skojarzony. Unikamy tego używając w

pierwszym rzędzie odpowiednich

komponentów.

Na przykład nie powinniśmy używać

DBEdit

dla pól logicznych. Pole to może

mieć tylko dwie wartości:

True

i

False

. Dlatego zamiast pola edycyjnego

użyjmy przycisku przełącznika (checkbox), przycisku opcji (radio button) lub listy
rozwijanej (drop-down list). Nie używajmy także

DBEdit

dla pól, których

wartości są tylko do odczytu; zamiast niego użyjmy komponentu DBText. Chroni
to zasoby systemowe i oszczędza kłopotu z ustawianiem właściwości

ReadOnly

komponentu. Podobnie

DBEdit

nie powinniśmy używać dla kolumn liczbowych,

które mogą mieć tylko niewielką ilość dopuszczalnych wartości - tutaj lepszy
będzie

DBRadioGroup

. Tabela 21.1 podaje, których komponentów najlepiej

używać z rozmaitymi podstawowymi typami danych.

Tabela 21.1. Typy danych w kolumnach i odpowiadające im komponenty VCL

Typ danych

Komponenty

Boolowski

DBCheckBox

,

DBRadioGroup

,

DBComboBox

,

DBListBox

Data

DBEdit

,

Calendar

,

SpinEdit

,

DataTimePicker

Liczbowy (pozwalający na
wprowadzanie dużych ilości wartości)

DBEdit

,

SpinEdit

Liczbowy (pozwalający na
wprowadzenie jedynie niewielkiej ilość
wartości)

DBRadioGroup

Łańcuch (pozwalający na wprowadzanie
dużych ilości wartości)

DBEdit

Łańcuch (pozwalający na wprowadzanie
jedynie niewielkiej ilości wartości)

DBComboBox, DBListBox

background image

632

Część IV

WSKAZÓWKA:

Typ kontrolki, używanej dla danego pola, można skonfigurować redagując
właściwość

TControlClass

w Eksploratorze Baz Danych (Database Explorer).

Po ustawieniu tej właściwości przeciągnięcie

TField

z Edytora Pól (Fields

Editor) na formularz spowoduje utworzenie wybranego komponentu.

Podstawowa zasada polega tu na użyciu takiego komponentu, który
w maksymalnym stopniu zapewnia poprawność wprowadzanych do niego danych,
zapobiegając przy tym wprowadzaniu wartości poprawnych.

Komponenty pochodne

Drugim poziomem implementacji reguł logiki aplikacji po stronie programu jest
warstwa komponentów pochodnych (custom component). Dzięki specyficznej,
opartej na komponentach architekturze Delphi, na rynku pojawił się cały szereg
wysokiej jakości narzędzi i bibliotek umożliwiających włączanie reguł logiki
aplikacji bezpośrednio do komponentów. Robi się to zwykle przez dziedziczenie
nowych komponentów ze znajdującej się w Delphi klasy komponentów

DataSet

i wbudowywanie do komponentów potomnych wymaganej reguły logiki aplikacji.

Narzędzia te umożliwiają na ogół specyfikowanie wszystkiego, co tylko może być
potrzebne - od indywidualnych masek wprowadzania dla pól, do złożonych
zależności między tabelami. Zwłaszcza w przypadku Delphi 1.0 stanowi to bardzo
praktyczne podejście do konstruowania racjonalnych implementacji reguł logiki
aplikacji.

Ujemną stroną takiego podejścia jest fakt, że ponieważ programiści nie muszą
koniecznie używać tych właśnie komponentów, to możliwe jest budowanie
aplikacji Delphi nie respektujących wbudowanych w nie reguł logiki aplikacji. Co
więcej, ponieważ podejście „komponentowe” jest rozwiązaniem specyficznym
tylko dla Delphi, to aplikacje stworzone z użyciem innych narzędzi (z wyjątkiem
Borland C++ Builder) nie mogą wykorzystywać reguł logiki aplikacji, osadzonych
w tego rodzaju potomkach

TDataSet

.

Zatem, jeśli chodzi o ten typ narzędzi, moja rada jest taka sama, jak w ogólnym
przypadku implementacji reguł logiki aplikacji po stronie programu: nawet jeśli
zdecydujemy się na użycie jednej z nich, to nadal jak największą część naszej
strategii reguł logiki aplikacji powinniśmy implementować na samym DBMS, zaś
komponentów pochodnych używać jako sposobu na wzbogacenie implementacji.

background image

Rozdział 21 Reguły logiki aplikacji w aplikacjach Delphi

633

Właściwości TField a reguły logiki aplikacji

Trzecim poziomem strategii reguł logiki aplikacji po stronie klienta jest poziom
właściwości

TField

. Reguły logiki aplikacji odnoszą się zwykle do bardziej

złożonych jednostek niż same tylko maski pól lub etykiety do wyświetlania. Mimo
to liczne właściwości klasy komponentu

TField

związane są w pewien sposób

z poprawnym implementowaniem reguł logiki aplikacji. Właściwości takie jak
atrybut maski edycyjnej w

TField

związane są przez to, że wymuszają zgodność

danych, które kolumna otrzymuje, z określonym formatem. Jest to wspomniana
wcześniej prosta odmiana reguł logiki aplikacji. Na bazie takich prostych reguł
logiki aplikacji budujemy strukturę reguł bardziej zaawansowanych, jak na
przykład te, które zapewniają integralność referencyjną pomiędzy dwiema
tabelami lub dostarczają danej kolumnie wartości domyślnych. Udana
implementacja reguł logiki aplikacji wymaga poświęcenia wielkiej uwagi
szczegółom.

Istnieją dwa sposoby implementowania prostych reguł logiki aplikacji poprzez
odpowiednie ustawianie właściwości komponentu

TField

. Pierwsza polega na

użyciu Słownika danych (Data Dictionary) Delphi i ustawieniu odpowiednich
właściwości

TField

z użyciem Zestawów atrybutów (Attribute Sets). Druga to

samodzielne ustawianie tychże właściwości

TField

w istniejących w naszej

aplikacji komponentach

DataSet

. Choć obie sprowadzają się w istocie do tego

samego - specyfikowane przez nasz Zestawy atrybutów

TField

staja się

ostatecznie częścią komponentów

TField

w naszej aplikacji - to preferowaną

opcją winno być użycie Słownika danych do definiowania naszych ustawień

TField

. Określanie właściwości

TField

z pomocą Słownika danych jest

bardziej elastyczne i

ma ogólniejsze zastosowanie, niż robienie tego za

pośrednictwem Edytora pól (Field Editor) komponentów

DataSet

. To, czego

w słowniku tym nie można zdefiniować lub czego definiować w nim nie ma sensu,
można ustawić w samych komponentach Da

t

aSet. Obie te metody omówię

szczegółowo po to, by można było w pełni ocenić korzyści związane z każdym
z tych podejść.

Importowanie informacji do Słownika

Informacje słownikową możemy do Słownika danych Delphi importować
bezpośrednio z naszej wyjściowej bazy danych. Ograniczenia, wartości domyślne,
typy danych i inne wymagane informacje z naszego serwera zostaną wtedy
przeniesione do słownika en masse. Oszczędza to kłopotu z odtwarzaniem
w słowniku więzów bazujących na serwerze i pomaga utrzymać serwerowe
i aplikacyjne reguły logiki aplikacji w stanie zsynchronizowanym. By importować
informacje z bazy danych do Słownika danych należy wykonać następującą
procedurę:

background image

634

Część IV

1. W Eksploratorze baz danych (Database Explorer) kliknij fiszkę

Dictionary

, po

czym rozwiń gałąź

Databases

.

2. Wybierz bazę danych, która mieścić będzie informacje dla Słownika danych.

Informacje te przechowywać można albo w nowej słownikowej bazie danych,
którą rejestrujemy poprzez opcję menu

Dictionary

\

New

, lub w bazie istniejącej,

takiej jak baza danych DBDEMOS dostarczana wraz z Delphi.

3. Kliknij opcjê

Import from Database

w menu

Dictionary

Eksploratora.

4. Po wyświetleniu okna dialogowego

Import

Database

wybierz alias BDE,

odpowiadający twej bazie danych, i kliknij

OK

.

Importowanie naszej bazy danych do Słownika danych Delphi wprowadza do
niego wszystkie występujące w niej więzy i inne informacje z poziomu pól.
Wprowadza również domeny ze związanymi z nimi więzami jako Zestawy
atrybutów (Attribute Set). Dzięki opisanemu procesowi, importowanej informacji
ze słownika (oraz wszelkich dokonanych w niej zmian) można będzie użyć
w naszej aplikacji Delphi. Jeśli na przykład importowaliśmy kolumnę, dla której
w naszej bazie danych jest zdefiniowane CHECK, to więzy te pojawią się również
w aplikacjach Delphi, odwołujących się do tejże kolumny. Zatem nasza aplikacja,
zamiast dopiero reagować na odrzucenie przez ograniczenie w

serwerze

wprowadzonej już, niepoprawnej wartości, sama zapobiegać będzie
przedostawaniu się nieodpowiednich danych do serwera.

Tworzenie własnych zestawów atrybutów

Prócz importowania gotowych zestawów atrybutów z baz danych, możemy
tworzyć zestawy własne i wiązać je z kolumnami w naszych tabelach. Aby
skonstruować i wykorzystać swój własny zestaw atrybutów, należy wykonać
następujące czynności:

1. Prawym klawiszem myszy kliknij gałąź

Attribute

Sets

w karcie

Dictionary

i z menu wybierz

New

.

2. Wpisz nazwę nowego zestawu atrybutów.

3. Skonfiguruj te właściwości

TField

, które powinny być wyspecyfikowane.

4. Kliknij przycisk

Apply

Eksploratora baz danych, aby je zapamiętać.

5. Rozwiń gałąź

Database

na karcie

Dictionary

i kliknij tę kolumnę tabeli, z którą

chciałbyś powiązać swój zestaw atrybutów.

6. Na karcie

Definition

Eksploratora kliknij listę rozwijaną

Attribute

Set

i wybierz

swój nowy zestaw atrybutów.

7. Kliknij przycisk

Apply

Eksploratora, aby zapamiętać dokonane zmiany.

background image

Rozdział 21 Reguły logiki aplikacji w aplikacjach Delphi

635

Przy pomocy zestawów atrybutów można ustawić wiele atrybutów

TField

.

Słownik danych Delphi stanowi bardzo wielkie ułatwienie w definiowaniu reguł
logiki aplikacji za pośrednictwem właściwości

TField

. Zaleta definiowania reguł

logiki aplikacji nie w samych komponentach DataSet, a w Słowniku danych polega
na tym, że reguły ustanowione w słowniku mogą być wykorzystywane w każdej
aplikacji Delphi, odwołującej się do odpowiednich tabel. Zapewnia to tę samą
korzyść, co podejście przyjęte przez niektórych producentów narzędzi baz danych
i polegające na wbudowywaniu reguł logiki aplikacji w komponenty pochodne -
jednak bez ujemnych stron wynikających ze stosowania obcego kodu.

Definiowanie reguł logiki aplikacji z użyciem TField

Poza wykorzystaniem Słownika danych Delphi do definiowania atrybutów

TField

, reguły logiki aplikacji można definiować również używając samych

komponentów

TField

. Delphi dodaje komponenty

TField

do klasy formularza

wówczas, gdy z menu

Edytora

pól

(Field Editor) zbioru danych (DataSet)

wybierzemy opcję

Add

fields

. Gdy w ten sposób tworzymy komponenty

TField

,

w Inspektorze obiektów (Object Inspector) odzwierciedlone zostają wszystkie
atrybuty, jakie zdefiniowaliśmy w Słowniku danych.

Aby ustawić reguły logiki aplikacji bazujące na

TField

, można skorzystać

z następującej procedury:

1. Wywołaj

Edytor pól

, dwukrotnie klikając komponent

DataSet

(

TTable

,

TQuery

lub

TStoredProc

).

2. Naciśnij CTRL+A, aby utworzyć definicję

TField

dla pól komponentu

DataSet

.

3. Kliknij po kolei w każdy z nich i sprawdź/ustaw ich właściwości w Inspektorze

obiektów.

Required

Jedną z najważniejszych spośród tych właściwości

TField

, które można ustawiać

w Inspektorze obiektów, jest właściwość

Required

. Określa ona, czy dane pole

musi mieć wartość. Przykład sytuacji, w której trzeba będzie zmienić domyślną
wartość tej właściwości mamy wtedy, gdy serwer dostarcza wartości dla klucza lub
innej kolumny

NOT NULL

. Ponieważ występowanie wartości w tej kolumnie jest

obowiązkowe na serwerze, to Delphi zakłada, że jest ono obowiązkowe i w samej
aplikacji, zatem wartością domyślną właściwości

Required

w

TField

staje się

True

. Jest to jednak zbędne, skoro wartości dla tego pola dostarcza serwer, a co

więcej - uniemożliwi poprawne działanie aplikacji. Przełączenie

Required

na

False

przerzuci obowiązek zapewnienia, że pole otrzyma swą wartość,

z powrotem na serwer, czyli tam gdzie i tak jest on wykonywany.

background image

636

Część IV

Pola obliczane

Pola obliczane są użyteczne w wielu sytuacjach, począwszy od zwykłego
dostarczania wartości do pól, a na wykonywaniu skomplikowanych obliczeń
z użyciem pól tabeli skończywszy. Używając mechanizmu pól obliczanych Delphi
możemy wykonywać operacje matematyczne, wyszukiwanie w

tabelach,

sprawdzanie poprawności danych i tak dalej. Pola obliczane są szczególnie
przydatne w przypadku tych danych, które musimy wyświetlać, lecz których nie
musimy przechowywać.

Aby utworzyć pole obliczane, trzeba wykonać dwie podstawowe czynności:

1. Zdefiniować pole w Edytorze pól (Fields Editor) dla danego komponentu

DataSet

.

2. Przypisać polu wartości w

procedurze

OnCalcFields

komponentu

DataSet

.

A oto kroki, które trzeba wykonać przy tworzeniu pola obliczanego:

1. Wyświetl Edytor pól dla danego komponentu

DataSet

, klikając komponent

dwukrotnie.

2. Kliknij prawym klawiszem myszy listę pól i z menu kontekstowego wybierz

New

field

.

3. W oknie dialogowym

New Field

wpisz nazwę, jaką chcesz nadać nowemu polu

obliczanemu, wybierz jego typ (Type) danych i w grupie pól opcji

Field type

kliknij pole

Calculated

.

4. Zakończ definiowanie klikając

OK

. Po powrocie do Edytora pól powinniśmy

w Inspektorze obiektów Delphi zobaczyć wylistowane właściwości nowego
pola. Zauważmy, że właściwość

Calculated

ustawiona jest na

True

.

5. Po zdefiniowaniu pola można już zaprogramować zdarzenie

OnCalcFields

dla naszego

DataSet

, które nowemu polu przypisuje wartość. Oto przykład

takiego przypisania:

taORDERSOrderDateTime.Value := Now;

Powyzsza linia kodu przypisuje polu obliczanemu o nazwie

taORDERSOrder

DateTime

wartość dostępnej w Delphi funkcji

Now

, czyli bieżącą datę i czas.

Pola obliczane są szczególnie użyteczne przy wykonywaniu ustalonych obliczeń
obejmujących kolumny tabeli. Pola obliczanego moglibyśmy na przykład użyć do
zakodowania kwoty pieniędzy, jaką instytucja wypłaca za przebyta mile wtedy,
gdy pracownik używa prywatnego samochodu w sprawach służbowych. Podobnie
do zdarzenie

OnCalcFields

można by wbudować prowizję, którą firma płaci

zwykle swym handlowcom. Możliwości są tu nieograniczone. Ważną rzeczą,
o której należy przy tym pamiętać, jest konieczność maksymalnego ograniczania

background image

Rozdział 21 Reguły logiki aplikacji w aplikacjach Delphi

637

ilości obliczeń, aby aplikacji nie spowolnić więcej, niż jest to bezwzględnie
konieczne.

OnValidate

Inna droga do ustanowienia reguł logiki aplikacji w

TField

wiedzie poprzez

zdarzenie

OnValidate

. Każdy

TField

ma związane ze sobą zdarzenie

OnValidate

, którego można użyć do weryfikacji jego wartości. Kod, który się

w nim znajdzie, może zrobić praktycznie wszystko - może porównać wartości, jaka
pole otrzymuje, ze stałymi, innymi polami lub rezultatami zapytania. Jeśli
stwierdzimy, że wartość, którą pole otrzymuje, jest nieprawidłowa, po prostu
generujemy wyjątek. Powoduje to wyświetlenie komunikatu o

błędzie

i uniemożliwia zatwierdzenie wiersza. Możemy tworzyć nasze własne, pochodne
typy wyjątków lub korzystać tylko z tych, których dostarcza Delphi.

OnExit

Innym powszechnie wykorzystywanym miejscem implementowania bazujących na
polach reguł logiki aplikacji jest zdarzenie

OnExit

w skojarzonych z danymi

(data-aware) komponentach, takich jak

DBEdit

. Do zdarzenie

OnExit

możemy

dołączyć kod, który będzie się wykonywać w momencie, gdy użytkownik zacznie
wychodzić z danej kontrolki. Kod ten może przypisywać wartości innym polom
(na przykład, przypisywać datę zakończenia w oparciu o dostarczoną datę
rozpoczęcia), dokonywać sprawdzenia wartości lub też uwidaczniać albo ukrywać
inne komponenty na formularzu w zależności od wprowadzonych wcześniej
wartości

Zbiory danych a reguły logiki aplikacji

Następnym poziomem, na którym konstruować można reguły logiki aplikacji
aplikacji, jest poziom zbiorów danych (DataSet). W

klasie komponentów

DataSet

(której pochodnymi są wszystkie komponenty

Table

,

Query

i

StoredProc

) występują trzy zdarzenia, które zasługują na specjalną uwagę:

OnNewRecord

,

BeforeDelete

i

BeforePost

. Odpowiadają one z grubsza

procedurom zdarzeń

INSERT

,

DELETE

I

UPDATE

, które można podłączać do

tabel bazy danych.

OnNewRecord

Zdarzenie

OnNewRecord

zachodzi za każdym razem, gdy do tabeli dodawany

jest nowy rekord. Można go wykorzystać do nadawania wartości kolumnom tabeli.
A oto próbka kodu, dostarczająca domyślnych wartości kolumnom

PetDeposit

i

LawnService

z tabeli LEASE, wykorzystywanej w sekcji „Tutorial” książki:

background image

638

Część IV

procedure TForm1.taLEASENewRecord(DataSet: TDataSet);
begin
taLEASEPetDeposit.Value:=0;
taLEASELawnService.Value:=True;
end;

BeforeDelete

Zdarzenie

BeforeDelete

, jak sama nazwa wskazuje, poprzedza kasowanie

wiersza. Zdarzenia

BeforeDelete

można użyć do sprawdzenia poprawności

usuwania wiersza zanim zostanie ono wykonane. Na przykład można je
wykorzystać aby zapobiec usunięciu wiersza, który jest powiązany z wierszami
innej tabeli. Jeśli w trakcie obsługi tego zdarzenia wygenerujemy wyjątek,
usuwanie zostaje przerwane. Poniżej podajemy próbkę kodu używającego tabel
LEASE i PROPERTY z części drugiej tej książki:

taLEASE.IndexName:=‘Propery_Number’;

If taLEASE.FindKey([taPROPERTYProperty_Number.AsInteger]) then

raise EDatabaseError.Create(‘Property_Number is in use - delete
failed’);

Ten fragment programu zabezpiecza przed usunięciem wierszy tabeli PROPERTY
które posiadają odwołanie do wierszy w tabeli LEASE.

BeforePost

Zdarzenie

BeforePost

, jak sama nazwa wskazuje, zachodzi tuż przed

zapisaniem wiersza w jego rodzimej tabeli. Zdarzenia

BeforePost

można użyć

do sprawdzenia poprawności wartości w nowym wierszu lub zmian dokonanych
w wierszu istniejącym. Jeśli w trakcie obsługi tego zdarzenia wygenerujemy
wyjątek, zatwierdzanie zostaje przerwane. Poniżej podajemy próbkę kodu
zapewniającą, że chronologicznie data

LeaseEndDate

wypadnie zawsze po

dacie

LeaseBeginDate

:

procedure TForm1.taLEASEBeforePost(DataSet: TDataSet);
begin

If (taLEASELeaseBeginDate.AsDateTime >

taLEASELeaseEndDate.AsDateTime) then

raise EDatabaseError.Create(‘Lease ending date m.

ust come after its beginning date’);

end;

Istnieje kilka innych specjalnych zdarzeń DataSet, które można wykorzystać do
implementowania bazujących na programie reguł logiki aplikacji. Tabela 21.1

background image

Rozdział 21 Reguły logiki aplikacji w aplikacjach Delphi

639

zawiera listę zdarzeń dostępnych w klasie komponentów

DataSet

, które mają

związek z projektowaniem reguł logiki aplikacji.

Tabela 21.2. Metody DataSet, które mogą się przydać przy implementowaniu

bazujących na aplikacji reguł biznesowych.

Zdarzenie Czynnik

wywołujący

AfterCancel

Zachodzi po Cancel

AfterClose

Zachodzi po zamknięciu DataSet

AfterDelete

Zachodzi po Delete

AfterEdit

Zachodzi po Edit

AfterInsert

Zachodzi po Insert lub Append

AfterOpen

Zachodzi po otwarciu DataSet

AfterPost

Zachodzi po Post

BeforeCancel

Zachodzi przed Cancel

BeforeClose

Zachodzi przed zamknięciem DataSet

BeforeEdit

Zachodzi przed Edit

BeforeInsert

Zachodzi przed Insert lub Append

BeforeOpen

Zachodzi przed otwarciem DataSet

OnCalcField

Zachodzi gdy pole obliczane potrzebuje wartości

OnDeleteError

Zachodzi gdy przy kasowaniu rekordu pojawia się
problem

OnEditError

Zachodzi gdy przy redagowaniu rekordu pojawia się
problem

OnFilterRecord

Zachodzi gdy filtrowanie jest uaktywnione i DataSet
potrzebuje wiersza


Wyszukiwarka

Podobne podstrony:
22 Rozdzial 21 KP4Q5YBIEV5DBSVC Nieznany (2)
22 Rozdzial 21 KP4Q5YBIEV5DBSVC Nieznany (2)
21 rozdzial 20 54reqfwyzspmd2u2 Nieznany
21 Rozdziae 20id 29118 Nieznany (2)
Rozdzial 21 22
FIY Rozdział 21, 22
rozdział 21 i 22
Rozdział 21 22
05 rozdzial 04 nzig3du5fdy5tkt5 Nieznany (2)
28 rozdzial 27 vmxgkzibmm3xcof4 Nieznany (2)
Cw 22 Przerzutniki cyfrowe id 1 Nieznany
09 08 Rozdzielnice budowlane RB Nieznany (2)
17 rozdzial 16 fq3zy7m2bu2oan6t Nieznany (2)
Kanicki Systemy Rozdzial 10 id Nieznany
29 rozdzial 28 ciw47mwstcqakqpq Nieznany
24 rozdzial 23 wjv3mksbkbdm37qy Nieznany
29 rozdzial 28 w3cbrpnwzh762znr Nieznany (2)

więcej podobnych podstron