With Serverless/FaaS the unit of work is a fine-grained, ephemeral function triggered by a variety of events. How can we design a system composed of countless functions without loosing sight of each function's purpose or without accidentally introducing a big ball of mud due to highly coupled functions. One approach could be by introducing Domain Driven Design (DDD). DDD is a methodology to capture a business domain as closely as possible into software coming with strategic and tactical design patterns. DDD helps to decompose a system into modular components (Bounded Contexts) and mapping the integration patterns between them (Context Mapping).
In this talk, I am going to highlight how Domain Driven Design and Serverless/FaaS can go together by splitting a system into Bounded Contexts and how these Bounded Contexts can be implemented by using Serverless technologies.
3. Areas of Cost Relating To Poor Software Quality
Source: https://www.it-cisq.org/the-cost-of-poor-quality-software-in-the-us-a-2018-report @suksr
4. Some Indicators for Poor Software Quality (extracted from CISQ report )
t
Defects
0%
Increasing defect trend
Low test coverage
Cyclomatic complexity
Large inheritance depth
High amount of effort to
understand piece of code
Badly engineered
software
Lack of domain
knowledge
Based on: https://www.it-cisq.org/the-cost-of-poor-quality-software-in-the-us-a-2018-report
Communication and
coordination breakdowns
in (large) teams
High degree of class
coupling
@suksr
6. Domain Driven Design (DDD) – Terminology
Strategic Design
Tactical Design
Bounded Context
Ubiquitous Language
Core Subdomain
Supporting Subdomain
Generic Subdomain
Problem Space
Solution Space
Context Maps
Anti-Corruption Layer
Shared Kernel
Open Host Service
Separate Ways
Partnership
Customer-Supplier
Conformist
Domain Model
Entity
Value Object
Aggregate
Repository
Factory
Application Service
Domain Service
Domain Event
@suksr
7. DDD & Wardley Maps
ValueChainInvisibleVisible
Evolution
Genesis Custom-Built Product (+rental) Commodity
(+utility)
Position
Movement
Uncharted Industrialised
@suksr
9. Wardley Maps – VALUE CHAIN
Who are your users?
ValueChain
InvisibleVisible
@suksr
10. Wardley Maps – VALUE CHAIN
Who are your users?
What are your users’ needs?
ValueChain
InvisibleVisible
@suksr
11. Wardley Maps – VALUE CHAIN
Who are your users?
What are your users’ needs?
What are the components/activities to fulfill
your users’ needs incl. dependencies?
ValueChain
InvisibleVisible
Position
@suksr
12. Wardley Maps – LANDSCAPE
ValueChain
InvisibleVisible
Evolution
Components along
evolution axes
Genesis Custom-Built Product (+rental) Commodity (+utility)
Position
Movement
@suksr
13. ValueChain
InvisibleVisible
Genesis Custom-Built Product (+rental) Commodity (+utility)
Evolution
Everything evolves
Past Current Future
Supply CompetitionDemand Competition
Uncharted Industrialised
Wardley Maps – PATTERNS
Movement
@suksr
14. ValueChain
InvisibleVisible
Genesis Custom-Built Product (+rental) Commodity (+utility)
Evolution
Past Current Future
Characteristics changeUncharted
Undefined market
Uncertain
Unpredictable
Rare
Poorly understood
Forming market
Learning on use
Increasing understanding
Slowly increasing
consumption
Rapid increases in
learning
Growing market
Learning on operation
Increasing education
Rapidly increasing
consumption
Rapid increase in use
Mature market
Known / accepted
Stable
Widespread and stabilising
Commonly understood
(in term of use)
Industrialised
Wardley Maps – PATTERNS
Movement
@suksr
15. ValueChain
InvisibleVisible
Genesis Custom-Built Product (+rental) Commodity (+utility)
Evolution
Wardley Maps – PRINCIPLES
Use appropriate methods
per evolution stage
Build in-house
Use/buy off-the-shelf product
Outsource to utility suppliers
@suksr
16. ValueChain
InvisibleVisible
Genesis Custom-Built Product (+rental) Commodity (+utility)
Evolution
Use appropriate methods
per evolution stage
Wardley Maps – PRINCIPLES
Build in-house
Use/buy off-the-shelf product
Outsource to utility suppliers
@suksr
17. ValueChain
InvisibleVisible
Genesis Custom-Built Product (+rental) Commodity (+utility)
Evolution
Use appropriate methods
per evolution stage
Wardley Maps – PRINCIPLES
Build in-house
Use/buy off-the-shelf product
Outsource to utility suppliers
@suksr
18. ValueChain
InvisibleVisible
Genesis Custom-Built Product (+rental) Commodity (+utility)
Evolution
Know your users &
focus on user needs
Wardley Maps – PRINCIPLES
Build in-house / Agile
Use/buy off-the-shelf product / Lean
Outsource to utility suppliers / Six Sigma
@suksr
19. ValueChain
InvisibleVisible
Genesis Custom-Built Product (+rental) Commodity (+utility)
Evolution
DDD & Wardley Maps
Ubiquitous Language
Domain Knowledge
Understanding the problem domain first
Problem Domain
Domain
Experts
Development
Teams
Collaboration
@suksr
21. ValueChain
InvisibleVisible
Genesis Custom-Built Product (+rental) Commodity (+utility)
Evolution
DDD & Wardley Maps Problem Domain
Strategic Design
DDD Patterns &
Practices
Tactical Design
Analysing the
business
domain
Discovering
Subdomains
Problem Space
Decomposing
into modular
components
(Bounded
Contexts)
Mapping
interaction
patterns
between BC
(Context Maps)
Solution Space
@suksr
22. ValueChain
InvisibleVisible
Genesis Custom-Built Product (+rental) Commodity (+utility)
Evolution
DDD & Wardley Maps Problem Domain
Strategic Design
DDD Patterns &
Practices
Tactical Design
Architecting a solution
fitting the problem
domain as closely as
possible
Provides
building blocks
to implement
domain model
Analysing the
business
domain
Discovering
Subdomains
Problem Space
Decomposing
into modular
components
(Bounded
Contexts (BC)
Mapping
interaction
patterns
between BC
(Context Maps)
Solution Space
@suksr
Solution Space
23. ValueChain
InvisibleVisible
Genesis Custom-Built Product (+rental) Commodity (+utility)
Evolution
Distilling the problem
domain & discovering the
core subdomain
DDD & Wardley Maps
Core
Subdomain
Problem Domain
STRATEGIC DESIGN (PROBLEM SPACE)
Supporting
Subdomain
Generic
Subdomain
ProblemSpace
@suksr
24. ValueChain
InvisibleVisible
Genesis Custom-Built Product (+rental) Commodity (+utility)
Evolution
Distilling the problem
domain & discovering the
core subdomain
DDD & Wardley Maps
Core
Subdomain
Problem Domain
Competitive advantage
Complex
Changes often
Build in-house
STRATEGIC DESIGN (PROBLEM SPACE)
Supporting
Subdomain
Generic
Subdomain
ProblemSpace
@suksr
25. ValueChain
InvisibleVisible
Genesis Custom-Built Product (+rental) Commodity (+utility)
Evolution
Distilling the problem
domain & discovering the
core subdomain
DDD & Wardley Maps
Core
Subdomain
Problem Domain
Competitive advantage
Complex
Changes often
Build in-house
No competitive advantage
Quite simple
Does not change often
Prefer to buy/use off-the-shelf
STRATEGIC DESIGN (PROBLEM SPACE)
Supporting
Subdomain
Generic
Subdomain
ProblemSpace
@suksr
26. ValueChain
InvisibleVisible
Genesis Custom-Built Product (+rental) Commodity (+utility)
Evolution
Distilling the problem
domain & discovering the
core subdomain
DDD & Wardley Maps
Core
Subdomain
Problem Domain
Competitive advantage
Complex
Changes often
Build in-house
No competitive advantage
Quite simple
Does not change often
Prefer to buy/use off-the-shelf
No competitive advantage
Generally complex
Does not change often
Buy/use off-the-shelf / outsource
STRATEGIC DESIGN (PROBLEM SPACE)
Supporting
Subdomain
Generic
Subdomain
ProblemSpace
@suksr
27. ValueChain
InvisibleVisible
Genesis Custom-Built Product (+rental) Commodity (+utility)
Evolution
Model Driven Design
DDD & Wardley Maps
STRATEGIC DESIGN (SOLUTION SPACE)
Development
Teams
Domain
Experts
Ubiquitous
Language
Analysis
Model
Code
Model
Domain Model
Core
Subdomain
Supporting
Subdomain
Generic
Subdomain
Problem Domain
ProblemSpaceSolutionSpace
abstracted by
@suksr
28. ValueChain
InvisibleVisible
Genesis Custom-Built Product (+rental) Commodity (+utility)
Evolution
Bounded Contexts
DDD & Wardley Maps
STRATEGIC DESIGN (SOLUTION SPACE)
Core
Subdomain
Supporting
Subdomain
Generic
Subdomain
Problem Domain
ProblemSpaceSolutionSpace
Linguistic/semantic
boundary
Ownership boundary
Model boundary
Physical boundary
Different architectural
patterns per context
possible
@suksr
39. Hexagonal Architecture
Business
Logic
Application
Port
Adapter
BOUNDED CONTEXT: EVENT MANAGEMENT
EventController
AWS API Gateway
Port
REST-API with
AWS API-Gateway and
AWS Lambda
EventController
AWS API Gateway
newEvent deleteEvent activateEvent
POST
/events
DELETE
/events/{id}
POST
/events/{id}/activate
Inner
Outer
Outside
@suksr
40. export class EventsController {
private readonly eventsService: EventApplicationService;
public constructor(eventsService: EventApplicationService) {
this.eventsService = eventsService;
}
public activateEvent: Handler = async (event: APIGatewayEvent, context: Context, callback: Callback) => {
if (!event.pathParameters) {
return callback(undefined, failure({ status: "error", error: "no event id specified" }));
}
if (!event.requestContext.authorizer) {
return callback(undefined, failure({ status: "error", error: "no authorized user specified" }));
}
try {
const eventId = new EventId(event.pathParameters.id);
const userId = new UserId(event.requestContext.authorizer.claims['cognito:username']);
await this.eventsService.activateEvent(eventId, userId);
callback(undefined, success({status: "ok"}));
} catch(e) {
return callback(undefined, failure({ status: "error", error: e }));
}
};
public newEvent: Handler = async (event: APIGatewayEvent, context: Context, callback: Callback) => {
// ... //
}
REST-API
AdapterPort
Lambda
Function
Lambda
Function
Hexagonal Architecture
BOUNDED CONTEXT: EVENT MANAGEMENT
@suksr
46. Domain Model
BC: EVENT MANAGEMENT
Event
create: Event
activate
reschedule
rename
EventId
id: string
Name
create: Name
name: string
EventStatus
CREATED
ACTIVATED
DEACTIVATED
deactivate
Description
create:
Description
desc: string
Period
create: Period
start: Date
end: Date
Value
Object
Entity
Aggregate
Root
Aggregate
Application
Port
EventController
AWS API Gateway
Port
DynamoDBEventRepository
Event
@suksr
47. export default class Event {
readonly id: EventId;
name: Name;
description?: Description;
status: EventStatus;
period: Period;
private constructor(id: EventId, name: Name, status: EventStatus, period: Period, description?: Description) {
this.id = id;
this.name = name;
this.description = description;
this.status = status;
this.period = period;
}
public activate() {
if (this.status === EventStatus.CLOSED) {
throw new Error("You cannot activate a closed event");
}
if (this.status === EventStatus.ACTIVATED) {
throw new Error("This event has already been activated");
}
this.status = EventStatus.ACTIVATED;
}
public rename(name: Name) {
if (!name) {
throw new Error("You cannot rename the event to an empty name");
}
this.name = name;
}
// ... //
}
Aggregate
@suksr
48. Domain Model
BC: EVENT MANAGEMENT
Application
EventController
AWS API Gateway
DynamoDBEventRepository
Event
EventApplicationService
EventRepository
@suksr
49. export default class EventApplicationService {
private readonly eventRepository: EventRepository;
constructor(eventRepository: EventRepository) {
this.eventRepository = eventRepository;
}
public async activateEvent(id: EventId) {
const event = await this.eventRepository.eventOfId(id);
if (!event) {
throw new Error("Could not deactivate event with id " + id + ", since event does not exist.");
}
event.activate();
await this.eventRepository.saveEvent(event);
}
// ... //
}
ApplicationService
Domain Model
EVENT MANAGEMENT
@suksr
52. Business
Domain
Needs Strategy
Better Software Design
Ubiquitous Language
Domain Knowledge
Domain
Experts
Development
Teams
Collaboration
Gaining Domain Knowledge
Aligning Software Design
to Business Domain
Core
Subdomain
Discovering the
Core Subdomain
Do not apply DDD
everywhere!
Focus on your core!
Core
Subdomain
DDD helps with ...
@suksr
But ...