alexey.merson@gmail.com 2 - - PowerPoint PPT Presentation

alexey merson gmail com 2 3
SMART_READER_LITE
LIVE PREVIEW

alexey.merson@gmail.com 2 - - PowerPoint PPT Presentation

Domain Driven Design: alexey.merson@gmail.com 2 3 4 5 6 7 8 DDD 9 Domain Driven Design:


slide-1
SLIDE 1

Domain Driven Design: рецепт для прагматика

Алексей Мерсон alexey.merson@gmail.com

slide-2
SLIDE 2

2

slide-3
SLIDE 3

3

slide-4
SLIDE 4

4

slide-5
SLIDE 5

5

slide-6
SLIDE 6

6

slide-7
SLIDE 7

7

slide-8
SLIDE 8

8

slide-9
SLIDE 9

DDD

9

slide-10
SLIDE 10

Domain Driven Design:

Стратегическое проектирование Взаимодействие между людьми Подходы к архитектуре Тактические паттерны Борьба со сложностью

10

slide-11
SLIDE 11

11

slide-12
SLIDE 12

12

slide-13
SLIDE 13

13

slide-14
SLIDE 14

14

slide-15
SLIDE 15

15

slide-16
SLIDE 16

Ключевые идеи стратегического проектирования

16

slide-17
SLIDE 17

17

Доменные эксперты

slide-18
SLIDE 18

18

Доменные эксперты Технические специалисты

slide-19
SLIDE 19

19

Доменные эксперты Технические специалисты

slide-20
SLIDE 20

20

Доменные эксперты Технические специалисты

slide-21
SLIDE 21

21

Общение между участниками проекта формирует ubiquitous la language

slide-22
SLIDE 22

Сценарий: Докладчик регистрируется на событие и добавляет информацию о докладе

22

slide-23
SLIDE 23

23

Speaker Talk Event Domain model

slide-24
SLIDE 24

24

Доменная модель и ubiquitous language ограничены контекстом (bounded context)

slide-25
SLIDE 25

25

Speaker Talk Event Domain model Event planning context

slide-26
SLIDE 26

Speaker Talk Event Event planning context User Role Profile Identity context

26

slide-27
SLIDE 27

27

Speaker Talk Event Event planning context User Role Profile Identity context

slide-28
SLIDE 28

28

Sales service

slide-29
SLIDE 29

Сценарий: По нажатию на Checkout считается окончательная цена заказа с учетом скидки постоянного клиента, и заказ переходит в статус «Ожидание оплаты»

29

slide-30
SLIDE 30

30

public void Checkout(long id) { var ord = _ordersRepository.GetOrder(id); var orders = _ordersRepository.GetOrders().Count(

  • => o.CustomerId == ord.CustomerId

&& o.StateId == 3 && o.OrderDate >= DateTime.UtcNow.AddYears(-5));

  • rd.Price *= (100 - (orders >= 5 ? 30m : orders >= 3 ? 20m : orders >= 1 ? 10m : 0)) / 100;
  • rd.StateId = 1;

_ordersRepository.SaveOrder(ord); } https://github.com/a-merson/Stachka2019

slide-31
SLIDE 31

31

public void Checkout(long id) { var ord = _ordersRepository.GetOrder(id); var orders = _ordersRepository.GetOrders().Count(

  • => o.CustomerId == ord.CustomerId

&& o.StateId == 3 && o.OrderDate >= DateTime.UtcNow.AddYears(-5));

  • rd.Price *= (100 - (orders >= 5 ? 30m : orders >= 3 ? 20m : orders >= 1 ? 10m : 0)) / 100;
  • rd.StateId = 1;

_ordersRepository.SaveOrder(ord); } https://github.com/a-merson/Stachka2019

slide-32
SLIDE 32

32

public void Checkout(long id) { var ord = _ordersRepository.GetOrder(id); var orders = _ordersRepository.GetOrders().Count(

  • => o.CustomerId == ord.CustomerId

&& o.StateId == 3 && o.OrderDate >= DateTime.UtcNow.AddYears(-5));

  • rd.Price *= (100 - (orders >= 5 ? 30m : orders >= 3 ? 20m : orders >= 1 ? 10m : 0)) / 100;
  • rd.StateId = 1;

_ordersRepository.SaveOrder(ord); } https://github.com/a-merson/Stachka2019

slide-33
SLIDE 33

33

public void Checkout(long id) { var ord = _ordersRepository.GetOrder(id); var orders = _ordersRepository.GetOrders().Count(

  • => o.CustomerId == ord.CustomerId

&& o.StateId == 3 && o.OrderDate >= DateTime.UtcNow.AddYears(-5));

  • rd.Price *= (100 - (orders >= 5 ? 30m : orders >= 3 ? 20m : orders >= 1 ? 10m : 0)) / 100;
  • rd.StateId = 1;

_ordersRepository.SaveOrder(ord); } https://github.com/a-merson/Stachka2019

