Slide 1

Slide 1 text

10年 先を見据えて作る PHP WEBアプリケーション設計入門

Slide 2

Slide 2 text

2 10年

Slide 3

Slide 3 text

3 10年続くことなんて そうそうなくない?

Slide 4

Slide 4 text

4 2000 2005 2010 2015 2020

Slide 5

Slide 5 text

5 2000 2005 2010 2015 2020

Slide 6

Slide 6 text

6 2000 2005 2010 2015 2020

Slide 7

Slide 7 text

7 2000 2005 2010 2015 2020

Slide 8

Slide 8 text

8 2000 2005 2010 2015 2020

Slide 9

Slide 9 text

9 2000 2005 2010 2015 2020

Slide 10

Slide 10 text

10 2000 2005 2010 2015 2020

Slide 11

Slide 11 text

11 2000 2005 2010 2015 2020

Slide 12

Slide 12 text

12 2000 2005 2010 2015 2020

Slide 13

Slide 13 text

13 2000 2005 2010 2015 2020

Slide 14

Slide 14 text

14 2000 2005 2010 2015 2020 SDプラン

Slide 15

Slide 15 text

15 2000 2005 2010 2015 2020 SDプラン RSプラン

Slide 16

Slide 16 text

16 10年の月日が もたらすもの

Slide 17

Slide 17 text

17 10年 ×

Slide 18

Slide 18 text

18 2000 2005 2010 2015 2020

Slide 19

Slide 19 text

19 2000 2005 2010 2015 2020 PHP Tools (1995)

Slide 20

Slide 20 text

20 2000 2005 2010 2015 2020 PHP Tools (1995) PHP2 (1996) PHP3 (1998) PHP4 (2000) PHP5 (2004) PHP6 PHP7 (2015) PHP8 (2020)

Slide 21

Slide 21 text

21 2000 2005 2010 2015 2020 PHP Tools (1995) PHP2 (1996) PHP3 (1998) PHP4 (2000) PHP5 (2004) PHP6 PHP7 (2015) PHP8 (2020) phrame (2003) mojavi (2004) Agavi (2005) Ethna (2005) Maple (2005) CakePHP (2006) Symfony (2007) Zend Framework (2007) Laravel (2011) CodeIgniter (2006) FuelPHP (2011) Phalcon (2012) Yii (2008)

Slide 22

Slide 22 text

22 2000 2005 2010 2015 2020 PHP Tools (1995) PHP2 (1996) PHP3 (1998) PHP4 (2000) PHP5 (2004) PHP6 PHP7 (2015) PHP8 (2020) phrame (2003) mojavi (2004) Agavi (2005) Ethna (2005) Maple (2005) CakePHP (2006) Symfony (2007) Zend Framework (2007) Laravel (2011) CodeIgniter (2006) FuelPHP (2011) Phalcon (2012) Yii (2008)

Slide 23

Slide 23 text

23 2000 2005 2010 2015 2020 PHP Tools (1995) PHP2 (1996) PHP3 (1998) PHP4 (2000) PHP5 (2004) PHP6 PHP7 (2015) PHP8 (2020) phrame (2003) mojavi (2004) Agavi (2005) Ethna (2005) Maple (2005) CakePHP (2006) Symfony (2007) Zend Framework (2007) Laravel (2011) CodeIgniter (2006) FuelPHP (2011) Phalcon (2012) Yii (2008)

Slide 24

Slide 24 text

24 2000 2005 2010 2015 2020 PHP Tools (1995) PHP2 (1996) PHP3 (1998) PHP4 (2000) PHP5 (2004) PHP6 PHP7 (2015) PHP8 (2020) phrame (2003) mojavi (2004) Agavi (2005) Ethna (2005) Maple (2005) CakePHP (2006) Symfony (2007) Zend Framework (2007) Laravel (2011) CodeIgniter (2006) FuelPHP (2011) Phalcon (2012) Yii (2008)

Slide 25

Slide 25 text

25 2000 2005 2010 2015 2020 PHP Tools (1995) PHP2 (1996) PHP3 (1998) PHP4 (2000) PHP5 (2004) PHP6 PHP7 (2015) PHP8 (2020) phrame (2003) mojavi (2004) Agavi (2005) Ethna (2005) Maple (2005) CakePHP (2006) Symfony (2007) Zend Framework (2007) Laravel (2011) CodeIgniter (2006) FuelPHP (2011) Phalcon (2012) Yii (2008) 1 (2011)

Slide 26

Slide 26 text

26 2000 2005 2010 2015 2020 PHP Tools (1995) PHP2 (1996) PHP3 (1998) PHP4 (2000) PHP5 (2004) PHP6 PHP7 (2015) PHP8 (2020) phrame (2003) mojavi (2004) Agavi (2005) Ethna (2005) Maple (2005) CakePHP (2006) Symfony (2007) Zend Framework (2007) Laravel (2011) CodeIgniter (2006) FuelPHP (2011) Phalcon (2012) Yii (2008) 2 (2011) 1 (2011)

Slide 27

Slide 27 text

27 2000 2005 2010 2015 2020 PHP Tools (1995) PHP2 (1996) PHP3 (1998) PHP4 (2000) PHP5 (2004) PHP6 PHP7 (2015) PHP8 (2020) phrame (2003) mojavi (2004) Agavi (2005) Ethna (2005) Maple (2005) CakePHP (2006) Symfony (2007) Zend Framework (2007) Laravel (2011) CodeIgniter (2006) FuelPHP (2011) Phalcon (2012) Yii (2008) 2 (2011) 3 (2012) 1 (2011)

Slide 28

Slide 28 text

28 2000 2005 2010 2015 2020 PHP Tools (1995) PHP2 (1996) PHP3 (1998) PHP4 (2000) PHP5 (2004) PHP6 PHP7 (2015) PHP8 (2020) phrame (2003) mojavi (2004) Agavi (2005) Ethna (2005) Maple (2005) CakePHP (2006) Symfony (2007) Zend Framework (2007) Laravel (2011) CodeIgniter (2006) FuelPHP (2011) Phalcon (2012) Yii (2008) 2 (2011) 3 (2012) 4.0 (2013) 4.1 (2013) 4.2 (2014) 1 (2011)

Slide 29

Slide 29 text

29 2000 2005 2010 2015 2020 PHP Tools (1995) PHP2 (1996) PHP3 (1998) PHP4 (2000) PHP5 (2004) PHP6 PHP7 (2015) PHP8 (2020) phrame (2003) mojavi (2004) Agavi (2005) Ethna (2005) Maple (2005) CakePHP (2006) Symfony (2007) Zend Framework (2007) Laravel (2011) CodeIgniter (2006) FuelPHP (2011) Phalcon (2012) Yii (2008) 2 (2011) 3 (2012) 4.0 (2013) 5.0 (2015) 5.1 (2015) 4.1 (2013) 4.2 (2014) 5.2 (2015) 5.3 (2016) 5.4 (2017) 5.5 (2017) 5.6 (2018) 5.7 (2018) 5.8 (2019) 1 (2011)

Slide 30

Slide 30 text

30 2000 2005 2010 2015 2020 PHP Tools (1995) PHP2 (1996) PHP3 (1998) PHP4 (2000) PHP5 (2004) PHP6 PHP7 (2015) PHP8 (2020) phrame (2003) mojavi (2004) Agavi (2005) Ethna (2005) Maple (2005) CakePHP (2006) Symfony (2007) Zend Framework (2007) Laravel (2011) CodeIgniter (2006) FuelPHP (2011) Phalcon (2012) Yii (2008) 2 (2011) 3 (2012) 4.0 (2013) 5.0 (2015) 5.1 (2015) 4.1 (2013) 4.2 (2014) 5.2 (2015) 5.3 (2016) 5.4 (2017) 5.5 (2017) 5.6 (2018) 5.7 (2018) 5.8 (2019) 6 (2019) 7 (2020) 8 (2020) 1 (2011)

Slide 31

Slide 31 text

31 2000 2005 2010 2015 2020 PHP Tools (1995) PHP2 (1996) PHP3 (1998) PHP4 (2000) PHP5 (2004) PHP6 PHP7 (2015) PHP8 (2020) phrame (2003) mojavi (2004) Agavi (2005) Ethna (2005) Maple (2005) CakePHP (2006) Symfony (2007) Zend Framework (2007) Laravel (2011) CodeIgniter (2006) FuelPHP (2011) Phalcon (2012) Yii (2008) 2 (2011) 3 (2012) 4.0 (2013) 5.0 (2015) 5.1 (2015) 4.1 (2013) 4.2 (2014) 5.2 (2015) 5.3 (2016) 5.4 (2017) 5.5 (2017) 5.6 (2018) 5.7 (2018) 5.8 (2019) 6 (2019) 7 (2020) 8 (2020) 1 (2011)

Slide 32

Slide 32 text

32 どんな手立てを取れるか

Slide 33

Slide 33 text

33

Slide 34

Slide 34 text

34

Slide 35

Slide 35 text

35

Slide 36

Slide 36 text

36

Slide 37

Slide 37 text

37

Slide 38

Slide 38 text

10年 先を見据えて作る PHP WEBアプリケーション設計入門

Slide 39

Slide 39 text

No content

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

No content

Slide 43

Slide 43 text

No content

Slide 44

Slide 44 text

44 2000 2005 2010 2015 2020 PHP Tools (1995) PHP2 (1996) PHP3 (1998) PHP4 (2000) PHP5 (2004) PHP6 PHP7 (2015) PHP8 (2020) phrame (2003) mojavi (2004) Agavi (2005) Ethna (2005) Maple (2005) CakePHP (2006) Symfony (2007) Zend Framework (2007) Laravel (2011) CodeIgniter (2006) FuelPHP (2011) Phalcon (2012) Yii (2008)

Slide 45

Slide 45 text

45

Slide 46

Slide 46 text

46 2000 2005 2010 2015 2020 PHP Tools (1995) PHP2 (1996) PHP3 (1998) PHP4 (2000) PHP5 (2004) PHP6 PHP7 (2015) PHP8 (2020) phrame (2003) mojavi (2004) Agavi (2005) Ethna (2005) Maple (2005) CakePHP (2006) Symfony (2007) Zend Framework (2007) Laravel (2011) CodeIgniter (2006) FuelPHP (2011) Phalcon (2012) Yii (2008) 候補があがったら ・チームの士気が上がるか ・10年後に残ってそうか の観点で選ぶ

Slide 47

Slide 47 text

47 2000 2005 2010 2015 2020 PHP Tools (1995) PHP2 (1996) PHP3 (1998) PHP4 (2000) PHP5 (2004) PHP6 PHP7 (2015) PHP8 (2020) phrame (2003) mojavi (2004) Agavi (2005) Ethna (2005) Maple (2005) CakePHP (2006) Symfony (2007) Zend Framework (2007) Laravel (2011) CodeIgniter (2006) FuelPHP (2011) Phalcon (2012) Yii (2008) 候補があがったら ・チームの士気が上がるか ・10年後に残ってそうか の観点で選ぶ 10年残るかは運次第

Slide 48

Slide 48 text

48

Slide 49

Slide 49 text

49

Slide 50

Slide 50 text

50

Slide 51

Slide 51 text

No content

Slide 52

Slide 52 text

52

Slide 53

Slide 53 text

53

Slide 54

Slide 54 text

54 https://alistair.cockburn.us/hexagonal-architecture/ https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html User Interface Application Domain Infrastructure

Slide 55

Slide 55 text

55 https://alistair.cockburn.us/hexagonal-architecture/ https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html User Interface Application Domain Infrastructure

Slide 56

Slide 56 text

56 https://alistair.cockburn.us/hexagonal-architecture/ https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html User Interface Application Domain Infrastructure

Slide 57

Slide 57 text

57 User Interface Application Domain Infrastructure

Slide 58

Slide 58 text

58 User Interface Application Domain Infrastructure OK

Slide 59

Slide 59 text

59 User Interface Application Domain Infrastructure OK NG

Slide 60

Slide 60 text

60 User Interface Application Domain Infrastructure OK NG MVC Framework

Slide 61

Slide 61 text

No content

Slide 62

Slide 62 text

62 https://github.com/nrslib/scrum-app-sample-php

Slide 63

