SlideShare ist ein Scribd-Unternehmen logo
1 von 35
Downloaden Sie, um offline zu lesen
Layered Expression Trees
                    feat.
                   CQRS

                                     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/
Andrea Saltarello! Chi era costui?
• C.T.O. di Managed Designs, alla ricerca della
  «sostenibilità dello sviluppo software»
  1. Il cliente «deve» essere soddisfatto e pagare
  2. Il fornitore «deve» avere un margine ragionevole
  3. Il team «deve» essere soddisfatto del proprio lavoro
• (Co)Fondatore e presidente di UGIdotNET: ho
  bisogno di condividere esperienze a causa del
  bullet precedente 
• (Co)Fondatore e collo di bottiglia di GUISA
• (Co)Autore di .NET: Architecting Applications
  for the Enterprise di Microsoft Press
  •   Il #NAAE è il mio giornale di bordo, nel quale (nel
      2008) ho cercato di «sintetizzare» i punti 1 e 2 
In realtà…

Andrea Saltarello è l’amico di penna
di @ayende 
«BLUE» DDD
Blue Book: Architettura (1/2)
Blue Book: Architettura (2/2)
 è una layered architecture
 i layer Presentation e Infrastructure
compaiono «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
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
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.
Application Layer: in pratica
E’ un catalogo di servizi in grado di effettuare
il mesh della logica presente nel domain layer
esponendola alla applicazione (es:
presentation layer) in una forma ad… Alta
digeribilità.
CQRS
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/ ]
Command Query Responsibility
       Segregation




    Query           Command
CQRS, a.k.a. «Stato di Diritto»

CQRS introduce in DDD la «separazione dei
poteri»
• 1 stack per «leggere»
• 1 stack per «eseguire»


In pratica, significa non dover «indovinare» un
modello valido per entrambe le esigenze
In questa sessione ci interessa la «Q» 
Scenario 1: e-commerce

Home page: visualizzare prodotti raccomandati
Considerati tutti i prodotti catalogati, dall’elenco di
quelli in vendita presentare i 3 aventi maggior
giacenza in magazzino.
Ergo:
• Prodotti catalogati->Prodotti in vendita (domain)
• Prodotti in vendita->3 prodotti aventi maggior
  giacenza (application)
Scenario 2: ERP

Visualizzare fatture insolute di una business unit
Considerate tutte le fatture, estrarre quelle attinenti
una business unit e tra esse visualizzare tutte quelle
scadute e non pagate a distanza di 30 gg dalla
scadenza
Ergo:
• Fatture emesse -> Fatture della BU
• Fatture BU -> Fatture scadute
• Fatture scadute -> Fatture insolute
Scenario 3: CMS

Visualizzare gli ultimi 5 articoli
Considerati tutti gli articoli, dall’elenco di quelli
pubblicati estrarre i 5 più recenti
Ergo:
• Articoli -> Articoli pubblicati
• Articoli pubblicati -> 5 articoli più recenti
Scenario 4: CMS (Reloaded)

Ricerca articolo
Considerati tutti gli articoli, dall’elenco di quelli
pubblicati estrarre quelli che soddisfano i criteri di
ricerca
Ergo:
• Articoli -> Articoli pubblicati
• Articoli pubblicati -> articoli che soddisfano la
  query
Scenario 5: e-commerce (strikes back)

Ricerca prodotti
Considerati tutti i prodotti catalogati, dall’elenco di
quelli in vendita estrarre quelli che soddisfano i criteri
di ricerca.
Ergo:
• Prodotti catalogati->Prodotti in vendita
• Prodotti in vendita-> prodotti che soddisfano la
  query
La «Q» in CQRS

Cosa hanno in comune questi casi?
• Ogni «filtro» è una regola che «lavora» sul
  grafo
• Composizione di regole
• Ogni regola può essere usata in differenti
  parti dell’applicazione

Come fare… Senza un «botto» di DTO? 

P.S.: Si, «botto» è un ordine di grandezza del S.I. Kilo-
>Mega->Giga->Tera->Peta->Botto
Layered Expression Trees (LET idiom)
Facciamo un gioco: facciamo che layer e
servizi si scambino degli
IQueryable<YourFavouriteDomainEntity>
facendo «emergere» la query e specificando
la proiezione solo all’ultimo momento?
LET idiom feat. Ubiquitous Language

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
LET feat. CQRS




