Slide 1

Slide 1 text

モンスト10周年における真獣神化実装担当者が 10年分 形態変化 設計をイチから作り直した話 飯島 緋理 デジタルエンターテインメントオペレーションズ本部 モンスト開発部 モンストサーバ1グループ サーバチーム

Slide 2

Slide 2 text

2 自己紹介 ➔ 飯島緋理 (いいじまあかり) ➔ 富山県出身 ➔ 2022年新卒入社 ➔ モンストサーバチーム ◆ モンスト 運用と開発をしています ➔ コーヒー(浅煎り)が大好き ◆ 毎朝ハンドドリップしています

Slide 3

Slide 3 text

3 モンストサーバチームと サーバチーム(10〜15人ほど) 開発 運用 私 ● バージョンアップ案件 ● コラボ案件 etc… ● バージョンアップメンテ ● サーバ増強・縮退 etc… 先輩 1 先輩 2 先輩 N モンスト(日本版) モンスト(繁体字版) モンストスタジアム …

Slide 4

Slide 4 text

4 モンストサーバチームと サーバチーム(10〜15人ほど) 開発 運用 私 ● バージョンアップ案件 ● コラボ案件 etc… ● バージョンアップメンテ ● サーバ増強・縮退 etc… 先輩 1 先輩 2 先輩 N モンスト(日本版) モンスト(繁体字版) モンストスタジアム 私 真獣神化 案件 先輩 1 先輩 N 案件A 案件B ➔ サーバチーム1人に対して1つ 案件を担当 ➔ 今回 話題 、 真獣神化 開発でバージョンアップ案件 ☝ 先輩 2 …

Slide 5

Slide 5 text

5 目次 ● モンスト 形態変化 ● モンスト 形態変化 複雑化 ● 既存コード 問題点 ● 形態変化をイチから作り直す必要性 ● 形態変化を作り直す ○ 既存コードと理想コード ○ 既存コードから学ぶ ○ 形態変化別 テンプレートを用意 ○ 結果 ○ (おまけ) 1ヶ月テストを書き続ける ● まとめ

Slide 6

Slide 6 text

6 モンスト 形態変化

Slide 7

Slide 7 text

7 モンスト 形態変化 モンストと 、 育成したモンスター を自分 指で引っ張って敵モンスターに 当てて倒す“新感覚”アクションRPG

Slide 8

Slide 8 text

8 モンストと 、 育成したモンスター を自分 指で引っ張って敵モンスターに 当てて倒す“新感覚”アクションRPG 強化:レベルや経験値をUPさせる=強くなる 形態変化:レア度やステータスをUPさせる=強くなる モンスト 形態変化

Slide 9

Slide 9 text

9 モンストと 、 育成したモンスター を自分 指で引っ張って敵モンスターに 当てて倒す“新感覚”アクションRPG 強化:レベルや経験値をUPさせる=強くなる 形態変化:レア度やステータスをUPさせる=強くなる 2013.10.10 「進化」登場(モンストリリース) 2014.03.03 「神化」登場 2015.10.28 「獣神化」登場 2019.10.08 「獣神化改」登場 2023.10.07 「真獣神化」登場 モンスト10周年目で 5種類目が実装 → 複雑な状態に ※こ 発表で これらを 「形態変化」と総称して呼 びます モンスト 形態変化

Slide 10

Slide 10 text

10 モンスト 形態変化 複雑化

Slide 11

Slide 11 text

11 モンスト 形態変化 複雑化 形態変化 スライド形態変化 進化前 進化 神化 獣神化 獣神化改 真獣神化 形態変化 ・一方通行で退化できない ・進化 / 神化 / 獣神化 が受け口 スライド形態変化 ・進化 / 神化間で可能 ・獣神化 / 獣神化改 / 真獣神化 間   で可能

Slide 12

Slide 12 text