Slide 63 text

63

Slide 64

Slide 64 text

64

Slide 65

Slide 65 text

65

Slide 66

Slide 66 text

66

Slide 67

Slide 67 text

67 class BackLogController extends Controller { ... public function postAddUserStory( Request $request, BackLogApplicationService $applicationService ) { $request->validate([ "story" => "required" ]); $story = $request->input("story"); $command = new AddUserStoryCommand($story); $applicationService->addUserStory($command); return redirect()->action([BackLogController::class, "index"]); } }

Slide 68

Slide 68 text

68 class BackLogController extends Controller { ... public function postAddUserStory( Request $request, BackLogApplicationService $applicationService ) { $request->validate([ "story" => "required" ]); $story = $request->input("story"); $command = new AddUserStoryCommand($story); $applicationService->addUserStory($command); return redirect()->action([BackLogController::class, "index"]); } }

Slide 69

Slide 69 text

69 class BackLogController extends Controller { ... public function postAddUserStory( Request $request, BackLogApplicationService $applicationService ) { $request->validate([ "story" => "required" ]); $story = $request->input("story"); $command = new AddUserStoryCommand($story); $applicationService->addUserStory($command); return redirect()->action([BackLogController::class, "index"]); } }

Slide 70

Slide 70 text

70 class BackLogController extends Controller { ... public function postAddUserStory( Request $request, BackLogApplicationService $applicationService ) { $request->validate([ "story" => "required" ]); $story = $request->input("story"); $command = new AddUserStoryCommand($story); $applicationService->addUserStory($command); return redirect()->action([BackLogController::class, "index"]); } }

Slide 71

Slide 71 text

71 class BackLogController extends Controller { ... public function postAddUserStory( Request $request, BackLogApplicationService $applicationService ) { $request->validate([ "story" => "required" ]); $story = $request->input("story"); $command = new AddUserStoryCommand($story); $applicationService->addUserStory($command); return redirect()->action([BackLogController::class, "index"]); } }

Slide 72

Slide 72 text

72 class BackLogController extends Controller { ... public function postAddUserStory( Request $request, BackLogApplicationService $applicationService ) { $request->validate([ "story" => "required" ]); $story = $request->input("story"); $command = new AddUserStoryCommand($story); $applicationService->addUserStory($command); return redirect()->action([BackLogController::class, "index"]); } }

Slide 73

Slide 73 text

73 class BackLogController extends Controller { ... public function postAddUserStory( Request $request, BackLogApplicationService $applicationService ) { $request->validate([ "story" => "required" ]); $story = $request->input("story"); $command = new AddUserStoryCommand($story); $applicationService->addUserStory($command); return redirect()->action([BackLogController::class, "index"]); } }

Slide 74

Slide 74 text

74 class BackLogController extends Controller { ... public function postAddUserStory( Request $request, BackLogApplicationService $applicationService ) { $request->validate([ "story" => "required" ]); $story = $request->input("story"); $command = new AddUserStoryCommand($story); $applicationService->addUserStory($command); return redirect()->action([BackLogController::class, "index"]); } }

Slide 75

Slide 75 text

75 class BackLogController extends Controller { ... public function postAddUserStory( Request $request, BackLogApplicationService $applicationService ) { $request->validate([ "story" => "required" ]); $story = $request->input("story"); $command = new AddUserStoryCommand($story); $applicationService->addUserStory($command); return redirect()->action([BackLogController::class, "index"]); } }

Slide 76

Slide 76 text

76 class BackLogController extends Controller { ... public function postAddUserStory( Request $request, BackLogApplicationService $applicationService ) { $request->validate([ "story" => "required" ]); $story = $request->input("story"); $command = new AddUserStoryCommand($story); $applicationService->addUserStory($command); return redirect()->action([BackLogController::class, "index"]); } }

Slide 77

Slide 77 text

77 class BackLogController extends Controller { ... public function postAddUserStory( Request $request, BackLogApplicationService $applicationService ) { $request->validate([ "story" => "required" ]); $story = $request->input("story"); $command = new AddUserStoryCommand($story); $applicationService->addUserStory($command); return redirect()->action([BackLogController::class, "index"]); } }

Slide 78

Slide 78 text

78 class BackLogController extends Controller { ... public function postAddUserStory( Request $request, BackLogApplicationService $applicationService ) { $request->validate([ "story" => "required" ]); $story = $request->input("story"); $command = new AddUserStoryCommand($story); $applicationService->addUserStory($command); return redirect()->action([BackLogController::class, "index"]); } }

Slide 79

Slide 79 text

79 class BackLogController extends Controller { ... public function postAddUserStory( Request $request, BackLogApplicationService $applicationService ) { $request->validate([ "story" => "required" ]); $story = $request->input("story"); $command = new AddUserStoryCommand($story); $applicationService->addUserStory($command); return redirect()->action([BackLogController::class, "index"]); } }

Slide 80

Slide 80 text

80 class BackLogController extends Controller { ... public function postAddUserStory( Request $request, BackLogApplicationService $applicationService ) { $request->validate([ "story" => "required" ]); $story = $request->input("story"); $command = new AddUserStoryCommand($story); $applicationService->addUserStory($command); return redirect()->action([BackLogController::class, "index"]); } }

Slide 81

Slide 81 text

81 class BackLogController extends Controller { ... public function postAddUserStory( Request $request, BackLogApplicationService $applicationService ) { $request->validate([ "story" => "required" ]); $story = $request->input("story"); $command = new AddUserStoryCommand($story); $applicationService->addUserStory($command); return redirect()->action([BackLogController::class, "index"]); } }

Slide 82

Slide 82 text

82 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; public function __construct( Transaction $transaction, UserContextInterface $userContext, UserStoryRepositoryInterface $userStoryRepository ) { $this->transaction = $transaction; $this->userContext = $userContext; $this->userStoryRepository = $userStoryRepository; } public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); }); } }

Slide 83

Slide 83 text

83 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; public function __construct( Transaction $transaction, UserContextInterface $userContext, UserStoryRepositoryInterface $userStoryRepository ) { $this->transaction = $transaction; $this->userContext = $userContext; $this->userStoryRepository = $userStoryRepository; } public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); }); } }

Slide 84

