Domanda

Sono abbastanza nuovo per utilizzando strati separati per la logica di business (dominio) e la logica di accesso al database, ma nel corso delle cose lavorare fuori ho incontrato un problema a cui mi sento ancora non ho trovato una grande soluzione.

Chiarimento La mia soluzione esistente utilizza Mappers dati a che fare con le interazioni di database direttamente. Tuttavia, come ho più approfonditamente la questione molte persone hanno suggerito che lo strato di dominio non dovrebbe comunicare direttamente con né contenere i dati Mapper che in realtà eseguire l'interazione del database. Questo è il motivo per cui ho messo gli oggetti repository tra il dominio e le necessarie Mappers dati, ma questo non si sente del tutto naturale o corretta. Quindi la vera domanda è quale livello esiste naturalmente per gestire la comunicazione tra il dominio ei dati Mappers? Esempi di come strutturare sarebbe gradito.

Ad esempio:

  • Come faccio a gestire correttamente il recupero di una collezione di oggetti di dominio nel contesto di un altro oggetto dominio?
  • Come faccio a forzare l'inserimento di un oggetto di dominio singolo o raccolta di oggetti sulla base di un'azione eseguita contro un altro oggetto. Il caso che sto affrontando attualmente è che quando una persona è collegato a una campagna, quindi ho bisogno di inserire tutti gli eventi che devono essere eseguite per quella persona per quella campagna.
È stato utile?

Soluzione

Gabriel, questo è chiamato il " impedenza problema di corrispondenza ." Ci sono molte soluzioni in giro, da quelle pesanti come i fagioli di entità J2EE per Ruby ActiveRecord semplicemente codifica una connessione mano.

Aggiornamento

Ok, bene, è difficile vedere esattamente come attaccare questo senza molte più informazioni, ma qui è l'impostazione di base.

Uno qualsiasi di questi tipi di problemi architettonici sono guidati da requisiti non funzionali, come le prestazioni; Inoltre, v'è una questione di correttezza qui, nel senso che si vuole fare in modo gli aggiornamenti sono fatti nell'ordine corretto. Quindi, si sta andando ad avere bisogno di pensare al carico di lavoro , vale a dire il modello di utilizzo in un'applicazione reale. Con questo in mente, si dispone fondamentalmente un paio di questioni: in primo luogo, i tipi di dati di base nella vostra applicazione non possono mappare correttamente alla base di dati, e in secondo luogo il modello di dominio (ad esempio, che cosa è una proprietà VARCHAR rappresentato come nel codice?) non possono mappare in modo pulito al vostro modello di database.

Quello che vorrei è avere il database e il modello dmain lavorano in modo che un'istanza di un oggetto di dominio è esattamente una fila di una tabella del modello di database; in applicazioni su larga scala raramente si può fare questo a causa dei vincoli sia di prestazioni o vincoli imposti da un preesistente modello di database.

Ora, se controllare completamente il vostro modello di database, semplifica le cose un po ', perché allora si può rendere il vostro modello di database più da vicino assomigliano al dominio. Questo potrebbe significare il modello di database è un po 'denormalizzato, ma se è così, si può (a seconda del database) gestire questo con vista, o semplicemente non ha un database completamente normalizzata. La normalizzazione è un costrutto teorico utile, ma che non significa che non ci si può rilassare in un vero e proprio sistema.

Se non controllare completamente il vostro modello di database, allora avete bisogno di uno strato di oggetti che compongono la mappatura. Hai un sacco di opzioni tra cui scegliere in attuazione di tale: è possibile costruire viste o tabelle denormalizzati nel database, è possibile costruire oggetti intermedi, oppure si può fare un po 'di entrambi, o addirittura avere diversi passaggi di entrambi (vale a dire, un oggetto intermedio che accede a un tavolo denormalizaed.)

A quel punto, però, si esegue in problemi con "do not repeat yourself" e "fare la cosa più semplice che probabilmente funzionerà." Pensate a ciò che è più probabile che a cambiare? Il vostro modello di dominio? Se hai un modello di dominio forte, che è meno probabile --- il business cambia relativamente di rado. La rappresentazione esatta dei dati nel database? Un po 'più comune. O, più comunemente, i modelli esatti di utilizzo (come scoprire la necessità di gestire gli aggiornamenti simultanei.) Così, quando si pensa che, di cosa hai bisogno di fare per rendere il più semplice possibile per affrontare i cambiamenti più comuni.

Mi rendo conto che questo non ti dà istruzioni molto precise, ma non credo che siamo in grado di offrire precise istruzioni senza sapere un bel po 'sulla tua applicaiton. Ma poi ho anche un po 'l'impressione ti stai chiedendo di quello che sarebbe il modo "giusto" di gestire questo, mentre si sta già lavorando con qualcosa che più o meno fa il lavoro. Quindi, sarei andato a finire chiedendo "che cosa sei infelice con la società?" e "Come ti piacerebbe risolvere questo?"

Altri suggerimenti

C'è una distinzione tra un modello di dominio e l'attuazione di esso. Solo perché il modello mostra un rapporto Person ---> Campaign ---> Event non significa che è necessario implementare in questo modo. IOW, il vostro modello mostra la tua analisi e la progettazione in modo orientato agli oggetti, ma di implementare quel modello in OOP che è limitato in quanto bene si può replicare quel modello nel codice.

