Upgrade to Pro — share decks privately, control downloads, hide ads and more …

DDD & REST — Domain-Driven APIs for the web

DDD & REST — Domain-Driven APIs for the web

Slides of the talk I gave at OOP 2017, Munich.

@springcentral

Oliver Drotbohm

February 02, 2017
Tweet

More Decks by Oliver Drotbohm

Other Decks in Programming

Transcript

  1. 3

  2. 8

  3. 8

  4. Stringly typed code 10 class Customer { private Long id;

    private String firstname, lastname, email; … }
  5. 13 class Customer { private Long id; private Firstname firstname;

    private Lastname lastname; private EmailAddress emailAddress; … }
  6. 14 final class EmailAddress { private final String value; static

    EmailAddress of(String source) { if (!source.matches(…)) { throw new IllegalArgumentException(…); } … } }
  7. If you receive an
 instance of a value 
 type,

    you can be 
 sure it’s valid. 15
  8. 29 Shipping Accounting Catalog Orders User
 Registration Accounting Payment information

    Billing Address Shipping Shipping address Customer Product
  9. 34 void addToOrder(Order order, Product product, Quantity quantity) { Optional<LineItem>

    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); } }
  10. 37 Level 0: No events at all Level 1: Explicit

    operations Level 2: Some operations as events
  11. 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)); } }
  12. 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); } }
  13. 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(…); } }
  14. 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); } }
  15. 45 class Inventory { private final InventoryItemRepository items; @EventListener void

    on(OrderCompletedEvent order) { // Update inventory } }
  16. 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); } }
  17. 48 // Super class contains methods with // @DomainEvents und

    @AfterDomainEventPublication class Order extends AbstractAggregateRoot { Order complete() { register(new OrderCompletedEvent(this)); return this; } }
  18. 50 Level 0: No events at all Level 1: Explicit

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

    operations Level 2: Some operations as events Level 3: Event Sourcing
  20. 62 GET /order/4711 { „_links“ : { „cancel“ : {

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

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

    „href“ : … }, … „createdDate“ : …, „status“ : „Payment expected“ … }
  23. 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
  24. API evolvability is key
 in a system of systems 73

    See „Evolving Distributed Systems“
  25. 75 Aggregate Root / Repository Collection / Item Resources IDs

    URIs @Version ETags Last Modified Property Last Modified Header Relations Links
  26. 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
  27. 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
  28. Web Service Repository - Orders Spring Data Spring Data
 REST

    Payment Spring Data Manual
 implementation Manual
 implementation