より良い C++ モジュールを目指して - パート 2:モジュールの命名

うたたねをしている方のために説明すると、前回の記事でモジュールのマッピングについて説明したので、モジュールの命名について説明する必要があります。

ご覧のとおり、モジュールには名前があり、名前は難しいです。この場合、名前は、プログラムで使用される各モジュールを一意に識別するのに役立ちます。

この記事の最後では、公式の WG21 スタンディング ドキュメントを通じてモジュールの命名を管理することを提案しています。 意見ですが、我慢してください!

識別子のドット付け

モジュール名は、ドットで区切られた一連の識別子で構成されているという重要な点があります。ドットには、世界を階層的に編成する力​​という意味的な意味が付与されていると考えるかもしれません。そして、あなたは間違っているでしょう。ドットはドットです。そしてそれ以上のことはありません.それらは、あなたがそれらに帰する傾向がある以上の意味を持っていません.そして、すべてのモジュールは平等に作られています.サブモジュール、スーパーモジュール、セット、スーパーセットはありません。

12 そして 20 、標準に関する限り、関係ありません.3841 どちらでもない.Importing 53 特に 69 の名前をインポートしません .あなたはワイルドになることはできず、79 そんなことないから。

ただし、すべての立派なスパイ機関と同様に、できることは 87 を開始することです たとえば、モジュール 94 が与えられた場合、 (109 で宣言 )、さらに module114 を持つことができます ファイル内 126

export module foo;
export import foo.bar;

そうすることで、すべての名前が 139 によってエクスポートされます 145 に表示 および foo をインポートする他のすべての翻訳単位は、階層を作成します。But 159 同様に 166 できます 177 または 182;

私の名前を言ってください。

あなたは熱意を持って、すべてのコア ビジネス ロジックを 199 に入れることにしました。 209 のいくつかの便利なビット .

後で、2 つのモジュールを含むサードパーティのライブラリを使い始めることがあります:218 ライブラリのコアはどこにあり、適切な名前の 221 そのライブラリのいくつかの有用なビットが含まれています。

ここには共謀はありませんでした。ただ激しい衝突があり、コンパイルが突然ひどいスラムで終了しただけです。明らかに、あなたは何も悪いことをしていません。 231 を最初に要求したのはあなたです その名前を使えるのはあなただけです。 245 は素晴らしい名前であり、あなたのものです。今もこれからも。

他の人は意見を異にし、対立が生じ、私たちは少し窮地に立たされています.

ちょっとしたエルフ

259 はどこにありますか ?さて、264 で 期待どおりのモジュールです。次に、そのモジュールは 275 に論理的に配置されます ディレクトリ (元々は 284 と呼ばれていました) 、しかし、それは 297 に関して問題があることが判明しました Windows 開発者は古い Entish をあまり気にしていなかったので、すべてが 307 の一部です。 310 にあるプロジェクト .

言語学者が C++ 開発者ではないことは、実に幸運なことです。

ほとんどの妥当なプロジェクトは The Silmarillion ほど複雑ではありませんが、 、ライブラリ、モジュール、ディレクトリ、ファイル、名前空間など、多くのエンティティを作成して名前を付ける必要があるという事実は残っています.

モジュール マッピングに関する以前の記事で、モジュールとファイルに同じ名前を付ける利点について説明しました。統一された名前を付けると、コードベースが読みやすくなります。

ファイルに名前を付けるというプレッシャーから解放されたら (よろしくお願いします)、ライブラリと名前空間に注目しましょう。

モジュールが名前のコレクションである場合、名前空間は名前の名前のコレクションであり、ライブラリはリボン付きの名前の名前のコレクションです。もちろん、モジュールは複数の名前空間を開くことができ、名前空間は複数のモジュールにまたがることができます。ライブラリは、複数の名前空間とモジュールで構成できます。ヘッダーのみのライブラリと、モジュール インターフェイスのみのライブラリがあります。

ジョン・ヴェンが亡くなったとき、マウリッツ・エッシャーは25歳でした。彼らは会いましたか?

毎日のリマインダー

モジュールはネームスペースを作成しません .

モジュールは名前空間ではなく、名前空間を導入したり、エクスポートする名前に名前空間やプレフィックスなどの種類を提供したりしません。変更または改善します。悲しい顔の絵文字

これは、モジュールは名前空間の make ではないことを毎日思い出させるものでした .

名前空間とライブラリ

グローバル名前空間に名前を入れるのはよくないことだと理解しています.ADL が名前空間をひどいものにしていると考えています.

そのため、名前を付ける場所が多くありません。

