[DDD] Domein object populaten vanuit Repository

Pagina: 1
Acties:
  • 251 views sinds 30-01-2008
  • Reageer

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 28-06 21:02
Stel, je hebt een repository; bv CustomerRepository.

Deze Repository heeft een method 'getCustomer(int id)'.
Deze methode haalt de customer die overeenkomt met het gegeven id uit een persistance bron (bv uit een database).
Nu moet die repository daar een Customer domein object rond maken.

Hoe doe je dit, of welke manier verkies jij ?

Heb je bv. in je domein object een method 'Initialize( dataset d )', die je vanuit je repository aanroept ?
Die initialize krijgt dan bv een (typed) dataset/table/recordset mee, en die je gebruik je dan in die method om je object mee te 'populaten'.
Het voordeel hiervan is, dat je dan direct aan de private members van je domein object kan om deze hun waarde te gaan geven.
Een nadeel is, dat je dan een (typed) dataset nodig hebt.

Of, ga je in je repository je domein object mbhv reflection gaan initializeren ? Het nadeel hiervan is natuurlijk dat reflection wat trager is, en dat je eigenlijk ook 'untyped' gaat werken. At compile time ga je nl. niet weten of je de member-names wel correct gespeld hebt.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
Ik werk zelf met een DatabaseMapper object, welke dan geëxtend moet worden door een specifieke class, per domein object of inheritence tree 1 mapper. Deze heeft onder andere de taak om domein objecten aan te maken en te populaten. Zelf werk ik dan puur met setXXX() methods. Reflection vind ik persoonlijk te traag en ik zie niet zo'n probleem in een set method. Als het nodig is, documenteer ik dan dat die puur is bedoelt voor initialisatie en niet voor andere doelen.

Het geven van een dataset aan je domein class vind ik persoonlijk niet zo netjes. Wat je wel zou kunnen doen is een interface defineren in de package van je domein classes, iets als ICustomerDataSource, en dan een class maken die die interface implementeerd en alle call doorstuurd naar je dataset, om zo aan de gegevens te komen. Zo heb je geen depency meer op je dataset, maar wel een extra interface en class. Ligt er dan maar net aan hoe graag je het wilt loskoppelen.

[ Voor 4% gewijzigd door Michali op 07-09-2005 21:39 ]

Noushka's Magnificent Dream | Unity


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 28-06 21:02
Michali schreef op woensdag 07 september 2005 @ 21:39:
Zelf werk ik dan puur met setXXX() methods.
Bedoel je hiermee setters (zoals je properties hebt in .NET), of bedoel je zo'n initialize method zoals ik beschreven heb ?
Indien je hiermee 'properties' bedoelt, hoe ga je dan te werk voor bv fields die enkel read-only zijn, die dus eigenlijk enkel een 'getter' hebben ?
Het geven van een dataset aan je domein class vind ik persoonlijk niet zo netjes. Wat je wel zou kunnen doen is een interface defineren in de package van je domein classes, iets als CustomerDataSource en dan een class maken die die interface implementeerd en alle call doorstuurd naar je dataset
Een dataset zelf vind ik ook niet zo netjes.
Een typed DataSet is dan weer ongeveer iets zoals jij beschrijft met die interface; met een typed dataset kan je de datatables die zich in de dataset bevinden en de columns van die tables adhv een door jou gespecifieerde naam benaderen. (Je gebruikt dus niet de namen van de columns/tables zoals die in de database zitten).

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
whoami schreef op woensdag 07 september 2005 @ 21:43:
[...]

Bedoel je hiermee setters (zoals je properties hebt in .NET), of bedoel je zo'n initialize method zoals ik beschreven heb ?
Indien je hiermee 'properties' bedoelt, hoe ga je dan te werk voor bv fields die enkel read-only zijn, die dus eigenlijk enkel een 'getter' hebben ?
Ik bedoel inderdaad setters ja. Bij readonly properties zou ik dan een probleem hebben denk ik :P Als het dan echt belangrijk is dat de property niet op een andere manier gezet kan worden, dan zou ik wel even gebruik kunnen maken van reflection. Ik ga denk ik ook even experimenteren met die typed dataset. Nu ik er eens over nadenk lijkt me dat ook geen slechte methode.
Een dataset zelf vind ik ook niet zo netjes.
Een typed DataSet is dan weer ongeveer iets zoals jij beschrijft met die interface; met een typed dataset kan je de datatables die zich in de dataset bevinden en de columns van die tables adhv een door jou gespecifieerde naam benaderen. (Je gebruikt dus niet de namen van de columns/tables zoals die in de database zitten).
Ok, dat bedoelde ik ook idd.

