AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

[ORM] Lazy Loading - Wie implementieren?

Ein Thema von mquadrat · begonnen am 23. Sep 2011 · letzter Beitrag vom 26. Sep 2011
Antwort Antwort
Seite 1 von 2  1 2      
mquadrat

Registriert seit: 13. Feb 2004
1.113 Beiträge
 
Delphi XE2 Professional
 
#1

[ORM] Lazy Loading - Wie implementieren?

  Alt 23. Sep 2011, 11:56
Hallo zusammen,

Ich hab mal wieder was aus der Ecke der Konzepte. Wie würdet ihr in einem ORM in Delphi Lazy Loading implementieren? Das Mapping des OR soll komplett extern erfolgen, also z.B. über XML-Konfigurationsdateien oder Attribute. Es sollen keine Getter / Setter von Hand geschrieben werden. Direkter Zugriff auf Relationen soll über Properties möglich sein (also z.B. Rechnung.Kunde.Adresse, wobei Adresse als lazy loading in Kunde gekennzeichnet wäre).

Generell gibt es für Lazy Loading ja vier Möglichkeiten:

- Lazy Initialization: Die Property wird null-initialisiert. Beim ersten Zugriff wird das passende Objekt erstellt und geladen.
- Virtual Proxy: Es wird ein Objekt erstellt, dass das gleiche Interface wie die Zielklasse hat. Alle Aufrufe werden durchgeroutet.
- Virtual Holder: Statt das Objekt direkt aufzurufen wird immer die getValue() Funktion des Holders aufgerufen.
- Ghost: Das korrekte Objekt wird erstellt, aber nicht befüllt.


Lazy Initialization
Hierfür müsste entweder der Getter von Hand geschrieben werden oder "self-aware" Properties verwendet werden. Ich habe es noch nicht ausprobiert, aber ich denke dass müsste sich mit den Properties aus DSharp (oder einem ähnlichen Konzept) realisieren lassen.

Virtual Proxy
Um Code-Generierung zu vermeiden, müsste das Interface zur Runtime aufgebaut werden. Selbst wenn das geht, würde ich allerdings aufgrund der Typsicherheit von Delphi Probleme bei der weiteren Geschäftslogik erwarten oder es müsste im weiteren Verlauf immer eine Methode "getRealObject" mit dem richtigen Typ geben. Nicht wirklich komfortabel und schon fast ein Virtual Holder.

Virtual Holder
Sollte sich mit Generics durchaus machen lassen, sagt mir aber vom Konzept her so gar nicht zu.

Ghost:
Hier mat man ein ähnliches Problem wie bei der Lazy Initialization. Die Properties müssen den Zugriff realisieren und ggf. das Laden der Daten triggern. Man hat das Problem also von der aufrufenden Klasse in die aufgerufene Klasse verschoben. Auch das müsste mit den Properties von DSharp gehen, die Ihren Owner kennen.


Fazit:
Proxy und Holder haben IMHO konzeptionelle Unschönheiten, erlauben allerdings das Verwenden von "Standard-Properties". Lazy Initialization und Ghost verlangen den Einsatz von intelligenten Properties, was etwas unhandlich aber machbar ist. Ich würde also zu einem der beiden letzten tendieren.



Welche anderen Implementierungsmöglichkeiten gibt es? Was habe ich übersehen? Wie arbeiten existierende Delphi ORMs?
  Mit Zitat antworten Zitat
Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#2

AW: [ORM] Lazy Loading - Wie implementieren?

  Alt 23. Sep 2011, 13:39
Lazy Initialization klingt für mich am pragmatischsten, und ich sehe auch nichts, was wirklich dagegen spräche. Die anderen Lösungen wären imo mit einem noch größeren Aufwand verbunden. Ein kurzes if not Assigned(Field) then Field := ... im Getter ist nun wirklich nicht die Welt...
  Mit Zitat antworten Zitat
