Moo::Role で ResponseRole を作り、render メソッドを必須にします。with で Response クラスに適用し、render を実装し忘れたクラスは読み込み時に失敗する様子を確かめて、レスポンスの共通ルールを保証します。
Scenario 基底クラスを作り、SuccessScenario と NotFoundScenario に create_response を実装させます。継承でシナリオごとにクラスを分けると、新しいシナリオを足しても既存のクラスを書き換えずに済むことを確かめます。
偽APIに404などのエラーレスポンスを足すと、create_response メソッドに if/else が積み重なります。既存コードを書き換えないと新しいシナリオを足せない、テストが1つに固まる、という問題を実際のコードで確かめます。
バックエンドAPIが未完成でも、フロントエンドの検証は進めたい。Perl と Moo で、ステータス・コンテンツタイプ・ボディを持つ Response クラスと、成功レスポンスを返す MockApi クラスを作ります。
同じモンスターを大量に作るときの new() の限界から始め、MooX::Clone の clone()、浅いコピーの罠、Storable::dclone() の深いコピーを経て、GoF の Prototype パターンにたどり着くまでの全6回の目次です。各回は前の回の続きなので、第1回から順に読む連載です。
第1回から作ってきた「既存オブジェクトを複製して新しいオブジェクトを作る」やり方に、GoF の生成パターン Prototype という名前を付けます。構成要素を Monster と Weapon に対応させ、Factory Method との違いを表とコードで比べ、Moo::Role で明示的に表す方法まで扱います。
Storable::dclone() で独自の clone() メソッドを書き、武器を含むドラゴンを丸ごと複製します。dragon2 の武器を変えても dragon1 は変わらず、武器オブジェクトのアドレスも別になることを確認します。MooX::Clone との使い分けとして、単純な属性だけなら MooX::Clone、ネストがあれば dclone と整理します。
武器 Weapon を持つドラゴンを MooX::Clone の clone() で複製し、dragon2 の武器の威力を20に変えると、元の dragon の威力も20になります。clone() は参照だけをコピーするので2体が同じ Weapon を共有している、という浅いコピーの仕組みを、出力と参照の比較で確かめます。
clone() で作ったモンスターは元と独立しているので、コピー後に color を変えても元の緑スライムは変わりません。map と色の配列で緑・赤・青・金・銀の5色を一気に作り、HP などを少し上げた強化版まで、ベースを複製して一部だけ変える形で作ります。
MooX::Clone を use するだけで Moo クラスに clone() が加わります。ベースのスライムを1体作り、map { $base_slime->clone } 1..10 で10体にします。HP を10から15に変える修正もベース1箇所で済むことを確かめ、内部では属性値を取り出して new し直していることも見ます。
RPG のモンスター管理で Monster クラスを Moo で定義し、スライムを10体作ると同じ属性指定を10回書くことになります。冗長になる、修正が10箇所に及ぶ、タイポに気づきにくい、100体では破綻するという4つの問題と、ループにしても色違いや既存個体からの複製は解けない理由を確かめます。
Perl と Moo で作るローグライクの攻撃処理に、ログ・実績・サウンド・統計を足すたびに if/else が膨らむ困りごとを、通知先のクラス分けと登録の仕組みで解いて、最後に Observer パターンと名前を付ける全10回の連載の目次です。どこから読むか、困りごとからも選べます。
全9回で作ってきた設計が Observer パターンだったと明かし、Subject・Observer などの役割を作ったクラスと対応づけます。似た Pub/Sub パターンや Mediator パターンとの違いも整理します。
これまで作った Emitter と4種類の Observer を組み合わせて、対話的な CLI のダンジョン探索ゲームに仕上げます。1回の行動で、ログ・実績・サウンド・統計が連動して動く様子を実行例で確かめます。
敵の撃破数とダメージの統計を記録する StatisticsObserver を足します。ゲーム本体も Emitter も既存の Observer も変更せずに機能を足せることを通して、開放閉鎖原則(OCP)を体感します。