slide-34
SLIDE 34

34

public void Checkout(long id) { var ord = _ordersRepository.GetOrder(id); var orders = _ordersRepository.GetOrders().Count(

  • => o.CustomerId == ord.CustomerId

&& o.StateId == 3 && o.OrderDate >= DateTime.UtcNow.AddYears(-5));

  • rd.Price *= (100 - (orders >= 5 ? 30m : orders >= 3 ? 20m : orders >= 1 ? 10m : 0)) / 100;
  • rd.StateId = 1;

_ordersRepository.SaveOrder(ord); } https://github.com/a-merson/Stachka2019

slide-35
SLIDE 35

35

public void Checkout(long id) { var ord = _ordersRepository.GetOrder(id); var orders = _ordersRepository.GetOrders().Count(

  • => o.CustomerId == ord.CustomerId

&& o.StateId == 3 && o.OrderDate >= DateTime.UtcNow.AddYears(-5));

  • rd.Price *= (100 - (orders >= 5 ? 30m : orders >= 3 ? 20m : orders >= 1 ? 10m : 0)) / 100;
  • rd.StateId = 1;

_ordersRepository.SaveOrder(ord); } https://github.com/a-merson/Stachka2019

slide-36
SLIDE 36

36

slide-37
SLIDE 37

37

public void CheckoutV2(long orderId) { var order = _ordersRepository.GetOrder(orderId); var discount = _сalculator.CalculateDiscountBy(order.CustomerId);

  • rder.ApplyDiscount(discount);
  • rder.State = OrderState.AwaitingPayment;

_ordersRepository.SaveOrder(order); }

https://github.com/a-merson/Stachka2019

slide-38
SLIDE 38

38

public void CheckoutV2(long orderId) { var order = _ordersRepository.GetOrder(orderId); var discount = _сalculator.CalculateDiscountBy(order.CustomerId);

  • rder.ApplyDiscount(discount);
  • rder.State = OrderState.AwaitingPayment;

_ordersRepository.SaveOrder(order); }

https://github.com/a-merson/Stachka2019

slide-39
SLIDE 39

39

public void CheckoutV2(long orderId) { var order = _ordersRepository.GetOrder(orderId); var discount = _сalculator.CalculateDiscountBy(order.CustomerId);

  • rder.ApplyDiscount(discount);
  • rder.State = OrderState.AwaitingPayment;

_ordersRepository.SaveOrder(order); }

https://github.com/a-merson/Stachka2019

slide-40
SLIDE 40

40

public void CheckoutV2(long orderId) { var order = _ordersRepository.GetOrder(orderId); var discount = _сalculator.CalculateDiscountBy(order.CustomerId);

  • rder.ApplyDiscount(discount);
  • rder.State = OrderState.AwaitingPayment;

_ordersRepository.SaveOrder(order); }

https://github.com/a-merson/Stachka2019

slide-41
SLIDE 41

41

public void CheckoutV2(long orderId) { var order = _ordersRepository.GetOrder(orderId); var discount = _сalculator.CalculateDiscountBy(order.CustomerId);

  • rder.ApplyDiscount(discount);
  • rder.State = OrderState.AwaitingPayment;

_ordersRepository.SaveOrder(order); }

https://github.com/a-merson/Stachka2019

slide-42
SLIDE 42

42

public void CheckoutV2(long orderId) { var order = _ordersRepository.GetOrder(orderId); var discount = _сalculator.CalculateDiscountBy(order.CustomerId);

  • rder.ApplyDiscount(discount);
  • rder.State = OrderState.AwaitingPayment;

_ordersRepository.SaveOrder(order); }

https://github.com/a-merson/Stachka2019

slide-43
SLIDE 43

44

public decimal CalculateDiscountBy(long customerId) { var completedOrdersCount = _ordersRepository .GetLast5YearsCompletedOrdersCountFor(customerId); return DiscountBy(completedOrdersCount); }

https://github.com/a-merson/Stachka2019

slide-44
SLIDE 44

45

private decimal DiscountBy(int completedOrdersCount) { if (completedOrdersCount >= 5) return 30; if (completedOrdersCount >= 3) return 20; if (completedOrdersCount >= 1) return 10; return 0; }

https://github.com/a-merson/Stachka2019

slide-45
SLIDE 45

46

public void CheckoutV2(long orderId) { var order = _ordersRepository.GetOrder(orderId); var discount = _сalculator.CalculateDiscountBy(order.CustomerId);

  • rder.ApplyDiscount(discount);
  • rder.State = OrderState.AwaitingPayment;

_ordersRepository.SaveOrder(order); }

