Delphi - next generation

Alin Flaidăr

Desi apărut la apusul epocii codului pe 16 biti, Delphi a impus un nou standard în dezvoltarea rapidă de aplicatii si reprezintă primul mariaj fericit între un mediu de dezvoltare vizuală si un compilator veritabil. Noua versiune pe 32 de biti readuce produsul pe creasta valului tehnologic si vizează o crestere dramatică atît a productivitătii dezvoltatorilor cît si a performantelor aplicatiilor acestora.

Încă din toamna anului trecut Borland si-a precizat obiectivele ambitioase ale noului Delphi 2. Să le trecem în revistă si să inspectăm modul în care acestea s-au regăsit în produsul final:

Arhitectura compilatorului de cod optimizat pe 32 biti

Noul compilator Pascal este construit pe o tehnologie comună cu C++ versiunea 4.5 si împrumută masiv de la acesta din urmă de la tehnici de optimizare a codului pînă la raportarea în stivă a erorilor de compilare. O mostenire directă este si suportul dual al lui Delphi pentru fisiere de tip unităti Turbo Pascal (DCU) si fisiere în format standard OBJ. Ca urmare, partajarea de cod între Pascal si C++ a încetat să mai fie o problemă.

Trecerea la cod pe 32 biti cu al său model plat de memorie marchează inevitabil si căderea barierei celor 64 KB. În fine, structurile de date de orice fel, vectorii si string-urile pot avea acum orice dimensiune - limitată numai de sistemul de operare (2 GB pentru Win95). S-a terminat cu împărtirea parcimonioasă a celor 64 KB între segmentul de date si cel de stivă, cu depăsirile de stivă: segmentele de date si de stivă pot avea orice dimensiune iar cel de stivă poate creste dinamic.

Proiectantii au reusit să introducă tehnici remarcabile de optimizare a codului păstrînd compilarea într-un singur pas precum si viteza de peste 350000 linii pe un procesor Pentium. Optimizarea registrilor, utilizarea registrilor pentru reducerea stivelor de apel de rutine, eliminarea subexpresiilor comune, inducerea variabilelor de buclă generează cod masină deosebit de rapid si compact care nu schimbă sensul codului original si poate fi depanat natural cu debugger-ul.

Noul link-editor apelat la sfîrsitul procesului de compilare este cu 20% pînă la 50% mai rapid decît versiunea precedentă. Cîteva optimizări concură la obtinerea acestui rezultat. Astfel, utilizarea unei scheme de păstrare în memorie a unitătilor si formelor nemodificate măreste semnificativ viteza de link-editare prin comparatie cu reînărcarea modulelor de pe disc. Un nou format pentru unităti (DCU) permite link-editorului să utilizeze o tehnică de verificare inteligentă a versiunilor care reduce drastic redundanta din recompilare. Astfel, dacă în trecut modificarea unei functii dintr-o unitate determina recompilarea automată a tuturor unitătilor care foloseau vreun element din interfata unitătii modificate, acum numai unitătile care apelează explicit functia modificată sînt incluse în procesul de recompilare. Producătorii de biblioteci de obiecte si componente nu vor mai fi nevoiti să distribuie o nouă versiune, recompilată, pentru fiecare nouă versiune de Delphi.

Nu demult, la aparitia noilor sisteme de operare pe 32 biti, numeroase voci sustineau că noul cod pe 32 biti ar fi mult mai obez decît echivalentul lui pe 16 biti. Cu certitudine acest fapt nu este valabil pentru Delphi 2: optimizările compilatorului si link-editorului reduc tipic cu 20-25% dimensiunea executabilului rezultat.

Compatibilitate cu codul pe 16 biti

Fractura dintre sistmele de operare pe 16 si cele pe 32 biti s-a propagat pînă în mediile de dezvoltare de aplicatii. Ce-i drept, spre deosebire de Microsoft care asigură suport numai pentru ultimele tehnologii, Borland a făcut din totdeauna eforturi de protejare a investitiilor clientilor săi prin asigurarea unui nivel rezonabil de compatibilitate cu versiunile precedente ale compilatoarelor sale. La fel stau lucrurile si cu Delphi 2 a cărui compatibilitate cu versiunea precedentă este un veritabil pod între două lumi foarte diferite.