Slide 84 text

84 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); }); } }

Slide 85

Slide 85 text

85 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); }); } }

Slide 86

Slide 86 text

86 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); }); } }

Slide 87

Slide 87 text

87 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); }); } }

Slide 88

Slide 88 text

88 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); }); } }

Slide 89

Slide 89 text

89 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); }); } }

Slide 90

Slide 90 text

90 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); }); } }

Slide 91

Slide 91 text

91 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); }); } }

Slide 92

Slide 92 text

92 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); }); } }

Slide 93

Slide 93 text

93 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); }); } }

Slide 94

Slide 94 text

94 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); }); } }

Slide 95

Slide 95 text

95 interface UserStoryRepositoryInterface { public function find(UserStoryId $id): ?UserStory; public function save(UserStory $userStory): void; }

Slide 96

Slide 96 text

96 class EloquentUserStoryRepository implements UserStoryRepositoryInterface { ... public function save(UserStory $userStory): void { UserStoryDataModel::updateOrCreate( ["id" => $userStory->getId()->getValue()], [ "story" => $userStory->getStory(), "author" => $userStory->getAuthor()->getValue(), "demo" => $userStory->getDemo(), "estimate" => $userStory->getEstimate(), "seq" => $userStory->getSeq() ] ); } }

Slide 97

Slide 97 text

97 class EloquentUserStoryRepository implements UserStoryRepositoryInterface { ... public function save(UserStory $userStory): void { UserStoryDataModel::updateOrCreate( ["id" => $userStory->getId()->getValue()], [ "story" => $userStory->getStory(), "author" => $userStory->getAuthor()->getValue(), "demo" => $userStory->getDemo(), "estimate" => $userStory->getEstimate(), "seq" => $userStory->getSeq() ] ); } }

Slide 98

Slide 98 text

98 User Interface Application Domain Infrastructure OK NG MVC Framework

Slide 99

Slide 99 text

99

Slide 100

Slide 100 text

100

Slide 101

Slide 101 text

No content

Slide 102

Slide 102 text

102

Slide 103

Slide 103 text

103

Slide 104

Slide 104 text

104

Slide 105

Slide 105 text

105

Slide 106

Slide 106 text

106

Slide 107

Slide 107 text

107

Slide 108

Slide 108 text

108

Slide 109

Slide 109 text

No content

Slide 110

Slide 110 text

110 class BackLogApplicationService { ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $repository = new EloquentUserStoryRepository(); $repository->save($story); }); } }

Slide 111

Slide 111 text

111 class BackLogApplicationService { ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $repository = new EloquentUserStoryRepository(); $repository->save($story); }); } }

Slide 112

Slide 112 text

112 class BackLogApplicationService { /** @var UserStoryRepositoryInterface */ private $userStoryRepository; ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); }); } }

Slide 113

Slide 113 text

113 class BackLogApplicationService { /** @var UserStoryRepositoryInterface */ private $userStoryRepository; ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); }); } }

Slide 114

Slide 114 text

114 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; public function __construct( Transaction $transaction, UserContextInterface $userContext, UserStoryRepositoryInterface $userStoryRepository ) { $this->transaction = $transaction; $this->userContext = $userContext; $this->userStoryRepository = $userStoryRepository; } ... }

Slide 115

Slide 115 text

115 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; public function __construct( Transaction $transaction, UserContextInterface $userContext, UserStoryRepositoryInterface $userStoryRepository ) { $this->transaction = $transaction; $this->userContext = $userContext; $this->userStoryRepository = $userStoryRepository; } ... }

Slide 116

Slide 116 text

116 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; public function __construct( Transaction $transaction, UserContextInterface $userContext, UserStoryRepositoryInterface $userStoryRepository ) { $this->transaction = $transaction; $this->userContext = $userContext; $this->userStoryRepository = $userStoryRepository; } ... }

Slide 117

Slide 117 text

117

Slide 118

Slide 118 text

118 class ProductionServiceProvider implements Provider { ... private function registerApplications() { $this->app->bind(BackLogApplicationService::class); ... } private function registerInfrastructures() { $this->app->bind( BackLogQueryServiceInterface::class, EloquentBackLogQueryService::class ); $this->app->bind( UserStoryRepositoryInterface::class, EloquentUserStoryRepository::class ); ... } }

Slide 119

Slide 119 text

119 class ProductionServiceProvider implements Provider { ... private function registerApplications() { $this->app->bind(BackLogApplicationService::class); ... } private function registerInfrastructures() { $this->app->bind( BackLogQueryServiceInterface::class, EloquentBackLogQueryService::class ); $this->app->bind( UserStoryRepositoryInterface::class, EloquentUserStoryRepository::class ); ... } }

Slide 120

Slide 120 text

120 class LocalServiceProvider implements Provider { ... private function registerInfrastructures() { $this->app->bind( BackLogQueryServiceInterface::class, FileBackLogQueryService::class ); $this->app->bind( UserStoryRepositoryInterface::class, StubUserStoryRepository::class ); $this->app->bind(FileUserStoryRepository::class); ... } }

Slide 121

Slide 121 text

121 class LocalServiceProvider implements Provider { ... private function registerInfrastructures() { $this->app->bind( BackLogQueryServiceInterface::class, FileBackLogQueryService::class ); $this->app->bind( UserStoryRepositoryInterface::class, StubUserStoryRepository::class ); $this->app->bind(FileUserStoryRepository::class); ... } }

Slide 122

Slide 122 text

122 class StubUserStoryRepository implements UserStoryRepositoryInterface { public function find(UserStoryId $id): ?UserStory { return new UserStory( new UserStoryId("test-id"), "test-story", new UserId("test-author-id"), "demo sequence", 3, 1 ); } public function save(UserStory $userStory): void { } }

Slide 123

Slide 123 text

123 Eloquent UserStoryRepository BackLog ApplicationService

Slide 124

Slide 124 text

124 Eloquent UserStoryRepository BackLog ApplicationService UserStoryRepository Interface

Slide 125

Slide 125 text

125 Eloquent UserStoryRepository BackLog ApplicationService UserStoryRepository Interface

Slide 126

Slide 126 text

126

Slide 127

Slide 127 text

127

Slide 128

