対話的なメニューから冒険・セーブ・ロード・セーブデータ一覧・終了を選べるCLI版のRPGに、第8回までの機能を統合します。3つのエリアとオートセーブ付きで、完成コード全体を確認します。
3つのセーブスロットを使い分けられるようにします。スロットを選んでセーブ・ロードし、上書きと空きスロットの表示を足して、複数スロットの管理を動かして確かめます。
PlayerSnapshot の属性を is => ro にしておくと、外から値を書き換えようとしても失敗します。改ざんを試すコードで確かめ、rw だったらどうなるかも見て、不変にしておく理由をカプセル化の面から整理します。
GameManager に auto_save フラグと自動セーブのメソッドを足し、ボス戦前とエリア移動のタイミングで自動的にセーブします。オートセーブの ON/OFF 切り替えも入れます。
GameManager クラスで複数のスナップショットを配列に持ち、save_game・load_game・list_saves でセーブスロットとして出し入れします。
スナップショットから Player の状態を戻す restore_from_snapshot メソッドを書きます。セーブしてからダメージを受け、ロードして状態が戻る流れを動かして確認します。
PlayerSnapshot クラスを作り、HP・所持金・位置などの状態を1つのオブジェクトにまとめて保存します。属性を is => ro にして、作った後は中身を書き換えられないスナップショットにして、動作を確かめます。
ゲームオーバーで最初からやり直しになるRPGに、保存を足します。まず変数へ値をコピーする方法を試し、参照コピーになって保存した状態まで書き換わる問題と、内部状態が外に漏れる問題を確かめます。
Perl と Moo で、HP・所持金・位置を属性に持つ Player クラスを作ります。移動と戦闘のメソッドを書き、ゲームループで動かして、次回以降にセーブ機能を足していく土台のRPGにします。
月次レポートを作る ReportGenerator が、週次を足した if/else の肥大化を経て、継承とオーバーライドで組み直され、Factory Method パターンと名前が付くまでの全10回の目次です。第1回から順に読む連載で、どの回で何が変わるかを一覧できます。
if/else をやめて継承とオーバーライドで組んできた設計に、Factory Method パターンと名前を付けます。ReportGenerator と create_report が Creator と factoryMethod のどれに当たるかを対応づけ、委譲で切り替える Strategy パターンとの違いを表にします。
ここまで9回分の変更を1つにまとめた完成コードを通して読みます。4種類のレポートを生成して実行結果を確かめ、各回で何を足したかを表で振り返り、年次レポートや PDF 出力を足すならどこに手を入れるかを考えます。
QuarterlyReport と QuarterlyReportGenerator を新しく追加するだけで、四半期レポートが生成できるようになります。直したクラスがゼロであることを確認し、第2回の if/else 版では何を直す必要があったかと並べて比べます。
新しいメンバーが書いたジェネレーターが、ハッシュリファレンスを返してしまった場面から始めます。create_validated_report で戻り値が ReportRole を持つかを does で検査し、違反したらその場で die して原因に気づけるようにします。
月次・週次・日次のどれでも同じ保存処理が要るので、generate_and_save を基底クラスに1つだけ置きます。処理の流れは基底クラスが決め、サブクラスは何を作るかだけを書く分担になり、保存処理を直すのも1か所で済みます。