Query                Command
Layered Expression Trees feat. CQRS
Layered Expression Trees feat. CQRS
The Good
Ridotto effort di realizzazione/gestione:
• Nessun DTO (ad eccezione del ViewModel,
  che avremmo comunque)
• Modello «database like» facile da ottenere
  rapidamente
• Strutturazione «DDD like» della logica
• Se il DBMS è SQL Server, funziona «out of the
  box»
Performance:
• Estrazione «all at once» di tutti e soli i dati
  necessari
Layered Expression Trees feat. CQRS
The Bad
Unit testing «acrobatico»:
• In pratica, LINQ 2 Objects (o
  similari)
• In ogni caso, è un LINQ provider
  differente :-/ #meh
Layered Expression Trees feat. CQRS
The Ugly
• NHibernate è praticamente
  inutilizzabile: il LINQ provider
  «scoppia»
• Ogni LINQ provider è una storia a sè
One more thing… (cit.)
LET idiom, v2

Se:
 • dovessimo realizzare una applicazione e
   non un framework
 • per noi gli idiomi fossero «belli belli belli
   in modo assurdo» (cit.)


…Allora potremmo rimpiazzare i servizi
con degli extension methods ad hoc
LET idiom, v2
 public static class OutboundInvoiceExtensions
   {
      public static IQueryable<OutboundInvoice> RetrieveExpiredOutboundInvoices(this
IQueryable<OutboundInvoice> query)
      {
         var expiredInvoices = from i in query.RetrieveUnpaidOutboundInvoices()
                         where i.PaymentDueDate < DateTime.Now
                         select i;
         return expiredInvoices;
      }

     public static IQueryable<OutboundInvoice> RetrieveUnpaidOutboundInvoices(this
IQueryable<OutboundInvoice> query)
     {
       var unpaidInvoices = from i in query
                       where i.Status == "E"
                       select i;
       return unpaidInvoices;
     }

     public static IQueryable<OutboundInvoice> FilterByBusinessUnit(this
IQueryable<OutboundInvoice> query, int businessUnitId)
     {
       var invoices = from i in query
                    where i.JobOrder.BusinessUnit.OrganizationID == businessUnitId
                    select i;
       return invoices;
     }
  }
LET2 feat. Fluent Ubiquitous Language

Sembra Specification ma non è, serve a darti l’allegria! (semi cit.)

expiredOutboundInvoices = from i in
                        ReadModelFacade.OutboundInvoices
                        .FilterByBusinessUnit(businessUnitId)
                        .RetrieveExpiredOutboundInvoices()
                        orderby i.PaymentDueDate
                        select new
                        SummaryViewModel.OutboundInvoice
                        {
                             Id = i.ID,
                             CustomerName = i.Customer.Name,
                                PaymentDueDate = i.PaymentDueDate.Value,
                                TotalAmount = i.TotalPrice,
                                JobOrderName = i.JobOrder.Name,
                                Code = i.Code
                           };
PARLIAMONE 
Bibliografia “pratica”
[DDD] Domain Driven Design, Eric Evans ,
 Addison-Wesley
[NAAE] Microsoft .NET: Architecting
 Applications for the Enterprise, Andrea
 Saltarello & Dino Esposito, Microsoft Press
CQRS, Task Based UIs, Event Sourcing agh!,
 Greg Young
[NSK] NSK, http://nsk.codeplex.com
Mio blog ENG,
 http://blogs.ugidotnet.org/mrbrightside

Weitere ähnliche Inhalte

Andere mochten auch

Domain Driven Design e CQRS
Domain Driven Design e CQRSDomain Driven Design e CQRS
Domain Driven Design e CQRSManuel Scapolan
 
SUE AGILE Architettura (Italiano)
SUE AGILE Architettura (Italiano)SUE AGILE Architettura (Italiano)
SUE AGILE Architettura (Italiano)Sabino Labarile
 
Scrum? E' come fare il bucato!
Scrum? E' come fare il bucato!Scrum? E' come fare il bucato!
Scrum? E' come fare il bucato!Manuel Scapolan
 
Strumenti di event driven analytics-sistemi evoluti di analisi degli eventi
Strumenti di event driven analytics-sistemi evoluti di analisi degli eventiStrumenti di event driven analytics-sistemi evoluti di analisi degli eventi
Strumenti di event driven analytics-sistemi evoluti di analisi degli eventiGabriele Marazzi
 
Architetttura Della Soluzione
Architetttura Della SoluzioneArchitetttura Della Soluzione
Architetttura Della SoluzioneLuca Milan
 

Andere mochten auch (8)

Domain Driven Design e CQRS
Domain Driven Design e CQRSDomain Driven Design e CQRS
Domain Driven Design e CQRS
 
SUE AGILE Architettura (Italiano)
SUE AGILE Architettura (Italiano)SUE AGILE Architettura (Italiano)
SUE AGILE Architettura (Italiano)
 
NOSQL
NOSQLNOSQL
NOSQL
 
Scrum? E' come fare il bucato!
Scrum? E' come fare il bucato!Scrum? E' come fare il bucato!
Scrum? E' come fare il bucato!
 
Strumenti di event driven analytics-sistemi evoluti di analisi degli eventi
Strumenti di event driven analytics-sistemi evoluti di analisi degli eventiStrumenti di event driven analytics-sistemi evoluti di analisi degli eventi
Strumenti di event driven analytics-sistemi evoluti di analisi degli eventi
 
Optimized for what
Optimized for whatOptimized for what
Optimized for what
 
Architetttura Della Soluzione
Architetttura Della SoluzioneArchitetttura Della Soluzione
Architetttura Della Soluzione
 
Transactions redefined
Transactions redefinedTransactions redefined
Transactions redefined
 

Ähnlich wie Layered Expression Trees feat. CQRS

Never Mind the Bollocks: here's the Domain Driven Design
Never Mind the Bollocks: here's the Domain Driven DesignNever Mind the Bollocks: here's the Domain Driven Design
Never Mind the Bollocks: here's the Domain Driven DesignAndrea Saltarello
 
Introduzione al Domain Driven Design (DDD)
Introduzione al Domain Driven Design (DDD)Introduzione al Domain Driven Design (DDD)
Introduzione al Domain Driven Design (DDD)DotNetMarche
 
Design Patterns - enterprise patterns (part I)
Design Patterns - enterprise patterns (part I)Design Patterns - enterprise patterns (part I)
Design Patterns - enterprise patterns (part I)Fabio Armani
 
Una PA agile, funzionale e serverless: si può fare! by Federico Feroldi and D...
Una PA agile, funzionale e serverless: si può fare! by Federico Feroldi and D...Una PA agile, funzionale e serverless: si può fare! by Federico Feroldi and D...
Una PA agile, funzionale e serverless: si può fare! by Federico Feroldi and D...Codemotion
 
Una Pubblica Amministrazione Agile, Funzionale e Serverless: si può fare! - C...
Una Pubblica Amministrazione Agile, Funzionale e Serverless: si può fare! - C...Una Pubblica Amministrazione Agile, Funzionale e Serverless: si può fare! - C...
Una Pubblica Amministrazione Agile, Funzionale e Serverless: si può fare! - C...Federico Feroldi
 
Una PA agile, funzionale e serverless: si può fare! - Danilo Spinelli - Codem...
Una PA agile, funzionale e serverless: si può fare! - Danilo Spinelli - Codem...Una PA agile, funzionale e serverless: si può fare! - Danilo Spinelli - Codem...
Una PA agile, funzionale e serverless: si può fare! - Danilo Spinelli - Codem...Codemotion
 
Code Contracts and Generics: implementing a LINQ-enabled Repository
Code Contracts and Generics: implementing a LINQ-enabled RepositoryCode Contracts and Generics: implementing a LINQ-enabled Repository
Code Contracts and Generics: implementing a LINQ-enabled RepositoryAndrea Saltarello
 
Meetup ASP.NET Core Angular
Meetup ASP.NET Core AngularMeetup ASP.NET Core Angular
Meetup ASP.NET Core Angulardotnetcode
 
MongoDB User Group Padova - Overviews iniziale su MongoDB
MongoDB User Group Padova - Overviews iniziale su MongoDBMongoDB User Group Padova - Overviews iniziale su MongoDB
MongoDB User Group Padova - Overviews iniziale su MongoDBStefano Dindo
 
Design Patterns - Enterprise Patterns (part 2)
Design Patterns - Enterprise Patterns (part 2)Design Patterns - Enterprise Patterns (part 2)
Design Patterns - Enterprise Patterns (part 2)Fabio Armani
 
Idiomatic Domain Driven Design
Idiomatic Domain Driven DesignIdiomatic Domain Driven Design
Idiomatic Domain Driven DesignAndrea Saltarello
 
Un'architettura di riferimento per applicazioni enterprise
Un'architettura di riferimento per applicazioni enterpriseUn'architettura di riferimento per applicazioni enterprise
Un'architettura di riferimento per applicazioni enterpriseAlberto Lagna
 
Integrazione continua con TFS Build
Integrazione continua con TFS BuildIntegrazione continua con TFS Build
Integrazione continua con TFS BuildGian Maria Ricci
 
Migrazione dei meccanismi di workflow di un sistema informativo assicurativo ...
Migrazione dei meccanismi di workflow di un sistema informativo assicurativo ...Migrazione dei meccanismi di workflow di un sistema informativo assicurativo ...
Migrazione dei meccanismi di workflow di un sistema informativo assicurativo ...Donato Clun
 
Layered Expression Trees: una terza via (idiomatica) verso il DDD
Layered Expression Trees: una terza via (idiomatica) verso il DDDLayered Expression Trees: una terza via (idiomatica) verso il DDD
Layered Expression Trees: una terza via (idiomatica) verso il DDDAndrea Saltarello
 

Ähnlich wie Layered Expression Trees feat. CQRS (20)

Never Mind the Bollocks: here's the Domain Driven Design
Never Mind the Bollocks: here's the Domain Driven DesignNever Mind the Bollocks: here's the Domain Driven Design
Never Mind the Bollocks: here's the Domain Driven Design
 
Introduzione al Domain Driven Design (DDD)
Introduzione al Domain Driven Design (DDD)Introduzione al Domain Driven Design (DDD)
Introduzione al Domain Driven Design (DDD)
 
m-v-vm @ UgiAlt.Net
m-v-vm @ UgiAlt.Netm-v-vm @ UgiAlt.Net
m-v-vm @ UgiAlt.Net
 
Design Patterns - enterprise patterns (part I)
Design Patterns - enterprise patterns (part I)Design Patterns - enterprise patterns (part I)
Design Patterns - enterprise patterns (part I)
 
Kotlin hexagonal-architecture
Kotlin hexagonal-architectureKotlin hexagonal-architecture
Kotlin hexagonal-architecture
 
Una PA agile, funzionale e serverless: si può fare! by Federico Feroldi and D...
Una PA agile, funzionale e serverless: si può fare! by Federico Feroldi and D...Una PA agile, funzionale e serverless: si può fare! by Federico Feroldi and D...
Una PA agile, funzionale e serverless: si può fare! by Federico Feroldi and D...
 
Una Pubblica Amministrazione Agile, Funzionale e Serverless: si può fare! - C...
Una Pubblica Amministrazione Agile, Funzionale e Serverless: si può fare! - C...Una Pubblica Amministrazione Agile, Funzionale e Serverless: si può fare! - C...
Una Pubblica Amministrazione Agile, Funzionale e Serverless: si può fare! - C...
 
Una PA agile, funzionale e serverless: si può fare! - Danilo Spinelli - Codem...
Una PA agile, funzionale e serverless: si può fare! - Danilo Spinelli - Codem...Una PA agile, funzionale e serverless: si può fare! - Danilo Spinelli - Codem...
Una PA agile, funzionale e serverless: si può fare! - Danilo Spinelli - Codem...
 
Code Contracts and Generics: implementing a LINQ-enabled Repository
Code Contracts and Generics: implementing a LINQ-enabled RepositoryCode Contracts and Generics: implementing a LINQ-enabled Repository
Code Contracts and Generics: implementing a LINQ-enabled Repository
 
UI Composition
UI CompositionUI Composition
UI Composition
 
Repository pattern
Repository patternRepository pattern
Repository pattern
 
Meetup ASP.NET Core Angular
Meetup ASP.NET Core AngularMeetup ASP.NET Core Angular
Meetup ASP.NET Core Angular
 
MongoDB User Group Padova - Overviews iniziale su MongoDB
MongoDB User Group Padova - Overviews iniziale su MongoDBMongoDB User Group Padova - Overviews iniziale su MongoDB
MongoDB User Group Padova - Overviews iniziale su MongoDB
 
Design Patterns - Enterprise Patterns (part 2)
Design Patterns - Enterprise Patterns (part 2)Design Patterns - Enterprise Patterns (part 2)
Design Patterns - Enterprise Patterns (part 2)
 
Idiomatic Domain Driven Design
Idiomatic Domain Driven DesignIdiomatic Domain Driven Design
Idiomatic Domain Driven Design
 
Un'architettura di riferimento per applicazioni enterprise
Un'architettura di riferimento per applicazioni enterpriseUn'architettura di riferimento per applicazioni enterprise
Un'architettura di riferimento per applicazioni enterprise
 
OrientDB & Big Data
OrientDB & Big DataOrientDB & Big Data
OrientDB & Big Data
 
Integrazione continua con TFS Build
Integrazione continua con TFS BuildIntegrazione continua con TFS Build
Integrazione continua con TFS Build
 
Migrazione dei meccanismi di workflow di un sistema informativo assicurativo ...
Migrazione dei meccanismi di workflow di un sistema informativo assicurativo ...Migrazione dei meccanismi di workflow di un sistema informativo assicurativo ...
Migrazione dei meccanismi di workflow di un sistema informativo assicurativo ...
 
Layered Expression Trees: una terza via (idiomatica) verso il DDD
Layered Expression Trees: una terza via (idiomatica) verso il DDDLayered Expression Trees: una terza via (idiomatica) verso il DDD
Layered Expression Trees: una terza via (idiomatica) verso il DDD
 

Mehr von Andrea Saltarello

Da Rotor a .NET Core ed indietro: Microsoft &lt;3 Open Source
Da Rotor a .NET Core ed indietro: Microsoft &lt;3 Open SourceDa Rotor a .NET Core ed indietro: Microsoft &lt;3 Open Source
Da Rotor a .NET Core ed indietro: Microsoft &lt;3 Open SourceAndrea Saltarello
 
The Fine Art of Time Travelling: implementing Event Sourcing
The Fine Art of Time Travelling: implementing Event SourcingThe Fine Art of Time Travelling: implementing Event Sourcing
The Fine Art of Time Travelling: implementing Event SourcingAndrea Saltarello
 
Implementing Event Sourcing in .NET
Implementing Event Sourcing in .NETImplementing Event Sourcing in .NET
Implementing Event Sourcing in .NETAndrea Saltarello
 
Idiomatic Domain Driven Design: implementing CQRS
Idiomatic Domain Driven Design: implementing CQRSIdiomatic Domain Driven Design: implementing CQRS
Idiomatic Domain Driven Design: implementing CQRSAndrea Saltarello
 
Architecting an ASP.NET MVC Solution
Architecting an ASP.NET MVC SolutionArchitecting an ASP.NET MVC Solution
Architecting an ASP.NET MVC SolutionAndrea Saltarello
 
Build a LINQ-enabled Repository
Build a LINQ-enabled RepositoryBuild a LINQ-enabled Repository
Build a LINQ-enabled RepositoryAndrea Saltarello
 
From relational data to object spaces
From relational data to object spacesFrom relational data to object spaces
From relational data to object spacesAndrea Saltarello
 

Mehr von Andrea Saltarello (10)

Da Rotor a .NET Core ed indietro: Microsoft &lt;3 Open Source
Da Rotor a .NET Core ed indietro: Microsoft &lt;3 Open SourceDa Rotor a .NET Core ed indietro: Microsoft &lt;3 Open Source
Da Rotor a .NET Core ed indietro: Microsoft &lt;3 Open Source
 
The Fine Art of Time Travelling: implementing Event Sourcing
The Fine Art of Time Travelling: implementing Event SourcingThe Fine Art of Time Travelling: implementing Event Sourcing
The Fine Art of Time Travelling: implementing Event Sourcing
 
ASP.NET Core essentials
ASP.NET Core essentialsASP.NET Core essentials
ASP.NET Core essentials
 
Implementing Event Sourcing in .NET
Implementing Event Sourcing in .NETImplementing Event Sourcing in .NET
Implementing Event Sourcing in .NET
 
Idiomatic Domain Driven Design: implementing CQRS
Idiomatic Domain Driven Design: implementing CQRSIdiomatic Domain Driven Design: implementing CQRS
Idiomatic Domain Driven Design: implementing CQRS
 
Architecting an ASP.NET MVC Solution
Architecting an ASP.NET MVC SolutionArchitecting an ASP.NET MVC Solution
Architecting an ASP.NET MVC Solution
 
ASP.NET MVC: Full Throttle
ASP.NET MVC: Full ThrottleASP.NET MVC: Full Throttle
ASP.NET MVC: Full Throttle
 
Build a LINQ-enabled Repository
Build a LINQ-enabled RepositoryBuild a LINQ-enabled Repository
Build a LINQ-enabled Repository
 
From relational data to object spaces
From relational data to object spacesFrom relational data to object spaces
From relational data to object spaces
 
MVC2: non solo tecnologia
MVC2: non solo tecnologiaMVC2: non solo tecnologia
MVC2: non solo tecnologia
 

