Mantenere un modello MVC liberamente accoppiato dal DB?


9

Mi piace mantenere il mio codice testabile e ho deciso di seguire la strategia di Dependency-Injection per il mio attuale framework MVC, che ha sicuramente dimostrato di essere un ottimo modo per garantire codice, testabilità e modularità liberamente associati.

Ma essendo tutt'altro che un maestro nei modelli di progettazione, ho difficoltà a trovare un buon modo per mantenere i miei modelli il più vagamente accoppiati dalle classi di connettori del database, il più possibile.

Come può farlo?
Poiché non ho fornito alcun codice fisico insieme a questa domanda, apprezzerei davvero alcuni esempi o informazioni di logica / codice che potrebbero indirizzarmi verso una direzione per comprendere il problema sopra descritto.


Questa domanda appartiene all'ingegneria del software , in quanto riguarda più la strutturazione e il pensiero attorno a questo argomento, più che l'implementazione nel codice.
Lasse V. Karlsen,

Risposte:


6

Un modo è progettare i modelli prima di progettare il database. Durante la progettazione dei modelli, l'attenzione è focalizzata sull'acquisizione della logica aziendale e dei significati all'interno del dominio problematico. Ciò dovrebbe essere acquisito in modo sensato per l'azienda, includendo più di entità e campi di dati. Alcuni elementi di dati vengono interpretati da altri, alcuni dipendono da altri, ecc. Inoltre, si aggiunge a questo modello qualsiasi logica di base necessaria, ad esempio il modo in cui un oggetto risponde internamente quando un determinato elemento è impostato su un determinato valore.

È del tutto probabile che finirai con qualcosa che è identico al 90% in più a come finisci per conservare i dati. Va bene. Può essere completamente identico senza essere accoppiato.

Nota anche che modellare il dominio in una nebbia di vera persistenza l'ignoranza è un po 'un santo graal per la progettazione del software. Se ce la fai, fantastico. Ma se il dominio problematico è del tutto significativo e presenta qualche complessità, è comunque una buona idea tornare di tanto in tanto dalla modellazione del dominio per fare un controllo di integrità sulla persistenza dei dati per assicurarsi di non aver dipinto te stesso in un angolo.

Basta ricordare i ruoli effettivi dei vari componenti e tenerli separati durante la progettazione. Per qualsiasi decisione di progettazione, chiediti se uno di questi ruoli viene violato:

  1. Database: archivia i dati, mantiene l'integrità dei dati, conserva i dati a riposo.
  2. Modelli: contiene la logica aziendale, modella il dominio problematico, mantiene i dati in movimento, risponde a eventi di livello aziendale, ecc.
  3. Viste: presenta i dati agli utenti, esegue la logica lato utente (convalida di base prima che venga eseguita la vera convalida nei modelli, ecc.).
  4. Controller: risponde agli eventi dell'utente, passa il controllo ai modelli, instrada le richieste e restituisce le risposte.

Ciao David. Grazie per la tua ampia risposta! Pur mantenendo un elevato livello di accoppiamenti sfusi, come collegheresti i modelli con un connettore per database?
Industriale

1
@Industriale: ci sono diversi modi per connettere i modelli alla persistenza, ma finora l'unico metodo che ho trovato che soddisfa veramente il mio desiderio di separare le preoccupazioni è avere interfacce di repository nel dominio che sono implementate esternamente da un DAL. I metodi di repository accettano e restituiscono modelli di dominio e si convertono internamente tra questi e tutte le entità di database generate. (Ad essere sincero, non ho fatto molto in PHP.) Quindi puoi usare un framework DAL per generare automaticamente tutto il tuo CRUD DB, ecc. E poi scrivere i tuoi repository come interfaccia tra quella roba e i tuoi modelli.
David,

@Industriale: ad esempio, se si utilizza un ORM, tale ORM verrebbe referenziato dal DAL (che è isolato dai modelli di dominio) e trasformerebbe i modelli in accesso ai dati di conseguenza. Oppure, se si accede direttamente al database con SQL manuale, lo si farebbe nei metodi di repository del DAL e tradurrebbe i risultati delle query SQL in modelli di dominio prima di restituirli.
David,

@Industrial: tieni presente anche che i metodi di repository non devono essere solo CRUD. Molta intelligenza può essere inserita in quel codice. Molti di quelli più complessi possono avere un sacco di codice interno che trasforma i dati dal database. Oppure, se quelli complessi comportano molti viaggi nel database, per ottenere miglioramenti delle prestazioni è possibile inserire la logica in una procedura memorizzata e il metodo DAL passa semplicemente a quella procedura e traduce i risultati in modelli.
David,

Ciao David! Volevo solo ringraziarti di nuovo per questa risposta. Sicuramente uno dei migliori che ho ricevuto su StackExchange!
Industriale

2

Vuoi avere due cose.

  1. I tuoi modelli (accessi al DBAL e esecuzione della maggior parte della logica dell'app).
  2. I tuoi "modelli di dominio", ovvero entità dati, rappresentano le entità del tuo sistema come utenti, post, prodotti ecc.

    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;
        }
    
    }

Codice d'uso

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

Ecco fatto, ecco come creare modelli di dominio (Entità) e avere modelli MVC che eseguono la connettività DB e la manipolazione dei dati.

Se ti stai chiedendo cosa sia PPI, cerca Google "PPI Framework".

Buona fortuna con la tua ricerca.

Saluti, Paul Dragoonis.


1

Ricorda, MVC è nato in smalltalk, che ha la persistenza automatica per tutti gli oggetti. Quindi il modello MVC non prescrive alcuna soluzione per la separazione modello / persistenza.

La mia preferenza è di fornire un oggetto "Repository" che sappia come creare oggetti Model dal database e archiviare oggetti Model nel database. Quindi il Modello non sa nulla della persistenza. Tuttavia, alcune azioni dell'utente dovranno attivare un salvataggio, quindi è probabile che il Controller sia a conoscenza del repository. Di solito utilizzo una qualche forma di Dependency Injection per impedire al Controller di essere accoppiato al Repository.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.