SlideShare a Scribd company logo
1 of 55
Domain Driven Design 101
Agenda Why Building blocks Repositories, entities, specifications etc Putting it to practice Dependency injection Persistence Validation Architecture Challenges When not to use DDD Resources
Software is complicated
We solve complexity in software by distilling our problems
publicboolCanBook(Cargocargo, Voyagevoyage) { doublemaxBooking = voyage.Capacity * 1.1; if (voyage.BookedCargoSize + cargo.Size > maxBooking) returnfalse;       ... } publicboolCanBook(Cargocargo, Voyagevoyage) { if (!overbookingPolicy.IsAllowed(cargo, voyage)) returnfalse;       ... } DDD is about making concepts explicit
Domain Model
Ubiquitous language
publicinterfaceISapService { doubleGetHourlyRate(intsapId); } û A poor abstraction publicinterfaceIPayrollService { doubleGetHourlyRate(Employeeemployee); } ü Intention-revealing interfaces
publicclassEmployee { voidApplyForLeave(DateTime start, DateTime end, ILeaveService leaves)     {         ...     } }
Domain Expert
Entities
Value Types
publicclassEmployee : IEquatable<Employee> { publicbool Equals(Employee other)     { returnthis.Id.Equals(other.Id);     } } Entities are the same if they have the same identity publicclassPostalAddress : IEquatable<PostalAddress> { publicbool Equals(PostalAddress other)     { returnthis.Number.Equals(other.Number)             && this.Street.Equals(other.Street)             && this.PostCode.Equals(other.PostCode)             && this.Country.Equals(other.Country);     } } Value Types are the same if they have the same value
publicclassColour { publicint Red { get; privateset; } publicint Green { get; privateset; } publicint Blue { get; privateset; }   publicColour(int red, int green, int blue)     { this.Red = red; this.Green = green; this.Blue = blue;     }   publicColourMixInTo(Colour other)     { returnnewColour( Math.Avg(this.Red, other.Red), Math.Avg(this.Green, other.Green),  Math.Avg(this.Blue, other.Blue));     } } Value Types are immutable
Aggregates
Aggregate root *
Repositories
publicinterfaceIEmployeeRepository { EmployeeGetById(int id); void Add(Employeeemployee); void Remove(Employeeemployee);   IEnumerable<Employee> GetStaffWorkingInRegion(Regionregion); } Repositories provide collection semantics and domain queries
Domain Services
publicinterfaceITripService { floatGetDrivingDistanceBetween(Location a, Location b); }
Specifications
classGoldCustomerSpecification : ISpecification<Customer> { publicboolIsSatisfiedBy(Customer candidate)     { returncandidate.TotalPurchases > 1000.0m;     } }   if (newGoldCustomerSpecification().IsSatisfiedBy(employee)) // apply special discount Specifications encapsulate a single rule
Specifications can be used… to construct objects
var spec = newPizzaSpecification()               .BasedOn(newMargaritaPizzaSpecification())               .WithThickCrust()               .WithSwirl(Sauces.Bbq)               .WithExtraCheese();   var pizza = newPizzaFactory().CreatePizzaFrom(spec); Constructing objects according to a specification
Specifications can be used… for querying
publicinterfaceICustomerRepository { IEnumerable<Customer> GetCustomersSatisfying( ISpecification<Customer> spec); } vargoldCustomerSpec = newGoldCustomerSpecification();   var customers = this.customerRepository     .GetCustomersSatisfying(goldCustomerSpec); Querying for objects that match some specification
Anticorruption Layer
Your subsystem Anti-corruption layer Other subsystem
Any 3rd party system that I have to integrate with was written by a drunken monkey typing with his feet. Oren Eini aka Ayende
Bounded Context
publicclassLead { publicIEnumerable<Opportunity> Opportunities { get; } publicPerson Contact { get; } } publicclassClient { publicIEnumerable<Invoice> GetOutstandingInvoices(); publicAddressBillingAddress { get; } publicIEnumerable<Order> PurchaseHistory { get; } } publicclassCustomer { publicIEnumerable<Ticket> Tickets { get; } }
Dependency Injection
publicinterfaceINotificationService { void Notify(Employeeemployee, string message); } An interface defines the model publicclassEmailNotificationService : INotificationService {     void Notify(Employeeemployee, string message)     { var message = newMailMessage(employee.Email, message); this.smtpClient.Send(message);     } } Far away, a concrete class satisfies it
publicclassLeaveService { privatereadonlyINotificationService notifications;   publicLeaveService(INotificationService notifications)     { this.notifications = notifications;     }   publicvoidTakeLeave(Employeeemployee, DateTime start, DateTime end)     { // do stuff   this.notifications.Notify(employee, "Leave approved.");     } } Dependencies are injected at runtime
Persistence Ignorance
…ordinary  classes where you focus on the business problem at hand without adding stuff for infrastructure-related reasons… nothing else should be in the Domain Model.
publicclassCustomer { publicint Id { get; privateset; } publicstringFirstName { get; set; } publicstringLastName { get; set; }   publicIEnumerable<Address> Addresses { get; } publicIEnumerable<Order> Orders { get; }   publicOrderCreateOrder(ShoppingCart cart)     {         ...     } } Plain Old CLR Object (POCO)
[global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="AdventureWorksLTModel", Name="Customer")]     [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)]     [global::System.Serializable()] publicpartialclassCustomer : global::System.Data.Objects.DataClasses.EntityObject     {         [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]         [global::System.Runtime.Serialization.DataMemberAttribute()] publicintCustomerID         { get             { returnthis._CustomerID;             } set             { this.OnCustomerIDChanging(value); this.ReportPropertyChanging("CustomerID"); this._CustomerID = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); this.ReportPropertyChanged("CustomerID"); this.OnCustomerIDChanged();             }         } privateint _CustomerID; partialvoidOnCustomerIDChanging(int value); partialvoidOnCustomerIDChanged();   This is not a POCO.
Architecture
Traditional Architecture Presentation Business Logic (BLL) Infrastructure Data Access (DAL)
Onion Architecture User Interface G Application Services M Domain Services Database Domain Model Services File system Infrastructure Tests etc
Onion Architecture EmployeeController User Interface G Application Services M IEmailSender Domain Services Database Domain Model Services File system Employee, IEmployeeRepository Infrastructure Tests SmtpEmailSender etc NHibernateEmployeeRepository
Validation
Validation Examples Input validation Is the first name filled in? Is the e-mail address format valid? Is the first name less than 255 characters long? Is the chosen username available? Is the password strong enough? Is the requested book available, or already out on loan? Is the customer eligible for this policy? Business domain
publicclassPersonRepository : IPersonRepository { publicvoid Save(Person customer)     { if (!customer.IsValid()) thrownewException(...)     } } validation and persistence anti-patterns
The golden rule for validation: The Domain Model is always  in a valid state
publicclassNewUserFormValidator : AbstractValidator<NewUserForm> { IUsernameAvailabilityServiceusernameAvailabilityService;   publicNewUserFormValidator()     { RuleFor(f => f.Email).EmailAddress();   RuleFor(f => f.Username).NotEmpty().Length(1, 32)             .WithMessage("Username must be between 1 and 32 characters");   RuleFor(f => f.Url).Must(s => Uri.IsWellFormedUriString(s))             .Unless(f => String.IsNullOrEmpty(f.Url))             .WithMessage("This doesn't look like a valid URL");   RuleFor(f => f.Username)             .Must(s => this.usernameAvailabilityService.IsAvailable(s))             .WithMessage("Username is already taken");     } } separation of validation concerns with FluentValidation
Where validation fits EmployeeController User Interface G Application Services M IEmailSender Domain Services Database Employee, IEmployeeRepository Domain Model Services NewUserForm, NewUserFormValidator IOverdraftLimitPolicy File system Infrastructure Tests SmtpEmailSender IUsernameAvailabilityService etc NHibernateEmployeeRepository
Making Roles Explicit
Challenges
When DDD isn’t appropriate
Benefits
Books
Links Domain Driven Design mailing list http://tech.groups.yahoo.com/group/domaindrivendesign/ ALT.NET mailing list http://tech.groups.yahoo.com/group/altdotnet/ DDD Step By Step http://dddstepbystep.com/ Domain Driven Design Quickly (e-book) http://www.infoq.com/minibooks/domain-driven-design-quickly

More Related Content

What's hot

Domain Driven Design(DDD) Presentation
Domain Driven Design(DDD) PresentationDomain Driven Design(DDD) Presentation
Domain Driven Design(DDD) PresentationOğuzhan Soykan
 
Domain Driven Design - Strategic Patterns and Microservices
Domain Driven Design - Strategic Patterns and MicroservicesDomain Driven Design - Strategic Patterns and Microservices
Domain Driven Design - Strategic Patterns and MicroservicesRadosław Maziarka
 
Domain driven design and model driven development
Domain driven design and model driven developmentDomain driven design and model driven development
Domain driven design and model driven developmentDmitry Geyzersky
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven DesignYoung-Ho Cho
 
Domain Driven Design (DDD)
Domain Driven Design (DDD)Domain Driven Design (DDD)
Domain Driven Design (DDD)Tom Kocjan
 
Domain Driven Design Quickly
Domain Driven Design QuicklyDomain Driven Design Quickly
Domain Driven Design QuicklyMariam Hakobyan
 
Applying Domain-Driven Design to craft Rich Domain Models
Applying Domain-Driven Design to craft Rich Domain ModelsApplying Domain-Driven Design to craft Rich Domain Models
Applying Domain-Driven Design to craft Rich Domain ModelsAlexander van Trijffel
 
Domain-Driven Design
Domain-Driven DesignDomain-Driven Design
Domain-Driven DesignAndriy Buday
 
Domain Driven Design Demonstrated
Domain Driven Design Demonstrated Domain Driven Design Demonstrated
Domain Driven Design Demonstrated Alan Christensen
 
Implementing DDD with C#
Implementing DDD with C#Implementing DDD with C#
Implementing DDD with C#Pascal Laurin
 
Refactoring for Domain Driven Design
Refactoring for Domain Driven DesignRefactoring for Domain Driven Design
Refactoring for Domain Driven DesignDavid Berliner
 
Baby steps to Domain-Driven Design
Baby steps to Domain-Driven DesignBaby steps to Domain-Driven Design
Baby steps to Domain-Driven DesignŽilvinas Kuusas
 
A Practical Guide to Domain Driven Design: Presentation Slides
A Practical Guide to Domain Driven Design: Presentation SlidesA Practical Guide to Domain Driven Design: Presentation Slides
A Practical Guide to Domain Driven Design: Presentation Slidesthinkddd
 
Modelling a complex domain with Domain-Driven Design
Modelling a complex domain with Domain-Driven DesignModelling a complex domain with Domain-Driven Design
Modelling a complex domain with Domain-Driven DesignNaeem Sarfraz
 
Domain driven design
Domain driven designDomain driven design
Domain driven designits_skm
 

What's hot (20)

Domain driven design
Domain driven designDomain driven design
Domain driven design
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
 
Domain Driven Design(DDD) Presentation
Domain Driven Design(DDD) PresentationDomain Driven Design(DDD) Presentation
Domain Driven Design(DDD) Presentation
 
Domain Driven Design - Strategic Patterns and Microservices
Domain Driven Design - Strategic Patterns and MicroservicesDomain Driven Design - Strategic Patterns and Microservices
Domain Driven Design - Strategic Patterns and Microservices
 
Domain driven design and model driven development
Domain driven design and model driven developmentDomain driven design and model driven development
Domain driven design and model driven development
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
 
Domain Driven Design (DDD)
Domain Driven Design (DDD)Domain Driven Design (DDD)
Domain Driven Design (DDD)
 
Domain Driven Design Quickly
Domain Driven Design QuicklyDomain Driven Design Quickly
Domain Driven Design Quickly
 
Applying Domain-Driven Design to craft Rich Domain Models
Applying Domain-Driven Design to craft Rich Domain ModelsApplying Domain-Driven Design to craft Rich Domain Models
Applying Domain-Driven Design to craft Rich Domain Models
 
Domain-Driven Design
Domain-Driven DesignDomain-Driven Design
Domain-Driven Design
 
Domain Driven Design Demonstrated
Domain Driven Design Demonstrated Domain Driven Design Demonstrated
Domain Driven Design Demonstrated
 
Implementing DDD with C#
Implementing DDD with C#Implementing DDD with C#
Implementing DDD with C#
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
 
Refactoring for Domain Driven Design
Refactoring for Domain Driven DesignRefactoring for Domain Driven Design
Refactoring for Domain Driven Design
 
Baby steps to Domain-Driven Design
Baby steps to Domain-Driven DesignBaby steps to Domain-Driven Design
Baby steps to Domain-Driven Design
 
A Practical Guide to Domain Driven Design: Presentation Slides
A Practical Guide to Domain Driven Design: Presentation SlidesA Practical Guide to Domain Driven Design: Presentation Slides
A Practical Guide to Domain Driven Design: Presentation Slides
 
Domain driven design
Domain driven designDomain driven design
Domain driven design
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
 
Modelling a complex domain with Domain-Driven Design
Modelling a complex domain with Domain-Driven DesignModelling a complex domain with Domain-Driven Design
Modelling a complex domain with Domain-Driven Design
 
Domain driven design
Domain driven designDomain driven design
Domain driven design
 

Viewers also liked

Jivy Group - Saying Goodbye
Jivy Group - Saying GoodbyeJivy Group - Saying Goodbye
Jivy Group - Saying GoodbyeRavit Friedberg
 
Implementing DDD Concepts in PHP
Implementing DDD Concepts in PHPImplementing DDD Concepts in PHP
Implementing DDD Concepts in PHPSteve Rhoades
 
Domain-driven design - eine Einführung
Domain-driven design - eine EinführungDomain-driven design - eine Einführung
Domain-driven design - eine Einführungdie.agilen GmbH
 
Domain Driven Design and Hexagonal Architecture
Domain Driven Design and Hexagonal ArchitectureDomain Driven Design and Hexagonal Architecture
Domain Driven Design and Hexagonal ArchitectureCrishantha Nanayakkara
 
CQRS, der etwas andere Architekturansatz
CQRS, der etwas andere ArchitekturansatzCQRS, der etwas andere Architekturansatz
CQRS, der etwas andere ArchitekturansatzOPEN KNOWLEDGE GmbH
 
도메인 주도 설계의 본질
도메인 주도 설계의 본질도메인 주도 설계의 본질
도메인 주도 설계의 본질Young-Ho Cho
 
DDD 구현기초 (거의 Final 버전)
DDD 구현기초 (거의 Final 버전)DDD 구현기초 (거의 Final 버전)
DDD 구현기초 (거의 Final 버전)beom kyun choi
 

Viewers also liked (12)