Si consideri il seguente.

Un Person non è definita dalla sua proprietà di un Campaign, in modo da campagna può essere lasciato fuori dei suoi responsibities conoscenza. D'altra parte, un Campaign è definito dai Events che si verificano come parte della sua esecuzione, quindi è giusto avere una raccolta di eventi di una campagna. Il punto che sto facendo è che ogni classe deve avere quel tanto che basta il comportamento e le conoscenze per rendere più complesso.

Per quanto riguarda la comunicazione tra il dominio e gli strati di persistenza, le considerano due sistemi ben distinti che non sono interessati con l'altra. Tutti ciascuno di loro sa è ciò che i suoi responsiblities sono e che cosa gli annunci fa. Ad esempio, il livello di persistenza sa persistere dati passati ad esso e per annunciare che i dati sono stati salvati. Tuttavia, il livello di persistenza non ha necessariamente bisogno di comprendere gli oggetti di dominio. Allo stesso modo, lo strato di dominio capisce Person, Campaign, e Event ma non sa nulla di persistenza.

L'implicazione di quanto sopra è che lo strato dominio deve essere complessivamente con sé e non dovrebbe dipendere strato di persistenza per i suoi dati. Tuttavia, ha ancora bisogno di essere alimentato con i dati per svolgere le sue responsabilità. Tali dati possono provenire da l'interfaccia utente o il database ed è passata ad esso tramite una terza parte che conosce entrambi gli strati di dominio e di persistenza.

Quindi, nel codice (pseudo-C #) ...

namespace DomainLayer
{
    interface IDomainListener 
    {
        void PersonCreated(Person person);
    }

    class Person
    {
        private string name;

        public Person(string name)
        {
            this.name = name;
        }

        public string Name
        {
            get { return name; }
        }
    }

    class Domain 
    {
        private IDomainListener listener;

        public Domain(IDomainListener listener) {
            this.listener = listener;
        }

        public void CreatePerson(string name) {
            Person person = new Person(name);
            listener.PersonCreated(person);
        }
    }
}


namespace PersistenceLayer
{
    interface IPersistenceListener
    {
        void PersonDataSaved(int id, object data);
    }

    class Persistence
    {
        private IPersistenceListener listener;

        public Persistence(IPersistenceListener listener) 
        {
            this.listener = listener;
        }

        public void SaveData(object data)
        {
            int id = ...; // save data and return identifier
            listener.DataSaved(id, data);
        }
    }
}

namespace MyApplication
{
    class MyController : IDomainListener, IPersistenceListener
    {
        public void CreatePersonButton_Clicked()
        {
            Domain domain = new Domain(this);
            domain.CreatePerson(NameTextbox.Text);
        }

        public void PersonCreated(Person person)
        {
            Persistence persistence = new Persistence(this);
            persistence.SavePersonData(person.Name);
        }

        public void DataSaved(int id, object data)
        {
            // display data on UI
        }
    }   
}

Come si può vedere, gli spazi dei nomi rappresentano i diversi livelli. Le interfacce XYZListener definiscono gli annunci che vengono trasmessi dal livello XYZ. Eventuali altri livelli che sono interessati a questi annunci e risponderanno alle loro necessità di attuare queste interfacce, così come il nostro livello MyApplication.

Quando il pulsante "creare" viene cliccato, il controllore crea l'oggetto facciata Domain per lo strato di dominio e si registra come un ascoltatore. E poi chiama il metodo CreatePerson che crea un'istanza di un Person poi annuncia che questo è stato fatto, passando per la nuova istanza. Il controllore risponde a questo annuncio nell'attuazione PersonCreated dove genera una facciata dello strato di persistenza e si registra come l'ascoltatore nuovamente. E poi chiama il metodo SaveData whichannounces DataSaved una volta completato. L'attuazione di tale metodo quindi visualizza i dati sulla UI.

Come si può vedere, il livello di dominio e lo strato di persistenza sono ciascuna a conoscenza di soli tmemselves e non sono interessati con le responsabilità degli altri. È la logica applicazione manifestata qui come il controllore, che i fili i due insieme.

Torna al tuo problema specifico, si potrebbe avere un metodo FindPerson sulla persistenza, che avrebbe annunciato PersonFound(int id). La risposta dal regolatore sarebbe quello di chiamare il livello di persistenza per recuperare i dati circa la campagna e gli eventi, quindi chiamare lo strato di dominio con i dati per costruire il Person.

Ci scusiamo per la lunga risposta ...

Molti sistemi impiegano uno strato di dati indipendente per gestire la persistenza da e verso un database. Ci sono diversi modelli per l'organizzazione di un tale strato. Alcuni usano una sorta di implementazione fabbrica simile, altri impiegano una mappatura uno-a-uno con uno strato di dati di classe per classe di dominio.

Il modello per lo strato di dati dipende spesso stile e la preferenza. Ciò che è importante è che separa il livello di persistenza dallo strato dominio. Credo che ci sono strumenti là fuori che vi aiuterà a generare questo livello, ma la mia conoscenza di PHP è sottile, quindi non posso nominare alcun modo specifico per PHP.

Vorrei guardare i livelli di astrazione dei dati utilizzati da PHPCake e Symfony.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top