Follow my new blog

Donnerstag, 22. April 2010

Geshreddert persistent – Gedanken zu einem Datengranulat

Mapping von Daten zwischen Pesistenzmedium und Objektmodell ist nicht zu vermeiden. Es ist keine Last, sondern pure Notwendigkeit, wenn wir mit persistenten Daten “in Zeit und Raum” integrieren wollen. Denn dann müssen persistente Daten eine sehr flexible Struktur haben, die sich immer wieder neuen Anforderungen an in-memory Datenmodelle anpassen lässt. Zu dieser Erkenntnis hat mich eine Diskussion um Ayende Rahiens Dokumentendatenbank RavenDB gebracht.

Mein Gefühl ist nun, dass solch flexible persistente Struktur weder RDBMS noch DocDBs bieten. Ihre Datenmodelle sind zwar flexibler als die von ODBMS, doch ich glaube, das ist noch nicht genug. Zum Beleg hier Ayendes Dokumente für eine Blog-Datenbank:image

Das implizite Schema ist ganz einfach. User, Blog, Post sind Entitäten, die einander referenzieren; ein Post enthält Comments, verweist also nicht weiter auf sie.

Die ist natürlich überschaubarer als ein typisches relationales Schema für das Szenario (ebenfalls von Ayende):

image

Was habe ich nun daran auszusetzen? Das relationale Schema ist vor allem erstmal ein Schema, das geplant werden muss. Solche Planung ist gerade in der Anfangsphase eines Projektes schwierig und tendiert dazu, immer wieder angepasst werden zu müssen. Häufige Schemaänderungen am Persistenzmedium machen aber keinen Spaß.

Dem hält die NoSql-Bewegung schemalose Datenbank entgegen, von denen RavenDB ein Vertreter ist. Ayende konnte die obigen Dokumente einfach so ohne Vorplanung in seine Datenbank “schmeißen”. Keine Schemadefinition ist nötig. Er kann sie dann über ihre Id oder Queries auf ihren Feldern wieder herausholen. Eine NoSql-Datenbank leistet also nicht weniger als ein RDBMS – spart Ihnen jedoch Planungsaufwand. Ändert sich die Struktur eines Dokuments, speichern Sie es einfach neu. RavenDB ist auch tolerant gegenüber dem Hinzufügen/Löschen von Feldern oder Typänderungen. Indexe für schnelle Suche gibt es ebenfalls.

Sind NoSql-Datenbanken also nicht vielleicht die besseren Datenbanken?

Es gibt keine “absolut guten” Datenbanken, die immer eingesetzt werden sollten. Güte/Qualität/Eignung hängt von Ihren Anforderungen ab. Die unausgesprochene Anforderung, die RDBMS lange erfüllt haben und immer noch erfüllen, war/ist die nach hoher Effizienz gepaart mit einiger Flexibilität. Immerhin sind RDBMS Kinder der 1970er, als Software unter starker Ressourcenknappheit (Speicher, Prozessorgeschwindigkeit, Datenübertragungsrate) gelitten hat. Da war Effizienz in dieser Hinsicht ein hohes Gut.

Heute sind diese Ressourcen in vielen Szenarien kein Problem mehr. Andere Anforderungen gewinnen daher an Bedeutung. Die aus meiner Sicht wesentliche Anforderung ist die nach Flexibilität. Wir haben schon genug Mühe mit unseren Objektmodellen, da wollen wir nicht noch aufwändig ein zweites Schema für die persistenten Daten pflegen.

Dass NoSql-Datenbanken jetzt ein Thema sind, finde ich also ganz verständlich. Sie bieten durch Schemalosigkeit mehr Flexibilität. (Dass sie darüber hinaus auch noch andere Anforderungen besser als RDBMS erfüllen, lasse ich hier undiskutiert. Darum geht es mir nicht.)

Doch warum bei Tupeldatenbanken (z.B. Amazon SimpleDb) oder Dokumentendatenbanken (z.B. RavenDB) stehenbleiben? Geht vielleicht noch mehr Flexibilität? Ich glaub schon.

Beziehungsprobleme