În cele mai multe cazuri, aplicatiile pe 16 biti pot fi pur si simplu recompilate si îmbogătite cu facilităti specifice pe 32 biti. Portabilitatea este asigurată de asa numitul unit aliasing care permite redirectionarea referintelor la unităti vechi către versiunile noi, de manipularea mesajelor prin tipuri similare de date, precum si de păstrarea în paletă a unor componente - altfel depăsite - din versiunea anterioară.

Portarea codului de pe 16 pe 32 de biti îsi are însă avatarurile ei, indiferent că este vorba de Pascal ori C++. Unele tipuri de date implicite si-au schimbat dimensiunea si au apărut tipuri noi de date care servesc mai bine scopuri vechi. Codul care presupune o anumită dimensiune fizică a structurilor de date devine inoperant. Optimizările în limbaj de asamblare sînt nu numai necompilabile dar si desuete în cele mai multe cazuri prin comparatie cu cele efectuate nativ de compilator. Alocarea de memorie pe bază criteriului memoriei libere nu mai functionează corect ca urmare a noii scheme de alocare a memoriei dintr-un spatiu de adrese virtual nelimitat.

Tehnicile clasice de comunicatie inter-aplicatii sînt total neutilizabile în noul mediu cu cerinte sporite de stabilitate în care aplicatiile rulează în spatii de adrese complet diferite si nu mai pot partaja un banal bloc de memorie. Bibliotecile DLL pe 16 biti care asigurau partajarea variabilelor globale între mai multe instante ale aceleiasi aplicatii sau între aplicatii diferite dau cea mai mare bătaie de cap întrucît securitatea multitasking-ului preemptiv al lui Win32 impune alocarea unui segment de date separat pentru fiecare instantă. Solutiile pentru aceste probleme sînt specifice pentru Win32 si comportă fisiere mapate în memorie ori utilizarea unui mesaj special de copiere a datelor dintr-un spatiu de adrese în altul.

Si nu în cele din urmă, noul cod pe 32 biti nu mai link-editează dinamic vechile DLL-uri pe 16 biti, care trebuie fie recompilate, fie - în absenta surselor - accesate via DDE prin scrierea unui server DDE specializat. Nu mai vorbim de VBX-uri care trebuiesc total înlocuite cu controalele OCX echivalente.

Suport complet pentru controale si automatizare OLE

Borland a renuntat la veleitătile de independentă din trecut, aderînd acum în întregime la tehnologia OLE. Formatul obiectelor din Delphi si BC++ au la bază modelul comun de obiect (COM), ambele limbaje oferind astfel suport obiectual nativ pentru OLE. Integrarea OLE merge pînă la a asigura compatibilitate completă cu viitorul Network OLE anuntat de Microsoft.

Integrarea controalelor OLE (OCX) într-un mediu de dezvoltare complet obiectual precum cel al lui Delphi nu prezintă nici o problemă. Mai usor decît cu bătrînele VBX, controalele OCX se includ facil în paleta de componente, iar Delphi creează automat o clasă care "îmbracă" controlul în component cu proprietăti, metode si evenimente, si permite chiar dezvoltatorilor derivarea de noi obiecte care să mostenească caracteristicile controlului original.

Întrucît compilatorul generează cod masină nativ, Delphi poate fi utilizat si pentru scrierea de noi controale OCX, cu toate că această sarcină este sensibil mai dificilă decît dezvoltarea de componente native.

Un nou tip - variant - a fost creat special pentru facilitarea automatizărilor OLE. Acesta permite utilizatorilor să declare variabile al căror tip este determinat în timpul rulării, adaptînd astfel aplicatia de tip controlor OLE la flexibilitatea automatizării OLE. În fapt, se poate utiliza o singură variabilă pentru conectarea la diferite tipuri de servere OLE.

Parametrii cu nume permit utilizatorilor să specifice numai parametrii de interes în apelurile de servere OLE, păstrînd valorile implicite ale server-ului pentru ceilalti parametri.

