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

形から入ったドメイン駆動設計によるゲーム開発の光と闇

n1215
October 23, 2019

 形から入ったドメイン駆動設計によるゲーム開発の光と闇

TECHxGAME COLLEGE #28(https://techxgamecollege.connpass.com/event/148035/) の発表資料です

n1215

October 23, 2019
Tweet

More Decks by n1215

Other Decks in Programming

Transcript

  1. ⾃⼰紹介 京都から来ました - 中榮健⼆ (なかえけんじ) - twitter: @n_1215  - 株式会社Nextat

    取締役 - baserCMS コアコミッター(最近コミットしてない) - Laravel + Unity でソシャゲ開発など Nextat Inc. 3
  2. お話しするゲームシステムの主な構成 ゲームサーバ: PHP + Laravel ゲームAPI: Web, Android, iOSに対応するため、JSONを返すAPI マスタデータ管理画⾯:

    マスタデータ作成・更新のための機能。HTML CS管理画⾯: ユーザの⾏動履歴などお問い合わせ対応⽤の機能。HTML データベース: MySQL、Redis クライアント: Unity、 JavaScript Nextat Inc. 21
  3. Model Eloquent (ActiveRecord系のORM) の"モデル"を継承しただけ クエリ発⾏、DB保存、ドメインロジックを全て⾏う class UserCharacter extends \Illuminate\Database\Eloquent\Model {

    } Controller class UserCharactersController { public function lock(int $userCharacterId): JsonResponse { $userId = auth()->id(); $userChara = UserCharacter::whereUserId(userId)->findOrFail($userCharacterId); $userChara->is_locked = true; $userChara->save(); return response()->json($userChara->toArray()); // この辺りがView } } Nextat Inc. 25
  4. 定番の戦術1. レイヤ化アーキテクチャ レイヤ 責務 UI (Presentation) ユーザに情報を表⽰、ユーザのコマンドを解釈 Application ソフトウェアで⾏う仕事の定義。ドメインオブジェクトにより問 題を解決

    Domain (Model) ビジネスの概念、情報、ビジネスルールを表現 Infrastructure 上位のレイヤを⽀える⼀般的な技術的機能を提供 Nextat Inc. 26
  5. ex). ユーザ所持キャラクター(略式) class UserCharacter { /** ID */ private $userCharacterId;

    /** キャラクター(マスタ) */ private $character; /** 攻撃⼒などのステータス */ private $status; /** ロックされているかどうか */ private $isLocked; public function lock(): void { $this->isLocked = true; } } Nextat Inc. 30
  6. ex) キャラクターのレアリティ class CharacterRarity { /** @var int */ private

    $value; public function __construct(int $value): void { if ($value < 1 || $value > 5) { throw new \InvalidArgumentException(' レアリティは1 以上5以下の整数'); } $this->value = value; } public function getValue(): int { return $this->value(); } } Nextat Inc. 32
  7. ex) キャラクターのファクトリ class CharacterFactory { public function makeFromRecord(CharacterRecord $record): Character

    { return new Character( new CharacterId($record->id), new Name($record->name), new Rarity($record->rarity), // 略 ); } } Nextat Inc. 34
  8. ex) キャラクターのリポジトリ class CharacterRepository { public function find(CharacterId $characterId): ?Character

    { $record = CharacterRecord::query()->find($characterId->getValue())); if ($record === null) { return null; } return $this->characterFactory->makeFromRecord($record); } } Nextat Inc. 36
  9. ex) ユーザ所持キャラクターをロックする操作 class LockUserCharacterService { public function lock(UserCharacterId $userCharacterId): UserCharacter

    { $userCharacter = $this->userCharacterRepository->find($userCHaracterId); $userCharacter->lock(); $this->userCharacterRepository->save($userCharacter); return $userCharacter; } } Nextat Inc. 38
  10. 整理し直す before after UI Controller,View Controller,View Application Controller ApplicationService Domain

    Eloquent Model Entity、VO RepositoryのInterface Factory DomainService Infrastructure Eloquent Model Repository(Eloquent実装) Nextat Inc. 39
  11. Therefore its name was called Babel, because there the LORD

    confused the language of all the earth. And from there the LORD dispersed them over the face of all the earth. https://biblehub.com/esv/genesis/11.htm The city and its tower Nextat Inc. 49
  12. 語順も違うし…… 英語:主語(S)動詞(V)⽬的語(0) The user character attacks to the enemy. $userCharacter->attack($enemy);

    ⽇本語: 主語(S)⽬的語(0) 動詞(V) ユーザー所持キャラクターが 敵を 攻撃する $ ユーザー所持キャラクター-> 攻撃する($ 敵) 助詞もないし⽚⾔っぽい Nextat Inc. 59
  13. ex) ユーザ所持キャラクターの限界突破の履歴 class BreakLimitUserCharacterService public function breakLimit( PlayerId $playerId, UserCharacterId

    $userCharacterId ) { // ( 略) // 限界突破の処理 $afterUserCharacter = $beforeUserCharacter->breakLimit($materials); $this->userCharacterRepository->save($afterUserCharacter); // 履歴を残す処理 $this->breakLimitHistoryService->add( $beforeUserCharacter, $afterUserCharacter, $materials ); // その他限界突破素材アイテムを消費する処理など } Nextat Inc. 85
  14. コードの重複 ユーザに付与されるデータ アイテムマスタ + 有効期限 + 数 装備品マスタ + 初期経験値

    + 数 キャラクターマスタ + 初期経験値 + 初期限界突破数 + 数 switchで分岐してそれぞれ処理 あまりに多すぎて実は共通化したほうがいいことに気づく Nextat Inc. 89