Slide 128 text

128

Slide 129

Slide 129 text

129 あー モデリングとか コーディングしてたら オブジェクトの データ違ったなー

Slide 130

Slide 130 text

130 あー モデリングとか コーディングしてたら オブジェクトの データ違ったなー テーブル定義 変えないとな―

Slide 131

Slide 131 text

131 あー モデリングとか コーディングしてたら オブジェクトの データ違ったなー テーブル定義 変えないとな― ALTER TABLE ...

Slide 132

Slide 132 text

132 あー モデリングとか コーディングしてたら オブジェクトの データ違ったなー テーブル定義 変えないとな― ALTER TABLE ...

Slide 133

Slide 133 text

133 class LocalServiceProvider implements Provider { ... private function registerInfrastructures() { $this->app->bind( BackLogQueryServiceInterface::class, FileBackLogQueryService::class ); $this->app->bind( UserStoryRepositoryInterface::class, StubUserStoryRepository::class ); $this->app->bind(FileUserStoryRepository::class); ... } }

Slide 134

Slide 134 text

134 class StubUserStoryRepository implements UserStoryRepositoryInterface { public function find(UserStoryId $id): ?UserStory { return new UserStory( new UserStoryId("test-id"), "test-story", new UserId("test-author-id"), "demo sequence", 3, 1 ); } public function save(UserStory $userStory): void { } }

Slide 135

Slide 135 text

135 class StubUserStoryRepository implements UserStoryRepositoryInterface { public function find(UserStoryId $id): ?UserStory { return new UserStory( new UserStoryId("test-id"), "test-story", new UserId("test-author-id"), "demo sequence", 3, 1 ); } public function save(UserStory $userStory): void { } }

Slide 136

Slide 136 text

136

Slide 137

Slide 137 text

137 https://github.com/nrslib/repository-support-php

Slide 138

Slide 138 text

138 class LocalServiceProvider implements Provider { ... private function registerInfrastructures() { $this->app->bind( BackLogQueryServiceInterface::class, FileBackLogQueryService::class ); $this->app->bind( UserStoryRepositoryInterface::class, FileUserStoryRepository::class ); $this->app->bind(FileUserStoryRepository::class); ... } }

Slide 139

Slide 139 text

139 class FileUserStoryRepository implements UserStoryRepositoryInterface { use FileRepository; public function find(UserStoryId $id): ?UserStory { $story = $this->load($id->getValue()); if (is_null($story)) { return null; } else { return $story; } } public function save(UserStory $userStory): void { $rawId = $userStory->getId()->getValue(); $this->store($rawId, $userStory); } }

Slide 140

Slide 140 text

140 class FileUserStoryRepository implements UserStoryRepositoryInterface { use FileRepository; public function find(UserStoryId $id): ?UserStory { $story = $this->load($id->getValue()); if (is_null($story)) { return null; } else { return $story; } } public function save(UserStory $userStory): void { $rawId = $userStory->getId()->getValue(); $this->store($rawId, $userStory); } }

Slide 141

Slide 141 text

141 trait FileRepository { /** @var FileStore */ private $store; /** @var null|string */ protected $identifier = null; public function __construct() { $this->store = new FileStore(); } public function loadAll() { return $this->store->getAll( $this->id() ); } protected function store($key, $data) { $this->store->put($this->id(), $key, $data); } protected function load($key) { return $this->store->get($this->id(), $key); } private function id() { if (is_null($this->identifier)) { return __CLASS__; } else { return $this->identifier; } } }

Slide 142

Slide 142 text

142 trait FileRepository { /** @var FileStore */ private $store; /** @var null|string */ protected $identifier = null; public function __construct() { $this->store = new FileStore(); } public function loadAll() { return $this->store->getAll( $this->id() ); } protected function store($key, $data) { $this->store->put($this->id(), $key, $data); } protected function load($key) { return $this->store->get($this->id(), $key); } private function id() { if (is_null($this->identifier)) { return __CLASS__; } else { return $this->identifier; } } }

Slide 143

Slide 143 text

143

Slide 144

Slide 144 text

144

Slide 145

Slide 145 text

145 あー モデリングとか コーディングしてたら オブジェクトの データ違ったなー

Slide 146

Slide 146 text

146 あー モデリングとか コーディングしてたら オブジェクトの データ違ったなー フィールド追加して .dat 消して終わり

Slide 147

Slide 147 text

147 Production と Debug で環境を変えられる

Slide 148

Slide 148 text

No content

Slide 149

Slide 149 text

149 class UserStory { /** @var UserStoryId */ private $id; /** @var string */ private $story; /** @var UserId */ private $author; /** @var string|null */ private $demo; /** @var int|null */ private $estimate; /** @var int|null */ private $seq; public function __construct( UserStoryId $id, string $story, UserId $author, string $demo = null, int $estimate = null, int $seq = null ) { $this->id = $id; $this->story = $story; $this->author = $author; $this->demo = $demo; $this->estimate = $estimate; $this->seq = $seq; } ... }

Slide 150

Slide 150 text

150 /** * Class UserStoryDataModel * @package Scrum¥EloquentInfrastructure¥Models * * @property integer $id * @property string $story * @property string $author * @property string|null $demo * @property integer|null $estimate * @property integer|null $seq */ class UserStoryDataModel extends Model { protected $table = "user_stories"; public $incrementing = false; protected $keyType = "string"; public $guarded = []; }

Slide 151

Slide 151 text

151

Slide 152

Slide 152 text

152 UserStory

Slide 153

Slide 153 text

153 UserStory UserStory DataModel

Slide 154

Slide 154 text

154 UserStory UserStory DataModel

Slide 155

Slide 155 text

155 class UserStory extends Model { protected $table = "user_stories"; public $incrementing = false; protected $keyType = "string"; public $guarded = []; /** @var UserStoryId */ private $id; ... }

Slide 156

Slide 156 text

156 class UserStory extends Model { protected $table = "user_stories"; public $incrementing = false; protected $keyType = "string"; public $guarded = []; /** @var UserStoryId */ private $id; ... } User Story

Slide 157

Slide 157 text

157 class UserStory extends Model { protected $table = "user_stories"; public $incrementing = false; protected $keyType = "string"; public $guarded = []; /** @var UserStoryId */ private $id; ... } User Story

