"Non attraversare i flussi" Oggetti di accesso al database indipendenti dal livello dati in un'architettura N-Tier?

3

Aggiungo funzionalità al nostro sito Web che esegue processi a esecuzione prolungata in modo asincrono utilizzando MSMQ. In questo modo, tuttavia, è necessario informare gli utenti quando le loro richieste sono state completate. Usando il pattern di comando, ho creato un'interfaccia * chiamata INotify e l'ho composta nella classe message, quindi la classe di elaborazione dei messaggi può semplicemente chiamare GiveNotice () sull'oggetto INotify del messaggio. La prima implementazione, EmailNotify, è stata più difficile del previsto, poiché sono stato sorpreso di scoprire che MailMessage non è serializzabile, ma ha funzionato.

Ora sto lavorando su un nuovo notificatore concreto, DBNotify, che chiamerà un SP di qualche tipo e aggiornerà uno stato nel database transazionale principale. Sono inciampato nel fatto che vorrei riutilizzare l'architettura DAL che abbiamo già creato, ma INotify è un membro del progetto Model, che è più fondamentale del DAL.

La nostra gerarchia è simile a questa: Common > Modello > DAL > BAL

Ecco ulteriori dettagli sui nostri particolari livelli. Tieni presente che l'ho ereditato, quindi non sto cercando suggerimenti per migliorarlo; Mi sto chiedendo come "infrangere le regole".

Common è responsabile di tutte le funzioni di "utilità" utilizzate in molti punti dell'applicazione, ad esempio l'accesso alle impostazioni di configurazione, le stringhe di analisi e le funzionalità non correlate al business.

Model è il repository di oggetti business, quello che alcuni chiamano oggetti di trasferimento dati, raccolte di getter e setter. Ho aggiunto alcune "intelligenze" a questo livello, ma solo le regole aziendali interne a quell'oggetto, ad esempio "Il nome di un articolo deve iniziare con un carattere alfanumerico."

DAL è il livello di accesso ai dati, in teoria, tutto ciò che accade qui è che gli oggetti del modello vengono spostati dentro e fuori dal database.

BAL è il livello aziendale; incapsula le regole aziendali che regolano l'interazione degli oggetti (ad esempio "Un modulo deve avere almeno due elementi.").

Quindi l'interfaccia di INotify è definita un'astrazione per consentire al metodo di notifica di variare in modo indipendente (ad esempio e-mail, TXT, twitter, ecc.) dall'elaborazione del messaggio. L'ho creato al livello Model, che è indipendente dal livello DAL, quindi non posso riutilizzare quel codice senza creare una dipendenza circolare.

Qualcun altro ha avuto a che fare con un oggetto business il cui scopo è interagire con un database, e come lo collochi nell'architettura N-tier?

Prima di dirmi di usare Linq per Sql, grazie mille. Questa non è una domanda tecnica (come faccio a farlo), è una domanda di design (come dovrei farlo).

Penso che la risposta sia l'iniezione di dipendenza, ma non l'ho mai usata.

    
posta Michael Blackburn 01.04.2011 - 03:03
fonte

2 risposte

6

È corretto che l'iniezione di dipendenza risolva questo problema in modo pulito. Tuttavia non è necessario sapere necessariamente che cos'è o disporre di un framework per risolvere questo problema.

Ciò di cui hai bisogno è un modo per registrare un'implementazione di INotify come un'implementazione disponibile da utilizzare. (Registra dove, dici? Dico "da qualche parte, ovunque, qualunque cosa abbia senso".) E un modo per dire "Datemi l'implementazione X, per favore". Quindi ora puoi avere una classe nel DAL che si registra come implementazione DBNotify di INotify. E un'altra classe nel livello Model può richiedere il servizio di ricerca per l'implementazione DBNotify e restituire tale implementazione. Ora il livello Model non ha bisogno di sapere che DBNotify è stato implementato sul layer DAL. Naturalmente qualsiasi classe che voglia utilizzare effettivamente tali classi Model dovrà caricare DBNotify, perché il proprio livello Model non sa da dove proviene l'implementazione. Questo non è un limite particolarmente brutto, ma è quello che le classi che usano i tuoi modelli devono sapere. Hai evitato di avere una dipendenza esplicita all'interno del tuo livello del modello, ma al costo di divulgare le informazioni sulla dipendenza a tutte le classi DAL che potrebbero voler utilizzare tali classi del modello.

È qui che entra in gioco un'infrastruttura per le dipendenze. Il framework delle dipendenze è responsabile di essere il luogo in cui vengono registrate e trovate le implementazioni concrete. Meglio ancora, le informazioni su quali classi forniscono cosa, e quali altre classi hanno bisogno di cosa, di solito viene spostato in una sorta di file di configurazione. Quindi il framework dell'iniezione delle dipendenze si conclude con la responsabilità di dire, Questo tipo di oggetto ha bisogno di quel tipo di INotify, quindi ecco cosa deve essere caricato ed ecco come metterli insieme. E ora il la dipendenza non è visibile nel tuo modello e non deve essere divulgata ad altre classi DAL. Ma la stessa struttura per le dipendenze si finisce per essere una dipendenza per ogni cosa.

Quindi dovresti lanciare la tua soluzione o usare un'infrastruttura per le dipendenze? La mia opinione personale è che se si impara il framework, si desidera ammortizzare lo sforzo su tutto il codice possibile. Quindi, se disponi di un numero di luoghi che possono beneficiare di questa funzione, utilizza il framework e pianifica di iniziare a utilizzarlo in molti punti del codice. Ma se non hai altri luoghi che lo utilizzeranno, allora il tuo rolling, con la brutta dipendenza, non è un approccio orrendo.

Tuttavia, se la vedi come un'opportunità per imparare l'iniezione di dipendenza, non ti lagnerei per averlo usato. Anche se in seguito decidi di non usarlo molto.

    
risposta data 01.04.2011 - 08:50
fonte
2

Hmm, il tuo INotify è a livello di modello, ma la funzionalità necessaria per una particolare implementazione di essa è in un livello più in alto. Non c'è nulla che ti impedisca di creare una classe che implementa le interfacce del tuo sistema di notifica in quel livello (DAL o anche BAL) pur avendo la meccanica dichiarata nel livello del modello. Basta stare attenti a non trascinare le cose a monte (Principio di sostituzione di Liskov).

Quindi, per attivarlo, è possibile utilizzare una sorta di factory per creare un'istanza dell'implementazione necessaria al livello corretto, che viene quindi interpretata come un semplice notificatore. Realizzare questo framework di iniezione è davvero un buon modo per andare, specialmente se la configurazione, una volta impostata, non è dinamica. Ciò detto, la maggior parte può anche occuparsi della riconfigurazione dinamica, è solo un po 'più di lavoro.

Spero di aver capito bene il tuo problema e questo mi aiuta. Se esco nei campi, modifica e la domanda vedrò se riesco a dargli un altro tentativo.

    
risposta data 01.04.2011 - 05:25
fonte

Leggi altre domande sui tag