web-dev-qa-db-ja.com

名前空間を持つスマーフ命名クラスの回避に関する問題

here (番号21)からsmurfネーミングという用語を引き出しました。問題をよく知らない人を救うために、Smurfの命名は、関連するクラス、変数などの束に共通の接頭辞をプレフィックスとして付ける行為なので、「SmurfAccountViewSmurfAccountDTOSmurfAccountControllerに渡します」などになります。

私がこれに対して一般的に聞いた解決策は、smurf名前空間を作成し、smurfプレフィックスを削除することです。これは一般的に私に役立ちましたが、私は2つの問題に直面しています。

  1. Configurationクラスのライブラリを使用しています。 WartmongerConfigurationと呼ぶこともできますが、Wartmonger名前空間にあるため、単にConfigurationと呼ばれます。同様に、Configurationと呼ばれるSmurfConfigurationクラスがありますが、これはSmurf名前空間にあるため、冗長です。私のコードでは、Smurf.ConfigurationWartmonger.Configurationの横に表示されている場所があり、完全修飾名を入力すると扱いにくく、コードが読みにくくなります。 SmurfConfigurationおよび(それが私のコードであり、ライブラリーではない場合)WartmongerConfigurationを処理する方が良いでしょう。

  2. 私のSmurf名前空間には、Serviceと呼ばれる可能性があるSmurfServiceというクラスがあります。 Serviceは、Smurfジョブを実行する複雑なSmurfライブラリーの上にある facade です。 SmurfServiceは、Smurf接頭辞なしのServiceが非常に汎用的であるため、より適切な名前のように見えます。 SmurfServiceはすでに一般的で役に立たない名前であり、smurfを取り除くことでこれがより明白になっただけであることを認めます。しかし、RunnerLauncherなどの名前が付けられている可能性があります。SmurfLauncherの機能はわかりませんが、Launcherの機能はわかっているので、SmurfLauncherとして「気分が良くなります」。 Smurf.Launcherの動作はSmurf.SmurfLauncherと同じくらい明白であると主張することができますが、 `Smurf.Launcherは、smurfsを起動するクラスではなく、セットアップに関連するある種のクラスであることがわかりました。

これらのいずれかに対処するためのオープンとシャットダウンの方法があれば、それは素晴らしいことです。そうでない場合、それらの煩わしさを軽減するためのいくつかの一般的な慣行は何ですか?

39
Daniel Koverman

あなたはいくつかの良い点を上げます。

  1. クラスの重複に関しては、C#でクラスにエイリアスを設定できます。たとえばusing ColorScheme = The.Fully.Qualified.Namespace.Outlook2007ColorScheme;を使用してください StackOverflowに関するこの投稿 を参照してください。あなたはあなたのプログラミング言語を示していませんが、あなたが書いたものからそれを推測しました。したがって、2つの異なるプロジェクトを扱っている場合、それらをSmurfConfigurationおよびWartmongerConfigurationとしてエイリアス化すると、両方のクラスを使用するときにあいまいさがなくなります。

  2. サービスが外部アプリケーションに公開されているので、アプリケーション名でサービスをブランド化しても問題はないようです。この場合、実際に使用しているアプリケーションのサービスのグループを明確にするため、SmurfServiceは有効です。

名前空間を使用してこのスタイルの命名を回避する必要があると思います。 MyCompanyMyProductMyAreaClassNameを読み取らずに、コードを調べて、クラスが何であるかを額面で確認することがより困難になります。エイリアシング手法を使用すると、必要に応じてあいまいさを減らすことができます。名前付けに複雑さを導入する必要があると思うのは、#2で指摘したように、人々がサービスを消費するときだけです。これは、消費者がさまざまなサービスを持っている場合、あいまいさを消費することは混乱を招く可能性があるため、この名前のスタイルを持つことは完全に理にかなっています。

16
Sam

名前空間の目的は、異なるライブラリから同じ名前のクラスを衝突させることなく使用できるようにすることです。両方から同じ名前付きクラスを使用する必要がある場合は、一方または両方に名前空間スコープをプレフィックスとして付けて、あいまいさを取り除く必要があります。

そうは言っても、Smurfがクラスについて何か具体的なことを言ったとしても、Smurfクラスがたくさんあるのはそれほど悪いことではありません。クラス名は、クラスの機能に関する情報を提供するのに十分な説明でなければなりません。

      Session
       ^   ^
      /     \
DBSession   HttpSession

同様に、DBSessionは、DBRequestオブジェクトを返すDBResponseオブジェクトを取得する場合があります。 HttpSessionは、HttpRequestおよびHttpResponseオブジェクトに対しても機能します。

これらは目的を持ったスマーフクラスです。

それらはMyCompany名前空間に住んでいる可能性がありますが、MyCompanyHttpSessionおよびMyCompanyDBSessionは以前よりも多くの情報を提供しません。この場合、Smurfを削除して名前空間にします。

MyCompany.HttpSession
26
Dave Rager

私は前にこの同じ混乱点に出くわしました、そしてそれは通常それがその名前の一部としてあるものの種類を含めることの本当に問題です。

潜在的な種類の構成としてSmurfConfigurationおよびWartmongerConfigurationについて言及します。名前空間への形容詞(その種類)を削除して、残っているのはバニラConfigurationだけであることを示しています。私はそれを避けるでしょう。

それは、ストロベリーアイスクリームがストロベリーネームスペースの単なるアイスクリームであり、チョコレートも同様であると決定するようなものですが、何が起こったのかというと、物自体からそのアイデンティティを与える形容詞を離婚したということです。いちごカテゴリーのアイスではありません。ストロベリーアイスです。一種のアイスです。

アプリでStrawberry.IceCreamクラスをインポートし、IceCreamから直接インスタンス化を開始するとします。

var ic = new IceCream(); //actually I'm strawberry ice cream

これは、別のIceCreamクラスをインポートするまでは、うまくいくように思えるかもしれません。これで、なんとかしてそれらを区別する必要があるという元の問題に戻りますが、これは問題です。あなたがずっと欲しかったのは:

var sic = new StrawberryIceCream();
var cic = new ChocolateIceCream();

名前空間は、偶然に同じ概念をライブラリで表現する可能性のあるサードパーティ間の潜在的な競合を回避するために残された方がよいでしょう。ただし、1人の開発者がライブラリまたはプロジェクトを作成するときは、各概念に一意の名前を付け、組織専用のフォルダーとして名前空間を使用する必要があります。多くの場合、フォルダーの名前は、それが整理する概念の名前に含まれていますが、それで問題ありません。

3
Mario T. Lanza

一連のクラスに共通のプレフィックスがある場合、おそらく独自の名前空間に入れるに値するというのは、絶対的な経験則です。この問題に対処するには、2つの名前空間から同様の名前のクラスを使用する必要がある場合:

1)名前空間にエイリアスを設定します。ただし、簡潔にまとめると、自然な省略形になる可能性があります。1文字でもかまいません。

using Sm = Smurf;
using W = Wartmonger;

次に、常に使用される場所にプレフィックスを付け、インスタンスに適切な名前を付けます。

Sm::Configuration smConf; 
W::Configuration wConf;

2)他の回答で提案されているように、クラスにエイリアスを付けます。

using SmConf = Smurf.Configuration;

3)ユーザーが制御できるライブラリー。「構成」という用語を使用しないことを検討してください。シソーラスを使用します。 「設定」、「モデル」、「パラメータ」。いずれにしても、コンテキストにとってより意味のあるものになる可能性があります。もしSmurfがある種の数値分析モジュールであったとしたら、おそらく「パラメータ」を記述してその構成を行う方がよいでしょう。モジュールのコンテキストに関連付けられた特定の語彙を使用して、他の名前空間に混合された場合でも一意性を保持する一意の名前を作成します。これはOPの質問2に対する答えのようなものかもしれません。

4)コードをリファクタリングして、2つの異なる場所の構成の使用を混在させる必要がないようにします。その詳細はあなた次第です。

5)クラスに渡す前に、2つの構成を1つに結合します。組み合わせたconfクラスを使用して、以下を表します。

struct Conf {
    SmurfConfiguration smurf;
    WartmongerConfiguation wart;
}

短いメンバー変数名は、クラス/名前空間にエイリアスを設定するのと同じことを実現しています。

2
Benedict

名前に1点追加すると困るのはおかしいようです。

Wartmonger.Configuration configuration = Wartmonger.Configuration .new();

// vs

WartmongerConfiguration configuration = WartmongerConfiguration.new();

SmurfWartmongerの両方の構成を1つの場所で一緒に使用するが、別々に複数の場所で使用する場合-名前空間は間違いなく良いアプローチです。

名前空間があると、内部コードで "クリーン"な名前を使用できるようになります。プレフィックスを使用すると、SmurfConfigurationの内部コード内でSmurfServiceを使用することになり、そのコードを開くたびに煩わしくなります。

1
Fabio