LLBLGen 3.0 beta - nou si vechi
Probabil multi din cei ce cititi acest blog va intrebati - de ce m-ar interesa ce a aparut nou intr-un O/RM comercial/proprietar de care am auzit doar in treacat, cand eu folosesc fara probleme Entity Framework, NHibernate, LINQtoSQL sau alt mapper?
Eu cel putin, sunt curios din mai multe motive: sa vad cum altcineva abordeaza o problema comuna (partea de persistenta in acest caz), sa vad o solutie poate diferita si nu in ultimul rand pentru ca o perspectiva mai larga ma ajuta sa aleg cea mai potrivita solutie dintre mai multe alternative, de la caz la caz.
Ca in multe alte domenii, nu exista "cel mai bun" tool - totul depinde de specificul aplicatiei dezvoltate, de metodologia folosita, de experienta echipei, de gusturile individuale..
LLBLGen 3.0 Beta 1 e proaspat aparut (23 ian.) si e disponibil pentru download doar pentru clienti (care au un username/password de access la zona de download), deci pe net se gasesc inca putine informatii. De ce nu exista inca un trial care sa-l poata downloada oricine, e greu de spus (probabil fiindca include si codul sursa)..
Revenind la "What's new", avem de a face cu un domeniu in care e greu sa mai apara ceva cu adevarat "revolutionar" in ce priveste esenta unui O/R mapper - la urma urmei SQL-ul e de cand lumea, obiectele si clasele la fel, odata cu LINQ s-a rezolvat in mare parte problema descrierii la nivel de limbaj a unui query, strongly typed si fara a recurge la structuri de date foarte complexe. Normal, intotdeauna vor mai fi inbunatatiri de performanta in ce priveste SQL-ul generat..
1. Ca urmare, si in ce priveste LLBLGen, modificarile majore se concentreaza pe alte aspecte care pot face viata programatorului mai usoara: daca in cazul unor O/RM-uri, precum NHibernate, multi programatori prefera sa isi creeze clasele manual, una cate una, si sa isi defineasca maparile direct intr-un XML (desi exista generatoare de cod third-party care ajuta mult pe partea asta), in cazul altor O/RM-uri putini programatori s-ar simti "confortabil" fara a avea "la pachet" un generator de cod si un designer ma mult sau mai putin "vizual".
Atat Entity Framework, LINQtoSQL cat si LLBLGen, pe langa runtime vin si cu un generator de cod si un designer.
In schimb, "problema" cea mai desc criticata de unii la aceste generatoare de cod e ca reduc controlul programatorului asupra codului generat, si ca (pana recent), majoritatea promovau un stil de dezvoltare "database-driven", in care mai intai trebuie definita structura bazei de date, dupa care generatorul crea un set de clase pornind de la tabelele, view-urile sau stored procedure-urile din baza de date.
Desi e o metoda foarte productiva, vine cu cateva dezavantaje:
- implicit, clasele vor avea o structura foarte apropiata de structura bazei de date
- programatorul e tentat sa gandeasca mai putin in termeni OOP, si mai mult in termeni "relationali"
- usurinta de a crea cate o clasa pentru absolut fiecare tabela, chiar si acolo unde nu e cu adevarat necesar
- si in primul rand, dificultatea de dezvolta o aplicatie "test-driven" (TDD), cu unit-teste etc. - deseori clasele generate nu vor expune o interfata si vor contine o gramada de cod generat, folosit pentru partea de persistenta..
Desi toate acestea se pot depasi si evita cu vointa si "disciplina", atat Entity Framework in viitoarea versiune 4.0, cat si LLBLGen in ver. 3.0, vor suporta probabil cel mai cerut feature: "code first"/"domain driven" development (pe langa mopdelul existent, "database first"):
- clasele sunt create primele pornind de la cerintele functionale ale aplicatiei (ideal scriind un set de unit-teste mai intai)
- partea de persistenta e privita ca un serviciu ce tine de infrastructura
- diferentele intre clase (domain model) si structura bazei de date devin mai explicite
- atunci cand e posibil, structura bazei de date poate fi generata/updatata pornind de la structura claselor (si pe baza maparilor), nu neaparat invers (metoda care se poate aplica mai mult la aplicatii noi si baze de date cate nu sunt folosite si de alte aplicatii mai vechi).
Conceptual, acest mod de lucru e ilustrat in documentatia LLBLGen astfel:

In cuvinte, principiul e destul de simplu: programatorul, poate incepe prin a defini "abstract entity model-ul" (pentru cine nu e familiar cu terminologia, oarecum e un concept oarecum similar cu "logical/conceptual schema" din Entity Framework). La modul concret, poate fi privit ca un "domain model", pe baza caruia, pe de o parte se pot genera clasele intr-un limbaj de programare (C#, VB.Net etc.), si care, pe de alta parte, poate fi mapat pe o structura a baze de date relationale.
Normal, in principiu exista si posibilitatea de a se genera "abstract entity model-ul" pornind de la un set de clase existente, dar aceasta posibilitate nu va fi disponibila in LLBLGen (cu exceptia unui caz particular, de care voi aminti mai incolo).
Odata definit entity model-ul in designer (vizual sau de la tastatura), se va putea fie defini maparile cu o baza de date existenta, fie se va putea genera automat structura bazei de date pornind de la entiy model.
Pentru cineva obisnuit sa inceapa o aplicatie cu crearea bazei de date, si dat fiind ca multa lume a ajuns sa faca asta destul de rapid intr-un DBMS, daca e sa "schimbe macazul" si sa inceapa cu un entity model, vor simti nevoia unui tool care sa permita definirea de entitati si a relatiilor intre ele intr-un mod cat mai rapid si productiv, fara a fi obligati sa jongleze cu mouse-ul intr-un designer si sa caute comenzi in meniuri contextuale.
Pentru asta in LLBLGen 3 exista asa-numitul "QuickModel" designer - care poate fi inteles doar privind un demo:
[http://weblogs.asp.net/fbouma/archive/2009/11/25/llblgen-pro-v3-0-model-first-with-quickmodel-and-more.aspx] si e probabil una din cele mai interesante folosiri a unui DSL (domain specific language).
2. Ar fi timpul sa amintesc de cea de a doua noutate cu care vine LLBLGen 3.0: odata ce si-au dat seama ca e greu sa mai apara chestii inovative strict legate de engine-ul pe care e bazat un O/RM, si cum aveau deja un designer si generator de cod bazat pe template-uri de buna calitate, si-au dat seama ca il pot folosi pentru a genera cod si a edita maparile si pentru alte O/RM-uri: LINQtoSQL, NHibernate si Entity Framework. Normal, codul generat, cat si codul scris de programator va folosi tot framework-urile respective (scopul ne fiind crearea unui wrapper care sa le abstractizeze - oricum un astfel de wrapper e ceva destul de utopic in practica).
Ce inseamna asta pentru cineva care foloseste Visual Studio pentru a genera clasele si a defini maparile pentru Entify Framework de exemplu? Insemana ca are o alternativa - cel putin in ver. EF 1.0, designer-ul fiind foarte "pagubos" la modele cu peste 100 de clase (ceea ce nu e un numar mare in aplicatii reale).
Pentru cineva care foloseste NHibernate, alternativele sunt mult mai diverse (generatoare de cod precum CodeSmith, MyGeneration, Moregen, NConstruct etc.).
3. LLBLGen 3.0 stocheaza (in sfarsit..) definitiile entitatilor si maparile intr-un fisier XML, in loc de unul binar - pare ceva simplu (NHibernate, LINQtoSQL si Entity Framework fac asta de multa vreme), dar nu e deloc simplu daca se doreste ca acel XML sa poata fi editat de mai multi developeri in acelasi timp, si sa poata fi "merge"-uit de un tool de source control fara dureri prea mari. Un XML e cvasi-inutil intr-o echipa, daca o modificare minora duce la re-aranjarea a 50% din liniile fisierului XML - LLBLGen promite ca modificarile vor fi cat mai localizate.
4. Grouping - in majoritatea proiectelor reale, e destul de greoaie mentinerea tuturor claselor din domain model intr-un singur proeict/assembly - LLBLGen permite gruparea claselor si generarea de proiecte separate pentru acestea. Desigur, asta e posibil doar daca nu exista referinte circulare intre clasele din proiecte diferite (referintele circulare intre assembly-uri nefiind posibile).
Cate screenshot-uri "in premiera":



O sa revin cu mai multe detalii in curand (http://ronua.ro/CS/blogs/tudort/archive/2010/05/02/LLBLGen-Alternative-lucrul-Entity-Fremework-4_5F00_0.aspx).
P.S.: am renuntat deocamdata la sh, tz, î, ă, â - too painfull.. :)