8

Ho letto su più framework PHP, in particolare su Zend Framework, ma mi sto confondendo sul modo corretto di andare avanti.Il modello DataMapper interrompe MVC?

Zend Framework non utilizza ActiveRecords ma utilizza il modello Table Data Gateway e Row Data Gateway e utilizza un DataMapper per mappare il contenuto del Row Data Gateway sul modello, poiché ActiveRecord si interrompe quando i modelli non lo fanno avere un mapping 1: 1 nelle tabelle del database. C'è un example of this nella guida rapida di Zend.

Per me, il loro esempio sembra molto gonfio con un sacco di getter e setter dappertutto. Mi sono imbattuto in vari post del blog su Domain Driven Design sostenendo che l'utilizzo di così tanti getter e setter è una cattiva pratica perché espone all'esterno tutti i dati del modello interno, quindi non ha alcun vantaggio sugli attributi pubblici. Here is one example.

La mia domanda: se rimuovi quei getter e setter, come renderesti le tue visualizzazioni? Ad un certo punto i dati devono colpire la vista in modo da poter mostrare qualcosa all'utente. Seguendo il consiglio DDD sembra rompere la separazione tra M e V in MVC. Seguendo l'esempio di MVC e Zend sembra di rompere DDD e mi lascia scrivere un sacco di getters, setter e DataMappers per tutti i miei modelli. A parte il fatto di essere molto impegnato, sembra anche violare DRY.

Vorrei davvero apprezzare alcuni (collegamenti a) buoni esempi o ulteriori informazioni su come tutto si combina perfettamente. Sto cercando di migliorare le mie capacità di architetto e progettazione qui.

risposta

2

Utilizzando Value Objects, è possibile eliminare alcuni di quei metodi di setter pubblico. Ecco una descrizione di the difference between Entity and Value Objects. Gli oggetti valore sono immutabili e spesso legati a un'entità. Se si passano tutti i valori con il costruttore, non è necessario impostare queste proprietà da codice esterno.

qualcosa in più, non direttamente legate ad una risposta, ma più focalizzato sulla DDD:

