@nqounetです。
「Perlでローグライク通知システムを作ろう」シリーズの第3回です。前回は、ログと実績が混在した問題のあるコードを見ました。今回は、通知を受け取るクラスを独立させて、責務を分離します。
前回の振り返り
前回は、実績システムを追加しようとしたときに以下の問題が発生しました。
- メソッドの肥大化
- 機能追加のたびに既存コード修正が必要
- テストが困難
解決策:通知を受け取るクラスを分離する
問題を解決するために、以下のアプローチを取ります。
- ログ出力を専門に行う
LogObserverクラスを作成 - 実績管理を専門に行う
AchievementObserverクラスを作成 - 各クラスに「通知を受け取る」メソッド(
update)を持たせる
LogObserverクラスを作成する
まずは、ログ出力専用のクラスを作成します。
| |
実行結果は以下のようになります。
| |
LogObserverクラスは「ログを出力する」という1つの責務だけを持っています。
AchievementObserverクラスを作成する
次に、実績管理専用のクラスを作成します。
| |
実行結果は以下のようになります。
| |
AchievementObserverクラスは「実績を管理する」という1つの責務だけを持っています。
両方のObserverを組み合わせる
2つのObserverを組み合わせて、ゲームイベントを両方に通知してみましょう。
| |
実行結果は以下のようになります。
| |
ログ出力と実績管理が、それぞれ独立したクラスで行われています。
改善された点
クラスを分離したことで、以下の点が改善されました。
| 問題 | 改善前 | 改善後 |
|---|---|---|
| メソッドの肥大化 | 1つのメソッドに複数の処理 | 各Observerが1つの責務を持つ |
| 機能追加 | 既存メソッドを修正 | 新しいObserverクラスを追加 |
| テスト | 分離してテスト困難 | 各Observerを個別にテスト可能 |
共通点:updateメソッド
LogObserverとAchievementObserverには共通点があります。
- 両方とも
updateという名前のメソッドを持つ updateメソッドはGameEventを受け取る- 受け取ったイベントに対して適切な処理を行う
この「updateメソッドを持つ」という約束を、次回は正式なルールとして定義します。
今回のまとめ
今回は、通知を受け取るクラスを分離しました。
LogObserver: ログ出力を担当AchievementObserver: 実績管理を担当- 両クラスとも
updateメソッドで通知を受け取る
完成コード
今回の完成コードは以下の通りです。
| |
次回予告
次回は「通知を受け取る約束を決めよう」です。Moo::Roleのrequiresを使って、「全てのObserverはupdateメソッドを持つ」という約束を正式に定義します。