Layered Expression Trees feat. CQRS

  • 1. Layered Expression Trees feat. CQRS 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/
  • 2. Andrea Saltarello! Chi era costui? • C.T.O. di Managed Designs, alla ricerca della «sostenibilità dello sviluppo software» 1. Il cliente «deve» essere soddisfatto e pagare 2. Il fornitore «deve» avere un margine ragionevole 3. Il team «deve» essere soddisfatto del proprio lavoro • (Co)Fondatore e presidente di UGIdotNET: ho bisogno di condividere esperienze a causa del bullet precedente  • (Co)Fondatore e collo di bottiglia di GUISA • (Co)Autore di .NET: Architecting Applications for the Enterprise di Microsoft Press • Il #NAAE è il mio giornale di bordo, nel quale (nel 2008) ho cercato di «sintetizzare» i punti 1 e 2 
  • 3. In realtà… Andrea Saltarello è l’amico di penna di @ayende 
  • 6. Blue Book: Architettura (2/2) è una layered architecture i layer Presentation e Infrastructure compaiono «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
  • 7. 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
  • 8. 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.
  • 9. Application Layer: in pratica E’ un catalogo di servizi in grado di effettuare il mesh della logica presente nel domain layer esponendola alla applicazione (es: presentation layer) in una forma ad… Alta digeribilità.
  • 10. CQRS
  • 11. 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/ ]
  • 12. Command Query Responsibility Segregation Query Command
  • 13. CQRS, a.k.a. «Stato di Diritto» CQRS introduce in DDD la «separazione dei poteri» • 1 stack per «leggere» • 1 stack per «eseguire» In pratica, significa non dover «indovinare» un modello valido per entrambe le esigenze In questa sessione ci interessa la «Q» 
  • 14. Scenario 1: e-commerce Home page: visualizzare prodotti raccomandati Considerati tutti i prodotti catalogati, dall’elenco di quelli in vendita presentare i 3 aventi maggior giacenza in magazzino. Ergo: • Prodotti catalogati->Prodotti in vendita (domain) • Prodotti in vendita->3 prodotti aventi maggior giacenza (application)
  • 15. Scenario 2: ERP Visualizzare fatture insolute di una business unit Considerate tutte le fatture, estrarre quelle attinenti una business unit e tra esse visualizzare tutte quelle scadute e non pagate a distanza di 30 gg dalla scadenza Ergo: • Fatture emesse -> Fatture della BU • Fatture BU -> Fatture scadute • Fatture scadute -> Fatture insolute
  • 16. Scenario 3: CMS Visualizzare gli ultimi 5 articoli Considerati tutti gli articoli, dall’elenco di quelli pubblicati estrarre i 5 più recenti Ergo: • Articoli -> Articoli pubblicati • Articoli pubblicati -> 5 articoli più recenti
  • 17. Scenario 4: CMS (Reloaded) Ricerca articolo Considerati tutti gli articoli, dall’elenco di quelli pubblicati estrarre quelli che soddisfano i criteri di ricerca Ergo: • Articoli -> Articoli pubblicati • Articoli pubblicati -> articoli che soddisfano la query
  • 18. Scenario 5: e-commerce (strikes back) Ricerca prodotti Considerati tutti i prodotti catalogati, dall’elenco di quelli in vendita estrarre quelli che soddisfano i criteri di ricerca. Ergo: • Prodotti catalogati->Prodotti in vendita • Prodotti in vendita-> prodotti che soddisfano la query
  • 19. La «Q» in CQRS Cosa hanno in comune questi casi? • Ogni «filtro» è una regola che «lavora» sul grafo • Composizione di regole • Ogni regola può essere usata in differenti parti dell’applicazione Come fare… Senza un «botto» di DTO?  P.S.: Si, «botto» è un ordine di grandezza del S.I. Kilo- >Mega->Giga->Tera->Peta->Botto
  • 20. Layered Expression Trees (LET idiom) Facciamo un gioco: facciamo che layer e servizi si scambino degli IQueryable<YourFavouriteDomainEntity> facendo «emergere» la query e specificando la proiezione solo all’ultimo momento?
  • 21. LET idiom feat. Ubiquitous Language 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
  • 25. The Good Ridotto effort di realizzazione/gestione: • Nessun DTO (ad eccezione del ViewModel, che avremmo comunque) • Modello «database like» facile da ottenere rapidamente • Strutturazione «DDD like» della logica • Se il DBMS è SQL Server, funziona «out of the box» Performance: • Estrazione «all at once» di tutti e soli i dati necessari
  • 27. The Bad Unit testing «acrobatico»: • In pratica, LINQ 2 Objects (o similari) • In ogni caso, è un LINQ provider differente :-/ #meh
  • 29. The Ugly • NHibernate è praticamente inutilizzabile: il LINQ provider «scoppia» • Ogni LINQ provider è una storia a sè
  • 31. LET idiom, v2 Se: • dovessimo realizzare una applicazione e non un framework • per noi gli idiomi fossero «belli belli belli in modo assurdo» (cit.) …Allora potremmo rimpiazzare i servizi con degli extension methods ad hoc
  • 32. LET idiom, v2 public static class OutboundInvoiceExtensions { public static IQueryable<OutboundInvoice> RetrieveExpiredOutboundInvoices(this IQueryable<OutboundInvoice> query) { var expiredInvoices = from i in query.RetrieveUnpaidOutboundInvoices() where i.PaymentDueDate < DateTime.Now select i; return expiredInvoices; } public static IQueryable<OutboundInvoice> RetrieveUnpaidOutboundInvoices(this IQueryable<OutboundInvoice> query) { var unpaidInvoices = from i in query where i.Status == "E" select i; return unpaidInvoices; } public static IQueryable<OutboundInvoice> FilterByBusinessUnit(this IQueryable<OutboundInvoice> query, int businessUnitId) { var invoices = from i in query where i.JobOrder.BusinessUnit.OrganizationID == businessUnitId select i; return invoices; } }
  • 33. LET2 feat. Fluent Ubiquitous Language Sembra Specification ma non è, serve a darti l’allegria! (semi cit.) expiredOutboundInvoices = from i in ReadModelFacade.OutboundInvoices .FilterByBusinessUnit(businessUnitId) .RetrieveExpiredOutboundInvoices() orderby i.PaymentDueDate select new SummaryViewModel.OutboundInvoice { Id = i.ID, CustomerName = i.Customer.Name, PaymentDueDate = i.PaymentDueDate.Value, TotalAmount = i.TotalPrice, JobOrderName = i.JobOrder.Name, Code = i.Code };
  • 35. Bibliografia “pratica” [DDD] Domain Driven Design, Eric Evans , Addison-Wesley [NAAE] Microsoft .NET: Architecting Applications for the Enterprise, Andrea Saltarello & Dino Esposito, Microsoft Press CQRS, Task Based UIs, Event Sourcing agh!, Greg Young [NSK] NSK, http://nsk.codeplex.com Mio blog ENG, http://blogs.ugidotnet.org/mrbrightside