12 進化前 進化 神化 獣神化 獣神化改 真獣神化 モンスト 形態変化 複雑化 形態変化 スライド形態変化 形態変化 ・一方通行で退化できない ・進化 / 神化 / 獣神化 が受け口 スライド形態変化 ・進化 / 神化間で可能 ・獣神化 / 獣神化改 / 真獣神化 間   で可能

Slide 13

Slide 13 text

13 進化前 進化 神化 獣神化 獣神化改 真獣神化 モンスト 形態変化 複雑化 形態変化 スライド形態変化 形態変化 ・一方通行で退化できない ・進化 / 神化 / 獣神化 が受け口 スライド形態変化 ・進化 / 神化間で可能 ・獣神化 / 獣神化改 / 真獣神化 間   で可能

Slide 14

Slide 14 text

14 進化前 進化 神化 獣神化 獣神化改 真獣神化 モンスト 形態変化 複雑化 形態変化 スライド形態変化 形態変化 ・一方通行で退化できない ・進化 / 神化 / 獣神化 が受け口 スライド形態変化 ・進化 / 神化間で可能 ・獣神化 / 獣神化改 / 真獣神化 間   で可能

Slide 15

Slide 15 text

15 進化前 進化 神化 獣神化 獣神化改 真獣神化 モンスト 形態変化 複雑化 形態変化 スライド形態変化 形態変化 ・一方通行で退化できない ・進化 / 神化 / 獣神化 が受け口 スライド形態変化 ・進化 / 神化間で可能 ・獣神化 / 獣神化改 / 真獣神化 間   で可能

Slide 16

Slide 16 text

16 進化前 進化 神化 獣神化 獣神化改 真獣神化 基本的な形態変化ができる条件 ・コインが足りていること ・レベルMAXであること ・素材が足りていること  →形態変化で素材が異なる  →特殊な素材がある  →消費に優先順位がある ・ミッション達成していること etc.. 複雑化 ポイント ❶ 複雑化 ポイント ❷ モンスト 形態変化 複雑化 形態変化 スライド形態変化

Slide 17

Slide 17 text

17 進化前 進化 神化 獣神化 獣神化改 真獣神化 神化 獣神化 スライド形態変化 (無限に)種類を増やせる 複雑化 ポイント ❸ 神化 獣神化改 モンスト 形態変化 複雑化 形態変化 スライド形態変化

Slide 18

Slide 18 text

18 進化前 進化 神化 獣神化 獣神化改 真獣神化 神化 獣神化 特殊アイテムを使用すれ 獣神化 ・レベル 上限UP ・ステータス 上限UP 獣神化改 ・スキル発動 制約をなくせる → スライド形態変化しても   アイテム使用履歴 残る 複雑化 ポイント ❹ モンスト 形態変化 複雑化 形態変化 スライド形態変化

Slide 19

Slide 19 text

19 進化前 進化 進化 進化 獣神化前 獣神化 真獣神化前 真獣神化 獣神化 獣神化改 同じ形態変化 階層が あったり... 間 形態変化がなく、 形態変化 種類が少なかっ たり... そもそも形態変化 先がなかったり... 複雑化 ポイント ❺ 複雑化 ポイント ❻ 複雑化 ポイント ❼ etc… モンスト 形態変化 複雑化 形態変化 スライド形態変化

Slide 20

Slide 20 text

20 既存コード 問題点

Slide 21

Slide 21 text

21   形態変化別 処理 既存コード 問題点 ス タ | ト お わ り   素材別 処理   共通処理 1つ ファイルに 全て 形態変化が集約&都度分岐

Slide 22

Slide 22 text

22 既存コード 問題点 ス タ | ト お わ り   形態変化別 処理   素材別 処理   共通処理 WET なコードになっている ● WET (Write Every Time: 繰り返す) ● 同じ条件を扱う制御文 ブロック群が様々な場所に重複して出現 ● WET DRY (Don’t Repeat Yourself: 繰り返さない) 対義語で、DRYになっていな いコードに対する皮肉的な言い方 ● 以下3つ 困難が発生する 1. コードを読む作業が難しくなる 2. コードを修正する作業が難しくなる 3. テストがない ※ 以上3つ 箇条書き 、 上田勲『プリンシプル オブ プログラミング』p34 抜粋 → 以上 3つ 困難全てに遭遇する