r2c2

Registriert seit: 9. Mai 2005
Ort: Nordbaden
925 Beiträge
 
#3

AW: [ORM] Lazy Loading - Wie implementieren?

  Alt 23. Sep 2011, 16:12
Das ist ein sehr interessantes Problem. Hab ich mir noch gar keine Gedanken dazu gemacht.

Welche anderen Implementierungsmöglichkeiten gibt es?
Weitere sind mir nicht bekannt.

Zitat:
Wie arbeiten existierende Delphi ORMs?
Kann ich dir leider nicht sagen. Ist aber nachguckbar.

Lazy Initialization klingt für mich am pragmatischsten, und ich sehe auch nichts, was wirklich dagegen spräche. Die anderen Lösungen wären imo mit einem noch größeren Aufwand verbunden. Ein kurzes if not Assigned(Field) then Field := ... im Getter ist nun wirklich nicht die Welt...
Es geht darum, dass Persistenz im Idealfall orthogonal zur Geschäftslogik sein sollte. Klar ist es nicht viel "Arbeit", aber unsauber. Wenn man den Mechanismus ändern will, kriegt man Probleme, der zusätzliche Code ist ne zusätzliche Fehlerquelle (lustig, wenn man sowas mal vergisst) und es macht den Code unübersichtlicher. Das ist jetzt nichts, was jetzt katastrophale Auswirkungen hätte. Es ist nur unschön und kann zu vermeidbaren Problemen führen. Und genau deshalb halte ich es für sinnvoll, hier zwei, drei Gedanken mehr drauf zu verschwenden.


Zwei Gedanken deshalb von mir:
- LazyInitialization könnte man u.U. mit Annotationen/Attributen reparieren. Also den Lazy-Initialization-Code zur Laufzeit einfügen. Hab ich aber nich nie gemacht, kann dazu also leider nicht viel sagen.
- Den Proxy fände ich eigentlich auch am schönsten, weil nun wirklich orthogonal. Ob man zu Laufzeit den Proxy erzeugen kann, weiß ich nicht. In Java geht das und so hege ich die Hoffnung, dass es in Delphi auch ne Möglichkeit gibt. Probleme mit der Typisierung sehe ich da nicht. Es könnte nur sein, dass das zur Laufzeit nicht geht und man auf Code-Generatoren ausweichen muss.

mfg

Christian
Kaum macht man's richtig, schon klappts!
  Mit Zitat antworten Zitat
mquadrat

Registriert seit: 13. Feb 2004
1.113 Beiträge
 
Delphi XE2 Professional
 
#4

AW: [ORM] Lazy Loading - Wie implementieren?

  Alt 23. Sep 2011, 16:58
Das ist ein sehr interessantes Problem. Hab ich mir noch gar keine Gedanken dazu gemacht.
Da immer bedauert wurde, dass in Delphi-Land so wenig über Konzepte nachgedacht wird, wollte ich das mal anstoßen

Zitat:
Zwei Gedanken deshalb von mir:
- LazyInitialization könnte man u.U. mit Annotationen/Attributen reparieren. Also den Lazy-Initialization-Code zur Laufzeit einfügen. Hab ich aber nich nie gemacht, kann dazu also leider nicht viel sagen.
- Den Proxy fände ich eigentlich auch am schönsten, weil nun wirklich orthogonal. Ob man zu Laufzeit den Proxy erzeugen kann, weiß ich nicht. In Java geht das und so hege ich die Hoffnung, dass es in Delphi auch ne Möglichkeit gibt. Probleme mit der Typisierung sehe ich da nicht. Es könnte nur sein, dass das zur Laufzeit nicht geht und man auf Code-Generatoren ausweichen muss.
Hätte beim Proxy die Property nicht den Typ des Proxys statt der eigentlichen Klasse? Oder möchtest du die eigentliche Klasse verstecken und immer den Proxy verwenden? Könnte aber auch sein, dass ich gerade auf der Leitung stehe, nachdem ich mich über die Live-Bindings Doku geärgert habe
  Mit Zitat antworten Zitat
r2c2

Registriert seit: 9. Mai 2005
Ort: Nordbaden
925 Beiträge
 
#5

AW: [ORM] Lazy Loading - Wie implementieren?

  Alt 23. Sep 2011, 17:10
Hätte beim Proxy die Property nicht den Typ des Proxys statt der eigentlichen Klasse?
Nö.

Zitat:
Oder möchtest du die eigentliche Klasse verstecken und immer den Proxy verwenden?
Nö.

Bei nem Proxy hast du immer ne Basisklasse (bzw. ein Interface). Siehe GoF:207 oder, falls du das GoF-Book nicht zu Hand haben solltest, zur Not auch Wikipedia. Du deklarierst immer den Supertyp, hast aber entweder die eigentliche Klasse oder eben den Proxy. Der Code, der das nun verwendet, kriegt den Unterschied gar nicht mit ==> abstrakte Kopplung.

Zitat:
Könnte aber auch sein, dass ich gerade auf der Leitung stehe, nachdem ich mich über die Live-Bindings Doku geärgert habe
Hab die nicht gesehen. Was ärgert dich daran?

mfg

Christian
Kaum macht man's richtig, schon klappts!
  Mit Zitat antworten Zitat
mquadrat

Registriert seit: 13. Feb 2004
1.113 Beiträge
 
Delphi XE2 Professional
 
#6

AW: [ORM] Lazy Loading - Wie implementieren?

  Alt 23. Sep 2011, 17:19
Interface.. logisch..


EDIT: Was mich an der Live-Binding Doku ärgert? Sie ist praktisch nicht existent

