SlideShare une entreprise Scribd logo
1  sur  34
Copyright © DeNA Co.,Ltd. All Rights Reserved.
長期運用に耐えるため
の設計とリファクタリ
ング
April 27, 2018
廣橋 俊昭
DeNA Games Tokyo
Copyright © DeNA Co.,Ltd. All Rights Reserved.
自己紹介
 名前
 廣橋 俊昭
 生年月日
 1990/02/04 (28歳)
 趣味
 ダーツ
 経歴
 2013年、DeNA入社
 複数のブラウザゲームを渡り歩き開発/運用を経験
 2015年、運用タイトルのリードエンジニアに
 2017年、DeNA Games Tokyoに合流、
ブラウザゲーム/アプリゲームの運営に携わる
2
Copyright © DeNA Co.,Ltd. All Rights Reserved.
アジェンダ
 運用を見据えての設計観点
⁃ 正規化の重要性
⁃ 機能単位でのコード分割
 リファクタリングをやる必要性とタイミング
3
Copyright © DeNA Co.,Ltd. All Rights Reserved.
ゲーム運用でよくあること
 イベントの開催
⁃ マスターデータの追加
• カードデータ (名前, HP, 攻撃力)
• BOSSのデータ
• 等々
⁃ 新たな効果/演出の追加
• 単体攻撃だけでなく全体攻撃の追加
• 連続攻撃の追加
• 等々
 新機能のリリース
⁃ キャラクターを強化できる素材の追加
• テーブル/コードをまるっと追加する
4
Copyright © DeNA Co.,Ltd. All Rights Reserved.
ゲーム運用でよくあること
 イベントの開催
⁃ マスターデータの追加
• カードデータ (名前, HP, 攻撃力)
• BOSSのデータ
• 等々
⁃ 新たな効果/演出の追加
• 単体攻撃だけでなく全体攻撃の追加
• 連続攻撃の追加
• 等々
 新機能のリリース
⁃ キャラクターを強化できる素材の追加
• テーブル/コードをまるっと追加する
5
これらをミスなく運用していきたい
Copyright © DeNA Co.,Ltd. All Rights Reserved.
アジェンダ
 運用を見据えての設計
⁃ 正規化の重要性
⁃ 機能単位でのコード分割
 リファクタリングをやる必要性とタイミング
6
Copyright © DeNA Co.,Ltd. All Rights Reserved.
キャラクターの(特殊)効果の実装
 とあるイベントにて
⁃ キャラクター3人をデッキに編成して敵を倒す
 キャラクターの基礎パラメータは以下の通り
⁃ キャラクターID
⁃ 名前
⁃ HP
⁃ 攻撃力
⁃ 防御力
 各キャラクターは戦闘中に1回特殊効果を発動できる
7
デッキ
敵キャラ
Copyright © DeNA Co.,Ltd. All Rights Reserved.
キャラクターの(特殊)効果の実装
 各キャラクターの特殊効果は以下の通り
8
稀に自分の攻撃力の3倍ダメージを敵に与える
(失敗した場合は1倍)
5連続攻撃を行う
自分の攻撃力の1.5倍のダメージを敵に与える
実装はひとまずおいてデータの持ち方を考えてみる
Copyright © DeNA Co.,Ltd. All Rights Reserved.
キャラクターの(特殊)効果の実装
 各キャラクターの特殊効果は以下の通り
9
稀に自分の攻撃力の3倍ダメージを敵に与える
(失敗した場合は1倍)
5連続攻撃を行う
自分の攻撃力の1.5倍のダメージを敵に与える
Copyright © DeNA Co.,Ltd. All Rights Reserved.
データの持ち方-1
 シンプルに考えて1つのテーブルにまとめてみる
⁃ 機能的には実現できそう
⁃ 新たなキャラクターデータを足したらどうなるか
• 基礎パラメータの異なる5連続攻撃を行うキャラD
10
ID 名前 HP 攻撃力 防御力 特殊効果ID 特殊効果説明
キャラA 1 A 10 20 5 1 稀に自分の攻撃力の3倍ダメー
ジを敵に与える
(失敗した場合は1倍)
キャラB 2 B 15 10 10 2 5連続攻撃を行う
キャラC 3 C 20 15 10 3 自分の攻撃力の1.5倍のダメー
ジを敵に与える
Copyright © DeNA Co.,Ltd. All Rights Reserved.
データの持ち方-1
 シンプルに考えて1つのテーブルにまとめてみる
⁃ 機能的には実現できそう
⁃ 新たなキャラクターデータを足したらどうなるか
• 基礎パラメータの異なる5連続攻撃を行うキャラD
• 説明を重複して何度も登録しないといけない
⁃ 修正したい場合修正箇所が増える
⁃ 運用しているとキャラクターの種類は増えるはず
11
ID 名前 HP 攻撃力 防御力 特殊効果ID 特殊効果説明
キャラA 1 A 10 20 5 1 稀に自分の攻撃力の3倍ダメー
ジを敵に与える
(失敗した場合は1倍)
キャラB 2 B 15 10 10 2 5連続攻撃を行う
キャラC 3 C 20 15 10 3 自分の攻撃力の1.5倍のダメー
ジを敵に与える
キャラD 4 D 25 10 15 2 5連続攻撃を行う
Copyright © DeNA Co.,Ltd. All Rights Reserved.
正規化してデータを保持する
 正規化を施してみる
⁃ 正規化はざっくりいうと冗長部分をなくすこと
⁃ キャラクターと特殊効果のテーブルをわけてみる
12
Copyright © DeNA Co.,Ltd. All Rights Reserved.
正規化してデータを保持する
 正規化を施してみる
⁃ 正規化はざっくりいうと冗長部分をなくすこと
⁃ キャラクターと特殊効果のテーブルをわけてみる
• キャラクターから効果はIDで参照できる
• 説明を何度も書かなくてよくなる
13
ID 名前 H
P
攻撃力 防御力 特殊効果ID
キャラA 1 A 10 20 5 1
キャラB 2 B 15 10 10 2
キャラC 3 C 20 15 10 3
キャラD 4 D 25 10 15 2
特殊効果ID 特殊効果説明
1 稀に自分の攻撃力の3倍ダメー
ジを敵に与える
(失敗した場合は1倍)
2 5連続攻撃を行う
3 自分の攻撃力の1.5倍のダメー
ジを敵に与える
Copyright © DeNA Co.,Ltd. All Rights Reserved.
正規化は大事
 テーブル設計で正規化はよくあるテクニックだが、長期運用には欠かせ
ない
⁃ 重複はマスターデータ作成/修正コストが高い
• 修正範囲が広い
• 変更を加える場合、修正漏れが発生する可能性がある
14
Copyright © DeNA Co.,Ltd. All Rights Reserved.
アジェンダ
 運用を見据えての設計
⁃ 正規化の重要性
⁃ 機能単位でのコード分割
 リファクタリングをやる必要性とタイミング
15
Copyright © DeNA Co.,Ltd. All Rights Reserved.
キャラクターの(特殊)効果の実装
 各キャラクターの特殊効果は以下の通り