Slide 23

Slide 23 text

23 形態変化をイチから作り直す必要性

Slide 24

Slide 24 text

24 形態変化をイチから作り直す必要性 形態変化 種類が今後も増える可能性がある ● モンスト 10周年目を迎え、新しく真獣神化が実装された ● これからも開発が続いていく可能性が高い 1. 誰もが変更&追加しやすいコードにしなけれ ならない a. 開発スピードが下がるようなこと あって ならない 2. 古いコードに頼って かりで いけない a. 10年前 古いコードが多く残っている b. コーディング記法が変わっているかもしれない c. (もしかしたら)変更&追加に 考古学が必須となり手間が増える

Slide 25

Slide 25 text

25 形態変化をイチから作り直す前に、 既存 コードに変更(真獣神化 実装)を入れてみて、思っ たことを整理しよう! ● 理由① フラストレーションを糧に形態変化をイチから作り直す必要性を見出す ● 理由② 先に「真獣神化 開発」だけにフォーカスする ○ 「開発」と「リファクタリング」を同時期に一緒にしない ■ NG例:目的 混同、変更 追跡やテスト 複雑化 ○ 先に「開発」をして、時間に余裕があれ 「リファクタリング」をする ○ 真獣神化リリースまで期日があり遅れて いけない 形態変化をイチから作り直す必要性

Slide 26

Slide 26 text

26 ス タ | ト お わ り   形態変化別 処理   素材別 処理   共通処理 ここに、 真獣神化 実装を追加してみる! 形態変化をイチから作り直す必要性

Slide 27

Slide 27 text

27 ス タ | ト お わ り   形態変化別 処理   素材別 処理   共通処理 既存 コードに変更を加えてみて思ったことを整理する ①「形態変化別 実装を理解する にとても時間がかかる」  読み進む度に都度分岐が発生し、それぞれ 挙動が一目でわかりづらい  形態変化別だけで なく素材 消費方法 分岐も相まってかなり複雑な状態  注目したい処理 側に、必要 ない情報が溢れている 誰もが読みやすく理解しやすい コードにしなけれ ならない 形態変化をイチから作り直す必要性

Slide 28

Slide 28 text

28 ス タ | ト お わ り   形態変化別 処理   素材別 処理   共通処理 既存 コードに変更を加えてみて思ったことを整理する ②「考古学が大変だった」  コードやテストから容易に仕様把握ができず、 git blame したり、当時  Pull Request や Issue を漁って過去 変更を調査  → しかし、レポジトリ移行により、10年前 歴史が失われている  最初期 git log が失われているため、辿れない部分があった コード or テストから仕様把握しやすいように 新しいチームメンバーに 難しい考古学をさせて いけない 形態変化をイチから作り直す必要性

Slide 29

Slide 29 text

29 ス タ | ト お わ り   形態変化別 処理   素材別 処理   共通処理 既存 コードに変更を加えてみて思ったことを整理する ③「テストケースが足りない」  テストからも仕様を把握することができない  カバレッジ率 元々高いが形態変化別でパターンを網羅できていない  (例:進化と神化 両方で使用されるメソッド A, B, C があるとして、  進化で AとC テストがあり、神化で B だけテストがある) テストを足すことで仕様把握を 簡単に&安全を保証しなけれ ならない 形態変化をイチから作り直す必要性

Slide 30

Slide 30 text

30 ス タ | ト お わ り   形態変化別 処理   素材別 処理   共通処理 既存 コードに変更を加えてみて思ったことを整理する ① 誰もが読みやすく理解しやすいコードにしなけれ ならない ② コード or テストから仕様把握しやすいように新しいチームメンバーに 難しい考古学をさせて いけない ③ テストを足すことで仕様把握を簡単に&安全を保証しなけれ ならない 私: 「既存 コードに変更を入れる がとても辛かった...」 「リリース日まで時間 たくさん残した で、  残り時間で形態変化をイチから作り直すぞ!」 形態変化をイチから作り直す必要性

