2012-03-15 22 views
7

Diciamo che per ogni entità di dominio, ho un repository che fornisce un'API a un mappatore di dati. Ad esempio, se ho un UserEntity, avrei un UserRepository che parla con un UserMapper per mantenere i dati utente in un database.Dove creare nuove entità di dominio? Controller, repository o mapper?

Ora, supponiamo che un modulo venga inviato su una pagina Web e che il mio controller sappia che è necessario creare un nuovo UserEntity in base alle informazioni inviate.

lo fa:

  1. fare nuova UserEntity() proprio lì sul posto, ed eseguire tutti i metodi setter necessari in base ai dati del modulo presentati, quindi passare l'UserEntity al pronti contro termine, che passa a il mapper per l'inserimento?

    controllore crea UserEntity => Repo => Mapper => DB

  2. trasformare i dati del modulo in un array, e passarlo al UserRepository che poi gestisce nuova UserEntity() e setter, e lo passa a il mapper per l'inserimento?

    controller passa dati utente => Repo crea UserEntity => Mapper => DB

  3. passare la matrice al UserRepository, che passa la matrice per il mapping per il nuovo UserEntity e l'inserimento?

    controller passa dati utente => Repo passa dati utente => Mapper crea UserEntity => DB

chi è la responsabilità di gestire la creazione di oggetti?

risposta

1

Questa è una domanda difficile a cui rispondere. I miei due centesimi sono al numero 1 per un paio di motivi. In primo luogo, si presume che tu abbia la convalida del dominio nella tua entità che potrebbe benissimo rifiutare i dati che vengono trasmessi. Se ciò dovesse accadere in 2 o 3, hai fatto alcuni oggetti in profondità prima del rifiuto. Potrebbe non esserci molta memoria o tempo di esecuzione in termini di differenza tra 2/3 e 1, ma è una differenza. Cerco di fallire velocemente.

In secondo luogo, penso che il controller che conosce i dati trasmessi e gli oggetti sia del tutto accettabile. Sono d'accordo con "modello grasso, controller magro" ma dicendo che il controller non può sapere delle entità sta facendo il controller troppo magro per i miei gusti.

+0

Questa è una grande analisi della situazione. Sono curioso di sentire altri pensieri, ma penso che sia certamente accettabile crearlo nel controller. Tuttavia, forse meno flessibilità? Ad esempio, se aggiungo un nuovo campo alla tabella Utente nel DB, devo quindi ricordare di andare a ciascun Controller che crea UserEntities. – johnnietheblack

+0

Molto probabilmente modificherete la vista che accetta dette nuove informazioni (supponendo che stiamo parlando di un'applicazione web tradizionale), la modifica del controller non è eccessiva. Le probabilità sono se hai dimenticato di modificare il controller che hai dimenticato di modificare la vista. Inoltre, una semplice ricerca globale può trovare dove viene utilizzata la tua classe. – Crashspeeder

+0

Un altro buon punto, e se Controller è la risposta, allora non sono turbato ... ma ancora, c'è una parte di me che si sente "colpevole" a scrivere lo stesso processo di istanziazione in diversi punti. No? Allo stesso modo, ho impostato le mie viste in modo che per aggiungere campi modulo che rifletterebbero la nuova modifica della tabella sarebbe necessario modificare solo un singolo file. – johnnietheblack

2

So che questa domanda è vecchia, ma ho pensato di buttare qui i miei pensieri poiché l'unica risposta non è stata accettata ufficialmente e questo potrebbe essere utile per i futuri utenti. Per rispondere direttamente alla tua domanda, direi nessuno dei precedenti. Preferisco avere un servizio extra, un "manager", se lo desideri, per intercalare l'interazione tra il controller e gli oggetti repo/mapper. Ogni modello ha un gestore dedicato per gestirne la creazione, gli aggiornamenti e la cancellazione.

Controller

mi considerano il controller come il collante della domanda. Possiamo separare tutte le preoccupazioni che vogliamo in quanti più pezzi possibile, ma da qualche parte lungo la linea, qualcosa deve capire sia il lato della vista che il lato del modello, e quell'oggetto è il controller. Detto questo, credo che i controller dovrebbero essere magri, quindi l'unico vero compito del controller è di mappare una richiesta a una risposta. Qualsiasi tipo di elaborazione intermedia dovrebbe essere avviata altrove.

In un'applicazione CRUD, è abbastanza facile scappare con la creazione di istanze di nuovi oggetti e la loro permanenza nel controller, anche se viene eseguita più di una volta, perché sono solo alcune righe da incollare. E se la creazione di oggetti non fosse banale? Sto mantenendo un'applicazione con molte relazioni complesse e una creazione inviata dall'utente spesso implica la creazione di molti oggetti contemporaneamente. Non è fattibile mantenerlo in un ambiente con solo controllore e modello.

extra livelli di servizio

Per gestire questo, ho creato 2 strati di servizi aggiuntivi: FormHandler e Manager. Ogni volta che viene inviato un modulo, i contenuti del modulo vengono inviati al livello del gestore del modulo. I gestori di moduli sono responsabili della comprensione dei dati del modulo in arrivo e della normalizzazione. I gestori di moduli possono quindi trasferire i dati agli oggetti gestore appropriati per l'elaborazione. Gli oggetti Manager elaborano i dati e aggiornano il livello del dominio. Sono responsabili della creazione di modelli, della modifica dei modelli e della loro permanenza nel back-end.

In questo modo, i controller sono a conoscenza di richiesta, risposta, modulo (eventualmente, se il framework supporta la creazione di moduli sul lato server) e FormHandler. I gestori di moduli hanno conoscenza del modulo (o dei dati del modulo) e del responsabile. Manager ha conoscenza di repository, mapper e model. Nota, ora, i Manager sono l'unico punto di interazione con i Modelli e il Mappatore e non hanno alcuna conoscenza dei dati del Modulo o della Richiesta o Risposta. D'altro canto, i controllori e i gestori di moduli non hanno bisogno di conoscere i dati o la persistenza del livello del dominio.

Conclusione

Con questo disegno:

Controller -> FormHandler -> ModelManager -> Mapper

ho trovato tutte le mie classi sono ora unit-testabili (anche i controller in una certa misura) a causa di separazione degli interessi che sono ben diviso, e il singolo punto di interazione è un vantaggio per evitare la logica duplicata.

Note

Il repo nella mia mente è solo per interrogare il database - chiedendogli se ha qualcosa, non la creazione di cose nuove.

La mia esperienza in questo caso è da utilizzando Symfony 2 e Dottrina 2.

YMMV; per esempio. è possibile che il livello del modulo non sia necessario, ma l'ho trovato molto utile per la trasformazione dei dati da dati di visualizzazione/modulo in qualcosa che i modelli di dominio comprendono.

Problemi correlati