Never Mind the Bollocks: here's the Domain Driven Design

39
NEVER MIND THE BOLLOCKS: HERE’S THE Domain Driven Design Andrea Saltarello C.T.O. @ managed /designs http://blogs.ugidotnet.org/pape http://twitter.com/andysal74 http://creativecommons.org/licenses/by-nc-nd/2.5/

description

La lettura del Blue Book può generare reazioni che vanno dal "Cargo cult" (a.k.a. "non avrai altro Modello all’infuori di me") a "’sta roba non mi serve: io faccio gestionali, non applicazioni che lanciano i razzi sulla Luna". Previa una attualizzazione dei concetti del Blue Book, che ha ormai compiuto 10 anni, in questa sessione affronteremo leggende metropolitane e falsi miti e implementeremo DDD mostrando poche slide e tanto codice.

Transcript of Never Mind the Bollocks: here's the Domain Driven Design

Page 1: Never Mind the Bollocks: here's the Domain Driven Design

NEVER MIND THE BOLLOCKS:HERE’S THE

Domain Driven Design

Andrea SaltarelloC.T.O. @ managed/designshttp://blogs.ugidotnet.org/papehttp://twitter.com/andysal74

http://creativecommons.org/licenses/by-nc-nd/2.5/

Page 2: Never Mind the Bollocks: here's the Domain Driven Design

Kudos

Grazie a:

• Trenitalia

• Depeche Mode

• Joy Division

Perché, avendo viaggiato su un treno che aveva oltre 1h di ritardo, ho potuto migliorare un po’ le slide ed ascoltare tanta buona musica

Page 3: Never Mind the Bollocks: here's the Domain Driven Design

Andrea Saltarello! Chi era costui?

1. C.E.O. di Managed Designs, alla ricerca della «sostenibilità dello sviluppo software»– Il cliente «deve» essere soddisfatto e pagare– Il fornitore «deve» avere un margine ragionevole– Il team «deve» essere soddisfatto del proprio lavoro

2. Fondatore e presidente di UGIdotNET: ho bisogno di condividere esperienze a causa del bulletprecedente

3. (Co)Autore (insieme a Dino) di .NET: Architecting Applications for the Enterprise di Microsoft Press, il mio giornale di bordo nel quale (nel 2008 e 2014) ho cercato di «sintetizzare» i punti 1 e 2

Page 4: Never Mind the Bollocks: here's the Domain Driven Design

Leggere attentamente le avvertenze…

(Quasi) Tutte le demo saranno basate su:

• NSK, un framework di e-commerce sviluppato in bottega e scaricabile qui con licenza open source. #legacy

• Merp, un «Micro» ERP sviluppato in bottega e scaricabile qui con licenza open source.

N.B.: entrambi sono come il galeone di Dylan Dog, quindi mai terminati e non tutti i check-in sono come la caramella Polo (cioè «riusciti col buco» )

Page 5: Never Mind the Bollocks: here's the Domain Driven Design

Cos’è DDD?

Domain Driven Design:• Non è una metodologia• Non è una architettura• Non è un silver bullet

• è un approccio strategico alla realizzazione del software pensato per contrastare la complessità insita nel farlo; gli asset strategici sono: – Aggregate– Bounded Context– (Eventi)– Ubiquitous Language

Page 6: Never Mind the Bollocks: here's the Domain Driven Design

Ubiquitous Language

E’ il linguaggio utilizzato nelle discussioni tra tutti i partecipanti al progetto, nei diagrammi, nella documentazione e nel codice, diventando così comune a tutti gli attori che partecipano alla realizzazione del software

Attenzione ai dialetti!

Page 7: Never Mind the Bollocks: here's the Domain Driven Design

Ubiquitous Language: falsi positivi

Nella sua definizione di segno linguistico, Ferdinand de Saussure distingue:

• un elemento formale, o esterno, costituito dal significante,

• e un elemento intrinseco, concettuale, costituito dal significato.

Qualsiasi segno esiste solo grazie alla relazione tra significante e significato. In altre parole, il significante è la forma, fonica o grafica, utilizzata per richiamare l'immagine che, nella nostra mente, è associata a un determinato concetto, o significato.

