domenica 27 febbraio 2011

Il DAL deve dipendendere dal BLL e non viceversa!

Avete presente la classica applicazione three-tier?

  1. Presentation

  2. Business logic

  3. Data access


Molte volte, troppe volte, abbiamo visto dipendenze di questo tipo:



Io stesso avevo progettato applicazioni in questo modo, infatti risulta abbastanza naturale, per esempio, nel nostro strato di business logic scrivere qualcosa del genere (ovviamente orderRepository proviene dal DAL):


DAL.Order order = this.orderRepository.getOrder(id);
OrderDTO orderDto = OrderDTO.createFrom(order);


Ma in questo modo, se volessimo cambiare database come si fa? Una soluzione potrebbe essere quella di lasciare al DAL la responsabilità di gestire i differenti tipi di storage. Ma in ogni caso questo ci costringe a realizzare un business logic layer consapevole di come vengono salvati gli oggetti, cioè che nel DAL esiste un oggetto Order, (che probabilmente corrisponderà ad una tabella), quindi ci limita molto anche nella progettazione del DAL stesso. Non a caso questo tipo di architettura è il risultato del pericolosissimo data-driven design, cioè quella tecnica di sviluppo che prevede le fasi:

  1. design del database;

  2. reverse-engineering dello schema del db in classi, nel DAL;

  3. sviluppo di servizi che manipolano queste classi, nel BLL;

  4. realizzazione di interfacce che grosso modo riproducono i campi del database e le sue strutture.



Ma il nocciolo dell'applicazione è il suo model, il suo business logic, non il suo storage. Se ci rendiamo conto di questo, dovrebbe essere l'accesso ai dati a dipendere dal business e non viceversa. Dunque come realizziamo la nostra architettura in questo modo:

Come possiamo gestire l'accesso ai dati dal BLL? In questo ci viene incontro la dependency injection, in modo semplicissimo:

  1. nel BLL creiamo un'interfaccia IOrderRepository, che stavolta non ci restituirà degli oggetti che replicano la struttura del database ma i nostri veri oggetti di dominio;

  2. nel BLL creiamo il nostro servizio OrderService, con un riferimento a IOrderRepository;

  3. nel DAL, che dipende dal BLL, implementiamo IOrderRepository, il quale effettua la mappatura dal database al modello: è questo strato il responsabile di scelte come: usiamo un ORM? Salviamo su XML? Usiamo MongoDB?

  4. istruiamo il nostro dependency injection container con l'implementazione da iniettare in OrderService;


ed ecco fatto: abbiamo finalmente slegato totalmente il BLL dal DAL. Possiamo abbandonare il diabolico data-driven design.

Nessun commento: