Domanda

Per vari motivi, stiamo scrivendo una nuova libreria di oggetti business / archiviazione dati. Uno dei requisiti di questo livello è quello di separare la logica delle regole aziendali e il livello di archiviazione dei dati effettivo.

È possibile disporre di più livelli di archiviazione dati che implementano l'accesso allo stesso oggetto, ad esempio un database principale "quot" origine di archiviazione dati che implementa la maggior parte degli oggetti, e un altro "ldap" sorgente che implementa un oggetto Utente. In questo scenario, l'utente può facoltativamente provenire da un'origine LDAP, forse con funzionalità leggermente diverse (ad esempio, non è possibile salvare / aggiornare l'oggetto utente), ma altrimenti viene utilizzato dall'applicazione allo stesso modo. Un altro tipo di archiviazione dei dati potrebbe essere un servizio Web o un database esterno.

Ci sono due modi principali in cui stiamo cercando di implementarlo, e io e un collega non siamo d'accordo su un livello fondamentale che è corretto. Vorrei qualche consiglio su quale sia il migliore da usare. Cercherò di mantenere le mie descrizioni di ciascuna il più neutra possibile, poiché sto cercando alcuni punti di vista oggettivi qui.

  • Gli oggetti business sono classi base e gli oggetti di archiviazione dati ereditano gli oggetti business. Il codice client si occupa degli oggetti di archiviazione dei dati.

    In questo caso, le regole aziendali comuni sono ereditate da ciascun oggetto di archiviazione dei dati, e sono gli oggetti di archiviazione dei dati che vengono utilizzati direttamente dal codice client.

    Ciò implica che il codice client determina quale metodo di archiviazione dei dati utilizzare per un determinato oggetto, poiché deve dichiarare esplicitamente un'istanza a quel tipo di oggetto. Il codice client deve conoscere esplicitamente le informazioni di connessione per ciascun tipo di archiviazione dati che utilizza.

    Se un livello di archiviazione dati implementa funzionalità diverse per un determinato oggetto, il codice client lo conosce esplicitamente al momento della compilazione perché l'oggetto ha un aspetto diverso. Se il metodo di archiviazione dei dati viene modificato, il codice client deve essere aggiornato.

  • Gli oggetti business incapsulano oggetti di archiviazione dati.

    In questo caso, gli oggetti business vengono utilizzati direttamente dall'applicazione client. L'applicazione client passa le informazioni di connessione di base al livello aziendale. La decisione su quale metodo di archiviazione dei dati utilizza un determinato oggetto viene presa dal codice dell'oggetto business. Le informazioni sulla connessione sarebbero una porzione di dati presi da un file di configurazione (l'app client non ne conosce / cura i dettagli), che potrebbe essere una singola stringa di connessione per un database o più stringhe di connessione di pezzi per vari tipi di archiviazione dei dati. Ulteriori tipi di connessione per l'archiviazione dei dati potrebbero essere letti anche da un altro punto, ad esempio una tabella di configurazione in un database che specifica gli URL di vari servizi Web.

    Il vantaggio qui è che se un nuovo metodo di archiviazione dei dati viene aggiunto a un oggetto esistente, un'impostazione di configurazione può essere impostata in fase di esecuzione per determinare quale metodo utilizzare ed è completamente trasparente per le applicazioni client. Non è necessario modificare le app client se cambia il metodo di archiviazione dei dati per un determinato oggetto.

  • Gli oggetti business sono classi base, gli oggetti origine dati ereditano dagli oggetti business. Il codice client si occupa principalmente delle classi di base.

    Questo è simile al primo metodo, ma il codice client dichiara le variabili dei tipi di oggetti business di base e i metodi statici Load () / Create () / etc sugli oggetti business restituiscono gli oggetti digitati sull'origine dati appropriati.

    L'architettura di questa soluzione è simile al primo metodo, ma la differenza principale è la decisione su quale oggetto di archiviazione dei dati da utilizzare per un determinato oggetto business viene preso dal livello aziendale, non dal codice client.

So che esistono già librerie ORM esistenti che forniscono alcune di queste funzionalità, ma per favore scartate quelle per ora (esiste la possibilità che un livello di archiviazione dati sia implementato con una di queste librerie ORM) - nota anche che sono deliberatamente non dirti quale lingua viene utilizzata qui, a parte il fatto che è fortemente tipizzata.

