コーディング基本原則
godslew のコーディング哲学。すべてのプロジェクトに適用する普遍的な原則。
適用優先順位: プロジェクト固有ルール(project skill / repo docs) > 言語慣習・チーム規約 > この原則。
この原則はデフォルト方針であり、プロジェクトやチームの規約が存在する場合はそちらを優先すること。
1. 可読性 — 冗長でも読めるコードを書く
- 明示的 > 簡潔: 一行で書けても、意図が不明確なら分割する。「賢い」コードは保守コストが高い
- Early Return: ネスト(2重以上)は認知負荷を上げる。条件を反転して早期脱出する
- 関数分離: 複雑なロジックは名前付き関数に切り出す。関数名そのものが意図の説明になる。複雑なロジックとは例えば2つ以上の条件判定を含む式(
a == 1 && b != 1、x != 3 || y > 1)などを指す
- 定数化: マジックナンバー/文字列リテラルに名前を付ける。意図を隠す数値や文字列をコードに残さない
- 略語を避ける: 変数名・関数名は省略せず、ドメイン用語で正確に命名する。ただし業界標準の略語(URL, ID, API等)はそのまま使う
- 構造的コメント: 大きなファイルはまずファイル/クラス分割を検討する。分割が不適切な場合は論理ブロックごとにコメントで区切り、見通しを確保する
2. 型駆動の防御的プログラミング — 不正な状態を型で排除する(型が弱い言語ではバリデーション関数やアサーションで代替する)
- 型で状態を表現する: フラグの組み合わせではなく、直和型(sealed class / union type / enum等)で状態を定義する。型チェッカーや静的解析に不正状態を検出させる
- 値オブジェクト: プリミティブ型のIDや値はドメイン固有の型で包む。取り違えを静的チェックで防止する
- ファクトリーメソッド: 不変条件を持つ型には、生コンストラクタではなく検証付きファクトリー関数で生成する
- 網羅的分岐: 直和型の分岐にワイルドカード/デフォルトケースを使わない。新ケース追加時に静的チェックで漏れを検出する
- 安全な型変換: ダウンキャストではなくパターンマッチで型を判別する
- エラー分類は境界で: データ取得レイヤーでエラーを型に変換する。表示レイヤーに生の例外を漏らさない
- 関数的エラー伝播: try-catchブロックではなく、Result型等を使って成功/失敗を関数的にチェーンする
3. 構造化 — 関心の分離と責務の明確化
- 単一責務: 1つのクラス/関数/状態ホルダーは1つの関心事だけを扱う
- レイヤー間の明示的変換: 境界を越えるデータは専用の変換関数で整形する。暗黙の変換を許容しない
- 不変性がデフォルト: 状態は不変で保持し、更新時はコピーして新しいインスタンスを作る。可変変数は原則使わない
- 内部状態の分離: 複合的な状態は関心ごとに個別の状態ホルダーで管理する
- I/Oとロジックの分離: 入出力処理と中核ビジネスロジックを分離する。テスト容易性と再利用性を確保する
- スレッドセーフ: 共有状態にはスレッドセーフなデータ構造と適切な並行制御を使う
4. 普遍原則
- SSOT(Single Source of Truth): ロジック・定数・ルールを重複させない。一箇所で定義し、参照する
- 根本原因を直す: ワークアラウンドや表面的な修正ではなく、根本原因を特定して修正する
- YAGNI: 必要になるまで抽象化・汎用化しない。現在の要件に最小限のコードで対応する
- テストで確認する: 振る舞いの変更はテストで検証する。「動くはず」ではなく「動くことを確認した」を基準にする
- 既存規約に合わせる: 新しいパターンを持ち込む前に、プロジェクトの既存パターンを確認し合わせる
判断に迷ったとき
- 可読性 vs 型安全: まず命名・分割・補助関数で可読性を改善する。それでもコストに見合わない場合のみ局所的に単純化する。ただし不正状態の排除と境界検証は維持する
- 構造化すべきか?: 「複数箇所で使われるか」「ドメインルールを持つか」がYesなら構造化する。ローカルスコープのみなら不要
- コードが長くなることへの抵抗: 短さは目標ではない。「6ヶ月後の自分が読んで理解できるか」が基準