Slide 31

Slide 31 text

31 形態変化を作り直す

Slide 32

Slide 32 text

32 形態変化を作り直す ス タ | ト お わ り   形態変化別 処理   素材別 処理   共通処理 既存コードと理想コード 既存コード:1つ ファイルに 全て 形態変化が集約&都度分岐

Slide 33

Slide 33 text

33 ス タ | ト お わ り   形態変化別 処理   共通処理 進化 処理 神化 処理   素材別 処理 獣神化 処理 獣神化改 処理 真獣神化 処理 形態変化ごとに処理を追いやすくなるが... 理想コード:形態変化別 処理が理解しやすい&読みやすい 形態変化を作り直す 既存コードと理想コード

Slide 34

Slide 34 text

34 ス タ | ト お わ り   形態変化別 処理   共通処理 進化 処理 神化 処理   素材別 処理 獣神化 処理 獣神化改 処理 真獣神化 処理 共通処理が多く存在しており、まだDRYなコードで ない 理想コード:形態変化別 処理が理解しやすい&読みやすい 形態変化を作り直す 既存コードと理想コード

Slide 35

Slide 35 text

35 ス タ | ト お わ り   形態変化別 処理   素材別 処理   共通処理 既存コード:1つ ファイルに 全て 形態変化が集約&都度分岐 形態変化を作り直す 既存コードと理想コード

Slide 36

Slide 36 text

36 設計迷子になった私に対して、優しいサーバチーム みんな: 「既存 コード 設計がなぜ生まれた か、 もう一度見直してみる どうだろう?」 ハッとした私: 「既存 コード 評価 かりをしていて、 捨象することをすっかり忘れていた。」 形態変化を作り直す 既存コードから学ぶ

Slide 37

Slide 37 text

37 結果として:  評価... 強み、弱み、機会、脅威など 具体的な洞察を得る  捨象... より単純で理解しやすいモデルや概念を生み出す 捨象... 複雑な対象に取り組む際、余計なも を捨て本質を捉えること 例: 犬 犬販売管理 ※ 上田勲『プリンシプル オブ プログラミング』p82 抜粋 name weight type birth height name weight type birth height weight height 形態変化を作り直す 既存コードから学ぶ

Slide 38

Slide 38 text

38 既存 コード設計 本質: 「それぞれ 形態変化 流れがほとんど同じな で、  内部処理を統合し、形態変化別 処理 都度する」 1. レシピを用意 2. 素材チェック 3. 素材消費 4. キャラ変化 何かを悟った私: 「形態変化別 テンプレート(レシピ ようなも )を準備して、テンプレートを見ながら  キャラを形 態変化すると良さそう」 (1) レシピを見ながら... 形態変化を作り直す 既存コードから学ぶ

Slide 39

Slide 39 text

39 形態変化を作り直す 形態変化別 テンプレートを用意 デザインパターン:Template Method パターン … 目的:ある処理 おおまかなアルゴリズムをあらかじめ決めておいて、そ アルゴリズム 具体的 な設計をサブクラスに任せること。 ※『Wikipedia: Template Method パターン』抜粋 形態変化 テンプレート 抽象クラス サブクラス (進化) サブクラス (神化) サブクラス (獣神化) サブクラス (獣神化改) サブクラス (真獣神化) 結局、共通処理 多いまま 抽象クラスが肥大化 ... データ 持ち方を工夫する if (進化) 進化.new # 進化サブクラスを生成 else if (神化) 神化.new # 神化サブクラスを生成 … 継承

Slide 40

Slide 40 text