https://github.com/a-merson/Stachka2019

slide-46
SLIDE 46

47

Доменная модель и бизнес-логика должны использовать ubiquitous language

slide-47
SLIDE 47

Domain

Subdomain Subdomain Subdomain Bounded context Bounded context Bounded context

48

slide-48
SLIDE 48

Domain

Subdomain Subdomain Subdomain Bounded context Bounded context Bounded context

49

slide-49
SLIDE 49

Domain

Subdomain Subdomain Subdomain Bounded context Bounded context Bounded context

50

slide-50
SLIDE 50

Subdomains Core Supporting Generic

51

slide-51
SLIDE 51

Subdomains Core Supporting Generic

52

slide-52
SLIDE 52

Subdomains Core Supporting Generic

53

Контент

slide-53
SLIDE 53

Subdomains Core Supporting Generic

54

slide-54
SLIDE 54

Subdomains Core Supporting Generic

55

Маркетинг

slide-55
SLIDE 55

Subdomains Core Supporting Generic

56

slide-56
SLIDE 56

Subdomains Core Supporting Generic

57

Оплата

slide-57
SLIDE 57

Domain

Subdomain Subdomain Subdomain Bounded context Bounded context Bounded context

58

slide-58
SLIDE 58

Subdomain Bounded context

Задачи бизнеса Программные решения

59

slide-59
SLIDE 59

Бухгалтерия Программные решения

60

slide-60
SLIDE 60

61

Билеты Контент

Яндекс Касса Custom application

slide-61
SLIDE 61

Архитектура и управление зависимостями

62

slide-62
SLIDE 62

Domain Driven Design

Micro services Layers Event- Driven CQRS

63

slide-63
SLIDE 63

Цель: максимально избавить доменную логику от зависимостей

64

slide-64
SLIDE 64

Data layer Business layer Presentation layer

65

slide-65
SLIDE 65

Infrastructure layer Domain layer Application layer Presentation layer

66

slide-66
SLIDE 66

Domain layer Application layer UI & Infrastructure

67

slide-67
SLIDE 67

Domain layer Application layer UI & Infrastructure

68

slide-68
SLIDE 68

Domain layer Application layer UI & Infrastructure

69

slide-69
SLIDE 69

Domain layer Application layer UI & Infrastructure

70

slide-70
SLIDE 70

Domain layer Application layer UI & Infrastructure

71

slide-71
SLIDE 71

72

Гексагональная архитектура Порты и адаптеры

slide-72
SLIDE 72

Еще раз о языке

73

slide-73
SLIDE 73

74

Speaker Talk Event Domain model

slide-74
SLIDE 74

75

Speaker Talk Event Domain model

Сценарий: Докладчик регистрируется на событие и добавляет информацию о докладе

slide-75
SLIDE 75

76

English Русский

slide-76
SLIDE 76

77

slide-77
SLIDE 77

78

https://github.com/a-merson/Stachka2019

slide-78
SLIDE 78

79

https://github.com/a-merson/Stachka2019

slide-79
SLIDE 79

Рецепт для прагматика

  • 1. Общение + общение + общение = ubiquitous language

80

slide-80
SLIDE 80

Рецепт для прагматика

  • 1. Общение + общение + общение = ubiquitous language
  • 2. Модели ограничиваются контекстами

81

slide-81
SLIDE 81

Рецепт для прагматика

  • 1. Общение + общение + общение = ubiquitous language
  • 2. Модели ограничиваются контекстами
  • 3. Минимум зависимостей для доменной модели

82

slide-82
SLIDE 82

Рецепт для прагматика

  • 1. Общение + общение + общение = ubiquitous language
  • 2. Модели ограничиваются контекстами
  • 3. Минимум зависимостей для доменной модели
  • 4. Максимально выразительный код бизнес-логики

83

slide-83
SLIDE 83

Рецепт для прагматика

  • 1. Общение + общение + общение = ubiquitous language
  • 2. Модели ограничиваются контекстами
  • 3. Минимум зависимостей для доменной модели
  • 4. Максимально выразительный код бизнес-логики
  • 5. ?????
  • 6. PROFIT

84

slide-84
SLIDE 84

Полезные ссылки:

  • 1. https://habr.com/users/marshinov (например Как мы попробовали

DDD, CQRS и Event Sourcing и какие выводы сделали)

  • 2. https://blog.byndyu.ru
  • 3. DDD и функциональное программирование
  • https://fsharpforfunandprofit.com/
  • 4. Hexagonal Architecture (Ports&Adapters)
  • https://herbertograca.com/2017/09/14/ports-adapters-architecture/

85

slide-85
SLIDE 85

Спасибо за внимание!

alexey.merson@gmail.com https://github.com/a-merson/Stachka2019