- 判断は「意図」ではなく「制約」として残す
- 名前は、最も軽い制約である
- 型は、判断を強制する
- 境界は、判断の置き場所を固定する
- 判断を残しすぎないという判断
- 制約の「強さ」を意識して設計する
- 設計とは、判断の履歴を残すこと
- まとめ
ここまでの章で、設計とは判断を閉じ込める行為であり、 その判断は必ず変わり、壊れ、直されるものであることを見てきました。
では、次の問いに進みます。
その判断を、どこに、どうやって残すのか。
この章では、設計の議論をいよいよコードの中に降ろします。 抽象論ではなく、日々書いているコードの中で 判断をどう扱えばよいのかを整理していきます。
判断は「意図」ではなく「制約」として残す
設計の意図は、しばしばコメントやドキュメントに書かれます。
- このクラスは◯◯のために存在する
- ここは将来変更される想定
これ自体は悪いことではありません。 しかし、意図だけが残り、制約が残らない設計には限界があります。
コードに残すべきなのは、 「こう使ってほしい」ではなく「こう使うことはできない」 という判断です。
制約として残された判断は、
- 誤った使い方を防ぐ
- 設計者の不在時にも効力を持つ
- 時間が経っても意味を失いにくい
という性質を持ちます。
名前は、最も軽い制約である
判断を残す最初の手段は、名前です。
- クラス名
- 関数名
- 変数名
名前は、 「これは何か」「これは何ではないか」 を同時に伝えます。
たとえば、
- Manager
- Helper
- Util
といった名前は、判断をほとんど閉じ込めていません。
逆に、
- 何の責務を持つのか
- どこまでを扱うのか
が読み取れる名前は、 それだけで利用範囲を制限します。
名前は弱い制約ですが、 弱いからこそ、最初に置く価値があります。
型は、判断を強制する
名前だけでは防げない誤用は、必ず出てきます。
そこで次に使うのが、型です。
- プリミティブ型をそのまま使わない
- 意味のある値オブジェクトを作る
- null を許可しない型にする
型は、 守らなければならない判断 をコードとして強制します。
型として残された判断は、
- コンパイル時に検証される
- 利用側に説明を要求しない
という強い効力を持ちます。
境界は、判断の置き場所を固定する
名前と型だけでは、 判断の影響範囲を限定しきれないことがあります。
そこで登場するのが、境界です。
- モジュール
- レイヤ
- インターフェース
境界の役割は、 この判断は、ここに閉じ込める と明示することです。
境界があることで、
- 変更点が集約される
- 影響範囲が見積もれる
- 壊してよい場所が分かる
ようになります。
判断を残しすぎないという判断
判断をコードに残すことは重要ですが、 すべてを強い制約にすればよいわけではありません。
- 名前で十分な判断
- 型で縛るべき判断
- 境界を切るほどでもない判断
これらを見極めること自体が、設計です。
判断を残しすぎると、
- 変更がしにくくなる
- 本来変えてよい部分まで固定される
という問題が起きます。
ここでも、 判断の強度を選ぶ という第6章の話が生きてきます。
制約の「強さ」を意識して設計する
設計における制約には、強さの違いがあります。
- コメントやドキュメントは、意図を伝えるが守られる保証はない
- 命名は、読み手の判断をある程度縛るが、解釈の余地が残る
- 境界は、構造として責務や依存方向を示す
- 型は、コンパイル時に破られることを許さない
この中で、 最も強い制約は型 です。 型は人の理解や注意力に依存せず、機械的に誤りを排除します。
しかし、強い制約ほど万能というわけではありません。 型は局所的には非常に強力ですが、システム全体の構造までは表現できません。
そこで重要になるのが、 境界 です。
境界は、
- どこまでがこの責務か
- どの方向に依存してよいか
といった設計判断を、構造として表現する制約です。
境界で構造を縛り、その上で型によって振る舞いを縛る。 設計とは、制約を一気に強くすることではなく、 適切な制約を付与する行為 です。
設計とは、判断の履歴を残すこと
時間が経ったコードベースには、 必ず複数の判断が折り重なっています。
そのとき重要なのは、
- この判断はどこに残っているか
- どの判断が、どの制約として現れているか
を追えることです。
良い設計とは、 判断の履歴をコードから読み取れる設計 だと言えます。
まとめ
- 判断は意図ではなく、制約としてコードに残す
- 名前・型・境界は、判断の強度の違いである
- 強い制約ほど、置く場所と範囲を慎重に選ぶ
- 設計とは、判断を選び、履歴として残す行為である
次章では、 こうした判断をチームでどう共有し、 設計を属人化させないかを扱います。