Page 8: Never Mind the Bollocks: here's the Domain Driven Design

Bounded Context

Un Bounded Context è un contesto all’interno del quale è valido uno specifico ubiquitouslanguage

Un sistema è quindi una composizione di contesti differenti (es: web store, accountability, delivery&shipment …), comunicanti tra di loro mediante apposite Context Map

L’esistenza dei bounded context permette scelte ad hoc per ognuno di essi

Page 9: Never Mind the Bollocks: here's the Domain Driven Design

Aggregate

All’interno di un BC, interagiscono unità funzionali autonome chiamate Aggregate: ogni aggregate rappresenta l’artefatto che riproduce «both data and behaviour» di un concetto «importante» esistente nel contesto stesso.

• Il sistema coordina il lavoro degli aggregate

• L’insieme degli aggregate rappresenta il Domain Model

Page 10: Never Mind the Bollocks: here's the Domain Driven Design

Andrea vs. DDD, A.D. 2004

Tutto chiaro: un sistema è una composizione di Bounded Context all’interno dei quali interagiscono, coordinati dal sistema stesso, degli Aggregate che rappresentano i significati espressi nell’Ubiquitous Language.

Fantastico! Figata!

Ho un solo piccolo problema: come implemento ‘sta roba?

Page 11: Never Mind the Bollocks: here's the Domain Driven Design

BLUE BOOK

Page 12: Never Mind the Bollocks: here's the Domain Driven Design

2004: a Domain Odissey

Page 13: Never Mind the Bollocks: here's the Domain Driven Design

DDD: architettura «Blue Book»

• è una layered architecture

• i layer Presentation e Infrastructurecompaiono «per sport» nel diagramma

• i layer Application e Domain costituiscono quella che tipicamente chiamiamo «business logic»

– Domain: logica invariante rispetto ai casi d’uso

– Application: logica specifica ai casi d’uso

Page 14: Never Mind the Bollocks: here's the Domain Driven Design

Domain layer: Key Concepts

• Il Domain Layer contiene la domain logic ed è composto da– Model: Entità (identità e stato) e Valori (solo stato)

– Servizi

• Il Model è «both data and behaviour» (cit.)

• La persistenza del Model è gestita da Repository

• Le istanze delle entità di dominio sono costruite da Factory

• Entità e Valori a runtime formano dei grafi di oggetti. I grafi dotati di “dignità propria” sono chiamati Aggregate e il sistema (es: i Repository) si “impegna” a gestirli correttamente ed atomicamente

Page 15: Never Mind the Bollocks: here's the Domain Driven Design

Da 0 ad Aggregate

• E' un insieme di elementi raggruppati in un’unità logica, quindi un grafo di oggetti

• Ha come radice l'entità principale dell'aggregato

• La radice è l’unico elemento che può essere referenziato fuori dai confini dell’aggregato

• Non è possibile agire direttamente sugli elementi senza passare dalla radice dell'aggregato

• L’aggregate ha la responsabilità di implementare la propria logica

Page 16: Never Mind the Bollocks: here's the Domain Driven Design

Non stiamo modellando la realtà assoluta, bensì un modello utile all’interno di un bounded context

Per intenderci: la mappa in alto è “sbagliata”, però “funziona”

Page 17: Never Mind the Bollocks: here's the Domain Driven Design

Application Layer: in teoria

Application Layer: defines the jobs the software is supposed to do and directs the expressive domain objects to work out problems. The tasks this layer is responsible for are meaningful to the business or necessary for interaction with the application layers of other systems. This layer is kept thin. It does not contain business rules or knowledge, but only coordinates tasks and delegates work to collaborations of domain objects in the next layer down. It does not have state reflecting the business situation, but it can have state that reflects the progress of a task for the user or the program.

[DDD, ]

Page 18: Never Mind the Bollocks: here's the Domain Driven Design

Application Layer: in pratica

E’ un catalogo di servizi in grado di effettuare ilmesh della logica presente nel domain layer esponendola alla applicazione (es: presentation layer) in una forma ad… Alta digeribilità.

Page 19: Never Mind the Bollocks: here's the Domain Driven Design

DDD vs Real World

Avere a disposizione un domain layer «smart» è bello, ma costoso:

• Materializzazione degli oggetti

• Mesh della business logic

Tipicamente, si finisce per passare la vita a «fare DTO»:

• Application Layer <-> Presentation Layer

• Domain Layer <-> Application Layer

Page 20: Never Mind the Bollocks: here's the Domain Driven Design

Layered Expression Trees (LET idiom)

Facciamo un gioco: invece di definire un «botto» di DTO, facciamo che layer e servizi si scambino degli IQueryable<YourDomainEntity>, facendo «emergere» la query e specificando la proiezione solo all’ultimo momento?

L’espressione «Capra e cavoli» vi dice niente?

N.B.: «botto» è un ordine di grandezza del S.I. Kilo->Mega->Giga->Tera->Peta->Botto

Page 21: Never Mind the Bollocks: here's the Domain Driven Design

Ubiquitous Language <3 LET

LET aumenta la pervasività dell’Ubiquitous Language nel codice:

recommendedProducts = (from p in CatalogServices.GetAvailableProductsOnSale()

orderby p.UnitsInStock descending

select new ProductDescriptor

{

Id = p.Id,

Name = p.Name,

UnitPrice = p.UnitPrice,

UnitsInStock = p.UnitsInStock,

}).Take(3);

Questa query è «quasi» scritta nel linguaggio del Domain Expert (ma vedremo che si può far meglio)

Page 22: Never Mind the Bollocks: here's the Domain Driven Design

Debriefing Domain Model

A single model cannot be appropriate for reporting, searching and transactional

behaviours

(Greg Young)

Domain Model funziona, ma richiede un po’ di compromessi: è possibile implementare DDD con una architettura differente?

Page 23: Never Mind the Bollocks: here's the Domain Driven Design

CQRS

Page 24: Never Mind the Bollocks: here's the Domain Driven Design

Command Query Responsibility Segregation

Command and Query Responsibility Segregation (CQRS) originated with Bertrand Meyer’s Command and Query Separation Principle. Wikipedia defines the principle as:

It states that every method should either be a command that performs an action, or a query that returns data to the caller, but not both.

Command and Query Responsibility Segregation uses the same definition of Commands and Queries that Meyer used and maintains the viewpoint that they should be pure. The fundamental difference is that in CQRS objects are split into two objects, one containing the Commands one containing the Queries.

[Fonte: http://cqrsinfo.com/documents/cqrs-introduction/ ]

Page 25: Never Mind the Bollocks: here's the Domain Driven Design

Command Query Responsibility Segregation

Query Command

Page 26: Never Mind the Bollocks: here's the Domain Driven Design

L’architettura di CQRS

1. «Fare CQRS» significa separare lo stack di lettura da quello che provoca i cambi di stato del sistema.

2. Distinguere lo stack di lettura da quello «comportamentale» permette di utilizzare per ognuno di essi una architettura ad hoc

3. I comportamenti del sistema sono espressi mediante le azioni (a.k.a. Command) che esso può effettuare

Page 27: Never Mind the Bollocks: here's the Domain Driven Design

Lo stack di CQRS

1. L’utente Un attore chiede al sistema l’esecuzione di un command

2. Il command modifica lo stato del sistema

3. Il read model permette all’utente di conoscere il nuovo stato del sistema

Page 28: Never Mind the Bollocks: here's the Domain Driven Design

CQRS: lo stack di lettura

• Plain SQL

• (Micro) O/RM

• LET (Layered Expression Trees)

• Servizi

Page 29: Never Mind the Bollocks: here's the Domain Driven Design

CQRS <3 LET

Quale manager di una business unit, desidero avviare la procedura di recupero credito per tutti gli insoluti di mia competenza #ubiquitouslanguage #nuffsaid

Database.OutgoingInvoices..PerBusinessUnit(businessUnitId).ExpiredOnly().Select(i => new {InvoiceNumber = i.Number, CustomerId = i.Customer.Id}).AsParallel().ForAll(i => bus.Send(new CollectDebtCommand(i.InvoiceNumber, i.CustomerId)));

P.S.: Lo avevo detto che avremmo migliorato

Page 30: Never Mind the Bollocks: here's the Domain Driven Design

CQRS feat. Transaction Script

Transaction Script[P of EAA, 110]

Organizes business logic by procedures where each procedure handles a single request from the presentation.

In pratica, modelliamo i comandi come funzioni, che saranno invocate dall’application layer

Page 31: Never Mind the Bollocks: here's the Domain Driven Design

Entity-less CQRS

«Gli offri una mano, e si prende tutto il braccio» (detto popolare)

Se posso modellare lo stack «comportamentale» senza la necessità di renderlo capace di leggere il nuovo stato del sistema, potrei rinunciare tout court ad una rappresentazione basata su entità. Sticazzi E perché dovrei farlo?

Page 32: Never Mind the Bollocks: here's the Domain Driven Design

(Domain) Events

It really became clear to me in the last couple of years that we need a new building block and that is the Domain Event.

Eric Evans

An event is something that has happened in the past.

Greg Young

A domain event … captures the memory of something interesting which affects the domain

Martin Fowler

Page 33: Never Mind the Bollocks: here's the Domain Driven Design

CQRS feat. Domain Events

Terzo principio della dinamica: ad ogni azione corrisponde una reazione un evento

«CTRL+Z principle»: Invece di focalizzarci sull’ultimo stato noto del sistema, potremmo osservare gli eventi che lo hanno determinato: in questo modo, potrò risalire allo stato del sistema in ogni momento di interesse, oppure produrre nuove proiezioni

JobOrderCreated InvoiceIssuedJobOrderExtended JobOrderClosed

Page 34: Never Mind the Bollocks: here's the Domain Driven Design

CQRS vs. eventi

Ok, però io ho bisogno di sapere se la fattura sia stata pagata o il bilancio di una commessa. Come faccio?

• Ricostruisco lo stato ripercorrendo l’intero log degli eventi (lento, ma potrei usare degli snapshot)

• Mantengo un database «read friendly»

Page 35: Never Mind the Bollocks: here's the Domain Driven Design

CQRS/ES to the rescue

1. L’applicazione esegue un command

2. il command cambia lo stato del sistema ed invia al sistema stesso un evento in qualità di notifica

3. Gli eventi vengono notificati ai sottoscrittori ad essi interessati quali:

1. Gestori di workflow (a.k.a. «Saghe»), che eseguiranno altri command

2. Denormalizzatori, che aggiorneranno il read model

P.S.: consiglio: facciamo fare le notifiche ad un Mediator (a.k.a. «Bus»)

Page 36: Never Mind the Bollocks: here's the Domain Driven Design

Read

Model

Application

Layer

Domain

layer

Event

store

QUERY

COMMAND

Bu

s

EVENT Handler

Handler

Handler

Snapshot

DB

CQRS/ES in a nutshell

Page 37: Never Mind the Bollocks: here's the Domain Driven Design

On a technology side…

Abbiamo bisogno di un bus e di un event store: build or buy?• Event Store:

– SQLQualcosa– MongoDB– RavenDB– …

• Bus:– NEventStore– NServiceBus– …

Il mio “consiglio”? Buy #tuttalavita

Page 38: Never Mind the Bollocks: here's the Domain Driven Design

The “Buy” Side of the Force

SQLQualcosa MongoDB RavenDB

• Skillset diffuso• Tool per “LaQualunque”• Both On-Premise &

cloud

• Gratis• “Gira” su Linux• Both On-Premise &

cloud• Schemaless

• LINQ provider cazzuto• Supporto TX+DTC• Schemaless

MSMQ NEventStore NServiceBus

• AHAHAHAHAHAHAHAH • Gratis• FOSS• Stack DDD/CQRS/ES

completo

• Opzioni di configurazione

• Supporto notifiche

Page 39: Never Mind the Bollocks: here's the Domain Driven Design

Bibliografia

[DDD] Domain Driven Design, Eric Evans , Addison-Wesley

What I've learned about DDD since the book, Eric Evans, InfoQ

[NAAE] Microsoft .NET: ArchitectingApplications for the Enterprise (2° ed.), Andrea Saltarello & Dino Esposito, Microsoft Press

[NSK] NSK, http://nsk.codeplex.com

[MERP] Merp, https://naa4e.codeplex.com/