Ein MVC-Modell lose mit der DB verbunden halten?

9

Ich halte meinen Code gerne testbar und habe mich für die Dependency-Injection-Strategie für mein aktuelles MVC-Framework entschieden, die sich definitiv als eine großartige Möglichkeit erwiesen hat, lose gekoppelten Code, Testbarkeit und Modularität sicherzustellen.

Da ich jedoch weit davon entfernt bin, ein Meister in Designmustern zu sein, fällt es mir schwer, einen guten Weg zu finden, um meine Modelle so locker wie möglich von den Datenbank-Connector-Klassen zu koppeln.

Wie kann das gemacht werden?
Da ich zusammen mit dieser Frage keinen physischen Code angegeben habe, würde ich mich über einige Logik- / Codebeispiele oder Informationen freuen, die mich in eine Richtung weisen könnten, um das oben beschriebene Problem zu verstehen.

Industriell
quelle
Diese Frage gehört zum Software Engineering , da es mehr um die Strukturierung und das Denken rund um dieses Thema als um die Implementierung in Code geht.
Lasse V. Karlsen

Antworten:

6

Eine Möglichkeit besteht darin, Ihre Modelle zu entwerfen, bevor Sie Ihre Datenbank entwerfen. Beim Entwerfen Ihrer Modelle liegt der Schwerpunkt auf der Erfassung der Geschäftslogik und der Bedeutungen innerhalb der Problemdomäne. Dies sollte auf eine Weise erfasst werden, die für das Unternehmen sinnvoll ist und mehr als nur Entitäten und Datenfelder umfasst. Einige Datenelemente werden von anderen interpretiert, andere hängen von anderen ab usw. Zusätzlich würden Sie diesem Modell jede grundlegende Logik hinzufügen, die Sie benötigen, z. B. wie ein Objekt intern reagiert, wenn ein bestimmtes Element auf einen bestimmten Wert festgelegt wird.

Es ist sehr wahrscheinlich, dass Sie am Ende etwas haben, das zu 90% mit der Art und Weise identisch ist, wie Sie die Daten beibehalten. Das ist gut. Es kann völlig identisch sein, ohne gekoppelt zu sein.

Beachten Sie auch, dass das Modellieren der Domäne in einem Nebel wahrer Unwissenheit über die Persistenz ein heiliger Gral für das Software-Design ist. Wenn du es schaffst, fantastisch. Wenn die Problemdomäne jedoch überhaupt von Bedeutung ist und eine gewisse Komplexität aufweist, ist es immer noch eine gute Idee, von Zeit zu Zeit von der Domänenmodellierung zurückzutreten, um eine Überprüfung der Datenpersistenz durchzuführen, um sicherzustellen, dass Sie nicht gemalt haben dich in eine Ecke.

Denken Sie nur an die tatsächlichen Rollen der verschiedenen Komponenten und lassen Sie diese Rollen beim Entwerfen getrennt. Fragen Sie sich bei einer bestimmten Entwurfsentscheidung, ob eine dieser Rollen verletzt wird:

  1. Datenbank - Speichern Sie die Daten, bewahren Sie die Integrität der Daten und halten Sie die Daten in Ruhe.
  2. Modelle - Enthalten die Geschäftslogik, modellieren die Problemdomäne, halten die Daten in Bewegung, reagieren auf Ereignisse auf Unternehmensebene usw.
  3. Ansichten - Präsentieren Sie den Benutzern Daten, führen Sie eine benutzerseitige Logik durch (grundlegende Validierung, bevor eine echte Validierung in den Modellen durchgeführt wird usw.).
  4. Controller - Reagieren Sie auf Benutzerereignisse, übergeben Sie die Kontrolle an Modelle, leiten Sie Anforderungen weiter und geben Sie Antworten zurück.