Geändert von mquadrat (23. Sep 2011 um 17:24 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Meflin
Meflin

Registriert seit: 21. Aug 2003
4.856 Beiträge
 
#7

AW: [ORM] Lazy Loading - Wie implementieren?

  Alt 23. Sep 2011, 17:32
Interface.. logisch..
Ich weiß nicht was mit Delphi möglich ist, NHibernate, mit dem ich gerade arbeite, implementiert die Proxies als zur Laufzeit erzeugte Ableitung der Entity.

Ach und weil du Konfiguration über XML erwähnt hast: Wer will das machen?? Automapping FTW, nur so als Denkanstoß
  Mit Zitat antworten Zitat
Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#8

AW: [ORM] Lazy Loading - Wie implementieren?

  Alt 23. Sep 2011, 17:27
Lazy Initialization klingt für mich am pragmatischsten, und ich sehe auch nichts, was wirklich dagegen spräche. Die anderen Lösungen wären imo mit einem noch größeren Aufwand verbunden. Ein kurzes if not Assigned(Field) then Field := ... im Getter ist nun wirklich nicht die Welt...
Es geht darum, dass Persistenz im Idealfall orthogonal zur Geschäftslogik sein sollte. Klar ist es nicht viel "Arbeit", aber unsauber. Wenn man den Mechanismus ändern will, kriegt man Probleme, der zusätzliche Code ist ne zusätzliche Fehlerquelle (lustig, wenn man sowas mal vergisst) und es macht den Code unübersichtlicher. D
1. Sorry, ich bin kein studierter Informatiker – was heißt „Persistenz orthogonal zur Geschäftslogik“?
2. Normal lässt man bei ORMs den Code doch eh generieren, da kann man doch den Getter ohne Probleme einbauen.
3. Was ist daran unsauber?
  Mit Zitat antworten Zitat
r2c2

Registriert seit: 9. Mai 2005
Ort: Nordbaden
925 Beiträge
 
#9

AW: [ORM] Lazy Loading - Wie implementieren?

  Alt 23. Sep 2011, 18:04
1. Sorry, ich bin kein studierter Informatiker – was heißt „Persistenz orthogonal zur Geschäftslogik“?
Normalerweise sollte eine Klasse nur eine Aufgabe haben (Single Responsibility Principle) oder anders ausgedrückt: verschiedene Aufgaben sollten auch verschiedene Klassen aufgeteilt werden (Separation Of Concerns). Das sind grundlegende Prinzipien der Softwareentwicklung, die helfen Software wartbar zu machen. Man kann so leicht Teile austauschen, ändern und wiederverwenden ohne dabei unnötigen Aufwand zu haben und unnötig Fehler zu produzieren.

So sollte also die Persistenz (das Speichern in der DB) unabhängig von der eigentlichen Programmlogik sein (das nennt man Orthogonalität). im Idealfall steht in den Klassen die gespeichert werden sollen gar kein Code, der sich ums Speichern kümmert. Das Speichern steht in einer anderen Klasse, die jedes beliebige Objekt speichern kann.

Nicht immer ist Orthogonalität einfach zu erreichen, aber es hat ja auch niemand behauptet Softwareentwicklung wär immer nur einfach.

Zitat:
2. Normal lässt man bei ORMs den Code doch eh generieren, da kann man doch den Getter ohne Probleme einbauen.
Wenn man drum herum kommen kann, verzichtet man lieber aufs generieren. Es ist ein zusätzlicher Schritt, der den build-Prozess verkompliziert und damit fehleranfällig macht. Manchmal ist das Generieren von Code aber der schlauere Weg, weil man dadurch ganz andere Fehlerquellen vermeidet. Es ist eben eine Abwägungssache.

Zitat:
3. Was ist daran unsauber?
Die fehlende Orthogonalität.

[
Ich weiß nicht was mit Delphi möglich ist, NHibernate, mit dem ich gerade arbeite, implementiert die Proxies als zur Laufzeit erzeugte Ableitung der Entity.
Das ist das, was ich meine. In Java gibt es eine proxy-Klasse, die zur Laufzeit beliebige Interfaces implementieren kann. Die wird u.a. für RMI verwendet um die Stubs/Proxys zu erzeugen und ich vermute mal Hibernate benutzt das auch.


mfg

Christian
Kaum macht man's richtig, schon klappts!
  Mit Zitat antworten Zitat
Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#10

AW: [ORM] Lazy Loading - Wie implementieren?

  Alt 23. Sep 2011, 18:22
1. Sorry, ich bin kein studierter Informatiker – was heißt „Persistenz orthogonal zur Geschäftslogik“?
Normalerweise sollte eine Klasse nur eine Aufgabe haben (Single Responsibility Principle) oder anders ausgedrückt: verschiedene Aufgaben sollten auch verschiedene Klassen aufgeteilt werden (Separation Of Concerns). Das sind grundlegende Prinzipien der Softwareentwicklung, die helfen Software wartbar zu machen. Man kann so leicht Teile austauschen, ändern und wiederverwenden ohne dabei unnötigen Aufwand zu haben und unnötig Fehler zu produzieren.
Jo, weiß ich, mach ich natürlich auch so. Sehe aber nicht inwiefern der Getter dieses Prinzip verletzt. Der Getter erzeugt ja nur das Objekt mit dem entsprechenden Parameter (z.B. ID), das eigentliche Laden sollte dann das erzeugte Objekt anstoßen – der Code zum Laden selbst sollte natürlich wieder in eine weitere Klasse ausgelagert sein. Diese Klasse (die ein festgelegtes Interface implementiert) könnte man entweder als Parameter im Konstruktor übergeben, oder sonstwie registrieren, wodurch sich der Ladecode nachträglich austauschen lässt.

In der Datenklasse steht dann kein Code, der sich direkt um die Persistenz kümmert, lediglich ein Getter, der eine Eigenschaft zurückliefert. Das würde ich noch nicht als Geschäftslogik bezeichnen.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:05 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz