Slide 1

Slide 1 text

DDD & REST Domain-Driven APIs for the web / olivergierke Oliver Gierke [email protected]

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

3

Slide 4

Slide 4 text

When designing REST APIs, what can we learn from DDD? “ 4

Slide 5

Slide 5 text

What does it take to bridge the worlds of DDD & REST? “ 5

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

7 http://www.infoq.com/minibooks/domain-driven-design-quickly

Slide 8

Slide 8 text

8

Slide 9

Slide 9 text

8

Slide 10

Slide 10 text

Value objects 9

Slide 11

Slide 11 text

Stringly typed code 10 class Customer { private Long id; private String firstname, lastname, email; … }

Slide 12

Slide 12 text

Stringly typed code 11 class SomeService { void createUser(String firstname, String lastname) { … } }

Slide 13

Slide 13 text

Stringly typed code 12 class SomeService { void createUser(…, String email) { // Valid email address? … } }

Slide 14

Slide 14 text

13 class Customer { private Long id; private Firstname firstname; private Lastname lastname; private EmailAddress emailAddress; … }

Slide 15

Slide 15 text

14 final class EmailAddress { private final String value; static EmailAddress of(String source) { if (!source.matches(…)) { throw new IllegalArgumentException(…); } … } }

Slide 16

Slide 16 text

If you receive an
 instance of a value 
 type, you can be 
 sure it’s valid. 15

Slide 17

Slide 17 text

Stringly typed code 16 class SomeService { void createUser(…, String email) { // Valid email address? } }

Slide 18

Slide 18 text

Strongly typed code 17 class SomeService { void createUser(…, EmailAddress email) { // Valid email address! } }

Slide 19

Slide 19 text

Make implicit
 concepts explicit. 18

Slide 20

Slide 20 text

Entities,
 Aggregates & Repositories 19

Slide 21

Slide 21 text

20 Order LineItem Product Invoice Customer Payment Address Email

Slide 22

Slide 22 text

Don’t get trapped by datastore thinking. 21

Slide 23

Slide 23 text

22 Order LineItem Product Invoice Customer Payment Address Email

Slide 24

Slide 24 text

Aggregates.
 Scopes of consistency. 23

Slide 25

Slide 25 text

24 Order LineItem Product Invoice Customer Payment Address Email

Slide 26

Slide 26 text

Aggregates.
 The key things
 to refer to. 25

Slide 27

Slide 27 text

26 Order LineItem Product Invoice Customer Payment Address Email

Slide 28

Slide 28 text

Bounded Context 27

Slide 29

Slide 29 text

Order LineItem Product Invoice Customer Payment Address

Slide 30

Slide 30 text

29 Shipping Accounting Catalog Orders User
 Registration

Slide 31

Slide 31 text

29 Shipping Accounting Catalog Orders User
 Registration Accounting Payment information Billing Address Shipping Shipping address Customer

Slide 32

Slide 32 text

29 Shipping Accounting Catalog Orders User
 Registration Accounting Payment information Billing Address Shipping Shipping address Customer Product

Slide 33

Slide 33 text

Canonical references
 but data duplication 30

Slide 34

Slide 34 text

Domain Events 31

Slide 35

Slide 35 text

Explicitness
 maturity model 32

Slide 36

Slide 36 text

33 Level 0: No events at all

Slide 37

Slide 37 text

33 Level 0: No events at all Level 1: Explicit operations

Slide 38

Slide 38 text

34 void addToOrder(Order order, Product product, Quantity quantity) { Optional item = order.items.stream()
 .filter(it -> it.product.equals(product)); // Update existing item or create new one if (item.isPresent()) { item.ifPresent(it -> it.increase(quantity)); } else { order.items.add(new LineItem(product, quantity); } }

Slide 39

Slide 39 text

35 class Order { Order add(Product product, Quantity quantity) { // Code goes here… } }

Slide 40

Slide 40 text

If you’re calling two setters in a row, you’re missing a concept. 36

Slide 41

Slide 41 text

37 Level 0: No events at all Level 1: Explicit operations

Slide 42

Slide 42 text

37 Level 0: No events at all Level 1: Explicit operations Level 2: Some operations as events

Slide 43

Slide 43 text

38 class OrderManagement { private final OrderRepository orders; private final Inventory inventory; @Transactional void completeOrder(Order order) { orders.save(order.complete()); order.doWithLineItems(item -> inventory.reduce(item.product, item.quantity)); } }

Slide 44

Slide 44 text

Feature creep 39

Slide 45

Slide 45 text

40 class OrderManagement { private final OrderRepository orders; private final Inventory inventory; private final LoyaltyProgram loyalty; @Transactional void complete(Order order) { orders.save(order.complete()); order.doWithLineItems(item -> inventory.reduce(item.product, item.quantity)); loyalty.update(order); } }

Slide 46

Slide 46 text

Synchronous remote communication 41

Slide 47

Slide 47 text

42 class OrderManagement { private final OrderRepository orders; private final RestOperations operations; @Transactional void completeOrder(Order order) { orders.save(order.complete()); // Update external systems operations.postForEntity(…); operations.postForEntity(…); } }

Slide 48

Slide 48 text

Domain events 43

Slide 49

Slide 49 text

44 class OrderManagement { private final OrderRepository orders; private final ApplicationEventPublisher publisher; @Transactional void completeOrder(Order order) { OrderCompletedEvent event = order.complete(); orders.save(order); publisher.publish(event); } }

Slide 50

Slide 50 text

45 class Inventory { private final InventoryItemRepository items; @EventListener void on(OrderCompletedEvent order) { // Update inventory } }

Slide 51

Slide 51 text

46 class EmailNotification { private final MailSender mailSender; @Async @TransactionalEventListener void on(OrderCompletedEvent order) { // Send emails } }

Slide 52

Slide 52 text

47 class OrderManagement { private final ApplicationEventPublisher publisher; private final OrderRepository orders; @Transactional void completeOrder(Order order) { OrderCompletedEvent event = order.complete(); orders.save(order); publisher.publish(event); } }

Slide 53

Slide 53 text

48 // Super class contains methods with // @DomainEvents und @AfterDomainEventPublication class Order extends AbstractAggregateRoot { Order complete() { register(new OrderCompletedEvent(this)); return this; } }

Slide 54

Slide 54 text

49 class OrderManagement { private final OrderRepository orders; void completeOrder(Order order) { repository.save(order.complete()); } }

Slide 55

Slide 55 text

50 Level 0: No events at all Level 1: Explicit operations Level 2: Some operations as events

Slide 56

Slide 56 text

50 Level 0: No events at all Level 1: Explicit operations Level 2: Some operations as events Level 3: Event Sourcing

Slide 57

Slide 57 text

Domain events as
 state transitions. 51

Slide 58

Slide 58 text

Expose important
 events to interested parties via feeds. 52

Slide 59

Slide 59 text

REST 53

Slide 60

Slide 60 text

REST ≠ 
 CRUD via HTTP 54

Slide 61

Slide 61 text

Representation
 design matters 55

Slide 62

Slide 62 text

Aggregates Identifiable
 Referable
 Scope of consistency 56

Slide 63

Slide 63 text

Resources Identifiable
 Referable
 Scope of consistency 57

Slide 64

Slide 64 text

Hypermedia 58

Slide 65

Slide 65 text

Serving data and navigation information
 at the same time. 59

Slide 66

Slide 66 text

Hypermedia as
 the engine of
 application state 60

Slide 67

Slide 67 text

RESTBucks payment expected preparing cancelled ready completed 1 2 3 4 5 6

Slide 68

Slide 68 text

62 GET /order/4711 { „_links“ : { „cancel“ : { „href“ : … }, … „createdDate“ : …, „status“ : „Payment expected“ … }

Slide 69

Slide 69 text

How does the client
 know if a state
 transition is allowed? 63

Slide 70

Slide 70 text

Option 1:
 Inspecting the payload 64

Slide 71

Slide 71 text

65 GET /order/4711 { „_links“ : { „cancel“ : { „href“ : … }, … „createdDate“ : …, „status“ : „Payment expected“ … }

Slide 72

Slide 72 text

66 “Internationalize
 all user facing text.

Slide 73

Slide 73 text

Aaaargh! 67

Slide 74

Slide 74 text

Option 2:
 Inspecting
 hypermedia elements 68

Slide 75

Slide 75 text

69 GET /order/42 { „_links“ : { „cancel“ : { „href“ : … }, … „createdDate“ : …, „status“ : „Payment expected“ … }

Slide 76

Slide 76 text

Reducing decisions in clients to whether a
 link is present or not. 70

Slide 77

Slide 77 text

Trading domain knowledge with protocol complexity in clients. 71

Slide 78

Slide 78 text

72 Amount of domain knowledge in the client Amount of protocol knowledge in the client Coupling to the server Non-hypermedia
 based systems Hypermedia
 based systems

Slide 79

Slide 79 text

API evolvability is key
 in a system of systems 73 See „Evolving Distributed Systems“

Slide 80

Slide 80 text

Translate backend concepts into web- appropriate ones. 74

Slide 81

Slide 81 text

75 Aggregate Root / Repository Collection / Item Resources IDs URIs @Version ETags Last Modified Property Last Modified Header Relations Links

Slide 82

Slide 82 text

RESTBucks payment expected preparing cancelled ready completed 1 2 3 4 5 6

Slide 83

Slide 83 text

Method URI Action Step POST /orders Create new order 1 POST/PATCH /orders/{id} Update the order (only if "payment expected") 2 DELETE /orders/{id} Cancel order (only if "payment expected") 3 PUT /orders/{id}/payment Pay order (only if "payment expected") 4 Barista preparing the order GET /orders/{id} Poll order state 5 GET /orders/{id}/receipt Access receipt DELETE /orders/{id}/receipt Conclude the order process 6

Slide 84

Slide 84 text

Method Resource type Action Step POST orders Create new order 1 POST/PATCH update Update the order 2 DELETE cancel Cancel order 3 PUT payment Pay order 4 Barista preparing the order GET order Poll order state 5 GET receipt Access receipt DELETE receipt Conclude the order process 6

Slide 85

Slide 85 text

Spring RESTBucks 79

Slide 86

Slide 86 text

Web Service Repository - Orders Spring Data Spring Data
 REST Payment Spring Data Manual
 implementation Manual
 implementation

Slide 87

Slide 87 text

Resources 81 Spring RESTBucks
 https://github.com/olivergierke/spring-restbucks Benefits of Hypermedia APIs
 http://olivergierke.de/2016/04/benefits-of-hypermedia/ Evolving Distributed Systems http://olivergierke.de/2016/10/evolving-distributed-systems/

Slide 88

Slide 88 text

Questions? 82