Featured image of post 注文ステータスが変わるたびに全ステーションへ手で通知している。登録した相手へ自動で伝える【Observer】

注文ステータスが変わるたびに全ステーションへ手で通知している。登録した相手へ自動で伝える【Observer】

注文ステータスの変更を焼き場・揚げ場・ドリンクバーへ1つずつ手で通知していて、通知先を足すたびに通知元を直す羽目になる。登録した相手へ自動で伝える形にする(Observer)。Perl と Moo で実装します。

Featured image of post 空席のはずの席が「会計待ち」になる。bool フラグの組み合わせをやめて状態を部品にする【State】

空席のはずの席が「会計待ち」になる。bool フラグの組み合わせをやめて状態を部品にする【State】

is_occupied や is_billing のような真偽値フラグが増え、ありえない組み合わせの席ができる。状態ごとの部品に次の遷移を持たせ、矛盾した状態を作れなくする(State)。Perl と Moo で実装します。

Featured image of post あらゆる処理を1つのクラスが抱え込み、直すたびに全体が揺れる。責務ごとに分けて委譲する【God Class】

あらゆる処理を1つのクラスが抱え込み、直すたびに全体が揺れる。責務ごとに分けて委譲する【God Class】

税計算も在庫確認も通知も1つのクラスが引き受けていて、どの変更もそこへ流れ込む。責務ごとの専用クラスに切り出し、元のクラスは委譲だけをする薄い層にする(God Class)。シリーズ最終話。Perl と Moo で実装します。

連載 コードバーテンダー (第12話 / 全12話)
Featured image of post 消費税率を直すだけで15ファイルを開く羽目になった。税率を1つのクラスに集める【Shotgun Surgery】

消費税率を直すだけで15ファイルを開く羽目になった。税率を1つのクラスに集める【Shotgun Surgery】

0.08 が15か所に散らばっていて、1か所直すと他とのずれでテストが壊れ、洗い出しに2日かかった。TaxPolicy に税率と計算を集め、変更を1か所に閉じ込める(Shotgun Surgery)。Perl と Moo で実装します。

Featured image of post 実装が1つしかない抽象クラスと、一度も使わないオプションが残っている。将来のための設計を消す【Speculative Generality】

実装が1つしかない抽象クラスと、一度も使わないオプションが残っている。将来のための設計を消す【Speculative Generality】

「将来使うかも」で作った基底クラスやロールが、今は1つの実装のためだけに読まれ続けている。YAGNI に従って、使われていない抽象化を取り除く(Speculative Generality)。Perl と Moo で実装します。

Featured image of post テストのたびにモックを登録してリセットする。ServiceLocator をやめ、依存をコンストラクタで受け取る【Service Locator】

テストのたびにモックを登録してリセットする。ServiceLocator をやめ、依存をコンストラクタで受け取る【Service Locator】

Notifier の中で ServiceLocator に問い合わせるため、何が必要かコンストラクタから分からず、テストの順序で結果も変わる。依存を required な属性で宣言する(Service Locator)。Perl と Moo で実装します。

Featured image of post 注文から顧客、住所、都市名まで -> でたどる。Customer を直したら周りも全部壊れる【Law of Demeter】

注文から顧客、住所、都市名まで -> でたどる。Customer を直したら周りも全部壊れる【Law of Demeter】

$order->customer->address->city のように奥の構造まで直接たどると、中間のクラスを変えたとき呼び出し側まで壊れる。handles で直接の隣人にだけ委譲する(Law of Demeter)。Perl と Moo で実装します。

Featured image of post init() を先に呼ぶ手順を飛ばされて、本番が落ちた。呼ぶ順番をコードの型で縛る【Temporal Coupling】

init() を先に呼ぶ手順を飛ばされて、本番が落ちた。呼ぶ順番をコードの型で縛る【Temporal Coupling】

init() や setup() を先に呼ばないと動かない作りは、手順書を読み飛ばした瞬間に本番を落とす。段階ごとに別の型を返し、順番を間違えると呼べない形にする(Temporal Coupling)。Perl と Moo で実装します。

Featured image of post メールアドレス欄に電話番号が入り、金額は文字列のまま足されて桁がずれる。値を専用の型にする【Primitive Obsession】

メールアドレス欄に電話番号が入り、金額は文字列のまま足されて桁がずれる。値を専用の型にする【Primitive Obsession】

メールも電話番号も金額も Str と Int で持つと、取り違えてもエラーにならず、検証も呼び出し口ごとに散らばる。値に名前と制約を持たせた Value Object にする(Primitive Obsession)。Perl と Moo で実装します。

Featured image of post OrderManager を通す決まりで、メソッドが全部ただの転送になった。間の一段を外して直接呼ぶ【Middle Man】

OrderManager を通す決まりで、メソッドが全部ただの転送になった。間の一段を外して直接呼ぶ【Middle Man】

全メソッドを OrderService へ転送するだけの Manager クラスは、読む人に一段余計に掘らせ、変更も二重に波及する。取り除いて直接呼び、固有の処理だけを残す(Middle Man)。Perl と Moo で実装します。

Featured image of post 継承した save と delete を die で潰し、update は空にした。継承をやめて必要な性質だけ受け取る【Refused Bequest】

継承した save と delete を die で潰し、update は空にした。継承をやめて必要な性質だけ受け取る【Refused Bequest】

読み取り専用のクラスが親の save や delete を拒否していて、呼ぶまで壊れていることに気づけない。extends を Role の合成や handles の委譲に置き換える(Refused Bequest)。Perl と Moo で実装します。

Featured image of post 前任者の3年前のコードが怖くて消せない。呼び出し元を確かめて、段階的に削除する【Dead Code】

前任者の3年前のコードが怖くて消せない。呼び出し元を確かめて、段階的に削除する【Dead Code】

「念のため」残した使われないメソッドとコメントアウトが、生きたコードの変更まで止めている。呼び出し元の追跡、deprecation の警告、削除の3手順で片付ける(Dead Code)。Perl と Moo で実装します。

Featured image of post レポート生成メソッドが $order-> だらけで、Order の変更のたびに壊れる。処理をデータのある側へ移す【Feature Envy】

レポート生成メソッドが $order-> だらけで、Order の変更のたびに壊れる。処理をデータのある側へ移す【Feature Envy】

ReportGenerator が Order のデータを取りに行ってばかりで、Order の属性を変えるたびにレポートまで壊れる。メソッドをデータのあるクラスへ移し(Move Method)、必要なら handles で委譲する。Perl と Moo で実装します。