Slide 158

Slide 158 text

158 UserStory UserStory DataModel

Slide 159

Slide 159 text

159 User Interface Application Domain Infrastructure OK NG MVC Framework

Slide 160

Slide 160 text

160 User Interface Application Domain Infrastructure OK NG MVC Framework OK?

Slide 161

Slide 161 text

161 Infrastructure User Interface Application Domain OK NG

Slide 162

Slide 162 text

162 Infrastructure User Interface Application Domain OK NG

Slide 163

Slide 163 text

163 Infrastructure User Interface Application Domain OK NG

Slide 164

Slide 164 text

164 Infrastructure User Interface Application Domain OK NG

Slide 165

Slide 165 text

165 Infrastructure User Interface Application Domain OK NG

Slide 166

Slide 166 text

166 Infrastructure User Interface Application Domain OK NG

Slide 167

Slide 167 text

167 https://alistair.cockburn.us/hexagonal-architecture/

Slide 168

Slide 168 text

No content

Slide 169

Slide 169 text

169 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); }); } }

Slide 170

Slide 170 text

170 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); }); } }

Slide 171

Slide 171 text

171 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), Auth::user()->getAuthIdentifier(), $command->getDemo() ); $this->userStoryRepository->save($story); }); } }

Slide 172

Slide 172 text

172 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), Auth::user()->getAuthIdentifier(), $command->getDemo() ); $this->userStoryRepository->save($story); }); } }

Slide 173

Slide 173 text

173 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), Auth::user()->getAuthIdentifier(), $command->getDemo() ); $this->userStoryRepository->save($story); }); } }

Slide 174

Slide 174 text

174 interface UserContextInterface { function getId(): ?UserId; }

Slide 175

Slide 175 text

175 interface UserContextInterface { function getId(): ?UserId; } class AuthUserContext implements UserContextInterface { function getId(): ?UserId { $user = Auth::user(); if (is_null($user)) { return null; } $rawId = $user->getAuthIdentifier(); $id = new UserId($rawId); return $id; } }

Slide 176

Slide 176 text

176 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); }); } }

Slide 177

Slide 177 text

177 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); }); } }

Slide 178

Slide 178 text

178 class BackLogApplicationService { /** @var Transaction */ private $transaction; /** @var UserContextInterface */ private $userContext; /** @var UserStoryRepositoryInterface */ private $userStoryRepository; ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->scope(function () use ($command) { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); }); } }

Slide 179

Slide 179 text

179 class BackLogApplicationService { ... public function addUserStory(AddUserStoryCommand $command) { DB::beginTransaction(); try { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); DB::commit(); } catch ($exception) { DB::rollBack(); } } }

Slide 180

Slide 180 text

180 class BackLogApplicationService { ... public function addUserStory(AddUserStoryCommand $command) { DB::beginTransaction(); try { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); DB::commit(); } catch ($exception) { DB::rollBack(); } } }

Slide 181

Slide 181 text

181 class BackLogApplicationService { ... public function addUserStory(AddUserStoryCommand $command) { DB::beginTransaction(); try { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); DB::commit(); } catch ($exception) { DB::rollBack(); } } }

Slide 182

Slide 182 text

182 interface Transaction { /** * @param callable $transactionScope * @return mixed */ function scope(callable $transactionScope): ?object; function begin(); function commit(); function rollback(); }

Slide 183

Slide 183 text

183 class LaravelDbTransaction implements Transaction { function scope(callable $transactionScope): ?object { return DB::transaction($transactionScope); } function begin() { DB::beginTransaction(); } function commit() { DB::commit(); } function rollback() { DB::rollBack(); } }

Slide 184

Slide 184 text

184 $this->app->bind(Transaction::class, LaravelDbTransaction::class);

Slide 185

Slide 185 text

185 class BackLogApplicationService { ... public function addUserStory(AddUserStoryCommand $command) { $this->transaction->begin(); try { $id = new UserStoryId(uniqid()); $story = new UserStory( $id, $command->getStory(), $this->userContext->getId(), $command->getDemo() ); $this->userStoryRepository->save($story); $this->transaction->commit(); } catch ($exception) { $this->transaction->rollback(); } } }

Slide 186

Slide 186 text

186 class NopTransaction implements Transaction { function scope(callable $transactionScope): ?object { return $transactionScope(); } function begin() { } function commit() { } function rollback() { } }

Slide 187

Slide 187 text

No content

Slide 188

Slide 188 text

188 class BackLogController extends Controller { ... public function postAddUserStory(Request $request) { $request->validate([ "story" => "required" ]); $story = $request->input("story"); $command = new AddUserStoryCommand($story); $applicationService = new BackLogApplicationService( new LaravelDbTransaction(), new AuthUserContext(), new EloquentUserStoryRepository() ); $applicationService->addUserStory($command); return redirect()->action([BackLogController::class, "index"]); } }

Slide 189

Slide 189 text

189 class BackLogController extends Controller { ... public function postAddUserStory(Request $request) { $request->validate([ "story" => "required" ]); $story = $request->input("story"); $command = new AddUserStoryCommand($story); $applicationService = new BackLogApplicationService( new LaravelDbTransaction(), new AuthUserContext(), new EloquentUserStoryRepository() ); $applicationService->addUserStory($command); return redirect()->action([BackLogController::class, "index"]); } }

Slide 190

Slide 190 text

190 class UserStory { ... public function __construct( UserStoryId $id, string $story, UserId $author, string $demo = null, int $estimate = null, int $seq = null ) { if (strlen($story) == 0) { throw new ¥InvalidArgumentException("story is empty.") } $this->id = $id; $this->story = $story; $this->author = $author; $this->demo = $demo; $this->estimate = $estimate; $this->seq = $seq; } }

Slide 191

Slide 191 text

191 class UserStory { ... public function __construct( UserStoryId $id, string $story, UserId $author, string $demo = null, int $estimate = null, int $seq = null ) { if (strlen($story) == 0) { throw new ¥InvalidArgumentException("story is empty.") } $this->id = $id; $this->story = $story; $this->author = $author; $this->demo = $demo; $this->estimate = $estimate; $this->seq = $seq; } }