16
稀に自分の攻撃力の3倍ダメージを敵に与える
(失敗した場合は1倍)
5連続攻撃を行う
自分の攻撃力の1.5倍のダメージを敵に与える
再掲
今度は実装側を考えてみる
Copyright © DeNA Co.,Ltd. All Rights Reserved.
実装の大まかな流れ
1. キャラクターの情報を取得する
2. キャラクターの特殊効果を引っ張る
3. 敵キャラクターの情報を取得する
4. 特殊効果とキャラクター情報からダメージ値を計算
5. ボスのHPからダメージ値を引く
17
sub skill_execute( my $character_id, my $boss_id) {
my $character = get_character_by_id($character_id);
my $boss = get_boss_by_id($boss_id);
my $skill = get_skill_by_id($character->get_skill_id());
my $damage = $skill->calc_damage($character);
$boss->set_hp($boss->get_hp() - $damage);
return;
}
Copyright © DeNA Co.,Ltd. All Rights Reserved.
実装の大まかな流れ
1. キャラクターの情報を取得する
2. キャラクターの特殊効果を引っ張る
3. 敵キャラクターの情報を取得する
4. 特殊効果とキャラクター情報からダメージ値を計算
5. ボスのHPからダメージ値を引く
18
sub skill_execute( my $character_id, my $boss_id) {
my $character = get_character_by_id($character_id);
my $boss = get_boss_by_id($boss_id);
my $skill = get_skill_by_id($character->get_skill_id());
my $damage = $skill->calc_damage($character);
$boss->set_hp($boss->get_hp() - $damage);
return;
}
Copyright © DeNA Co.,Ltd. All Rights Reserved.
特殊効果実装 – その1
 例によってシンプルに実装してみる
