engineering-principles について
engineering-principles は、個人やコーディングエージェントが保守する小規模プロジェクト向けの言語非依存ガイドです。局所的な理解、必要性に応じた複雑さ、明快な構造、リスクに見合う検証を重視します。
主な機能
- 01局所的な理解と明快なナビゲーション
- 02具体的な必要性に基づく複雑さ
- 03凝集度が高く浅い構造
- 04明示的な副作用と依存関係
- 05リスクに応じた検証
- 06簡潔な設計チェック
活用シーン
- 01機能に適したシンプルな設計の選択
- 02パッケージやファイルの整理
- 03テストの必要性の判断
- 04運用と復旧の要件確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jamespegg/ skills --skill engineering-principlesインストール後、Claude Code で/engineering-principlesを入力して読み込まれたか確認します。
同梱ファイルagents/openai.yaml
詳細
アーキテクチャとエンジニアリングの原則
ローカルでの推論を最適化します。 開発者は、間接的なレイヤーや隠れた依存関係をたどることなく、コードベースの小さく分かりやすい範囲を調べるだけで、機能を見つけ、理解し、変更し、検証できるべきです。
1 人で保守し、将来のコーディングエージェントも扱う小規模プロジェクト向けの、言語に依存しない既定の方針です。実際の要件を満たす、最もシンプルで一貫性のある設計を優先してください。厳密さは必要に応じて適用し、機械的に適用しないでください。何を使って構築するかは tech-preferences を、AI のリスクと権限の境界については verifiable-trust を参照してください。
実装の前に複雑さを正当化する
- コードだけでなく、要件にも疑問を投げかけます。 コンポーネント、動作、依存関係、防御策を追加する前に、具体的な必要性と、エンドツーエンドで最もシンプルな実現方法を明確にします。不要な要件は、洗練された方法で実装するより、削除するほうが適切なことがよくあります。
- 根拠と仮定を区別します。 信頼できる障害については、その発生可能性、影響、復旧可能性に応じて対策します。推測上のシナリオに対して、複雑な仕組みを作らないでください。認証情報、権限、取り消せない永続状態の変更には、強固な保護策を維持します。
- 複雑さには価値を持たせます。 新しい概念、検証、レイヤー、設定項目、テストはそれぞれ、実際のリスクを減らすか、実際の機能を実現するものでなければなりません。作業を減らせる場合は、責務を作り直すのではなく、プラットフォームや既存のインストーラーを再利用します。
- 小さくても完成した解決策を優先します。 切り替えで不要になるのであれば、使われていない置き換え先に一時的な互換コードを残さないでください。ただし、実際の利用者や移行手順が必要とする場合は別です。重複を解消するために、重複コードより把握しにくいフレームワークを導入しないでください。
- 完成した設計を見直します。 動作が機能したら、必須の動作を損なわずに、責務、分岐、依存関係を取り除けないか確認します。行数の最小化や恣意的な制限ではなく、概念を減らし、理解を速めることを最適化します。
構成とナビゲーション
- アーキテクチャのレイヤーではなく、機能ごとに整理します。 パッケージやディレクトリには、ソフトウェアが何をするかを表す名前を付けます。
ports、adapters、models、servicesのような汎用ラベルは、アーキテクチャ用語がその分野における最も明確な名前である場合を除き、使わないでください。 - 名前とナビゲーションを分かりやすくします。 パッケージ、ファイル、型、関数には、コードをどこに置くべきかを開発者が予測できる、意味の明確な名前を付けます。
- まとまりのあるパッケージを少なく保ちます。 関連する責務はまとめ、新しいパッケージの境界を設ける前に、パッケージ内で説明的な別ファイルに分けることを優先します。
- 高い凝集度と疎結合を保ちます。 同じ理由で変更されるコードは、通常まとめて配置します。無関係な機能間の明示的な依存関係は最小限にします。
- 構造を浅く保ちます。 実際の境界がない限り、ネスト、細分化、余分なレイヤーを設けないでください。
- 何でも入れる場所を作らないでください。
utils、common、helpers、miscのような汎用の置き場は作りません。それぞれの動作に明確な担当箇所を設けます。 - 関心事を分離しても、パッケージを分ける必要はありません。 パッケージ数やファイルサイズは目標ではありません。
実装と依存関係
- 利用者向けの API を設計します。 小さく予測しやすい操作を公開し、利用者が理解する必要のない実装の詳細は隠します。
- 具体的な依存関係を優先します。 意味のある境界、差し替え可能な実装、またはテスト要件がインターフェースを正当化しない限り、直接呼び出します。習慣でインターフェースを作らないでください。
- 副作用を明示します。 隠れた可変のグローバル状態、予想外の副作用、魔法のような配線は避けます。
- 巧妙さや推測に基づく再利用より明快さを重視します。 関係のない機能を結合する共通の抽象化を作るより、少し重複させるほうが適切な場合があります。架空の拡張ポイントを作らないでください。
- エラーに意図を持って対処します。 明確に失敗させ、有用なコンテキストを保持し、リソースをクリーンアップし、復旧方法を説明します。
- 複雑さに見合う場合にのみ並行処理を使います。 まずは逐次処理から始め、必要であれば、所有権、キャンセル、タイムアウト、シャットダウンを理解しやすくします。
- デプロイ可能なサービス境界に一貫性を持たせます。 サービスは明確な機能を担い、サービス間の契約を明示します。独立してデプロイできるからといって、内部のレイヤーを過剰に増やす必要はありません。
設定、ランタイム、運用
- コードとデプロイ設定を分離します。 シークレットや環境に依存する値は外部化します。適切な場合は、レビュー可能でバージョン管理された構造化設定をアプリケーションポリシーに使用します。認証情報を埋め込まないでください。
- 再現可能なビルドとリリースにします。 依存関係を宣言して固定し、一度ビルドしたら、識別可能で不変の成果物を昇格させます。
- プロセスは置き換え可能にし、永続状態は意図的に管理します。 予測可能な起動、正常なシャットダウン、復旧を実現します。一時的なプロセス状態と、永続的なユーザーデータ、ID、リポジトリを区別します。
- 環境間に有意な一貫性を保ちます。 開発、CI、デプロイで、比較可能なパスと依存関係を使い、違いは明示します。
- 可観測性と運用性を確保します。 手作業の慣例よりも、有用なエラー、構造化ログ、ヘルスチェック、文書化された再現可能な検証・復旧コマンドを重視します。
検証と進化
- 偶発的な実装ではなく、観測可能な振る舞いをテストします。 振る舞いを変更する場合は、合意済みの公開境界で、テストファーストの red → green による垂直スライスを優先します。独立した根拠に基づく期待値を使って、重要な成功、失敗、復旧の経路を検証します。プロセスを満たすだけの、実装と密結合した脆いテストや、同語反復的なテストは書かないでください。静的チェックでは実際の不変条件を強制します。
- 小さくても完結した変更にします。 無関係なリファクタリング、仮定上のインフラ、放棄された互換性レイヤーを持ち込まずに問題を解決します。意図的に変更する場合を除き、契約を維持します。
- 長く参照でき、見つけやすい形で決定を残します。 保守担当者が確認する場所に、明白でない制約、根拠、運用方法を文書化します。冗長な指示や重複した指示は避けます。
- コードベース自体がアーキテクチャを説明できるようにします。 明確な構成、契約、実行可能な規約によって、エージェントへの指示を減らします。エージェントが繰り返し失敗する場合は、恒常的なルールを追加する前に、構造、ドキュメント、チェックを改善します。
- 指示に依存するシステムより、自己説明的なシステムを優先します。 ドキュメントには、意図や明白でない選択を残し、分かりにくいコードの埋め合わせをさせないでください。
- 妥当な水準の厳密さを保ちます。 実験では迅速で元に戻せる学習を重視し、本番環境や重大な変更では、より強固なセキュリティ、可観測性、検証、復旧を実現します。
テストと CI への投資
テスト、フィクスチャ、CI には、継続的な保守コストと実行コストがかかります。小規模で問題から復旧しやすいサイドプロジェクトでは、可能な限り多くのテストをそろえるのではなく、有用な確信と迅速なフィードバックを優先してください。
- テストごとに必要性を説明してください。 検出する現実的な障害とその影響を明示し、別のテストですでに同じ動作をカバーしていないか確認してください。すべての分岐、一時的なマイグレーション、過去のインシデントを、恒久的なリグレッションテストの網羅表にしないでください。認証情報、権限、破壊的な書き込み、復旧が難しい状態については、より手厚くカバーしてください。
- 意味のある最小コストの境界で一度だけテストしてください。 ローカルの動作テストとコントラクトテスト、実際の境界を対象とする少数の実行可能なテスト/統合テスト、パッケージング用の最小限のビルド済みイメージのスモークテストを優先してください。同じシナリオをすべての層で繰り返しても、自動的に確信が高まるわけではありません。
- 合成した時間のために実時間を費やさないでください。 可能な場合は、制御可能なリトライ間隔やクロックを注入してください。実際のタイミング、プロセスシグナル、コンテナオーケストレーションの動作そのものがリスクとなる場合に限り、それらを実際に動かしてテストしてください。重いフィクスチャには、明確に異なる採用理由が必要です。
- 手動受け入れテストは意図を持って選んでください。 影響が小さく、容易に復旧できる、まれな外部サービス、過去バージョンからのアップグレード、運用担当者のみが行うシナリオは、簡潔に文書化した人手によるスモークテストのほうが適している場合があります。頻繁に繰り返すシナリオや、正確に確認しにくいシナリオは自動化してください。
- 通常のフィードバックサイクルを小さく保ってください。 通常の PR では、高速で影響の大きいチェックを実行してください。追加の確信が待ち時間に見合う場合は、大規模なマイグレーションの網羅的テスト、高コストなフルイメージのテスト、環境依存のチェックを、オプトインまたはリリース時のみの実行にしてください。包括的に見せるためだけにゲートや CI インフラを作らないでください。
- 並列化の前にプロファイルしてください。 テスト、パッケージング、ジョブの所要時間を測定し、不要な逐次依存を避けてください。リソース制限と成果物の公開の安全性が許す場合に限り、独立した作業を並列化してください。安全に行える場合は古くなった PR の実行をキャンセルしますが、必須の不変なリリースビルドはキャンセルしないでください。
- 不要になった検証を削除してください。 マイグレーションが完了した後や、テストの失敗が現在のコントラクトに影響しなくなった後は、検証を簡素化するか削除してください。必須の検証レベルを変更する際は、古いリリース手順や判断の記録も更新してください。
設計の簡易チェック
パッケージ、依存関係、抽象化、プロセスを追加する前に、次の点を検討してください。
- 根本にある要件は必要ですか。それを解決する最小の成果は何ですか。
- この機能を誰かが自然に探す場所はどこですか。その場で理解できますか。
- この境界は、実際の責任や変更理由に対応していますか。
- この複雑さは、根拠のあるニーズや重大なリスクに対処するうえで、直接的な方法よりも簡潔ですか。
- 重要な動作や障害を検証できますか。また、重大な変更から復旧できますか。
これは軽量な判断の手引きであり、すべての編集に必須のチェックリストではありません。慣例によって見通しが悪くなる場合は、トレードオフを明示し、よりシンプルな設計を選んでください。
必須ではない参考指針
- Effective Go、Go Code Review Comments、Go Proverbs:意図が伝わる名前、利用側を重視した小さなインターフェース、明示的なエラー、不要な抽象化の回避。
- The Twelve-Factor App:明確な設定、再現可能なビルド、環境の一貫性、破棄可能なプロセス、運用上の可視性。
これらの考え方は、Go の使用、すべての設定での環境変数の使用、または永続状態が意図されている場合のステートレス化を必須とはしません。