Repository Pattern: Un buon design al servizio della testabilità.
Le slides si riferiscono al talk tenuto in Mikamai Milano durante i TDD Meetup di Milano, il 02/05/2017
2. Mi presento
Christian Nastasi
Software Architect & Technical Coach
Sviluppo Software dal 1999
Esperienza di quasi 2 anni a Londra
Email: christian.nastasi@gmail.com
Linkedin: /in/cnastasi/
3. Disclaimer
● Non possiedo la verità assoluta, questo è solo uno dei
tanti approcci possibili
● Fra 1 anno probabilmente scriverò codice in maniera
completamente differente
4. Programma della serata
- Cenni teorici: Breve introduzione del Repository Pattern e di altri pattern che
verranno utilizzati nella sessione.
- Sessione di live coding: Partendo da codice pseudo-legacy, attraverso una serie di
refactoring, si giunge all’implementazione del Repository Pattern
5. A Repository mediates between the domain and
data mapping layers, acting like an in-memory
domain object collection.
Client objects construct query specifications
declaratively and submit them to Repository for
satisfaction.
Objects can be added to and removed from the
Repository, as they can from a simple collection of
objects, and the mapping code encapsulated by the
Repository will carry out the appropriate
operations behind the scenes.
Martin Fowler
Repository Pattern: Definizione
Un Repository fa da intermediario tra il dominio
(business logic) ed il layer di persistenza, agendo come
una collezione di oggetti di dominio, salvati in
memoria.
Gli oggetti “cliente” costruiscono le query
dichiarativamente e le inviano al Repository per essere
eseguite.
Gli oggetti possono essere aggiunti e rimossi nello
stesso modo in cui viene fatto per una collezione di
oggetti. Il codice relativo alla persistenza è incapsulato
all’interno del repository, che si occuperà di eseguire le
operazioni appropriate “dietro le quinte”
Martino Cacciatore di uccelli
6. Repository Pattern: Definizione
Un Repository è un’astrazione che ci permette di separare i dati
da come vengono utilizzati a come vengono memorizzati.
L’astrazione è quella della collezione di oggetti con interfaccia
CRUD.
7. Repository Pattern: Definizione
Le query vanno scritte in modo dichiarativo: significa che
dobbiamo indicare soltanto cosa vogliamo ottenere.
Il come è compito del Repository, che incapsula al suo interno le
logiche di persistenza.
8. Repository Pattern: Esempio di interfaccia
interface EntityRepository
{
public function get (int $id):?Entity;
public function getBy (Criteria $criteria):Iterator;
public function getAll():Iterator;
public function save (Entity $entity);
public function delete (Entity $entity);
public function exists (Entity $entity):bool;
}
9. Repository Pattern: Repository vs DAO
DAO
E’ un’astrazione della
persistenza.
E’ più vicino ai database, ed è
spesso incentrato sulle tabelle.
Repository
E’ un’astrazione di una
collezione di oggetti.
E’ più vicino al dominio,
avendo a che fare solamento
con gli aggregati.
10. Single Responsibility Principle
“Ogni elemento di un programma (classe, metodo, variabile) deve avere una sola
responsabilità.
Tale responsabilità debba deve interamente incapsulata dall'elemento stesso.
Tutti i servizi offerti dall'elemento dovrebbero essere strettamente allineati a tale
responsabilità.”
Wikipedia
11. Open / Closed principle
“Le entità (classi, moduli, funzioni, ecc.) software dovrebbero essere aperte
all'estensione, ma chiuse alle modifiche; in maniera tale che un'entità possa permettere
che il suo comportamento sia modificato senza alterare il suo codice sorgente.
In particolare, una volta completata l'implementazione di un'entità, questa non
dovrebbe essere più modificata, eccetto che per eliminare errori di programmazione.
L'introduzione di nuove caratteristiche o la modifica di quelle esistenti dovrebbe
richiedere la creazione di nuove entità.”
Wikipedia
12. Liskov substitution principle
Gli oggetti dovrebbero poter essere sostituiti con dei loro
sottotipi, senza alterare il comportamento del programma che li
utilizza. (vedi anche Design by Contracts)
16. Caso di studio: Blog MVP
- As a user I want to publish a post
- As a user I want to see all my posts
- As a user I want to publish a comment on a post
- As a user I want to see all the comments of a post
17. Step 0: Codice Monolitico
- Classe monolitica
- Logica e persistenza mischiate nello
stesso posto
- Non si possono usare i mock
- Necessità di un database di test
18. Entità
Un’entità è un modello che rappresenta un oggetto di dominio e che può
essere identificato univocamente attraverso un id.
Istanze differenti dello stesso oggetto ma con un id identico rappresentano la
stessa entità e sono pertanto uguali.
19. Vantaggi
+ Si può mutare il layer di persistenza senza incidere sul funzionamento
della logica
+ Utilizzando un Repository In-memory i tempi per eseguire i test di unità
si accorciano e non c’è bisogno di ripulire il DB ogni volta.
+ Incoraggia un design DRY (don’t repeat yourself)
+ Il layer di persistenza potrebbe essere di qualsiasi natura, anche remoto
(Utile in una logica a microservices)