Rust プロジェクトをクリーンに保つ

RustBeginner
オンラインで実践に進む

はじめに

動作するコードは、他の人が安全に保守できるプロジェクトに必要な要素の一つにすぎません。引き継ぎ可能な Rust crate では、フォーマットを統一し、問題のありそうなパターンを避け、公開インターフェースを説明し、テストに合格し続けることも重要です。

この実験では、Rust 標準のプロジェクトツールを使って小さなライブラリを修正します。まず rustfmt、Clippy、rustdoc を一つずつ導入し、その後、テストスイートと組み合わせて、繰り返し実行できる品質向上ループを作ります。各ツールが何を確認するのかに集中できるよう、コードは意図的に小さくしています。

ソースコードのフォーマットを統一する

このステップでは、rustfmt を使ってレイアウトの違いを検出し、プログラムの動作を変えずに修正します。

準備済みのライブラリに移動し、ソースファイルを開きます。

cd /home/labex/project/handoff-helpers
nano src/lib.rs

最初の関数は有効な Rust コードですが、スペースとインデントがファイルの他の部分と異なります。フォーマット規則は機械的に適用できるため、各コントリビューターが手作業で整えるよりも、ツールを使うほうが確実です。編集せずに Ctrl+X を押して nano を終了します。

まず、チェックモードを実行します。

cargo fmt -- --check

このコマンドは失敗し、差分を表示することが想定されています。cargo fmt はパッケージ内の Rust ファイルを選択します。最初の -- は Cargo のオプションの終わりを示し、2 番目の --check は rustfmt に渡されます。チェックモードは差分を報告しますが、ファイルを書き換えません。そのため、自動チェックで利用できます。

次に、フォーマッターを適用します。

cargo fmt

もう一度ソースを開きます。

nano src/lib.rs

最初の関数のスペース、改行、インデントが統一されています。名前とロジックは変わっていません。nano を終了し、チェックモードで何も表示されないことを確認します。

cargo fmt -- --check

出力がなく、終了ステータスが成功であれば、すべての Rust ファイルがすでに rustfmt の規則に一致しています。

Clippy の警告を修正する

このステップでは、Clippy を使って、コンパイルはできるものの意図をより明確に表現できるコードを見つけます。

Rust コンパイラーは、コードが有効で型安全かどうかを確認します。Clippy は、問題のありそうなパターン、不要に複雑なパターン、Rust の慣用的でないパターンを検出する lint を追加します。警告をエラーとして扱う設定で実行します。

cargo clippy -- -D warnings

最初の実行は失敗することが想定されています。rustfmt の場合と同様に、-- は残りのオプションを基盤となるツールに渡します。-D warnings警告を拒否する(deny warnings) という意味です。そのため、報告された警告をすべて修正するまで、品質チェックはゼロ以外の終了ステータスになります。

Clippy は、次の 2 点を改善するよう指摘します。長さをゼロと比較する代わりに、空かどうかを直接確認するメソッドを使うことと、呼び出し側に Vec の所有を要求せず、スライスを受け取ることです。ソースを開きます。

nano src/lib.rs

次の部分を変更します。

if cleaned.len() == 0 {

変更後:

if cleaned.is_empty() {

続いて、open_count の引数を次のように変更します。

tasks: &Vec<bool>

変更後:

tasks: &[bool]

is_empty() は確認したい内容を直接表します。スライスを使うと、具体的なベクターコンテナーを要求せずに、借用したシーケンスデータを受け取れます。保存して nano を終了し、小さな変更をフォーマットしてから Clippy を再実行します。

cargo fmt
cargo clippy -- -D warnings

警告のない最後の Finished 行が表示されれば、より厳格な lint ポリシーの下でもライブラリが問題なくコンパイルされたことを示します。

公開インターフェースをドキュメント化する

このステップでは、ドキュメントコメントを追加し、閲覧可能な API ドキュメントを生成します。

/// で始まるコメントは、その直後にある項目をドキュメント化します。//! で始まるコメントは、それを囲む crate またはモジュールを説明します。Rustdoc は、どちらの形式もリンク付きの HTML ドキュメントに変換します。

ライブラリのソースを開きます。

nano src/lib.rs

ファイルの先頭に、次の 2 行を追加します。

//! Small helpers for preparing task data for reports.
#![deny(missing_docs)]

この内部属性により、公開項目にドキュメントがない場合はビルドエラーになります。ドキュメント作成を単なる推奨事項ではなく、明確なプロジェクトポリシーとして扱えるようになります。

normalize_title の直前に、次のコメントを追加します。

/// Returns a trimmed title, or `Untitled` when the input is blank.

open_count の直前に、次のコメントを追加します。

/// Counts entries whose completion value is `false`.

保存して nano を終了します。このパッケージだけのドキュメントを生成します。

cargo doc --no-deps

cargo doc は rustdoc を実行します。--no-deps オプションを指定すると、依存 crate のドキュメント生成を省略できるため、対象を絞ってより速く処理できます。生成されるエントリーページは target/doc/handoff_helpers/index.html です。Cargo は Rust crate 名で、パッケージ名のハイフンをアンダースコアに変換します。

ls target/doc/handoff_helpers/index.html

このパスが表示されれば、rustdoc が crate のページを生成し、ドキュメント不足をエラーにするポリシーにも合格したことを確認できます。

完全な品質向上ループを実行する

このステップでは、個別のツールを、予測可能な引き渡し前の手順として組み合わせます。

フォーマット、lint、ドキュメント、テストは、それぞれ異なる点を確認します。

  • rustfmt は、ソースが標準のレイアウトになっているかを確認します。
  • Clippy は、問題のありそうなパターンや不明確なパターンが残っていないかを確認します。
  • テストは、必要な動作が引き続き機能するかを確認します。
  • rustdoc は、プロジェクトのポリシーに従って公開インターフェースをドキュメント化できるかを確認します。

失敗したときに原因を明確に特定できるよう、各チェックを個別に実行します。まずフォーマットを確認します。

cargo fmt -- --check

厳格な lint を実行します。

cargo clippy -- -D warnings

ライブラリのテストを実行します。

cargo test

出力には、2 つのテストが成功したことが表示されます。最後に、対象を絞ったドキュメントを再生成します。

cargo doc --no-deps

4 つのコマンドがこの順番ですべて成功すれば、crate のフォーマットが統一され、lint に問題がなく、動作がテストされ、ドキュメントも作成されたことになります。引き渡し前に同じループを実行すれば、品質を最後の目視による推測ではなく、繰り返し確認できる証拠にできます。

まとめ

rustfmt でフォーマットを修正し、Clippy の厳格な指摘を解決し、公開ライブラリのインターフェースをドキュメント化し、rustdoc の出力を生成し、テストに合格し続ける状態を保ちました。さらに重要なのは、これらのツールを繰り返し実行できる品質向上ループとして組み合わせ、信頼性の高いプロジェクトの引き渡しを支えられるようにしたことです。