40 形態変化 テンプレート クラス インスタンス (進化) インスタンス (神化) インスタンス (獣神化) インスタンス (獣神化改) インスタンス (真獣神化) インスタンス インスタンス変数 違いで形態変化別 テンプレートを作成する ・データ 持ち方を共通化(新しいデータ構 を生成)することで、  テンプレート自身どんな形態変化な か知る必要なし ・形態変化別 分岐処理自体が存在しなくなる → DRY!!! if (進化) Template.new(進化 アイテム, 進化 キャラ, …) else if (神化) Template.new(神化 アイテム, 神化 キャラ, …) … 新しいデータ構 を生成する 形態変化を作り直す 形態変化別 テンプレートを用意

Slide 41

Slide 41 text

41 形態変化 テンプレート バリデーション & 形態変化実行 形態変化後 形態変化前 ① ② ③ 進化 神化 獣神化 獣神化改 真獣神化 素材 消費方法 決定 ① ス タ | ト お わ り ① 形態変化前キャラと形態変化後キャラを取得 ② ① 形態変化後キャラを元に形態変化テンプレートを生成 ③ ② テンプレートを見て① 形態変化前キャラに 形態変化を実行 形態変化を作り直す 形態変化別 テンプレートを用意 依存 クラス インスタンス

Slide 42

Slide 42 text

42 形態変化後 形態変化前 ① ① ス タ | ト お わ り ① 形態変化前キャラと形態変化後キャラを取得 形態変化を作り直す 形態変化別 テンプレートを用意 依存 クラス インスタンス

Slide 43

Slide 43 text

43 形態変化 テンプレート 形態変化後 形態変化前 ① ② 進化 神化 獣神化 獣神化改 真獣神化 ① ス タ | ト お わ り 今回 こ テンプレート! ① 形態変化前キャラと形態変化後キャラを取得 ② ① 形態変化後キャラを元に形態変化テンプレートを生成 形態変化を作り直す 形態変化別 テンプレートを用意 依存 クラス インスタンス

Slide 44

Slide 44 text

44 形態変化を作り直す 形態変化別 テンプレートを用意 ① 形態変化前キャラと形態変化後キャラを取得 ② ① 形態変化後キャラを元に形態変化テンプレートを生成 形態変化 テンプレート 形態変化後 形態変化前 ① ② 進化 神化 獣神化 獣神化改 真獣神化 ① ス タ | ト お わ り 形態変化別にインスタンス変数 値を設定 形態変化共通 新データ構 を生成 → 形態変化別 違い テンプレート   構築処理を追うだけで良い → 分岐処理がなく処理を追いやすくなった → DRYなコードになり変更が容易になった 今回 こ テンプレート! 依存 クラス インスタンス

Slide 45

Slide 45 text

45 形態変化 テンプレート 形態変化後 形態変化前 ① ② 進化 神化 獣神化 獣神化改 真獣神化 素材 消費方法 決定 ① ス タ | ト お わ り ① 形態変化前キャラと形態変化後キャラを取得 ② ① 形態変化後キャラを元に形態変化テンプレートを生成 形態変化を作り直す 形態変化別 テンプレートを用意 依存 クラス インスタンス

Slide 46

Slide 46 text

46 ① 形態変化前キャラと形態変化後キャラを取得 ② ① 形態変化後キャラを元に形態変化テンプレートを生成 形態変化 テンプレート 形態変化後 形態変化前 ① ② クラス 進化 神化 獣神化 獣神化改 真獣神化 素材 消費方法 決定 ① ス タ | ト お わ り テンプレートに任せずに 別クラスに分離して責務 を分ける → 素材 消費方法を自由   に選択できる → 素材 み 変更が   しやすい 形態変化を作り直す 形態変化別 テンプレートを用意 依存 クラス インスタンス

Slide 47

Slide 47 text

47 形態変化 テンプレート バリデーション & 形態変化実行 形態変化後 形態変化前 ① ② ③ 依存 クラス 進化 神化 獣神化 獣神化改 真獣神化 素材 消費方法 決定 ① ス タ | ト お わ り ① 形態変化前キャラと形態変化後キャラを取得 ② ① 形態変化後キャラを元に形態変化テンプレートを生成 ③ ② テンプレートを見て① 形態変化前キャラに 形態変化を実行 インスタンス 形態変化を作り直す 形態変化別 テンプレートを用意