Programatorii care au remarcat cu neplăcere absenta de suport obiectual pentru server OLE în precedenta versiune pe 16 biti vor fi multumiti să constate că Delphi 2 este capabil să creeze server-e OLE Automation atît conectate în proces cît si independente. Puteti exporta metodele server-ului OLE către oricare tert controller OLE, de la o aplicatie creată cu Delphi 2 pînă la Microsoft Word sau Excel. O nouă perspectivă se deschide acum programatorilor Delphi - aceea de a putea separa functiile aplicatiei în module distincte construite pe o arhitectură client-server, care pot rula local sau pe masini diferite exploatînd la maximum resursele procesorului prin multi-threading precum si cele ale retelei prin împărtirea sarcinilor pe masini distincte.

Scrierea unui server OLE se face la propriu, singurul suport vizual fiind asigurat doar în primii pasi de Automation Object Expert. Functionalitatea de server OLE se obtine prin mostenire de la clasa TAutoObject, la care se adaugă proprietătile si metodele exportate într-o sectiune specială, botezată automated. Aplicatia poate fi compilată ca DLL, rezultînd un server conectat în proces sau se poate obtine un executabil ce se comportă ca server independent.

Cei 32 biti de la Microsoft

În Delphi 2 se regăseste suport pentru toate facilitătile oferite de Windows 95 si NT. De departe cea mai semnificativă este capacitatea de a crea cod executabil în fire paralele de executie (multi-threading). Complexitatea initierii si controlării firelor de executie paralele este încapsulată acum într-o clasă specializată - TThread - care permite definirea unui thread prin introducerea codului specific în metoda Execute si atribuirea unei metode care reactionează la încheierea executiei firului. Prioritatea executiei se stabileste prin simpla atribuire de valoare proprietătii Priority, iar lansarea thread -ului prin setarea proprietătii Suspended.

Încapsularea obiectuală a thread-urilor face ca executarea în paralel a mai multor sarcini identice să se reducă la instantierea mai multor obiecte din aceeasi clasă derivată din TThread. Diferitele instante pot partaja variabilele globale între ele sau crează copii proprii ale variabilelor prin utilizarea declaratiei threadvar. Exceptînd unele componente din Visual Component Library, nu există restrictii asupra includerii în codul thread-ului a obiectelor sau functiilor din interfata API Windows.

Biblioteca de sistem include tipuri si functii care asigură suport complet pentru Unicode. Tipul fundamental WideChar defineste caracterul reprezentat pe 16 biti si ordonat conform Unicode, în timp ce PWideChar este pointer la string-ul de caractere Unicode. Tipul generic Char continuă însă să fie de tip ANSI, pe 8 biti.

Interfata procedurală cu Win32 API este completă (chiar dacă mizerabil documentată) si permite accesul aplicatiilor la diversele functionalităti oferite de sistemul de operare. Între acestea se numără si Winsockets, fisiere mapate în memorie, interfata de comunicatii TAPI. Totusi, cel putin pentru suportul groupware MAPI ar fi fost necesară o interfată obiectuală dedicată.

Mai multă productivitate

Doar cerintele utilizatorilor de azi privind functionalitatea aplicatiilor cresc la fel de repede precum scad termenele de predare. Presiunea sporită asupra dezvoltatorilor de programe face ca acestia să nu se mai multumească doar cu un compilator foarte rapid; dezvoltarea este frînată de numerosi factori si solutiile însumate pot duce la salturi spectaculoase de productivitate.

Object Pascal a dispus întotdeauna de avantajele traditionale ale compilatorului care depistează erori logice provenite din cod incorect ori ambiguu, ca si de verificările stricte de tip. În noua versiune, compilatorul continuă să compileze codul chiar si după găsirea primei erori, oferind o imagine completă a corectitudinii programelor, utilă mai ales în depanarea proiectelor mari. Contrar compilatoarelor C++, rareori o primă eroare induce raportarea unei întregi serii de erori fără relevantă.

Compilatorul oferă acum un sistem de diagnosticare a erorilor mult mai complet incluzînd detectarea utilizării de variabile sau pointeri neinitializati, variabile neutilizate, rezultate neutilizate returnate de functii, bucle goale si nepotriviri de tipuri. Analizorul sintactic a devenit mai subtil, permitîndu-si sugestii utile mai ales programatorilor începători.

