私は、設計の天才ではない
複雑な要求を前に、頭の中で完璧なアーキテクチャを一発で組み上げられるような才能は持ち合わせていない。むしろ、私のようなエンジニアが、複雑さに飲み込まれずに生き残るためには、才能に頼らない泥臭い「手順」が必要だと思う。
私が頼りにしてきたその手順とは、「コードを書く前に、境界線を引くこと」、そして 「その境界線に、血の通った約束を定義すること」 に尽きる。
1. 紙の上で、まず自分自身と向き合う
コードを書くのは楽しい。頑張って書いたコードが動き出す瞬間は、エンジニアにとって何物にも代えがたい喜びだ。
しかし、私はすぐに実装を始めない。なぜなら、早い段階でコードに触れてしまうと、その「実装の美しさ」や「技術的な優位性」に心が囚われ、本質的な矛盾を見逃してしまうからだ。
だから、設計を考える前には必ず、業務全体がどのように行われ、どのように一巡するかをペーパープロトタイピングで確認する。
紙の上に、業務の流れ図、ユーザーの行動、データの動きを書き出す。まるで子どもが遊ぶように、誰が、いつ、何を、なぜ行うのかを考える。このアナログな行為は、自分自身との静かな対話だ。
ここで私が見つけるべきものは、「完璧な答え」ではない。 見つけるべきは、 「矛盾点」 だ。
「この状態で、あのデータが更新されるのは論理的におかしくないか?」 「この業務の切れ目で、ユーザーが迷うだろう」
この矛盾点の検出こそが、その後の設計における「戦場」の場所を教えてくれる羅針盤になる。
2. 境界線は「需要と供給」の関係で生まれる
矛盾点と向き合い、業務を抽象化していくと、自然と 「境界線」 が見えてくる。
それは、業務の切れ目であり、機能の切れ目であり、責務の切れ目だ。 この境界線は、決して設計者の理想や技術的な美しさで決めてはならない。
それは常に、「需要と供給」 の関係で定義される。
-
需要: ある機能を使いたい人(クライアント、ユーザー、他のコンポーネント)
-
供給: その機能を提供し、責任を負う側(サーバー、クラス、モジュール)
この「使いたい側」と「使われる側」の関係を見つけたとき、そこに境界線を引く。
この境界線が曖昧だと、どうなるか? 使いたい側は「多分こう動くはずだ」という希望的観測で実装し、使われる側は「どこまで保証すればいいのか」という不安を抱えたまま実装する。結果、システム全体が疑心暗鬼に陥り、コードは防御的なプログラミングにまみれ、誰も保守したくない泥沼が完成する。
3. 境界線で交わす「契約」をInterfaceとして定義する
境界線が明確になったら、次のステップはシンプルだ。
この境界線で、需要と供給の間に 「約束」 を交わす。 その約束を形式的に定義したものこそが、Interfaceの正体である。
このアプローチは、 「契約による設計(Design by Contract, DbC)」 の思想に近い。
Interfaceは、単なるメソッドのリストではない。 それは、 「使う側がこれを守るなら(事前条件)、使われる側はこれを保証する(事後条件)」 という、両者の間に成立する厳密な契約書なのだ。
そして、このInterfaceこそを、実装の詳細よりも先に定義する。
なぜなら、この「約束」が固まれば、供給側(実装するエンジニア)は、需要側が何を求めているのかというカオスから解放され、自信を持って提供すべき価値(事後条件)の実現に集中できるからだ。
私のような凡庸なエンジニアにとって、このInterfaceという「契約の盾」は、外部からの理不尽な要求や、未来の不確実性から自分を守るための、最強の武器となる。
以下に、この抽象化された関係を図示する。
結論:設計とは、不安を排除するための知的な「狡さ」である
完璧なコードは書けないかもしれない。 だが、この「契約の境界線」という土台を丁寧に引くことで、私はシステム全体の複雑さを個々の小さな領域に閉じ込めることができる。
Interfaceを先に定義し、詳細な実装は後に回す。これは、一発で正解へ到達しようとする天才のやり方ではない。 これは、不安と矛盾に立ち向かうために、あえて 「何もしない領域」と「責任を負う領域」 を明確に分け、着実に生存を担保していく、凡庸なエンジニアの知的な「狡さ」なのだ。
この地道な手順こそが、私のエンジニアとしての矜持を支えている。