Slide 48

Slide 48 text

48 形態変化 テンプレート バリデーション & 形態変化実行 形態変化後 形態変化前 ① ② ③ 進化 神化 獣神化 獣神化改 真獣神化 素材 消費方法 決定 ① ス タ | ト お わ り コイン 足りている? 素材 足りている? etc… 形態変化 メイン処理!!! ① 形態変化前キャラと形態変化後キャラを取得 ② ① 形態変化後キャラを元に形態変化テンプレートを生成 ③ ② テンプレートを見て① 形態変化前キャラに 形態変化を実行 形態変化を作り直す 形態変化別 テンプレートを用意 依存 クラス インスタンス

Slide 49

Slide 49 text

49   形態変化別 処理 形態変化を作り直す ス タ | ト お わ り   素材別 処理   共通処理 結果:BEFORE 1つ ファイルに 全て 形態変化が集約&都度分岐

Slide 50

Slide 50 text

50 形態変化 テンプレート バリデーション & 形態変化実行 形態変化後 形態変化前 ① ② ③ 進化 神化 獣神化 獣神化改 真獣神化 素材 消費方法 決定 ① ス タ | ト お わ り ① 形態変化前キャラと形態変化後キャラを取得 ② ① 形態変化後キャラを元に形態変化テンプレートを生成 ③ ② テンプレートを見て① 形態変化前キャラに 形態変化を実行 形態変化を作り直す 結果:AFTER 依存 クラス インスタンス

Slide 51

Slide 51 text

51 形態変化を作り直す 結果 ● シンプルな構成になって、見通しがよくなった ● 形態変化別 違い テンプレート(インスタンス変数)を見るだけでわ かるようになったため、処理が追いやすくなった ● サーバチーム 皆さんからも読みやすい!と 声があった ● テストがとても書きやすかった!!! ● テストがしっかりしていた で作り直しによる重大なバグ 生まれな かった

Slide 52

Slide 52 text

52 テストを書く〜前半戦〜 ・作り直し対象 Model  テストをControllerに避難 ・足りないテストを追加 テストを書く〜後半戦〜 ・新しく作り直したモデル  ユ ニットテストを追加 形態変化を 作り直す 形態変化を作り直す (おまけ) 1ヶ月テストを書き続ける Controller 足りていない テスト追加 Model テスト NEW Model Controller NEW Model NEW Model テスト 既存 挙動を担保したまま、足りないテストを追加 作り直しによるバグを生み出さない Model Model テスト 約 2.5週間 約 1.5週間 132 → 814 examples 105 examples Controller

Slide 53

Slide 53 text

53 まとめ

Slide 54

Slide 54 text

54 まとめ ● 真獣神化 実装(開発)と、 形態変化 設計をイチから作り直した (リファクタリング) ● テスト 大事さを再確認 ○ テスト おかげで重大なバグ なく、作り直し 成功した ● Pull Request や Commit メッセージ 重要性を再確認 ○ 考古学 辛い... 反省点 ● 既存コード 評価 かりで、捨象が後回しになってしまった ● トライアンドエラー方式でとりあえず手を動かしてみたが効率が悪かった ● 抽象化と言語化をやり込んでから実装すべきだった ● 追加したテストを見直す(高 化)までがリファクタリング 今後 展望 ● 反省点を活かして、次 XXX を作り直すぞ!!!

Slide 55

Slide 55 text

55 リファクタリング とてもタメになる ● 頭でっかちにならない → 知識を実践的なスキルに変えることができる ● レビューが上達する → 人が書いたコード 「読み方」を学べ、「なぜ」を理解できる ● コミュニケーションが活発になる → チーム内で 知識共有や議論を促進できる ● 視野が広くなる → 長期的な視点、将来入ってくるチームメンバー 視点に立てる

Slide 56

Slide 56 text

56 謝辞 サーバチーム 皆さんから 本当にたくさん アドバイスいただき、助けていただきました。 ありがとうございました!