Designing a Serverless Application with Domain Driven Design - - PowerPoint PPT Presentation

designing a serverless application with domain driven
SMART_READER_LITE
LIVE PREVIEW

Designing a Serverless Application with Domain Driven Design - - PowerPoint PPT Presentation

Designing a Serverless Application with Domain Driven Design Susanne Kaiser Independent Tech Consultant @suksr Costs of Poor Software Quality in the US in 2018 (by CISQ report ) $2,840,000,000,000 TWOTRILLIONEIGHTHUNDREDFOURTYBILLION USD


slide-1
SLIDE 1

Designing a Serverless Application with Domain Driven Design

Susanne Kaiser Independent Tech Consultant @suksr

slide-2
SLIDE 2

$2,840,000,000,000

TWOTRILLIONEIGHTHUNDREDFOURTYBILLION USD

Costs of Poor Software Quality in the US in 2018 (by CISQ report )

Source: https://www.it-cisq.org/the-cost-of-poor-quality-software-in-the-us-a-2018-report

@suksr

slide-3
SLIDE 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

slide-4
SLIDE 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

slide-5
SLIDE 5

Domain Driven Design (DDD)

Business Domain Needs Strategy Software Design

@suksr

slide-6
SLIDE 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

slide-7
SLIDE 7

DDD & Wardley Maps

Value Chain

I n v i s i b l e V i s i b l e

Evolution

Genesis Custom-Built Product (+rental) Commodity (+utility) P

  • s

i t i

  • n

Movement

Uncharted Industrialised @suksr

slide-8
SLIDE 8

Value Chain

I n v i s i b l e V i s i b l e

Evolution

Visualisation of a value chain’s evolution

Genesis Custom-Built Product (+rental) Commodity (+utility) P

  • s

i t i

  • n

Movement

Wardley Maps BY SIMON WARDLEY

Uncharted Industrialised @suksr

slide-9
SLIDE 9

Wardley Maps – VALUE CHAIN

Who are your users?

Value Chain

I n v i s i b l e V i s i b l e

@suksr

slide-10
SLIDE 10

Wardley Maps – VALUE CHAIN

Who are your users? What are your users’ needs?

Value Chain

I n v i s i b l e V i s i b l e

@suksr

slide-11
SLIDE 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?

Value Chain

I n v i s i b l e V i s i b l e P

  • s

i t i

  • n

@suksr

slide-12
SLIDE 12

Wardley Maps – LANDSCAPE

Value Chain

I n v i s i b l e V i s i b l e

Evolution

Components along evolution axes

Genesis Custom-Built Product (+rental) Commodity (+utility) P

  • s

i t i

  • n

Movement

@suksr

slide-13
SLIDE 13

Value Chain

I n v i s i b l e V i s i b l e Genesis Custom-Built Product (+rental) Commodity (+utility)

Evolution

Everything evolves

Past Current Future

Supply Competition Demand Competition

Uncharted Industrialised

Wardley Maps – PATTERNS

Movement

@suksr

slide-14
SLIDE 14

Value Chain

I n v i s i b l e V i s i b l e Genesis Custom-Built Product (+rental) Commodity (+utility)

Evolution

Past Current Future

Characteristics change

Uncharted 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

slide-15
SLIDE 15

Value Chain

I n v i s i b l e V i s i b l e 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

slide-16
SLIDE 16

Value Chain

I n v i s i b l e V i s i b l e 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

slide-17
SLIDE 17

Value Chain

I n v i s i b l e V i s i b l e 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

slide-18
SLIDE 18

Value Chain

I n v i s i b l e V i s i b l e 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

slide-19
SLIDE 19

Value Chain

I n v i s i b l e V i s i b l e 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

slide-20
SLIDE 20

Value Chain

I n v i s i b l e V i s i b l e Genesis Custom-Built Product (+rental) Commodity (+utility)

Evolution

DDD & Wardley Maps

Problem Domain

Strategic Design

DDD Patterns & Practices

Tactical Design

@suksr

slide-21
SLIDE 21

Value Chain

I n v i s i b l e V i s i b l e 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

slide-22
SLIDE 22

Value Chain

I n v i s i b l e V i s i b l e 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

slide-23
SLIDE 23

Value Chain