Tot acestia din urmă au tendinta de a comasa întregul cod într-o singură unitate greu de întretinut si depanat. Pentru a-l încuraja sa-si separe în mod logic munca în unităti distincte cu interfete strict delimitate, Delphi le oferă selectia vizuală a unitătilor care se includ în clauza uses.

Următorul pas logic pentru încurajarea programării modulare a fost referinta automată la componente continute în forme diferite. Desi proprietătile sau metodele componentelor din alte forme decît cea curentă erau accesibile programatic (prin scrierea de cod), în faza de design erau inaccesibile. Facilitatea de a referi componente din alte forme ale proiectului în timpul dezvoltării vizuale permite separarea modulelor care încapsulează structurile de date ca si relatiile dintre acestea de modulele care implementează interfata cu utilizatorul.

În acelasi context se înscrie si noul tip de obiect vizual - DataModule - destinat stocării componentelor non-vizuale cum ar fi tabelele, query-urile si sursele de date pentru a încuraja separarea logicii de baze de date si de calcul de elementele de prezentare vizuală pentru interactiune cu utilizatorul. Structura bazei de date poate fi definită în mod consistent într-un modul de date o singură dată pentru întregul proiect, iar obiectele continute de acesta pot fi referite apoi din diverse alte forme.

Poate cea mai importantă obiectie a puristilor programării obiectuale fată de tehnica vizuală a precedentei versiuni a lui Delphi a fost imposibilitatea de a deriva - vizual - noi forme prin mostenirea celor existente. Este natural - într-un mediu complex de proiectare - să creezi obiecte standard, din care urmează să fie derivate obiecte concrete care să mostenească imediat orice modificare s-ar efectua în obiectele de bază. Delphi 2 preia această caracteristică fundamentală OOP si o extinde la mediul vizual de dezvoltare. Prin tehnica mostenirii vizuale se pot crea - în faza de design - noi forme care să preia proprietătile, evenimentele si metodele formei originale pe oricîte nivele de mostenire, fără a induce penalizări de performantă în aplicatia finală.

Pentru formele cu caracter mare de generalitate - utilizabile în mai multe proiecte - Delphi 2 oferă un mediu de stocare - Object Repository - partajabil chiar de membrii unei echipe într-o retea locală. Tot aici pot fi stocate module de date, biblioteci DLL sau experti. Orice aplicatie poate mosteni, referi sau copia un obiect din Object Repository.

Controale Windows 95

Între cele aproape 100 de componente din paleta lui Visual Component Library se regăseste si suita completă de controale specifice lui Windows 95 si disponibile în curînd si în Windows NT 4.0. Suita se compune din TabSet si PageControl pentru crearea de dialoguri cu mai multe pagini, TreeView destinat afisării unei ierarhii de obiecte, ListView pentru prezentarea pe coloane a unei liste de obiecte, ImageList care controlează o listă de imagini pentru afisare arborescentă sau pe coloane, HeaderControl pentru plasarea de bare de control pe spatiul de lucru, RichEdit - un editor de text cu facilităti extinse de formatare, StatusBar - zonă plasată în partea inferioară a ferestrelor destinată afisării situatiei curente a aplicatiei, TrackBar - o îmbunătătire sub formă de potentiometru a clasicului scrollbar, ProgressBar - similar cu TGauge si destinat afisării progresului unei proceduri, UpDown - butoane de incrementare / decrementare a unei valori, si în fine, HotKey - conceput pentru atasarea facilă a unor combinatii de taste active pentru orice component.

Prin draparea lor în componente, programatorul este scutit de frecusul cu interfata noduroasă de nivel procedural. Cînd este necesar un nivel superior de functionalitate, dezvoltatorii pot implementa propriile lor metode, proprietăti si componente prin mostenire. Toate controalele Win95 pot fi subclasate, ba chiar reprezintă un teren fertil pentru inovatii si extensii. În pachetul Developer se livrează si sursele complete ale bibliotecii de componente, care se dovedesc foarte valoroase în întelegerea comportamentului specific al obiectelor de interfată.

Suport extins pentru aplicatiile de baze de date

Numeroase sînt extensiile de baze de date care pot fi regăsite în actuala versiune de Delphi si care usurează considerabil surmontarea problemelor specifice ridicate de proiectele de baze de date.