[ Voor 3% gewijzigd door Michali op 07-09-2005 21:51 ]

Noushka's Magnificent Dream | Unity


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 18-06 12:12

pjvandesande

GC.Collect(head);

whoami schreef op woensdag 07 september 2005 @ 21:43:
[...]

Bedoel je hiermee setters (zoals je properties hebt in .NET), of bedoel je zo'n initialize method zoals ik beschreven heb ?
Indien je hiermee 'properties' bedoelt, hoe ga je dan te werk voor bv fields die enkel read-only zijn, die dus eigenlijk enkel een 'getter' hebben ?
Readonly fields zouden via de argument in de ctor gezet moeten worden.

Reflection vind ik sowieso uitgesloten, dit komt bij mij over als: een slecht design dus daarom gebruik maar reflection.

[ Voor 19% gewijzigd door pjvandesande op 08-09-2005 13:22 ]


  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 31-12-2024
In mijn Model package leeft een RepositoryFactory welke op basis van reflectie en configuratie de RepositoryStubs assembly of Repository assembly laadt. De repository interfaces bestaan in de Model package, omdat die conceptueel bij het domain model horen. De RepositoryStubs is uitsluitend voor unit tests. De Repository assembly en dus de concrete repository implementaties maken gebruik van DataMappers, waar bijvoorbeeld een CustomerDataMapper een record uit de datastore leest en een domain object instantieert en vult met data (ik gebruik iBATIS of NHibernate). DataMapper implementaties zitten bij mij in de Persistence assembly.

Afbeeldingslocatie: http://www.xs4all.nl/~pgielens/img/kydmfpl2.gif

Zie Keeping the Domain Model free from Persistence Logic voor meer details.

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
questa schreef op donderdag 08 september 2005 @ 12:49:
[...]


Readonly fields zouden via de argument in de ctor gezet moeten worden.

Reflection vind ik sowieso uitgesloten, dit komt bij mij over als: een slecht design dus daarom gebruik maar reflection.
Bij de manier hoe ik werk kan ik de constructor niet gebruiken. Ik heb het populaten van objecten namelijk gescheiden van het instantieren ervan. Dit omdat ik tussen het instantieren en populaten het object eerst nog in de cache gooi ivm. cyclic depencies. Ik weet dat ze niet vaak voorkomen en dat je ze moet vermijden, maar ik heb al een gehad dat het geheel in een mooi loopje gaat. Ik zou het in de cache gooien wel iedere keer handmatig kunnen doen, maar dan ben ik dus bezig met het schrijven van duplicate code die ook vermeden kan worden.

Noushka's Magnificent Dream | Unity


  • whoami
  • Registratie: December 2000
  • Laatst online: 28-06 21:02
Wat vind je van het Persistent domain object pattern.

https://fgheysels.github.io/


  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 31-12-2024
Een ander smaakje. Een groot nadeel vind ik dat je de persistence dependency injecteert waardoor deze op het eerste oog niet lijkt te bestaan, maar wel degelijk bestaat! Zoals Frans hier al aangeeft zijn keuzes situatie gebonden. Wij gebruiken iBATIS en implementeren dus zelf DataMappers. Een DataMapper kent het domain object en dan zou de de ManagerImpl diezelfde DataMapper aanspreken? Dan heb je dus een cyclische referentie te pakken afhankelijk van je package indeling.

Even los van het feit ik een domain object het liefts persistence unaware maak, zodat developers niet zomaar Save... Load aan kunnen roepen, maar definieer services in mijn domain model die een "intention revealing" interface bieden, waar ik een objectgraaf tbv van een specifieke use-case in een go persist (UoW). Maargoed ik ben zeker niet objectief aangezien ik net in een dergelijk project verzeild ben geraakt.

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
Nog een mooie: Hoe maak je een domain object unaware van de persistence als je lazy loading toepast? Mischien met een speciale interface die de betreffende functionaliteit biedt en dan ook via depency injection een object verkrijgen? Dit is ook iets waar ik nog veel over nadenk.

