Architettura di una applicazione basata su JPA

Marco Andreini

D.A.O.

  • Domain Access Object sono oggetti utili ad astrarre e separare due sottosistemi diversi

  • tipicamente in ambiente JEE separano le interazioni con la persistenza dalla logica di funzionamento

  • si possono testare meglio le logiche di funzionamento sostituendo i DAO reali con degli ausili ad-hoc

D.T.O.

  • Il Domain Transfer Object è un Design Pattern usato per trasferire dati tra sottosistemi di un’applicazione

  • non hanno alcuna logica di funzionamento, sono solo contenitori di dati

  • quindi non richiedono test

  • sono usati anche nella serializzazione per incapsulare dati anche provenienti da bean diversi.

Dependency Injection

La Dependency Injection è una tecnica per assemblare le applicazioni da un insieme di classi concrete che implementano interfacce generiche.

Questo permette la creazione di sistemi accoppiati in modo non vincolante (loosely coupled).

 — dall’articolo di Martin Fowler sulla Dependency Injection

D.I. il problema

diagram classes
  • PersonFinder è una interfaccia per cercare contatti

  • PersonLister utilizza una PersonFinder per elencare le corrispondenze

  • PersonFinderDao è una classe concreta che implementa la PersonFinder, per esempio basandosi su EntityManager

D.I. l’obiettivo

  • il nostro obiettivo è avere codice che non dipende da classi concrete

  • per poter essere indipendenti dall’implementazione specifica

  • per poter sostituire i componenti senza riscrivere il codice

  • per poter testare ogni componente senza interagire con gli altri componenti

D.I. cosa non vogliamo

public class BadPersonLister {

  private PersonFinder finder;

  public BadPersonLister(EntityManager em) {
    this.finder = new PersonFinderDao(em); // non è testabile senza `em`
  }

  // ... oppure
  public void setPersonFinder(EntityManager em) {
    this.finder = new PersonFinderDao(em); // non è testabile senza `em`
  }
}

D.I. cosa vogliamo

public class PersonListener {

  private PersonFinder finder;

  public PersonLister(PersonFinder finder) {
    this.finder = finder;
  }

  // oppure
  public void setPersonFinder(PersonFinder finder) {
    this.finder = finder;
  }
}

Non dipende più da alcun EntityManager

D.I. idea

  • L’idea di base è che una classe indichi all’applicazione che c’è una dipendenza, ma in modo piuttosto astratto

  • PersonLister richiede una PersonFinder

  • Una terza parte si occuperà di inserire (inject) a tempo di esecuzione una istanza che corrisponde alla richiesta (PersonFinderDao)

  • La terza parte è il cosiddetto Inversion of Control Container o dependency injection framework

Injection: esempio

La specifica di riferimento è quella della JSR 330 - Dependency Injection for Java

Gli oggetti si creano per mezzo del framework di injection che si occupa di inserire correttamente le dipendenze a runtime.

public class PersonLister {

  @Inject
  PersonFinder finder;

  // ...
}

Tipologie di Dependency Injection

public class PersonLister {

  @Inject // Field Injection
  PersonFinder finder;

  @Inject // Cunstructor Injection - da prefire perché più chiara
  public PersonLister(PersonFinder finder) {
    this.finder = finder;
  }
}