Hallo frankx,
Prozedural ist sie, weil sie selbst keine Eigenschaften hat?
Ja so ungefährt. Sie repräsentiert ja auch kein konkretes Objekt wie "Benutzer" sondern nur etwas sehr technisches wie "Datenbankschnittstelle". Natürlich gibt es auch immer solche technischen Objekte, bei Dir gibt es aber nur solche technischen Objekte.
"Muss" ich jedes mal "new Benutzer($id)" machen oder innerhalb der Gruppe "new Gruppe ($groupName)" werden dann die Benutzer nach ihrer Gruppenzugehörigkeit geladen?
Naja bei ORM-Ansatz würdest Du die Objekte aufbauen, als ob es keine Datenbank gäbe:
class Benutzer {
String name;
Gruppe gruppe;
...
}
class Gruppe {
String name;
Benutzer[] benutzer;
...
}
Dann würde man zusätzlich noch irgend welche Zusatzinformationen in den Code oder in eine zustäztliche Configurationsdatei schreiben, die z.B. festlegen, dass Gruppe.bennutzer das gegenstück zu Benutzer.gruppe ist.
Wenn man dann orm.execute("from Bentzer where name='foo') ausführt, würde man ein Benutzer-Objekt erhalten. Je nach Konfiguration wurde da die Gruppe gleich mit geladen oder auch noch nicht.
Der ORM manipuliert den Code der Klassen (jedenfalls macht das Hibernate für Java so), sodass, wenn man dann benutzer.getGruppe() oder gruppe.getGruppen() aufruft, das entsprechende SQL-Query ausgeführt wird, ohne dass man das selbst implementieren müsste. Man kann also weitgehend so programmieren, als gäbe es gar keine DB.
Außerdem hat man eben diese Objekt-Query-Sprache, mit der man dennoch sehr effiziente Abfragen formulieren kann.
Das Modell auszutauschen ist meist nicht sinnvoll.
Das Modell meint jetzt die Datenstruktur und ihre Zusammenhänge (Benutzer mit all seinen Eigenschaften, Gruppen mit ihren n->m Relationen) oder mein Modell die Art der Speicherung (XML, SQL)?
Modell meint ersteres. Das Model ist eine logische Darstellung der Dinge, mit denen das Programm eigentlich arbeitet. XML oder eine Datenbank haben damit erst einmal nichts zu tun.
Nicht wissen muss der Contoller wohl, wie die DB heißt und wie er sich damit verbindet.
Richtig, Modell meint hier aber wirklich die logische Struktur und das logische Verhalten, nicht die Form der Speicherung. Und diese Struktur muss ein Controller ja kennen.
Meist muss er auch noch etwas über die Speicherung wissen, ob da irgendwie eine Datenbank, Dateien oder sonst irgend etwas dahinter steckt, macht oft einen unterschied. Eine Datenbank erlaubt z.B. Transaktionen, es gibt mehrere Benutzer die gleichzeitig Änderungen vornehmen könnnen, es können bestimmte Fehler auftreten. Solche Eigenschaften wirken sich doch meist auch auf den Controller aus. Welche Datenbank das ist, ob es XML-Datein oder ein anderes Format ist etc. spielt aber keine Rolle.
Vom "Model" würde er wohl eben eine ResourceHandle erwarten, und dann die entsprechenden Queries machen, zumindest eine Variante, die mir in einer ZF-Beispielanwendung unter kam.
Ja, so einen Einstiegspunkt benötigt man natürlich immer. Selbst wenn man sich nur von Objekt zu Objekt hangelt, muss man ja mal irgendwie das erste Objekt abrufen. Beim ORM-Ansatz gibt es da ja auch immer ein Objekt hinter dem sich letztenendes die DB-Verbindung bzw. die Transaktion verbergen.
Mh, was ist daran "nützlich"?
Nützlich ist, dass man effiziente Queries direkt auf Objekt-Ebene formulieren kann und nicht doch wieder irgendwo SQL schreiben und seine Objekte von Hand zusammensetzen muss. Abgesehen davon, dass SQL teilweise von der DB abhängen kann.
Und wieso ist man nicht so sicher, was da passiert?
Naja, man weiß nicht genau, was für SQL-Queries entstehen. Wenn man z.B. ein Query bezüglich einer Schnittstelle oder abstrakten Klasse macht, kann es sein, dass da mehrere Subqueries für die Tabellen konkreter Klassen abgesetzt werden. Das kommt auch darauf an, wie die Vererbungshierarchie auf Tabellen abgebildet wird. Das ist etwas, was man dem Query nicht gleich ansieht, was man aber natürlich schon ungefähr wissen sollte, aber am Anfang eben nicht unbedingt weiß.
Model->getList("Benutzer) würde ein Array of SimpleXMLObjekts zurückgeben zB.. Model->get($Benutzer, $id) ein SXO des Benutzer mit der genannte ID. Ich könnte natürlich auch eine Benutzer-Klasse haben, die im Konstruktor die $id verwurstet (s.o.) und dann mit $Benuter->getName() dessen Namen ausgibt oder mit $Benutzer->update($params = array()) gewisse Eigenschaften setzt.
Ja, letzteres wäre der "übliche" Weg. Wobei der Code zur Verarbeitung von XML eigentlich nicht in den Modell-Klassen stehen sollte, sondern in einer Bibliothek, sodass man so etwas machen kann:
Model model = XMLSerialization->read(file);
Benutzer name = model.getBenutzer("name");
...
XMLSerialization->write(model, file);
Das heißt, die Modelklasse weiß nur, wie sie ein ResourceHandle herstellt?
Die Modelklasse_n_ wissen im Idealfall nur, wie das Modell logisch aufgebaut ist. Das Abbilden zwischen Modell und XML übernimmt eine Bibliothek.
Da man bei Datenbanken dieses einmalige Auslesen und Speichern wegen der Datenmenge nicht machen kann, kann man da SQL in die Modellklassen packen, das ist aber wie gesagt auch nur eine Behelfslösung. Nach der "reinen Lehre" sollte ein Modell völlig unabhängig von der Speicherung sein.
Also zB. dass die Datei für "Benutzer" "BenutzerData.xml" heißt und im Ornder "data" liegt? Das muss der Controller ja nicht wissen, oder?
Richtig, diese Information liegt aber eigentlich ganz außerhalb der MVC-Klassen. Entweder hat man irgendwo noch einen Singleton rumfahren, der diesen Einstiegspunkt zur Verfügung stellt. Sowas in der Art:
Model model = Storage.getInstance().read();
Storage.getInstance().save(model);
Oder man hat irgendwo einen Programmteil, der dafür zuständig ist, den Controller zu instanzieren, und man kann an dieser Stelle ein "ResourceHandle" erzeugen und als Parameter mit geben.
Bei Desktopprogrammen muss der Controller auch oft wissen, wo die Daten gespeichert werden, da es sich bspw. um Dokumente handelt, die man mit dem Programm bearbeitet.
Oder Single-Responsibility-Prinzip?
So könnte man es wohl auch nennen. "Coupling and Cohesion" sind die klassischen, akademischen Bezeichnungen und wurden 1974 von irgend welchen IBM-lern eingeführt oder so. Hat also erstmal nichts mit objektorientierung zu tun ;-)
Nein, das war mir auch schon klar. Ich dachte halt, dass - vielleicht klappt das nur im kleinen Rahmen - der Conroller eben nur die Requests an die entsprechende Abfrage weitergibt.
Ja, ich denke das klappt ganz gut, so lang man das Objektmodell nicht wirklich braucht und man die Anwendung entweder nicht so funktional gliedern muss oder die Komponenten so unabhängig sind, dass es dazwischen ohnehin kaum Verknüpfungen gibt.
In meinem Fall wären das zB. Artists, Locations, Agencies, oder aber Schüler, Lehrer, Eltern. Die Profilanzeige würde sich aus den Eigenschaften ergeben und wäre ja eh Sache der View, Listenausgabe ungefiltert ist auch ident, und deshalb die Idee mit dem ->getList(). Der Controller könnte dann u.U. noch die Zugangsberechtigung checken (darf der und der das und das anzeigen, was bei Artists/Locations/Agencies weniger der Fall wäre, bei einem schulinternen(!) "...VZ" schon eher).
Ja, sowas könnte man evtl. auch in eine Schicht zwischen Controller und Model legen. Hier bekommt man aber auch schon wieder Probleme damit, dass man eine DB hat. Üblicherweise würde man Berechtigungen wohl im Model abhandeln, so nach der Art:
benutzer.getDetails(benutzer2);
Da würden dann die Rechte geprüft für benutzer2 und gegebenfalls ein Fehler zurückgegeben. Bei einer Datenbank will man aber evtl. auch das Berechtigungssystem der Datenbank nutzen, um Daten zu schützen. Wenn man dem Controller außerdem erlaubt, direkt Queries abzusetzen, muss man dafür auch noch die Rechte prüfen. Eine Lösung wäre vielleicht eine Zwischenschicht, sodass man die Rechtekonrolle zumindest an einer Stelle implementieren kann. Wenn man die verteilt, macht man leichter Fehler.
Heißt, zum Lernen gut, aber nicht optimiert?
Nein, das heißt, man bekommt schonmal den Modell-Code, die ganzen SQL-Queries und das Aufbauen des Modells muss man aber noch selber schreiben.
Auha, ich dachte, irgendwann hört das mal auf mit dem immer nochwas dazulernen müssen (;-).
Ich glaube nicht ;-)
Na RoR baut doch gleich die Datenbank im Hintergrund auf, wenn ich das recht kapiert habe.
Ja, aber ja Aufgrund des eigenen Klassenmodells, ob man nun das Klassenmodell aus dem Datenbankmodell oder umgekehrt erzeugt, ist ja erstmal egal. Klassenmodelle aus dem Datenbankmodell zu erzeugen, ist eigentlich nur dann interessant, wenn man das Datenbankmodell vorgeschrieben bekommt, weil man z.B. eine bestehende Datenbank verwenden muss.
http://de.wikipedia.org/wiki/XML-RPC noch so ein Fremdwort (;-).
Naja, klingt geheimnisvoller, als es ist. Letztenendes werden einfach nur Daten und Funktionsaufrufe einer Spracher über ein Netzwerk transportiert. Man kann damit recht schön verteilte Anwendungen schreiben, ohne selbst irgend welche Protokolle implementieren zu müssen.
Grüße
Daniel