同じ名前で名前空間が異なる複数のクラス?


11

名前が同じで名前空間が異なるクラスを持つコード(問題がある場合はC#)を実行しました。それらはすべて同じ論理的なものを表す傾向がありますが、同じオブジェクトの異なる「ビュー」であることがよくあります。異なる名前空間は、同じソリューションの一部であり、同じdllでさえあります。

私は私の考えを持っていますが、利用可能なツールまたは回避すべきパターンの巧妙な使用と見なすために、この実践について決定的なものを見つけることができませんでした。

スマーフの命名に関するこの質問はこれに触れていますが、別の方向からです。名前の曖昧さをなくすには、恣意的で広範に及ぶ接頭辞が必要になる可能性が高いため、その質問は排除したかった。

この実践に関するガイドラインは何ですか?


1
OOPには多くの例外がありますが、特にすべてのクラスが同じレベルのアクセシビリティを共有している場合は特に、最初はこの悪い設計を検討します。任意のファイルでクラス名を読み取るとき、名前空間ディレクティブを参照する必要なしに、クラスがどの名前空間ですぐに配置されるのかを知りたいのです。
Leopold Asperger

同じ状態を処理する複数の関連オブジェクトを持つことには有効なケースがありますが、通常、それらは機能によって分離されています。たぶん、ビューのモデルを適応させる1つのオブジェクトがあるかもしれません。別のオブジェクトがオブジェクトの計算を実行する場合があります。もう1つは、アダプターまたはファサードです。あなたが持っているかもしれないのでFooAdapterFooViewerFooCalculator、など確かに同じものに名前が付けられていません。しかし、あなたが話している特定のクラスに関する詳細な情報がなければ、答えを提供することは困難です。

@JohnGaughan- Employee例として考えます。他の従業員、人事、外部暴露の従業員がいます。それらはすべて「従業員」という名前で、すべてにさまざまなヘルパー(EmployeeRepository、EmployeeViewなど)があります。それらはすべて同じdllにあり、いくつかの共通のプロパティ(名前、タイトル)を共有していますが、すべて異なります(電話番号、給与)。
Telastyn 14

Employeesを数回モデル化するシステムを使用してきたので、すべての属性の結合とtypeor department属性を含むモデルが必要であるように聞こえます。そうでなければ、コードの不必要な重複があります。

5
名前空間がそもそもの理由だったのではないでしょうか。名前の衝突を許可するには?
Dan Pichelman、2014

回答:


5

私のプロジェクトの1つでもこれを見て作業した後、そのような使用法に対する答えを出そうとします。

コードの読みやすさ

まず第一に、コードの読みやすさが重要であり、この慣行はそれに反することを考慮してください。誰かがコードを読んで、それが関数を持っているとだけ言ってみましょうdoSomething(Employee e)Employee異なるパッケージに10の異なるクラスが存在するため、最初にインポート宣言を使用して、実際の入力が何であるかを調べる必要があるため、これは読み取り可能ではなくなりました。

しかし、これは高レベルのビューであり、ランダムな名前の衝突がしばしば見受けられます。意味が残りのコードと現在のパッケージから導き出される可能性があるため、誰も気にしたり、見つけたりすることはありません。もちろん、ローカルでは問題ありません。もちろんEmployeehrパッケージ内を見ると、従業員のHRビューについて話していることを知っている必要があります。

しかし、これらのパッケージを離れるとすぐに、物事は壊れます。別のモジュール/パッケージ/その他で作業していて、従業員と作業する必要がある場合、その型を完全に修飾しないと、読みやすさが犠牲になります。さらに、10の異なるEmployeeクラスがあると、IDEのオートコンプリートは機能しなくなり、従業員のタイプから手動で選択する必要があります。

コードの複製

これらの各クラスは互いに関連しているという性質上、多くの重複によりコードが劣化する傾向があります。ほとんどの場合、従業員の名前や識別番号などがあり、各クラスでこれらを実装する必要があります。各クラスは独自の種類のビューを追加しますが、基礎となる従業員データを共有しない場合は、役に立たないがコストのかかる膨大な量のコードになってしまいます。

コードの複雑さ

あなたが尋ねるほど複雑になる可能性があるものは何ですか?結局のところ、各クラスは必要なだけシンプルに保つことができます。本当に問題になるのは、変更をどのように伝達するかです。適度に機能が豊富なソフトウェアでは、従業員データを変更できる可能性があり、それをあらゆる場所に反映したいとします。ある女性が結婚したばかりで、彼女の名前をからXに変更する必要があるとしますYそのため。あらゆる場所でこれを実行するのに十分なほど困難ですが、これらの異なるクラスをすべて持っている場合はさらに難しくなります。他の設計上の選択によっては、これは簡単に、各クラスが独自の種類のリスナーなどを実装して、変更を通知する必要があることを意味します。これは、基本的に、処理する必要があるクラスの数に適用される要素に変換されます。 。もちろん、コードの重複が多くなり、コードの可読性が低下します。このような要因は、複雑さの分析では無視できるかもしれませんが、コードベースのサイズに適用すると、厄介です。

コード通信

設計の選択にも関連する、コードの複雑さに関する上記の問題とは別に、より高いレベルの設計の明確性が低下し、ドメインの専門家と適切に通信する能力が失われます。アーキテクチャ、設計、または要件について話し合うとき、のような単純なステートメントを自由に作成できなくなりますgiven an employee, you can do ...。開発者employeeは、その時点で実際に何が意味するのかわからなくなります。もちろん、ドメインの専門家はそれを知っています。私たちは皆そうです。ちょっと。しかし、ソフトウェアに関しては、もはやコミュニケーションはそれほど簡単ではありません。

問題を取り除く方法

これを認識しつつ後とあれば、あなたのチームは取り組む問題は大きな十分であることに同意し、その後、あなたはそれに対処する方法を考え出す必要があります。通常、マネージャーにゴミを取り除くためにチーム全体に1週間の休みを与えるよう依頼することはできません。したがって、本質的には、これらのクラスを一度に1つずつ部分的に削除する方法を見つける必要があります。これに関する最も重要な部分は、チーム全体で、Employee本当に何であるかを決定することです。個々の属性のすべてを1人の神従業員に統合しないでください。中核となる従業員についてもっと考え、最も重要なこととして、そのEmployeeクラスがどこに存在するかを決定します。

コードレビューを行う場合、問題が少なくともそれ以上拡大しないことを確認することは特に簡単です。つまり、Employeeもう一度追加したい場合は、すべての人を正しい方向に止めます。また、新しいサブシステムが合意に準拠しEmployee、古いバージョンへのアクセスが許可されないように注意してください。

プログラミング言語によっては、最終的に削除されるクラスにマークを付けることもできます@Deprecated。これは、変更が必要なもので作業していることをチームがすぐに理解できるようにするためです。

古くなった従業員のクラスを取り除くことに関しては、個々のケースごとにどのようにしてそれを排除するのが最善かを決定するか、または一般的なパターンに同意することができます。クラス名を付けてそれを実際の従業員で囲むことができます。パターン(デコレーターまたはアダプターが思い浮かびます)、または、または、またはを使用できます。

長い話を簡単に言うと、この「実践」は技術的には健全ですが、将来的にのみ発生する隠れたコストで一杯になります。問題をすぐに取り除くことはできないかもしれませんが、その有害な影響を封じ込めることからすぐに始めることができます。


Coreクラスを持つことは良い解決策のようです。他のクラスはそこから拡張できます。IDEについては、オートコンプリートは、コンテキストに最も一致するように提案するクラスを知るのに十分スマートです。全体として、コードベースが内部で使用されている場合は特に、これがこのような大きな問題である理由はわかりません。
InformedA 2014

1
ある状況から外れると、それは十分に賢くはありません。問題のあるクラスの両方を実際に必要とするクラスを考えてみましょう。オートコンプリートはまったく役に立ちません。そして、これらを他の10のクラスと区別することもありません。しかし、実際の問題は、新しいチームメンバーであり、それらのパッケージドメインのすべてが実際に何であるか、そしてどれを選択するべきかさえ知らないということです。
フランク

同じ名前の複数のクラスが同じコンテキストで使用されている場合、それは困難です。私はそのケースを見たことがありません。同じ名前の複数のクラスを見てきましたが、あなたが言ったように、同じコンテキストで使用されることはあまりありません。
InformedA 2014

@randomA-残念なことに、このケースはこのコードベースではかなり一般的です。
Telastyn 2014

良い点はありますが、コア問題の解決策を実際に提供していません。コア問題が解決された後の方法論(「従業員の本当の意味」)だけです。あなたが捨てた唯一の明白な「解決策」(「個々の属性すべてを1人の神従業員に統合する」)は、正しくそうしました。あなたがDB.Employee、Marshalling.Employee、ViewModels.Employee、GUI.Views.Employeeなどを持っているとしましょう、あなたのソリューションは何ですか?
Pablo H

9

Scalaコレクションフレームワークは、この良い例です。変更可能なコレクションと不変のコレクションだけでなく、シリアルコレクションと並列コレクション(将来的には分散される可能性もある)コレクションがあります。したがって、たとえば、次の4つのMap特性があります。

scala.collection.Map
scala.collection.immutable.Map
scala.collection.mutable.Map
scala.collection.concurrent.Map

プラス3 ParMaps:

scala.collecion.parallel.ParMap
scala.collecion.parallel.immutable.ParMap
scala.collecion.parallel.mutable.ParMap

さらに興味深い:

scala.collection.immutable.Map            extends scala.collection.Map
scala.collection.mutable.Map              extends scala.collection.Map
scala.collection.concurrent.Map           extends scala.collection.mutable.Map

scala.collecion.parallel.ParMap           extends scala.collection.Map
scala.collecion.parallel.immutable.ParMap extends scala.collecion.parallel.ParMap
scala.collecion.parallel.mutable.ParMap   extends scala.collecion.parallel.ParMap

したがって、ParMapextends ParMapextends MapMapextends Mapextends Mapです。

他に何:しかし、それに直面させます、あなたはそれらを呼び出しますか?これは完全に理にかなっています。それが名前空間の目的です!


3
「それが名前空間の目的です!」=> +1
svidgen 2014

私はこれが好きですが、C#/。NETの世界では、並列クラスをParallelサブ名前空間に移動すると、ヘルパークラスSystem.Threading.Parallelと衝突します。名前空間「Concurrent」は、コレクションクラスでの「同時アクセス」を意味するためにすでに使用されているため、代わりに使用したくありませんでした。妥協案として、サブネームスペース「Parallelized」を選択しました。
redcalx

2

これは、2つの本質的に反対の答えがどちらも正しい、本当に興味深い質問です。これは、私たちのプロジェクトで行っているこのディスカッションの実例です。

@Jorgと@Frankの2つの答えを参考にして、これまでにどちらか一方の方向に進みたいという2つの非常に重要な考慮事項があると思います。

  1. 同じコードコンテキスト内で複数の同じ名前のクラスを使用する必要がある状況が予想される場合、これが同じ名前を使用しない理由です。つまり、を使用する必要hr.Employeeがあるが、を介して権限を確認する必要がある場合、security.Employee非常に煩わしくなります。
  2. 逆に、同じ名前のクラスがすべて同じまたは非常に類似したAPIを持っている場合、異なる名前空間で同じ名前を使用する必要がある場合の良い例です。Scalaの例はまさにこれで、すべてのMapクラスが同じインターフェースを実装するか、互いのサブクラスです。この場合、ユーザーはクラスまたはインターフェースのすべての実装を同じように正しく扱うことができるため、あいまいさまたは「混乱」は間違いなく良いことと呼ばれる可能性があります。これがインターフェースとサブクラスのポイントです。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.