歴史的にRustは、拡張性が高く信頼性のあるシステムプログラムを書くための言語として設計されてきました。モジュールシステムは、名前空間の厳格な区分、コードの孤立化、および名前の衝突なしで大規模プロジェクトを編成するために作られました。モジュールは、コードを構造化し、実装の詳細を隠蔽し、公開APIを管理することを可能にします。
プロジェクトが成長するにつれて、コンポーネントの孤立化、コードの再利用、および可視性の管理に関する問題が発生します。エラーは、pub、pub(crate)というキーワードの誤った使用、およびディレクトリとファイルの構造が不足しているか不正確であることに関連していることが多いです。
解決策:Rustでは、モジュールはキーワードmodを使って宣言されます。ファイルとディレクトリは名前空間を構成し、階層を強調します。すべてがデフォルトでプライベートであり、pub、pub(crate)、pub(super)というキーワードを使って可視性を管理します。エクスポートやエイリアスの適切な使用、およびプロジェクトの適切なモジュール分割により、コードは拡張可能で保守性が高く、安全になります。
コードの例:
// src/lib.rs mod network; pub use network::client::Client; // src/network/mod.rs pub mod client; // src/network/client.rs pub struct Client { pub name: String, }
主な特徴:
ディレクトリ構造がモジュールの定義と一致しない場合、何が起こりますか?
コードはコンパイルされません:Rustはファイルとモジュールの厳密な一致を期待します(例えば、mod fooが宣言された場合、foo.rsファイルまたはfoo/mod.rsディレクトリが存在する必要があります)。
pub(crate)は外部の消費者から実装を隠しつつ、クレート内のすべてのモジュールから利用可能にすることができますか?
はい、pub(crate)は同じクレート内の任意のモジュールで要素を可視化しますが、このクレートを依存関係として使用する外部プロジェクトには見えません。
公開の再エクスポートなしでルートファイルから深くネストされたモジュールの関数をインポートするにはどうすればよいですか?
階層の直接の参照を介して:crate::module::submodule::function。pub useがないと、それらはクレート内でのみ使用可能です。
ネットワークモジュールは、すべてのサーバー、クライアント、プロトコルパーサーのコンポーネントをnetwork.rsという1つのファイルに含んでいます。すべてがpubとして宣言され、テストのために内部コードが直接接続されています。時間が経つにつれて、不要な結合が進み、公開インターフェイスと実装を切り離すのが困難になります。
利点:
欠点:
ネットワークはサブモジュールに分割されます:client、server、protocol。networkからは公開インターフェイスのみがエクスポートされ、APIはコンパクトで、詳細はカプセル化されています。各モジュールのテストは隔離されています。
利点:
欠点: