設計 / アーキテクチャ
変更しやすさを構造で買う
設計の良し悪しは「動くかどうか」では測れない。測れるのは、仕様変更が来たときに何ファイル触るか。凝集度・結合度・依存の向きは、その「触る範囲」を制御するための語彙であり、SOLID もレイヤードもその適用例にすぎない。
読み終わると、これに答えられるようになります
- ?依存性逆転は具体的に何を逆転させているのか
- ?レイヤードアーキテクチャで DB のカラム名が画面まで漏れるのはなぜ問題なのか
- ?「共通化」がかえって変更を重くするのはどういうときか
凝集度と結合度 — 変更したとき何ファイル触るか
良い設計は「動くか」では測れない。測れるのは、仕様変更が来たときの影響範囲。それを制御する2つの語彙。
「共通化」したユーティリティに分岐が増え続け、1箇所の修正が3画面を壊した
SOLID — 5つの原則が守ろうとしている1つのこと
暗記する対象ではなく、判断の道具として使う。それぞれが「どういう変更に備えているか」から理解する。
決済手段を1つ追加するのに、既存の分岐を12箇所書き換えることになった
レイヤードアーキテクチャ — 依存の向きを一方向に揃える
層に分けること自体に価値はない。価値があるのは、依存が一方向であることと、業務ロジックが技術から独立すること。
DB のカラム名を変えたら、画面のテンプレートが壊れた
ドメインモデリング — 業務の言葉をコードの形にする
テーブル設計から始めると、業務ルールの置き場所がなくなる。何が概念で、何が制約かを見つける作業。
金額を number で持ち回り、税込と税抜が混ざった状態で合計されていた
モノリスとマイクロサービス — 分けた境界の数だけ、失敗の仕方が増える
速く開発するために8つのサービスに分けたら、項目を1つ足すのに4つのサービスを順番にデプロイするようになった。分けることで得られるのは独立性で、境界を間違えると独立性は得られず、費用だけが残る。
6人のチームが8つのサービスに分けたら、項目を1つ足すのに4サービスの順番デプロイが要り、ポイントの付与漏れが続いた
時刻とタイムゾーン — 保存した「0時」は、どこの0時か
毎日0時から9時までの注文が、前日の売上に計上されていた。時刻には「瞬間」「壁の時計の時刻」「日付」の3種類があり、混ぜた瞬間に9時間ずれる。
毎日0時から9時までの注文が前日の売上に入り、月末の締めの数字が経理の集計と合わなかった
I/O と並行処理 — 待っている間に、何をするか
サムネイル生成を1本足しただけで、無関係な API まで全部遅くなった。待ち時間の処理と、計算そのものは、同じ場所に置いてはいけない。
サムネイル生成を API に足したら、DB もネットワークも暇なのに、無関係な API まで応答が4秒になった
文字コードと正規化 — 同じに見える文字が、一致しない
「ガ」で検索しても出てこない。目で見ると同じ文字。バイト列は違う。長さも、比較も、見た目とはずれる。
Mac から登録された「ガ」が、Windows から検索しても一致しなかった
状態をどこに置くか — URL に無いものは、共有できない
絞り込んだ一覧を同僚に送ったら、何も絞られていない画面が開いた。状態をどこに置くかは、何ができて何ができないかを決める。
絞り込んだ一覧の URL を共有したら、相手の画面では何も絞られていなかった
トレードオフの決め方 — 正解を探すのをやめて、払うものを選ぶ
3 年前に選んだ DB の理由を、誰も覚えていなかった。得るものは覚えていても、払うものは書いていなかった。設計判断に正解は無く、あるのは「この制約なら、これを払う」という選択だけ。
3 年前に「スケールするから」と選んだ DB の理由を誰も覚えておらず、集計のたびに全件を読み、同じ議論を 2 週間繰り返した
コンポーネントをどう分けるか — 見た目が同じでも、変わる理由が違えば別の部品
共通の商品カードは、1 年で引数が 23 個になった。ある画面の修正で、別の画面のカードが崩れた。似ているものをまとめた部品は、変わる理由の数だけ分岐を抱える。
共通の商品カードが 1 年で引数 23 個になり、セール画面の修正でお気に入り画面のカードが崩れた