2014-05-08 11 views
10

Mentre facevo una domanda sulle convenzioni di denominazione dei modelli singolari/plurali di ieri, ho riscontrato il concetto di un modello di dominio. A quanto ho capito finora, un modello di dominio è semplicemente un oggetto che rappresenta un'entità nella mia applicazione.Modelli di dominio PHP, DAO e modalità di implementazione

Per usare un esempio molto semplice, qualcosa di simile:

class User { 

    private $name; 

    public setName() {} 
    public getName() {} 

} 

Ora, la domanda sorge spontanea, come faccio a popolare questo "Domain Model", o da qualche fonte di ingresso, di da un database o origine dati?

Mentre leggevo su Modelli di dominio, ho avuto l'impressione che non ci fosse altro che una rappresentazione del concetto di Dominio in questione all'interno di essi. Quindi ora avrò bisogno anche di un'altra classe (DAO?) Responsabile per l'interazione con l'origine dati, in questo caso una tabella di database chiamata "Utente". La mia classe DAO gestirà inserimenti, aggiornamenti, eliminazioni e più recuperi.

sono arrivato fino a questo approccio per la compilazione di un utente del dominio del modello da input, in questi dati caso postali, e quindi salvare il record al database, con una classe UserDAO:

/** 
* Populating Domain Model from input, and saving to database 
*/ 

/** Instantiate User Domain Model, and populate it from input */ 
$user = new User(); 
$user->setName($_POST['name']); 

/** Creating a new database record from User Domain Model */ 
$userdao = new UserDAO($pdo); 
$userdao->insert($user); 

Ed ecco come ho anticipato l'interazione con il database quando ho bisogno di recuperare i dati, in questo caso più record utente:

/** 
* Fetching data from database to populate User Domain Models in an array 
*/ 

/** Instantiate new UserDAO object to interact with User table */ 
$users = new UserDAO($pdo); 
$users->findAll(); 

$user_collection = []; 

/** Loop UserDAO object set to populate user collection array */ 
foreach ($users as $user) { 

    /** Create new User domain object from row, and add to collection array */ 
    $user = new User($user); 
    $user_collection[$user->name()] = $user; 

} 

sembra che l'unico vero vantaggio è organizzazione.

La mia iterazione corrente ha essenzialmente una classe utente che assume tutte le responsabilità della classe UserDAO di cui sopra, e restituisce direttamente gli array di dati dal database, che poi utilizzo nei miei "Controller"/"Presentatori" e che gocciolare attraverso le mie viste (passive).

Quello che mi chiedo è:

  1. Sono sulla strada giusta?

  2. Dove si trova la convalida dell'input? Presumo che debba andare nel modello di dominio, se ho ragione nelle mie supposizioni finora?

  3. Qual è il vantaggio di utilizzare questa tecnica, oltre ad aiutare ad organizzare i concetti di base su cui l'applicazione si baserà e opererà? Perché ho bisogno di questo strato aggiuntivo invece di operare direttamente sui risultati dell'array dal DB?

+0

Io chiamo i miei handler di classi DAO, ad esempio "User_handler". Questi gestori popolano i modelli di dominio e accettano set di dati per inserti o aggiornamenti. La convalida dell'input viene eseguita nei miei controller. – Timmetje

+0

* fortemente * correlato: http://stackoverflow.com/questions/5863870/how-should-a-model-be-structured-in-mvc/5864000#5864000 – ircmaxell

risposta

24

La chiave qui è quello di guardare quali classi dovrebbero avere che le responsabilità e, in particolare, che sono necessari responsabilità per rendere la vostra funzione di dominio.

Domain User Object

dovrebbe essere responsabile per te raccontare il suo stato rispetto alle regole di business utili della vostra applicazione (isAdmin(), isBanned(), isSuspended(), getWarnLevel()). Pensa a questo oggetto come un bucket API. Cosa vuoi sapere a riguardo? Quali informazioni utili può rivelare? Costruisci un'API che risponda a queste domande. Fai attenzione a non lasciare che l'Utente ti dica troppo su altri oggetti nel sistema. Questo non dovrebbe essere una sua responsabilità.

si preoccupa:

  • raccontandovi stesso
  • Gestire il proprio stato

non si preoccupa

  • Sia che si ottiene persisteva
  • Come è fatto
  • qualsiasi altro oggetto (a meno che non si tratta di una radice aggregato)
  • sacco di altre cose

User Repository

Una classe responsabile di aver permesso di recuperare e persistere completamente formato, esistente Users. Forse rimangono solo in memoria durante la richiesta corrente. Forse rimangono nel cache. Forse persistono in MySQL. Non importa. Tutto ciò che fa è permetterti di ottenere utenti e persisterli. Questa è la sua responsabilità. Può, ma non deve, conoscere il meccanismo di persistenza. Ha solo bisogno di sapere come utilizzare il meccanismo di persistenza.

