OTAKU / マニフェスト

第1章 — 硬い核、柔らかい縁

OTAKU マニフェスト

OTAKUは頭字語であり、すべての文字が制約です。40のルールがそれを測定可能にし、1つの指標がメソッドの存在可否を決めます。

この哲学には硬い核と柔らかい縁があります。核=5つの柱とそれを運用する閾値は交渉しません。縁=言語、フレームワーク、スタイル、ツールは自由です。

5つの柱の順序には意図があります。規律が最初なのは、それがなければ何も残らないからです。契約が最後なのは、外の世界が見てよい唯一のものだからです。

O

規律を自ら律する

自分に厳しく。

制約だけが自由への道です。複雑度、サイズ、命名は議論ではなく測定の対象です。

T

構成のための道具

Unixのように構成する。

入出力が明確な小さな部品。アプリケーションはデータパイプで、副作用は縁に留まります。

A

中核を装甲する

ビジネスの中核を守る。

依存は内側だけへ。エンティティとユースケースはフレームワークの名前を知りません。

K

インフラを静かに保つ

インフラはただの詳細。

永続化はメモリ上のコレクションのように振る舞います。失敗は明示的で、状態は既定で不変です。

U

普遍言語と契約

ユーザーの言葉で語る。

ユビキタス言語を設計先行の契約に明示します。プリミティブは包み、すべての公開メソッドに契約があります。

主要な指標

循環的複雑度(Thomas J. McCabeによる、メソッドを通る独立経路の数)がこの哲学の主要な計器です。複雑度が5を超えるメソッドは、どれほど読みやすく見えても却下されます。5つの経路は、読み手が同時に保持すべき5つの推論です。

規律の節の他のすべては、この数を低く保つための手段です。1階層のインデント、ELSEなし、switch/caseなし、ガード節、抽出。この指標は本書のすべての言語で測定でき、どのエコシステムにも報告するツールがあります。

40のルール

すべてのルールには測定可能な閾値があります。迷ったら、より制限の強い選択をしてください。

40のルール · 7グループ · 5つの柱

O複雑度

  1. メソッドごとの循環的複雑度は5を超えてはならない。
  2. メソッド内のインデントは1階層まで。
  3. ELSEキーワードを使わない(ガード節や早期リターンを使う)。
  4. switch/case文を使わない(ポリモーフィズム、match式、Strategyを使う)。
  5. マジックナンバーやマジックストリングを避ける(定数かenumを使う)。

Oサイズ

  1. クラスは最大50行(クラス本体のコードのみ)。
  2. メソッドは最大20行(実行コードのみ)。
  3. 名前空間またはパッケージあたり最大10クラス。
  4. インスタンス変数が3つ以上のクラスは禁止。
  5. メソッドの引数は最大2つ。
  6. コンストラクタの引数は最大2つ。
  7. インターフェースのメソッドは最大2つ。

O命名

  1. 略語を使わず、完全で説明的な名前を使う。
  2. 真偽値を返すメソッドは is / has / can / should で始める。
  3. メソッド名は動詞で始める。
  4. 定数は UPPER_SNAKE_CASE。
  5. プロパティとメソッドは camelCase。

Tモジュール性

  1. コレクションを第一級オブジェクトにする(配列を専用クラスで包む)。
  2. 1行につき1つのドット。可読性のためメソッドチェーンを避ける。
  3. staticメソッドはファクトリと純粋関数のみ許可。
  4. コマンドとクエリを分離する(値を返すメソッドに副作用を持たせない)。
  5. 可能な限り関数を純粋にする(同じ入力なら同じ出力、副作用なし)。
  6. グローバル状態やシングルトンを避け、依存を明示的に注入する。
  7. 小さく焦点の定まった関数を好む(1つのこと以上をするなら抽出する)。

A保護

  1. getter / setter / 公開プロパティを禁止し、振る舞いのメソッドを使う。
  2. プロパティは既定でprivate。protectedはフレームワークの継承のみ。
  3. クラスは既定でfinal。拡張はインターフェース経由で行う。
  4. 継承はフレームワークの基底クラスのみ許可。合成を優先する。
  5. 境界(コンストラクタと公開メソッド)で全ての入力を検証する。
  6. 早期に失敗する(前提条件が破られたら即座に例外を投げる)。
  7. 引数を変更しない(不変として扱う)。

K副作用と失敗

  1. 不変性を優先する(readonlyプロパティ、新しいインスタンスを返す)。
  2. コレクションを返すメソッドは空のコレクションを返し、nullを返さない。
  3. 失敗しうるメソッドはResult/Eitherを返すか例外を投げる。nullは返さない。
  4. 暗黙より明示:隠れた依存、マジックメソッド、暗黙の型変換を避ける。
  5. ドメインにインフラの詳細(SQL、HTTP、ファイルパス)を漏らさない。

U契約

  1. すべてのプリミティブと文字列を値オブジェクトで包む。
  2. 明示的なシリアライズ以外でジェネリック型(mixed, array, object)を使わない。
  3. すべての公開メソッドはインターフェースで宣言する。
  4. コメントは「なぜ」を説明し、実装ではなく契約に置く。

柱は互いを支える

規律が構成を可能にします。300行のクラスは差し替えられません。構成が中核を守ります。モノリスは依存を隠せません。守られた中核がインフラを本当に任意のものにします。契約だけが、それを外部から検証できる理由です。

柱を1つ外すと、残りは儀式になります。5つすべてを保てば、システムは退屈になります。橋が退屈であるのと同じ意味で。