Dictionarul de date stochează si utilizează informatia despre continutul si comportamentul datelor din tabele. Aici se pot specifica atribute extinse de cîmpuri precum valorile minimă, maximă si implicită, optiunile de formatare în afisare si editare. Este locul ideal pentru a stabili si asigura integritatea datelor. Formele în care urmează să fie utilizate vor prelua instantaneu caracteristicile si vor stabili conexiunile la selectarea cîmpurilor de date.

Componentele de acces la bazele de date au fost rescrise în întregime păstrînd însă interfata versiunilor precedente. Astfel, tabelele si query-urile sînt completate cu proprietăti si evenimente de filtrare dinamică a datelor si oferă evenimente suplimentare pentru tratarea extinsă a erorilor. Există o proprietate care permite utilizarea facilitătii de stocare în cache a modificărilor (detalii despre cache updates mai jos). Tabelele pot face uz de tehnica specială BDE de filtrare a datelor printr-o expresie de tip SQL care garantează obtinerea unui set editabil de înregistrări (ceea ce nu întotdeauna este posibil printr-un query) cu minimum de consum de memorie.

Paleta de acces la baze de date s-a îmbogătit cu o formă specială de query - TUpdateSQL - care preia operatiunile de stergere, inserare si actualizare de înregistrări spre deosebire de clasicul TQuery, care este rezervat acum doar pentru operatiuni de interogare. Remarcabil este editorul vizual de compunere rapidă a frazei SQL, inclus în toate versiunile pachetului spre deosebire de editorul lui TQuery rezervat în continuare pentru greu accesibilul pachet Delphi Client-Server.

De o atentie deosebită se bucură si componentele vizuale de prezentare si editare a datelor. Obiectele DBLookupCombo si DBLookupList sînt păstrate numai pentru compatibilitate; înlocuitoarele lor mai versatile si mai performante sînt acum DBLookupComboBox si DBLookupListBox. Omniprezentul DBGrid este semnificativ îmbogătit cu facilităti de formatare la nivel de coloană si include tehnici de căutare si look-up în cîmpul curent. Un nou component - DBCtrlGrid permite prezentarea mai multor înregistrări dintr-o tabelă, fiecare avînd rezervat propriul spatiu de afisare în care se pot plasa toate celelalte tipuri de controale de date pentru editarea cîmpurilor. Afisarea unei liste de imagini dintr-o tabelă se poate face astfel fără a mai scrie vreo linie de cod.

În precedenta versiune a bibliotecii de componente se resimtea puternic absenta unui set de componente pentru dezvoltarea vizuală de rapoarte. Greul Report Smith era în mod evident destinat aplicatiilor de corporatie bazate pe server-e SQL, fără a se potrivi cu necesitătile unei aplicatii desktop. Din fericire industria shareware a produs rapid cîteva asemenea solutii, dintre care Borland a cumpărat-o pe cea mai reusită si a inclus-o în toate pachetele de Delphi. QuickReport reprezintă un set de 11 componente care se integrează perfect cu componentele de acces la bazele de date (TTable, TQuery), dar pot prelua datele si din vectori, liste sau orice fel de variabile. Rapoartele se redactează sub forma clasică de benzi care pot include titluri, cîmpuri calculate, de însumare si de sistem, dar si imagini bitmap sau metafile ori forme geometrice simple. Sînt posibile rapoarte master-detail pe mai multe nivele sau cu mai multe seturi detail si grupate pe criterii foarte diverse, inclusiv cîmpuri calculate. Benzile pot reprezenta seturi detail, antete sau subsoluri de pagină, grup sau raport si pot fi organizate pe mai multe coloane sau în format de etichete multiple, iar calculele pot fi initializate la nivel de bandă. Datele se pot previzualiza în faza de design iar un component special permite previzualizarea lor în timpul rulării. Pentru baze de date mici (de ordinul zecilor de mii de înregistrări) Quick Report este cu un ordin de mărime mai rapid decît Report Smith. Ca urmare însă a includerii lor în fisierul executabil sub formă de resurse, rapoartele sînt complet inaccesibile utilizatorului final pentru modificări.

Mai multă putere în motorul de baze de date

