Med light fyllda entiteter syftar jag på entiter där huvudförälder-entiteten i ett aggregat enbart fylls. Exempelvis man fyller order-entiteten men man lägger inte till orderraderna eller kunden till ordern, dvs dessa är null. Syftet med att göra så kan tex vara att det är för prestandakrävande för en applikation att fylla ett helt aggregrat. Först och främst får du ju fråga dig om du kommer behöva först ladda in ett objekt lite grann och sen lite mer. För i så fall är det ju just lazy loading du vill göra, det finns liksom inga alternativ. Om det inte är det så kan jag spontant bara se en lösning som inte är lazy loading eller "typ lazy loading", och det är att Jag har tänkt lite och en variant som dykt upp kring detta med light entiteter är att eventuellt skapa en basklass som är light. Sedan får subklassen representera aggregatet. Vad tror du/ni om det? Personligen anser jag att arv används alldeles för mycket utan att egentligen behövas. Light fyllda entiteter?
Nu till min fråga. Hur vet man som utvecklare att hela objektet inte är fyllt? Finns det något smart sätt att hantera detta på? Ska man implementera Lazy load i dessa avseenden eller hur löser man det på ett bra sätt?
En annan sak som jag också funderar lite över är hur det hela blir när man tex sparar (db) ett aggregat som inte är fyllt helt, dvs skickar man ned en order-entitet med orderrader som inte är fyllda hur hanteras detta på ett bra sätt? För om orderrader är null innebär det att man inte ska göra något med raderna i databasen eller innebär det att man ska ta bort alla rader som finns? Skickar man ned ett light aggregat så vill man ju inte att det ska hände något med orderraderna.Sv: Light fyllda entiteter?
skaffa separata, mindre klasser som inte har referenser till andra objekt.
<b>>[...]dvs dessa är null. Syftet med att göra så kan tex vara att det är för prestandakrävande för en applikation att fylla ett helt aggregrat. </b>
Om du bestämmer dig för att alltid använda samma klasser har du ju egentligen två alternativ;
1. "null" betyder "har inte laddat in det här objektet", vilket innebär att om du sparar objektet så sparar du bara objektet och alla null-skilda referenser. Behöver komma åt kund, så ser du att det är null och då laddar du in det. Vad gäller 1-n som listan med orderrader kan du ju välja mellan att låta själva listan vara null, eller hämta in antalet orderrader och göra en lista, fast där varje element är null.
2. det kan finnas korrekta "null"-rader, typ en order utan kund. I så fall måste du ju på något sätt ange att den inte är laddad, och det finns ju en hel hierarki lösningar:
- skapa en proxy "CustomerProxy" som har en IsLoaded, ev. en IsDirty osv. för att låta alla objekt hålla reda på om de finns eller inte. Alternativt bygger du in det i varje klass. (Då fylls en Customer med CustomerID, en Loaded-flagga sätts till false, och först när den ska användas laddas hela grejen och Loaded sätts true)
- Låt Order-klassen ha ett antal olika bool-fält "CustomerLoaded", "OrderLinesLoaded", osv.
- Låt Order-klassen ha några olika tillstånd, typ en enum, "OrderHeaderPresentation", "FullOrderPresentation", osv.. I praktiken samma sak som alternativet ovan, men emotionellt annorlunda, påminner mycket om att implementera det med flera klasser istället.
<b>>En annan sak som jag också funderar lite över är hur det hela blir när man tex sparar (db) ett aggregat som inte är fyllt helt, dvs skickar man ned en order-entitet med orderrader som inte är fyllda hur hanteras detta på ett bra sätt? För om orderrader är null innebär det att man inte ska göra något med raderna i databasen eller innebär det att man ska ta bort alla rader som finns?</b>
Det här är ju egentligen samma sak, och du har mängder med sätt att lösa det på;
- OrderLines representerar exakt alla OrderLines som finns. Det innebär att du tar bort alla objekt som inte finns med i den listan. Då kan du låta null betyda "har inte laddats".
- OrderLines representerar alla OrderLines som programmet känner till just nu. Tar man då bort en OrderLine så markerar man det med en Deleted-variabel i OrderLine, eller i en separat lista med "deleted orderlines".
- Sen har du varianter med "Hur såg det ut före?", som du jämför med precis innan du sparar, vilket ger dig svar på om grejer ska tas bort eller uppdateras, osv.Sv:Light fyllda entiteter?
Sv: Light fyllda entiteter?
Men att göra som du föreslår innebär ju att du både kan vara i en situation där du inte bryr dig om några ev. referenser, och dessutom kräva att få ett aggregat, och det är ju snyggt.
Problemet kan ju vara om man kan göra antaganden om basklassen som man inte kan göra om aggregatet, men spontant kan jag inte se vad det skulle vara "datamässigt", möjligtvis något om i vilket tillstånd en klass är eller så. Ett annat problem kan vara frågan om vem som har ansvar.
Om vi har Order och OrderLines har vi två uppenbart tänkbara implementationer;
1. Varje Order har en lista med OrderLines.
2. Varje OrderLine har en referens till en Order.
Att spara ett aggregat borde med din princip gå till som att:
"Om jag är ett aggregat (dvs en subklass) så spara först mig och sen mina barn, annars - spara bara mig." Det tar ju förstås klassen själv hand om.
Låt nu säga att det har blivit miss i kommunikationen så att vi både har Order och OrderAggregate enl. din princip OCH OrderLine och OrderLineAggregate enl. samma princip (detta är ett högst konstruerat exempel).
OrderAggregate har ju då en lista med OrderLine, som i sin tur kan vara OrderLineAggregate och då ha referens till en Order. Antingen är det då referenser till andra Order-objekt, och det är ju då fel (vi får t.ex. feta problem med vilken Order som egentligen sparades om man tar spara), eller så är det till det riktiga. Men då hamnar vi i oändliga loopar där två objekt försöker spara varandra.
Det kan man ju då lösa med ett "IsSaving"-tillstånd. Och då är det inte så jäkla smidigt längre...
Sen glömde jag en ganska uppenbar lösning i förra inlägget och det är när man övergår från att varje objekt ska hålla reda på sina grannar utan man har en övergripande manager, som då har olika strategier för vad som ska laddas när. Nästan alltid overkill enl. mig.