Introduction to-ddd
Introduction to-dddIntroduction to-ddd
Introduction to-ddd
 
Context Mapping In Action
Context Mapping In ActionContext Mapping In Action
Context Mapping In Action
 
Pastsimple4
Pastsimple4Pastsimple4
Pastsimple4
 
Jivy Group - Saying Goodbye
Jivy Group - Saying GoodbyeJivy Group - Saying Goodbye
Jivy Group - Saying Goodbye
 
Implementing DDD Concepts in PHP
Implementing DDD Concepts in PHPImplementing DDD Concepts in PHP
Implementing DDD Concepts in PHP
 
Domain-driven design - eine Einführung
Domain-driven design - eine EinführungDomain-driven design - eine Einführung
Domain-driven design - eine Einführung
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
 
Domain Driven Design and Hexagonal Architecture
Domain Driven Design and Hexagonal ArchitectureDomain Driven Design and Hexagonal Architecture
Domain Driven Design and Hexagonal Architecture
 
CQRS, der etwas andere Architekturansatz
CQRS, der etwas andere ArchitekturansatzCQRS, der etwas andere Architekturansatz
CQRS, der etwas andere Architekturansatz
 
Domain-Driven Design
Domain-Driven DesignDomain-Driven Design
Domain-Driven Design
 
도메인 주도 설계의 본질
도메인 주도 설계의 본질도메인 주도 설계의 본질
도메인 주도 설계의 본질
 
DDD 구현기초 (거의 Final 버전)
DDD 구현기초 (거의 Final 버전)DDD 구현기초 (거의 Final 버전)
DDD 구현기초 (거의 Final 버전)
 

Similar to Domain Driven Design 101

ASP.NET MVC 3.0 Validation
ASP.NET MVC 3.0 ValidationASP.NET MVC 3.0 Validation
ASP.NET MVC 3.0 ValidationEyal Vardi
 
Dart for Java Developers
Dart for Java DevelopersDart for Java Developers
Dart for Java DevelopersYakov Fain
 
Domain-Driven Design with SeedStack
Domain-Driven Design with SeedStackDomain-Driven Design with SeedStack
Domain-Driven Design with SeedStackSeedStack
 
Building the an End-to-End ASP.NET MVC 4, Entity Framework, HTML5, jQuery app...
Building the an End-to-End ASP.NET MVC 4, Entity Framework, HTML5, jQuery app...Building the an End-to-End ASP.NET MVC 4, Entity Framework, HTML5, jQuery app...
Building the an End-to-End ASP.NET MVC 4, Entity Framework, HTML5, jQuery app...Dan Wahlin
 
14147503 Intentions Interfaces Making Patterns Concrete
14147503 Intentions Interfaces Making Patterns Concrete14147503 Intentions Interfaces Making Patterns Concrete
14147503 Intentions Interfaces Making Patterns ConcreteQConLondon2008
 
Struts 2 + Spring
Struts 2 + SpringStruts 2 + Spring
Struts 2 + SpringBryan Hsueh
 
Client-side JavaScript Vulnerabilities
Client-side JavaScript VulnerabilitiesClient-side JavaScript Vulnerabilities
Client-side JavaScript VulnerabilitiesOry Segal
 
GraphQL - when REST API is not enough - lessons learned
GraphQL - when REST API is not enough - lessons learnedGraphQL - when REST API is not enough - lessons learned
GraphQL - when REST API is not enough - lessons learnedMarcinStachniuk
 
Policy Injection in ASP.NET using Enterprise Library 3.0
Policy Injection in ASP.NET using Enterprise Library 3.0Policy Injection in ASP.NET using Enterprise Library 3.0
Policy Injection in ASP.NET using Enterprise Library 3.0PhilWinstanley
 
Service Oriented Architecture in Magento 2
Service Oriented Architecture in Magento 2Service Oriented Architecture in Magento 2
Service Oriented Architecture in Magento 2Max Pronko
 
Advisor Jumpstart: JavaScript
Advisor Jumpstart: JavaScriptAdvisor Jumpstart: JavaScript
Advisor Jumpstart: JavaScriptdominion
 
So S.O.L.I.D Fu - Designing Better Code
So S.O.L.I.D Fu - Designing Better CodeSo S.O.L.I.D Fu - Designing Better Code
So S.O.L.I.D Fu - Designing Better CodeNeil Crookes
 
HashiCorp Vault Plugin Infrastructure
HashiCorp Vault Plugin InfrastructureHashiCorp Vault Plugin Infrastructure
HashiCorp Vault Plugin InfrastructureNicolas Corrarello
 
CiklumJavaSat_15112011:Alex Kruk VMForce
CiklumJavaSat_15112011:Alex Kruk VMForceCiklumJavaSat_15112011:Alex Kruk VMForce
CiklumJavaSat_15112011:Alex Kruk VMForceCiklum Ukraine
 
Применение паттерна Page Object для автоматизации веб сервисов
Применение паттерна Page Object для автоматизации веб сервисовПрименение паттерна Page Object для автоматизации веб сервисов
Применение паттерна Page Object для автоматизации веб сервисовCOMAQA.BY
 
Scalable web application architecture
Scalable web application architectureScalable web application architecture
Scalable web application architecturepostrational
 
Lerman Vvs14 Ef Tips And Tricks
Lerman Vvs14  Ef Tips And TricksLerman Vvs14  Ef Tips And Tricks
Lerman Vvs14 Ef Tips And TricksJulie Lerman
 
Udi Dahan Intentions And Interfaces
Udi Dahan Intentions And InterfacesUdi Dahan Intentions And Interfaces
Udi Dahan Intentions And Interfacesdeimos
 

Similar to Domain Driven Design 101 (20)

ASP.NET MVC 3.0 Validation
ASP.NET MVC 3.0 ValidationASP.NET MVC 3.0 Validation
ASP.NET MVC 3.0 Validation
 
Dart for Java Developers
Dart for Java DevelopersDart for Java Developers
Dart for Java Developers
 
Domain-Driven Design with SeedStack
Domain-Driven Design with SeedStackDomain-Driven Design with SeedStack
Domain-Driven Design with SeedStack
 
Building the an End-to-End ASP.NET MVC 4, Entity Framework, HTML5, jQuery app...
Building the an End-to-End ASP.NET MVC 4, Entity Framework, HTML5, jQuery app...Building the an End-to-End ASP.NET MVC 4, Entity Framework, HTML5, jQuery app...
Building the an End-to-End ASP.NET MVC 4, Entity Framework, HTML5, jQuery app...
 
14147503 Intentions Interfaces Making Patterns Concrete
14147503 Intentions Interfaces Making Patterns Concrete14147503 Intentions Interfaces Making Patterns Concrete
14147503 Intentions Interfaces Making Patterns Concrete
 
Struts 2 + Spring
Struts 2 + SpringStruts 2 + Spring
Struts 2 + Spring
 
SOLID Principles
SOLID PrinciplesSOLID Principles
SOLID Principles
 
Client-side JavaScript Vulnerabilities
Client-side JavaScript VulnerabilitiesClient-side JavaScript Vulnerabilities
Client-side JavaScript Vulnerabilities
 
CDI @javaonehyderabad
CDI @javaonehyderabadCDI @javaonehyderabad
CDI @javaonehyderabad
 
GraphQL - when REST API is not enough - lessons learned
GraphQL - when REST API is not enough - lessons learnedGraphQL - when REST API is not enough - lessons learned
GraphQL - when REST API is not enough - lessons learned
 
Policy Injection in ASP.NET using Enterprise Library 3.0
Policy Injection in ASP.NET using Enterprise Library 3.0Policy Injection in ASP.NET using Enterprise Library 3.0
Policy Injection in ASP.NET using Enterprise Library 3.0
 
Service Oriented Architecture in Magento 2
Service Oriented Architecture in Magento 2Service Oriented Architecture in Magento 2
Service Oriented Architecture in Magento 2
 
Advisor Jumpstart: JavaScript
Advisor Jumpstart: JavaScriptAdvisor Jumpstart: JavaScript
Advisor Jumpstart: JavaScript
 
So S.O.L.I.D Fu - Designing Better Code
So S.O.L.I.D Fu - Designing Better CodeSo S.O.L.I.D Fu - Designing Better Code
So S.O.L.I.D Fu - Designing Better Code
 
HashiCorp Vault Plugin Infrastructure
HashiCorp Vault Plugin InfrastructureHashiCorp Vault Plugin Infrastructure
HashiCorp Vault Plugin Infrastructure
 
CiklumJavaSat_15112011:Alex Kruk VMForce
CiklumJavaSat_15112011:Alex Kruk VMForceCiklumJavaSat_15112011:Alex Kruk VMForce
CiklumJavaSat_15112011:Alex Kruk VMForce
 
Применение паттерна Page Object для автоматизации веб сервисов
Применение паттерна Page Object для автоматизации веб сервисовПрименение паттерна Page Object для автоматизации веб сервисов
Применение паттерна Page Object для автоматизации веб сервисов
 
Scalable web application architecture
Scalable web application architectureScalable web application architecture
Scalable web application architecture
 
Lerman Vvs14 Ef Tips And Tricks
Lerman Vvs14  Ef Tips And TricksLerman Vvs14  Ef Tips And Tricks
Lerman Vvs14 Ef Tips And Tricks
 
Udi Dahan Intentions And Interfaces
Udi Dahan Intentions And InterfacesUdi Dahan Intentions And Interfaces
Udi Dahan Intentions And Interfaces
 

Recently uploaded

A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...AliaaTarek5
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityIES VE
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationKnoldus Inc.
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesThousandEyes
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfNeo4j
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 

Recently uploaded (20)

A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a reality
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog Presentation
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdf
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 

Domain Driven Design 101

  • 2.
  • 3. Agenda Why Building blocks Repositories, entities, specifications etc Putting it to practice Dependency injection Persistence Validation Architecture Challenges When not to use DDD Resources
  • 5. We solve complexity in software by distilling our problems
  • 6. publicboolCanBook(Cargocargo, Voyagevoyage) { doublemaxBooking = voyage.Capacity * 1.1; if (voyage.BookedCargoSize + cargo.Size > maxBooking) returnfalse;   ... } publicboolCanBook(Cargocargo, Voyagevoyage) { if (!overbookingPolicy.IsAllowed(cargo, voyage)) returnfalse;   ... } DDD is about making concepts explicit
  • 9. publicinterfaceISapService { doubleGetHourlyRate(intsapId); } û A poor abstraction publicinterfaceIPayrollService { doubleGetHourlyRate(Employeeemployee); } ü Intention-revealing interfaces
  • 10. publicclassEmployee { voidApplyForLeave(DateTime start, DateTime end, ILeaveService leaves) { ... } }
  • 14. publicclassEmployee : IEquatable<Employee> { publicbool Equals(Employee other) { returnthis.Id.Equals(other.Id); } } Entities are the same if they have the same identity publicclassPostalAddress : IEquatable<PostalAddress> { publicbool Equals(PostalAddress other) { returnthis.Number.Equals(other.Number) && this.Street.Equals(other.Street) && this.PostCode.Equals(other.PostCode) && this.Country.Equals(other.Country); } } Value Types are the same if they have the same value
  • 15. publicclassColour { publicint Red { get; privateset; } publicint Green { get; privateset; } publicint Blue { get; privateset; }   publicColour(int red, int green, int blue) { this.Red = red; this.Green = green; this.Blue = blue; }   publicColourMixInTo(Colour other) { returnnewColour( Math.Avg(this.Red, other.Red), Math.Avg(this.Green, other.Green), Math.Avg(this.Blue, other.Blue)); } } Value Types are immutable
  • 19. publicinterfaceIEmployeeRepository { EmployeeGetById(int id); void Add(Employeeemployee); void Remove(Employeeemployee);   IEnumerable<Employee> GetStaffWorkingInRegion(Regionregion); } Repositories provide collection semantics and domain queries
  • 23. classGoldCustomerSpecification : ISpecification<Customer> { publicboolIsSatisfiedBy(Customer candidate) { returncandidate.TotalPurchases > 1000.0m; } }   if (newGoldCustomerSpecification().IsSatisfiedBy(employee)) // apply special discount Specifications encapsulate a single rule
  • 24. Specifications can be used… to construct objects
  • 25. var spec = newPizzaSpecification() .BasedOn(newMargaritaPizzaSpecification()) .WithThickCrust() .WithSwirl(Sauces.Bbq) .WithExtraCheese();   var pizza = newPizzaFactory().CreatePizzaFrom(spec); Constructing objects according to a specification
  • 26. Specifications can be used… for querying
  • 27. publicinterfaceICustomerRepository { IEnumerable<Customer> GetCustomersSatisfying( ISpecification<Customer> spec); } vargoldCustomerSpec = newGoldCustomerSpecification();   var customers = this.customerRepository .GetCustomersSatisfying(goldCustomerSpec); Querying for objects that match some specification
  • 29. Your subsystem Anti-corruption layer Other subsystem
  • 30. Any 3rd party system that I have to integrate with was written by a drunken monkey typing with his feet. Oren Eini aka Ayende
  • 32. publicclassLead { publicIEnumerable<Opportunity> Opportunities { get; } publicPerson Contact { get; } } publicclassClient { publicIEnumerable<Invoice> GetOutstandingInvoices(); publicAddressBillingAddress { get; } publicIEnumerable<Order> PurchaseHistory { get; } } publicclassCustomer { publicIEnumerable<Ticket> Tickets { get; } }
  • 34. publicinterfaceINotificationService { void Notify(Employeeemployee, string message); } An interface defines the model publicclassEmailNotificationService : INotificationService { void Notify(Employeeemployee, string message) { var message = newMailMessage(employee.Email, message); this.smtpClient.Send(message); } } Far away, a concrete class satisfies it
  • 35. publicclassLeaveService { privatereadonlyINotificationService notifications;   publicLeaveService(INotificationService notifications) { this.notifications = notifications; }   publicvoidTakeLeave(Employeeemployee, DateTime start, DateTime end) { // do stuff   this.notifications.Notify(employee, "Leave approved."); } } Dependencies are injected at runtime
  • 37. …ordinary classes where you focus on the business problem at hand without adding stuff for infrastructure-related reasons… nothing else should be in the Domain Model.
  • 38. publicclassCustomer { publicint Id { get; privateset; } publicstringFirstName { get; set; } publicstringLastName { get; set; }   publicIEnumerable<Address> Addresses { get; } publicIEnumerable<Order> Orders { get; }   publicOrderCreateOrder(ShoppingCart cart) { ... } } Plain Old CLR Object (POCO)
  • 39. [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="AdventureWorksLTModel", Name="Customer")] [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)] [global::System.Serializable()] publicpartialclassCustomer : global::System.Data.Objects.DataClasses.EntityObject { [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)] [global::System.Runtime.Serialization.DataMemberAttribute()] publicintCustomerID { get { returnthis._CustomerID; } set { this.OnCustomerIDChanging(value); this.ReportPropertyChanging("CustomerID"); this._CustomerID = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); this.ReportPropertyChanged("CustomerID"); this.OnCustomerIDChanged(); } } privateint _CustomerID; partialvoidOnCustomerIDChanging(int value); partialvoidOnCustomerIDChanged();   This is not a POCO.
  • 41. Traditional Architecture Presentation Business Logic (BLL) Infrastructure Data Access (DAL)
  • 42. Onion Architecture User Interface G Application Services M Domain Services Database Domain Model Services File system Infrastructure Tests etc
  • 43. Onion Architecture EmployeeController User Interface G Application Services M IEmailSender Domain Services Database Domain Model Services File system Employee, IEmployeeRepository Infrastructure Tests SmtpEmailSender etc NHibernateEmployeeRepository
  • 45. Validation Examples Input validation Is the first name filled in? Is the e-mail address format valid? Is the first name less than 255 characters long? Is the chosen username available? Is the password strong enough? Is the requested book available, or already out on loan? Is the customer eligible for this policy? Business domain
  • 46. publicclassPersonRepository : IPersonRepository { publicvoid Save(Person customer) { if (!customer.IsValid()) thrownewException(...) } } validation and persistence anti-patterns
  • 47. The golden rule for validation: The Domain Model is always in a valid state
  • 48. publicclassNewUserFormValidator : AbstractValidator<NewUserForm> { IUsernameAvailabilityServiceusernameAvailabilityService;   publicNewUserFormValidator() { RuleFor(f => f.Email).EmailAddress();   RuleFor(f => f.Username).NotEmpty().Length(1, 32) .WithMessage("Username must be between 1 and 32 characters");   RuleFor(f => f.Url).Must(s => Uri.IsWellFormedUriString(s)) .Unless(f => String.IsNullOrEmpty(f.Url)) .WithMessage("This doesn't look like a valid URL");   RuleFor(f => f.Username) .Must(s => this.usernameAvailabilityService.IsAvailable(s)) .WithMessage("Username is already taken"); } } separation of validation concerns with FluentValidation
  • 49. Where validation fits EmployeeController User Interface G Application Services M IEmailSender Domain Services Database Employee, IEmployeeRepository Domain Model Services NewUserForm, NewUserFormValidator IOverdraftLimitPolicy File system Infrastructure Tests SmtpEmailSender IUsernameAvailabilityService etc NHibernateEmployeeRepository
  • 52. When DDD isn’t appropriate
  • 54. Books
  • 55. Links Domain Driven Design mailing list http://tech.groups.yahoo.com/group/domaindrivendesign/ ALT.NET mailing list http://tech.groups.yahoo.com/group/altdotnet/ DDD Step By Step http://dddstepbystep.com/ Domain Driven Design Quickly (e-book) http://www.infoq.com/minibooks/domain-driven-design-quickly
  • 56. Any fool can write code that a computer can understand. Good programmers write code that humans can understand. Martin Fowler
  • 57. Thanks for listening! http://twitter.com/dingwallr http://richarddingwall.name rdingwall@gmail.com

Editor's Notes

  1. -Complexity =enemy-Creeps in-Affects ability to deliver-Separate concerns-Breaking into smaller units-DDD is about distilling into an explicit model-All in one place-Easier to work with than sprocs/code behind
  2. -Not complicated-Important business concept hidden-Not just anonymous calculation-Overbooking policy-2nd example doesn’t need comments-DDD is about making concepts explicit-As separate objects
  3. -Imagine if you could truly isolate all your business logic-DDD is about creating a model of the domain-Subject area-Not usually related to computers-Usually based on people and business-Abstraction of reality-Important bits-e.g.-Domain model includes data AND behaviour-Isolated layer in your application-Living breathing C#, not UML-Completely free from the tech used to implement it-No database, no XML, no files, no web services, biztalk, sharepoint-No transactions-Just pure domain concepts-No dependencies on anything except itself
  4. -Expressed in-Quite often there is a language wall between clients and developers-They says discontinue a product, you translate it to delete it from the product table
  5. -Say we have an app that has to get an employee’s hourly rate-First example is all about the implementation details-Happens to be stored in SAP at the moment-SAP identifier is an implementation detail-Intention revealing interfaces-Expressed in the ubquitious language
  6. -Doesn’t just apply to nouns, but verbs as well-”An employee applies for leave”-Leaves don’t come outta thin air-So we put a method on employee-Makes roles clear, who does what-Also applies to bidirectional associations
  7. -Someone you talk to when you’re figuring all this stuff out-If you’re doing agile he might join team-Not necessarily technical-I have a picture of a business owner-Can explain not only how, but WHY-BAs not best, just proxy
  8. -Object with a thread of continuity-Lasts the lifetime of an object-Like a person-You can change everything about them: name, address, sex-But over their whole lifetime they’re still the same person-Same with object, entities are the same object for the duration of their lifetime-Implemented with an identifier or ID
  9. -Value types on the other hand-Are identified by their value-E.g. color, addresses, shopping lists
  10. -Cluster of objects -Consistency boundary-Simplifies things massively-Master object called aggregate root
  11. -Cannot hold reference to anything except the root-Can’t access any entity except from the root-Consistency boundary-Save the whole thing-Cascades-Versioning-Locking – coarse grain lock-No longer cherry picking
  12. -Common pattern-When you need something-Where you put things when your application isn’t using themAbstracts away persistence- SQL database- Object relational mappers- Stored procs- Caching- Fetching strategiesOne per aggregate root
  13. -Interfaces are first-class member of the domain-Collection semantics-No CRUD (save/update), just add/remove-ORM dirty tracking, get out of this commit mindset-Only domain queries, not general data access -Search -Reporting (OLAPvs OLTP)
  14. -Behaviour that isn’t logically part of any entity
  15. -Trip service-Again uses UL-TripService, not GoogleMapsWebAPI service
  16. -Encapsulates a single business rule-Tests if an object satisfies the specified criteria-Brings UL into code as an explicit NAMED concept-Promotes DRY-Validation-Creating objects-Querying
  17. -When you order a pizza-Say what toppings, crust-If you think about it-Not a pizza yet
  18. -As business get more of their systems integrated-Becoming more common for writing systems that need to talk to other systems-But each system has it’s own semantics that we don’t want in our abstraction-Anticorruption layer maps external objects to fit our model
  19. -Our nice domain model on the left-Little cohesive objects-Hairy tangled third party system -Its own layer-Internals-Facade or adapter patterns
  20. -Another reason why you should use an anti corruption layer-Quote, an Assumption you should make-Lets you mock out the external system-Swap in an alternative when it goes down, for testing etc-Not just for DDD
  21. -Different definitions in different contexts-E.g. different departments may reuse language differently-SOA people often try to shoehorn them together into one grand unified model of the universe-Not how the business works in real life-DDD Embrace each context’s language and model
  22. -Could smush together-Pretty big and unwieldy-Contradictions around contact-Sales: contact is business development manager-Support: contact is developers-Each is a separate domain model-Separate ubiquitous language-Separate persistence-Anticorruption layers between them
  23. -”Don’t call us, we’ll call you” principle
  24. -All about interfaces-Decouple our code-Depend on the model, not the implementation-Users of INotificationService have no idea
  25. -Instead of calling out-Inversion of control
  26. -In stored-proc based apps changes don’t become official until ‘committed’-The database IS the model-Data model gets built first-And the app is just a thin layer and some validation on top-Require frequent round trips-One foot in the DB at all times-Impossible to unit test-In DDD we recognize relational schemas has different objectives-Performance, normalization, indexing-Not a 1:1 mirror of the domain model-Just an implementation detail-A place to put things when your app isn’t using them-Big shift in thinking-Domain model first, figure out how to map it to a relational schema later-But greatly simplifies things-Opens up unit testing-Lets you write a DB later
  27. -Ultimate goal of object relational mappers-Persistence ignorance-The domain model has no idea about data access or things coming and going-The way we achieve this is with POCOs
  28. -So much crap-This is persistence logic-Does not belong in yourdomain model-Use a proper object relational mapper like NHibernate-That maintain mappings separately in a different layer
  29. -DAL talks to SQL-BLL talks to external systems-Presentation talks to the web-Each layer depends on bits in from the layer underneath-So if you want to add something, first you have to add it in the DAL, then BLL-That’s why we found business logic scattered from one end to the other
  30. -Domain model != view model-The M in MVC-Instead of depending downwards, dependenciesgoes inwards
  31. -255 = persistence validation, done by ORM
  32. -Nieve example of things you dont wanna do-Repository doing CRUD-Validating only before it writes to the DB-self-validating entities (doesn’t work for different contexts)-E.g. Hasn’t chosen an insurance policy yet, but doesn’t make them an invalid cusomter
  33. -Cos when you think about-We don’t validate domain entities-We validate forms and actions people try and submit via the UI-Domain model != view model
  34. -Learning curve-Requires a lot of buy in-Fitting into the landscape-Code-People-conceptual contours, generic subdomains, distributed domain driven design
  35. -DDD is for dealing with complex domains-If you don’t have a complex domain-If you have no behaviour or logic-If your’model’ maps perfectly to a relational DB schema-Clues that you don’t need DDD-If you don’t have access to a domain expert-Use it as a pattern language-Only for OO, e.g. no device drivers
  36. -But if you do-Model that’s much easier to understand-Everything in one place-Ubiquitous language-End up with code that’s almost readable by non-technical domain experts-OO done right-Isolation makes it much easier to unit test-Not dependent on technical details-Much easier to refactor-Not a cure for complexity-Not a golden bullet-Overall it’s about lifting our game-At the end of the day we are craftsmen-People come to us-Expect our code to work for a long time-DDD is about achieving that longterm maintainability
  37. -So where to from here-You really wanna read this book
  38. -Just before you go