⁃ この分量だとそこまで問題ない
かもしれない
⁃ しかし運用が続き、たくさんの
効果が追加されたら・・・
• 10連続攻撃
• 1/2で2倍攻撃
• 1.8倍攻撃
• etc
19
sub calc_damage (my $character) {
my $self = shift;
my $atk = $character->get_atk();
if ($self->get_id() == 1) {
# 1/10で3倍攻撃
if (rand() % 10 == 0) {
return $atk * 3;
} else {
return $atk;
}
} elsif (($self->get_id() == 2) {
# 今は5倍攻撃と変わらない
return $atk * 5;
} elsif (($self->get_id() == 3)) {
return $atk * 1.5;
} else {
# error!!
}
}
Copyright © DeNA Co.,Ltd. All Rights Reserved.
特殊効果が増えていくと・・・
 ダメージ計算のコードが数百行になる
⁃ コードの流れを追うのが難しくな
る
⁃ 既存の特殊効果を修正/追記した
い場合、該当箇所を探すのが大変
 どんどん効果追加の難易度があがって
いく
20
sub calc_damage (my $character) {
my $self = shift;
my $atk = $character->get_atk();
if ($self->get_id() == 1) {
# 特殊効果1
} elsif ($self->get_id() == 2) {
# 特殊効果2
} elsif ($self->get_id() == 3) {
# 特殊効果3
} elsif ($self->get_id() == 4) {
# 特殊効果4
} elsif ($self->get_id() == 5) {
# 特殊効果5
} elsif ($self->get_id() == 6) {
# 特殊効果6
} elsif ($self->get_id() == 7) {
# 特殊効果7
} elsif ($self->get_id() == 8) {
# 特殊効果8
} …
}
Copyright © DeNA Co.,Ltd. All Rights Reserved.
特殊効果実装 – その2
 効果ごとにコードを分割してみる
⁃ 特殊効果ID単位でわける
• get_skill_by_idで返す$skillをわける
• よくある手法はtemplate methodだが、ここでは割愛
⁃ きになる方はデザインパターンで検索
21
sub skill_execute( my $character_id, my $boss_id) {
my $character = get_character_by_id($character_id);
my $boss = get_boss_by_id($boss_id);
my $skill = get_skill_by_id($character->get_skill_id());
my $damage = $skill->calc_damage($character);
$boss->set_hp($boss->get_hp() - $damage);
return;
}
Copyright © DeNA Co.,Ltd. All Rights Reserved.
機能単位でのコード分割
 分割されたことで特殊効果ごとの挙動が明確に
⁃ 1効果1ファイルなので追加も容易
• Baseをつくると必要なmethodが明確になる
⁃ エラー時等も対象が絞れて迅速に対応できる
22
sub calc_damage(my
$character) {
my $self = shift;
if (rand() % 10 == 0) {
return
$character->get_atk() * 3
} else {
return
$character->get_atk()
}
}
sub calc_damage(my
$character) {
return $character-
>get_atk() * 5;
}
sub calc_damage(my
$character) {
return $character-
>get_atk() * 1.5
}
特殊効果ID : 1 特殊効果ID : 2 特殊効果ID : 3
Copyright © DeNA Co.,Ltd. All Rights Reserved.
アジェンダ
 運用を見据えての設計
⁃ 正規化の重要性
⁃ 機能単位でのコード分割
 リファクタリングをやる必要性とタイミング
23
Copyright © DeNA Co.,Ltd. All Rights Reserved.
リファクタリングの前置き
 リファクタリング
⁃ コンピュータプログラミングにおいて、プログラムの外部から見た
動作を変えずにソースコードの内部構造を整理することである
• Wikipediaより引用
 正規化や機能単位でのコード分割をしていればリファクタリング不要で
は?
24
Copyright © DeNA Co.,Ltd. All Rights Reserved.
リファクタリングの前置き
 リファクタリング
⁃ コンピュータプログラミングにおいて、プログラムの外部から見た
動作を変えずにソースコードの内部構造を整理することである
• Wikipediaより引用
 正規化や機能単位でのコード分割をしていればリファクタリング不要で
は?
25
リファクタリングが途中で必要になるケースを紹介
Copyright © DeNA Co.,Ltd. All Rights Reserved.
キャラクターの(特殊)効果
 各キャラクターの特殊効果は以下の通り
 実装は正規化済み + 機能単位でコードがわかれているとする
26
稀に自分の攻撃力の3倍ダメージを敵に与える
(失敗した場合は1倍)
5連続攻撃を行う
自分の攻撃力の1.5倍のダメージを敵に与える
Copyright © DeNA Co.,Ltd. All Rights Reserved.
キャラクターの(特殊)効果の仕様追加その1
 キャラクターの種類の追加に伴い、以下の仕様を追加
⁃ 敵キャラを複数体出せるようにする
• 5連続攻撃と5倍攻撃は異なるものに
 既存で動いている部分に影響なく追加したい心理が働く
⁃ 実装期間が短めだった場合
⁃ 仕様追加がそこまで大きくリファクタリングするほどでもない場合
⁃ 等々
27
Copyright © DeNA Co.,Ltd. All Rights Reserved.
影響範囲少な目のコード
 極端ではあるが、外側をifでくくってしまう
⁃ 敵が一人の場合はほとんど影響なし
⁃ 似たようなコードは量産されてしまう・・・
⁃ skill_executeの可読性down
28
sub skill_execute( my $character_id, my $boss_ids) {
if (scalar @$boss_ids == 1) {
# 敵が一人の従来の処理
my $boss_id = $boss_ids->[0];
} else {
# 敵が複数人の場合
…
my $boss_num = scalar @$boss_ids;
# 新規実装
my $damage_list = calc_damage_list($character, $boss_num);
…
}
}
Copyright © DeNA Co.,Ltd. All Rights Reserved.
キャラクターの(特殊)効果の仕様追加その2
 キャラクターの種類の追加に伴い、以下の仕様を追加
⁃ デッキ内の自分のキャラクターをランダムで回復させたい
 今までのHP減算前提のコードの再利用はできなさそう・・・
⁃ 今回もifで分岐させる
29
Copyright © DeNA Co.,Ltd. All Rights Reserved.
キャラクターの(特殊)効果の仕様追加その2
 キャラクターの種類の追加に伴い、以下の仕様を追加
⁃ デッキ内の自分のキャラクターをランダムで回復させたい
 今までのHP減算前提のコードの再利用はできなさそう・・・
30
sub skill_execute( my $character_id, my $boss_ids) {
my $self = shift;
if ($self->get_id() == 回復ID) {
# 回復処理
} else {
if (scalar @$boss_ids == 1) {
# 敵が一人の従来の処理
} else {
# 敵が複数人の場合
}
}
}
いつの間にか複雑な条件分岐だらけに・・・
Copyright © DeNA Co.,Ltd. All Rights Reserved.
なぜこのようなことに・・・
 当初のコードは機能ごとに分割していたが、仕様変更に耐えられなかっ
た
⁃ 1対象への攻撃前提なので以下は想定外
• 複数敵キャラクターの追加
• 自キャラクターへの効果
 回避もできたかもしれない
⁃ 機能リリース時の仕様は1対象への攻撃かもしれないが、複数や回
復を企画メンバーはすでに考えていたかもしれない
⁃ サービスの未来を見据えて企画とエンジニアが話すことも大事
31
Copyright © DeNA Co.,Ltd. All Rights Reserved.
なぜこのようなことに・・・
 当初のコードは機能ごとに分割していたが、仕様変更に耐えられなかっ
た
⁃ 1対象への攻撃前提なので以下は想定外
• 複数敵キャラクターの追加
• 自キャラクターへの効果
 回避もできたかもしれない
⁃ 機能リリース時の仕様は1対象への攻撃かもしれないが、複数や回
復を企画メンバーはすでに考えていたかもしれない
⁃ サービスの未来を見据えて企画とエンジニアが話すことも大事
32
とはいえ、こうなったら恐れずリファクタリング!!
Copyright © DeNA Co.,Ltd. All Rights Reserved.
リファクタリングする
 基本方針
⁃ 機能単位で分割する
⁃ 複数のターゲットに効果を与えると考える
 skill_executeの中身にリファクタリングを絞り、挙動に変更を与えなけ
れば確認範囲を最小限ですむはず
33
sub skill_execute( my $executor_id, my $target_ids) {
my $character = get_character_by_id($ executor _id);
my $targets = get_targets_by_id($target_ids);
my $skill = get_skill_by_id($character->get_skill_id());
$skill->exec_effect($character, $targets);
return;
}
sub exec_effect()
targetを選んで稀
に3倍攻撃。
sub exec_effect()
targetを5回抽選し
て攻撃
sub exec_effect()
targetを選んで1.5
倍攻撃
sub exec_effect()
targetを選んで回
復
Copyright © DeNA Co.,Ltd. All Rights Reserved.
まとめ
 長期運用で主に意識したい設計観点は以下の2点
⁃ 極力テーブル構造は正規化する
• マスターデータの誤入力を抑える
⁃ 機能単位でコードは分割
• 可読性の担保
• 機能追加の容易さの確保
 気をつけて設計してもリファクタリングは必要
⁃ 企画とエンジニアとの話し合いで回避できることも
⁃ リファクタリングの際も設計観点は変わらない
34

Contenu connexe

Tendances

DeNA の新しいネイティブ開発(パズル戦隊デナレンジャー)
DeNA の新しいネイティブ開発(パズル戦隊デナレンジャー)DeNA の新しいネイティブ開発(パズル戦隊デナレンジャー)
DeNA の新しいネイティブ開発(パズル戦隊デナレンジャー)dena_study
 
FINAL FANTASY Record Keeperのマスターデータを支える技術
FINAL FANTASY Record Keeperのマスターデータを支える技術FINAL FANTASY Record Keeperのマスターデータを支える技術
FINAL FANTASY Record Keeperのマスターデータを支える技術dena_study
 
DeNAのゲームを支えるプラットフォーム Sakasho #denatechcon
DeNAのゲームを支えるプラットフォーム Sakasho #denatechconDeNAのゲームを支えるプラットフォーム Sakasho #denatechcon
DeNAのゲームを支えるプラットフォーム Sakasho #denatechconDeNA
 
DeNAのプログラミング教育の取り組み #denatechcon
DeNAのプログラミング教育の取り組み #denatechconDeNAのプログラミング教育の取り組み #denatechcon
DeNAのプログラミング教育の取り組み #denatechconDeNA
 
DeNAの動画配信サービスを支えるインフラの内部 #denatechcon
DeNAの動画配信サービスを支えるインフラの内部  #denatechconDeNAの動画配信サービスを支えるインフラの内部  #denatechcon
DeNAの動画配信サービスを支えるインフラの内部 #denatechconDeNA
 
Unity開発で週イチ呑み会を支える技術
Unity開発で週イチ呑み会を支える技術Unity開発で週イチ呑み会を支える技術
Unity開発で週イチ呑み会を支える技術kazuya noshiro
 
オタクエンジニアを熱くさせる!モチベーションをあげるチームビルディング
オタクエンジニアを熱くさせる!モチベーションをあげるチームビルディングオタクエンジニアを熱くさせる!モチベーションをあげるチームビルディング
オタクエンジニアを熱くさせる!モチベーションをあげるチームビルディング虎の穴 開発室
 
オタクエンジニアを熱くさせる!モチベーションと効率をあげるチームビルディング_20210611_TechDay#1_3
オタクエンジニアを熱くさせる!モチベーションと効率をあげるチームビルディング_20210611_TechDay#1_3オタクエンジニアを熱くさせる!モチベーションと効率をあげるチームビルディング_20210611_TechDay#1_3
オタクエンジニアを熱くさせる!モチベーションと効率をあげるチームビルディング_20210611_TechDay#1_3虎の穴 開発室
 
Xen+Windowsで構築するサーバ仮想化環境
Xen+Windowsで構築するサーバ仮想化環境Xen+Windowsで構築するサーバ仮想化環境
Xen+Windowsで構築するサーバ仮想化環境VirtualTech Japan Inc.
 
Anyca(エニカ)のC2Cビジネスを支えるシステムと運用 #denatechcon
Anyca(エニカ)のC2Cビジネスを支えるシステムと運用 #denatechconAnyca(エニカ)のC2Cビジネスを支えるシステムと運用 #denatechcon
Anyca(エニカ)のC2Cビジネスを支えるシステムと運用 #denatechconDeNA
 
【公開版】アジャイル推進組織奮闘記
【公開版】アジャイル推進組織奮闘記【公開版】アジャイル推進組織奮闘記
【公開版】アジャイル推進組織奮闘記seag-t
 
虎の穴ラボ Tech day#3 チームで戦う!とらのあな通販冬の大感謝祭でのフロント開発について
虎の穴ラボ Tech day#3 チームで戦う!とらのあな通販冬の大感謝祭でのフロント開発について虎の穴ラボ Tech day#3 チームで戦う!とらのあな通販冬の大感謝祭でのフロント開発について
虎の穴ラボ Tech day#3 チームで戦う!とらのあな通販冬の大感謝祭でのフロント開発について虎の穴 開発室
 
ガチャサイクルと海外課金
ガチャサイクルと海外課金ガチャサイクルと海外課金
ガチャサイクルと海外課金Hiromasa Iwasaki
 
虎の穴ラボ TechDay#3 フルリモート率100%!リモートワークを可能にするマネージメント
虎の穴ラボ TechDay#3 フルリモート率100%!リモートワークを可能にするマネージメント 虎の穴ラボ TechDay#3 フルリモート率100%!リモートワークを可能にするマネージメント
虎の穴ラボ TechDay#3 フルリモート率100%!リモートワークを可能にするマネージメント 虎の穴 開発室
 
Unityでこんなことができる KLab×博多Tech塾
Unityでこんなことができる KLab×博多Tech塾Unityでこんなことができる KLab×博多Tech塾
Unityでこんなことができる KLab×博多Tech塾KLab Inc. / Tech
 
現場から組織を動かす方法
現場から組織を動かす方法現場から組織を動かす方法
現場から組織を動かす方法Takuya Okamoto
 
社内DX推進!非エンジニア向けにプログラミング講座を実施してみた!
社内DX推進!非エンジニア向けにプログラミング講座を実施してみた!社内DX推進!非エンジニア向けにプログラミング講座を実施してみた!
社内DX推進!非エンジニア向けにプログラミング講座を実施してみた!虎の穴 開発室
 
虎の穴ラボ エンジニア採用説明資料
虎の穴ラボ エンジニア採用説明資料虎の穴ラボ エンジニア採用説明資料
虎の穴ラボ エンジニア採用説明資料虎の穴 開発室
 
ハイブリッドクラウドで変わるインフラストラクチャ設計
ハイブリッドクラウドで変わるインフラストラクチャ設計ハイブリッドクラウドで変わるインフラストラクチャ設計
ハイブリッドクラウドで変わるインフラストラクチャ設計gree_tech
 

Tendances (20)

DeNA の新しいネイティブ開発(パズル戦隊デナレンジャー)
DeNA の新しいネイティブ開発(パズル戦隊デナレンジャー)DeNA の新しいネイティブ開発(パズル戦隊デナレンジャー)
DeNA の新しいネイティブ開発(パズル戦隊デナレンジャー)
 
FINAL FANTASY Record Keeperのマスターデータを支える技術
FINAL FANTASY Record Keeperのマスターデータを支える技術FINAL FANTASY Record Keeperのマスターデータを支える技術
FINAL FANTASY Record Keeperのマスターデータを支える技術
 
DeNAのゲームを支えるプラットフォーム Sakasho #denatechcon
DeNAのゲームを支えるプラットフォーム Sakasho #denatechconDeNAのゲームを支えるプラットフォーム Sakasho #denatechcon
DeNAのゲームを支えるプラットフォーム Sakasho #denatechcon
 
DeNAのプログラミング教育の取り組み #denatechcon
DeNAのプログラミング教育の取り組み #denatechconDeNAのプログラミング教育の取り組み #denatechcon
DeNAのプログラミング教育の取り組み #denatechcon
 
DeNAの動画配信サービスを支えるインフラの内部 #denatechcon
DeNAの動画配信サービスを支えるインフラの内部  #denatechconDeNAの動画配信サービスを支えるインフラの内部  #denatechcon
DeNAの動画配信サービスを支えるインフラの内部 #denatechcon
 
Unity開発で週イチ呑み会を支える技術
Unity開発で週イチ呑み会を支える技術Unity開発で週イチ呑み会を支える技術
Unity開発で週イチ呑み会を支える技術
 
オタクエンジニアを熱くさせる!モチベーションをあげるチームビルディング
オタクエンジニアを熱くさせる!モチベーションをあげるチームビルディングオタクエンジニアを熱くさせる!モチベーションをあげるチームビルディング
オタクエンジニアを熱くさせる!モチベーションをあげるチームビルディング
 
オタクエンジニアを熱くさせる!モチベーションと効率をあげるチームビルディング_20210611_TechDay#1_3
オタクエンジニアを熱くさせる!モチベーションと効率をあげるチームビルディング_20210611_TechDay#1_3オタクエンジニアを熱くさせる!モチベーションと効率をあげるチームビルディング_20210611_TechDay#1_3
オタクエンジニアを熱くさせる!モチベーションと効率をあげるチームビルディング_20210611_TechDay#1_3
 
Xen+Windowsで構築するサーバ仮想化環境
Xen+Windowsで構築するサーバ仮想化環境Xen+Windowsで構築するサーバ仮想化環境
Xen+Windowsで構築するサーバ仮想化環境
 
Anyca(エニカ)のC2Cビジネスを支えるシステムと運用 #denatechcon
Anyca(エニカ)のC2Cビジネスを支えるシステムと運用 #denatechconAnyca(エニカ)のC2Cビジネスを支えるシステムと運用 #denatechcon
Anyca(エニカ)のC2Cビジネスを支えるシステムと運用 #denatechcon
 
【公開版】アジャイル推進組織奮闘記
【公開版】アジャイル推進組織奮闘記【公開版】アジャイル推進組織奮闘記
【公開版】アジャイル推進組織奮闘記
 
虎の穴ラボ Tech day#3 チームで戦う!とらのあな通販冬の大感謝祭でのフロント開発について
虎の穴ラボ Tech day#3 チームで戦う!とらのあな通販冬の大感謝祭でのフロント開発について虎の穴ラボ Tech day#3 チームで戦う!とらのあな通販冬の大感謝祭でのフロント開発について
虎の穴ラボ Tech day#3 チームで戦う!とらのあな通販冬の大感謝祭でのフロント開発について
 
ガチャサイクルと海外課金
ガチャサイクルと海外課金ガチャサイクルと海外課金
ガチャサイクルと海外課金
 
虎の穴ラボ TechDay#3 フルリモート率100%!リモートワークを可能にするマネージメント
虎の穴ラボ TechDay#3 フルリモート率100%!リモートワークを可能にするマネージメント 虎の穴ラボ TechDay#3 フルリモート率100%!リモートワークを可能にするマネージメント
虎の穴ラボ TechDay#3 フルリモート率100%!リモートワークを可能にするマネージメント
 
Unityでこんなことができる KLab×博多Tech塾
Unityでこんなことができる KLab×博多Tech塾Unityでこんなことができる KLab×博多Tech塾
Unityでこんなことができる KLab×博多Tech塾
 
現場から組織を動かす方法
現場から組織を動かす方法現場から組織を動かす方法
現場から組織を動かす方法
 
バレンシアガ『Afterworld: The Age of Tomorrow』の舞台裏 UNREAL FEST EXTREME 2021 SUMMER
バレンシアガ『Afterworld: The Age of Tomorrow』の舞台裏  UNREAL FEST EXTREME 2021 SUMMERバレンシアガ『Afterworld: The Age of Tomorrow』の舞台裏  UNREAL FEST EXTREME 2021 SUMMER
バレンシアガ『Afterworld: The Age of Tomorrow』の舞台裏 UNREAL FEST EXTREME 2021 SUMMER
 
社内DX推進!非エンジニア向けにプログラミング講座を実施してみた!
社内DX推進!非エンジニア向けにプログラミング講座を実施してみた!社内DX推進!非エンジニア向けにプログラミング講座を実施してみた!
社内DX推進!非エンジニア向けにプログラミング講座を実施してみた!
 
虎の穴ラボ エンジニア採用説明資料
虎の穴ラボ エンジニア採用説明資料虎の穴ラボ エンジニア採用説明資料
虎の穴ラボ エンジニア採用説明資料
 
ハイブリッドクラウドで変わるインフラストラクチャ設計
ハイブリッドクラウドで変わるインフラストラクチャ設計ハイブリッドクラウドで変わるインフラストラクチャ設計
ハイブリッドクラウドで変わるインフラストラクチャ設計
 

Similaire à 長期運用に耐えるための設計とリファクタリング(DeNA Games Tokyo)

DeNA流cocos2d xとの付き合い方
DeNA流cocos2d xとの付き合い方DeNA流cocos2d xとの付き合い方
DeNA流cocos2d xとの付き合い方dena_study
 
制作を支えたツール達 (パズル戦隊デナレンジャー)
制作を支えたツール達 (パズル戦隊デナレンジャー)制作を支えたツール達 (パズル戦隊デナレンジャー)
制作を支えたツール達 (パズル戦隊デナレンジャー)dena_study
 
DeNAインフラの今とこれから - 今編 -
DeNAインフラの今とこれから - 今編 -DeNAインフラの今とこれから - 今編 -
DeNAインフラの今とこれから - 今編 -Tomoya Kabe
 
ガールアックス:リアルタイム通信処理の効率的な実装
ガールアックス:リアルタイム通信処理の効率的な実装ガールアックス:リアルタイム通信処理の効率的な実装
ガールアックス:リアルタイム通信処理の効率的な実装dena_study
 
レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる
レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れるレガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる
レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れるsairoutine
 
こんな辛いテストはいやだ
こんな辛いテストはいやだ こんな辛いテストはいやだ
こんな辛いテストはいやだ Takuya Mikami
 
「AROW」お披露目(実用編)
「AROW」お披露目(実用編)「AROW」お披露目(実用編)
「AROW」お披露目(実用編)Drecom Co., Ltd.
 
FFRKを支えるWebアプリケーションフレームワークの技術
FFRKを支えるWebアプリケーションフレームワークの技術FFRKを支えるWebアプリケーションフレームワークの技術
FFRKを支えるWebアプリケーションフレームワークの技術dena_study
 
Cocos2d-x 3.0を使ったゲーム “消滅都市” の開発事例
Cocos2d-x 3.0を使ったゲーム “消滅都市” の開発事例Cocos2d-x 3.0を使ったゲーム “消滅都市” の開発事例
Cocos2d-x 3.0を使ったゲーム “消滅都市” の開発事例gree_tech
 
DeNAの最新のマスタデータ管理システム Oyakata の全容
DeNAの最新のマスタデータ管理システム Oyakata の全容DeNAの最新のマスタデータ管理システム Oyakata の全容
DeNAの最新のマスタデータ管理システム Oyakata の全容sairoutine
 
【TECH×GAME COLLEGE#28】形から入ったドメイン駆動設計によるゲーム開発の光と闇
【TECH×GAME COLLEGE#28】形から入ったドメイン駆動設計によるゲーム開発の光と闇【TECH×GAME COLLEGE#28】形から入ったドメイン駆動設計によるゲーム開発の光と闇
【TECH×GAME COLLEGE#28】形から入ったドメイン駆動設計によるゲーム開発の光と闇techgamecollege
 
ソーシャルゲームの為のデータベース設計
ソーシャルゲームの為のデータベース設計ソーシャルゲームの為のデータベース設計
ソーシャルゲームの為のデータベース設計kaminashi
 
ターン制コマンドバトルにおける強化学習効率化
ターン制コマンドバトルにおける強化学習効率化ターン制コマンドバトルにおける強化学習効率化
ターン制コマンドバトルにおける強化学習効率化gree_tech
 
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編Fixstars Corporation
 
強化学習を利用した自律型GameAIの取り組み ~高速自動プレイによるステージ設計支援~ #denatechcon
強化学習を利用した自律型GameAIの取り組み ~高速自動プレイによるステージ設計支援~ #denatechcon強化学習を利用した自律型GameAIの取り組み ~高速自動プレイによるステージ設計支援~ #denatechcon
強化学習を利用した自律型GameAIの取り組み ~高速自動プレイによるステージ設計支援~ #denatechconDeNA
 
ゲームエンジニアのためのデータベース設計
ゲームエンジニアのためのデータベース設計ゲームエンジニアのためのデータベース設計
ゲームエンジニアのためのデータベース設計sairoutine
 
[141004] cedec 2014 참관기 & 강연 리뷰 #1
[141004] cedec 2014 참관기 & 강연 리뷰 #1[141004] cedec 2014 참관기 & 강연 리뷰 #1
[141004] cedec 2014 참관기 & 강연 리뷰 #1MinGeun Park
 
DeNA_Techcon2017_DeNAでのチート・脆弱性診断への取り組み
DeNA_Techcon2017_DeNAでのチート・脆弱性診断への取り組みDeNA_Techcon2017_DeNAでのチート・脆弱性診断への取り組み
DeNA_Techcon2017_DeNAでのチート・脆弱性診断への取り組みToshiharu Sugiyama
 
DeNA内製ゲームエンジンの現状と目指す未来 #denatechcon
DeNA内製ゲームエンジンの現状と目指す未来 #denatechconDeNA内製ゲームエンジンの現状と目指す未来 #denatechcon
DeNA内製ゲームエンジンの現状と目指す未来 #denatechconDeNA
 
GCM#4 アーティストのためのプログラマブルシェーダー講座Part2
GCM#4 アーティストのためのプログラマブルシェーダー講座Part2GCM#4 アーティストのためのプログラマブルシェーダー講座Part2
GCM#4 アーティストのためのプログラマブルシェーダー講座Part2GREE/Art
 

Similaire à 長期運用に耐えるための設計とリファクタリング(DeNA Games Tokyo) (20)

DeNA流cocos2d xとの付き合い方
DeNA流cocos2d xとの付き合い方DeNA流cocos2d xとの付き合い方
DeNA流cocos2d xとの付き合い方
 
制作を支えたツール達 (パズル戦隊デナレンジャー)
制作を支えたツール達 (パズル戦隊デナレンジャー)制作を支えたツール達 (パズル戦隊デナレンジャー)
制作を支えたツール達 (パズル戦隊デナレンジャー)
 
DeNAインフラの今とこれから - 今編 -
DeNAインフラの今とこれから - 今編 -DeNAインフラの今とこれから - 今編 -
DeNAインフラの今とこれから - 今編 -
 
ガールアックス:リアルタイム通信処理の効率的な実装
ガールアックス:リアルタイム通信処理の効率的な実装ガールアックス:リアルタイム通信処理の効率的な実装
ガールアックス:リアルタイム通信処理の効率的な実装
 
レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる
レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れるレガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる
レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる
 
こんな辛いテストはいやだ
こんな辛いテストはいやだ こんな辛いテストはいやだ
こんな辛いテストはいやだ
 
「AROW」お披露目(実用編)
「AROW」お披露目(実用編)「AROW」お披露目(実用編)
「AROW」お披露目(実用編)
 
FFRKを支えるWebアプリケーションフレームワークの技術
FFRKを支えるWebアプリケーションフレームワークの技術FFRKを支えるWebアプリケーションフレームワークの技術
FFRKを支えるWebアプリケーションフレームワークの技術
 
Cocos2d-x 3.0を使ったゲーム “消滅都市” の開発事例
Cocos2d-x 3.0を使ったゲーム “消滅都市” の開発事例Cocos2d-x 3.0を使ったゲーム “消滅都市” の開発事例
Cocos2d-x 3.0を使ったゲーム “消滅都市” の開発事例
 
DeNAの最新のマスタデータ管理システム Oyakata の全容
DeNAの最新のマスタデータ管理システム Oyakata の全容DeNAの最新のマスタデータ管理システム Oyakata の全容
DeNAの最新のマスタデータ管理システム Oyakata の全容
 
【TECH×GAME COLLEGE#28】形から入ったドメイン駆動設計によるゲーム開発の光と闇
【TECH×GAME COLLEGE#28】形から入ったドメイン駆動設計によるゲーム開発の光と闇【TECH×GAME COLLEGE#28】形から入ったドメイン駆動設計によるゲーム開発の光と闇
【TECH×GAME COLLEGE#28】形から入ったドメイン駆動設計によるゲーム開発の光と闇
 
ソーシャルゲームの為のデータベース設計
ソーシャルゲームの為のデータベース設計ソーシャルゲームの為のデータベース設計
ソーシャルゲームの為のデータベース設計
 
ターン制コマンドバトルにおける強化学習効率化
ターン制コマンドバトルにおける強化学習効率化ターン制コマンドバトルにおける強化学習効率化
ターン制コマンドバトルにおける強化学習効率化
 
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編
 
強化学習を利用した自律型GameAIの取り組み ~高速自動プレイによるステージ設計支援~ #denatechcon
強化学習を利用した自律型GameAIの取り組み ~高速自動プレイによるステージ設計支援~ #denatechcon強化学習を利用した自律型GameAIの取り組み ~高速自動プレイによるステージ設計支援~ #denatechcon
強化学習を利用した自律型GameAIの取り組み ~高速自動プレイによるステージ設計支援~ #denatechcon
 
ゲームエンジニアのためのデータベース設計
ゲームエンジニアのためのデータベース設計ゲームエンジニアのためのデータベース設計
ゲームエンジニアのためのデータベース設計
 
[141004] cedec 2014 참관기 & 강연 리뷰 #1
[141004] cedec 2014 참관기 & 강연 리뷰 #1[141004] cedec 2014 참관기 & 강연 리뷰 #1
[141004] cedec 2014 참관기 & 강연 리뷰 #1
 
DeNA_Techcon2017_DeNAでのチート・脆弱性診断への取り組み
DeNA_Techcon2017_DeNAでのチート・脆弱性診断への取り組みDeNA_Techcon2017_DeNAでのチート・脆弱性診断への取り組み
DeNA_Techcon2017_DeNAでのチート・脆弱性診断への取り組み
 
DeNA内製ゲームエンジンの現状と目指す未来 #denatechcon
DeNA内製ゲームエンジンの現状と目指す未来 #denatechconDeNA内製ゲームエンジンの現状と目指す未来 #denatechcon
DeNA内製ゲームエンジンの現状と目指す未来 #denatechcon
 
GCM#4 アーティストのためのプログラマブルシェーダー講座Part2
GCM#4 アーティストのためのプログラマブルシェーダー講座Part2GCM#4 アーティストのためのプログラマブルシェーダー講座Part2
GCM#4 アーティストのためのプログラマブルシェーダー講座Part2
 

長期運用に耐えるための設計とリファクタリング(DeNA Games Tokyo)

  • 1. Copyright © DeNA Co.,Ltd. All Rights Reserved. 長期運用に耐えるため の設計とリファクタリ ング April 27, 2018 廣橋 俊昭 DeNA Games Tokyo
  • 2. Copyright © DeNA Co.,Ltd. All Rights Reserved. 自己紹介  名前  廣橋 俊昭  生年月日  1990/02/04 (28歳)  趣味  ダーツ  経歴  2013年、DeNA入社  複数のブラウザゲームを渡り歩き開発/運用を経験  2015年、運用タイトルのリードエンジニアに  2017年、DeNA Games Tokyoに合流、 ブラウザゲーム/アプリゲームの運営に携わる 2
  • 3. Copyright © DeNA Co.,Ltd. All Rights Reserved. アジェンダ  運用を見据えての設計観点 ⁃ 正規化の重要性 ⁃ 機能単位でのコード分割  リファクタリングをやる必要性とタイミング 3
  • 4. Copyright © DeNA Co.,Ltd. All Rights Reserved. ゲーム運用でよくあること  イベントの開催 ⁃ マスターデータの追加 • カードデータ (名前, HP, 攻撃力) • BOSSのデータ • 等々 ⁃ 新たな効果/演出の追加 • 単体攻撃だけでなく全体攻撃の追加 • 連続攻撃の追加 • 等々  新機能のリリース ⁃ キャラクターを強化できる素材の追加 • テーブル/コードをまるっと追加する 4
  • 5. Copyright © DeNA Co.,Ltd. All Rights Reserved. ゲーム運用でよくあること  イベントの開催 ⁃ マスターデータの追加 • カードデータ (名前, HP, 攻撃力) • BOSSのデータ • 等々 ⁃ 新たな効果/演出の追加 • 単体攻撃だけでなく全体攻撃の追加 • 連続攻撃の追加 • 等々  新機能のリリース ⁃ キャラクターを強化できる素材の追加 • テーブル/コードをまるっと追加する 5 これらをミスなく運用していきたい
  • 6. Copyright © DeNA Co.,Ltd. All Rights Reserved. アジェンダ  運用を見据えての設計 ⁃ 正規化の重要性 ⁃ 機能単位でのコード分割  リファクタリングをやる必要性とタイミング 6
  • 7. Copyright © DeNA Co.,Ltd. All Rights Reserved. キャラクターの(特殊)効果の実装  とあるイベントにて ⁃ キャラクター3人をデッキに編成して敵を倒す  キャラクターの基礎パラメータは以下の通り ⁃ キャラクターID ⁃ 名前 ⁃ HP ⁃ 攻撃力 ⁃ 防御力  各キャラクターは戦闘中に1回特殊効果を発動できる 7 デッキ 敵キャラ
  • 8. Copyright © DeNA Co.,Ltd. All Rights Reserved. キャラクターの(特殊)効果の実装  各キャラクターの特殊効果は以下の通り 8 稀に自分の攻撃力の3倍ダメージを敵に与える (失敗した場合は1倍) 5連続攻撃を行う 自分の攻撃力の1.5倍のダメージを敵に与える 実装はひとまずおいてデータの持ち方を考えてみる
  • 9. Copyright © DeNA Co.,Ltd. All Rights Reserved. キャラクターの(特殊)効果の実装  各キャラクターの特殊効果は以下の通り 9 稀に自分の攻撃力の3倍ダメージを敵に与える (失敗した場合は1倍) 5連続攻撃を行う 自分の攻撃力の1.5倍のダメージを敵に与える
  • 10. Copyright © DeNA Co.,Ltd. All Rights Reserved. データの持ち方-1  シンプルに考えて1つのテーブルにまとめてみる ⁃ 機能的には実現できそう ⁃ 新たなキャラクターデータを足したらどうなるか • 基礎パラメータの異なる5連続攻撃を行うキャラD 10 ID 名前 HP 攻撃力 防御力 特殊効果ID 特殊効果説明 キャラA 1 A 10 20 5 1 稀に自分の攻撃力の3倍ダメー ジを敵に与える (失敗した場合は1倍) キャラB 2 B 15 10 10 2 5連続攻撃を行う キャラC 3 C 20 15 10 3 自分の攻撃力の1.5倍のダメー ジを敵に与える
  • 11. Copyright © DeNA Co.,Ltd. All Rights Reserved. データの持ち方-1  シンプルに考えて1つのテーブルにまとめてみる ⁃ 機能的には実現できそう ⁃ 新たなキャラクターデータを足したらどうなるか • 基礎パラメータの異なる5連続攻撃を行うキャラD • 説明を重複して何度も登録しないといけない ⁃ 修正したい場合修正箇所が増える ⁃ 運用しているとキャラクターの種類は増えるはず 11 ID 名前 HP 攻撃力 防御力 特殊効果ID 特殊効果説明 キャラA 1 A 10 20 5 1 稀に自分の攻撃力の3倍ダメー ジを敵に与える (失敗した場合は1倍) キャラB 2 B 15 10 10 2 5連続攻撃を行う キャラC 3 C 20 15 10 3 自分の攻撃力の1.5倍のダメー ジを敵に与える キャラD 4 D 25 10 15 2 5連続攻撃を行う
  • 12. Copyright © DeNA Co.,Ltd. All Rights Reserved. 正規化してデータを保持する  正規化を施してみる ⁃ 正規化はざっくりいうと冗長部分をなくすこと ⁃ キャラクターと特殊効果のテーブルをわけてみる 12
  • 13. Copyright © DeNA Co.,Ltd. All Rights Reserved. 正規化してデータを保持する  正規化を施してみる ⁃ 正規化はざっくりいうと冗長部分をなくすこと ⁃ キャラクターと特殊効果のテーブルをわけてみる • キャラクターから効果はIDで参照できる • 説明を何度も書かなくてよくなる 13 ID 名前 H P 攻撃力 防御力 特殊効果ID キャラA 1 A 10 20 5 1 キャラB 2 B 15 10 10 2 キャラC 3 C 20 15 10 3 キャラD 4 D 25 10 15 2 特殊効果ID 特殊効果説明 1 稀に自分の攻撃力の3倍ダメー ジを敵に与える (失敗した場合は1倍) 2 5連続攻撃を行う 3 自分の攻撃力の1.5倍のダメー ジを敵に与える
  • 14. Copyright © DeNA Co.,Ltd. All Rights Reserved. 正規化は大事  テーブル設計で正規化はよくあるテクニックだが、長期運用には欠かせ ない ⁃ 重複はマスターデータ作成/修正コストが高い • 修正範囲が広い • 変更を加える場合、修正漏れが発生する可能性がある 14
  • 15. Copyright © DeNA Co.,Ltd. All Rights Reserved. アジェンダ  運用を見据えての設計 ⁃ 正規化の重要性 ⁃ 機能単位でのコード分割  リファクタリングをやる必要性とタイミング 15
  • 16. Copyright © DeNA Co.,Ltd. All Rights Reserved. キャラクターの(特殊)効果の実装  各キャラクターの特殊効果は以下の通り 16 稀に自分の攻撃力の3倍ダメージを敵に与える (失敗した場合は1倍) 5連続攻撃を行う 自分の攻撃力の1.5倍のダメージを敵に与える 再掲 今度は実装側を考えてみる
  • 17. Copyright © DeNA Co.,Ltd. All Rights Reserved. 実装の大まかな流れ 1. キャラクターの情報を取得する 2. キャラクターの特殊効果を引っ張る 3. 敵キャラクターの情報を取得する 4. 特殊効果とキャラクター情報からダメージ値を計算 5. ボスのHPからダメージ値を引く 17 sub skill_execute( my $character_id, my $boss_id) { my $character = get_character_by_id($character_id); my $boss = get_boss_by_id($boss_id); my $skill = get_skill_by_id($character->get_skill_id()); my $damage = $skill->calc_damage($character); $boss->set_hp($boss->get_hp() - $damage); return; }
  • 18. Copyright © DeNA Co.,Ltd. All Rights Reserved. 実装の大まかな流れ 1. キャラクターの情報を取得する 2. キャラクターの特殊効果を引っ張る 3. 敵キャラクターの情報を取得する 4. 特殊効果とキャラクター情報からダメージ値を計算 5. ボスのHPからダメージ値を引く 18 sub skill_execute( my $character_id, my $boss_id) { my $character = get_character_by_id($character_id); my $boss = get_boss_by_id($boss_id); my $skill = get_skill_by_id($character->get_skill_id()); my $damage = $skill->calc_damage($character); $boss->set_hp($boss->get_hp() - $damage); return; }
  • 19. Copyright © DeNA Co.,Ltd. All Rights Reserved. 特殊効果実装 – その1  例によってシンプルに実装してみる ⁃ この分量だとそこまで問題ない かもしれない ⁃ しかし運用が続き、たくさんの 効果が追加されたら・・・ • 10連続攻撃 • 1/2で2倍攻撃 • 1.8倍攻撃 • etc 19 sub calc_damage (my $character) { my $self = shift; my $atk = $character->get_atk(); if ($self->get_id() == 1) { # 1/10で3倍攻撃 if (rand() % 10 == 0) { return $atk * 3; } else { return $atk; } } elsif (($self->get_id() == 2) { # 今は5倍攻撃と変わらない return $atk * 5; } elsif (($self->get_id() == 3)) { return $atk * 1.5; } else { # error!! } }
  • 20. Copyright © DeNA Co.,Ltd. All Rights Reserved. 特殊効果が増えていくと・・・  ダメージ計算のコードが数百行になる ⁃ コードの流れを追うのが難しくな る ⁃ 既存の特殊効果を修正/追記した い場合、該当箇所を探すのが大変  どんどん効果追加の難易度があがって いく 20 sub calc_damage (my $character) { my $self = shift; my $atk = $character->get_atk(); if ($self->get_id() == 1) { # 特殊効果1 } elsif ($self->get_id() == 2) { # 特殊効果2 } elsif ($self->get_id() == 3) { # 特殊効果3 } elsif ($self->get_id() == 4) { # 特殊効果4 } elsif ($self->get_id() == 5) { # 特殊効果5 } elsif ($self->get_id() == 6) { # 特殊効果6 } elsif ($self->get_id() == 7) { # 特殊効果7 } elsif ($self->get_id() == 8) { # 特殊効果8 } … }
  • 21. Copyright © DeNA Co.,Ltd. All Rights Reserved. 特殊効果実装 – その2  効果ごとにコードを分割してみる ⁃ 特殊効果ID単位でわける • get_skill_by_idで返す$skillをわける • よくある手法はtemplate methodだが、ここでは割愛 ⁃ きになる方はデザインパターンで検索 21 sub skill_execute( my $character_id, my $boss_id) { my $character = get_character_by_id($character_id); my $boss = get_boss_by_id($boss_id); my $skill = get_skill_by_id($character->get_skill_id()); my $damage = $skill->calc_damage($character); $boss->set_hp($boss->get_hp() - $damage); return; }
  • 22. Copyright © DeNA Co.,Ltd. All Rights Reserved. 機能単位でのコード分割  分割されたことで特殊効果ごとの挙動が明確に ⁃ 1効果1ファイルなので追加も容易 • Baseをつくると必要なmethodが明確になる ⁃ エラー時等も対象が絞れて迅速に対応できる 22 sub calc_damage(my $character) { my $self = shift; if (rand() % 10 == 0) { return $character->get_atk() * 3 } else { return $character->get_atk() } } sub calc_damage(my $character) { return $character- >get_atk() * 5; } sub calc_damage(my $character) { return $character- >get_atk() * 1.5 } 特殊効果ID : 1 特殊効果ID : 2 特殊効果ID : 3
  • 23. Copyright © DeNA Co.,Ltd. All Rights Reserved. アジェンダ  運用を見据えての設計 ⁃ 正規化の重要性 ⁃ 機能単位でのコード分割  リファクタリングをやる必要性とタイミング 23
  • 24. Copyright © DeNA Co.,Ltd. All Rights Reserved. リファクタリングの前置き  リファクタリング ⁃ コンピュータプログラミングにおいて、プログラムの外部から見た 動作を変えずにソースコードの内部構造を整理することである • Wikipediaより引用  正規化や機能単位でのコード分割をしていればリファクタリング不要で は? 24
  • 25. Copyright © DeNA Co.,Ltd. All Rights Reserved. リファクタリングの前置き  リファクタリング ⁃ コンピュータプログラミングにおいて、プログラムの外部から見た 動作を変えずにソースコードの内部構造を整理することである • Wikipediaより引用  正規化や機能単位でのコード分割をしていればリファクタリング不要で は? 25 リファクタリングが途中で必要になるケースを紹介
  • 26. Copyright © DeNA Co.,Ltd. All Rights Reserved. キャラクターの(特殊)効果  各キャラクターの特殊効果は以下の通り  実装は正規化済み + 機能単位でコードがわかれているとする 26 稀に自分の攻撃力の3倍ダメージを敵に与える (失敗した場合は1倍) 5連続攻撃を行う 自分の攻撃力の1.5倍のダメージを敵に与える
  • 27. Copyright © DeNA Co.,Ltd. All Rights Reserved. キャラクターの(特殊)効果の仕様追加その1  キャラクターの種類の追加に伴い、以下の仕様を追加 ⁃ 敵キャラを複数体出せるようにする • 5連続攻撃と5倍攻撃は異なるものに  既存で動いている部分に影響なく追加したい心理が働く ⁃ 実装期間が短めだった場合 ⁃ 仕様追加がそこまで大きくリファクタリングするほどでもない場合 ⁃ 等々 27
  • 28. Copyright © DeNA Co.,Ltd. All Rights Reserved. 影響範囲少な目のコード  極端ではあるが、外側をifでくくってしまう ⁃ 敵が一人の場合はほとんど影響なし ⁃ 似たようなコードは量産されてしまう・・・ ⁃ skill_executeの可読性down 28 sub skill_execute( my $character_id, my $boss_ids) { if (scalar @$boss_ids == 1) { # 敵が一人の従来の処理 my $boss_id = $boss_ids->[0]; } else { # 敵が複数人の場合 … my $boss_num = scalar @$boss_ids; # 新規実装 my $damage_list = calc_damage_list($character, $boss_num); … } }
  • 29. Copyright © DeNA Co.,Ltd. All Rights Reserved. キャラクターの(特殊)効果の仕様追加その2  キャラクターの種類の追加に伴い、以下の仕様を追加 ⁃ デッキ内の自分のキャラクターをランダムで回復させたい  今までのHP減算前提のコードの再利用はできなさそう・・・ ⁃ 今回もifで分岐させる 29
  • 30. Copyright © DeNA Co.,Ltd. All Rights Reserved. キャラクターの(特殊)効果の仕様追加その2  キャラクターの種類の追加に伴い、以下の仕様を追加 ⁃ デッキ内の自分のキャラクターをランダムで回復させたい  今までのHP減算前提のコードの再利用はできなさそう・・・ 30 sub skill_execute( my $character_id, my $boss_ids) { my $self = shift; if ($self->get_id() == 回復ID) { # 回復処理 } else { if (scalar @$boss_ids == 1) { # 敵が一人の従来の処理 } else { # 敵が複数人の場合 } } } いつの間にか複雑な条件分岐だらけに・・・
  • 31. Copyright © DeNA Co.,Ltd. All Rights Reserved. なぜこのようなことに・・・  当初のコードは機能ごとに分割していたが、仕様変更に耐えられなかっ た ⁃ 1対象への攻撃前提なので以下は想定外 • 複数敵キャラクターの追加 • 自キャラクターへの効果  回避もできたかもしれない ⁃ 機能リリース時の仕様は1対象への攻撃かもしれないが、複数や回 復を企画メンバーはすでに考えていたかもしれない ⁃ サービスの未来を見据えて企画とエンジニアが話すことも大事 31
  • 32. Copyright © DeNA Co.,Ltd. All Rights Reserved. なぜこのようなことに・・・  当初のコードは機能ごとに分割していたが、仕様変更に耐えられなかっ た ⁃ 1対象への攻撃前提なので以下は想定外 • 複数敵キャラクターの追加 • 自キャラクターへの効果  回避もできたかもしれない ⁃ 機能リリース時の仕様は1対象への攻撃かもしれないが、複数や回 復を企画メンバーはすでに考えていたかもしれない ⁃ サービスの未来を見据えて企画とエンジニアが話すことも大事 32 とはいえ、こうなったら恐れずリファクタリング!!
  • 33. Copyright © DeNA Co.,Ltd. All Rights Reserved. リファクタリングする  基本方針 ⁃ 機能単位で分割する ⁃ 複数のターゲットに効果を与えると考える  skill_executeの中身にリファクタリングを絞り、挙動に変更を与えなけ れば確認範囲を最小限ですむはず 33 sub skill_execute( my $executor_id, my $target_ids) { my $character = get_character_by_id($ executor _id); my $targets = get_targets_by_id($target_ids); my $skill = get_skill_by_id($character->get_skill_id()); $skill->exec_effect($character, $targets); return; } sub exec_effect() targetを選んで稀 に3倍攻撃。 sub exec_effect() targetを5回抽選し て攻撃 sub exec_effect() targetを選んで1.5 倍攻撃 sub exec_effect() targetを選んで回 復
  • 34. Copyright © DeNA Co.,Ltd. All Rights Reserved. まとめ  長期運用で主に意識したい設計観点は以下の2点 ⁃ 極力テーブル構造は正規化する • マスターデータの誤入力を抑える ⁃ 機能単位でコードは分割 • 可読性の担保 • 機能追加の容易さの確保  気をつけて設計してもリファクタリングは必要 ⁃ 企画とエンジニアとの話し合いで回避できることも ⁃ リファクタリングの際も設計観点は変わらない 34