(Disclaimer: L'unica cosa che so di Zend Framework è quello che ho letto in questo articolo collegato.) Zend Framework utilizza DataMappers anziché i repository. Questo è davvero DDD-ish? Bene, Fowler's interpretation of a Repository potrebbe dire di no. Tuttavia, Eric Evans afferma che un deposito DDD può essere molto semplice. Nel modo più semplice, un repository è un DataMapper (vedere il libro DDD). Per qualcosa di più complesso e ancora DDD, vedi l'articolo di Fowler. DDD ha un repository concettuale che può differire dalla definizione del pattern.

Vi esorto a continuare a leggere su Domain-Driven Design. Penso che ci sia un difetto nel presupposto che getter e setter violano il DDD. DDD si occupa di concentrarsi sul modello di dominio e le migliori pratiche per farlo. Gli accessori sono solo un piccolo dettaglio.

+0

Grazie. Quell'articolo Devlicious è una buona lettura. Ho intenzione di leggere anche il resto della serie. –

+0

Questa è una buona risposta e vorrei aggiungere che non c'è nulla di sbagliato nei getter, setter. In realtà, averli è un ottimo modo per aggiungere logica di validazione. Rendere pubbliche le proprietà è veloce e sporco e va bene durante la prototipazione, ma non è una soluzione a lungo termine. Supponiamo di volere cambiare il nome di una proprietà. Se lo fai, ogni pezzo di codice che accede a quella proprietà deve cambiare. Se si utilizza un nome generico per il metodo accessor, non è necessario modificare il codice client. Inoltre, Doctrine è una soluzione molto più ricca di Zend DB. Non consiglierei Doctrine1, ma prova Doctrine2. –

2

Non è necessario implementare tutti i getter/setter, è possibile utilizzare __get() e __set(). Qual è il problema allora?

1

Dalla mia lettura del post, la domanda è più filosofica che pratica.

Non ho il tempo di scrivere in profondità, ma ecco i miei due centesimi. Mentre sono d'accordo sul fatto che vuoi limitare il numero di richieste get e set perché una classe dovrebbe nascondere i suoi interni, devi anche tener conto che Java e PHP sono strumenti diversi e hanno scopi diversi. Nell'ambiente web le tue classi vengono costruite e tolte con ogni richiesta e quindi il codice che scrivi non dovrebbe dipendere da classi enormi. Nell'articolo che hai sottolineato l'autore suggerisce di posizionare la logica della vista nella classe. Questo probabilmente non ha senso sul web, dal momento che probabilmente voglio presentare la vista in più formati (rss, html, ecc ...). L'utilizzo dei metodi accessor (get & set) è quindi un male necessario. Vuoi comunque usarli pensosamente per non spararti ai piedi. La chiave è cercare di fare in modo che le lezioni svolgano il lavoro per te invece di cercare di costringerli a lavorare esternamente. Accedendo alle proprietà con un metodo invece di nascondere direttamente gli interni che è quello che vuoi.

Ancora una volta, questo post potrebbe utilizzare alcuni esempi, ma non ho il tempo adesso.

Qualcun altro può fornire alcuni esempi del perché i metodi di accesso non siano malvagi?

+0

Grazie. La mia domanda è davvero più filosofica che pratica. Mettendo la logica di visualizzazione nel modello di dominio mi sembrava problematico (in quanto viola MVC) e questo è ciò che ha spinto la domanda. Quello che spero davvero di vedere sono alcuni esempi pratici che mostrano chiaramente la teoria in azione. Se è davvero un equilibrio tra Domain Driven Design e MVC, mi piacerebbe vedere come le altre persone risolvono l'apparente conflitto tra loro. –

0

Implementazione getter e setter ha due vantaggi, ai miei occhi:

  1. È possibile scegliere le proprietà da rendere pubblico, in modo da non devono necessariamente esporre tutte le parti interne del modello
  2. Se usa un IDE con completamento automatico, tutte le proprietà disponibili saranno un TAB quando inizi a digitare "get" o "set" - questa è la sola ragione per me.
1

Ci sono due approcci qui: quello che chiamo "tell non chiedere approccio", e l'altro è l'approccio ViewModel/DTO. In sostanza le domande ruotano intorno a ciò che è il "modello" nella tua vista. Tell non chiedere richiede che l'unico modo in cui un oggetto possa essere esternalizzato, provenga dall'oggetto stesso. In altre parole, per rendere un oggetto, si avrebbe un metodo di rendering, ma quel metodo di rendering avrebbe bisogno di parlare con un'interfaccia. Qualcosa di simile a questo:

class DomainObject { 
    .... 
    public function render(DomainObjectRenderer $renderer) { 
     return $renderer->renderDomainObject(array $thegorydetails); 
    } 
} 

Nel contesto di Zend Framework, è possibile creare una sottoclasse Zend_View e avere la vostra sottoclasse implementare questa interfaccia.

L'ho già fatto, ma è un po 'ingombrante.

La seconda opzione è convertire il modello di dominio in un oggetto ViewModel, che è come una visualizzazione semplificata, appiattita, "a catena" dei dati, personalizzata per ciascuna vista specifica (con un ViewModel per visualizzazione) e sulla via del ritorno, converti i dati POST in un EditModel.

Questo è un modello molto diffuso nel mondo ASP.NET MVC, ma è anche simile al modello di classe "DTO" utilizzato per trasferire i dati tra "livelli" in un'applicazione. Dovresti creare dei mapper per fare il lavoro sporco per te (non diversamente da un DataMapper, in realtà). In PHP 5.3, è possibile utilizzare reflection per modificare proprietà private, quindi DomainObject non ha nemmeno bisogno di esporre se stesso!