Mein Gefühl ist, dass auch Dokumentendatenbanken noch Flexibilitätspotenzial verschenken. Das Problem steckt aus meiner Sicht im Umgang mit Beziehungen:

image

Ein Post-Dokument verweist auf ein Blog-Dokument, ein Post-Dokument enthält Felder und insb. mehrere Comment-Strukturen. Das sind zwei Arten von Beziehungen, explizite und implizite. Einmal wird verwiesen, einmal wird enthalten.

Klingt alles so natürlich – doch ich glaube, da steckt der Teufel im Detail. Wir machen unsere Datenmodelle unflexibel, weil wir beide Arten von Beziehungen vermischen. Ein Dokument wie ein Post ist über den Verweis an das Blog-Dokument gekoppelt. Ein Post ist abhängig vom Blog. Und Abhängigkeiten sind unschön; soviel sollte sich herumgesprochen haben.

Dass wir Einheiten definieren und persistieren wollen, ist unzweifelhaft. Ich habe also nichts gegen Dokumente. Solche Einheiten fassen Daten in Form von Feldern (Name-Wert-Paare) zusammen. Welche Felder sollen in einem Dokument stehen? Felder mit hoher Kohäsion, d.h. solche, die einfach eng zusammen gehören.

Dokumente sind damit sozusagen Einheiten mit einer “Single Responsibility”. Die stehen für genau eine Sache, z.B. ein Artikel in einem Blog oder ein Benutzer usw. Das macht sie auch zu Einheiten hoher Effizienz. Denn so ein Dokument kann man “in einem Rutsch” gut aus einem Persistenzmedium laden.

Und solche Einheiten haben eine Identität, d.h. sie lassen sich referenzieren, statt immer wieder in unterschiedlichen Zusammenhängen gespeichert werden zu müssen. Sie manifestieren das DRY-Prinzip in der Datenhaltung. Konsistenz ist leichter herstellbar.

Ob innerhalb eines Dokuments dann ein Feld nur einen Datenwert hat oder mehrere, halte ich für unerheblich. Im obigen Dokument hat tags z.B. mehrere Werte. Das widerspricht der relationalen 1. Normalform – aber was soll´s ;-) Wir reden über Flexibilität und Dokumentendatenbanken. Ganz pragmatisch gesehen sind multiple Werte kein Problem.

Welche Form ein Wert jedoch hat, das halte ich für bedenkenswert. Sollte ein Wert, der innerhalb eines Dokuments steht, selbst wieder eine Struktur haben, so wie die Comment-Werte? Ich glaube, nein. Felder sollten die Atome eines Dokuments sein, ihre Werte unteilbar. Zeichenketten, Zahlen, Datum/Zeit… das war´s.

Das halte ich aus zwei Gründen für vorteilhaft:

  1. Ob ein Feld einen oder mehrere Werte haben können soll, ist bei der Datenmodellierung meist schnell entschieden. Für die Persistenz als Dokument macht es, wie oben gezeigt, außerdem keinen Unterschied. Auch ob ein Feldwert eine Struktur hat oder nicht, ist meist leicht zu entscheiden. Straße+PLZ+Ort als 3 Felder speichern oder doch besser als eigene Datenstruktur? Kein Problem. Doch dann kommt die knifflige Frage, wenn die Entscheidung für eine Datenstruktur fielt. Soll die in einem Dokument gespeichert werden oder außerhalb nur mit einer Referenz darauf? Darüber kann man lange diskutieren und immer wieder Blicke in die Glaskugel werfen.
    Um das zu vermeiden, möchte ich nahelegen, per se alle strukturierten Werte nicht in einem Dokument abzulegen, sondern darauf zu verweisen. Mein erster Antrieb ist also hohe Produktivität. Nicht lang schnacken ;-)
  2. Doch nicht nur die Produktivität steigt, wenn Sie über Inklusion/Exklusion nicht lange diskutieren müssen. Daten, die für sich, d.h. separat in einem (kleinen) Dokument gespeichert sind, können Sie wiederverwenden. Im Hauptspeicher sind Objekte die Einheiten, die referenziert werden können. In Doumentendatenbanken sind es Dokumente. Felder zu Strukturen zusammenfassen und separat speichern spart also Platz und macht es leichter, Konsistenz herzustellen.
    Das ist erstmal das Potenzial, das in der Auslagerung von Strukturen liegt. Ob Sie es nutzen und einem Adressdokument wirklich eine eigene Identität geben und es wiederverwenden, ist dann nochmal eine zweite Frage. Die Auslagerung, d.h. Entkopplung von Strukturen macht das jedoch erst möglich.
  3. Auslagerung ist Entkopplung. Oder umgekehrt: Einschachtelung ist eine stärkere Form der Kopplung als Referenzieren. Es ist ja gerade der Zweck eines Dokuments, sich eng an seine Felder zu koppeln. Das führt zu Effizienz. Was zusammengehört, soll man nicht auseinander reißen. So eng koppeln wie (aus Effizienzgründen) nötig, so lose koppeln wie möglich. Das ist nicht für in der Softwarearchitektur wichtig, sondern auch bei der Datenmodellierung eine Tugend, denke ich. Wo Sub-Strukturen auftauchen, scheint mir daher eine Grenze überschritten. Bei ihnen sollte die enge Kopplung durch Inklusion enden. Schachtelung ist also nicht nur bei Programmstrukturen “böse”, sondern auch bei Datenstrukturen.

Unterm Strich bin ich also dafür, Daten zu Dokumenten zusammenzufassen. Eine gute Sache. Daten in einen Sack füllen, zubinden, ab in die Datenbank damit.

Diese “Datensäcke”/Dokumente sind für mich das Granulat flexibler persistenter Datenhaltung. Sie sind die aus Anwendungssicht unteilbaren Dateneinheiten. Die hohe Kohäsion ihrer Felder hält sie zusammen. Und die Felder haben wiederum atomare Werte – allerdings können das mehrere sein.

Soweit zur Modellierung der Kommentare in Ayendes Post-Dokument. Was aber ist mit dem Verweis auf das Blog? Ich glaube, dass Felder keine Beziehungen enthalten sollten. Punkt.

Ja, genau, lassen Sie sich das auf der Zunge zergehen: Dokumente selbst referenzieren keine anderen Dokumente. Referenzen wie das blog-Feld in Ayendes Post-Dokument halte ich für eine zu enge Kopplung. Wie oben schon gesagt: Der Verweis macht das Dokument abhängig. Das ist bei Daten so unschön wie bei Funktionseinheiten. Abhängigkeiten sind “böse”.

Warum steckt der Bezug zum Blog im Post? Aus zwei Gründen: Erstens aus einem Mangel an geeigneten Alternativen und zweitens aus Effizienzgründen. Beides halte ich für überwindbare Hindernisse, wenn persistente Datenmodelle flexibel sein sollen. Der Effizienzgrund verschwindet durch den Wunsch nach Flexibilität. Effizienz und Flexibilität widersprechen sich (meistens). Und der Mangel an Alternativen sollte sich beheben lassen. Hier ist “Tooling” gefragt.

Ohne eingeschachtelte Strukturen (comments) und ohne Beziehungen (blog) halte ich dann das Beziehungsproblem für gelöst. Es gibt dann keine enge Kopplung mehr nach innen und keine Kopplung mehr nach außen. Dokumente stehen dann für sich im “Datenraum” als “Granulatkügelchen”. Mein Post-Dokument würde so aussehen:

// posts/1
{
    "title": "RavenDB",
    "content": "... content ...",
    "categories": ["Raven", "NoSQL"]
    "tags" : ["RavenDB", "Announcements"],
}

Beziehungsraum

Wenn Dokumente keine Beziehungen mehr enthalten, wie werden die denn dann aber aufgebaut? Sie sind doch wichtig. Post-Dokumente gehören zu einem Blog und haben Kommentare. Irgendwie muss ein Post-Dokument also auf sein Blog und seine Kommentare verweisen. Doch wo/wie soll das geschehen, wenn es keine Felder mit Referenzen und keine Schachtelung mehr gibt?

Ich schlage einen “Beziehungsraum” vor, einen Bereich/Container, der nur die Beziehungen zwischen Dokumenten verwaltet. Das wäre eine klare Separation of Concerns (SoC). Dokumente enthalten Daten. Der Beziehungsraum enthält Beziehungen. Zusammen ergeben sie das persistente Datengeflecht.

Im Beziehungsraum wären jedem Dokument die Dokumente zugeordnet, mit denen es in Beziehung steht. Der Beziehungsraum bestünde also quasi nur aus Identitäten. Der Identität post/1 wären dann z.B. die Identitäten blog/1 und comment/1, comment/2 zugeordnet.

image

Etwas weniger bildhaft könnte das so aussehen:

image

Das wäre dann ein normaler Graph. Die Beziehungen sind bewusst ohne Pfeile, weil ich denke, dass alle Beziehungen grundsätzlich bidirektional persistiert werden sollten. Denn: Wer weiß, ob man nicht irgendwann mal auch “rückwärts” traversieren will? Wer heute ein Blog herauszieht aus der Datenbank, um darüber Postings zu erreichen, der will es morgen vielleicht umgekehrt tun. Immer schön flexibel bleiben.

Ein Graph legt natürlich nahe, eine Graphendatenbank wie Neo4J (http://neo4j.org/) oder InfoGrid (http://infogrid.org/) für das Datengranulat einzusetzen. Leider gibt es anscheinend bisher (Stand April 2010) keine ähnlich leistungsfähigen Angebote auf der .NET Plattform, doch das mag sich ja ändern. Dokumentendatenbanken schießen aus dem Boden, warum nicht auch Graphendatenbanken? Müssen ja nicht gleich Enterprise-Qualität haben. Erstmal geht es auch kleiner, embedded, um mal mit dem Paradigma warm zu werden.

Oder sind Graphendatenbanken es auch noch nicht? Denn lt. deren API sieht es noch so aus, als würden Beziehungen mit den Knoten gespeichert. (Aber vielleicht ist das nur einem einfachen API geschuldet und im Persistenzmedium sieht es dann anders aus.) Denn meine Idee ist ja eben, die Knoten (“Datensäcke”) frei von Beziehungen zu halten. Das Bild dafür sähe eher so aus:

image

“Irgendwas” zwischen den “Datensäcken”, den Granulatkügelchen setzt sie in Beziehung.

Während ein generischer Graphendatenbank-API Beziehungen so aufbauen würde:

Node post = new Node(…);

Node blog = new Node(…);

post.Relate(blog);

oder

blog.Relate(post);

Wäre ein Granulat-API ehrlich, wenn er es so täte:

RelationSpace rs = …;

rs.Relate(post, blog);

Aber das könnte natürlich auch in einer Node.Relate() Methode versteckt sein. Hm… Ich bin noch unsicher, wie ich es gern hätte.

In jedem Fall scheint mir die deutliche Unterscheidung zwischen Daten und Beziehungen wichtig. So wird das persistente Datenmodell sauber (im Sinne des SoC) und flexibel. Zusätzlich wären Beziehungen immer first class citizens und könnten ebenfalls mit Attributen versehen werden. Sie könnten z.B. den Beziehungsenden “Rollen” zuweisen:

rs.Relate(post, “partOf/contains”, blog);

Aus Sicht eines Posting wäre das Blog das Ganze dessen Teil (“partOf”) es ist. Für ein Posting könnte damit gezielt erfragt werden, wovon es denn Teil ist:

IEnumerable<Node> blogs = rs.Traverse(post, “partOf”);

Oder ein Blog könnte nach seinen Postings befragt werden:

IEnumerable<Node> postings = rs.Traverse(blog, “contains”);

Aber vielleicht ist der Graph-API doch etwas intuitiver?

… = post.Traverse(“partOf”);

Um einem Node Zugriff auf den “Beziehungsbaum” zu geben, müsste er dafür allerdings damit initialisiert worden sein. Hm… warum nicht? Es geht hier ja nicht um einen API/ein Datenmodell, dass in allen Anwendungsschichten und über Remoting-Grenzen hinweg funktionieren soll. Mapping ist notwendig. Die über den API zugänglichen Granulatkügelchen und Beziehungen müssen damit nur gefüllt werden können. Danach kann das objektorientierte Datenmodell allein stehen.

Semantikfreiheit

Das bringt mich zu einem letzten Punkt: Ich glaube immer mehr, dass im Persistenzmedium keine Semantik stecken sollte. Die ist ein Concern, der nicht dahin gehört. Ein Persistenzmedium ist ein Persistenzmedium ist ein Persistenzmedium. Es speichert Daten dauerhaft, so dass aus ihnen später wieder “Werkstücke” gefertigt werden können. Dafür sind in einem Datengranulat “Kügelchen” und Beziehungen festzuhalten. Fertig.

An einem Blog hängen viele Postings. Ein Posting hat viele Kommentare. Dieser Zusammenhang ist zu persistieren. Ob ein Blog-Objekt in einem bestimmten Kontext seine Postings in einer IList<> oder einem Dictionary<,> oder in einem Array halten will, ist nicht Sache des Persistenzmediums. Ein Mapping sorgt dafür, dass die vielen Postings in die kontextspezifische Collection eines Blogs kommen.

Das Persistenzmedium kennt nur atomare Granulatkügelchen mit einem oder mehreren atomaren Werten je Feld. Und es kennt bidirektionale benannte Beziehungen zwischen den Granulatkügelchen.

Das scheint mir die Grundanforderung an ein Datengranulat-Modell. Was in einem Objektmodell für die Verarbeitung “irgendwie verwoben ist”, wird für die Persistenz gründlich geshreddert. Nur so ist es möglich, es später für die Verarbeitung in anderen Kontexten möglichst einfach immer wieder anders zusammenzusetzen.

image

Der Unterschied zum relationalen Datenmodell besteht dabei darin, dass das relationalen Datenmodell kontextspezifische Schemata nahelegt. Datengranulat hingegen sieht immer gleich aus. Die Granulatkügelchen mögen unterschiedliche “Farben” und Größen haben, doch sie sind in einem immer gleich: es sind Atome ohne inhärente Beziehungen. Beziehungen sind extern zu ihnen und sehen ebenfalls immer gleich aus.

Jetzt die Frage: Wo ist eine Datengranulat-Persistenztechnologie? Dokumentendatenbanken sind es nicht. In ihnen können “Datensäcke” zwar hübsch gespeichert werden, doch für die Beziehungen sind Dokumente untauglich, glaube ich.

RDBMS wiederum könnten für Beziehungen ordentlich sein, aber schemalose “Datensäcke” sind nicht ihr Ding.

Ein ODBMS könnte hier hingegen passen. Das Granulat-Datenmodell ist ja universell und ändert sich nicht. Flexibilität ist nicht nötig. Da ODBMS für starre Datenmodelle geeignet sind und direkte Beziehungen effizient verwalten, könnte darauf eine Granulatdatenbank aufgesetzt werden.

Oder doch besser eine Graphendatenbank? Hm… Ich glaube, damit würde ich am ehesten mal spielen wollen.

Oder selbst bauen? Mal mit F# Infrastruktur basteln? Ein Entwicklertraum würde wahr… :-) Na, mal schauen. Erstmal drüber schlafen. Am Ende gehts ja zunächst nur um einen API. Wie es darunter aussieht, ist egal.

Kommentare:

serega hat gesagt…

Ralf, das ist ja alles interessant, aber mir noch etwas zu abstrakt. Warum brauchst Du so viel Flexibilität? So ein Ansatz sieht sehr nach Bottom-Up aus, wovon ich eigentlich kein Fan bin. Ich halte heute für optimal den Ansatz von DDD, basierend auf einer DocDb. Ich denke, dass BC und AR Patterns genau dafür sorgen, um die Beziehungen (die Du gerade verboten hast) richtig hinzukriegen.
Natürlich ist das nicht "leicht". Schwer ist das aber auch nicht - nur etwas ungewöhnlich für manche, die nur mit dem Designer klar kommen. Für solche macht diese Diskussion sowieso nicht viel Sinn. Die gehen eher mit Entity Framework besser um.
Ich würde es lieber mit dem Top-Down-Ansatz versuchen, als bottom-up in die Glaskugel zu schauen.

Ralf Westphal - One Man Think Tank hat gesagt…

@Serega: Schaue ich in die Glaskugel? Hm... Genauso viel wie die Leute, die DocDb nutzen oder CQRS. Die tun das nämlich, weil sie unzufrieden sind mit dem, was für sie davor war.

Ich bin unzufrieden. Deshalb suche ich nach Wegen, meine Unzufriedenheit zu mildern. Das halte ich für kein Glaskugelgucken. Das ist vielmehr der Antrieb, der hinter jedem Fortschritt oder zumindest jeder Forschung steckt.

Wenn ich dabei über die unterste Schicht nachdenke, dann bedeutet das nicht notwendig, dass ich bottom-up denke. Ich verorte da vielmehr ein Wurzelproblem. Als muss ich es dort lösen.

Ich finde DocDBs auch hübsch. Aber ich erlaube mir, auch diesem Hype nicht gleich zu verfallen. O/R Mapper sahen auch schon wie "die Lösung" aus. Nun sind es DocDBs.

Aber wofür überhaupt "die Lösung"?

Das, so meine ich, hat sich eben geändert. Früher brauchten wir "die Lösunge" für effiziente Persistenz. Da kamen RDBMS.

Heute brauchen wir für etwas anderes eine Lösung. Nämlich für flexible Persistenz. Wir müssen Daten für Modelle (um nichts anderes geht es bei DDD) so persistieren, dass wir uns nicht in eine Ecke pinseln. Und wir wollen auch für Daten kein BDUF.

Das scheint nun mit DocDBs etwas besser zu gehen als mit RDBMS. Schön. Aber warum dabei stehenbleiben? Nachdenken sollte erlaubt sein.

Vor allem schaue ich ja nicht in die Glaskugel, weil ich mich bemühe, das Grundproblem zu analysieren. (Dass wir Flexibilität brauchen, sollte unzweifelhaft sein. Um nichts anderes geht es der ganzen Agilitätsbewegung. Da haben wir ja auch akzeptiert, dass die nicht in die Glaskugel schaut, sondern postuliert: du willst immer flexibel sein und die nicht durch einen Jahre vorausschauenden Projektplan einengen lassen.)

Und so bin ich für mich da angelangt, dass ich vermute, unser Dateninflexibilitätsproblem hat mit Beziehungen zu tun. Mit einem Mangel an Prinzipien bei der Datenmodellierung. Wenig DRY (abgesehen von relationalen Normalisierungen), wenig SoC, wenig SRP. Und so sinne ich darüber, wie ein persistentes Datenmodell aussehen könnte, das diesen Prinzipien mehr folgt.

-Ralf

Anonym hat gesagt…

Hallo,

ich finde es gut sich Gedanken über Flexibilität bei Datenpersistenz zu machen. Dem Statement "… ich vermute, unser Dateninflexibilitätsproblem hat mit Beziehungen zu tun." kann ich mich nur anschließen. Die Artikelserie über das Intuitive Datenmodell (IDM) war nach meiner Meinung schon auf einem sehr guten Weg zu dieser Erkenntnis. Ist es nicht nur ein kleiner Schritt von den Atomic und Composite Values (AV, CV) des IDM zu einem Datenmodell, welches ausschließlich durch (meinetwegen typisierten) AVs und typenlosen binären Beziehungen zwischen AVs definiert ist?

Die Graph-DBs machen das zwar im Grunde so, nur sind sie eben viel mehr als ein Modell für eine flexible Persistenz; z.B. InfoGrid zwingt einem ein bestimmtes Programmiermodell auf: Ich muss meine Objekte zu MeshObjects machen und Relationen dazwischen explizit mit „relate“ oder „unrelate“ herstellen oder aufheben. Klar, das muss sein, es ist ja auch ein richtiges DBMS mit Zustandsprotokollierung, Transaktionen und allem was dazugehört. Das brauche ich aber nicht immer. Oft reicht schon oft das LoungeRepository, welches aber durchaus auf „Datengranulat“ und einer „Relations-Kitt-Komponente“ die wieder Ordnung herstellt basieren kann.

(…Ich hoffe der Ralf ist mir nicht böse, dass ich hier eigenmächtig Zusammenhänge zwischen verschiedenen Artikeln und Projekten von ihm herstelle. Wenn ich falsch liege, bin ich bereit eines besseren gelehrt zu werden…)

Also „flexible Persistenz“ ohne BDUF ist hier das Kampfwort – wobei ich den Begriff „sich um die Ecke pinseln“ nur intuitiv verstehe :-) …

Mit dem Problem bin ich immer wieder in "meiner" Domäne konfrontiert: Design von Algorithmen für CAGD (Computer Aided Geometric Design). Ein bewährtes Berechnungsmodell ist hier die Boundary Representation (B-Rep) – ein Graph der topologische Beziehungen zwischen Knoten, Kanten, Facetten (Vertex, Edge, Face) beschreibt, die geometrische Elemente (Point, Curve, Surface …) referenzieren. Dieses Modell eignet sich gut für effiziente Algorithmen, die aber den ändernden Zugriff auf die Struktur des B-Rep Graphen voraussetzen. Was ich nicht will ist, dass mein Laufzeitmodell an ein Persistenz-Modell gebunden ist, dessen change tracking System jede Veränderung des Graphen protokolliert. Was ich brauche, ist eine Möglichkeit den erreichten Zustand der (vielen) B-Rep Graphen unter Beibehaltung von generierten oder vergebenen Identitäten ganz oder teilweise zu persistieren, vielleicht auch mal das Repository nach bestimmten Zusammenhängen und Ordnungen fragen. Dabei will ich bei meinem Domain-Modell keine Einschränkungen in Punkto Datenzugriff in Kauf nehmen, am liebsten möchte ich es auch von keinen wie-auch-immer gearteten Basis-Klassen oder Interfaces abhängig machen – gut, so etwas wie „object“ oder „RepositoryIdentity“ nicht mitgerechnet.

Mein bewährtes Modell für die Persistenz von solchen Daten lässt sich im Grunde wie folgt beschreiben: ein Objekt wird in ein AtomicValue mit Identität umgesetzt. Die Referenzen des Objekts zu anderen Objekten sind als identifizierbare gerichtete binäre Relationen zwischen AV mit Identität x und AV mit Identität y umgesetzt: r(i) = {av(x), av(y) }, fertig. Das Modell ist dann durch eine Menge von AVs und eine Menge von Relationen zwischen AVs vollständig beschrieben. Die Vorteile: 100%-tige Übereinstimmung mit meinem Domänenmodell, leichte Erweiterbarkeit, kaum Voraussetzungen an das Implementierungsmodell. Und: es lässt sich bei Bedarf leicht und effizient in jedes andere gängige Modell (Relational, Object-based..) umsetzten, was man von der anderen Richtung nicht behaupten kann...

Gruß,

Paul

serega hat gesagt…

Ralf, Flexibilität macht für sich allein auch keinen Sinn. Ich glaube, dass die Idee alles mit einem einzelnen Model zu beschreiben einfach nicht zielführend ist. Als ich in der Uni OOP studiert habe, war mir auch alles einfach - ein Auto hat vier Räder, ein Rad kann einem Auto gehören. Solche Modele sind aber aus dem Kontext gerissen und für sich allein sind die unsinnig. DDD hat dafür eine logische Lösung gefunden - nämlich BC. Innerhalb eines BCs ist es sehr unwahrscheinlich, dass die gewünschte Flexibilität gebraucht wird. Die monolitischen Modelen wird aber auch keine Flexibilität (in der Persistenz) retten können.

Das ist alles einfach meine Meinung. Vielleicht brauche ich einmal ein Beispiel erstmal zu sehen, wo die Flexibilität wirklich eine grosse Rolle spielt.

Sergey

Ralf Westphal - One Man Think Tank hat gesagt…

@Sergey: Klar, Flexibilität allein macht auch nicht glücklich. Aber ich sehe dort den Engpass.

Früher hatten wir ein großes Effizienzproblem. Das ist in vielen Fällen heute nicht mehr existent.

Früher wie heute haben wir aber ein Flexibilitätsproblem. Datenmodelle zu planen ist heute immer noch oft ein BDUF. Und dann sitzt man in der Tinte, weil man sich an ein Schema geheftet hat.

Deshalb glaube ich, dass ein Schema, das ja für Effizienz sorgen soll, eine Sache von Optimierung sein sollte. Im Umkehrschluss fängt man daher besser ohne Schema an. Und maximal ohne Schema scheint mir da der Gedanke einer Graphendatenbank wie skizziert, mit einem Relationenraum.

Bounded Contexts machen das Problem kleiner, aber nicht signifikant, glaube ich. Für einzelne BCs mag es dann mit einem Schema gehen. Aber warum sollte man sich darauf festlegen, wenn es ohne noch flexibler ist?

DokumentenDBs sind ein guter Schritt. Mein Gefühl ist, dass da noch ein bisschen mehr geht.

-Ralf

Ralf Westphal - One Man Think Tank hat gesagt…

@Paul: Hört sich plausibel an, was du schreibst. Ich freue mich, dass dir das Intuitive Datenmodell geholfen hat. Das sehe ich auch in der Nähe meiner aktuellen Gedanken.

Dass du Bezüge zw. meinen Postings herstellst, finde ich gut :-)

Wenn du sagst, dass du dein Domänenmodell nicht an ein Persistenzmedium binden willst, ist das genau richtig. Das macht dann zwar Mapping nötig - aber dadurch wirst du wirklich unabhängig. Ich sag ja: Mapping ist keine Last ;-)

Das LoungeRepo (oder auch RavenDB) sind aber noch nicht das, was ich derzeit suche. Darin haben ja Entitäten/Dokumente noch Beziehungen "in sich". Das scheint mir aber das Problem. Eine Vermischung von Daten-Concerns.

Deshalb überlege ich, mal prototypisch was anderes zu basteln. Eher eine GraphenDB. Sozusagen als Fingerübung auch für den Umgang mit Esent. Mal schauen...

-Ralf

Anonym hat gesagt…

Hallo,

Ja, im LoungeRepo haben Entitäten/Dokumente noch Beziehungen "in sich". Aber ist das aus der Sicht der Anwendung nicht ein Implementierungsdetail? Der Objektgraph auf der Anwendungsseite (auf den wir ja nicht verzichten wollen, oder?) sieht auf der Persistenzseite aus wie Säcke mit Datengranulat (ich mag die Metapher..) und die Ordnung-herstellende Menge von Relationen. Für den Anwender äußert sich das nur durch die Existenz von flexibleren Graph-DB-artigen Query-Schnittstellen... Beispiel folgt, kann auf dem PocketPC schlecht Code schreiben...

Gruß,

Paul

Ralf Westphal - One Man Think Tank hat gesagt…

@Paul: Im LoungeRepo werden eben keine Granulatkügelchen gespeichert, weil (!) die Entitäten sich noch referenzieren. Es gehört für mich zur Definition von Datengranulat, dass die Kügelchen selbst unabhängig voneinander sind. Ob ein Kügelchen neben einem anderen, weit oder nah dran liegt... das ist nicht "im Kügelchen", sondern eine Sache der Anordnung von außen. Die Beziehungen sehe ich nur als Beobachter von außen.

Das LoungeRepo ist also noch kein so allgemeiner Speicher, wie ich es mir vorstelle.

-Ralf

Anonym hat gesagt…

Hallo Ralf,

ich habe mich etwas unklar ausgedrückt... Ich weiss wie das LoungeRepo aufgebaut ist. In meinem Post habe ich an ein hypothetisches Datengranulat-basiertes "Business-class-Lounge-Repository" gedacht :-)

Gruss,

Paul