Modelle pro Datenbanktabelle?

11

Ich verwende Codeigniter und habe mich in einer ähnlichen Situation befunden, in der ich Modellmethoden wiederholt habe. Ich erstelle ein Modell pro Controller. Aber würde ich das Erstellen eines Modells pro Datenbanktabelle als bewährte Methode betrachten? Auf diese Weise werden Methoden nicht zweimal geschrieben.

Anstelle von Modell pro Controller oder mehreren kleinen Modellen, die gemeinsam genutzt werden.

Beispiel, wenn ich eine Modellmethode get_user ($ user_id) habe, könnte ich sie auf users_models.php schreiben ...

Einer der Nachteile, die ich dabei sehe, ist, dass ich möglicherweise mehrere Modelle aufrufen muss und nicht nur controllerername_models.php.

Könnte das Laden mehrerer Modelle, bei denen möglicherweise nicht mehrere Methoden von einem Controller verwendet werden, die Leistung und Geschwindigkeit beeinträchtigen? Was könnte der beste Weg sein, um dies zu beheben?

Hinweis: Es gibt ähnliche Fragen, die jedoch nicht den Grund des Modells pro Datenbanktabelle abdecken.

Howard Steff
quelle

Antworten:

8

Ich sage, dass ein Modell pro Tabelle nur Ihre Datenbank in einer Klassenstruktur neu erstellt. Es ist als anämisches Modell bekannt und wird als Anti-Muster angesehen. Das liegt daran, dass Klassen sowohl Daten als auch Verhalten haben sollen. Wenn Sie Ihre Modelle auf eine einzelne Tabelle beschränken, wo platzieren Sie den Code (Verhalten), der für Daten und Verhalten aus mehreren Tabellen erforderlich ist? Ihre Controller würden dann Modelle benötigen, die eines oder mehrere dieser "Tabellen" -Modelle verwenden ... Abgesehen von den grundlegendsten Apps profitieren Sie von diesem Ansatz also kaum oder gar nicht.

Marjan Venema
quelle
Nur ein kleiner Nachtrag - es wird von Martin Fowler als Anti-Pattern angesehen. Punkt hier. Er hat einige Einsichten in diesen Fall, aber das bedeutet nicht, dass es schlecht ist - anders als bei God Object, das ist fast immer schlecht, ist eine Struktur wie diese manchmal unglaublich nützlich und leicht zu handhaben. Ich halte das überhaupt nicht für ein Anti-Muster.
T. Sar
1
Zum Beispiel ist das "anämische Modell" SOLID-konform - ist es wirklich schlecht, ein Objekt mit einem einzigen Zweck zu haben (Daten speichern)? Während ich viele Dinge respektiere, die Mr. Fowler sagt, war dies Bullshit.
T. Sar
7

Im Allgemeinen sollten Sie Ihre Modelle nicht pro Tabelle oder pro Controller, sondern pro Geschäftsobjekt erstellen. Manchmal ist es vielleicht eine 1: 1-Beziehung zu Ihrer Tabellenstruktur oder zu Ihren Controllern, aber nicht notwendig.

In Ihrem Beispiel haben Sie möglicherweise eine users_modelKlasse, die von mehreren Controllern aufgerufen wird. Das ist in Ordnung und manchmal sogar wünschenswert. In den meisten Fällen bezieht die users_modelKlasse ihre Daten jedoch aus mehreren Tabellen.
Beispielsweise kann ( muss ) die last_login_dateEigenschaft der users_modelKlasse aus einer separaten Tabelle abgerufen werden, die eine Eins-zu-Viele-Beziehung zur Haupttabelle hat.user_auditusers

Und ich würde sagen, wenn Sie eine SQL-Tabelle pro Geschäftsobjekt haben, ist es höchstwahrscheinlich, dass Ihre Datenbankstruktur nicht normalisiert ist.

Dime
quelle
3

Ich stimme größtenteils der Antwort von Dime zu, dass Sie Ihre Modelle pro Geschäftsobjekt erstellen möchten. Die Probleme, die das Unternehmen zu lösen versucht, sollten die Erstellung der Modellklassen beeinflussen. In der Praxis habe ich festgestellt, dass das Erstellen eines Modells pro Tabelle ein guter Anfang ist. Ein ordnungsgemäß entworfenes Schema ahmt wahrscheinlich die Geschäftsprozesse nach, die Sie im Anwendungscode modellieren müssen - auch als Domänenmodell bezeichnet.

Die Verwendung einer Objekt- / relationalen Zuordnungsebene ist nützlich, damit Ihr Domänenmodell dieselben Beziehungen wie das Datenbankschema enthält, ohne dass wiederholte Aufrufe einer Datenzugriffsebene erforderlich sind. Schauen Sie sich Eloquent für PHP als Beispiel an. Sowohl das Schema als auch das Domänenmodell sollten so konzipiert sein, dass sie die Geschäftsprozesse unterstützen.

Dies führt zum ersten Teil von Marjan Venemas Antwort:

Ich sage, dass ein Modell pro Tabelle nur Ihre Datenbank in einer Klassenstruktur neu erstellt. Es ist als anämisches Modell bekannt und wird als Anti-Muster angesehen.

Ein anämisches Domänenmodell ist ein Anti-Muster. Ein "Modell pro Tabelle", wie Venema vorschlägt, könnte als "Neuerstellung Ihrer Datenbank" angesehen werden. Es ist jedoch absolut falsch zu sagen, dass dies allein ein anämisches Domänenmodell ist.

Von Martin Fowler:

Das Grundsymptom eines anämischen Domänenmodells ist, dass es auf den ersten Blick wie das Original aussieht. Es gibt Objekte, von denen viele nach den Substantiven im Domänenraum benannt sind, und diese Objekte sind mit den reichen Beziehungen und Strukturen verbunden, die echte Domänenmodelle haben. Der Haken kommt, wenn Sie sich das Verhalten ansehen und feststellen, dass diese Objekte kaum ein Verhalten aufweisen, sodass sie kaum mehr als Taschen voller Getter und Setter sind.

(Betonung, meine)

Der Schlüsselfaktor in einem anämischen Domänenmodell ist ein Mangel an Verhalten oder Methoden in den Domänenmodellklassen.

Das liegt daran, dass Klassen sowohl Daten als auch Verhalten haben sollen. Wenn Sie Ihre Modelle auf eine einzelne Tabelle beschränken, wo platzieren Sie den Code (Verhalten), der für Daten und Verhalten aus mehreren Tabellen erforderlich ist?

Auch hier können und sollten Sie Verhalten in Ihre Domänenmodelle einfügen, selbst wenn diese nur einer Tabelle zugeordnet sind. Verhalten, das mehrere Tabellen betrifft, wirkt sich tatsächlich auf mehrere Objekte aus, die zufällig mehreren Tabellen zugeordnet sind. Domain Driven Design ist ein Ansatz für genau dasselbe Problem, das Venema erwähnt hat: "Wo platzieren Sie den Code (Verhalten), der für Daten und Verhalten aus mehreren Tabellen benötigt wird?"

Und die Antwort ist eine aggregierte Wurzel . Martin Fowler erklärt:

Aggregat ist ein Muster im domänengesteuerten Design. Ein DDD-Aggregat ist ein Cluster von Domänenobjekten, die als eine Einheit behandelt werden können. Ein Beispiel kann eine Bestellung und ihre Werbebuchungen sein. Dies sind separate Objekte. Es ist jedoch nützlich, die Bestellung (zusammen mit ihren Werbebuchungen) als ein einzelnes Aggregat zu behandeln.

(Betonung, meine)

Ein "Cluster von Domänenobjekten" kann auch als "Domänenmodelle, die mehreren Tabellen zugeordnet sind" angesehen werden. Verhalten, das mehrere Tabellen betrifft, sollte im Aggregatstamm definiert werden - Eine Klasse, die das "Ding" kapselt, das mehrere Tabellen oder Objekte betrifft:

Nochmals von Martin Fowler:

Ein Aggregat enthält häufig mehrere Sammlungen sowie einfache Felder.

So beantworten Sie die ursprüngliche Frage des OP:

... würde das Erstellen eines Modells pro Datenbanktabelle als bewährte Methode angesehen werden? Auf diese Weise werden Methoden nicht zweimal geschrieben.

Ich würde sagen, dies ist ein guter Anfang, aber beachten Sie, dass Ihr Schema und Ihr Objektmodell nicht zu 100% übereinstimmen müssen. Das Objektmodell sollte sich mehr mit der Implementierung und Durchsetzung von Geschäftsregeln befassen. Das Schema sollte sich mehr auf die modulare und skalierbare Speicherung von Geschäftsdaten konzentrieren.

Ein Modell pro Controller wäre keine gute Praxis, obwohl es eine Modellvariante gibt, die als Ansichtsmodell bezeichnet wird und in die Controller-Ebene passt. Ein Ansichtsmodell ist eine Neuorganisation des Domänenmodells für eine bestimmte Art von Anzeige, sei es eine Webseite oder ein Formular in einer GUI-Anwendung.

Greg Burghardt
quelle