Skip to content

Latest commit

 

History

History
112 lines (87 loc) · 7.62 KB

File metadata and controls

112 lines (87 loc) · 7.62 KB

Coding Rules

このドキュメントは、この RDBMS 学習プロジェクトで共通に守るコーディングルールを定義する。 Rust の一次情報と、このリポジトリの構成・目的を踏まえて、実装判断がぶれないことを目的とする。

適用範囲

  • ワークスペース配下の全クレートに適用する。
  • Cargo.tomledition = "2024"rust-version = "1.94" を前提にする。
  • フォーマットと lint の最終的な設定ソースは rustfmt.tomlclippy.toml とする。

1. 基本原則

  • まず正しさを優先し、その上で可読性と拡張性を確保する。
  • 学習用コードであっても、後続の storage / sql / query / catalog が再利用しやすい境界を維持する。
  • 実装前にテスト方針を決め、失敗するテストから着手する。
  • 設計判断が今後の構造や公開 API に影響する場合は docs/decisions.md に記録する。

2. Rust バージョンと依存関係

  • 新しい構文・標準ライブラリ API・依存ライブラリの使用は、rust-version = "1.94" で成立するものに限る。
  • MSRV を引き上げる必要がある変更は、理由を明記したうえで Cargo.toml と関連ドキュメントを同時に更新する。
  • 依存追加は「標準ライブラリでは不足する理由」「このプロジェクトでの用途」「MSRV への影響」を説明できる場合だけ行う。

3. 命名と API 設計

  • Rust の標準命名規約に従う。
    • 型・トレイト・ enum variant は UpperCamelCase
    • 関数・メソッド・モジュール・ローカル変数は snake_case
    • 定数は SCREAMING_SNAKE_CASE
  • 略語は Rust で一般的な綴りを使う。既存の標準ライブラリやエコシステムの名前に寄せる。
  • getter は原則 value() / value_mut() とし、不必要に get_ を付けない。
  • 変換系メソッドはコストと所有権に応じて as_ / to_ / into_ / into_inner を使い分ける。
  • 公開 API では、意味の曖昧な bool 引数や引数過多を避ける。設定が増える場合は専用型へ切り出す。
  • 構造体フィールドは必要最小限だけ公開し、まず pub(crate) や専用メソッドで表現できないか検討する。

4. モジュール分割

  • 1 モジュール 1 責務を基本とする。パーサー、AST、カタログ、ページ管理などの関心を混在させない。
  • crate をまたぐ公開型は、その crate の責務境界を表すものに限定する。
  • 不変条件を持つ値は、生のフィールド公開よりもコンストラクタや専用メソッドで生成させる。
  • 循環参照的な依存が見えたら、その場しのぎで回避せず、責務分割を見直す。

5. エラー処理

  • 回復可能な失敗は Result で返し、呼び出し側へ判断を委ねる。
  • エラー伝播は ? を優先し、深い match のネストで意図を埋もれさせない。
  • ライブラリ crate では文脈を表す独自エラー型を優先し、thiserror で表現する。
  • 実行境界や CLI などの集約層では anyhow を使ってよいが、下位レイヤーの公開 API では濫用しない。
  • unwrap / expect はテストコード、到達不能な不変条件、プロトタイプを除いて使わない。
  • panic! は「利用者が回復できない内部バグ」または「安全性の前提が破られた状態」に限定する。

6. テスト

  • 実装前に失敗するテストを書く。正常系と異常系を最低 1 つずつ用意する。
  • 単体テストはモジュール内部の振る舞いと不変条件を検証する。
  • 統合テストは tests/ 配下に置き、公開 API を外部利用者と同じ形で検証する。
  • パーサーや式評価のような分岐が多い領域では、テーブルドリブンテストを優先する。
  • バグ修正時は、再発防止のために失敗を再現するテストを先に追加する。
  • テスト名は期待する振る舞いが読める文章にする。

7. コメントとドキュメント

  • コメントは「何をしているか」の説明ではなく、「なぜその設計・分岐・順序が必要か」を書く。
  • 非自明なロジック、所有権制約、並行処理の前提、不変条件には意図コメントを付ける。
  • 公開 API には rustdoc を付け、要約を 1 文目で述べる。
  • fallible な公開 API には # Errors、panic しうる API には # Panics、unsafe API には # Safety を記述する。
  • rustdoc のサンプルで失敗しうる処理を書く場合は unwrap ではなく ? を使う。
  • コメント言語は日本語でよいが、Safety など rustdoc の見出し名は標準的な英語表記を使う。

8. unsafe と並行処理

  • unsafe は、計測された必要性があるか、安全な代替手段では表現できない場合に限る。
  • unsafe ブロックは最小範囲に閉じ込め、直前に // Safety: コメントで成立条件を書く。
  • unsafe fn / unsafe trait / unsafe impl を追加する場合は、呼び出し側または実装側が守る条件を明記する。
  • Send / Sync の手動実装は極力避ける。必要な場合は、保持フィールド・公開メソッド・破棄処理まで含めて安全性を説明する。
  • 並行処理は正しさが先で、性能最適化は後に行う。ロック順序や共有状態の所有者はコメントで残す。

9. フォーマット・Lint・レビュー前チェック

  • 変更後は少なくとも cargo fmtcargo clippy --workspace を通す。
  • 警告は放置せず修正を優先する。allow を入れる場合は理由をコメントで残す。
  • rustfmt.tomlmax_width = 100 を前提に、行長よりも意味のまとまりを優先して整形する。
  • clippy.toml の閾値は設計の補助線として扱い、引数数・型複雑性・認知的複雑性が大きい場合は分割を検討する。

10. このプロジェクト向けの補足

  • sql crate では AST は構文表現に徹し、実行時都合の情報を混ぜない。
  • storage crate ではページ ID、スロット番号、オフセットなどの生整数を長く持ち回さず、意味を持つ型で包むことを優先する。
  • query crate ではアルゴリズム最適化より先に、正しさを検証できる中間表現とテストを整える。
  • 途中実装で TODO を残す場合は、何が未実装で何が前提か分かるようにする。曖昧な TODO: implement だけを残さない。

参考にした一次情報