I n v i s i b l e V i s i b l e 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

P r

  • b

l e m S p a c e

@suksr

slide-24
SLIDE 24

Value Chain

I n v i s i b l e V i s i b l e 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

P r

  • b

l e m S p a c e

@suksr

slide-25
SLIDE 25

Value Chain

I n v i s i b l e V i s i b l e 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

P r

  • b

l e m S p a c e

@suksr

slide-26
SLIDE 26

Value Chain

I n v i s i b l e V i s i b l e 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

P r

  • b

l e m S p a c e

@suksr

slide-27
SLIDE 27

Value Chain

I n v i s i b l e V i s i b l e 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

P r

  • b

l e m S p a c e S

  • l

u t i

  • n

S p a c e

abstracted by @suksr

slide-28
SLIDE 28

Value Chain

I n v i s i b l e V i s i b l e 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

P r

  • b

l e m S p a c e S

  • l

u t i

  • n

S p a c e

Linguistic/semantic boundary Ownership boundary Model boundary Physical boundary Different architectural patterns per context possible @suksr

slide-29
SLIDE 29

Value Chain

I n v i s i b l e V i s i b l e Genesis Custom-Built Product (+rental) Commodity (+utility)

Evolution

P r

  • b

l e m S p a c e Evaluate Submissions Manage Event

Organiser

Build & Publish Schedule Communicate w/ Speakers Signup/Signin

Know your users & focus on user needs

Submit Session

DDD & Wardley Maps

STRATEGIC DESIGN (PROBLEM SPACE) Speaker

@suksr

slide-30
SLIDE 30

Value Chain

I n v i s i b l e V i s i b l e Genesis Custom-Built Product (+rental) Commodity (+utility)

Evolution

P r

  • b

l e m S p a c e Evaluate Submissions Manage Event

Organiser

Build & Publish Schedule Communicate w/ Speakers Signup/Signin

Speaker

Submit Session

DDD & Wardley Maps

STRATEGIC DESIGN (PROBLEM SPACE)

Discovering subdomains

Supporting Generic Core @suksr

slide-31
SLIDE 31

Value Chain

I n v i s i b l e V i s i b l e Genesis Custom-Built Product (+rental) Commodity (+utility)

Evolution

P r

  • b

l e m S p a c e Evaluate Submissions Manage Event

Organiser

Build & Publish Schedule Communicate w/ Speakers Signup/Signin

Speaker

Submit Session

DDD & Wardley Maps

STRATEGIC DESIGN (SOLUTION SPACE)

Supporting Generic Core

Event Evaluation Account Schedule Message Session

Domain Models

S

  • l

u t i

  • n

S p a c e

@suksr

slide-32
SLIDE 32

Value Chain

I n v i s i b l e V i s i b l e Genesis Custom-Built Product (+rental) Commodity (+utility)

Evolution

P r

  • b

l e m S p a c e Evaluate Submissions Manage Event

Organiser

Build & Publish Schedule Communicate w/ Speakers Signup/Signin

Speaker

Submit Session

DDD & Wardley Maps

Supporting Generic Core

Event Evaluation Account Schedule Message Speaker Session CfP S

  • l

u t i

  • n

S p a c e

STRATEGIC DESIGN (SOLUTION SPACE)

Domain Models

@suksr

slide-33
SLIDE 33

Value Chain

I n v i s i b l e V i s i b l e Genesis Custom-Built Product (+rental) Commodity (+utility)

Evolution

P r

  • b

l e m S p a c e Evaluate Submissions Manage Event

Organiser

Build & Publish Schedule Communicate w/ Speakers Signup/Signin

Speaker

Submit Session

DDD & Wardley Maps

Supporting Generic Core

Event Evaluation Account Schedule Message Speaker Profile Submitted Session CfP Settings Recipient Open CfP Evaluated Session Scheduled Session S

  • l

u t i

  • n

S p a c e

STRATEGIC DESIGN (SOLUTION SPACE)

Domain Models

@suksr

slide-34
SLIDE 34

Value Chain

I n v i s i b l e V i s i b l e Genesis Custom-Built Product (+rental) Commodity (+utility)

Evolution

P r

  • b

l e m S p a c e Evaluate Submissions Manage Event

Organiser

Build & Publish Schedule Communicate w/ Speakers Signup/Signin

