Featured image of post 商品カテゴリが増えるたびにサブクラスを足し、次は20個追加。種類をデータで表す【Type Object】

商品カテゴリが増えるたびにサブクラスを足し、次は20個追加。種類をデータで表す【Type Object】

コード探偵ロックの事件簿:商品カテゴリごとにサブクラスを作り、13個になったところへ来期は20カテゴリの追加が決まった。中身は値が違うだけで構造は同じ。カテゴリをクラスではなくデータ(YAML)で表し、違う振る舞いだけを差し込む(Type Object)。

Featured image of post 閾値を変えたら12か所のifのうち3か所を直し漏れた。条件を1つの部品にまとめる【Specification】

閾値を変えたら12か所のifのうち3か所を直し漏れた。条件を1つの部品にまとめる【Specification】

コード探偵ロックの事件簿:与信審査の閾値を700から650に変えたとき、12か所に散らばった if のうち3か所を直し漏れ、正規の顧客がローンを組めなくなった。条件をクラスにまとめ、AND・OR・NOT で組み合わせる(Specification)。

Featured image of post プラグインを1つ足すたびにコンストラクタとテストを全部直す。棚に登録する形にする【Registry】

プラグインを1つ足すたびにコンストラクタとテストを全部直す。棚に登録する形にする【Registry】

コード探偵ロックの事件簿:依存をすべてコンストラクタで渡すようにしたら、通知プラグインを1つ足すたびにコンストラクタの引数とテストを全部直すことになった。プラグインはレジストリに登録し、そのレジストリだけを注入する(Registry と DI の併用)。

Featured image of post ローカルでは通るテストが、CIでは全部赤。クラスの中のnewを外から渡す【Dependency Injection】

ローカルでは通るテストが、CIでは全部赤。クラスの中のnewを外から渡す【Dependency Injection】

コード探偵ロックの事件簿:CI を入れたら、ローカルでは通るテストが全部落ちた。原因はクラスの中で CSV の読み込みや SMTP 送信の部品を直接 new していたこと。部品はコンストラクタで受け取り、組み立ては1か所にまとめる(Dependency Injection)。

Featured image of post テストコードは触っていないのに、夜間テストが毎日数件ずつ赤くなる。依存を明示する【Service Locator】

テストコードは触っていないのに、夜間テストが毎日数件ずつ赤くなる。依存を明示する【Service Locator】

コード探偵ロックの事件簿:共通のサービスをグローバルなレジストリから取り出していたため、テストどうしが状態を共有し、実行順によって18件中4〜7件が落ちる。必要な依存はコンストラクタで受け取り、足りなければ生成時に気づけるようにする(Service Locator の撤去)。

Featured image of post 'actve'、1文字のタイポで深夜に2時間。文字列と数値に名前と型を付ける【Magic Numbers / Strings】

'actve'、1文字のタイポで深夜に2時間。文字列と数値に名前と型を付ける【Magic Numbers / Strings】

コード探偵ロックの事件簿:決済のステータス更新が反映されない原因は、文字列 'actve' の1文字抜けだった。数値や文字列を直に書かず、use constant で名前を付け、Type::Tiny の Enum でコンストラクタ時に弾く(Magic Numbers / Strings)。

Featured image of post 「消すと壊れるかも」で残したコードが積もり、誰も触れない。根拠を持って消す【Dead Code / Lava Flow】

「消すと壊れるかも」で残したコードが積もり、誰も触れない。根拠を持って消す【Dead Code / Lava Flow】

コード探偵ロックの事件簿:コメントアウトの旧ロジックや if (0) が「消すと壊れるかも」で残り続ける。カバレッジを測って根拠を持ち、段階的に消す(Dead Code / Lava Flow)。

Featured image of post 継承したのに使えないメソッドをdieで潰している。継承をやめて必要な能力だけ持つ【Refused Bequest】

継承したのに使えないメソッドをdieで潰している。継承をやめて必要な能力だけ持つ【Refused Bequest】

コード探偵ロックの事件簿:基底クラスを継承した CreditNote が、合わない validate を die で潰していた。継承をやめ、必要な能力だけをロールと委譲で持たせる(Composition over Inheritance)。

Featured image of post メソッドチェーンを委譲で潰したら、転送するだけのクラスができた。仲介役を外す【Middle Man】

メソッドチェーンを委譲で潰したら、転送するだけのクラスができた。仲介役を外す【Middle Man】

コード探偵ロックの事件簿:メソッドチェーンをなくすために委譲を全クラスへ広げたら、中身のない転送メソッドだけを並べたクラスが生まれた。意味のない仲介役を外し、委譲する場所と直接呼ぶ場所を見直す(Remove Middle Man)。

Featured image of post 住所のカラム名を変えたら、触っていない配送料と税の計算が落ちた。鎖を断つ【Law of Demeter】

住所のカラム名を変えたら、触っていない配送料と税の計算が落ちた。鎖を断つ【Law of Demeter】

コード探偵ロックの事件簿:住所のカラム名を変えただけで、メソッドチェーンでたどっていた配送料・税・請求書の計算が同時に例外で落ちた。中間のオブジェクトをたどらず、Moo の handles で直接聞ける形にする(Law of Demeter)。

Featured image of post 機能を足すたび無関係なテストが壊れる。他クラスのデータを触るメソッドを持ち主へ【Feature Envy】

機能を足すたび無関係なテストが壊れる。他クラスのデータを触るメソッドを持ち主へ【Feature Envy】

コード探偵ロックの事件簿:レポート生成のメソッドが他クラスのゲッターばかり呼び、機能を足すたびにテストが壊れる。メソッドをデータの持ち主へ移す(Feature Envy の解消)。

Featured image of post 注文はあるのに在庫が減っていない。毎週手で直す不整合を、変更を一括で確定して防ぐ【Unit of Work】

注文はあるのに在庫が減っていない。毎週手で直す不整合を、変更を一括で確定して防ぐ【Unit of Work】

コード探偵ロックの事件簿:注文・在庫・支払いを別々に書き込んでいたため、途中で失敗すると注文だけが残り、13週続けて手で直していた。変更をすべて1つのオブジェクトに登録し、commit でまとめて反映、失敗したら全部取り消す(Unit of Work)。

Featured image of post 受注チェックを直すと集計テストが落ち、集計を直すと受注が落ちる。読み書きを分ける【CQRS】

受注チェックを直すと集計テストが落ち、集計を直すと受注が落ちる。読み書きを分ける【CQRS】

コード探偵ロックの事件簿:受注の書き込みとダッシュボードの集計が1つのリポジトリに同居し、バリデーションを直すと集計のテストが落ち、集計を直すと受注が落ちる。書き込み(Command)と読み取り(Query)を別のクラスに分ける(CQRS)。

Featured image of post 監査で30日前の在庫を聞かれても、上書きした在庫数からは出せない。出来事を残す【Event Sourcing】

監査で30日前の在庫を聞かれても、上書きした在庫数からは出せない。出来事を残す【Event Sourcing】

コード探偵ロックの事件簿:在庫数を直接上書きしていたため、監査部門から過去30日間の入出荷の根拠を求められても、今の数しか分からない。入荷・出荷を出来事として追記し、在庫数は出来事を再生して求める(Event Sourcing)。任意の時点の在庫も計算できます。