Prezentarea lui Delphi 2 nu putea omite noua versiune pe 32 biti a lui Borland Database Engine, pe care se bazează performantele obtinute de programele Delphi de baze de date, aceleasi de altfel cu cele obtinute cu Paradox sau Visual dBASE. BDE comportă o arhitectură obiectuală care permite un acces simplu si nativ din limbajele obiectuale la functiile încorporate de un nivel foarte înalt, de la operatiuni cu seturi de date prin interogări SQL sau QBE si filtre pînă la suport navigational complet prin relatii master-detail si lookup.

Noua conceptie pe 32 biti se reflectă în suportul pentru multitasking preemptiv: mai multe programe pot fi deservite simultan de BDE si pot accesa aceeasi bază de date în acelasi timp. În plus, în cadrul aceluiasi program se pot executa simultan mai multe operatiuni BDE separate în fire de executie diferite. Este posibilă astfel executia de query-uri multiple în spate în timp ce în fată utilizatorul editează o tabelă.

BDE suportă acum nume lungi, descriptive (260 caractere incluzînd si spatii) de tabele desktop, inclusiv în fraze SQL sau QBE. Numele de tabele SQL sînt în general limitate la 30 de caractere de server-le SQL corespunzătoare.

Accesul la bazele de date de pe server-e se poate efectua acum prin utilizarea conventiei UNC (conventia numelui universal) preferată de Win95 si NT mapării discurilor logice.

Nucleul de interogare SQL este complet rescris si separat acum de nucleul QBE. Performanta interogărilor SQL pe tabele desktop a crescut substantial si au căzut o serie de restrictii din subsetul Local SQL, care se apropie acum si chiar depăseste standardul SQL 92. Sînt posibile includerea de subquery-uri în clauzele WHERE si HAVING, utilizarea de expresii în functiile de agregare (gen SUM( Cîmp1+Cîmp2) sau chiar SUM( MIN(Cîmp1))), ca si în clauzele GROUP BY si ORDER BY, precum si utilizarea operatorului UNION. În paranteză fie spus, bug-ul care împiedica un full outer join cu cîmpuri multiple de legătură persistă încă si în noua versiune. Subseturile de înregistrări returnate de înterogări asupra mai multor tabele pot fi editate cu reflectarea modificărilor în tabelele originale. Subseturile rezultate din query-uri pot fi suplimentar rafinate prin utilizarea de filtre.

O îmbunătătire care va îndepărta cosmarul multor dezvoltatori de baze de date desktop este suportul tranzactional complet pentru tabele Paradox si dBASE. Modificările tabelelor pot fi grupate într-o tranzactie si efectuate (commit) sau anulate (rollback) integral, asigurînd actualizarea bazei de date de o manieră consistentă si cu păstrarea integritătii referentiale. Driver-ul pentru tabele Paradox > ver.6 este capabil de index secundar unic, index cu ordonare descrescătoare si cîmpuri care se auto-incrementează, în timp ce driver-ul dBASE suportă acum încriptarea tabelelor si index în format Clipper.

Facilitatea de efectuare locală a modificărilor (cached updates) permite utilizatorilor să efectueze operatiuni asupra bazei de date într-o perioadă mai lungă de timp fără a modifica imediat baza de date de pe server, reducînd la minimum consumul de resurse pe server ca si traficul pe retea.

Dezvoltatorii de aplicatii client-server SQL vor aprecia posibilitatea de a monitoriza frazele SQL care se transmit server-ului la fiecare executie de functie BDE, ca si utilizarea de guvernatori care limitează numărul de înregistrări din seturile de date returnate de server în scopuri de accelerare a procesului de dezvoltare.

Run

Decizia de a lucra cu Delphi 2 se împleteste strîns cu aceea de a accepta si exploata un nou mediu de lucru, pe 32 biti, multitasking, multithreading, cu noi concepte de realizare modulară a programelor prin OLE Automation si tehnici client-server. În ultimul an sistemele de operare pe 32 biti au atins masa critică iar industria a început să se schimbe din nou. Jucătorii de marcă mizează acum pe 32 biti iar Delphi 2 a apărut la momentul oportun pentru a face tranzitia rapid si eficient.

Caseta Inovatii în Object Pascal


(C) Copyright Computer Press Agora