Sto cercando qualche consiglio generale qui su quale metodo è meglio usare (o sentiti libero di suggerire qualcos'altro) e perché.

È stato utile?

Soluzione

potrei suggerire un'altra alternativa, con possibilmente un migliore disaccoppiamento: oggetti business usa oggetti dati e oggetti dati implementano oggetti di archiviazione. Ciò dovrebbe mantenere le regole di business negli oggetti business ma senza alcuna dipendenza dall'origine o dal formato di archiviazione, consentendo allo stesso tempo agli oggetti dati di supportare qualsiasi manipolazione sia richiesta, inclusa la modifica dinamica degli oggetti di archiviazione (ad es. Per manipolazione online / offline)

questo rientra nella seconda categoria sopra (gli oggetti business incapsulano oggetti di archiviazione dati), ma separa più chiaramente la semantica dei dati dai meccanismi di archiviazione

Altri suggerimenti

Puoi anche avere una facciata da impedire al tuo cliente di chiamare direttamente l'azienda. Inoltre crea punti di accesso comuni alla tua attività.

Come detto, la tua azienda non dovrebbe essere esposta ad altro che al DTO e alla facciata.

Sì. Il tuo cliente può occuparsi di DTO. È il modo ideale per trasferire i dati attraverso l'applicazione.

In genere preferisco l'oggetto business "incapsula oggetto dati / archiviazione" migliore. Tuttavia, in breve potresti trovare un'elevata ridondanza con i tuoi oggetti dati e i tuoi oggetti business che potrebbero non sembrare utili. Ciò è particolarmente vero se si opta per un ORM come base del proprio livello di accesso ai dati (DAL). Ma a lungo termine è il vero vantaggio: il ciclo di vita delle applicazioni. Come illustrato, non è insolito per " dati " provengono da uno o più sottosistemi di archiviazione (non limitati a RDBMS), in particolare con l'avvento del cloud computing e come comunemente accade nei sistemi distribuiti. Ad esempio, potresti avere alcuni dati che provengono da un servizio Restful, un altro pezzo o un oggetto da un RDBMS, un altro da un file XML, LDAP e così via. Con questa realizzazione, ciò implica l'importanza di un ottimo incapsulamento dell'accesso ai dati da parte dell'azienda. Fai attenzione alle dipendenze che esponi (DI) anche attraverso i tuoi core e proprietà.

Detto questo, un approccio con cui ho giocato è quello di mettere la "carne" dell'architettura in un controller aziendale. Considerando l'accesso contemporaneo ai dati più come una risorsa che il pensiero tradizionale, il controller accetta quindi in un URI o in un'altra forma di metadati che possono essere utilizzati per sapere quali risorse di dati deve gestire per gli oggetti business. Quindi, gli oggetti business NON incapsulano essi stessi l'accesso ai dati; piuttosto il controller lo fa. Ciò mantiene i tuoi oggetti aziendali leggeri e specifici e consente al tuo controller di fornire ottimizzazione, compostabilità, atmosfera delle transazioni e così via. Tieni presente che il tuo controller quindi "ospiterà" le raccolte di oggetti business, proprio come il controller di molti ORM.

Inoltre, considera anche la gestione delle regole di business. Se osservi attentamente il tuo UML (o il modello nella tua testa come faccio io: D), noterai che il tuo modello di regole di business è in realtà un altro modello, a volte anche persistente (se stai usando un motore di regole di business, ad esempio) . Prenderei in considerazione la possibilità che anche il controller aziendale controlli effettivamente il sottosistema delle regole e che l'oggetto business faccia riferimento alle regole tramite il controller. Il motivo è perché, inevitabilmente, le implementazioni delle regole spesso devono eseguire ricerche e controlli incrociati, al fine di determinare la validità. Spesso, potrebbero essere necessarie sia ricerche di oggetti business idratate, sia ricerche di database back-end. Prendi in considerazione la possibilità di rilevare entità duplicate, ad esempio, dove solo il "nuovo" uno è idratato. Lasciando che le tue regole siano gestite dal tuo controllore aziendale, puoi quindi fare quasi tutto ciò di cui hai bisogno senza sacrificare quella bella astrazione pulita nel tuo modello di "dominio". & Quot;

In pseudo-codice:

using(MyConcreteBusinessContext ctx = new MyConcreteBusinessContext("datares://model1?DataSource=myserver;Catalog=mydatabase;Trusted_Connection=True ruleres://someruleresource?type=StaticRules&handler=My.Org.Business.Model.RuleManager")) {

User user = ctx.GetUserById("SZE543");
user.IsLogonActive = false;
ctx.Save();
}

//a business object
class User : BusinessBase {
  public User(BusinessContext ctx) : base(ctx) {}

  public bool Validate() {
    IValidator v = ctx.GetValidator(this);
    return v.Validate();
  }
}

// a validator
class UserValidator : BaseValidator, IValidator {
 User userInstance;
 public UserValidator(User user) {
  userInstance = user;
 }

 public bool Validate() {
   // actual validation code here
   return true;
 }
}

I client non devono mai gestire direttamente gli oggetti di archiviazione. Possono gestire direttamente i DTO, ma qualsiasi oggetto che abbia una logica di archiviazione non inclusa nel proprio oggetto business non dovrebbe essere chiamato direttamente dal client.

Dai un'occhiata a CSLA.net di Rocky Lhotka.

Bene, eccomi qui, ha menzionato il collega Greg.

Greg ha descritto le alternative che abbiamo preso in considerazione con grande precisione. Voglio solo aggiungere alcune considerazioni aggiuntive alla descrizione della situazione.

Il codice client può non essere a conoscenza del datastorage in cui sono archiviati gli oggetti business, ma è possibile nel caso in cui sia presente un solo datastorage o ci siano più datastorage per lo stesso tipo di oggetto business (utenti archiviati nel database locale e in esterno LDAP) ma il client non crea questi oggetti business. In termini di analisi del sistema, significa che non dovrebbero esserci casi d'uso in cui l'esistenza di due datastorage di oggetti dello stesso tipo può influire sul flusso dei casi d'uso.

Non appena sorge la necessità di distinguere gli oggetti creati in diversi archivi di dati, il componente client deve diventare consapevole della molteplicità degli archivi di dati nel suo universo e diventerà inevitabilmente responsabile della decisione quale archivio di dati utilizzare al momento della creazione di oggetti (e, credo, caricamento di oggetti da una memoria dati). Il livello aziendale può fingere di prendere queste decisioni, ma l'algoritmo del processo decisionale si baserà sul tipo e sul contenuto delle informazioni provenienti dal componente Cliente, rendendo il cliente effettivamente responsabile della decisione.

Questa responsabilità può essere implementata in numerosi modi: può essere un oggetto di connessione di tipo specifico per ogni archiviazione di dati; può essere un metodo separato per chiamare per creare nuove istanze BO ecc.

Saluti,

Michael

CLSA è in circolazione da molto tempo. Comunque mi piace l'approccio discusso nel libro di Eric Evans http://dddcommunity.org/

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