[ Voor 28% gewijzigd door Michali op 08-09-2005 23:15 ]

Noushka's Magnificent Dream | Unity


Acties:
  • 0 Henk 'm!

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Even terug naar de eerste vraag. Welke methodes zijn er nou allemaal om je business objecten te vullen met gegevens uit een persistance bron? Wat zijn de voor- en nadelen? Welke gebruiken jullie?

"The shell stopped unexpectedly and Explorer.exe was restarted."


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 28-06 21:02
Michali schreef op donderdag 08 september 2005 @ 23:15:
Nog een mooie: Hoe maak je een domain object unaware van de persistence als je lazy loading toepast?
Daar heb ik de laatste tijd ook over zitten nadenken:
Je kan een 'proxy collection' maken, en die proxy krijgt een 'loader' mee.
Fowler heeft daar een voorbeeld van in z'n PoEAA boek.

Het gaat ongeveer zo:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class ProxyCollection
{
      ArrayList data;
      ILoader loader;

      public ProxyCollection( ILoader collectionLoader)
      {
           loader = collectionLoader;
      }

      public ArrayList GetSource()
      {
            if( data == null )
            {
                   data = loader.GetCollection();
            }
             return data;
      }
}


code:
1
2
3
4
interface ILoader
{
      IList GetCollection();
}


code:
1
2
3
4
5
6
7
8
9
public class ProductCollectionLoader
{
     int forProductId;
 
     public ProductCollectionLoader( int forCategory )
     {
           // Get the products that belong to the given category
     }
}
paulgielens schreef op donderdag 08 september 2005 @ 22:49:
[...]

Even los van het feit ik een domain object het liefts persistence unaware maak, zodat developers niet zomaar Save... Load aan kunnen roepen
Ben ik met je eens; ik heb ook liever niet dat ik een Save() of een Load() kan aanroepen op m'n BO.

[ Voor 72% gewijzigd door whoami op 09-09-2005 08:59 ]

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

whoami schreef op vrijdag 09 september 2005 @ 08:53:
[...]

Ben ik met je eens; ik heb ook liever niet dat ik een Save() of een Load() kan aanroepen op m'n BO.
Maar als je dan bijvoorbeeld bij het opslaan van een object Klant gelijk zijn adres gegevens wil opslaan moet je dit dan apart gaan doen?
Dus eerst had je dit:
code:
1
2
3
4
  Klant := new Klant();
  Klant.Load(1);
  Klant.Adres.Straat = "nieuwe straat";
  Klant.Save();

Hierin zit in de Klant.Save() een this.Adres.Save() aanroep. Maar hoe pak je dit aan als het Klant object niet weet dat ie is opgeslagen?

"The shell stopped unexpectedly and Explorer.exe was restarted."


Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 31-12-2024
Michali schreef op donderdag 08 september 2005 @ 23:15:
Nog een mooie: Hoe maak je een domain object unaware van de persistence als je lazy loading toepast?
iBATIS gebruikt daarvoor DynamicProxy uit het Castle project. Je moet daarvoor de iBATIS MappedStatements en LazyLoadList classes maar eens bekijken.