Speaker

Submit Session

DDD & Wardley Maps

Supporting Generic Core

S

  • l

u t i

  • n

S p a c e

STRATEGIC DESIGN (SOLUTION SPACE)

Bounded Contexts

Linguistic/semantic boundary Model integrity boundary

Event Evaluation Account Schedule Message Submitted Session CfP Settings Recipient Open CfP Evaluated Session Scheduled Session Speaker Profile Session Evaluation Submission Handling Event Mngmnt. Schedule Mngmnt. Messaging Account Handling

@suksr

slide-35
SLIDE 35

Value Chain

I n v i s i b l e V i s i b l e Genesis Custom-Built Product (+rental) Commodity (+utility)

Evolution

P r

  • b

l e m S p a c e Evaluate Submissions Manage Event

Organiser

Build & Publish Schedule Communicate w/ Speakers Signup/Signin

Speaker

Submit Session

DDD & Wardley Maps

Supporting Generic Core

S

  • l

u t i

  • n

S p a c e

STRATEGIC DESIGN (SOLUTION SPACE)

Submission Handling Event Mngmnt. Session Evaluation Messaging Account Handling Schedule Mngmnt.

Bounded Contexts

Ownership boundary Linguistic/semantic boundary Model integrity boundary @suksr

slide-36
SLIDE 36

Value Chain

I n v i s i b l e V i s i b l e Genesis Custom-Built Product (+rental) Commodity (+utility)

Evolution

P r

  • b

l e m S p a c e Evaluate Submissions Manage Event

Organiser

Build & Publish Schedule Communicate w/ Speakers Signup/Signin

Speaker

Submit Session

DDD & Wardley Maps

Supporting Generic Core

S

  • l

u t i

  • n

S p a c e

STRATEGIC DESIGN (SOLUTION SPACE)

Submission Handling Event Mngmnt. Session Evaluation Messaging Account Handling Schedule Mngmnt.

Bounded Contexts

Ownership boundary Linguistic/semantic boundary Model integrity boundary Physical boundary

SCM Data store CI/CD Artefact

@suksr

slide-37
SLIDE 37

Value Chain

I n v i s i b l e V i s i b l e Genesis Custom-Built Product (+rental) Commodity (+utility)

Evolution

P r

  • b

l e m S p a c e Evaluate Submissions Manage Event

Organiser

Build & Publish Schedule Communicate w/ Speakers Signup/Signin

Speaker

Submit Session

DDD & Wardley Maps

Supporting Generic Core

S

  • l

u t i

  • n

S p a c e

TACTICAL DESIGN

Submission Handling Event Mngmnt. Session Evaluation Messaging Account Handling Schedule Mngmnt.

Architectural Patterns

Architectural patterns can differ per Bounded Context, e.g.

S t r a t e g i c D e s i g n T a c t i c a l D e s i g n Layered Architecture Hexagonal Architecture CQRS

@suksr

slide-38
SLIDE 38

Hexagonal Architecture

Business Logic Application REST-API Port Port

Message Broker

Adapter Adapter Adapter Port Inner Outer Outside

@suksr

slide-39
SLIDE 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

slide-40
SLIDE 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 Adapter

Port Lambda Function Lambda Function

Hexagonal Architecture

BOUNDED CONTEXT: EVENT MANAGEMENT

@suksr

slide-41
SLIDE 41

Hexagonal Architecture

Business Logic Application Port BOUNDED CONTEXT: EVENT MANAGEMENT

EventController

AWS API Gateway Port

Data Storage with AWS DynamoDB

DynamoDBEventRepository

Inner Outer Outside

@suksr

slide-42
SLIDE 42

