Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
00578 008905 10733508 na godz. na dobę w sumie
Programowanie w języku Delphi - ebook/pdf
Programowanie w języku Delphi - ebook/pdf
Autor: Liczba stron: 192
Wydawca: Helion Język publikacji: polski
ISBN: 978-83-283-0800-8 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> programowanie >> delphi - programowanie
Porównaj ceny (książka, ebook (-20%), audiobook).

Poznaj najlepsze techniki pisania kodu w Delphi!


Wbrew pozorom na świecie pracuje bardzo wielu programistów posługujących się językiem Delphi. Sęk w tym, że większość z nich nie ma pojęcia o niezwykłych i użytecznych funkcjonalnościach dostępnych w nowszych wersjach tego języka oraz nie umie zastosować tych narzędzi we własnej pracy. Jeśli czujesz, że i Ty zaliczasz się do tego grona, a brak umiejętności sprawia, że nie możesz rozwinąć skrzydeł, ta książka jest dla Ciebie. Są w niej opisane niezwykle przydatne narzędzia oraz sytuacje, w których te narzędzia sprawdzają się szczególnie dobrze, a także kilka ogólnie dostępnych platform.

W gruncie rzeczy ta książka jest poświęcona wyłącznie tworzeniu nowego, dobrego kodu w języku Delphi. Nie znajdziesz w niej nic o projektowaniu okienek, języku VCL ani platformie FMX, ale jeśli chcesz się dowiedzieć więcej o kodowaniu interfejsów zamiast implementacji, o właściwych sposobach korzystania z wyjątków i o ich obsłudze, o testowaniu i poprawianiu kodu, o zastosowaniu platformy String for Delphi do lepszego zarządzania kolekcjami danych albo o uzyskiwaniu wglądu w kod podczas jego wykonywania za pomocą nowego, potężnego narzędzia RTTI, z pewnością niniejsza publikacja Cię zachwyci.

Wykorzystaj w pełni moc i elegancję Delphi!



Nick Hodges — programista zaangażowany w projekt Delphi od początku jego istnienia. Był testerem pierwszej wersji języka i członkiem zespołu TeamB, a także menedżerem produktu i kierownikiem działu badawczo-rozwojowego języka Delphi. Jest członkiem Advisory Board na corocznej konferencji firmy Borland, aktywnym prelegentem, blogerem i autorem artykułów poświęconych różnym zagadnieniom języka Delphi.
Znajdź podobne książki Ostatnio czytane w tej kategorii

Darmowy fragment publikacji:

