În cadrul oricărei aplicații, un sistem de gestiune a datelor e un topic comun, aproape toate aplicațiile îl folosesc într-un fel sau altul. Indiferent că sunt aplicații financiare care lucrează cu servere de baze de date sau jocuri care păstrează preferințele utilizatorului în fișiere text, aceste aplicații se bazează pe existența unui strat de persistare a informațiilor
De-a lungul evoluției acestor sisteme de gestiune, bazele de date relaționale au fost cele care au cunoscut cea mai bună dezvoltare. Există pentru ele chiar și teorii matematice pentru a exprima într-un mod mai abstract construcțiile relaționale.
Pe de altă parte, standardul de programare care s-a impus cel mai mult este programarea orientată pe obiect și s-a ajuns în situația în care trebuie să combinăm două metodologii care în general nu prea se împacă. Avem pe de o parte domeniul aplicației care este o ierarhie de obiecte și clase cu relații specifice, iar pe de altă parte avem o multitudine de tabele cu relații specifice între ele. Ierarhiile de clase sunt făcute pentru a fi traversate cu ușurință, pe când relațiile dintre tabele sunt gândite pentru a aplica operații de tipul proiecțiilor, selecțiilor, intersecțiilor ș.a.m.d. Dar ce le rămâne dezvoltatorilor care doresc să lucreze în modul în care și-au structurat gândirea? Un răspuns simplu pe care toți au ajuns să îl dea la genul acesta de întrebare este: un ORM32. ORM-uri au ajuns un standard și ele în ce privește SGBD33-urile, existând la ora actuală un număr impresionant de astfel de soluții dintre care pot enumera : NHibernate34, OpenAccess ORM35, LightspeedORM36.
Într-adevăr, bazele de date ralaționale în combinație cu un ORM sunt un standard acceptat, însă pentru această aplicație am vrut să „explorez” un teren mult mai nou și anume cel al bazelor de date obiectuale. Industria nu a stagnat în ultimii ani, dar probabil nu au fost destule cereri în acest sens pentru a promova un nou tip de sisteme de gestiune a bazelor de date cum sunt OODBMS37. Plus că pe partea financiară firmele de software au investit mult, peste orice cifră imaginabilă în SGBD-uri relaționale, în administratori ale acestor baze de date și în unelete care să le spună cât de performantă este DAL38-ul lor și query-urile pe care le emit.
OODBMS-urile au fost dezvoltate încă de prin ani ’70, însă termenul în sine a apărut pentru prima dată de-abia prin 1985. O mulțime de experimentări au fost introduse de-a lungul timpului și chiar și produse comerciale foarte de succes au ieșit pe rampă. Un fapt important de luat în considerare este că o bază de date obiectuală a ţinut pentru prima oară mai mult de 1000 de teraocteți și cea mai mare rată de inserție de date, aproximativ 1 teraoctet pe oră conform lucrării [Becla2005].
Utilizarea unui OODBMS aduce cu sine avantajul de a nu mai fii nevoit să faci faţă incompatibilității din modul de reprezentare a datelor, oferă transparență când e vorba de persistarea obiectelor și, contrar părerilor actuale, nu au o curbă de învățare abruptă, nu sunt încete, suportă interogările și sunt scalabile.
Am găsit utilizarea unei baze de date obiectuală foarte revigorantă. Mi-a permis să mă gândesc clar la obiectele din domeniu. Nu am vrut nici să abuzez de opțiunile date, însă m-a scutit pe partea de development de foarte multe mapări și interogări pe care le-aș fi scris în mod normal într-un DAL.
Capitolul 3. Librării implicate în dezvoltarea aplicației 3.1 Librăria StructureMap
StructureMap oferă facilități pentru injectarea dependințelor și configurarea acestora (inversarea controlului) fie prin cod, fie folosind fișiere xml. În acest fel se poate obține un nivel foarte mare de decuplare a codului.
Ca și regulă, dependințele au fost declarate în constructor, astfel încât să poată fi injectate în momentul în care este necesară construirea altor instanțe. Declarațiile sunt foarte simple și directe după cum se poate vedea din exemplul următor:
namespace Universum
{
public static class Bootstrap
{
public static void BootstrapStructureMap()
{
ObjectFactory.Configure(configure =>
{
configure.AddRegistry();
configure.AddRegistry();
configure.AddRegistry();
configure.AddRegistry();
configure.AddRegistry();
configure.AddRegistry();
configure.AddConfigurationFromXmlFile("StructureMap.config.xml");
});
}
}
}
În general, se păstrează toate configurațiile într-un singur loc și din ce se vede evident organizate în extensii ale clasei Registry, care permite configurarea din cod. Există cazuri în care extensiile trebuie specificate din configurații, motiv pentru care există o directivă către StructureMap.config.xml. Modul în care a fost gândit acest fișier permite importarea de noi fișiere de configurare direct.
Un listing pentru o extensie a tipului Registry arată în felul următor:
public class RepositoryRegistry : Registry
{
public RepositoryRegistry()
{
ForRequestedType().TheDefault.Is.ConstructedBy(ctx => ctx.GetInstance());
ForRequestedType()
.TheDefaultIsConcreteType();
ForRequestedType()
.TheDefaultIsConcreteType();
}
}
În mediile .NET și Java s-au adoptat configurațiile din cod în două moduri: prin atribute, respectiv anotații sau prin șablonul FluentInterface39. StructureMap adoptă ambele stiluri, dar eu am ales interfața fluentă, întrucât este pe de o parte o preferință personală, dar și mai eficientă decât atributele, nemaifiind necesară parcurgerea tuturor tipurilor din assembly pentru a construi harta tipurilor care trebuie injectate.
Configurația prin fișiere XML40 este destul de simplă, fără a intra prea mult în detalii menționez că e necesar declararea unui element rădăcină denumit care aceptă adițional două atribute DefaultProfile – specifică profilul folosit la runtime – și MementoStyle – care specifică modul în care se definesc nodurile documentului. Ca și noduri se poate utiliza:
-
eticheta care aduce noi fișiere din care se încarcă configurații;
-
eticheta care specifică unde se vor căuta tipurile definite ca și plugin-uri;
-
eticheta care conține instanțele definite;
-
eticheta care permite crearea de suprascrieri globale a unor valori utilizate;
-
eticheta care are ca efect specificarea tipului concret ce va fi utilizat pentru un tip abstract.
Odată ce serviciile, și implicit implementările lor, au fost înregistrate, accesul la un tip de date se poate face prin cod utilizând tipul ObjectFactory printr-un apel către metoda statică GetInstance și utilizând ca parametru tipul dorit sau folosind funcția în forma generică GetInstance. StructureMap determină dinamic tipurile care vor fi injectate fie prin constructor, fie prin proprietăți pe baza configurației, iar pentru tipurile care nu pot fi construite aruncă o eroare.[wStrMap]
Motivul pentru care am ales această librărie a fost în primul rând simplitatea utilizării și în al doilea rând gradul mare de adopție a acestei librării de către majoritatea comunității .NET. Alternative sunt suficiente, dintre cele pe care le-am mai folosit sau de care am citit la un moment dat sau altul menționez: Autofac41, Ninject42, Spring.NET43, Castle Windsor44.
Dostları ilə paylaş: |