(findById($id), findByEmail($email), findBanned(), findByCriteria($Criteria) - buon candidato per la strategia o il motivo specifica, save($User), delete($User)). Ancora una volta, la chiave qui è creare un'API che soddisfi le regole aziendali del dominio. Hai bisogno di trovare un utente per email? Quindi rendilo un punto di accesso esplicito nel repository. Se non hai bisogno, allora non farlo. Come è necessario trovare Users? Rispondilo con un'API.

si preoccupa

  • Le consente di accedere a oggetti utente esistenti in base a qualsiasi criterio arbitrario
  • invocando il meccanismo di persistenza che hai fornito è

non si preoccupa

  • Come funziona esattamente User oggetti vengono mantenute
  • Fare User oggetti
  • sacco di altre cose

fabbrica User

UserRepositories sono valide per usi User oggetti esistenti, ma come si fa a creare loro in il primo posto? Con le fabbriche Queste possono essere semplici fabbriche, che rendono solo un tipo di utente. Oppure possono essere fabbriche astratte, che rendono diversi tipi di utenti.Questo dipende da te e da ciò che i tuoi sistemi hanno bisogno. Ancora una volta, pensa in termini di quali API sono necessarie per soddisfare le regole di business del tuo dominio: (make($type, $data), makeAdmin($data), makeMember($data)). La sintassi dell'operatore variadic di PHP 5.6 renderà questo WAY più pulito per funzionare con btw.

si preoccupa

  • Fare lucido nuovo Users

non si preoccupa di

  • La fonte dei dati per fare quelle nuovissimo Users
  • Quello che fai con il User dopo che è fatta
  • sacco di altre cose

User Gateway/Mapper

Questo potrebbe essere il vostro meccanismo di persistenza attuale: potrebbe interfacciarsi direttamente con un database relazionale, fare uso di una fabbrica e abituarsi al deposito. Effettua il recupero effettivo del database e mappa i dati in un formato che può essere digerito dalla fabbrica. La factory non dovrebbe essere responsabile di questa mappatura perché non dovrebbe avere alcuna conoscenza del formato sorgente, ma solo del formato necessario per assemblare l'oggetto dominio. Quindi la responsabilità della mappatura sta nel Gateway/Mapper.

si preoccupa

  • Qualora il User sta ottenendo ostinava a/Estratto da, e come
  • Traducendo che i dati da persistenza a qualcosa di un fabbrica vuole
  • si preoccupa probabilmente circa un fabbrica

Non interessa

  • Il driver di archiviazione specifico (ad es. MySQL, Postgres) - questo è dove entra in gioco DOP
  • Creazione di una nuova User oggetto
  • sacco di altre cose

Ora, è vero questo sembra il modo più semplice di quanto non sia in realtà. Come gestisci i figli degli aggregati (ad esempio i molti Comments che appartengono a uno Post)? A che punto li dai allo Post? Glielo chiedi sempre o solo quando lo chiedi esplicitamente (ad es. Tramite una richiamata?) Queste sono domande difficili a cui non ho le risposte e che sono parzialmente soddisfatte dalle esigenze del tuo dominio in il primo posto.

ORM è un problema difficile da risolvere. La dottrina e la eloquente sono eccellenti, ma non seguono strettamente lo schema sopra. Va bene però. Il modello sopra è una linea guida, non una regola. L'obiettivo è concentrarsi sulla separazione delle preoccupazioni e sulla responsabilità focalizzata.Potrebbe non essere necessario per la tua applicazione avere tutti questi livelli.

Per quanto riguarda la convalida, ci sono due tipi di convalida:

  1. ingresso Form Validation

  2. convalida oggetto Dominio

validazione dei form di solito è meglio farlo da una classe Form Validator e alcune regole definite in modo specifico per un dato modulo. Di solito puoi definire tali regole in qualsiasi classe di build che hai (ad esempio Form::text('first_name', array('rules' => 'required|alpha'))). Il controllore deve prendere il validatore del modulo come dipendenza, ma non dovrebbe fare la validazione vera e propria.

La convalida degli assembly di domini di dominio (ad esempio, la protezione dell'integrità del modello) può vivere sia nell'oggetto dominio stesso tramite i setter, sia che può vivere in fabbrica. Questo dipende interamente da come si progetta di costruire oggetti di dominio.

Si noti che è necessario avere ENTRAMBI i tipi di convalida: convalida modulo per convalidare l'input e convalida dell'oggetto dominio per convalidare l'integrità dei dati quando si crea l'oggetto.

+0

Grazie per la fantastica risposta! È molto utile :) – ineedhelp

Problemi correlati