Tytuł oryginału: Coding in Delphi Tłumaczenie: Andrzej Watrak ISBN: 978-83-283-0797-1 ©2012 – 2014 Nick Hodges Polish edition copyright © 2016 by Helion S.A. All rights reserved. All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from the Publisher. Wszelkie prawa zastrzeżone. Nieautoryzowane rozpowszechnianie całości lub fragmentu niniejszej publikacji w jakiejkolwiek postaci jest zabronione. Wykonywanie kopii metodą kserograficzną, fotograficzną, a także kopiowanie książki na nośniku filmowym, magnetycznym lub innym powoduje naruszenie praw autorskich niniejszej publikacji. Wszystkie znaki występujące w tekście są zastrzeżonymi znakami firmowymi bądź towarowymi ich właścicieli. Autor oraz Wydawnictwo HELION dołożyli wszelkich starań, by zawarte w tej książce informacje były kompletne i rzetelne. Nie biorą jednak żadnej odpowiedzialności ani za ich wykorzystanie, ani za związane z tym ewentualne naruszenie praw patentowych lub autorskich. Autor oraz Wydawnictwo HELION nie ponoszą również żadnej odpowiedzialności za ewentualne szkody wynikłe z wykorzystania informacji zawartych w książce. Wydawnictwo HELION ul. Kościuszki 1c, 44-100 GLIWICE tel. 32 231 22 19, 32 230 98 63 e-mail: helion@helion.pl WWW: http://helion.pl (księgarnia internetowa, katalog książek) Pliki z przykładami omawianymi w książce można znaleźć pod adresem: ftp://ftp.helion.pl/przyklady/prodel.zip Drogi Czytelniku! Jeżeli chcesz ocenić tę książkę, zajrzyj pod adres http://helion.pl/user/opinie/prodel Możesz tam wpisać swoje uwagi, spostrzeżenia, recenzję. Printed in Poland. • Kup książkę • Poleć książkę • Oceń książkę • Księgarnia internetowa • Lubię to! » Nasza społeczność Spis tre(cid:258)ci Przedmowa ............................................................................................................................. 9 Wprowadzenie ...................................................................................................................... 11 Podzi(cid:218)kowania ...................................................................................................................... 13 Platformy wykorzystane w ksi(cid:200)(cid:285)ce ....................................................................................... 15 Rozdzia(cid:239) 1. Wyj(cid:200)tki i ich obs(cid:239)uga ......................................................................................... 17 1.1. Wprowadzenie ...............................................................................................................17 1.2. Strukturalna obs(cid:239)uga wyj(cid:200)tków ........................................................................................17 1.3. Jak nie korzysta(cid:202) z wyj(cid:200)tków ...........................................................................................18 Nie „po(cid:239)ykaj” wyj(cid:200)tków ...............................................................................................18 Nie przechwytuj wyj(cid:200)tków bezkrytycznie .....................................................................18 Nie nadu(cid:285)ywaj wyj(cid:200)tków .............................................................................................19 Nie u(cid:285)ywaj wyj(cid:200)tków jako podstawowego sposobu sygnalizacyjnego ...........................19 1.4. Jak prawid(cid:239)owo korzysta(cid:202) z wyj(cid:200)tków ..............................................................................20 U(cid:285)ywaj wyj(cid:200)tków tak, aby kod ich obs(cid:239)ugi nie zak(cid:239)óca(cid:239) realizacji programu ..................20 Twórcy aplikacji powinni tylko przechwytywa(cid:202) wyj(cid:200)tki ................................................20 Przechwytuj tylko wybrane wyj(cid:200)tki ..............................................................................20 Wyj(cid:200)tki mog(cid:200) zg(cid:239)asza(cid:202) twórcy komponentów i bibliotek ..............................................22 Zg(cid:239)aszaj w(cid:239)asne niestandardowe wyj(cid:200)tki .......................................................................22 Niech inni programi(cid:258)ci widz(cid:200) komunikaty o wyj(cid:200)tkach ................................................22 (cid:165)mia(cid:239)o podawaj dok(cid:239)adne komunikaty o wyj(cid:200)tkach .....................................................23 W bibliotece twórz dwie wersje ka(cid:285)dej metody ...........................................................23 1.5. Wnioski ...........................................................................................................................24 Rozdzia(cid:239) 2. Interfejsy ............................................................................................................ 25 2.1. Wprowadzenie ...............................................................................................................25 2.2. Rozprz(cid:218)ganie kodu .........................................................................................................25 2.3. Czym jest interfejs? ..........................................................................................................26 2.4. Interfejsy s(cid:200) wsz(cid:218)dzie ......................................................................................................26 2.5. Prosty przyk(cid:239)ad ................................................................................................................28 2.6. Implementacja interfejsu .................................................................................................29 2.7. Kilka dodatkowych uwag .................................................................................................30 2.8. Dziedziczenie interfejsów ...............................................................................................30 2.9. Inne uwagi warte zapami(cid:218)tania .......................................................................................31 2.10. Klasa TInterfacedObject ...................................................................................................31 2.11. Jak poprawnie u(cid:285)ywa(cid:202) interfejsów ...................................................................................33 Poleć książkęKup książkę 4 Programowanie w j(cid:218)zyku Delphi 2.12. Dlaczego nale(cid:285)y u(cid:285)ywa(cid:202) interfejsów? .............................................................................. 34 Kodowanie abstrakcyjne .............................................................................................. 34 Implementacje pod(cid:239)(cid:200)czane .......................................................................................... 35 Komunikacja mi(cid:218)dzy modu(cid:239)ami .................................................................................. 35 Testowalny kod ........................................................................................................... 36 Wzorce kodu .............................................................................................................. 36 Rozdzia(cid:239) 3. Typy generyczne ................................................................................................ 37 3.1. Z pomoc(cid:200) przybywa typ generyczny ............................................................................... 38 3.2. Ograniczenia .................................................................................................................. 39 Ograniczenie constructor ............................................................................................ 40 Ograniczenie class ....................................................................................................... 40 Ograniczenie record .................................................................................................... 41 Ograniczenie interface ................................................................................................ 42 Przekazywanie rekordów jako typów parametrycznych ............................................... 42 3.3. Interfejsy generyczne ...................................................................................................... 43 3.4. Metody generyczne ........................................................................................................ 43 3.5. Kolekcje generyczne ....................................................................................................... 44 3.6. My(cid:258)lenie generyczne ...................................................................................................... 45 3.7. Wystudiowany, prosty przyk(cid:239)ad ...................................................................................... 45 3.8. Praktyczny przyk(cid:239)ad ........................................................................................................ 46 Typ TWylicz ................................................................................................................ 46 Problemy z typami generycznymi ................................................................................ 48 3.9. Wnioski .......................................................................................................................... 49 3.10. Wywiad z typem generycznym ....................................................................................... 49 Rozdzia(cid:239) 4. Metody anonimowe ........................................................................................... 51 4.1. Wprowadzenie ............................................................................................................... 51 4.2. Definicja ......................................................................................................................... 51 4.3. Po co to wszystko? .......................................................................................................... 52 Prosty przyk(cid:239)ad ............................................................................................................ 53 Metody anonimowe jako zmienne .............................................................................. 55 4.4. Domkni(cid:218)cia .................................................................................................................... 55 4.5. Deklaracje standardowe ................................................................................................. 56 4.6. Praktyczny przyk(cid:239)ad ........................................................................................................ 57 4.7. Inny, jeszcze ciekawszy przyk(cid:239)ad .................................................................................... 58 Metody anonimowe s(cid:200) bardzo elastyczne .................................................................... 59 4.8. Metody anonimowe w bibliotece RTL ............................................................................. 61 Klasa TThread i metody anonimowe ............................................................................ 61 4.9. Predykaty ....................................................................................................................... 61 I co z tego? .................................................................................................................. 61 4.10. Wnioski .......................................................................................................................... 63 4.11. Wywiad z metod(cid:200) anonimow(cid:200) ....................................................................................... 63 Rozdzia(cid:239) 5. Kolekcje .............................................................................................................. 65 5.1. Wprowadzenie ............................................................................................................... 65 5.2. Ogólne uwagi dotycz(cid:200)ce kolekcji .................................................................................... 65 5.3. Kolekcje w j(cid:218)zyku Delphi ............................................................................................... 66 Kolekcja TList T ...................................................................................................... 66 Kolekcja TStack T ................................................................................................... 68 Kolekcja TQueue T ................................................................................................ 69 Kolekcja TDictionary TKey, TValue ......................................................................... 70 Kolekcje obiektów ....................................................................................................... 72 Poleć książkęKup książkę Spis tre(cid:258)ci 5 5.4. Kolekcje w platformie Delphi Spring Framework .............................................................72 Ogólne informacje .......................................................................................................72 Dwa nieopisane dotychczas typy kolekcji .....................................................................73 5.5. Dlaczego nale(cid:285)y u(cid:285)ywa(cid:202) kolekcji Spring4D? ....................................................................73 5.6. Wnioski ...........................................................................................................................74 Rozdzia(cid:239) 6. Enumeratory w Delphi ....................................................................................... 75 6.1. Wprowadzenie ...............................................................................................................75 6.2. Interfejs IEnumerator T ...............................................................................................77 6.3. Specjalistyczne enumeratory ...........................................................................................78 6.4. Klasa TEnumerable T w module Generics.Collections .................................................80 6.5. Wnioski ...........................................................................................................................80 Rozdzia(cid:239) 7. Interfejs IEnumerable ........................................................................................ 81 7.1. Interfejs IEnumerable T ..............................................................................................82 7.2. Predykaty ........................................................................................................................83 7.3. Wywiad z interfejsem IEnumerable T (IEoT) ...............................................................87 Rozdzia(cid:239) 8. Informacje RTTI ................................................................................................. 89 8.1. Wprowadzenie ...............................................................................................................89 8.2. Typ TValue ......................................................................................................................90 8.3. RTTI i klasy ......................................................................................................................92 Klasa TRttiType ............................................................................................................94 8.4. RTTI i instancje klas .........................................................................................................96 Odczytywanie i nadawanie warto(cid:258)ci ............................................................................96 Wywo(cid:239)ywanie metod ...................................................................................................97 8.5. Uwagi ogólne ..................................................................................................................98 8.6. RTTI i inne typy danych ..................................................................................................98 RTTI i typy porz(cid:200)dkowe ...............................................................................................99 RTTI i rekordy ..............................................................................................................99 RTTI i tabele ................................................................................................................99 8.7. Inne metody RTTI .........................................................................................................100 8.8. Dyrektywy kompilatora zwi(cid:200)zane z RTTI .......................................................................100 Silna konsolidacja typów ............................................................................................102 8.9. Wnioski .........................................................................................................................102 Rozdzia(cid:239) 9. Atrybuty ........................................................................................................... 103 9.1. Wprowadzenie .............................................................................................................103 9.2. Czym s(cid:200) atrybuty? .........................................................................................................103 9.3. Prosty przyk(cid:239)ad ..............................................................................................................107 9.4. Wnioski .........................................................................................................................109 9.5. Wywiad z atrybutem .....................................................................................................109 Rozdzia(cid:239) 10. Klasa TVirtualInterface ................................................................................. 111 10.1. Troch(cid:218) lepsza klasa TVirtualInterface .............................................................................115 10.2. Naprawd(cid:218) u(cid:285)yteczny przyk(cid:239)ad .......................................................................................116 10.3. Interfejs IProstaAtrapa ....................................................................................................116 10.4. Klasa TProstaImitacja .....................................................................................................118 10.5. Wnioski .........................................................................................................................120 Rozdzia(cid:239) 11. Wst(cid:218)p do wstrzykiwania zale(cid:285)no(cid:258)ci .............................................................. 121 11.1. Wprowadzenie ..............................................................................................................121 11.2. Czym jest zale(cid:285)no(cid:258)(cid:202)? .....................................................................................................121 11.3. Prawo Demeter .............................................................................................................122 11.4. Przyk(cid:239)ad projektu ..........................................................................................................122 Poleć książkęKup książkę 6 Programowanie w j(cid:218)zyku Delphi 11.5. Prawo Demeter w j(cid:218)zyku Delphi .................................................................................. 123 11.6. Przyk(cid:239)adowy kod krok po kroku .................................................................................... 124 11.7. Kontener wstrzykiwania zale(cid:285)no(cid:258)ci ................................................................................ 131 11.8. Wnioski ........................................................................................................................ 134 Rozdzia(cid:239) 12. Wi(cid:218)cej o wstrzykiwaniu zale(cid:285)no(cid:258)ci ................................................................ 135 12.1. Zale(cid:285)no(cid:258)ci opcjonalne .................................................................................................. 136 12.2. Wstrzykiwanie metod przypisuj(cid:200)cych ............................................................................ 136 12.3. Wstrzykiwanie metod ................................................................................................... 137 12.4. Kontener Spring Container i klasa ServiceLocator .......................................................... 138 Rejestrowanie interfejsów ......................................................................................... 139 Zarz(cid:200)dzanie czasem (cid:285)ycia obiektów ......................................................................... 140 Niestandardowe tworzenie obiektów ....................................................................... 141 Okre(cid:258)lenie domy(cid:258)lnego obiektu ............................................................................... 142 Rejestrowanie tych samych klas dla dwóch interfejsów ............................................. 142 Wstrzykiwanie pól i w(cid:239)a(cid:258)ciwo(cid:258)ci podczas rejestracji .................................................. 142 Wykorzystanie rejestracji do wstrzykiwania konstruktorów i metod .......................... 144 12.5. Rejestrowanie elementów za pomoc(cid:200) atrybutów ........................................................... 145 12.6. Klasa ServiceLocator jako antywzorzec .......................................................................... 147 12.7. Podsumowanie wstrzykiwania zale(cid:285)no(cid:258)ci ...................................................................... 151 Rozdzia(cid:239) 13. Testy jednostkowe ......................................................................................... 153 13.1. Co to s(cid:200) testy jednostkowe? .......................................................................................... 153 Co to jest „jednostka”? ............................................................................................. 154 Czy rzeczywi(cid:258)cie wykonuj(cid:218) testy jednostkowe? ........................................................ 154 Czym jest platforma izolacyjna? ................................................................................ 154 13.2. Po co wykonywa(cid:202) testy jednostkowe? ........................................................................... 157 Dzi(cid:218)ki testom jednostkowym wyszukasz b(cid:239)(cid:218)dy ......................................................... 157 Dzi(cid:218)ki testom jednostkowym unikniesz b(cid:239)(cid:218)dów ........................................................ 157 Dzi(cid:218)ki testom jednostkowym oszcz(cid:218)dzisz czas ......................................................... 157 Testy jednostkowe zapewniaj(cid:200) spokój ...................................................................... 157 Testy jednostkowe dokumentuj(cid:200) w(cid:239)a(cid:258)ciwe u(cid:285)ycie klas .............................................. 158 13.3. Testy jednostkowe w Delphi ......................................................................................... 158 Platforma DUnit ....................................................................................................... 158 Platforma DUnitX ..................................................................................................... 158 13.4. Ogólne zasady testów jednostkowych ........................................................................... 159 Testuj jedn(cid:200) klas(cid:218) w izolacji ........................................................................................ 159 Przestrzegaj zasady AAA ........................................................................................... 159 Najpierw twórz proste testy, „krótkie i na temat” ...................................................... 159 Twórz testy sprawdzaj(cid:200)ce zakresy ............................................................................. 159 Testuj granice ........................................................................................................... 160 Je(cid:285)eli to mo(cid:285)liwe, sprawd(cid:283) ca(cid:239)e spektrum mo(cid:285)liwych warto(cid:258)ci .................................. 160 Je(cid:285)eli to mo(cid:285)liwe, sprawd(cid:283) ka(cid:285)dy przebieg kodu ...................................................... 160 Twórz testy wyszukuj(cid:200)ce b(cid:239)(cid:218)dy i poprawiaj je ........................................................... 160 Ka(cid:285)dy test musi by(cid:202) niezale(cid:285)ny od innych testów ..................................................... 160 Stosuj w te(cid:258)cie tylko jedn(cid:200) asercj(cid:218) ............................................................................ 161 Nadawaj testom czytelne nazwy i nie przejmuj si(cid:218), (cid:285)e s(cid:200) d(cid:239)ugie ............................... 161 Sprawdzaj, czy ka(cid:285)dy wyj(cid:200)tek jest rzeczywi(cid:258)cie zg(cid:239)aszany ......................................... 161 Unikaj stosowania metod CheckTrue i Assert.IsTrue ................................................. 161 Regularnie wykonuj testy .......................................................................................... 161 Wykonuj testy przy ka(cid:285)dorazowej kompilacji kodu .................................................. 161 13.5. Programowanie uwzgl(cid:218)dniaj(cid:200)ce testy ............................................................................ 162 13.6. Prosty przyk(cid:239)ad ............................................................................................................. 162 Poleć książkęKup książkę Spis tre(cid:258)ci 7 Rozdzia(cid:239) 14. Testy z u(cid:285)yciem platformy izolacyjnej ........................................................... 169 14.1. Krótkie przypomnienie ..................................................................................................169 14.2. Platformy izolacyjne w Delphi .......................................................................................170 14.3. Jak zacz(cid:200)(cid:202) ......................................................................................................................170 Do akcji wkracza platforma izolacyjna ......................................................................170 Prosta atrapa .............................................................................................................170 Testowanie dziennika ...............................................................................................172 Atrapy, które wykonuj(cid:200) operacje ..............................................................................173 Zale(cid:285)no(cid:258)ci wykonuj(cid:200)ce oczekiwane operacje ...........................................................176 Zale(cid:285)no(cid:258)ci zg(cid:239)aszaj(cid:200)ce wyj(cid:200)tki ...................................................................................178 W te(cid:258)cie stosuj tylko jedn(cid:200) imitacj(cid:218) ...........................................................................179 Oczekiwane parametry musz(cid:200) by(cid:202) zgodne z rzeczywistymi ......................................180 14.4. Wnioski .........................................................................................................................180 Dodatek A. Materia(cid:239)y .......................................................................................................... 181 Wstrzykiwanie zale(cid:285)no(cid:258)ci .....................................................................................................181 Testy jednostkowe ................................................................................................................181 Systemy kontroli kodu (cid:283)ród(cid:239)owego .......................................................................................182 Subversion ........................................................................................................................182 Git ....................................................................................................................................182 Mercurial ..........................................................................................................................182 Projekty ................................................................................................................................182 Inne ciekawe materia(cid:239)y ........................................................................................................183 Dodatek B. Moja przygoda z Delphi .................................................................................. 185 Skorowidz .......................................................................................................................... 189 Poleć książkęKup książkę 8 Programowanie w j(cid:218)zyku Delphi Poleć książkęKup książkę ROZDZIA(cid:146)10 Klasa TVirtualInterface W tym miejscu powinieneś już być przekonany, że należy programować interfejsy, a nie implementacje. (Czyż nie obiecałem Ci w pierwszym rozdziale, że będę to zdanie powtarzał aż do znudzenia?) Interfejsy umożliwiają tworzenie luźno sprzężonego kodu. Jeżeli wciąż nie wierzysz, że rozprzężenie kodu jest wyjątkowo ważną kwestią, radzę Ci przerwać lekturę w tym miejscu, wziąć do ręki mały młotek i stukać się nim w czoło tak długo, aż zmienisz zdanie. Jeżeli więc już to zrobiłeś, to wiesz, że interfejs przed użyciem trzeba zaimplementować. Zanim cokolwiek zrobisz, musisz dopisać do niego trochę kodu. Zazwyczaj wykorzystuje się w tym celu klasę implementacyjną: 1 type 2 IPrzetwarzanieDanych = interface 3 procedure PrzetwarzajDane; 4 end; 5 6 TPrzetwarzanieDanych = class(TInterfacedObject, IPrzetwarzanieDanych) 7 procedure PrzetwarzajDane; 8 end; A gdyby tak zaimplementować interfejs, nie korzystając z określonej klasy? Gdyby można było w jakiś sposób zaimplementować interfejs za pomocą jednego modułu kodu? Gdyby można było decydować podczas wykonywania programu o sposobie implementacji interfejsu? Czy zadawałbym te pytania i pisał o tych rzeczach, gdyby nie były możliwe do wykonania? Oczywiście jest to możliwe. W wersji Delphi XE2 została wprowadzona bardzo ciekawa klasa TVirtualInterface, służąca do tworzenia klas pochodnych i dynamicznego implementowania interfejsów. Jeżeli zastanowisz się przez chwilę, stwierdzisz, że jest to bardzo ciekawa funkcjonalność. Została ona wykorzystana między innymi w niezwykłej platformie testowej Delphi Mocks Framework (o której opowiem w następnym rozdziale), umożliwiającej implementację imitacji klas dowolnego interfejsu, który się w powyższej klasie wskaże. Jak dowiedziałeś się w rozdziale 2., zazwyczaj podczas implementacji interfejsu trzeba tworzyć określoną klasę. Zatem podczas wykonywania kodu będzie to implementacja statyczna. Istnieją sposoby, zazwyczaj jest to wstrzykiwanie zależności, umożliwiające wybór implementacji, ale nawet wtedy zbiór klas jest ograniczony. Klasa TVirtualInterface umożliwia dynamiczne, tj. w trakcie wykonywania kodu, określenie sposobu implementacji interfejsu. Zacznę od pokazania kilku prostych, a potem bardziej praktycznych przykładów zastosowania tej klasy. Poniżej przedstawiona jest publiczna część klasy TVirtualInterface: 1 { TVirtualInterface: Creates an implementation of an interface at runtime. 2 All methods in the Interface are marshaled through a generic stub function 3 that raises the OnInvoke event.} Poleć książkęKup książkę 112 Programowanie w j(cid:218)zyku Delphi 4 TVirtualInterface = class(TInterfacedObject, IInterface) 5 ... 6 public 7 function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall; 8 { Create an instance of TVirtualInterface that implements the methods of 9 an interface. PIID is the PTypeInfo for the Interface that is to be 10 implemented. The Interface must have TypeInfo ($M+). Either inherit from 11 IInvokable, or enable TypeInfo for the interface. Because this is an 12 TInterfacedObject, it is reference counted and it should not be Freed 13 directly. 14 } 15 constructor Create(PIID: PTypeInfo); overload; 16 constructor Create(PIID: PTypeInfo; 17 InvokeEvent: TVirtualInterfaceInvokeEvent); overload; 18 destructor Destroy; override; 19 { OnInvoke: Event raised when a method of the implemented interface is called. 20 Assign a OnInvoke handler to perform some action on invoked methods.} 21 property OnInvoke: TVirtualInterfaceInvokeEvent read FOnInvoke 22 write OnInvoke; 23 end; Poniżej znajduje się kilka uwag do tej deklaracji: (cid:132) Przede wszystkim zauważ, że klasa TVirtualInterface pochodzi od klasy TInterfacedObject i implementuje interfejs IInterface. Zaimplementowane są w niej trzy metody tego interfejsu umożliwiające prawidłowe zliczanie referencji, tak samo jak w przypadku innych klas implementacyjnych. (cid:132) Po drugie, interfejs, który ma być zaimplementowany za pomocą tej klasy, musi zawierać metodę TypeInfo. Najprostszym sposobem spełnienia tego warunku jest utworzenie interfejsu pochodnego od IInvokable. W przeciwnym wypadku trzeba w kodzie interfejsu użyć dyrektywy kompilatora {$M+}. Zwróć również uwagę, że komentarz nad deklaracją klasy zawiera informacje, o których pisałem wcześniej — klasa TVirtualInterface umożliwia wykonywanie na interfejsie dowolnych operacji podczas realizacji kodu. Super. (cid:132) Ponadto pamiętaj, że w klasie tej ponownie zadeklarowana jest metoda QueryInterface, zamieniona na metodę wirtualną. Aby móc coś zrobić za pomocą klasy TVirtualInterface, trzeba utworzyć jej klasę pochodną i umieścić w niej dwa elementy: konstruktora i implementację metody DoEvent. Poniżej, w najprostszym możliwym przykładzie, jaki mi przyszedł do głowy, przedstawiona jest klasa pochodna od TVirtualInterface: 1 type 2 TNajprostszyInterfejsWirtualny = class(TVirtualInterface) 3 constructor Create(PIID: PTypeInfo); 4 procedure Wywo(cid:239)ajMetod(cid:218)(Metoda: TRttiMethod; const Argumenty: TArray TValue ; 5 out Wynik: TValue); 6 end; 7 8 constructor TNajprostszyInterfejsWirtualny.Create(PIID: PTypeInfo); 9 begin 10 inherited Create(PIID, Wywo(cid:239)ajMetod(cid:218)); 11 end; 12 13 procedure TNajprostszyInterfejsWirtualny.Wywo(cid:239)ajMetod(cid:218)(Metoda: TRttiMethod; 14 const Argumenty: TArray TValue ; out Wynik: TValue); 15 begin 16 WriteLn( Wywo(cid:239)a(cid:239)e(cid:258) metod(cid:218) interfejsu ); 17 end; Poleć książkęKup książkę Rozdzia(cid:239) 10. Klasa TVirtualInterface 113 Jedyną wykonywaną tu operacją jest wyświetlenie komunikatu w oknie wiersza polecenia, niezależnie od wywołanej metody. Jest to udawana implementacja każdego interfejsu i niezależnie od wywołanej metody zostanie jedynie wyświetlony komunikat. Konstruktor ma jeden parametr, PIID, będący wskaźnikiem typu PTypeInfo do interfejsu, który ma być zaimplementowany. (Dlatego w przypadku tego interfejsu musi być użyta dyrektywa {$M+}. Najczęściej i najprościej robi się to za pomocą interfejsu IInvokable). Wewnątrz konstruktora wywoływany jest inny konstruktor. Przekazywany jest mu parametr PIID, jak również referencja do metody Wywo(cid:239)ajMetod(cid:218) typu TVirtualInterfaceInvokeEvent. W ten sposób konstruktor mówi: „Tutaj jest informacja dla implementowanego interfejsu i metoda, która będzie wywoływana po wywołaniu dowolnej metody tego interfejsu”. W tym przypadku metoda Wywo(cid:239)ajMetod(cid:218) wykonuje tylko jedną operację — wyświetla komunikat w oknie wiersza poleceń. Załóżmy więc, że zadeklarowany jest następujący interfejs: 1 type 2 IStartStop = interface(IInvokable) 3 [ {3B2171B0-D1C3-4A8C-B09E-ACAC4D625E57} ] 4 procedure Start; 5 procedure Stop(aLiczba: integer); 6 end; Następnie uruchomiona została poniższa aplikacja konsolowa: 1 StartStop := TNajprostszyInterfejsWirtualny.Create(TypeInfo(IStartStop)) 2 as IStartStop; 3 StartStop.Start; 4 StartStop.Stop(42); Zawartość okna wiersza poleceń będzie następująca: 1 Wywo(cid:239)a(cid:239)e(cid:258) metod(cid:218) interfejsu 2 Wywo(cid:239)a(cid:239)e(cid:258) metod(cid:218) interfejsu Komunikat wyświetlony będzie dwukrotnie, ponieważ w powyższym kodzie wywoływane są dwie metody. Efekt będzie zawsze ten sam, niezależnie od podanego interfejsu i wywoływanej metody. Oczywiście taki kod do niczego się nie nadaje. Aby był on w jakikolwiek sposób przydatny, potrzebne są informacje o wywoływanych metodach i przekazywanych parametrach, na które będzie można odpowiednio reagować. Jest to możliwe do zrobienia. Przyjrzyj się sygnaturze metody Wywo(cid:239)ajMetod(cid:218). Zauważ, że gdy jest ona wywoływana przez metodę TVirtualInterface.OnInvoke, przekazywane są jej informacje RTTI o wywoływanej metodzie, tabela klas TValue zawierająca interfejs wraz z argumentami przekazywanymi tej metodzie, jak również parametr wyjściowy typu TValue umożliwiający zwrócenie wartości, jeżeli wywoływaną metodą jest funkcja. Wykorzystajmy zatem metodę Wywo(cid:239)ajMetod(cid:218) do wyświetlenia wszystkich odebranych informacji. 1 procedure TWirtualnyInterfejsRaportuj(cid:200)cy.Wywo(cid:239)ajMetod(cid:218)(Metoda: TRttiMethod; 2 const Argumenty: TArray TValue ; out Wynik: TValue); 3 var 4 Argument: TValue; 5 TypArgumentu, NazwaArgumentu: string; 6 TymczTyp: TTypeKind; 7 begin 8 Write( Wywo(cid:239)a(cid:239)e(cid:258) metod(cid:218) , Metoda.Name); 9 if Length(Argumenty) 1 then 10 begin 11 WriteLn( , która ma , Length(Argumenty) - 1, parameterów: ); 12 for Argument in Argumenty do 13 begin 14 TymczTyp := Argument.Kind; Poleć książkęKup książkę 114 Programowanie w j(cid:218)zyku Delphi 15 if TymczTyp tkInterface then 16 begin 17 NazwaArgumentu := Argument.ToString; 18 TypArgumentu := Argument.TypeInfo.Name; 19 WriteLn(NazwaArgumentu, typu , TypArgumentu); 20 end; 21 end; 22 end else 23 begin 24 WriteLn( , która nie ma parametrów. ); 25 end; 26 end; W tym kodzie są po prostu przeglądane i wyświetlane wartości parametrów Metoda i Argumenty przekazane metodzie podczas jej wywołania. Pierwszy element tabeli zawiera zawsze informację o typie samego interfejsu, a pozostałe elementy są parametrami umieszczonymi w kolejności ich przekazania. W tym przykładzie kod po prostu wyświetla wartości i ich typy, ale oczywiście można je też przetwarzać wedle uznania. Powtórzę, jest to interesująca informacja, ale jest to dopiero jeden krok w kierunku poznania sposobu działania klasy TVirtualInterface. Utwórzmy kod, który wykonuje jakąś pożyteczną operację. Poniżej przedstawiony jest podstawowy interfejs: 1 type 2 IPrzydatnyInterfejs = interface(IInvokable) 3 [ {16F01BF0-961F-4461-AEBE-B1ACB8D3F0F4} ] 4 procedure Witaj; 5 function TekstWstecz(aTekst: string): string; 6 function Iloczyn(x, y: integer): integer; 7 end; Poniżej przedstawiona jest metoda Wywo(cid:239)ajMetod(cid:218) klasy TPrzydatnyInterfejs, wykonująca operacje, do których interfejs jest przeznaczony: 1 procedure TPrzydatnyInterfejs.Wywo(cid:239)ajMetod(cid:218)(Metoda: TRttiMethod; 2 const Argumenty: TArray TValue ; out Wynik: TValue); 3 begin 4 if UpperCase(Metoda.Name) = WITAJ then 5 begin 6 WriteLn( Witaj (cid:258)wiecie! ); 7 end else 8 begin 9 if UpperCase(Metoda.Name) = TEKSTWSTECZ then 10 begin 11 Wynik := ReverseString(Argumenty[1].AsString) 12 end else 13 begin 14 if UpperCase(Metoda.Name) = ILOCZYN then 15 begin 16 Wynik := Argumenty[1].AsInteger * Argumenty[2].AsInteger; 17 end else 18 begin 19 raise Exception.Create( B(cid:239)(cid:218)dny parametr metody Wywo(cid:239)ajMetod(cid:218) ); 20 end; 21 end; 22 end; 23 end; Powyższy kod nie wymaga wyjaśnień. Sprawdza po prostu nazwę wywoływanej metody i wykonuje odpowiednią operację, wykorzystując informacje przekazane w parametrze Argumenty. Jeżeli wywoływaną metodą jest funkcja, wtedy zmienna Wynik jest wykorzystywana jako zwracana wartość. Poleć książkęKup książkę Rozdzia(cid:239) 10. Klasa TVirtualInterface 115 Jak pamiętasz, pierwszym elementem (czyli tym na pozycji zerowej) tabeli Argumenty jest typ samego interfejsu. W powyższym kodzie przyjęte jest założenie dotyczące liczby i typów parametrów. Ponieważ kod ten może być uruchomiony jedynie przez metody zadeklarowane w interfejsie IPrzydatnyInterfejs, takie założenie można bezpiecznie przyjąć. Teraz opisane kody powinny być jasne — w przykładach w zasadzie symulowana jest klasa implementacyjna. Tak naprawdę nie jest to implementacja dynamiczna. Kody są jedynie prostymi przykładami statycznego wykorzystania klasy TVirtualInterface. Teraz musisz się dowiedzieć, jak dynamicznie implementować interfejs za pomocą klasy pochodnej od TVirtualInterface. 10.1. Troch(cid:218) lepsza klasa TVirtualInterface Do tej pory analizowaliśmy tylko kod demonstracyjny. Nie mogę sobie wyobrazić żadnego sposobu jego zastosowania w praktyce. Pokazuje on jednak funkcjonowanie klasy TVirtualInterface i wykorzystanie jej do własnych celów. Ponieważ TVirtualInterface jest fajną klasą, jest również nieco kłopotliwa w użyciu. A gdyby tak utworzyć klasę pochodną, która wykonywałaby za nas większość ciężkiej roboty i naprawdę ułatwiała tworzenie dynamicznych implementacji wirtualnego interfejsu? W jednym z wcześniejszych rozdziałów, poświęconym typom generycznym, starałem się nauczyć Cię „myśleć generycznie” i wyjaśnić Ci, dlaczego typy te (które wolę nazywać typami parametrycznymi) są pod wieloma względami bardziej przydatne niż kolekcje i listy. Przyjrzałem się klasie Tvirtual (cid:180)Interface i pomyślałem: „Jak widać, jest to klasa, która w rzeczywistości wymaga podania informacji o typie interfejsu, i aby za jej pomocą zrobić coś pożytecznego, trzeba w konstruktorze podać ten typ, hmmm”. Zapewne domyślasz się, co potem zrobiłem. Rozważmy więc następującą deklarację klasy: 1 type 2 TRozszerzonyInterfejsWirtualny T: IInvokable = class(TVirtualInterface) 3 protected 4 procedure Wywo(cid:239)ajMetod(cid:218)(Metoda: TRttiMethod; const Argumenty: TArray TValue ; 5 out Wynik: TValue); 6 procedure Wywo(cid:239)ajMetod(cid:218)Impl(Metoda: TRttiMethod; 7 const Argumenty: TArray TValue ; out Wynik: TValue); virtual; abstract; 8 public 9 constructor Create; 10 end; Jest to bardzo prosta klasa pochodna od TVirtualInterface. Jej najbardziej oczywistą cechą jest typ parametryczny T, ograniczony do interfejsu pochodnego od IInvokable. W ten sposób można jawnie określić interfejs, który będzie implementować klasa TRozszerzonyInterfejsWirtualny. Zauważ, że jest to klasa abstrakcyjna, ponieważ taka jest jej metoda Wywo(cid:239)ajMetod(cid:218)Impl. Dzięki typowi parametrycznemu mamy wszystko, co jest potrzebne do zaimplementowania interfejsu. Jak wiesz z poprzedniej części rozdziału, wymagana jest implementacja metody Wywo(cid:239)ajMetod(cid:218). W klasie TRozszerzonyInterfejsWirtualny zastosowana jest technika polegająca na implementacji interfejsu w klasie bazowej i wykorzystaniu „realnej” implementacji w osobnej metodzie wywoływanej przez klasę bazową. Implementacja wygląda następująco: 1 constructor TRozszerzonyInterfejsWirtualny T .Create; 2 begin 3 inherited Create(TypeInfo(T), Wywo(cid:239)ajMetod(cid:218)); 4 end; 5 6 procedure TRozszerzonyInterfejsWirtualny T .Wywo(cid:239)ajMetod(cid:218)(Metoda: TRttiMethod; 7 const Argumenty: TArray TValue ; out Wynik: TValue); 8 begin 9 Wywo(cid:239)ajMetod(cid:218)Impl(Metoda, Argumenty, Wynik); 10 end; Poleć książkęKup książkę 116 Programowanie w j(cid:218)zyku Delphi Konstruktor jest całkiem prosty — nie ma parametrów i wywołuje odziedziczony konstruktor, podając w jego parametrach metodę TypeInfo z interfejsem i metodę Wywo(cid:239)ajMetod(cid:218) typu TVirtualInterfaceInvokeEvent. W kodzie tej metody wywoływana jest po prostu metoda Wywo(cid:239)ajMetod(cid:218)Impl, która jest metodą abstrakcyjną i dlatego musi być zastąpiona w klasie pochodnej inną metodą. Aby więc wykorzystać tę klasę, wystarczy jedynie utworzyć jej klasę pochodną i podać interfejs jako typ parametryczny wraz z implementacją metody Wywo(cid:239)ajMetod(cid:218)Impl. W celu zaimplementowania interfejsu IPrzydatnyInterfejs z poprzedniego przykładu wystarczy jedynie wpisać: 1 TRozszerzonyPrzydatnyInterfejs = class(TRozszerzonyInterfejsWirtualny 2 IPrzydatnyInterfejs ) 3 protected 4 procedure Wywo(cid:239)ajMetod(cid:218)Impl(Metoda: TRttiMethod; 5 const Argumenty: TArray TValue ; out Wynik: TValue); override; 6 end; Metodę Wywo(cid:239)ajMetod(cid:218)Impl trzeba zaimplementować za pomocą tego samego kodu co metodę Wywo(cid:239)ajMetod(cid:218) w klasie TPrzydatnyInterfejs. Opisany sposób to nic specjalnego, ale lubię go, ponieważ upraszcza proces implementacji interfejsu wirtualnego i jest następnym przykładem praktycznego zastosowania typów parametrycznych. Podoba mi się również, że — jak wspomniałem wcześniej — jednoznacznie deklaruje się w nim implementowany interfejs. 10.2. Naprawd(cid:218) u(cid:285)yteczny przyk(cid:239)ad Wystarczy już tych nie całkiem przydatnych przykładów. Zgadzam się, że były one obrazowe, ale nie całkiem przydatne w praktyce. Prawdziwa użyteczność klasy TVirtualInterface ujawnia się podczas tworzenia kodu, w którym nie wiadomo, jaki interfejs będzie implementowany przez użytkownika. We wszystkich dotychczasowych przykładach pokazane były klasy implementujące znany interfejs. Wyjątkiem był przykład z klasą TWirtualnyInterfejsRaportuj(cid:200)cy, w którym wyświetlane były informacje o dowolnym interfejsie podanym w argumencie. Ponieważ obiecałem, że klasy TVirtualInterface można użyć do zrobienia czegoś przydatnego, zróbmy kolejny krok naprzód. Praktycznym zastosowaniem klasy TVirtualInterface jest utworzenie biblioteki imitacji klas wykorzystywanych do testowania modułów. Wspomniałem wcześniej o platformie Delphi Mocks Framework, której autorem jest Vince Parrett, autor słynnego narzędzia FinalBuilder (platformę tę opiszę dokładnie w następnym rozdziale). Inną doskonałą platformę testową, wchodzącą w skład pakietu DSharp, zbudował Stefan Glienke. W obu produktach wykorzystana jest klasa Tvirtual (cid:180)Interface do imitowania implementacji dowolnego interfejsu (aczkolwiek kod DSharp implementuje własną, bardzo pomysłową wersję tej klasy, która działa w wersji języka Delphi XE). W obu przypadkach można oczywiście wskazać w klasie dowolny interfejs i z powodzeniem testować moduły. A gdyby tak przygotować przykład bardzo prostego obiektu imitującego, który można byłoby wykorzystać do praktycznych testów? 10.3. Interfejs IProstaAtrapa W rozdziale „Testy jednostkowe” opiszę terminologię testową. Dokładnie omówię tam różnice pomiędzy atrapami (stub) i imitacjami (mock) klas. Dowiesz się tam, że atrapa jest to „klasa, która nie powoduje uzyskania ani pozytywnego, ani negatywnego wyniku testu i istnieje tylko po to, aby test można było wykonać”. A gdyby tak utworzyć uniwersalną atrapę, czyli klasę, która implementowałaby dowolny interfejs i nie robiła nic więcej? To nie powinno być zbyt trudne, prawda? Mamy już klasę implementującą interfejs, ale chcemy znaleźć sposób, aby klasa ta stała się interfejsem. Atrapa musi być tego samego typu co testowany interfejs, prawda? Poleć książkęKup książkę Przede wszystkim, ponieważ zawsze będziemy kodować abstrakcje, należy zadeklarować interfejs: Rozdzia(cid:239) 10. Klasa TVirtualInterface 117 1 IProstaAtrapa T = interface 2 [ {6AA7C2F0-E62F-497B-9A77-04D6F369A288} ] 3 function Wywo(cid:239)ywanyInterfejs: T; 4 end; Następnie zaimplementujmy go za pomocą klasy pochodnej od TRozszerzonyInterfejsWirtualny T : 1 TProstaAtrapa T: IInvokable = class(TRozszerzonyInterfejsWirtualny T , 2 IProstaAtrapa T ) 3 protected 4 procedure Wywo(cid:239)ajMetod(cid:218)Impl(Metoda: TRttiMethod; 5 const Argumenty: TArray TValue ; out Wynik: TValue); override; 6 public 7 function Wywo(cid:239)ywanyInterfejs: T; 8 end; Ponieważ klasa TProstaAtrapa T pochodzi od TRozszerzonyInterfejsWirtualny T , może implementować każdy wskazany w niej interfejs. Zastępowana jest w niej metoda Wywo(cid:239)ajMetod(cid:218)Impl klasy TRozszerzonyInterfejsWirtualny T , jak również implementowana metoda Wywo(cid:239)ywanyInterfejs interfejsu IProstaAtrapa T . Najpierw przyjrzyjmy się metodzie Wywo(cid:239)ajMetod(cid:218)Impl: 1 procedure TProstaAtrapa T .Wywo(cid:239)ajMetod(cid:218)Impl(Metoda: TRttiMethod; 2 const Argumenty: TArray TValue ; out Wynik: TValue); 3 begin 4 // Ponieważ jest to atrapa, nie można nic robić! 5 end; Niewiele tu widać — ten kod nic nie robi. Jednak do testów to wystarczy. Dokładnie tego oczekuje się od atrapy klasy — aby nie robiła nic. Nie zajmujemy się skutkami wywołania metod. Ważne jest jedynie, aby można było wywoływać je w testowanym kodzie. W tym momencie pojawia się funkcja Wywo(cid:239)ywanyInterfejs. Klasa zna typ testowanego interfejsu, ponieważ jest on przekazywany jako typ parametryczny. Klasa wie sama z siebie, jak zaimplementować zadany interfejs. Powinien zatem istnieć sposób uzyskania referencji do implementowanego interfejsu, prawda? 1 function TProstaAtrapa T .Wywo(cid:239)ywanyInterfejs: T; 2 var 3 pInfo : PTypeInfo; 4 begin 5 pInfo := TypeInfo(T); 6 if QueryInterface(GetTypeData(pInfo).Guid, Result) 0 then 7 begin 8 raise Exception.CreateFmt( Niestety, TProstaAtrapa T nie mo(cid:285)e zmieni(cid:202) typu s’ + 9 na interfejs , [string(pInfo.Name)]); 10 end; 11 end; Ponieważ klasa TProstaAtrapa T wie, czym jest typ T, można wywołać funkcję QueryInterface z informacją o typie T i uzyskać referencję do interfejsu. Oczywiście referencję tę można następnie dowolnie wykorzystywać podczas testów interfejsu w ramach testu modułu. Zatem teraz można bezpiecznie wywoływać metody testowanego interfejsu. Rozważmy następujący interfejs: 1 IPrzydatnyInterfejs = interface(IInvokable) 2 [ {16F01BF0-961F-4461-AEBE-B1ACB8D3F0F4} ] 3 procedure Witaj; 4 function TekstWstecz(aTekst: string): string; 5 function Iloczyn(x, y: integer): integer; Poleć książkęKup książkę 118 Programowanie w j(cid:218)zyku Delphi 6 end; 7 8 {...} 9 10 WriteLn( Implementacja klasy TProstaAtrapa ); 11 ProstaAtrapa := TProstaAtrapa IPrzydatnyInterfejs .Create; 12 WriteLn( Mi(cid:218)dzy tym a poni(cid:285)szym wierszem nie powinno si(cid:218) nic pojawi(cid:202) ); 13 ProstaAtrapa.Wywo(cid:239)ywanyInterfejs.Witaj; 14 ProstaAtrapa.Wywo(cid:239)ywanyInterfejs.Iloczyn(4, 4); 15 ProstaAtrapa.Wywo(cid:239)ywanyInterfejs.TekstWstecz( Przyk(cid:239)adowy tekst ); 16 WriteLn( Mi(cid:218)dzy tym a powy(cid:285)szym wierszem nie powinno si(cid:218) nic pojawi(cid:202) ); 17 WriteLn; Podczas wywoływania metod tego interfejsu nic się nie dzieje, bo takie jest założenie: atrapa klasy nie powinna nic robić. Ważne jest, aby można było je wywoływać podczas testowania modułu: 1 begin 2 {...} 3 MojaKlasaTestowa := 4 TKlasaImplementuj(cid:200)caCokolwiek.Create(ProstaAtrapa.Wywo(cid:239)ywanyInterfejs) 5 {...} 6 end; 10.4. Klasa TProstaImitacja Istnieje zatem przydatny, dynamiczny sposób wykorzystania klasy TVirtualInterface. Klasa TProstaAtrapa T świetnie się sprawdzi podczas testów, z których ma nie wynikać absolutnie nic. Jednak czasami potrzebny jest interfejs, który robi coś więcej, niż tylko istnieje. W takim przypadku tworzy się imitację klasy. W rozdziale poświęconym testowaniu modułów imitacja zdefiniowana jest jako „sztuczna klasa, udająca działanie testowanej klasy. W zależności od jej działania wynik testu może być pozytywny lub negatywny”. Imitacja zatem musi nie tylko istnieć, jak atrapa, lecz także coś robić, czyli działać w określony przez programistę sposób. Jedną z operacji najczęściej wykonywanych przez imitację jest zwracanie zdefiniowanego w jej kodzie wyniku po umieszczeniu w argumentach określonych danych. A gdyby tak utworzyć prostą imitację, która umożliwiałaby definiowanie działania wywoływanej metody? Oczywiście najpierw trzeba utworzyć kod interfejsu: 1 IProstaImitacja T = interface(IProstaAtrapa T ) 2 [ {9619542B-A53B-4C0C-B915-45ED140E6479} ] 3 procedure DodajWynik(aNazwaMetody: string; aWynik: TValue); 4 end; Interfejs ten pochodzi od interfejsu IProstaAtrapa T (pamiętaj, że w przypadku interfejsów termin „pochodzenie” nie odpowiada ściśle rzeczywistości) i dodaje metodę DodajWynik. Jest to metoda, która będzie wykorzystana do definiowania wyniku wywoływanej metody interfejsu. Poniżej przedstawiona jest klasa implementacyjna: 1 TProstaImitacja T: IInvokable = class(TProstaAtrapa T , IProstaImitacja T ) 2 private 3 FWyniki: TDictionary string, TValue ; 4 protected 5 procedure Wywo(cid:239)ajMetod(cid:218)Impl(Metoda: TRttiMethod; 6 const Argumenty: TArray TValue ; out Wynik: TValue); override; 7 public 8 constructor Create; 9 destructor Destroy; override; 10 procedure DodajWynik(aNazwaMetody: string; aWynik: TValue); 11 end; Poleć książkęKup książkę Rozdzia(cid:239) 10. Klasa TVirtualInterface 119 Przede wszystkim należy zwrócić uwagę, że klasa TProstaImitacja T pochodzi od klasy TProstaAtrapa T , zatem może implementować dowolny interfejs. Oczywiście implementuje ona również metodę DodajWynik. Parametrem tej metody jest nazwa wywoływanej metody interfejsu oraz wartość, która ma być przez nią zwracana. W ten sposób można dowolnie zdefiniować działanie klasy testowej. W tym bardzo prostym przykładzie przyjęte jest założenie, że testowane będą tylko funkcje i metody interfejsu. W ramach tego przykładu nie ma potrzeby testowania procedur, które z zasady nie wykonują żadnych operacji, przynajmniej w tym prostym przykładzie. Jak się przekonasz, w pełni funkcjonalna platforma testowa umożliwia śledzenie, czy dana procedura była wywoływana i ile razy, jak również umożliwia zbieranie innych informacji o procedurach. W tym przykładzie nie są uwzględniane parametry przekazywane metodzie, zwracany jest jedynie jej wynik. Pamiętaj, że jest to prosty, ale w pewnych sytuacjach przydatny przykład. Implementacja klasy TProstaImitacja T jest całkiem łatwa. Wewnątrz niej do śledzenia nazw wywoływanych metod i zwracanych przez nie wartości jest wykorzystywany słownik TDictionary TKey, TValue . Dane do niego są wpisywane za pomocą metody DodajWynik. Poniżej przedstawiona jest jej implementacja: 1 procedure TProstaImitacja T .DodajWynik(aNazwaMetody: string; aWynik: TValue); 2 begin 3 FWyniki.Add(aNazwaMetody, aWynik); 4 end; Dane te po dodaniu do słownika są wykorzystywane przez klasę do śledzenia wywoływanych metod. Jeżeli zostanie wywołana jakaś metoda interfejsu, wtedy klasa pobiera ze słownika odpowiedni wynik i zwraca go: 1 procedure TProstaImitacja T .Wywo(cid:239)ajMetod(cid:218)Impl(Metoda: TRttiMethod; 2 const Argumenty: TArray TValue ; out Wynik: TValue); 3 begin 4 Wynik := FWyniki[Metoda.Name]; 5 end; Oczywistą wadą powyższego kodu jest brak obsługi błędów. Jeżeli zostanie wywołana metoda interfejsu, dla której nie jest dostępna spodziewana zwracana wartość, wtedy zostanie zgłoszony wyjątek. Inny mankament polega na tym, że nie są uwzględniane wartości parametrów. Platforma testowa z prawdziwego zdarzenia musi umożliwiać definiowanie odpowiedzi w zależności od wartości podanych parametrów. Rozwiązanie tego problemu pozostawiam jako ćwiczenie dla Czytelnika. Teraz zatem, podczas korzystania z tej klasy, zwracane będą zadane dane. Poniższy kod: 1 WriteLn( Interfejs IPrzydatnyInterfejs z interfejsem IProstaImitacja ); 2 ProstaImitacja := TProstaImitacja IPrzydatnyInterfejs .Create; 3 ProstaImitacja.DodajWynik( Iloczyn , 99); 4 ProstaImitacja.DodajWynik( TekstWstecz , W rzeczywisto(cid:258)ci to dzia(cid:239)a ); 5 WriteLn(ProstaImitacja.Wywo(cid:239)ywanyInterfejs.Iloczyn(6, 7)); 6 WriteLn(ProstaImitacja.Wywo(cid:239)ywanyInterfejs.TekstWstecz( 7 Argumenty nie maj(cid:200) znaczenia )); 8 WriteLn; powoduje wyświetlenie następujących informacji: Poleć książkęKup książkę 120 Programowanie w j(cid:218)zyku Delphi Zwróć uwagę, że nie są to odpowiedzi, których należy się spodziewać, biorąc pod uwagę wartości parametrów (spodziewanym wynikiem mnożenia 6 przez 7 jest liczba 42), ale informacje, które wskaże się za pomocą metody DodajWynik. Teraz można wykorzystać interfejs IProstaImitacja T do określenia odpowiedzi wywoływanej metody. Być może chciałbyś przetestować metodę zwracającą wartość Boolean. Możesz użyć interfejsu IProstaImitacja InterfejsZMetod(cid:200)Boolean do sprawdzenia, co się stanie, gdy metoda ta zwróci wartość True lub False. 10.5. Wnioski Mamy zatem coś: przydatną implementację klasy TVirtualInterface. Choć przedstawione tu przykłady są naprawdę proste, można je wykorzystać do testów w praktyce, szczególnie implementację interfejsu IProstaAtrapa T . Atrapy klas są często stosowane podczas testów modułów i chociaż przedstawiona implementacja jest bardzo prosta, może być użyta do testowania każdego interfejsu. Pamiętaj, że klasę tę można wykorzystać wtedy, jeżeli znany jest interfejs i sposób jego implementacji. Są jednak przypadki, w których nie wiadomo, jaki interfejs będzie potrzebny do rozwiązania określonego problemu, i trzeba sprawdzić, który z nich okaże się najlepszy w określonej sytuacji. Atrapy i imitacje klas doskonale się do tego celu nadają. Są to potężne i przydatne narzędzia. Mam nadzieję, że niniejszy rozdział utwierdził Cię w tym przekonaniu. Poleć książkęKup książkę Skorowidz Delphi Spring Framework, 182 destruktor, 44 diagram Venna, 122 domknięcie, 55 DSharp, 16 DUnit, 154, 158, 164 DUnitX, 15, 154, 158, 163, 164, 182 dyrektywa, 100 $M+, 112, 171 $METHODINFO, 101 $RTTI, 100, 101 $STRONGLINKTYPES, 102 $WEAKLINKRTTI, 100 dziedziczenie interfejsów, Patrz: interfejs dziedziczenie klas, Patrz: klasa dziedziczenie E enumerator, 75, 76, 77, 78, 84 F FinalBuilder, 156, 170 FireMonkey, 11 funkcja, Patrz: metoda funkcjonalność, 26, 27 definicja abstrakcyjna, Patrz: interfejs RTTI, Patrz: RTTI G Gamma Erich, 34 Git, 182 GUID, 28 I identyfikator GUID, Patrz: GUID imitacja, 116, 118, 155, 156, 169, 172, 176, 177, 178, 179 konfigurowanie, 173 informacje RTTI, Patrz: RTTI instrukcja for...in, 66, 75, 76 try...finally, 58 uses, 26, 123 using, 58 with, 58 interfejs, 25, 26, 27, 34, 44, 111, 122, 151 deklarowanie, 26, 28, 31 dziedziczenie, 28, 30 generyczny, 43 IComparer, 44 identyfikator, 28 IEnumerable, 73, 81, 82, 83, 86, 87 deklaracja, 82 IEnumerator, 77 IInterface, 32, 112 IInvokable, 171 IList, 82 implementacja, 26, 28, 29, 30, 31, 111, 116, 142, 155, 170 dynamiczna, 111 zmiana, 35 instancja, 28 izolowanie, 129 kod, 27 pamięć, Patrz: pamięć zajmowana przez interfejsy pochodny, 30 segregacja, Patrz: zasada segregacji interfejsów w Delphi, 26 H Hanselman Scott, 155 hierarchia klas, Patrz: klasa hierarchia J jednostka, 154 A abstrakcja, 34 abstrakt, 31 antywzorzec, 147 atrapa, 116, 155, 169, 170, 176 zwracająca wartość, 173 atrybut, 103, 104, 105, 107, 109, 145 deklaracja, 104 Inject, 146 nieznany, 107 Setup, 158 SetupFixture, 158 TearDown, 158 TearDownFixture, 158 Test, 158, 164 TestFixture, 158, 164 autołączenie, 144 B Beck Kent, 162 biblioteka DLL, 18 imitacji klas, 116 OmniThread, Patrz: OmniThread RTL, 28, 33 Spring4D, Patrz: Spring4D uruchomieniowa, 44, Patrz: RTL zgłaszanie wyjątków, 22 blok try, 18 try...catch, 20 Class Under Test, Patrz: klasa testowana Code Insight, 11, 39 CUT, Patrz: klasa testowana C D DataSnap, 11 Delphi Mocks Framework, 16, 111, 156, 170, 182 Delphi Runtime Library, Patrz: RTL Delphi Sorcery Framework, 182 Poleć książkęKup książkę 190 Programowanie w j(cid:218)zyku Delphi K Kelly Barry, 183 klasa, 26, 92 abstrakcyjna, 27 bazowa, 29, 30 dziedziczenie, 28 Exception, 21 generyczna, 11 TDictionary, 44 TList, 44, 45 TObjectDictionary, 44 TObjectList, 44 TObjectStack, 44 TQueue, 44 TStack, 44 TThreadedList, 44 TThreadedQueue, 44 hierarchia, 123 implementacyjna, 29, 30, 111 implementowanie kilku interfejsów, 142 metadane, Patrz: metadane pochodna, 111, 112 pozorna, 169, 176 ServiceLocator, 132, 134, 139, 141, sprzęganie, 121, Patrz też: kod 147, 148, 150 sprzężony sztuczna, 155, 156 TAggregatedObject, 33 TApplication, 20 TClientDataset, 19 TCollections, 72, 73 TContainedObject, 33 TCustomAttribute, 103 TEnumerator, 80 testowa, 161 testowana, 154 TInterfacedObject, 32, 33, 112 TMock, 172, 176 TObject, 103 TRegistration, 140 TRttiContext, 93 TRttiField, 94 TRttiInterfaceType, 100 TRttiMethod, 95 TRttiProperty, 95 TRttiType, 93, 94, 100 TTestCase, 158 TVirtualInterface, 111, 112, 115, 116, 118, 170 klucz, 66 kod abstrakt, Patrz: abstrakt interfejsu, Patrz: interfejs kod rozprzęganie, 25, 26, 27, 111, 124, 129, 131 rozprzężony, 25, 34 sprzęganie, 26 sprzężony, 121 luźno, 34, 35, 124 za bardzo, 35 wzorzec, 36 źródłowy, 182 kolejka, 66, 69 kolekcja, 44, 65 element, 84, 85, 86 generyczna, 66, 73 ICollection, 72, 73 IDictionary, 73 IList, 72, 73 instancja, 84 IQueue, 72, 73 ISet, 73 IStack, 73 niegeneryczna, 72, 80 pochodna, 72 podzbiór, 81 TDictionary, 66, 70 TList, 66 TObjectDictionary, 66, 72 TObjectList, 66, 72 TObjectQueue, 66, 72 TObjectStack, 66, 72 TQueue, 66, 69 TStack, 66, 68, 69 TThreadedQueue, 66 TThreadList, 66 kompilator, 28, 32, 76 dyrektywa, Patrz: dyrektywa ustawienia domyślne, 89 konstruktor, 44, 121, 123 Create, 40, 76, 131 wstrzykiwanie, Patrz: wstrzykiwanie konstruktora kontener Spring Container, Patrz: moduł Spring.Container wstrzykiwania zależności, Patrz: wstrzykiwanie zależności kontener kontrawariancja, 48 kowariancja, 48 lista, 66 L M Mercurial, 182 Meszaros Gerard, 155 metadane, 89 metoda, 89 _AddRef, 31, 32 _Release, 31, 32 Add, 73 All, 85 anonimowa, 11, 51, 52, 57, 58, 59, 61, 63, 141 deklarowanie, 52 jako zmienna, 55 Any, 85 AsObject, 84 AsPooled, 140, 141 Assert.AreEqual, 161 Assert.IsTrue, 161 AsSingleton, 140 AsSingletonPerThread, 140, 141 AsTransient, 140, 141 CheckEquals, 158, 161 CheckNotEquals, 158 CheckTrue, 161 Concat, 86 Contains, 85 Count, 86 CreateAnonymousThread, 61 DelegateTo, 141 DoCurrent, 80 DoGetCurrent, 80 DoGetEnumerator, 80 DoMoveNext, 80 ElementAt, 85 EqualsTo, 86 Expect, 173 First, 84, 85 FirstOrDefault, 85 ForEach, 86 generyczna, 43, 44 GetAttributes, 107 GetCurrent, 78 GetDeclaredMethods, 95 GetEnumerator, 75, 76, 78, 84 GetMethods, 95 GetProperties, 95 InjectConstructor, 146, 148 InjectField, 146, 148 InjectMethod, 148 InjectProperty, 146, 148 Invoke, 98 IsClassMethod, 98 IsEmpty, 86 IsManaged, 100 IsOrdinal, 100 IsRecord, 100 IsSet, 100 IsStatic, 98 klasy, 98 LastOrDefault, 85 łączenie w ciąg, 84 Max, 85 Poleć książkęKup książkę Skorowidz 191 Min, 85 MoveNext, 75 odczytująca dane, 29 Peek, 69 private, 29 przeciążona, 158 przypisująca, 136 QueryInterface, 32, 117 Queue, 61 RegisterType, 139 rejestrująca, 139 Remove, 73 Reversed, 86 Setup, 158 Single, 85 SingleOrDefault, 85 Skip, 85 SkipWhile, 85 statyczna, 98 Take, 85 TakeWhile, 84, 86 TClass, 96 TearDown, 158 testowa, 158 ToArray, 86 ToList, 86 ToSet, 86 TryGetFirst, 84 TryGetLast, 84 TValue, 91 TypeInfo, 112 Verify, 173, 178 warunek konieczny, 17 When, 173 Where, 85 WillReturn, 173 wstrzykiwanie, Patrz: wstrzyki
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

Programowanie w języku Delphi
Autor:

Opinie na temat publikacji:


Inne popularne pozycje z tej kategorii:


Czytaj również:


Prowadzisz stronę lub blog? Wstaw link do fragmentu tej książki i współpracuj z Cyfroteką: