That Conference 2016, Kalahari Resort, Lake Delton, WI
Clean Architecture: Patterns, Practices, and Principles
Matthew Renze – @matthewrenze
Day 3, 10 Aug 2016
Disclaimer: This post contains my own thoughts and notes based on attending That Conference 2016 presentations. Some content maps directly to what was originally presented. Other content is paraphrased or represents my own thoughts and opinions and should not be construed as reflecting the opinion of the speakers.
Executive Summary
- A whirlwind overview of domain-centric architecture and discussion of its merits
- Overview of CQRS architectures (Command and Query Responsibility Segregation)
- Brief mention of microservices architectures
Story – Tale of two architecures
- John/Jane, same expertise
- Hire them to design two buildings, same purpose
- John
- Superstar, creates the architecture, hands off to builder
- Jane
- Starts by talking to inhabitants and crews
- Then involved during construction, helping implement
- Tweaks plan as necessary
- Captures essence of difference between clean architecture and traditional
About Me
- Consultant
- Pluralsight
- Msft MVP
Focus
- Enterprise architecture
- Line-of-business applications
- Modern equivalent of 3-layer
- Will talk about 6 key ideas
What is software architecture?
- High-level – higher level than the code
- Structure
- Layers – vertical partitions of system
- Components – sub-divisions of layers, or horizontal
- Relationships – how wired
Levels of architectural abstraction
- System
- Sub-systems
- Layers
- Components
- Classes
- Data and methods
Messy vs. Clean Architecture
- Bad – like spaghetti
- Good – lasagna
- Nice layers
What is Bad Architecture?
- Complex – accidental
- Inconsistent
- Incoherent – things don’t fit
- Rigid – not adaptible
- Brittle
- Untestable
- Unmaintainable
Clean Architecture
- Simple
- Understandable – easy to reason about
- Flexible
- Emergent
- Testable
- Maintainable – easier to maintain over lifetime
Clean architecture
- Architecture that is designed for inhabitants of the architecture
- Not for architect
- Or for machine
- Start designing architecture for inhabitants
- This is the primary concern
- Everything else is secondary
Why is clean architecture important?
- Cost/benefit
- Minimize cost to maintain
- Good to optimize for maintainability
- Since most cost is spent during maintenance
- Maximize business value
Decisions
- Context is king
- Answer always depends on context
- All decisions are a tradeoff
- Use your best judgment
Domain-Centric Architecture
- Heliocentric was more elegant model of the solar system
Classic 3-layer architecture
- Database at central, then data access, business logic
Domain-centric
- Domain at center
- Application around that
- Then Application
- Database hung off the side
Uncle Bob
- Most important thing is that the architecture is usable
Essential vs. Detail (e.g. for house)
- Space is essential
- Usability is essential
- Building material is a detail
- Ornamentation is a detail
Essential vs. Detail (Clean architecture)
- Domain is essential
- Domain: series of object models at center
- Mirrors the mental models of the domain
- Use cases are essential
- And users
- Presentation is a detail
- Persistence is a detail
- Can store in relational DB, NoSql, doc DB, etc.
Back to domain-centric diagram
- What is essential is at the center of the diagram
- Domain essential
- At center
- Everything points towards the domain
Hexagonal architecture
- Application layer (domain) at center
- Adapting to presentation
- Adapting to do input
- Adapting to persistence
Onion Architecture
- Domain Model at center
- Services
- UI at outer
The Clean Architecture (Uncle Bob’s)
- Entities at center
- Use Cases
- Controllers
- Outside: Devices, Web, UI, External Interfaces
It’s all the same thing
- All three of these are fundamentally the same
- Domain at the center
Why use domain-centric architecture?
- Pros
- Focus on essential
- Less coupling to details
- Necessary for DDD
- Cons
- Change is difficult
- Requires extra thought
- Initial higher cost
Application Layer
- Might embed use cases as high-level logic
What are layers?
- Levels of abstraction
- Single-Responsibility
- Developer roles/skills
- Multiple implementations
Classic 3-layer architecture
- Database at bottom
- Data Access
- Business Logic
- UI
- Users
- Top layers dependent on layer below it
Modern 4-layer architecture
- Presentation at top
- Application below that
- Domain layer
- Only domain logic
- Persistence below application
- Access to DB
- Infrastructure below application
- Access to OS
Application layer
- Implements use cases
- High-level application logic
- Knows about domain layer but not persistence or infrastructure
- No knowledge of upper layers
Layer Dependencies
- Dependency inversion
- Inversion of control
- Details depend on abstractions
- Independent deployability
- Flexibility and maintainability
- Flow of control
- Presentation calls Application
- Persistance calls Application
Example
- Presentation layer w/controller
- Application
- Command dep on IDatabaseContext, IInventoryClient
- Application–what the users are doing with the system
- E.g. ICreateSalesCommand
- Dep on Sale in Domain
- Domain–objects in system
- e.g. Sale object
- Domain–objects in system
- Interface in cross-cutting concerns
Why use an application layer?
- Pros
- Focus is on use cases
- Easy to understand
- Follows DIP – Dependency Inversion Principle
- Cons
- Additional cost
- Requires extra thought
- What is application logic vs. domain logic ?
- IoC is counter-intuitive
Commands and Queries
- Keep separated
- Command
- Do something
- Modifies state
- Should not return value
- Queries
- Answer question
- Do not modify state
- Always returns value
- Why?
- Avoid side-effects
- Sometimes odd, exceptions
- E.g. create record, return it
CQRS Architectures
- Application layer, separate into two parts
- Left
- Queries
- Data Access
- Right
- Commands
- Domain
- Persistence
- Database at bottom
- Data flow
- Down through commands
- Up through queries
- CQRS is domain architecture done in sensible way
CQRS Type 1 – Single Database
- Single database, typically NoSQL
- Persistence layer might be something like EF
- Queries – stored proc, linq to sql
CQRS Type 2 – Read/Write Databases
- Command stack leads to Write Database
- 3NF
- Read database
- 1NF, optimized for reads
- Use “eventually consistent” model to push data across from write to read
- Orders of magnitude performance improvement over single database
- Because we mostly do reads, not writes
CQRS Type 3 – Event Sourcing
- Command stack leads to Event Store
- Read database under query stack
- Replay events to get current state of entity (from deltas)
- State modifications pushed over to Read Database
Type 3 points
- Complete audit trail
- Point-in-time reconstruction
- Replay events
- Rebuild production database
- Just by replaying events
- Only worth doing if you need these features
Why use CQRS?
- Pros
- More efficient design
- Simpler within each stack
- At expense of inconsistency across stacks
- Optimized performance
- Of each side
- Cons
- Inconsistent across stacks
- More complexity
- Type 2 is more complex
- Adds consistency model
- Type 3 might be overkill
- If you don’t get business value from these features
- Inconsistent across stacks
Functional organization
- Screaming architecture
- Architecture should scream the intent of the system
- Organize architecture around use cases
- Uncle Bob
Building metaphor
- House, typical
- Intent – residential
- Rooms embody uses–bedroom, kitchen, living room
- Architecture shows use
- Look at list of components, rather than architectural diagram
- Can’t infer intent
Software intent
- Could organize folders by components (models, views, controllers)
- Or organize by things
- Customers, products, vendors
This vs. that
- Traditional
- Content, Controllers, Models, Scripts
- Functional
- Customer
- Product
So what?
- Functional cohesion is more efficient
- Because it better models how we think about the software
Why use functional organization
- Pros
- Spatial locality
- Easy to navigate
- Avoid vendor lock-in
- Cons
- Lose framework conventions
- Lose automatic scaffolding
- Categorical is easier at first
Microservices
Components
- Horizontal – UI, business, data access
- Vertical – Sales, Support, Inventory
- UI presents all vertical pieces as single unified UI
Problem Domain
- Sales and Support
Single domain model
- Traditionally, create single domain model
- E.g. Product on both sides, so we have single Product entity
- Employee – sales or service
- Problem
- Becomes exponentially more difficult
Bounded contexts
- Sales and support as boundaries
- Some entities in just Sales
- Some in Support
- Some in overlap
- Then pull apart and have separate models for each context
Microservice architectures
- Subdivide system
- Communicate with each other via lightweight mechanisms
- Bounded contexts
- Can have one agile team per bounded context
- Only have to know about one bounded context
- Small teams
- Qualities
- Independent
- Similar to SOA
- Independently deploy and scale each microservice
- Size of microservices
- Ongoing debate
- Bounding context maps to microservice
- So persistence model matches context matches service
- “Goldilocks” point
Why use microservices?
- Pros
- Less cost for large domains
- Smaller teams
- Independence
- Don’t need to know what other teams are doing
- Cons
- Only for large domains
- Overkill for small domains
- Lot of overhead cost for microservice
- Higher up-front cost
- Fault tolerance, latency, load balancing
- Might start with single system, split when you have multiple bounded contexts
- – Distributed system costs
- Only for large domains
Code Demo
- Solution architecture for simple web site
- ASP.NET MVC 5
- Top-level folders
- Application, Common, Domain, Infrastruccture, Peristence, Presentation
- Presentation, Sales folder
- sub-folders Models, Services, views
- Application layer
- Sales | Commands, Queries
- Under Commands, folder for each command
- Domain layer
- Fairly thin object model
- But a small amount of business logic in the objects
Where to go next
- Patterns of Enterprise Application Architecture – Fowler
- Bliki has updated stuff
- Clean Code – Uncle Bob
- cleancoders.com
- Great
- Domain-Driven Design – Evans
- For complex domains
- Greg Young, Udi Dahan
- CQRS event sourcing
- matthewrenze.com
- Pluralsight courses as well