Let wel! Persistence unware betekent voor mij al lang geen POCO/POJO meer! Je ontkomt er niet aan om je domain objecten te voorzien van infrastructurele elementen. Voor iBATIS betekent dit dat je, gezien iBATIS alleen public properties kan setten, dan properties omwille van persistence toevoegt. Voorbeeld: mijn Gebruiker object heeft een collectie van Machtigingen, maar deze expose ik uitsluitend als readonly collection naar de buitenwereld. Daarnaast introduceer ik een AddNewMachtiging methode die duidelijk naar de consumer van het Gebruiker object communiceert wat de interactie is met de Machtigingen associatie (Evans intention revealing). Je kan geen bestaande Machtiginen aanpassen en er is geen verwachting dat je speciale checks moet doen alvorens je een nieuwe machtigingen toevoegt (IList.Add zegt hier namelijk niets over). Nadeel is dat iBATIS een public setter nodig heeft :( daar ga je dan met je POCO.

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 31-12-2024
Kaassoevlee schreef op vrijdag 09 september 2005 @ 09:03:
Hierin zit in de Klant.Save() een this.Adres.Save() aanroep. Maar hoe pak je dit aan als het Klant object niet weet dat ie is opgeslagen?
Klant is de aggregate.


Problem

It is difficult to guarantee the consistency of changes to objects in a model with complex associations. Invariants need to be maintained that apply to closely related groups of objects, not just discrete objects. Yet cautious locking schemes cause multiple users to interfere pointlessly with each other and make a system unusable.

Solution
Cluster the Entities and ValueObjects into Aggregates and define boundaries around each. Choose one Entity to be the root of each Aggregate, and control all access to the objects inside the boundary through the root. Allow external objects to hold references to the root only. Transient references to internal members can be passed out for use within a single operation only. Because the root controls access, it cannot be blindsided by changes to the internals. This arrangement makes it practical to enforce all invariants for objects in the Aggregate and for the Aggregate as a whole in any state change.



ps: Nu komt het een beetje over alsof boeken de waarheid vertellen, maar dat is natuurlijk niet zo. Het zijn alleen maar ideeën en praktijkervaringen waar je voor jezelf de zaak moet mixen en op smaak brengen voor jouw situatie!

Acties:
  • 0 Henk 'm!

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Zou je (iemand) bovengenoemde oplossing in een voorbeeldje kunnen verwerken?

[ Voor 19% gewijzigd door jelmervos op 09-09-2005 09:18 ]

"The shell stopped unexpectedly and Explorer.exe was restarted."


Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
whoami schreef op vrijdag 09 september 2005 @ 08:53:
[...]

Daar heb ik de laatste tijd ook over zitten nadenken:
Je kan een 'proxy collection' maken, en die proxy krijgt een 'loader' mee.
Fowler heeft daar een voorbeeld van in z'n PoEAA boek.
Grappig, dat is namelijk exact de manier die ik nu toepas. Het enige waar ik nog problemen mee heb is het aanmaken van zo'n collection class. Ik zou er natuurlijk een factory voor kunnen gebruiken.

Noushka's Magnificent Dream | Unity


Acties:
  • 0 Henk 'm!

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Michali schreef op donderdag 08 september 2005 @ 23:15:
Nog een mooie: Hoe maak je een domain object unaware van de persistence als je lazy loading toepast? Mischien met een speciale interface die de betreffende functionaliteit biedt en dan ook via depency injection een object verkrijgen? Dit is ook iets waar ik nog veel over nadenk.
Waarom zou je het willen? Als je lazy loading wilt heb je die functionaliteit in je entity object nodig. Je kunt wel gaan knoeien met proxies en andere ranzigheid, maar dan creeer je een extra layer voor ... ja voor wat eigenlijk?

Men zou eens wat meer pragmatischer met de materie om moeten gaan.

Voor het probleem dat Paul aandraagt: dat je niet wilt dat Save/Load zomaar kunnen worden aangeroepen, daarvoor kun je een adapter pattern gebruiken, waarbij je de persistence logica aanbiedt als een adapter naar de persistence store toe. Lazy loading kun je dan niet gebruiken, immers, als je niet wilt dat iemand load kan doen zonder bv BL code te gebruiken vanuit de GUI, dan is lazy loading ook niet mogelijk.

Paul: iBatis, is dat niet dat ding die alle SQL queries opslaat in een xml file?

[ Voor 28% gewijzigd door EfBe op 09-09-2005 09:28 ]

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 28-06 21:02
EfBe schreef op vrijdag 09 september 2005 @ 09:24:
[...]

Waarom zou je het willen? Als je lazy loading wilt heb je die functionaliteit in je entity object nodig. Je kunt wel gaan knoeien met proxies en andere ranzigheid, maar dan creeer je een extra layer voor ... ja voor wat eigenlijk?
Op die manier zorg je ervoor dat je al je DB access 'samen' hebt staan, en niet verspreid over n classes.
Voor het probleem dat Paul aandraagt: dat je niet wilt dat Save/Load zomaar kunnen worden aangeroepen, daarvoor kun je een adapter pattern gebruiken, waarbij je de persistence logica aanbiedt als een adapter naar de persistence store toe.
Wat is die 'repository' meer dan een adapter ? Die repository is imho een soort 'adapter' naar je persistence store. Die repository gaat die gegevens ophalen, en voor jou een custom object maken.
Lazy loading kun je dan niet gebruiken, immers, als je niet wilt dat iemand load kan doen zonder bv BL code te gebruiken vanuit de GUI, dan is lazy loading ook niet mogelijk.
Dmv die proxy kan je wel gebruik maken van lazy loading. Die proxy gaat nl. op een (indirecte) manier de repository opnieuw gaan aanspreken.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 31-12-2024
EfBe schreef op vrijdag 09 september 2005 @ 09:24:
Paul: iBatis, is dat niet dat ding die alle SQL queries opslaat in een xml file?
"Dat ding" om resultaten van queries te mappen tegen objecten. Idd queries in een XML file, maar wij mappen tegen sprocs, dus slaan we de referentie naar de sprocs op in die XML file. iBATIS is dus beslists geen OR/M.

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 31-12-2024
EfBe schreef op vrijdag 09 september 2005 @ 09:24:
Waarom zou je het willen? Als je lazy loading wilt heb je die functionaliteit in je entity object nodig. Je kunt wel gaan knoeien met proxies en andere ranzigheid, maar dan creeer je een extra layer voor ... ja voor wat eigenlijk?
whoami schreef op vrijdag 09 september 2005 @ 09:34:
Op die manier zorg je ervoor dat je al je DB access 'samen' hebt staan, en niet verspreid over n classes.
Nee, je wil een ontwikkelaar afschermen van infrastructurele elementen zoals persistence en zijn feature set, waaronder lazy loading. Een proxy valt terug op de persistence infrastructuur, maar lijkt voor de consumer van je domain object op dat wat hij verwacht te vinden. Het gaat hier om de mindset! Frans maakt geen bewaar om benodigde features onder te brengen in de entity zelf (waar wij over domain objecten praten, als je Yourdon leest zal je merken dat we eigenlijk over hetzelfde praten), waar ik ervoor kies dit waar mogelijk te delegeren naar de infrastructuur.

Nogmaals hier speelt veel meer mee! De DDD mindset stuurt aan op een core domain, waar je infrastructuur niet kan ontkennen (zoals persistence support of IoC/Spring), maar niet beschouwd als core element. Een ander kan hier prima mee leven… je weet dat je zaken ergens wegschrijft, waarom zou je dat proberen te verbergen?!? Iets wat zonder twijfel belangrijk is voor je applicatie en waar je een groot deel van je ontwikkeltijd aan besteed. Wil je alle ontwikkelaars op een project de ins en outs van OR/M bijbrengen? Of wil je juist een team van specialisten inzetten?

Patterns zijn niet bedoeld om een discussie kracht bij te zetten of te buigen omwille van geldige argumenten. Een Repository is niets meer dan een aanbieder van een collection-like interface. Dat deze werk delegeert naar infrastructuur is een implementatie detail.

[ Voor 11% gewijzigd door Scare360 op 09-09-2005 11:50 ]


Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
Het punt ligt juist bij het testen van de domein objecten. Dit wil je ook geisoleerd kunnen doen, onafhankelijk van je persistence. Het loskoppelen dmv. een extra interface en depency injection is dan gewoon noodzaak. Het gaat immers niet om wat er werkelijk achter hangt. Het enige wat belangrijk is, is dat de benodigde informatie opgehaalt kan worden (en dus een set functies beschikbaar is waarmee dat kun: dus een interface). Hoe dat gebeurt is niet relevant voor de domein objecten.

Noushka's Magnificent Dream | Unity


Acties:
  • 0 Henk 'm!

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Michali schreef op vrijdag 09 september 2005 @ 12:00:
Het punt ligt juist bij het testen van de domein objecten. Dit wil je ook geisoleerd kunnen doen, onafhankelijk van je persistence. Het loskoppelen dmv. een extra interface en depency injection is dan gewoon noodzaak. Het gaat immers niet om wat er werkelijk achter hangt. Het enige wat belangrijk is, is dat de benodigde informatie opgehaalt kan worden (en dus een set functies beschikbaar is waarmee dat kun: dus een interface). Hoe dat gebeurt is niet relevant voor de domein objecten.
Wat houdt testen van je domein objects dan in? Testen zonder context is IMHO testen voor de buhne, en geeft een vals 'het werkt' gevoel.

M.a.w.: je domain objects zul je moeten testen in context, dus dat ze data krijgen van de persistence logica.

Waar het hier om gaat is HOE je ervoor zorgt dat een GUI team geen shortcuts maakt mbt de BL tier, voor wat betreft persistence logic, dus niet zelf data gaat wegschrijven of gaat fetchen, direct of indirect, maar de BL tier daar voor gebruikt. Dat is niet altijd noodzaak, maar sommige mensen willen nu eenmaal zo werken. WIL je zo werken, dan heb je een object nodig die voor jou de persistence logica regelt voor je entities zodat deze zelf niet die logica in zich hebben, en daar hoort lazy loading dus OOK bij, want anders kun je als GUI developer via lazy loading de complete database inladen.

Dat neemt niet weg dat de entities, zoals Paul al aangeeft, best persistence logic gerelateerde code in zich mogen hebben, waarom niet? Dat krampachtig verbergen met proxy kauwgom is leuk voor je CV maar voegt niet zoveel toe, want de MEERWAARDE van wat je dan overhoudt is nihil tov een entity object dat wel persistence logic code in zich heeft (bv changetracking) maar geen persistence method gerelateerde code (dus kan zichzelf niet saven, laden).

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 28-06 21:02
EfBe schreef op vrijdag 09 september 2005 @ 12:28:
[...]

Wat houdt testen van je domein objects dan in? Testen zonder context is IMHO testen voor de buhne, en geeft een vals 'het werkt' gevoel.

M.a.w.: je domain objects zul je moeten testen in context, dus dat ze data krijgen van de persistence logica.
Hoezo; je wil toch de 'business-logica' testen ? Je wil toch testen of die business logic rules correct zijn ? En dan maakt het niet uit waar die data vandaan komt.
Stel dat je eerst je domain layer maakt, en dan pas je database, dan zou dat willen zeggen dat je niet kunt testen zolang je geen DB hebt.

https://fgheysels.github.io/


  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Oke, ik heb nu een repository gemaakt welke mijn business objecten vult met gegevens. Helaas zit ik met het probleem dat ik op deze manier lazy loading niet kan gebruiken.

Ik heb dit geprobeerd op te lossen via een Interface, maar weet niet of dit wel mooi is. De code in de UI ziet er nu als volgt uit:
code:
1
2
3
4
5
6
7
8
var
  Repository: TOrderRepository;
  Order: TOrder;
begin
  Order := TOrder.Create;
  Repository := TOrderRepository.Create;
  Order.ItemsLoader := TOrderLineRepository.Create(Order);
  Repository.LoadOrderById(1, Order);

Hier moet ik dus een koppeling maken met de OrderLineRepository en de Order.ItemsLoader, zodat de order op het juiste moment zijn inhoud kan inladen.

Is dit een goede aanpak? Is het niet gewoon makkelijker om mijn business objecten een Load/Save/Delete te geven op een laag niveau?

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • whoami
  • Registratie: December 2000
  • Laatst online: 28-06 21:02
Lazy loading kan je doen dmv een proxy.
Assign, bij het vullen van je domein-object, een proxy class aan de collectie die je wilt lazy-loaden. Die proxy zal er dan moeten voor zorgen dat je collectie gevuld wordt als die voor de eerste keer aangeroepen wordt.

Ik zie ook dat je je domein object in je applicatie zelf maakt, dat zou ik niet doen. Ik zou de repository daar voor laten verantwoordelijk zijn:
code:
1
Order o := Repository.LoadOrderById (1);

https://fgheysels.github.io/


  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Is deze proxy dan onderdeel van je domain classes of van je repository classes?

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • whoami
  • Registratie: December 2000
  • Laatst online: 28-06 21:02
Van geen van de 2. Die proxy kan generiek zijn, als je 'm een 'loader' meegeeft. Die 'loader' zorgt dan eigenlijk voor het uiteindelijke ophalen.
Kijk anders eens naar het (virtual) proxy pattern; dit zou je moeten terugvinden in het 'Gang of Four' boek.

https://fgheysels.github.io/


Anoniem: 152834

Ik ben geen groot voorstander van lazy-loading. Ten eerste kan het problemen geven mbt multithreaded omgevingen. Als iemand bijvoorbeeld een object verwijderd waarvan een ander een lazy-loaded instantie heeft zal die ander een of ander half transient object hebben. Verder is het doorgaans niet nodig om lui te doen, je weet toch immers welke informatie je wilt tonen.

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Bedankt, dat met die proxy werkt.
Zijn dit soort oplossingen voor DDD ook ergens beschreven?

"The shell stopped unexpectedly and Explorer.exe was restarted."

Pagina: 1