


型付きのWebフレームワークを直し、データベース処理を3つの層に分ける
複数パッケージでできた型付きのWebフレームワークを直す時に使う。決められた開発環境の中で作業し、まず素早く、最後は全体をテストし、公開するモジュールを小さく保ち、データベース処理を層に分け、force-pushはしない。
このAIルールを使うには
## リポジトリが決めた開発環境に入り、変更するパッケージを見つける
グローバルにインストールされたツールに頼らず、リポジトリで宣言された環境マネージャーを通じて開発環境に入ります。
### 環境のセットアップ
- リポジトリのルートから開始し、承認済みの開発シェルを有効にします。
- 利用できる場合は、繰り返し実行するコマンドを高速化するために、環境のキャッシュ済み実行パスを使用します。
- コンパイラー、パッケージマネージャー、データベースツール、文書作成ツールが、固定された環境から提供されていることを確認します。
- 関連するパッケージまたは文書設定で宣言されたランタイムバージョンを使用します。
- デバッグログはローカルでの診断に必要な場合だけ有効にし、デバッグモードを本番の既定値として扱わないでください。
### 作業コンテキスト
複数パッケージのリポジトリでは、コマンドを実行する前に、変更を所有するパッケージを特定します。すべてのパッケージが同じワークフローを共有していると決めつけず、そのソースディレクトリ、テストのエントリーポイント、生成物、公開モジュール、ローカル指示を確認します。
## まず型のチェックで素早く確かめ、最後に全部のテストを回す
反復作業中は信頼できる最速のフィードバックループを使用し、その後、引き渡しに必要な、より広範で正式な検証を実行します。
### 範囲を絞った反復作業
- 環境全体のビルドにコストがかかる場合は、型について素早くフィードバックを得るために、対話型コンパイラー、型チェッカー、モジュールローダーを優先します。
- 初期の反復作業では、変更したモジュールまたは対象を絞ったテストのエントリーポイントだけを読み込みます。
- 標準入力を読み取る対話型ツールには、コマンドと明示的な終了経路の両方を与える必要があります。そうしないと、いつまでも待機し続ける可能性があります。
- 対話型セッションが再読み込みに対応している場合は、編集後に環境全体を何度も再ビルドするのではなく、そのセッションを再利用します。
### テストの登録
- 新しいテストを、パッケージの正式なテスト集約先または検出設定に追加します。
- 対象を絞ったテストが、そのエントリーポイントを通じて実際に実行されることを確認します。
- 変更の準備が整った時、または共有動作、ビルド設定、パッケージ境界に影響がある時は、リポジトリ全体の検証を実行します。
- 対象を絞ったコンパイル確認を、完全なテストスイートが成功した証拠として提示しないでください。
### 開発サーバー
ローカルサービスは、承認済みの環境と正しい作業ディレクトリからだけ起動します。開発サーバーがホストアプリケーションまたは親ディレクトリに依存する場合は、そのエントリーポイントを呼び出す前に、そのコンテキストを明示的に確立します。
## パッケージごとの役目を分け、公開するモジュールを最小にする
特に、ランタイム、開発ツール、テンプレート、マイグレーション、同期、アプリケーションプログラミングインターフェース、テスト、任意の統合機能を組み合わせたリポジトリでは、コードを変更する前に責務を整理します。
### 責務マップ
- サーバーの起動とミドルウェアを、フレームワーク設定から分離します。
- ルーティングと統一資源位置指定子の生成を型安全に保ち、リクエスト処理から分離します。
- モデル、検証、認証、バックグラウンド処理、ストレージ、メール、リアルタイム更新を責務ごとに分離します。
- アーキテクチャでツールとして定義されている場合は、コード生成、スキーマ設計、開発サーバーの動作をコアランタイムパッケージの外に置きます。
- 任意の統合機能とサーバー側コンポーネントは別パッケージとして扱い、その依存関係をコアへ漏らさないようにします。
### 公開インターフェース
利用側が必要とする、安定した最小限のモジュール範囲だけを公開します。生のステートメント、内部の組み立て処理、補助的な前置きコード、実装モジュールは非公開にし、呼び出し側を壊すことなく変更できるようにします。公開モジュールと公開関数には、プロジェクト標準のAPI文書を追加します。
### 言語上の規約
純粋な値、コンテキストパラメーター、フィールドアクセス、テンプレート、型レベルのルーティング、モデル型について、コードベースで確立された慣用表現に従います。同等でも不統一を増やす書き方より、プロジェクトですでに使われている規約を優先します。
## 値はクエリの文に埋め込まず、外に見せるのはsession層だけにする
データベースアクセスをステートメント層、トランザクション層、セッション層に整理し、エンコード、原子性、接続の所有権を明確にします。
### ステートメント層
- 生のパラメーター化クエリを、その入力エンコーダーと結果デコーダーとともに保持します。
- 実行時の値をクエリ文へ埋め込まず、すべての値にプレースホルダーを使用します。
- NULL許容性とデータベース型を明示的にエンコードします。
- 想定するカーディナリティに合うデコーダーを選びます。単一行が任意、単一行が必須、または複数行のいずれかです。
- ステートメントのキャッシュに関する判断を、ステートメントの定義と一緒に保持します。
### トランザクション層
- ステートメントを、原子性が必要な業務処理へ組み立てます。
- 分岐規則、存在確認、作成判断が一貫した一つの状態を参照する必要がある場合は、それらをトランザクション内に置きます。
- 呼び出し側が既存レコードと新規作成レコードを区別できるよう、べき等な結果を明示します。
- 独立した組み立てまたは選択的な組み立ては、処理が本当に独立しており、意図したトランザクションの意味を維持できる場合にだけ使用します。
### セッション層
- セッション層を公開データベースインターフェースとして提示します。
- 生のステートメントと内部トランザクションを隠しながら、接続の実行とトランザクション境界をセッションに所有させます。
- 複数ステートメントの処理には明示的なトランザクションを使用し、単一の独立したクエリにはステートメントを直接実行します。
## データベースの処理ごとに、分離レベルと返す値の型を合わせる
一つのパターンをあらゆる場所に適用するのではなく、分離レベル、カーディナリティ、結果型を処理の意味に合わせます。
### 分離レベルの選択
- 正しさが直列化に依存する重要な処理には、強力な書き込みトランザクションを使用します。
- 同時実行性が重要で、より弱い分離が許容されるクエリには、適切な読み取り分離レベルを使用します。
- 正しさが特定の分離モードに依存する処理は、すべて文書化します。
### 結果の規約
- 0行または1行の結果は、任意値で表現します。
- 複数行の結果は、プロジェクト標準のシーケンス型で表現します。
- 名前付きラッパーを追加しても有用な境界にならない、小規模な内部の複数列結果にはタプルを使用します。
- 更新または行の消去で1行も影響を受けない可能性がある場合は、明示的な成功指標を返します。
- べき等な処理では、処理を実行したかどうかと、その結果の値の両方を返します。
### コーデックの組み立て
エンコーダーライブラリがネストしたペアを組み立てる場合は、平坦な入力タプルを意図的に適合させ、その対応関係をステートメントの近くに置きます。列の順序、NULL許容性、行のカーディナリティを維持するようにデコーダーを組み立てます。値が誤ったフィールドへ気付かれずに対応付けられる可能性のある不一致には、対象を絞ったテストを追加します。
## 依存関係は使うパッケージだけに足し、force-pushはしない
変更の互換性、レビュー可能性、復旧可能性を維持します。
### コードと依存関係
- コードを明確にすることで貢献者に役立つ場合は、プロジェクトで推奨される言語表現を使用します。
- 公開インターフェースを、リポジトリ標準の文書作成システムで文書化します。
- コードベースで有効になっている言語拡張を尊重し、具体的な必要性がない限り、新しい拡張を導入しないでください。
- 依存関係は、それを使用するパッケージだけに追加します。
- 対応するエコシステムに適した互換性の下限と上限を宣言します。
- 実験的な依存関係を明確なリスクとして扱い、狭いインターフェースの背後に分離します。
### Gitの安全性
- force-with-leaseを含め、force-pushは絶対に行わないでください。
- リモートブランチが先に進んでいる場合は、取得して更新済みの履歴へリベースまたはマージし、競合を解決して検証した後、通常どおりプッシュします。
- 共有履歴を書き換えて、拒否されたプッシュを隠さないでください。
- 無関係な生成ファイル、ロックファイルの変更、ローカルの性能設定をコミットに含めないでください。
## ローカル用の上書き設定をコミットに入れず、文書はリリースの手順で出す
ローカルの性能設定と依存関係のオーバーライドは開発用として使用し、共有ソース管理へ漏れないようにします。
### ローカルの性能オーバーライド
- プロジェクトが対応している場合は、ローカルの反復作業用に一時的な高速ビルドフラグを有効にできます。
- ローカル専用の性能変更をコミットしないでください。
- 引き渡し前に、変更を隠す可能性のあるインデックスフラグだけに頼らず、実際の差分を確認します。
### ローカル依存関係の開発
フレームワークと、それを利用するアプリケーションを同時に開発する場合:
1. ローカルのフレームワークチェックアウトを、意図して選んだ開発場所に配置します。
2. 対応しているオーバーライド機構を通じて、アプリケーションの依存先をそのローカルパスに向けます。
3. 必要な環境を有効にし、依存関係の状態を更新します。
4. ローカルのフレームワークに対してアプリケーションをテストします。
5. 共有する変更を準備する前に、オーバーライドを取り除くか、意図的に文書化します。
### 文書とリリース
- 指定された環境から文書をローカルでプレビューします。
- 公開文書が別に管理されている場合は、承認済みのリポジトリワークフローを通じて、そのフレームワークまたは文書の依存関係を更新します。
- その更新に必要なロックファイルまたはソースの変更だけをコミットします。
- 文書またはインフラストラクチャは、指定されたリリース手順だけを通じてデプロイし、依存関係の更新、コミット済み状態、デプロイの間で求められる順序を維持します。
- フレームワークのリリースで下流の文書同期が必要な場合は、記憶に頼らず、その手順をリリースチェックリストに含めます。
