Documente Academic
Documente Profesional
Documente Cultură
(sursa: https://www.sun.com/offers/docs/java_EE6_overview_paper.pdf)
Persistence is the technique through which object models broker the
access and manipulation of information from a relational database.
JPA handles the details of how relational data is mapped to Java objects,
and it standardizes Object/Relational mapping.
JPA was introduced in Java EE 5, and provided a POJO-based persistence
model for Java EE and Java SE applications.
JPA has been enhanced in Java EE 6. The Java Persistence API (JPA)
version 2.0 specification facilitates more effective and reliable (that is,
more strongly typed) methodology for building object-centric criteria-
based dynamic database queries.
◦ Object/Relational mapping enhancements. For example, JPA 2.0 adds the ability to
map collections of basic data types, such as Strings or Integers, as well as collections
of embeddable objects. There are new annotations that support collection mappings.
◦ Java Persistence Query Language (JPQL) enhancements. These include new operators
such as NULLIF, VALUE, and others, and case expressions can be used in queries.
◦ Criteria API. A type safe query mechanism, based on the metamodel concept, which
can verify persistent Java objects. It can be statically or dynamically accessed. A
string-based model is also available, but not as type safe.
(sursa: https://www.sun.com/offers/docs/java_EE6_overview_paper.pdf)
Dependency Injection poate fi aplicat tuturor resurselor de care are
nevoie o componentă
Aplicaţia nu mai include cod pentru căutarea şi crearea resurselor
Serverul de aplicaţii injecteză automat resursele folosind adnotările din
cod
Bean-urile pot fi ataşate unor scopuri (request, sesiune etc); serverul de
aplicaţii va face managementul automat atât al life-cycle-lui bean-urilor
cât şi al resurselor necesare acestora (creare, injectare, distrugere)
Bean-urile au abilitatea de a genera şi observa evenimente, rezultând o
interacţiune loosely-coupled
Arhitectura permite suportul tranzacţional pentru secţiunea web a unei
aplicaţii enterprise
Desi popular, patternul Dependecy Injection nu a avut parte de o
abordare standard până recent. Dependency Injection for Java (JSR 330)
introduce un set standard de adnotări care pot fi folosite pentru
Dependecy Injection.
Paşii necesari pentru dezvoltarea şi lansarea în
producţie a aplicaţiilor JEE sunt:
◦ dezvoltarea componentelor (EJB-uri, pagini JSP, servlet-
uri, pagini HTML etc.)
◦ asamblarea componentelor în module
◦ asamblarea modulelor în aplicaţii
◦ deployment-ul aplicaţiilor (instalarea acestora în cadrul
serverelor de aplicaţii compatibile cu specificaţiile JEE)
Modulele JEE sunt părţi componente ale
aplicaţiilor enterprise special proiectate pentru a
rula în cadrul containerelor puse la dispoziţie de
serverele de aplicaţii JEE.
modul web – conţine servlet-uri, pagini JSP, librării de tag-uri JSP, fişiere
jar, documente html, documente multimedia asamblate în pagini html,
applet-uri, clase Java şi alte resurse.
◦ componentele se asamblează respectând o structură descrisă de specificaţiile JEE la
care se adaugă un fişier XML de configurare (web deployment descriptor file) având
numele web.xml.
◦ modulul poate fi opţional comprimat într-un fişier cu extensia standard .war (web
archive).
◦ modulul va rula în cadrul containerul web pus la dispoziţie de serverele de aplicaţii
JEE.
În toate cazurile descrise mai sus, rolul fişierului XML este acela de a specifica, în funcţie
de nivelul la care se află, comportamentul componentelor în cadrul modulelor, respectiv
al modulelor în cadrul aplicaţiei enterprise.
Ultima fază cuprinsă de specificaţiile JEE este faza de
deployment, adică de instalare a aplicaţiei enterprise
în cadrul serverelor de aplicaţii JEE, fiecare server de
aplicaţii punând la dispoziţie instrumente specifice de
deployment.
(sursa: https://www.sun.com/offers/docs/java_EE6_overview_paper.pdf)
Curs 2
concepte principale care se regăsesc la
fundaţia unui cluster enterprise
modalităţi de definire şi construire a
clusterelor
modalităţi de comunicare a nodurilor în
cadrul unui cluster
cluster: set de noduri care au în general un
scop comun
nod: calculator sau o instanţă de server, în
cazul din urmă mai multe instanţe de server
putând rula în cadrul aceluiaşi calculator
obţinerea toleranţei la defecte (fault
tolerance)
echilibrarea încărcării serverelor prin replicare
(load balancing through replication)
proporţia de timp în care acest serviciu este
accesibil cu un timp de răspuns rezonabil /
predictibil.
Termenul de ”Mare disponibilitate” (high
availability - HA) este în general folosit pentru a
indica o proporţie mare de timp.
HA este dependent de context: HA-ul pentru un
sistem critic dintr-o navetă spaţială este probabil
mult mai mare decât HA-ul pentru un site web.
HA specifică maximul de timp dintr-o anumită
perioadă, pentru care un serviciu poate să nu fie
disponibil.
Proporţia HA Timpul maxim cumulat admis de indisponibilitate în decursul unui an
98 % 7.3 zile
99 % 87.6 ore
99.99 % 53 minute
99.9999 % 31 secunde
(sursa: Load Balancing and Failover in the JBoss Application Server, JBoss Group)
La apariţia unei invocări, ultimul interceptor
va interoga politica de load-balancing în
vederea selectării unui nod ţintă după care va
trimite invocarea pentru execuţie către
acesta.
Dacă invocarea a fost făcută cu succes (nu au
apărut excepţii sistem), rezultatul invocării va
fi trimis clientului, altfel interceptorul va
verifica dacă poate să facă fail-over (excepţia
apărută poate fi recuperată – este
transparentă).
Ex: ...
Un exemplu de excepţie transparentă apare când
legătura cu nodul ţintă este întreruptă înainte de
trimiterea invocării. În acest caz, interceptorul va
notifica politica de load-balancing de această
situaţie, urmând să primească o nouă ţintă.
Problema partiţiilor
potenţială problemă de coerenţă a datelor
care poate apărea în cadrul execuţiei use-
case-urilor care implică mai multe
componente stateful.
stateful
pentru exemplificare se consideră două SFSB-
uri (Stateful Session Bean), S1 şi S2, replicate
în cadrul unui cluster pe două servere A şi B.
Clientul invocă o
metodă a bean-ului
bean ului S1
pe nodul A.
Bean-ul S1 invocă o
metodă a bean-ului
bean ului S2
în cadrul aceluiaşi nod.
Invocarea bean-ului S2
se termină cu succes
iar starea acestuia este
replicată pe nodul B.
Bean-ul S1 încearcă să
facă o altă invocare
asupra bean-ului S2,
dar nodul A se
defectează.
Considerând acest
scenariu,
scenariu nodul B va
ajunge să conţină o
stare inconsistentă.
Potenţiale soluţii:
◦ ...
O posibilă soluţie în abordarea acestei
probleme este instalarea la nivelul clusterului
a unui manager de tranzacţii care să readucă
bean ul S2 la starea iniţială
bean-ul iniţială.
...
O altă soluţie ar fi ca replicarea în cluster să
se facă simultan pentru toate componentele
modificate, numai în momentul în care
întreaga tranzacţie a fost executată cu
succes.
O altă problemă de coerenţă a datelor care
poate apărea la nivelul clusterului este
determinată de un potenţial defect la nivelul
reţelei de comunicaţii
comunicaţii, defect ce poate împărţi
clusterul în două sau mai multe partiţii care
nu p
pot comunica.
Clientul caută noduri
disponibile în cluster.
cluster
În momentul găsirii
unui nod disponibil,
disponibil
clientul înaintează
cererea către acesta.
Fiecare SFSB este
asociat în mod unic
unui singur client. Prin
urmare nu vor putea
exista alţi clienţi care
să acceseze aceeaşi
instanţă în altă partiţie.
Lista serverelor
disponibile la client
este actualizată după
fiecare invocare
invocare.
În momentul în care
defectul reţelei este
remediat, clienţii se vor
afla în situaţia de a
avea liste neactualizate
ale topologiei
clusterului.
La următoarea cerere a
clientului,
clientului starea bean-
bean
ului implicat va fi
replicată în cadrul
clusterului, iar lista de
servere de la nivelul
clientului va fi
reactualizată.
Bean-ul S3 nu este
replicat în cluster,
cluster
deoarece clientul nu a
invocat încă nici o
metodă asupra sa.
Serverul C se
defectează.
defectează
Clientul accesează din
nou bean-ul
bean ul S2 şi
găseşte (fails over)
noul server disponibil
A.
Bean-ul S2 invocă
bean-ul
bean ul S3 care este
neactualizat.
Potenţiale soluţii:
◦ ...
O posibilă soluţie în abordarea acestei
probleme este instalarea unui mecanism de
marcare a conţinutului componentelor
stateful la nivelul nodurilor clusterului,
clusterului
combinat cu un mecanism de detecţie şi
reactualizare pprin replicare
p a tuturor
componentelor out-of-date, mecanism ce va
intra acţiune în momentul cuplării partiţiilor.
Curs 5
O posibilă abordare a echilibrării încărcării în
cadrul unui cluster este aceea a folosirii
agenţilor mobili şi a algoritmilor genetici.
Task-urile distribuite pot fi duse la
îndeplinire de mai mulţi agenţi pe mai multe
noduri din reţea (calculatoare gazdă).
Maparea dintre agenţi şi nodurile din reţea
este de tipul many-to-one.
Este posibil ca toţi agenţii sau o parte dintre
aceştia să ruleze pe acelaşi calculator gazdă.
Problema care se ridică este cum se poate
realiza echilibrarea încărcării când toate
calculatoarele gazdă sau o parte dintre
acestea devin supraîncărcate şi cum se pot
remapa agenţii mobili din subgraful curent al
calculatoarelor gazdă pe un alt subgraf
subîncărcat din cadrul aceluiaşi cluster,
respectându-se anumite restricţii.
În prezent, reţelele de calculatoare sunt în
plină ascensiune, devenind din ce în ce mai
complexe, oferind o gamă largă de noi
servicii şi formând reţelele eterogene ce pot
lucra împreună ca un întreg. Prin urmare,
managementul reţelelor de calculatoare a
devenit o sarcină a cărei complexitate este în
continuă creştere.
Abordările descentralizate ale
managementului reţelelor de calculatoare
sunt în prezent discutate şi devine din ce în
ce mai evident faptul că soluţiile centralizate
nu pot furniza soluţii în ceea ce priveşte
scalabilitatea. În particular tehnologia
agenţilor mobili este examinată ca o nouă
soluţie în rezolvarea acestei probleme.
O caracteristică esenţială în managementul
reţelelor de calculatoare o reprezintă
echilibrarea încărcării deoarece asigură
utilizarea eficientă a resurselor reţelei cât şi
evitarea situaţiilor de supraîncărcare.
În secţiunile următoare, se iau în considerare
folosirea agenţilor mobili şi a algoritmilor
genetici pentru dezvoltarea unui mecanism
descentralizat de echilibrare a încărcării.
Obiectivul echilibrării încărcării este acela de
a distribui în mod egal încărcarea
computaţională şi a comunicaţiilor în cadrul
reţelei de calculatoare.
Dacă nu s-ar ţine cont de echilibrarea
încărcării, supraîncărcarea nodurilor şi
congestiile din reţea vor apărea în paralel cu
situaţia în care o parte dintre nodurile reţelei
nu vor fi folosite la capacitate maximă.
O aplicaţie distribuită este alcătuită dintr-o
colecţie de entităţi cooperante (task-uri).
Task-urile se pot executa secvenţial sau în
paralel pe două sau mai multe procesoare.
Maparea task-urilor are rolul de a distribui
încărcarea sistemului între procesoarele
existente astfel încât performanţele de
procesare per ansamblu, în funcţie anumite
criterii, să fie maximizate.
O strategie de alocare eficientă previne
situaţia în care unele procesoare sunt
subîncărcate în timp ce altele sunt
supraîncărcate.
Algoritmii genetici reprezintă tehnici generale
de căutare a soluţiilor optime într-un spaţiu
vast de soluţii posibile putând fi aplicaţi în
cadrul unei game variate de probleme de
optimizare.
În cele ce urmează, vom analiza următoarea
problemă de mapare: distribuirea optimă şi
dinamică a task-urilor comunicante în cadrul
procesoarelor unei reţele de calculatoare
distribuite folosind agenţi mobili şi algoritmi
genetici.
Această problemă este cunoscută ca fiind o
problemă NP-completă. Metodele euristice
pot găsi doar aproximări ale soluţiei optime,
dar o vor face într-un timp rezonabil.
P, NP, NP-complet
P = NP?
G1 izomorf cu G2?
◦ Se pare că nu este nici P, nici NP-completă, ci NP
G1 izomorf cu un subgraf din G2?
◦ NP-completă
(sursa: http://en.wikipedia.org/wiki/Graph_isomorphism)
Două tehnici de optimizare larg răspândite sunt:
◦ algoritmul hill-climbing
◦ algoritmul simulated annealing
Algoritmul hill-climbing găseşte minimul global
doar în cadrul spaţiilor convexe, altfel soluţia
găsită fiind un minim local.
Algoritmul simulated annealing furnizează o cale
de a depăşi acest inconvenient al algoritmului
hill-climbing, preţul plătit fiind acela al unui cost
computaţional ridicat. Mai rău, algoritmul
simmulated annealing este mai degrabă de
natură secvenţială, paralelizarea sa fiind un lucru
destul de dificil de obţinut.
Alte tehnici distribuite de optimizare, inerent
paralele:
◦ reţelele neuronale
◦ algoritmi genetici (discutaţi în continuare)
Sunt inspiraţi din adaptarea sistemelor
naturale evolutive, fiind recent aplicaţi în
probleme de optimizare într-o gamă largă de
domenii, cum ar fi:
◦ problema poştaşului (traveling salesman problem)
◦ problema optimizării conexiunilor reţelelor
neuronale
◦ sisteme de clasificare
◦ etc.
O aplicaţie distribuită compusă din task-uri
distribuite poate fi modelată printr-un graf
Gt=(Vt, Et), unde nodurile (vertices) reprezintă
task-uri, iar valorile asociate acestor noduri
reprezintă costuri computaţionale cunoscute
sau estimate ale task-urilor.
Muchiile (edges) reprezintă comunicaţiile
dintre task-uri, iar valorile asociate acestora
reprezintă costurile de comunicaţie
cunoscute sau estimate.
Iniţial s-a luat în considerare un graf static de
task-uri, comportamentul de realocare
dinamică fiind dat de un layer de agenţi
mobili care monitorizează şi remapează task-
urile aplicaţiei dacă este cazul.
Arhitectura reţelei este modelată printr-un
graf conex Gp=(Vp, Ep), unde nodurile
reprezintă procesoarele, iar valorile asociate
acestor noduri reprezintă puterea de
procesare cunoscută sau estimată a acestor
procesoare.
Muchiile reprezintă liniile de comunicaţie
dintre procesoare, iar valorile asociate
acestora reprezintă viteza de transfer a
datelor cunoscută sau estimată a acestor linii
de comunicaţie.
Calea de comunicaţie aleasă între două
procesoare este calea cea mai rapidă, dintre
toate căile posibile de comunicaţie fiind
aleasă calea care oferă cea mai mare viteză de
transfer a datelor.
Arhitectura reţelei este considerată ca fiind o
arhitectură statică, configuraţia fizică a reţelei
rămânând neschimbată.
Următoarea terminologie este folosită:
◦ M numărul de task-uri ce trebuiesc mapate, M=|Vt|
◦ N numărul de procesoare din cadrul reţelei, N=|Vp|
◦ ei costul computaţional al task-ului ti
◦ ppk puterea de procesare a procesorului pk
◦ cij costurile de comunicaţie între task-urile ti şi tj
◦ lskl cea mai bună linie de comunicaţie între
procesoarele pk şi pl
Maparea este definită sub forma unor funcţii
de tipul M p : Vt → V p care mapează fiecare task
la un anumit procesor.
Pentru a putea compara posibilele soluţii de
mapare a task-urilor la procesoare, o funcţie
de fitness F : M p → ℜ este definită pentru a
asocia o valoare reală fiecărei funcţii de
mapare generate.
Două criterii de mapare contradictorii au fost
considerate:
◦ Minimizarea costului total de comunicaţii între
procesoare. Acest cost este calculat ca o medie a
tuturor costurilor de comunicaţie dintre toate
perechile de task-uri, luând în considerare
procesoarele şi liniile de comunicaţie dintre
procesoarele pe care aceste task-uri au fost
mapate.
2 cij
MIN (CC ) = MIN ( ∑
M ( M − 1) i , j∈Vt ls M p (i ) M p ( j )
)
◦ Minimizarea dezechilibrului încărcării computaţionale a
sistemului. Măsura cantitativă folosită pentru evaluarea
acestui criteriu este abaterea standard (standard
deviation) a încărcării computaţionale pe diferite
procesoare.
M N
L = ∑ ei ∑ pp k
i =1 k =1
M
Lk = ∑e
i =1
i ppk
M p ( i )=k
Funcţia de fitness F aleasă pentru a evalua o
funcţie de mapare m ∈ M p este dată de suma
ponderată a celor două funcţii, CC şi SD,
definite mai sus:
F (m) = SD(m) + wCC (m)
− ( x−µ )2
1
f ( x) = e 2σ 2
2πσ 2
(sursa: http://en.wikipedia.org/wiki/Roulette-wheel_selection)
Cei mai buni indivizi rezultaţi din faza de
selecţie sunt împerecheaţi.
Genele fiecărei perechi de părinţi sunt
combinate pentru a da naştere altor indivizi,
pentru fiecare pereche de părinţi rezultând
doi copii.
Operatorul crossover este responsabil cu
combinarea genelor părinţilor.
Acest operator generează aleator un set de
puncte de crossover, atât ca număr, cât şi ca
poziţie, urmând să efectueze combinarea
propriu-zisă.
procedure run
for i=0 to generations/exchange phase
generate pairs of individuals from population (rank selection)
newPopulation = empty
for each pair
offspring = crossover pair (with crossoverStrength)
mutate offspring (with mutationStrength)
evaluate offspring
newPopulation += offspring
end for
elitismPopulation = retrieve elitism from population (with elitismPercent)
if mergeGenerations
population = elitismPopulation + merge(newPopulation, population - elitismPopulation)
else
population = elitismPopulation + newPopulation
end if
end for
end procedure
all torus processors perform in parallel
initialization phase
population = generate initial population
evaluate population
procedure run
GLOBAL sync phase
end initialization phase
De folosit când:
◦ componentele au nevoie de acces la informaţii de
sistem
◦ este nevoie de decuplarea aplicaţiei de protocoalele
utilizate cât şi de interfeţele de sistem
Oferă un punct central de control al cererilor
din layerul de prezentare.
(sursa: Sun Certified Enterprise Architect for Java EE Study Guide, Second Edition, 2010)
Avantaje:
◦ centralizează logica de control
◦ îmbunătăţeşte reutilizarea codului
◦ îmbunătăţeşte separarea tipurilor de servicii
De folosit când:
◦ aplicarea unei logici comune de control
◦ este nevoie de un management centralizat al view-
urilor
Separă view-ul de logica de procesare
(sursa: Sun Certified Enterprise Architect for Java EE Study Guide, Second Edition, 2010)
Avantaje:
◦ separă view-ul de logica de procesare
De folosit când:
◦ se doreşte dezvoltarea unui set comun de
componente de tip view
◦ view-urile se modifică în funcţie de drepturile de
acces
Execută cererea şi generează un răspuns
utilizând o procesare tip business limitată.
(sursa: Sun Certified Enterprise Architect for Java EE Study Guide, Second Edition, 2010)
Avantaje:
◦ separă view-ul de logica de procesare
◦ îmbunătăţeşte reutilizabilitatea
De folosit când:
◦ aplicaţia conţine view-uri statice
◦ procesarea tip business este limitată
Analizează cererea şi execută serviciile de tip
business logic înainte de a transmite
controlul către view.
(sursa: Sun Certified Enterprise Architect for Java EE Study Guide, Second Edition, 2010)
Avantaje:
◦ îmbunătăţeşte separarea tipurilor de servicii
De folosit când:
◦ sunt accesate diverse servicii business care
presupun modalităţi diferite de localizare
Oferă o faţadă cu granularitate mărită a
componentelor business pentru clienţii
remote.
(sursa: Sun Certified Enterprise Architect for Java EE Study Guide, Second Edition, 2010)
Avantaje:
◦ reduce numărul de invocări remote pe componentele
business din partea clienţilor
◦ decuplează layerele de prezentare şi business
◦ îmbunătăţeşte performanţele datorită reducerii
numărului de invocări de granularitate scăzută din
partea clienţilor
◦ furnizează un API mult mai curat aplicaţiei client
De folosit când:
◦ mai multe invocări din partea clientului pot fi grupate
într-o singură invocare de granularitate mărită
Design pattern care centralizează şi
înglobează componente business.
Poate fi văzut ca un helper pentru Session
facade care se ocupă cu executarea logicii de
business şi a workflow-ului.
(sursa: Sun Certified Enterprise Architect for Java EE Study Guide, Second Edition, 2010)
Avantaje:
◦ centralizează şi îmbunătăţeşte reutilizarea business
logic
◦ simplifică Session facade prin eliminarea business
logic de la nivelul acesteia
De folosit când:
◦ încep să apară secvenţe de cod duplicate la nivelul
Session facade
Separă datele şi mecanismele de persistenţă a
datelor de business logic.
(sursa: Sun Certified Enterprise Architect for Java EE Study Guide, Second Edition, 2010)
Avantaje:
◦ separă mecanismele de persistenţă a datelor de
business logic
De folosit când:
◦ se doreşte a creşte gradul de reutilizabilitate a
business logic
Înglobează mai multe entităţi business într-o
singură entitate de granularitate mărită.
(sursa: Sun Certified Enterprise Architect for Java EE Study Guide, Second Edition, 2010)
Avantaje:
◦ îmbunătăţeşte mentenanţa
◦ îmbunătăţeşte performanţele de transfer a datelor
în reţea
De folosit când:
◦ este nevoie de a trimite obiecte ce reprezintă
(parţial sau total) entităţi persistente între layere
Construieşte obiecte de transfer de date
compuse şi le returnează clientului.
(sursa: Sun Certified Enterprise Architect for Java EE Study Guide, Second Edition, 2010)
Avantaje:
◦ îmbunătăţeşte performanţele de transfer a datelor
în reţea
De folosit când:
◦ există mai multe obiecte de transfer de date care
sunt trimise între layere
Menţine rezultatele în cache şi pune la
dispoziţia clientului modalităţi de traversare
şi accesare a acestora.
(sursa: Sun Certified Enterprise Architect for Java EE Study Guide, Second Edition, 2010)
Avantaje:
◦ rezultatele sunt menţinute în cache
◦ îmbunătăţeşte performanţele reţelei
◦ îmbunătăţeşte separarea tipurilor de servicii
De folosit când:
◦ este nevoie de invocarea unui serviciu business în
mod asincron
Separă persistenţa unui obiect de modelul
obiect.
Utilizat în special în cadrul framework-urilor
ORM (Object Relational Model).
Folosit în paralel cu Data access object.
(sursa: Sun Certified Enterprise Architect for Java EE Study Guide, Second Edition, 2010)
Avantaje:
◦ decuplează logica de business de logica de
persistenţă
De folosit când:
◦ nu se doreşte folosirea bean-urilor de tip entitate
◦ utilizarea modelului obiect este complexă
Expune şi intermediază serviciile business
utilizând XML şi protocoale web.
(sursa: Sun Certified Enterprise Architect for Java EE Study Guide, Second Edition, 2010)
Avantaje:
◦ expune serviciile business pentru a fi accesate ca
servicii web
De folosit când:
◦ este nevoie de a accesa serviciile business ca
servicii web
Curs 9
Problemă:
◦ un client enterprise trebuie să execute logică tip
business pentru a completa un use-case
◦ use-case-ul trebuie să se execute într-o singură
tranzacţie şi într-o singură invocare în reţea
Context:
◦ execuţia unui use-case presupune accesarea mai
multor obiecte (servicii/entităţi persistente) la
nivelul serverului
◦ accesarea directă de tipul fine-grained calls:
adaugă un overhead datorită multiplelor invocări în
reţea
codul care implementează business logic la nivelul
clientului este mult mai greu de reutilizat şi de
întreţinut
(sursa: EJB Design Patterns. Advanced Patterns, Processes, and Idioms)
(sursa: EJB Design Patterns. Advanced Patterns, Processes, and Idioms)
(sursa: EJB Design Patterns. Advanced Patterns, Processes, and Idioms)
(sursa: EJB Design Patterns. Advanced Patterns, Processes, and Idioms)
Anti-pattern: crearea unei singure faţade care
implementează o gamă variată de use-case-
uri
Soluţie: use-case-urile vor fi grupate şi
implementate în faţade diferite în funcţie de
specificul acestora
Anti-pattern: logică de domeniu în faţadă
Soluţie:
◦ un model de domeniu bine proiectat trebuie să
conţină toată logica necesară implementării
diferitelor use-case-uri
◦ faţadele pot conţine logică de domeniu doar dacă
aceasta implică lucrul cu entităţi de domeniu
diferite care nu au o legătură directă
Anti-pattern: prezenţa unor secvenţe de
business logic duplicate
Soluţie:
◦ refactorizarea layerului de faţade
◦ extragerea secvenţelor de business logic duplicate
(independente de use-case) într-un layer separat de
servicii
Avantaje:
◦ overhead mic în reţea
◦ separarea clară a layerului de prezentare de
business logic
◦ integritate tranzacţională
◦ reutilizabilitate
◦ mentenanţă crescută
◦ separare tip verb-substantiv
use-case-uri – verbe
entităţi persistente - substantive
Problemă:
◦ un client enterprise trebuie să execute logică tip
business pentru a completa un use-case fără a
necesita un răspuns imediat
◦ use-case-ul trebuie să se execute într-o singură
tranzacţie şi într-o singură invocare în reţea fără a
necesita un răspuns imediat
(sursa: EJB Design Patterns. Advanced Patterns, Processes, and Idioms)
(sursa: EJB Design Patterns. Advanced Patterns, Processes, and Idioms)
Avantaje faţă de Session facade:
◦ se execută asincron
◦ execuţia este garantată (fault-tolerant)
◦ timp de răspuns imediat
◦ se elimină punctele singulare de defecte
Dezavantaje:
◦ parametri de intrare weakly typed
◦ nu există valori de return
◦ nu există mecanism de propagare a excepţiilor
datorită naturii asincrone
Problemă:
◦ un client enterprise trebuie să execute logică tip
business pentru a completa un use-case
◦ use-case-ul trebuie să se execute într-o manieră
lightweight, prin decuplarea clientului de server,
într-o singură tranzacţie şi într-o singură invocare
în reţea
(sursa: EJB Design Patterns. Advanced Patterns, Processes, and Idioms)
(sursa: EJB Design Patterns. Advanced Patterns, Processes, and Idioms)
(sursa: EJB Design Patterns. Advanced Patterns, Processes, and Idioms)
Părţi componente:
◦ command beans – clase POJO cu metode de tip set
şi get + o metodă execute() ce conţine business
logicul necesar pentru execuţia unui use-case
◦ logică de rutare la nivelul clientului – presupune
trimiterea comenzilor către server şi recepţionarea
răspunsului
◦ serviciu de tip stateless session bean ce acceptă şi
execută comenzi la nivelul serverului
Avantaje:
◦ dezvoltarea rapidă de prototipuri de aplicaţii
◦ separarea logicii de prezentare de logica de
business
◦ presupune o singură invocare în reţea
◦ decuplează clientul de server
◦ se pot executa local şi pot produce date fictive în
cazul în care implementarea la nivelul serverului nu
este încă funcţională
Dezavantaje:
◦ sunt stateless
◦ mecanism de tratare a erorilor limitat la o singură
excepţie generală datorită naturii generice a
serviciului ce preia comenzile la nivelul serverului
excepţiile originale pot fi încapsulate în cadrul
excepţiei generice
◦ explozie de obiecte de comandă în proiecte mari
◦ duplicarea codului
◦ serviciul generic de preluare a comenzilor cuplat cu
serviciile de tratare a comenzilor
Curs 10
Problemă:
◦ un client trebuie să transfere mai multe date către
şi de la server
◦ use-case-ul trebuie să se execute evitând mai
multe invocări în reţea
(sursa: EJB Design Patterns. Advanced Patterns, Processes, and Idioms)
(sursa: EJB Design Patterns. Advanced Patterns, Processes, and Idioms)
Avantaje:
◦ o singură invocare în reţea pentru a transmite date
multiple
◦ obiectele de transfer de date pot fi folosite atât
pentru citire cât şi pentru scriere
◦ datele sunt încapsulate la nivelul obiectelor de
transfer de date
◦ obiectele de transfer de date pot fi concepute la
orice granularitate
◦ obiectele de transfer de date pot conţine şi alte
date decât cele din domeniului de date
Problemă:
◦ layerul de DTO-uri necesită schimbări dese
◦ trebuie găsită o modalitate de a crea şi manipula
DTO-uri pentru a minimiza impactul schimbărilor
dese asupra sistemului
Context:
◦ fiecare use-case necesită propriile DTO-uri la
granularităţi diferite
◦ layerul de DTO-uri poate exploda în sute sau mii de
obiecte în funcţie de complexitatea aplicaţiei
◦ logica de creare şi manipulare a DTO-urilor trebuie
decuplată de domeniul de date
(sursa: EJB Design Patterns. Advanced Patterns, Processes, and Idioms)
(sursa: EJB Design Patterns. Advanced Patterns, Processes, and Idioms)
(sursa: EJB Design Patterns. Advanced Patterns, Processes, and Idioms)
(sursa: EJB Design Patterns. Advanced Patterns, Processes, and Idioms)
Avantaje:
◦ separă logica de creare şi consumare a DTO-urilor de
business logic
◦ separă domeniul de date de datele necesare fiecărui use-
case în parte
◦ îmbunătăţeşte mentenanţa
◦ nu poluează domeniul de date
◦ îmbunătăţeşte performanţele prin încapsularea datelor într-
un singur call în reţea
◦ factory-ul poate fi conceput să contruiască orice tip de
DTO-uri şi la orice granularitate
◦ suportă construirea unor grafuri complexe de DTO-uri în
funcţie de necesităţi
◦ se recomandă gruparea logicii aferente construirii şi
manipulării DTO-urilor în mai multe factory-uri diferite în
funcţie de use-case-uri
Problemă:
◦ un client iniţiază un update în server pe baza unor
date recepţionate într-o tranzacţie anterioară
◦ la momentul update-ului, datele care au stat la
baza modificărilor pot să nu mai fie de actualitate
◦ cum se poate determina şi rezolva această situaţie?
Exemplu:
1. Userul A citeşte Entitatea X într-o tranzacţie
2. Userul B citeşte Entitatea X într-o tranzacţie
3. Userul A modifică local Entitatea X
4. Userul B modifică local Entitatea X
5. Userul A actualizează Entitatea X într-o tranzacţie
6. Userul B actualizează Entitatea X într-o tranzacţie
Soluţie:
◦ folosire versioning pentru a detecta situaţiile în care
datele de la client nu mai sunt de actualitate
◦ versioning – implementat în general folosind o
variabilă de tip integer cu scopul de a identifica
starea unei entităţi la un moment dat
◦ variabila de versioning va fi incrementată de fiecare
dată când se modifică entitatea aferentă
Paşi:
◦ transmiterea variabilei de versioning către client
împreună cu datele utile în cadrul DTO-urilor
◦ la actualizare, variabila de versioning este trimisă
înapoi către server împreună cu datele modificate
◦ dacă variabila de versioning de la server
corespunde cu cea primită de la client în cererea de
actualizare atunci se aplică modificările şi se
incrementează variabila de versioning
◦ în caz contrar, cererea de actualizare este bazată pe
date care nu mai sunt actuale, aceasta fiind
refuzată
Curs 11
Într-o aplicaţie distribuită muti-tier,
transferurile de date au loc între toate
layerele, reprezentând un punct critic care
poate afecta în mod dramatic performantele
de ansamblu ale întregii aplicaţii.
Arhitectura multi-tier a dus la apariţia unei
serii de design patterns cu privire la
transferurile de date, de la cache-uri simple
la structuri de date dedicate.
Logica de business este împărţită între
diverse componente, care în funcţie de rolul
pe care îl au pot rula pe calculatoare diferite
şi în layere diferite.
O aplicaţie distribuită tipică este formată din
următoarele secţiuni:
◦ secţiunea Client – conţine componente care rulează
pe calculatoarele client
◦ secţiunea Web – conţine componente care rulează
în cadrul serverelor front-end
◦ secţiunea Business – conţine componente care
rulează în cadrul serverelor de aplicaţii enterprise
◦ secţiunea Enterprise Information System (EIS) –
conţine componente care rulează în cadrul
serverelor EIS
O aplicaţie enterprise distribuită poate fi alcătuită
din trei sau patru secţiuni.
În general, secţiunile Web şi Business sunt
instalate pe aceleaşi servere.
Prin urmare o aplicaţie multi-tier tipică este în
general considerată a fi alcătuită din trei secţiuni
(three-tier), deoarece este distribuită peste trei
locaţii diferite:
◦ calculatoarele client
◦ calculatoarele server
◦ calculatoarele de baze de date şi/sau calculatoarele
legacy în partea de back-end.
Aplicaţiile three-tier extind vechea arhitectură
two-tier client-server prin inserarea unui
server de aplicaţii multi-thread între
aplicaţiile client şi datele stocate de back-
end.
În orice aplicaţie distribuită există în general
două motive pentru care clientul
interacţionează cu serverul:
◦ pentru a prelua date de la server şi a le afişa
◦ pentru a modifica datele din partea de server prin
inserări, actualizări sau ştergeri
În cazul în care cantităţi masive de date trebuiesc
transferate, acestea pot fi furnizate sub forma
unor parametri către metodele ce urmează a fi
executate (în cazul în care clientul trimite date
către server), sau prin execuţii de metode de
granularitate mică (în cazul în care clientul preia
date de la server).
Prima opţiune poate scăpa rapid de sub control
în momentul în care se lucrează cu un număr
foarte mare de parametri, iar a doua opţiune
poate avea un impact negativ semnificativ asupra
performanţelor.
În acest context, o serie de design patternuri
care tratează problema transferului de date
între layerele unei aplicaţii distribuite au fost
dezvoltate.
Aceste design patternuri sugerează ideea de
a crea clase Java care vor oferi suportul
necesar pentru a construi aşa numitele
obiecte de transfer de date care vor încapsula
toate datele necesare în cadrul unei singure
comunicări în reţea.
Un obiect de transfer de date (DTO)
reprezintă o instanţă a unei clase Java
serializabile care încapsulează un snapshot al
unui set de date din partea de server la un
moment dat.
Obiectele de transfer de date pot fi folosite
atât pentru operaţiuni de citire cât şi de
actualizare a datelor într-un sistem distribuit.
Antipattern:
◦ Informaţiile de actualizare ar putea fi trimise serverului
prin intermediul parametrilor metodelor, dar această
abordare este descurajată deoarece de fiecare dată când
informaţiile necesită modificări (datorită evoluţiei
proiectului), numărul şi tipul parametrilor se vor schimba
în conformitate, declanşând schimbări în semnăturile
metodelor.
◦ Acest efect de cascadă nu se opreşte aici, porţiuni
semnificative din cod trebuind a fi modificate şi
recompilate atât pe partea de client cât şi pe partea de
server. Acest lucru la rândul lui declanşează
incompatibilităţi cu versiunile mai vechi ale aplicaţiei.
Prin încapsularea informaţiilor într-un DTO,
toate schimbările necesare sunt izolate la
nivelul DTO-ului şi a clasei Java
corespunzătoare.
Obiectele de transfer de date sunt cel mai des
întrebuinţate pentru operaţiuni de citire.
Când un client necesită citirea unui set de
date de pe server (de obicei cu scopul de a
popula interfaţa grafică), utilizând abordarea
încapsulării datelor în interiorul DTO-urilor,
clientul poate recepţiona toate informaţiile de
care are nevoie folosind doar o singură
comunicaţie în reţea.
Obiectele de transfer de date sunt practic
containere de date dependente de tip,
folosite pentru a transporta orice fel
informaţii între layerele unei aplicaţii
distribuite enterprise.
Noţiunea de a transfera copii ale datelor din
partea de server între secţiunile unei aplicaţii
distribuite poate fi foarte confuză pentru
programatorii ne-experimentaţi în domeniul
aplicaţiilor distribuite, deoarece nu există o
paradigmă similară în lumea aplicaţiilor non-
distribuite.
O problemă comună de care se lovesc
dezvoltatorii aplicaţiilor distribuite când
folosesc obiecte de transfer de date este
alegerea unei granularităţi optime, altfel
spus, care este cantitatea de date pe care un
DTO ar trebui să o încapsuleze, şi în ce punct
decizia de a folosi DTO-uri trebuie luată.
Ca şi modalitate primară de schimb de date
între client şi server, obiectele de transfer de
date constituie o parte a interfeţei care separă
dezvoltatorii din partea de client de
dezvoltatorii din partea de server.
La începutul proiectului, dezvoltatorii din
partea de client şi din partea de server trebuie
să cadă de comun acord asupra design-ului
obiectelor de transfer de date cam la acelaşi
moment în care trebuie să decidă şi ce
interfeţe ale serviciilor urmează să folosească.
Design-ul obiectelor de transfer de date la
începutul proiectului poate fi dificil deoarece
dezvoltatorii deseori nu înţeleg pe deplin ce
unităţi de date trebuiesc transferate între
client şi server.
O cale uşoară de a începe design-ul
obiectelor de transfer de date este de a copia
design-ul entităţilor de domeniu din partea
de server.
Design-ul obiectelor domeniu de transfer de
date este uşor, deoarece echipele din proiect
au în general o idee bună despre cum arată
modelul de domeniu care urmează a fi
utilizat, aceste cerinţe fiind stabilite încă din
fazele iniţiale de dezvoltare ale unui proiect.
Deşi această metodă de design al obiectelor
de transfer de date funcţionează bine la
începuturile unui proiect, pe măsură ce acesta
evoluează, clienţii enterprise ajung deseori să
necesite un acces la date cu o granularitate
mult mai fină decât cea prevăzută iniţial.
În cele din urmă, datele schimbate între client
şi server trebuie să se potrivească cu nevoile
clientului.
Prin urmare, pe măsură ce proiectul
evoluează şi nevoile clienţilor se finalizează,
obiectele domeniu de transfer de date deseori
devin neadecvate ca şi unităţi de schimb,
fiind de o granularitate mult prea mare
pentru a fi potrivite cerinţelor de granularitate
fină ale clientului.
Un client poate avea nevoie de date care pur
şi simplu nu sunt încapsulate de nici un
obiect domeniu de transfer de date.
În acest punct, dezvoltatorii pot trece la
design-ul unor obiecte custom de transfer de
date care nu sunt altceva decât obiecte de
transfer de date care încapsulează seturi
arbitrare de date şi a căror structură depinde
integral de nevoile particulare ale clientului.
Diferenţele dintre aceste două paradigme de
design:
◦ DTO-uri mapate pe domeniu
◦ DTO-uri custom
pot avea un impact semnificativ asupra
design-ului întregii aplicaţii.
Deşi reprezintă abordări contradictorii,
acestea pot coexista şi de obicei coexistă în
orice aplicaţie enterprise.
deseori acest model de DTO-uri nu se aliniază
bine nevoilor clientului.
interfeţe grafice diferite pot necesita seturi de
date diferite care pur şi simplu nu se mapează
peste containerele de date pe care DTO-urile
mapate pe domeniu le oferă.
un client poate cere doar câteva dintre
numeroasele atribute ale unei entităţi
persistente.
utilizarea unui DTO de domeniu pentru a
transfera toate atributele către client când doar
câteva sunt necesare reprezintă o risipă de
resurse de reţea.
Acest model nu suferă de neajunsurile
menţionate anterior, dar la rândul său
introduce alte neajunsuri.
În mod tipic, un nou DTO este scris pentru
fiecare use-case nou apărut în sistem, oferind
clientului un container pentru a transfera
doar datele care sunt cerute în cadrul noului
use-case.
În ciuda simplicităţii acestei abordări, folosirea
DTO-urilor în această manieră suferă de multiple
neajunsuri:
◦ Utilizând acest pattern, o aplicaţie tipică enterprise
distribuită va prezenta o proliferare de DTO-uri custom,
aşa de multe încât deseori dezvoltatorii vor fi dispuşi să
accepte DTO-uri cu o granularitate mai mare (care pot
conţine mai multe atribute decât este necesar) decât să
scrie noi DTO-uri custom. Atâta timp cât nu sunt
returnate prea multe date în exces, această abordare
este viabilă. Prin urmare, rămâne la latitudinea
dezvoltatorilor să echilibreze preocupările legate de
întreţinere versus performanţe.
DTO-urile custom sunt în general folosite pentru
operaţiuni read-only specifice interfeţelor grafice
cu utilizatorul şi sunt imutabile.
Deoarece aceste DTO-uri custom sunt simple
containere care nu reprezintă obiecte business
din partea de server, potenţialele modificări
asupra acestora nu îşi au sensul.
În mod tipic, actualizările sunt făcute prin
intermediul DTO-urilor mapate pe domeniu
(deoarece acestea reprezintă obiecte business
reale şi pot încapsula logică de validare) sau prin
intermediul unor metode specifice de use-case.
Cost ridicat de modificare în timp:
◦ pe parcursul dezvoltării unei aplicaţii enterprise, use-
case-urile existente pot suferi modificări în paralel cu
apariţia de noi use-case-uri. Clienţi diferiţi pot avea
nevoie să acceseze sub-seturi de date diferite din partea
de server, sub-seturi care nu au fost iniţial cuprinse în
cadrul aplicaţiei.
◦ folosind abordarea DTO-urilor custom, este necesară
scrierea de cod suplimentar pe partea de server (cum ar
fi cod pentru noile DTO-uri şi pentru logica de
construire aferentă acestora) pentru a satisface noile
nevoi de acces la date ale clienţilor.
◦ odată ce un proiect a fost lansat, accesul la programatori
pentru partea de server tinde să devină scump, la fel ca
şi procesul de redepoyment al aplicaţiei.
Nevoia de a construi un layer de obiecte de
transfer de date:
◦ DTO-urile custom constituie un nou layer care poate
exploda în mii de obiecte în cazul unor aplicaţii mari. Să
ne imaginăm un sistem distribuit în care fiecare domeniu
are ataşat un DTO de domeniu pentru a transfera datele
către şi dinspre secţiunea client. Use-case-urile
aplicaţiei pot necesita ca datele din aceste domenii să fie
împărţite în mai multe DTO-uri custom.
◦ prin urmare, un sistem de dimensiune medie poate
necesita sute de DTO-uri, fiecare dintre acestea având o
metodă aferentă de construire în partea de server.
◦ în cadrul aplicaţiilor mari, layerul de DTO-uri custom se
poate dovedi a fi foarte dificil de întreţinut.
Interfeţele grafice de la client sunt cuplate cu
partea de server:
◦ în cazul utilizării DTO-urilor custom, fiecare
interfaţă grafică client este strâns legată de DTO-ul
pe care îl foloseşte pentru a se popula.
◦ în momentul în care DTO-ul custom este modificat,
codul client trebuie reactualizat pentru a ţine seama
de modificările apărute.
Acest pattern oferă o alternativă la obiectele
de transfer de date, alternativă care
decuplează datele care sunt transferate de
obiectul care le încapsulează, menţinând în
acelaşi timp accesul şi transferul datelor între
secţiuni în cadrul unei singure comunicaţii în
reţea.
Acest pattern reuşeşte să depăşească
neajunsurile pattern-urilor discutate anterior,
dar introduce noi neajunsuri.
Nevoia de a menţine un contract pentru
cheile atributelor:
◦ în timp ce numele şi tipul atributelor sunt hard-
coded în numele metodelor din cadrul DTO-urilor
clasice, în cazul HashMap partea de client şi partea
de server trebuie să menţină un contract separat
pentru cheile şi tipurile atributelor, creându-se
astfel o dependenţă în plus între client şi server.
Pierderea ”tipurilor puternice”(strong typing) şi a
verificărilor din faza de compilare (compile-time
checking):
◦ în cazul utilizării DTO-urilor clasice, valorile manipulate
de către metodele de tip setter/getter sunt întotdeauna
verificate şi corecte din punct de vedere al tipului
acestora, orice fel de erori fiind detectate în faza de
compilare.
◦ prin contrast, în cazul utilizării HashMap-urilor, valorile
manipulate nu pot fi verificate din punct de vedere al
tipului la compilare, clientul fiind forţat să apeleze atât
la folosirea operatorilor de cast la runtime cât şi la
menţinerea unei asocieri corecte între cheile atributelor
şi tipul acestora.
Primitivele trebuiesc încapsulate:
◦ atributele de tip primitivă nu pot fi stocate într-un
map deoarece primitivele nu reprezintă subclase ale
clasei Object în Java.
◦ prin urmare, primitivele trebuiesc încapsulate într-
un obiect corespunzător înainte de inserarea
propriu-zisă în cadrul HashMap-ului.
Operatorul de cast cerut la fiecare citire:
◦ de fiecare dată când valorile atributelor sunt
preluate din HashMap, acestea trebuiesc convertite
de la tipul Object la tipul corespunzător atributelor
pe care le reprezintă.
Cei mai mulţi dezvoltatori preferă să
folosească abordarea DTO-urilor clasice.
Aceştia au înţeles foarte bine modul de
utilizare a DTO-urilor şi este foarte dificil
pentru programatorii din partea de client să
facă greşeli în acest context.
Abordarea transferului de date folosind
HashMap-uri reprezintă o sabie cu două
tăişuri care rezolvă multe probleme de
întreţinere dar pe de altă parte, nefolosită
corect, poate introduce probleme grave
asupra coerenţei datelor şi asupra aplicaţiei în
general.
Curs 12
metodă eficientă pentru transferul de date
între layerele aplicaţiilor distribuite enterprise
obiectele lightweight polimorfice folosesc:
◦ buffere interne
◦ logică de lazy-loading
◦ grupuri lazy-load definite la runtime
oferă performanţe superioare faţă de design
pattern-urile clasice care tratează transferul
de date între layere
într-o aplicaţie distribuită enterprise,
transferurile de date au loc între toate
layerele, reprezentând un punct critic care
poate afecta în mod dramatic performantele
de ansamblu ale întregii aplicaţii.
deşi complexitatea de design a pattern-ului
propus este mult mai mare decât cea a design
pattern-urilor discutate în cursurile
anterioare, acesta reuşeşte să depăşească
toate neajunsurile acestora
mai mult, această nouă abordare prezintă un
design care înglobează toate beneficiile
design pattern-urilor discutate pe lângă
faptul de a introduce noi beneficii
Structurile de date ale modelului de domeniu
sunt replicate la client în cadrul unei singure
comunicaţii în reţea:
◦ copii ale domeniului pot fi asamblate pe server şi
trimise la client folosind doar o singură comunicaţie
în reţea
◦ clientul poate apoi accesa local obiectele de transfer
de date şi poate executa operaţiuni de citire şi
actualizare asupra acestora fără a mai utiliza
resursele reţelei
◦ pentru actualizarea propriu-zisă la nivelul
serverului, clientul poate transmite obiectul de
transfer de date actualizat înapoi la server
Design pattern uşor de folosit şi de înţeles
atât de către dezvoltatorii din partea de client
cât şi de cei din partea de server.
Oferă suport pentru validarea sintactică a
atributelor la nivelul clientului:
◦ validarea sintactică a atributelor de domeniu poate fi
făcută la nivelul clientului prin încapsularea logicii de
validare în interiorul metodelor de tip setter din cadrul
obiectelor domeniu de transfer de date
◦ acest lucru permite ca erori legate de editarea sau
crearea de domenii să fie detectate direct la client
comparativ cu abordarea trimiterii obiectelor la server
doar pentru a recepţiona excepţii de validare
◦ bineînţeles că verificările semantice/validările business
ale atributelor urmează a fi efectuate în cele din urmă,
iar acest lucru în general nu poate fi făcut decât pe
partea de server
Întreţinere excelentă. Este eliminat complet
layerul de obiecte custom de transfer de date:
◦ codul din partea de partea de server care trebuia
scris pentru a genera DTO-uri custom peste
domenii este eliminat
◦ prin urmare, explozia de DTO-uri custom peste
domenii nu mai prezintă o problemă, oferindu-se
astfel o potenţială reducere a codului cu mii de linii,
complexitatea acestuia scăzând foarte mult
Ideal pentru interfeţe grafice dinamice:
◦ permite schimbarea comportamentului de cache al
bufferelor interne on-fly prin modificarea grupurilor
lazy-load la runtime
◦ prin urmare, interfeţele grafice dinamice nu suferă
nici o diminuare a performanţelor aşa cum se
întâmplă în cazul abordărilor clasice, de la nivelul
serverului fiind preluate doar datele strict necesare
aplicaţiei client
Cost scăzut de întreţinere în timp:
◦ noi sub-seturi de date de date pot fi definite la
runtime fără a necesita în nici un fel modificarea
codului de la nivelul serverului, clienţii având
posibilitatea de a decide în mod dinamic
componenţa containerelor
Prezintă o caracteristică importantă:
polimorfismul obiectelor de transfer de date:
◦ cu alte cuvinte un DTO poate să se transforme la
runtime, prin intermediul logicii de lazy-load (de
asemenea definită la runtime), într-un DTO de
domeniu sau într-un DTO custom, la orice
granularitate peste domeniul pe care îl reprezintă
Comunicaţii reduse între secţiuni:
◦ asigură faptul că numai datele cu adevărat necesare
sunt transferate între secţiunile aplicaţiei distribuite
Suportă DTO-uri care pot fi
modificate/actualizate chiar şi în cazul DTO-
urilor custom peste domenii:
◦ o componentă specială a fost concepută în partea
de server pentru a examina în mod transparent
bufferele interne ale DTO-urilor (custom sau nu) şi
a face actualizările necesare la nivelul serverului
Prezintă un control total asupra granularităţii
DTO-urilor.