PofEAAで読み解くDoctrine2

 PofEAAで読み解くDoctrine2

PHPカンファレンス福岡2018の15分枠の発表資料です。

2018.06.19 口頭で説明した内容を追記

88ad4f75d7c84fcf560bb6205c52e8c1?s=128

dnskimo

June 16, 2018
Tweet

Transcript

  1. PofEAAで読み解く Doctrine2 @dnskimox

  2. 自己紹介 ⊡ 本名:丹賀健一 ⊡ 通称:男爵 ⊡ dnskimo ⊡ dnskimox ⊡

    北海道在住 ⊡ 株式会社インフィニットループ ⊡ ソシャゲバックエンドAPI開発
  3. 宣伝のやつ https://www.infiniteloop.co.jp/blog/2018/06/seventeenth/

  4. P of EAA https://ja.wikipedia.org/wiki/マーティン・ファウ ラー ⊡ 原題『Patterns of Enterprise Application

    Architecture』 ⊡ マーティン・ファウラー著 ⊡ エンタープライズアプリケーションの ための設計パターン集
  5. エンタープライズアプリケーションと は? 1. データを永続化する 2. 大量のデータを扱う 3. 同時に多数のリクエストを受けつける 4. 他のエンタープライズアプリケーションと連携する

  6. エンタープライズアプリケーションと は? P of EAA ≒ WEBアプリケーションのための設 計パターン集

  7. Catalog of P of EAA ⊡ Domain Model ⊡ Active

    Record ⊡ Data Mapper ⊡ Unit of Work ⊡ Identity Map ⊡ Metadata Mapping ⊡ Foreign Key Mapping ⊡ Lazy Load ⊡ Single Table Inheritance ⊡ Repository ⊡ Model View Controller ⊡ Front Controller ⊡ Remote Facade ⊡ Service Layer ⊡ Data Transfer Object ⊡ Optimistic Offline Lock ⊡ Layer Supertype ⊡ Separated Interface ⊡ Value Object ⊡ etc...
  8. Doctrine2 ⊡ Data Mapperパターンを採用したORM ⊡ Symfony Standard Editionに同梱 ⊡ Doctrine2単独で使うことも可能

  9. 架空のActive Record

  10. 関心事多すぎ? Characterクラスの関心事 ⊡ 自身が保有するデータ ⊡ ドメインロジック ⊡ 自身の状態をDBに反映する方法 ⊡ DBから自身を復元する方法

  11. 関心の分離ができたら…… Characterクラスの関心事 ⊡ 自身が保有するデータ ⊡ ドメインロジック ???の関心事 ⊡ オブジェクトの状態をDBに 反映する方法

    ⊡ DBからオブジェクトを復元 する方法
  12. Data Mapper オブジェクトとデータベースを分離する

  13. “ A layer of Mappers that moves data between objects

    and a database while keeping them independent of each other and the mapper itself.
  14. Doctrine2のData Mapperのイメージ

  15. 登場人物紹介

  16. Entity ⊡ 永続化されるオブジェクト ⊡ 一意な識別子を持つ ⊡ Plain Old PHP Object

  17. ClassMetadata ⊡ エンティティとテーブルを対 応付けるための地図 ⊡ エンティティ同士の関係図

  18. Persister ⊡ DBにデータを保存する ⊡ DBからデータを取り出す ⊡ SQLを組み立てる

  19. Hyderator ⊡ DBから取り出したデータか らエンティティを復元する ⊡ 乾燥保存されたデータに水 を与える(Hydrate)

  20. Repository ⊡ エンティティ検索のためのコ レクション風のインター フェースを提供 ⊡ アプリケーション側の拡張ポ イント

  21. UnitOfWork ⊡ エンティティを監視し、その 変化を記録する ⊡ 詳細は後述

  22. EntityManager ⊡ データマッパーオブジェクト達 の窓口役(Facade) ⊡ データマッパーオブジェクト間 の調停者(Mediator)

  23. How It Works

  24. CRUDのC $em = EntityManager::create(...); $character = new Character(); $character->setName(“Bob”); $em->persist($character);

    $em->flush(); // Executed SQL: INSERT INTO characters (name) VALUES(‘Bob’);
  25. CRUDのCの舞台裏(1)

  26. CRUDのCの舞台裏(2)

  27. CRUDのR $em = EntityManager::create(...); $characterRepository = $em->getRepository(Character::class); $character = $characterRepository->find(1);

    // Executed SQL: SELECT FROM characters WHERE id = 1; $characters = $characterRepository->findByName(“Bob”); // Executed SQL: SELECT FROM characters WHERE name = ‘Bob’; $characters = $characterRepository->findAll(); // Executed SQL: SELECT FROM characters;
  28. CRUDのRの舞台裏

  29. 経験値獲得メソッド class Character... public function gainExp(int $exp) { assert(0 <

    $exp); $this->setExp($this->getExp() + $exp); // 以下レベルアップ判定など ... } }
  30. CRUDのU $em = EntityManager::create(...); $characterRepository = $em->getRepository(Character::class); $character = $characterRepository->find(1);

    // Executed SQL: SELECT FROM characters WHERE id = 1; $character->gainExp(100); $em->flush(); // Executed SQL: UPDATE characters SET exp = 100 WHERE id = 1;
  31. Unit of Work オブジェクトを追跡し、その変化を書き出す

  32. “ Maintains a list of objects affected by a business

    transaction and coordinates the writing out of changes and the resolution of concurrency problems.
  33. How It Works

  34. UnitOfWorkの暗躍 Rで密かにやっていたこと ⊡ エンティティを監視下に置く ⊡ エンティティのオリジナルデー タを保持する Uでやること ⊡ 現在のエンティティとオリジ

    ナルデータを比較する ⊡ 差分があったらPersisterに 更新を依頼する
  35. CRUDのUの舞台裏(1)

  36. CRUDのUの舞台裏(2)

  37. ロストアップデートの予感…… $character1A = $characterRepository->find(1); // Executed SQL: SELECT FROM characters

    WHERE id = 1; $character1B = $characterRepository->find(1); // Executed SQL?: SELECT FROM characters WHERE id = 1; $character1A->gainExp(100); $character1B->gainExp(100); $em->flush(); // Executed SQL?: UPDATE characters SET exp = 100 WHERE id = 1; // Executed SQL?: UPDATE characters SET exp = 100 WHERE id = 1;
  38. Identity Map メモリ上のオブジェクトを一意にする

  39. “ Ensures that each object gets loaded only once by

    keeping every loaded object in a map. Looks up objects using the map when referring to them.
  40. How It Works

  41. 真・CRUDのRの舞台裏(1)

  42. 真・CRUDのRの舞台裏(2)

  43. ロストアップデートは起きない $character1A = $characterRepository->find(1); // Executed SQL: SELECT FROM characters

    WHERE id = 1; $character1B = $characterRepository->find(1); // Executed SQL: NONE $character1A->gainExp(100); $character1B->gainExp(100); $em->flush(); // Executed SQL: UPDATE characters SET exp = 200 WHERE id = 1;
  44. CRUDのDについ ては割愛

  45. その他Doctrine2で使われているパ ターン ⊡ Domain Model ⊡ Active Record ⊡ Data

    Mapper ⊡ Unit of Work ⊡ Identity Map ⊡ Metadata Mapping ⊡ Foreign Key Mapping ⊡ Lazy Load ⊡ Single Table Inheritance ⊡ Repository ⊡ Model View Controller ⊡ Front Controller ⊡ Remote Facade ⊡ Service Layer ⊡ Data Transfer Object ⊡ Optimistic Offline Lock ⊡ Layer Supertype ⊡ Separated Interface ⊡ Value Object ⊡ etc...
  46. Let’s Doctrine!

  47. 参考文献 ⊡ Patterns of Enterprise Application Architecture ⊡ Catalog of

    Patterns of Enterprise Application Architecture ⊡ Data Mapper ⊡ Unit of Work ⊡ Identity Map ⊡ POJO