export default class DynamoDBEventRepository implements EventRepository { private static TABLE_NAME: string = "events"; private readonly dynamoDbClient: AWS.DynamoDB.DocumentClient; constructor() { this.dynamoDbClient = new AWS.DynamoDB.DocumentClient(); } public async eventOfId(id: EventId): Promise<Event|null> { const params : DocumentClient.GetItemInput = { TableName: DynamoDBEventRepository.TABLE_NAME, Key: { eventId: id } }; const result: DocumentClient.GetItemOutput = await this.dynamoDbClient.get(params).promise(); const item: AttributeMap|undefined = result.Item; if (item) { const id = new EventId(item.eventId); const name = Name.create(item.name); const description = Description.create(item.description); const period = Period.create(item.period.startDate, item.period.endDate); return Event.create(id, name, item.eventStatus, period, description); } return null; } public saveEvent(event: Event) { const params : DocumentClient.PutItemInput = { // ... // }; return this.dynamoDbClient.put(params).promise(); } }

Hexagonal Architecture

Database Adapter

Port DynamoDB Client BOUNDED CONTEXT: EVENT MANAGEMENT

@suksr

slide-43
SLIDE 43

Hexagonal Architecture

Business Logic Application Port BOUNDED CONTEXT: EVENT MANAGEMENT

EventController

AWS API Gateway Port

DynamoDBEventRepository

Business Logic Implementation

Inner Outer Outside

@suksr

slide-44
SLIDE 44

Value Chain

I n v i s i b l e V i s i b l e Genesis Custom-Built Product (+rental) Commodity (+utility)

Evolution

Evaluate Submissions Manage Event

Organiser

Build & Publish Schedule Communicate w/ Speakers Signup/Signin

Speaker

Submit Session

DDD & Wardley Maps

Supporting Generic Core

TACTICAL DESIGN

Submission Handling Event Mngmnt. Session Evaluation Messaging Account Handling Schedule Mngmnt.

Business Logic Implementation Patterns

Business logic implementation patterns can differ per Bounded Context, e.g.

Domain Model Active Record Transaction Script

@suksr

P r

  • b

l e m S p a c e S

  • l

u t i

  • n

S p a c e S t r a t e g i c D e s i g n T a c t i c a l D e s i g n

slide-45
SLIDE 45

Value Chain

I n v i s i b l e V i s i b l e Genesis Custom-Built Product (+rental) Commodity (+utility)

Evolution

Evaluate Submissions Manage Event

Organiser

Build & Publish Schedule Communicate w/ Speakers Signup/Signin

Speaker

Submit Session

DDD & Wardley Maps

Supporting Generic Core

TACTICAL DESIGN

Submission Handling Event Mngmnt. Session Evaluation Messaging Account Handling Schedule Mngmnt.

Building Blocks of Domain Models

  • Value Object
  • Entity
  • Aggregate
  • Repository
  • ApplicationService
  • Domain Event
  • ...

@suksr

P r

  • b

l e m S p a c e S

  • l

u t i

  • n

S p a c e S t r a t e g i c D e s i g n T a c t i c a l D e s i g n

slide-46
SLIDE 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

slide-47
SLIDE 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

slide-48
SLIDE 48

Domain Model

BC: EVENT MANAGEMENT Application

EventController

AWS API Gateway

DynamoDBEventRepository

Event

EventApplicationService EventRepository @suksr

slide-49
SLIDE 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

slide-50
SLIDE 50

Domain Model

EVENT MANAGEMENT Application

EventController

AWS API Gateway

DynamoDBEventRepository

Event

EventApplicationService EventRepository

export default interface EventRepository { saveEvent(event: Event): void; eventOfId(id: EventId): Promise<Event|null>; // ... // }

@suksr

slide-51
SLIDE 51

Value Chain

I n v i s i b l e V i s i b l e Genesis Custom-Built Product (+rental) Commodity (+utility)

Evolution

Evaluate Submissions Manage Event

Organiser

Build & Publish Schedule Communicate w/ Speakers Signup/Signin

Speaker

Submit Session

DDD & Wardley Maps

Supporting Generic Core

TACTICAL DESIGN

Submission Handling Event Mngmnt. Session Evaluation Messaging Account Handling Schedule Mngmnt.

DDD suits best for the core subdomain

Movement

Build in-house Use/buy off-the-shelf product Outsource to utility suppliers

  • or -
  • or -

@suksr

P r

  • b

l e m S p a c e S

  • l

u t i

  • n

S p a c e S t r a t e g i c D e s i g n T a c t i c a l D e s i g n

slide-52
SLIDE 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 ...

slide-53
SLIDE 53

Some References

https://learnwardleymapping.com/ https://medium.com/wardleymaps https://miro.com/blog/wardley-maps-whiteboard-canvas/ https://community.wardleymaps.com/