Slide 192

Slide 192 text

No content

Slide 193

Slide 193 text

193 Infrastructure User Interface Application Domain OK NG

Slide 194

Slide 194 text

194 Infrastructure User Interface Application Domain OK NG

Slide 195

Slide 195 text

195 Infrastructure User Interface Application Domain OK NG

Slide 196

Slide 196 text

196 Infrastructure User Interface Application Domain OK NG

Slide 197

Slide 197 text

197 Infrastructure User Interface Application Domain OK NG

Slide 198

Slide 198 text

198 Infrastructure User Interface Application Domain OK NG

Slide 199

Slide 199 text

199 Infrastructure User Interface Application Domain OK NG

Slide 200

Slide 200 text

200 Infrastructure User Interface Application Domain OK NG

Slide 201

Slide 201 text

201 Infrastructure User Interface Application Domain OK NG 1件~100件まで 自由に取れます

Slide 202

Slide 202 text

202 Infrastructure User Interface Application Domain OK NG 1件~100件まで 自由に取れます ドロップダウンで選択するので 10,30,50,100 のいずれかです

Slide 203

Slide 203 text

203 Infrastructure User Interface Application Domain OK NG 1件~100件まで 自由に取れます ドロップダウンで選択するので 10,30,50,100 のいずれかです

Slide 204

Slide 204 text

204 Infrastructure User Interface Application Domain OK NG Validation Module OK

Slide 205

Slide 205 text

No content

Slide 206

Slide 206 text

206

Slide 207

Slide 207 text

207

Slide 208

Slide 208 text

208

Slide 209

Slide 209 text

209

Slide 210

Slide 210 text

210

Slide 211

Slide 211 text

211

Slide 212

Slide 212 text

212

Slide 213

Slide 213 text

213

Slide 214

Slide 214 text

214

Slide 215

Slide 215 text

215

Slide 216

Slide 216 text

216

Slide 217

Slide 217 text

217 ID

Slide 218

Slide 218 text

218 ID ID

Slide 219

Slide 219 text

219 ID ID

Slide 220

Slide 220 text

220 class UserApplicationService { ... public function create(string $email, string $password): UserCreateResult { return $this->transaction->scope(function () use ($email, $password) { $user = $this->userFactory->create($email, $password); $found = $this->userRepository->findByEmail($user->getEmail()); if (!is_null($found)) { return UserCreateResult::fail(UserCreateError::EMAIL_ALREADY_USING); } $this->userRepository->save($user); return UserCreateResult::success($user->getId()); }); } ... }

Slide 221

Slide 221 text

221 class UserApplicationService { ... public function create(string $email, string $password): UserCreateResult { return $this->transaction->scope(function () use ($email, $password) { $user = $this->userFactory->create($email, $password); $found = $this->userRepository->findByEmail($user->getEmail()); if (!is_null($found)) { return UserCreateResult::fail(UserCreateError::EMAIL_ALREADY_USING); } $this->userRepository->save($user); return UserCreateResult::success($user->getId()); }); } ... }

Slide 222

Slide 222 text

222 class UserApplicationService { ... public function create(string $email, string $password): UserCreateResult { return $this->transaction->scope(function () use ($email, $password) { $user = $this->userFactory->create($email, $password); $found = $this->userRepository->findByEmail($user->getEmail()); if (!is_null($found)) { return UserCreateResult::fail(UserCreateError::EMAIL_ALREADY_USING); } $this->userRepository->save($user); return UserCreateResult::success($user->getId()); }); } ... }

Slide 223

Slide 223 text

223 class UserApplicationService { ... public function create(string $email, string $password): UserCreateResult { return $this->transaction->scope(function () use ($email, $password) { $user = $this->userFactory->create($email, $password); $found = $this->userRepository->findByEmail($user->getEmail()); if (!is_null($found)) { return UserCreateResult::fail(UserCreateError::EMAIL_ALREADY_USING); } $this->userRepository->save($user); return UserCreateResult::success($user->getId()); }); } ... }

Slide 224

Slide 224 text

224 class UserApplicationService { ... public function create(string $email, string $password): UserCreateResult { return $this->transaction->scope(function () use ($email, $password) { $user = $this->userFactory->create($email, $password); $found = $this->userRepository->findByEmail($user->getEmail()); if (!is_null($found)) { return UserCreateResult::fail(UserCreateError::EMAIL_ALREADY_USING); } $this->userRepository->save($user); return UserCreateResult::success($user->getId()); }); } ... }

Slide 225

Slide 225 text

225 class UserApplicationService { ... public function create(string $email, string $password): UserCreateResult { return $this->transaction->scope(function () use ($email, $password) { $user = $this->userFactory->create($email, $password); $found = $this->userRepository->findByEmail($user->getEmail()); if (!is_null($found)) { return UserCreateResult::fail(UserCreateError::EMAIL_ALREADY_USING); } $this->userRepository->save($user); return UserCreateResult::success($user->getId()); }); } ... }

Slide 226

Slide 226 text

226 class UserApplicationService { ... public function create(string $email, string $password): UserCreateResult { return $this->transaction->scope(function () use ($email, $password) { $user = $this->userFactory->create($email, $password); $found = $this->userRepository->findByEmail($user->getEmail()); if (!is_null($found)) { return UserCreateResult::fail(UserCreateError::EMAIL_ALREADY_USING); } $this->userRepository->save($user); return UserCreateResult::success($user->getId()); }); } ... }

Slide 227

Slide 227 text

227 class UserApplicationService { ... public function create(string $email, string $password): UserCreateResult { return $this->transaction->scope(function () use ($email, $password) { $user = $this->userFactory->create($email, $password); $found = $this->userRepository->findByEmail($user->getEmail()); if (!is_null($found)) { return UserCreateResult::fail(UserCreateError::EMAIL_ALREADY_USING); } $this->userRepository->save($user); return UserCreateResult::success($user->getId()); }); } ... }

Slide 228

Slide 228 text

228 class AuthController extends Controller { public function postRegister(Request $request, UserApplicationService $service) { ... $email = $request->get("email"); $password = $request->get("password"); try { $service->create($email, $password); } catch ($exception) { $result = UserCreateError::EMAIL_ALREADY_USING; } ... } }

