C ++で名前空間を使用するためのベストプラクティス[非公開]


38

ボブおじさんのクリーンコードを数か月前に読みましたが、コードの書き方に大きな影響を与えました。彼がすべてのプログラマーが知っておくべきことを繰り返しているように見えたとしても、それらをすべてまとめて実践することで、コードがずっときれいになります。特に、大きな関数を多くの小さな関数に分割し、大きなクラスを多くの小さなクラスに分割して非常に役立つことを発見しました。

さて、質問です。この本の例はすべてJavaですが、私は過去数年間C ++で働いています。Clean Codeのアイデアは、Javaには存在しない名前空間の使用にどのように拡張されますか?(はい、Javaパッケージについては知っていますが、実際には同じではありません。)

それぞれが明確に定義された責任を持つ多くの小さなエンティティを作成するというアイデアを名前空間に適用することは理にかなっていますか?関連するクラスの小さなグループは常に名前空間でラップされるべきですか?これは、多くの小さなクラスを持つ複雑さを管理する方法ですか、それとも多くの名前空間を管理するコストは法外なものでしょうか?

編集:私の質問は、このウィキペディアのPackage Principlesに関するエントリで回答されています。


7
良い、現実世界の開発者の質問のもう1つの例が閉じられました。これが開発者のベストプラクティスについて尋ねるスタック交換サイトではない場合、何ですか?
サムゴールドバーグ

@SamGoldberg:良くなりました。ここでこの質問に対する良い答えを見つけました:en.wikipedia.org/wiki/Package_Principles。リンクを投稿しただけで、コンテンツをコピー/貼り付けする時間がなかったため、この回答を投稿し、モデレーターが削除しました。
ディマ

1
質問に対する私の唯一の批評は、最後に複数の質問をするのではなく、単一の質問にまとめることだと思います。 「。
サムゴールドバーグ

回答:


22

(私はClean Codeを読んでおらず、Javaについてあまり知りません。)

それぞれが明確に定義された責任を持つ多くの小さなエンティティを作成するというアイデアを名前空間に適用することは理にかなっていますか?

はい、複数のクラスと複数の関数へのリファクタリングと同様に。

関連するクラスの小さなグループは常に名前空間でラップされるべきですか?

実際に答えずに:はい、少なくとも1つのトップレベル名前空間を使用する必要があります。これは、プロジェクト、組織、またはあなたが好きなものに基づいて行うことができますが、少数のグローバル名を使用すると、名前の競合を減らすことができます。その下にある他のすべてをグループ化する単一の名前空間は、1つのグローバル名のみを導入します。(extern "C"関数を除きますが、これはCの相互運用性のためであり、他のextern "C"関数にのみ影響します。)

関連するクラスの小さなグループを専用の名前空間でラップする必要がありますか? 多分。特に、FrobberThing、FrobberThang、FrobberDoohickeyなどのクラスで共通のプレフィックスを使用していることに気付いた場合は、名前空間(frobber :: Thingなど)を考慮する必要があります。これは、より大きなプロジェクトの一部である場合、ルート名前空間または別の名前空間の下にあります。

これは、多くの小さなクラスを持つ複雑さを管理する方法ですか、それとも多くの名前空間を管理するコストは法外なものでしょうか?

接頭辞付きの名前の上記の例を取ると、frobber :: Thingの管理はFrobberThingより難しくありません。文書化やコード補完などの一部のツールを使用するとさらに簡単になる場合があります。ADLには違いがありますが、これは有利です。関連付けられた名前空間の名前が少ないため、ADLの把握が簡単になり、宣言を使用して特定の名前を1つの名前空間に挿入できます。

名前空間エイリアスを使用すると、特定のコンテキストで長い名前空間に短い名前を使用できます。これにより、再び簡単に使用できるようになります。

void f() {
  namespace CWVLN = Company_with_very_long_name;  // Example from the standard.
  // In this scope, use CWVLN::name instead of Company_with_very_long_name::name.
  namespace fs = boost::filesystem;  // Commonly used.
}

さまざまなライブラリーに対して、単一のルート名前空間、ブースト、そして多くのサブ名前空間(boost :: asio、boost :: io、boost :: filesystem、boost :: tuplesなど)を持つBoostを検討してください。 一部の名前は、ルート名前空間に「昇格」されます。

すべての定義は名前空間:: boost :: tuplesにありますが、最も一般的な名前は、宣言を使用して名前空間:: boostに引き上げられます。これらの名前は、tuple、make_tuple、tieおよびgetです。さらに、refおよびcrefは:: boost名前空間で直接定義されます。

「実際の」モジュールを備えた言語との最大の違いは、よりフラットな構造を使用することです。これは、ネストされた名前を定義するための特別な努力をしない限り機能するためです。


完全な分析のために、1行の回答ではなく+1 @Fred Nurk。質問の内容を知るために本を読む必要はありません。このコメントスレッドは、C ++およびJavaプログラマーがこの本で持っている概念と相違点を公開します。Amazonのクリーンコードコメント
マーロン

8

すべてのコードに対して1つのマスター名前空間が必要です。これにより、名前空間に関して外部コードと区別されます。

マスター名前空間内で、サイズと複雑さに応じて、サブ名前空間を開くことができます。これは、コンテキスト内で名前が明確に意味する場所であり、異なるコンテキスト内で同じ名前が使用される場合があります。

特に、コンテキスト内で特定の何かを意味するFileInfoのような一般的なサウンド名がある場合は、名前空間に配置します。

これにはクラスを使用することもできますが、クラスは拡張できないため、ヘッダーを変更しないとクラスに新しい宣言を追加できません。


3

名前空間はモジュールの概念ではないため、名前の競合が発生する可能性がある場合にのみ使用します。


4
よく分からない。名前空間にラップされた関連クラスのセットがモジュールではないのはなぜですか?
ディマ

名前空間内に制限はありません。モジュールでは、特定のクラス、関数、または変数はモジュールの内部からのみアクセスできると言えます。名前空間ではこれは不可能であり、名前の接頭辞にすぎません。
ブレインラグ

3
モジュールの定義に私たちが同意していないようです。私にとって、関連するエンティティをグループ化し、わかりやすい名前を持つものは、カプセル化を提供するかどうかに関係なく、モジュールです。
ディマ

3
アクセス制限はモジュールに直交しています。実際、Pythonのような成功したシステムがあり、C ++の名前空間よりも「モジュールに似ています」が、アクセス制限をまったく課していません。
フレッドナーク

これはスコット・マイヤーの本に記載されているベストプラクティスの1つであると考えています。
ラファエル

1

Javaには名前空間がありますが、実際にはそう呼ばれていません。In javax.swing.* javaxは名前空間でswingあり、サブ名前空間です。私はこの本を読んでjavaパッケージについて何を言っているのかを知りませんでしたが、同じ原則はどの言語の名前空間にもほとんど直接当てはまります。

優れたヒューリスティックは、クラスに何度も同じプレフィックスを入力したいときにネームスペースを使用することです。たとえば、最近OmciAttribute、OmciAlarm、OmciMeなどと呼ばれるクラスをいくつか作成し、Omciを独自の名前空間に分割する必要があることに気付きました。


1

深い名前空間(通常は3つのレベルを意味します)が好きです。

  • 会社名があります。
  • app / util / lib / etc
  • 適切なプロジェクト名/またはパッケージ

状況に応じて、もう1つレベルがあります

  • 詳細(プラットフォーム固有の実装の詳細)
  • utils(まだ一般的なユーティリティに移動されていないユーティリティオブジェクト)。
  • 必要なものは何でも。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.