合理的な理由から、各ライブラリにはそのすべての名前を含むトップレベルの名前空間が 1 つ必要であり、ネストされた名前空間を避けることに同意します。

また、他の人の名前空間に名前を入れると、彼ら自身が同じ名前を導入すると破損につながることもわかっています。そのため、他の人の名前空間を開くことは嫌われています.

したがって、トップ レベルの名前空間はまとまった名前のセットを示すのではなく、所有権を示すものです .

ライブラリは所有権も通知します。論理的な統一性があっても (ライブラリは多くの場合、機能のまとまりのあるセットを提供します)、ライブラリの定義プロパティは所有者、つまりそのライブラリを提供または維持するエンティティを持つことです。

そのため、名前空間とライブラリは同じ機能を提供します:所有権の通知.同じコインの裏表であるということは、名前空間とライブラリは同じ名前を共有するべきではないでしょうか?

ネーミングが難しいと言いましたか? 324

335346 358 367として 373 d 386 この390を飲みながら 403 417 426 私に 434 を与える .Is 440 いい名前? 452 ! 462 のプロジェクトが既にそのように呼び出されている場合、472 になります。 483 .

(C++のプロジェクト名を組み合わせた楽しい文章ができたらリツイートします!)

通常、ライブラリとプロジェクトの名前は独創的ですが、一意である必要があり、同時に可能な限り短い側にする必要があります。

しかし、創造性と意味を保ちながら、名前を短く創造的にするにはどうすればよいでしょうか?

時代を超えた命名

Java

Java パッケージは、C++ モジュールと名前空間を組み合わせたものと同じ機能を提供します。Java ドキュメントには

企業は、逆のインターネット ドメイン名を使用してパッケージ名を開始します。たとえば、example.com のプログラマーによって作成された mypackage という名前のパッケージは com.example.mypackage です。

単一の会社内で発生する名前の衝突は、その会社内の慣習に従って、おそらく会社名の後に地域またはプロジェクト名を含めることによって処理する必要があります (たとえば、com.example.region.mypackage)。

Java 言語自体のパッケージは、java で始まります。または javax.

Java はほぼ 25 歳ですが、一意性を保証し、所有権を示す命名スキームを提案するほど賢明です

C♯

490 アセンブリ (≈ ライブラリ) と名前空間があり、モジュールは必要ありません。

名前空間の命名に関する非常に詳細なガイドラインを提供します。これは次のように要約されています:508

✓ DO 名前空間名に会社名のプレフィックスを付けて、異なる会社の名前空間が同じ名前を持つことを防ぎます。

✓ 名前空間名の第 2 レベルでは、バージョンに依存しない安定した製品名を使用してください。

510 についてよく知らない 、しかし、ネストされた名前空間の使用に悩まされることはないと思います.最も重要なことは、 526 、一意であり、不変でなければなりません。

行く

パッケージは一意に識別する必要があるリソースであるため、Go パッケージは URL を介してインポートできることに気づきました。

また、適切なパッケージ名についての洞察も提供します。どうやら 538 は適切なパッケージ名ではありません。誰が考えたでしょうか?

Rust と Javascript

はい、あえてこの 2 つを一緒にバンドルします。あえて 2 倍にします。

Rust には、C++ ライブラリとモジュールを組み合わせたクレートがあります。 Rust には、名前空間であるモジュールもあります。Javascript エコシステムには、名前空間のように動作するモジュールで構成されたパッケージ (ライブラリ) があり、多くの場合、関数として実装されます。混乱していますか?

幸いなことに、Rust と Javascript の両方に公式または事実上の集中型パッケージ マネージャー (それぞれ cargo と npm) があります。この集中型パッケージ マネージャーは、単純なスキーム (先着順、先着順) を使用して、パッケージ名の一意性を保証します。

NPM では、パッケージ名の前に組織名 (548) を付けることができます。 )、貨物はそうではありません.これは、結局のところ、これらのコミュニティで繰り返し発生するトピックです.

自分自身を所有するライブラリ

551 を使いたいとしましょう 、2D グラフィックス、オーディオ、さらには暗号化されたネットワークを行う優れたライブラリです。Qt は 90 年代初頭に Trolltech によって開発されました。したがって、Trolltech は Qt を所有しており、会社名はかなり一意であるため、562 は一意であり、一意の名前を永久に変更します。

2008年、トロールテックはノキアに買収されました。その後、Nokia は Microsoft に買収され、Qt は Digia に買収され、Digia が Qt Company を生み出しました。一方、Qt は 572 によって管理されているオープン ソース プロジェクトでもあります。 581 のおかげで一部存在している .2012 年に、Qt のフォークから CopperSpice と呼ばれる新しいプロジェクトを作成することを決定した人もいます。

おそらく 595 を知っているでしょう .これは優れたテスト フレームワークです。しかし、Catch を作成した偉大な人物である Phil Nash を知っていますか?それ以来、多くの人々が Catch に貢献してきました。Catch は github.com/catchorg/catch2 で開発されています。 ? 617 メンテナー、明らかに!

実際、ほとんどのオープンソース ライブラリはメンテナーによって所有されています。つまり、ライブラリはすべての人が同時に所有しているのではなく、誰もが同時に所有しているわけではありません。したがって、「Catch」は 624 と呼ばれるべきです。 630 または 641 ? (おっと、655 はキーワードです!)

さらに重要なことは、プロジェクトがフォークされる可能性があることです。

Microsoft が Google の Webkit のフォークをフォークした場合、それはまだ Google のものですか? 660 と呼ぶべきか または 671 ?または単に 684 ?

Opera が Google と Microsoft の両方を買収し、すべてのモジュールと最上位の名前空間の名前が異なる場合、これら 2 つのプロジェクトを再びマージすることはできますか?

ダイヤモンドのような名前は永遠に残るため、これらは本当に懸念事項です (Microsoft に気をつけてください!)。最上位の名前空間とモジュール名はなおさらです。

トップレベルの名前空間と同様に、モジュール名は非常に侵略的であり、The Great Plague のように広まります。 、または GPL .モジュールと名前空間の両方にエイリアスを設定できます (696 を使用)

古い Java プロジェクトを見ると、700 宣言は、太陽が生態系を照らした過去の時代の地質学的記録を示しています。

API だけの問題ではなく、モジュール名を ABI の一部にすることができます。名前を変更することはできません。これまで .

将来の下位互換性を確保する

意味のある規模の依存関係マネージャーはありませんが、名前の単一性はそのようなツールの中心です。 712 たとえば、プロジェクト名を使用してパッケージを識別し、名前が一意である必要があります。一意にアドレス可能なパッケージを使用すると、多くの大きな利点と素晴らしいツールの機会が提供されます。プロジェクト名、モジュール名、およびライブラリ名の間でさらに一貫性を持たせることで、名前の衝突がなくなり、すべてのライブラリは同じプロジェクトで簡単に使用できます。

720 と入力するとブーストをダウンロードするツールを想像してみてください。 または 737 を挿入するもの 743 と入力すると .

スタンディング ドキュメントの募集

C++ 標準 非常に多くの言語がパッケージ/名前空間/モジュール/etcnaming のガイドラインを提供しており、C++ が同じことを行うことが重要だと思います.

目標は、一意の名前を強制すること (不可能であるため) や、命名スキームを過度に制限することではありませんが、より大きなエコシステムの開発を妨げるような方法で人々がプロジェクトに名前を付けないようにすることです.

C++ コア ガイドラインは検討すべき別の分野かもしれませんが、公式なものではなく、全員が同じ規則に従っている場合にのみ、一貫した命名の利点を享受できます。

ラフドラフト:

  • 異なる企業、エンティティ、およびプロジェクトのモジュールが同じモジュール名を宣言するのを防ぐために、エンティティおよび/またはプロジェクト名をモジュール名の前に付けます。
  • エクスポートされた最上位の名前空間には、エクスポート元のモジュールの名前の一部として使用されるプロジェクト名と同じ名前が必要です。
  • 複数の最上位の名前空間をエクスポートしない
  • グローバル モジュール フラグメントの外にあるグローバル名前空間のエンティティをエクスポートしないでください。
  • モジュールを階層的に編成します。 たとえば、両方のモジュールが 757 の場合 と 767 772 のパブリック API の一部として存在します 、 789 792 を再エクスポートする必要があります
  • 809 などの一般的な名前は避けてください と 810 モジュール名の接頭辞と最上位の名前空間の名前。
  • 小文字のモジュール名を使用する
  • モジュール名識別子に基本的なソース文字セット以外の文字を使用しないでください。

結論

モジュールは、C++ コミュニティに、共通のルール セットの下でエコシステムを統合するめったにない機会を提供する可能性があります。\
この一連の規則により、より最新のモジュール指向の依存関係マネージャーとツールの出現が可能になります。

モジュールの名前を変更することはできないため、これらのルールは、言語機能としてモジュールを導入する同じ C++ バージョンと共に公開する必要があります。

どう思いますか?