Slide 229

Slide 229 text

229 class AuthController extends Controller { public function postRegister(Request $request, UserApplicationService $service) { ... $email = $request->get(“email”); $password = $request->get(“password”); $result = $service->create($email, $password); ... } }

Slide 230

Slide 230 text

230

Slide 231

Slide 231 text

No content

Slide 232

Slide 232 text

232

Slide 233

Slide 233 text

233

Slide 234

Slide 234 text

234

Slide 235

Slide 235 text

235

Slide 236

Slide 236 text

236

Slide 237

Slide 237 text

237 class RequestResponseLogger { public function handle(Request $request, Closure $next) { ... Logging Request $response = $next($request); ... Logging Response return $response; } }

Slide 238

Slide 238 text

238 class RequestResponseLogger { public function handle(Request $request, Closure $next) { ... Logging Request $response = $next($request); ... Logging Response return $response; } }

Slide 239

Slide 239 text

239 class RequestResponseLogger { public function handle(Request $request, Closure $next) { ... Logging Request $response = $next($request); ... Logging Response return $response; } }

Slide 240

Slide 240 text

240 class RequestResponseLogger { public function handle(Request $request, Closure $next) { ... Logging Request $response = $next($request); ... Logging Response return $response; } }

Slide 241

Slide 241 text

241

Slide 242

Slide 242 text

242 class BackLogApplicationService { ... public function estimateUserStory(string $aId, int $estimation): void { $this->transaction->scope(function () use ($aId, $estimation) { $id = new UserStoryId($aId); $story = $this->userStoryRepository->find($id); if (is_null($story)) { throw new NotFoundException($aId . " not found."); } $story->estimate($estimation); $this->userStoryRepository->save($story); }); } }

Slide 243

Slide 243 text

243 class BackLogApplicationService { ... public function estimateUserStory(string $aId, int $estimation): void { $this->transaction->scope(function () use ($aId, $estimation) { $id = new UserStoryId($aId); $story = $this->userStoryRepository->find($id); if (is_null($story)) { throw new NotFoundException($aId . " not found."); } $story->estimate($estimation); $this->userStoryRepository->save($story); }); } }

Slide 244

Slide 244 text

244 class BackLogApplicationService { ... public function estimateUserStory(string $aId, int $estimation): void { $this->transaction->scope(function () use ($aId, $estimation) { $id = new UserStoryId($aId); $story = $this->userStoryRepository->find($id); if (is_null($story)) { throw new NotFoundException($aId . " not found."); } $story->estimate($estimation); $this->userStoryRepository->save($story); }); } }

Slide 245

Slide 245 text

245 class BackLogApplicationService { ... public function estimateUserStory(string $aId, int $estimation): void { $this->transaction->scope(function () use ($aId, $estimation) { $id = new UserStoryId($aId); $story = $this->userStoryRepository->find($id); if (is_null($story)) { throw new NotFoundException($aId . " not found."); } $story->estimate($estimation); $this->userStoryRepository->save($story); }); } }

Slide 246

Slide 246 text

246 class BackLogApplicationService { ... public function estimateUserStory(string $aId, int $estimation): void { $this->transaction->scope(function () use ($aId, $estimation) { $id = new UserStoryId($aId); $story = $this->userStoryRepository->find($id); if (is_null($story)) { throw new NotFoundException($aId . " not found."); } $story->estimate($estimation); $this->userStoryRepository->save($story); }); } }

Slide 247

Slide 247 text

247 class BackLogApplicationService { ... public function estimateUserStory(string $aId, int $estimation): void { $this->transaction->scope(function () use ($aId, $estimation) { $id = new UserStoryId($aId); $story = $this->userStoryRepository->find($id); if (is_null($story)) { throw new NotFoundException($aId . " not found."); } $story->estimate($estimation); $this->userStoryRepository->save($story); }); } }

Slide 248

Slide 248 text

248 class ExceptionResolver { public function handle(Request $request, Closure $next) { $response = $next($request); if (!empty($response->exception)) { if ($response->exception instanceof NotFoundException){ return response(view("notfound")); } } return $response; } }

Slide 249

Slide 249 text

249

Slide 250

Slide 250 text

250 Infrastructure User Interface Application Domain OK NG

Slide 251

Slide 251 text

251 2000 2005 2010 2015 2020 SDプラン RSプラン

Slide 252

Slide 252 text

252

Slide 253

Slide 253 text

253

Slide 254

Slide 254 text

254

Slide 255

Slide 255 text

10年 先を見据えて作る PHP WEBアプリケーション設計入門

Slide 256

Slide 256 text

No content

Slide 257

Slide 257 text

257

Slide 258

Slide 258 text

258

Slide 259

Slide 259 text

259

Slide 260

Slide 260 text

260 class UserApplicationService { /** @var UserRepositoryInterface */ private $userRepository; ... public function retrieveById(string $aId): ?User { $id = new UserId($aId); $user = $this->userRepository->find($id); return $user; } }

Slide 261

Slide 261 text

261 class AuthenticateService { /** @var UserRepositoryInterface */ private $userRepository; public function __construct(UserRepositoryInterface $userRepository) { $this->userRepository = $userRepository; } public function authenticate(string $aEmail, string $password): bool { $email = new Email($aEmail); $user = $this->userRepository->findByEmail($email); if (is_null($user)) { return false; } $hasher = new PasswordHasher(); return $hasher->checkByUser($password, $user); } }

Slide 262

Slide 262 text

262 class OriginalUserProvider implements UserProvider { /** @var AuthenticateService */ private $authenticateService; /** @var UserApplicationService */ private $userService; public function __construct( AuthenticateService $authenticateService, UserApplicationService $userService ) { $this->authenticateService = $authenticateService; $this->userService = $userService; } ... public function validateCredentials(Authenticatable $user, array $credentials) { $password = $credentials["password"]; $email = $credentials["email"]; $result = $this->authenticateService->authenticate($email, $password); return $result; } }

Slide 263

Slide 263 text

263

Slide 264

Slide 264 text

264 Auther Masanobu Naruse YouTube https://www.youtube.com/c/narusemi HomePage https://nrslib.com Twitter @nrslib