David
quelle
Hallo David. Vielen Dank für Ihre ausführliche Antwort! Wie würden Sie die Modelle mit einem Datenbank-Connector verbinden, während Sie ein hohes Maß an losen Kopplungen beibehalten?
Industrial
1
@Industrial: Es gibt eine Reihe von Möglichkeiten, Modelle mit der Persistenz zu verbinden. Bisher habe ich jedoch nur eine Methode gefunden, die meinen Wunsch nach Trennung von Bedenken wirklich befriedigt, Repository-Schnittstellen in der Domäne zu haben, die extern von einem DAL implementiert werden. Die Repository-Methoden akzeptieren und geben Domänenmodelle zurück und konvertieren intern zwischen diesen und allen generierten Datenbankentitäten. (Um ehrlich zu sein, habe ich in PHP nicht so viel getan.) Sie können also ein DAL-Framework verwenden, um alle Ihre DB CRUDs usw. automatisch zu generieren und dann Ihre Repositorys als Schnittstelle zwischen diesen Dingen und Ihren Modellen zu schreiben.
David
@Industrial: Wenn Sie beispielsweise ein ORM verwenden, wird dieses ORM von Ihrem DAL (das von den Domänenmodellen isoliert ist) referenziert und Ihre Modelle werden entsprechend in Datenzugriff umgewandelt. Wenn Sie direkten Datenbankzugriff mit manuellem SQL durchführen, tun Sie dies in den Repository-Methoden Ihres DAL und übersetzen die Ergebnisse der SQL-Abfragen in Domänenmodelle, bevor Sie sie zurückgeben.
David
@Industrial: Beachten Sie auch, dass die Repository-Methoden nicht nur CRUD sein müssen. In diesen Code kann viel Intelligenz eingebrannt werden. Viele der komplexeren können viel internen Code enthalten, der Daten aus der Datenbank transformiert. Wenn die komplexen Daten viele Daten zur Datenbank umfassen, können Sie die Logik zur Leistungssteigerung in eine gespeicherte Prozedur einfügen, und die DAL-Methode geht einfach zu dieser Prozedur über und übersetzt die Ergebnisse in Modelle.
David
Hallo David! Ich wollte mich nur noch einmal für diese Antwort bedanken. Auf jeden Fall eines der besten, die ich auf StackExchange erhalten habe!
Industrie
2

Sie möchten zwei Dinge haben.

  1. Ihre Modelle (Accessoren für die DBAL und die meiste App-Logik).
  2. Ihre "Domain-Modelle", auch Datenentitäten genannt, repräsentieren die Entitäten Ihres Systems wie Benutzer, Beiträge, Produkte usw.

    class PPI_Model_User {
    
        protected $_conn = null;
    
        function __construct(array $options = array()) {
            if(isset($options['dsnData'])) {
                $this->_conn = new PPI_DataSource_PDO($options['dsnData']);
            }
        }
    
        function getAll() {
            $rows = $this->_connect->query("SELECT .....")->fetchAll();
            $users = array();
            foreach($rows as $row) {
                $users[] = new PPI_Entity_User($row);
            }
            return $users;
        }
    
    }

Verwendungscode

    $model = new PPI_Model_User(array('dsnData' => $dsnData));
    $users = $model->getAll();
    foreach($users as $user) {
        echo $user->getFirstName();
    }

Dort haben Sie es, auf diese Weise erstellen Sie Domänenmodelle (Entities) und lassen MVC-Modelle die DB-Konnektivität und Datenmanipulation durchführen.

Wenn Sie sich fragen, was PPI ist, suchen Sie bei Google nach "PPI Framework".

Viel Glück bei Ihrer Suche.

Grüße, Paul Dragoonis.

Paul Dragoonis
quelle
1

Denken Sie daran, dass MVC in Smalltalk entstanden ist, das für alle Objekte automatisch persistiert. Das MVC-Muster schreibt also keine Lösung für die Trennung von Modell und Persistenz vor.

Ich bevorzuge die Bereitstellung eines "Repository" -Objekts, das weiß, wie Modellobjekte aus der Datenbank erstellt und Modellobjekte in der Datenbank gespeichert werden. Dann weiß das Modell nichts über Persistenz. Einige Benutzeraktionen müssen jedoch einen Speichervorgang auslösen, sodass der Controller wahrscheinlich über das Repository Bescheid weiß. Normalerweise verwende ich eine Form der Abhängigkeitsinjektion, um zu verhindern, dass der Controller mit dem Repository gekoppelt wird.

Sean McMillan
quelle