How can we quickly tell what an application is about? How can we quickly tell what it does? How can we distinguish business concepts from architecture clutter? How can we quickly find the code we want to change? How can we instinctively know where to add code for new features? Purely looking at unit tests is either not possible or too painful. Looking at higher-level tests can take a long time and still not give us the answers we need. For years, we have all struggled to design and structure projects that reflect the business domain.
In this talk Sandro will be sharing how he designed the last application he worked on, twisting a few concepts from Domain-Driven Design, properly applying MVC, borrowing concepts from CQRS, and structuring packages in non-conventional ways. Sandro will also be touching on SOLID principles, Agile incremental design, modularisation, and testing. By iteratively modifying the project structure to better model the product requirements, he has come up with a design style that helps developers create maintainable and domain-oriented software.
3. What is this application about?
What are the main concepts?
What does this application do?
What are the main features?
Where do I need to change?
Where do I put a new feature?
4. Looking from above, I can’t see what the application does
or is about
Architectural and design concepts mixed with domain
Badly structured packages/namespaces
I don’t know where to start
Classes and methods are too low level
11. MVC & MVC Variations
They are all wrong. But they are also right. It all depends on the ‘V’iew.
12. Views impact MVC structure
Depending on the view technology, Views and Controllers
responsibility becomes more/less coupled or blurred.
Web applications
Single-page AJAX applications with stateless backend
Console-based applications
Desktop applications
Games
Mobile / tablets
External systems (talking via Queues / Webservices)
However, the model should remain unchanged.
13. MVC – A Macro Organisational Pattern
Model
V C M
Delivery
Mechanism
14. “Model” is overloaded and confusing
Model (M in MVC)
Domain Model (DDD)
View Model
Data Model
Entities & Active Record
and other artificial definitions from MVC frameworks
Associated with the persistence mechanism?
15. M => Domain Model (DDD)
Domain Model combines state and behaviour,
with more focus on the latter.
DDD define a few building blocks to your domain:
Entities
Value Objects
Factories
Repositories
Services
Application
Domain
Infrastructure
Aggregates
16. << Web app >>
Embedded Domain Model
Model
V C DM
Delivery
Mechanism
Infrastructure Infrastructure
DB
Queue
19. Domain Model – Responsibilities
UC = Use Case, DS = Domain Service, S = Infra. Service, R = Repository
Model
UC 1
R 3
DS 1
DS 3
R 1
S
Infrastructure Impl
DM
DS 2
Impl
UC 2
<< web app >>
26. What is inside model packages?
Aggregate root (entity)
Repository
Entity (part of Book aggregate)
Domain Service
Value Object (part of Book aggregate)
Part of aggregate behaviour
Repository
Value Object (part of User aggregate)
Aggregate root (entity)
Domain Service
27. What is inside infrastructure?
Interfaces defined by the domain.
Dependency Inversion Principle (DIP)
CreditCardProcessor implementations
Repository implementations
28. Domain Model collaborations guideline
C
UC 1
UC 2
DS 1
DS 3
DS 2
R 3
R 1
cl
cl
cl
cl
C = Controller, UC = Use Case, DS = Domain Service, R = Repository, cl = class
29. Class responsibility
C UC DS R
cl
DB
Input Output
End of code branch
Produces the output
End of flow
First to handle input
Start of the flow
Execution Flow
Closer to the input: Control flow, higher level abstraction, detailed work is delegated
(e.g. ProcessTrade (UC), MakePayment (UC)) — More suitable for Outside-In TDD
(mockist).
Closer to the output / end of branch: Specific and detailed behaviour, no delegation,
lower level abstraction (e.g. Parse XML (Parser), Create User (Repository))
Domain Model entry
point Domain Concept
entry point
30. Defining testing strategies and boundaries
• Unit
• Integration
• Acceptance
• Journey
• Black box
• Component
• System
• Functional
• Alpha
• Beta
• Conformance
• …
Types of tests
31. Testing strategies: User Journey
Model
UC 1
DM
UC 2
<< web app >>
UC 1
UC 2
Tests the journey a user will have to do something
useful in the system
Application is tested as a black box normally using
a BDD framework
Use cases are facked. We just want to know if the
application presents the user with the correct
journey
Designed according to User Stories
and Features
<<fake>>
<<fake>>
32. Infrastructure Impl
Testing strategies: Acceptance (Action / Behavioural)
UC DS 1
<<mock>>
RDS 2 R
Tests a behaviour (action) provided by the system
Use Case is the entry point
and all external dependencies
are stubbed
Domain Model
Normally tested using a BDD
framework
33. Testing strategies: Integration
Tests the classes at the system boundaries
Infrastructure Impl
UC DS 1
<<mock>>
RDS 2 R
Domain Model
Normally done using an in-
memory Database using a unit
testing framework
34. Testing strategies: Unit (Class level)
Unit test at class/method level
Infrastructure Impl
UC DS 1
RRDS 2
Domain Model
DS 1
DS 2
All collaborators are
mocked / stubbed
(spies)
35. Testing strategies: End-to-End
Model
UC 1
R 3
DS 1
DS 3
R 1
S
Infrastructure Impl
DM
DS 2
Impl
UC 2
<< web app >>
Full application deployed
Uses BDD framework, accessing a testing database and
fake external dependencies
Very few tests at this level, just to make sure
application is wired properly
36. Outside-In vs. Classic TDD
The closer to the input a class is, the more flow control and delegation it does.
The closer to the output a class is, the more specific and less delegation it does.
Using Outside-in TDD starting from Controllers and/or Use Cases.
Model
UC 1
R 3
DS 1
DS 3
R 1
S
Infrastructure Impl
DM
DS 2
Impl
UC 2
<< web app >>
37. Answering the two original questions
What is the application about? (main concepts)
What does the application do? (main features)
Expressed by nouns
Expressed by verbs
(Actions)