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

WEB アプリケーション設計入門 / Introduction to web application design

nrs
December 12, 2020

WEB アプリケーション設計入門 / Introduction to web application design

PHP Conference Japan 2020
トーク前提の資料です。そのため、トークがないと理解が難しいかもしれません。
https://youtu.be/UTKJ-Lgn3aI?t=36
※冒頭音声が小さいです。マイクを手に持ってから聞こえやすくなると思います。

資料中の ADOP については下記を参照ください。
https://nrslib.com/adop/

# Abstract
https://fortee.jp/phpcon-2020/proposal/da5b9d99-e5a6-4f51-adea-1f1c10d99020

# Ref
https://github.com/nrslib/scrum-app-sample-php
https://github.com/nrslib/repository-support-php

# URL
Togetter: https://togetter.com/li/1635360
YouTube: https://www.youtube.com/c/narusemi
HomePage: https://nrslib.com
Twitter: https://twitter.com/nrslib

nrs

December 12, 2020
Tweet

More Decks by nrs

Other Decks in Programming

Transcript

  1. 20 2000 2005 2010 2015 2020 PHP Tools (1995) PHP2

    (1996) PHP3 (1998) PHP4 (2000) PHP5 (2004) PHP6 PHP7 (2015) PHP8 (2020)
  2. 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)
  3. 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)
  4. 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)
  5. 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)
  6. 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)
  7. 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)
  8. 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)
  9. 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)
  10. 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)
  11. 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)
  12. 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)
  13. 33

  14. 34

  15. 35

  16. 36

  17. 37

  18. 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)
  19. 45

  20. 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年後に残ってそうか の観点で選ぶ
  21. 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年残るかは運次第
  22. 48

  23. 49

  24. 50

  25. 52

  26. 53

  27. 63

  28. 64

  29. 65

  30. 66

  31. 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"]); } }
  32. 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"]); } }
  33. 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"]); } }
  34. 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"]); } }
  35. 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"]); } }
  36. 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"]); } }
  37. 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"]); } }
  38. 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"]); } }
  39. 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"]); } }
  40. 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"]); } }
  41. 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"]); } }
  42. 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"]); } }
  43. 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"]); } }
  44. 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"]); } }
  45. 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"]); } }
  46. 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); }); } }
  47. 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); }); } }
  48. 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); }); } }
  49. 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); }); } }
  50. 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); }); } }
  51. 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); }); } }
  52. 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); }); } }
  53. 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); }); } }
  54. 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); }); } }
  55. 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); }); } }
  56. 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); }); } }
  57. 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); }); } }
  58. 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); }); } }
  59. 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() ] ); } }
  60. 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() ] ); } }
  61. 99

  62. 100

  63. 102

  64. 103

  65. 104

  66. 105

  67. 106

  68. 107

  69. 108

  70. 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); }); } }
  71. 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); }); } }
  72. 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); }); } }
  73. 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); }); } }
  74. 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; } ... }
  75. 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; } ... }
  76. 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; } ... }
  77. 117

  78. 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 ); ... } }
  79. 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 ); ... } }
  80. 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); ... } }
  81. 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); ... } }
  82. 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 { } }
  83. 126

  84. 127

  85. 128

  86. 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); ... } }
  87. 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 { } }
  88. 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 { } }
  89. 136

  90. 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); ... } }
  91. 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); } }
  92. 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); } }
  93. 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; } } }
  94. 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; } } }
  95. 143

  96. 144

  97. 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; } ... }
  98. 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 = []; }
  99. 151

  100. 155 class UserStory extends Model { protected $table = "user_stories";

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

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

    public $incrementing = false; protected $keyType = "string"; public $guarded = []; /** @var UserStoryId */ private $id; ... } User Story
  103. 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); }); } }
  104. 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); }); } }
  105. 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); }); } }
  106. 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); }); } }
  107. 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); }); } }
  108. 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; } }
  109. 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); }); } }
  110. 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); }); } }
  111. 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); }); } }
  112. 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(); } } }
  113. 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(); } } }
  114. 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(); } } }
  115. 182 interface Transaction { /** * @param callable $transactionScope *

    @return mixed */ function scope(callable $transactionScope): ?object; function begin(); function commit(); function rollback(); }
  116. 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(); } }
  117. 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(); } } }
  118. 186 class NopTransaction implements Transaction { function scope(callable $transactionScope): ?object

    { return $transactionScope(); } function begin() { } function commit() { } function rollback() { } }
  119. 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"]); } }
  120. 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"]); } }
  121. 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; } }
  122. 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; } }
  123. 202 Infrastructure User Interface Application Domain OK NG 1件~100件まで 自由に取れます

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

    ドロップダウンで選択するので 10,30,50,100 のいずれかです
  125. 206

  126. 207

  127. 208

  128. 209

  129. 210

  130. 211

  131. 212

  132. 213

  133. 214

  134. 215

  135. 216

  136. 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()); }); } ... }
  137. 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()); }); } ... }
  138. 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()); }); } ... }
  139. 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()); }); } ... }
  140. 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()); }); } ... }
  141. 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()); }); } ... }
  142. 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()); }); } ... }
  143. 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()); }); } ... }
  144. 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; } ... } }
  145. 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); ... } }
  146. 230

  147. 232

  148. 233

  149. 234

  150. 235

  151. 236

  152. 237 class RequestResponseLogger { public function handle(Request $request, Closure $next)

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

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

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

    { ... Logging Request $response = $next($request); ... Logging Response return $response; } }
  156. 241

  157. 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); }); } }
  158. 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); }); } }
  159. 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); }); } }
  160. 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); }); } }
  161. 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); }); } }
  162. 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); }); } }
  163. 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; } }
  164. 249

  165. 252

  166. 253

  167. 254

  168. 257

  169. 258

  170. 259

  171. 260 class UserApplicationService { /** @var UserRepositoryInterface */ private $userRepository;

    ... public function retrieveById(string $aId): ?User { $id = new UserId($aId); $user = $this->userRepository->find($id); return $user; } }
  172. 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); } }
  173. 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; } }
  174. 263