Featured image of post 通知手段を足すたびに、決済ロジックの中のnewを書き換える。生成を工場に移す【Factory Method】

通知手段を足すたびに、決済ロジックの中のnewを書き換える。生成を工場に移す【Factory Method】

コード探偵ロックの事件簿:決済完了時の通知がメール・SMS・Slack・Push と増え、そのたびに OrderService の中で通知クラスを new する分岐を足していた。生成を工場クラスに移し、注文処理は工場に頼むだけにする(Factory Method)。テストではダミーの工場を渡せます。

Featured image of post 他チームのクラスの内部を直接読み、キー名の変更でAPIが全滅。代理人越しに触る【Proxy】

他チームのクラスの内部を直接読み、キー名の変更でAPIが全滅。代理人越しに触る【Proxy】

コード探偵ロックの事件簿:別チームのクラスの内部ハッシュを直接読んでいたため、キー名が変わっただけでレポート API が全滅した。代理人を挟み、アクセスをそこだけに通す(Proxy)。

Featured image of post トークンの期限を変えただけで、全APIが認証エラーで落ちた。チェックを鎖に分ける【Chain of Responsibility】

トークンの期限を変えただけで、全APIが認証エラーで落ちた。チェックを鎖に分ける【Chain of Responsibility】

コード探偵ロックの事件簿:IP 制限・認証・権限チェックを1つのメソッドの if に詰め込み、トークンの期限を変えただけで全 API が落ちた。チェックごとに分けて鎖でつなぐ(Chain of Responsibility)。

Featured image of post 失敗してDBは戻せても、決済APIの課金は取り消せない。操作に取り消しを持たせる【Command】

失敗してDBは戻せても、決済APIの課金は取り消せない。操作に取り消しを持たせる【Command】

コード探偵ロックの事件簿:注文処理が途中で失敗したとき、DB はロールバックできても外部の決済 API の課金は戻らず、お金だけ受け取って注文はキャンセルされる。操作を実行と取り消しの対を持つオブジェクトにし、失敗したら逆順に取り消す(Command)。

Featured image of post 1クラスが全サブシステムを直接呼び、仕様変更1つでエラーが連鎖。窓口を立てる【Facade】

1クラスが全サブシステムを直接呼び、仕様変更1つでエラーが連鎖。窓口を立てる【Facade】

コード探偵ロックの事件簿:配送ロボットの受注システムで、1つのクラスが決済・在庫・配送・通知のサブシステムを直接操作し、仕様を1つ変えたらエラーが連鎖した。サブシステムの前に窓口のクラスを1つ置き、呼び出し側はそこだけを使う(Facade)。

Featured image of post 引数10個の関数が5階層、IDの順番を取り違えた。引数を1つにまとめる【Parameter Object】

引数10個の関数が5階層、IDの順番を取り違えた。引数を1つにまとめる【Parameter Object】

コード探偵ロックの事件簿:引数10個の関数が5階層続き、途中で user_id と shop_id の順番が入れ替わった。どちらも数値でエラーにならない。一緒に渡る引数を1つにまとめる(Parameter Object)。

Featured image of post 夜間バッチを並列にしたら、テストの処理が本番DBを書き換えた。接続を外から渡す【Singleton/DI】

夜間バッチを並列にしたら、テストの処理が本番DBを書き換えた。接続を外から渡す【Singleton/DI】

コード探偵ロックの事件簿:どこからでも呼べる Singleton の DB 接続を使い回し、並列の夜間バッチでテストのつもりの処理が本番 DB を書き換えた。接続をコンストラクタで受け取る(Dependency Injection)。

Featured image of post JSONで年齢が文字列になり、電話番号の先頭の0が消える。値を専用のクラスで包む【Value Object】

JSONで年齢が文字列になり、電話番号の先頭の0が消える。値を専用のクラスで包む【Value Object】

コード探偵ロックの事件簿:年齢や電話番号を Perl の素のスカラーで持ち、ログ出力で文字列結合しただけで JSON の型が変わる。年齢が文字列になり、電話番号の先頭の0が消えた。値を専用のクラスに包み、出力の形もそこで決める(Value Object)。

Featured image of post 0〜3の数字で持つ注文状態、発送済みにキャンセルが通った。状態をクラスにする【State】

0〜3の数字で持つ注文状態、発送済みにキャンセルが通った。状態をクラスにする【State】

コード探偵ロックの事件簿:注文の状態を 0・1・2・3 の数字で持ち、支払い・発送・キャンセルの処理がすべて if-elsif で状態を確かめる。条件が絡み、発送済みの注文にキャンセルが通った。状態ごとのクラスに振る舞いを任せる(State)。

Featured image of post ポイント付与の機能を継承で組み合わせたら、機能3つで8クラス。外から重ねて足す【Decorator】

ポイント付与の機能を継承で組み合わせたら、機能3つで8クラス。外から重ねて足す【Decorator】

コード探偵ロックの事件簿:ポイント付与にログ・メール通知・2倍キャンペーンを継承で足していったら、機能3つでクラスが8個、4つ目で16個に増える。本体を同じインターフェースの包みで重ね、機能を外から足す(Decorator)。

Featured image of post 在庫更新を1か所直すと、メール通知やダッシュボードが止まる。通知で受け手を分ける【Observer】

在庫更新を1か所直すと、メール通知やダッシュボードが止まる。通知で受け手を分ける【Observer】

コード探偵ロックの事件簿:在庫を更新する1つのメソッドにメール通知・ログ・ダッシュボード更新が詰め込まれ、1か所直すと別の機能が止まる。在庫の変化を通知にして、受け手がそれぞれ反応する形に分ける(Observer)。

Featured image of post CSV出力のバグを直すと、コピペした隣にも同じ修正が要る。手順を親にまとめる【Template Method】

CSV出力のバグを直すと、コピペした隣にも同じ修正が要る。手順を親にまとめる【Template Method】

コード探偵ロックの事件簿:2つの CSV エクスポートが、データ取得・ヘッダー生成・行の整形・出力の結合という同じ手順をコピペで持ち、バグ修正も二重になる。手順の骨格を親クラスに置き、違う部分だけをサブクラスに書く(Template Method)。

Featured image of post 形式を足すたび5000行のif-elsifに書き足す。形式ごとのクラスに分ける【Strategy】

形式を足すたび5000行のif-elsifに書き足す。形式ごとのクラスに分ける【Strategy】

コード探偵ロックの事件簿:5000行のメソッドが CSV・JSON・XML の出力をすべて if-elsif で抱え、YAML を足すにもそこへ書き足すしかない。形式ごとの処理をクラスに分け、外から差し替える(Strategy)。Perl と Moo で実装します。