私は物理デバイスを扱うプロジェクトで作業していますが、このプロジェクトのクラスに適切な名前を付ける方法に戸惑っています。
実際のデバイス(センサーとレシーバー)が1つであり、ソフトウェアでのそれらのrepresentationは別のものであることを考慮して、「Info」サフィックス名パターンでいくつかのクラスに名前を付けることを考えています。
たとえば、Sensor
は実際のセンサーを表すクラスですが(実際に動作しているデバイスに接続されている場合)、SensorInfo
はそのようなセンサーの特性のみを表すために使用されます。たとえば、ファイルを保存するときに、SensorInfo
をシリアル化する代わりに、Sensor
をファイルヘッダーにシリアル化します。
しかし、オブジェクトのライフサイクルの中間点があり、どちらを使用するか、またはどのようにして別のものから取得するか、または両方のバリアントを実際に1つのクラスのみに折りたたむ必要があるかどうかさえ決定できないため、今は混乱しています。
また、あまりにも一般的すぎるEmployee
クラスの例は明らかに実在の人物の表現にすぎませんが、私の知る限り、代わりにクラスにEmployeeInfo
という名前を付けることは推奨されません。
私が使用している言語は.NETです。この命名パターンは、これらのクラスの例として、フレームワーク全体で共通しているようです。
Directory
およびDirectoryInfo
クラス。File
およびFileInfo
クラス。ConnectionInfo
class(対応するConnection
クラスなし);DeviceInfo
クラス(対応するDevice
クラスなし);だから私の質問です:この命名パターンの使用についての一般的な根拠はありますか?名前のペア(Thing
とThingInfo
)を使用することが理にかなっている場合と、ThingInfo
クラスまたはThing
クラス、対応するクラスなし?
「情報」は誤称だと思います。オブジェクトには状態とアクションがあります。「info」は、すでにOOPに組み込まれている「state」の別名です。
あなたは何ですか本当にここでモデル化しようとしていますか?他のコードがハードウェアを使用できるように、ハードウェアをソフトウェアで表すオブジェクトが必要です。
言うのは簡単ですが、ご存知のとおり、それだけではありません。 「ハードウェアを表す」というのは驚くほど幅広い。これを行うオブジェクトには、いくつかの懸念があります。
センサーなどの特定のデバイスは、プリンター/スキャナー/ファックスの多機能デバイスと言うよりも問題が少ないでしょう。センサーはおそらくビットストリームを生成するだけですが、複雑なデバイスには複雑なプロトコルと相互作用がある場合があります。
とにかく、特定の質問に戻りますが、特定の要件とハードウェアの相互作用の複雑さに応じて、これを行う方法がいくつかあります。
以下は、温度センサーのクラス階層を設計する方法の例です。
ITemperatureSource:温度データを生成できるあらゆるものを表すインターフェイス:センサー。ファイルラッパーやハードコードされたデータ(たとえば、模擬テスト)でもかまいません。
Acme4680Sensor:ACMEモデル4680センサー(ロードランナーが近くにあることを検出するのに最適)。これは複数のインターフェースを実装する場合があります。おそらく、このセンサーは温度と湿度の両方を検出します。このオブジェクトには、「センサーが接続されていますか?」などのプログラムレベルの状態が含まれています。そして「最後の読みは何でしたか?」
Acme4680SensorComm:物理デバイスとの通信に使用solelyそれは多くの状態を維持しません。メッセージの送受信に使用されます。ハードウェアが理解するメッセージごとにC#メソッドがあります。
HardwareManager:デバイスの取得に使用されます。これは基本的にインスタンスをキャッシュするファクトリです。ハードウェアデバイスごとにデバイスオブジェクトのインスタンスは1つだけです。スレッドAがACME温度センサーを要求し、スレッドBがACME湿度センサーを要求する場合、これらは実際には同じオブジェクトであり、両方のスレッドに返される必要があることを認識するのに十分スマートでなければなりません。
トップレベルでは、ハードウェアタイプごとにインターフェイスがあります。これらは、C#データ型を使用して、C#コードがデバイスで実行するアクションを記述します(たとえば、rawデバイスドライバーが使用する可能性があるバイト配列).
同じレベルで、ハードウェアタイプごとに1つのインスタンスを持つ列挙クラスがあります。温度センサーは1つのタイプで、湿度センサーは別のタイプです。
この1つ下のレベルは、これらのインターフェースを実装する実際のクラスです。これらは、上記で説明したAcme4680Sensorに似た1つのデバイスを表します。デバイスが複数の機能を実行できる場合、特定のクラスは複数のインターフェイスを実装できます。
各デバイスクラスには、ハードウェアと通信する低レベルのタスクを処理する独自のプライベート通信(通信)クラスがあります。
ハードウェアモジュールの外では、表示される唯一のレイヤーは、インターフェイス/列挙型とHardwareManagerです。 HardwareManagerクラスは、デバイスクラスのインスタンス化を処理し、インスタンスをキャッシングするファクトリアブストラクションです(インスタンスreallyは、2つのデバイスクラスが同じハードウェアデバイスと通信することを望まない)など。特定のタイプを必要とするクラスセンサーのハードウェアは、特定の列挙型のデバイスを取得するようにHardwareManagerに要求します。これにより、デバイスがすでにインスタンス化されているかどうか、作成されていない場合は初期化する方法などがわかります。
ここでの目標は、低レベルのハードウェアロジックからビジネスロジックを分離することです。画面にセンサーデータを出力するコードを記述している場合、そのコードは、使用しているセンサーの種類を気にする必要はありませんif if only if ifこの分離は、これらのハードウェアインターフェイスを中心としています。
注:ハードウェアマネージャーと各デバイスクラスの間には、図が矢印のスープになってしまったため描画しなかった関連付けがあります。
これらのクラスはいくつかの名前空間に分散しているため、ここで単一の統一規則を見つけるのは少し難しいかもしれません(ConnectionInfo
はCrystalDecisions
にあり、DeviceInfo
はSystem.Reporting.WebForms
)。
ただし、これらの例を見ると、サフィックスには2つの異なる使用法があるようです。
静的メソッドを提供するクラスとインスタンスメソッドを提供するクラスを区別します。これは、System.IO
クラスの場合で、その説明で下線が引かれています。
ディレクトリ :
ディレクトリおよびサブディレクトリを作成、移動、および列挙するための静的メソッドを公開します。このクラスは継承できません。
ディレクトリとサブディレクトリを作成、移動、列挙するためのインスタンスメソッドを公開します。このクラスは継承できません。
Info
は、ここでは少し奇妙な選択のように見えますが、違いは比較的はっきりしています。Directory
クラスは、特定のディレクトリを表すか、状態を保持せずに一般的なディレクトリ関連のヘルパーメソッドを提供できます一方、DirectoryInfo
は実際には前者にすぎません。
クラスが情報のみを保持し、動作を提供しないことを強調これは接尾辞のない名前から合理的に予想される。
その文の最後の部分は、たとえばConnectionInfo
とEmployeeInfo
を区別するパズルのピースかもしれないと思います。 Connection
というクラスがある場合、実際に接続が持つ機能を実際に提供すると期待します。void Open()
などのメソッドを探しています。ただし、 Employee
クラスが実際に実際のEmployee
と同じことを実行したり、void DoPaperwork()
やbool TryDiscreetlyBrowseFacebook()
のようなメソッドを探したりすることを期待する人はいないでしょう。
一般に、Info
オブジェクトは、オブジェクトの状態に関する情報をカプセル化しますある時点で。ファイルを見て、そのサイズに関連付けられたFileInfo
オブジェクトをシステムに与えるようにシステムに要求した場合、そのオブジェクトは、要求が与えられたとき(または、より正確には、呼び出しが行われてから戻るまでのある時点でのファイルのサイズ)。リクエストが返されてからFileInfo
オブジェクトが検査されるまでの間にファイルのサイズが変更される場合、私はnotがそのような変更がFileInfo
オブジェクト。
この動作はFile
オブジェクトの動作とは非常に異なることに注意してください。非排他モードでディスクファイルを開く要求により、File
プロパティを持つSize
オブジェクトが生成された場合、ディスクファイルのサイズが変化すると、返される値が変化することが期待されます。 File
オブジェクトはファイルの状態を表すだけではなく、ファイル自体を表します。
多くの場合、リソースに接続するオブジェクトは、サービスが不要になったときにクリーンアップする必要があります。 *Info
オブジェクトはリソースにアタッチされないため、クリーンアップは必要ありません。その結果、Info
オブジェクトがクライアントの要件を満たす場合は、基になるリソースを表すオブジェクトを使用するよりも、コードが1を使用する方が、そのリソースへの接続がクリーンアップする必要があります。
実際のデバイス(センサーとレシーバー)が1つであり、ソフトウェアでのそれらの表現が別のものであることを考えると、「情報"サフィックス名パターン。
たとえば、
Sensor
は実際のセンサーを表すクラスですが(実際に動作しているデバイスに接続されている場合)、SensorInfo
はそのようなセンサーの特性のみを表すために使用されます。たとえば、ファイルを保存するときに、SensorInfo
をシリアル化する代わりに、Sensor
をファイルヘッダーにシリアル化します。
この区別は好きではありません。すべてのオブジェクトは「ソフトウェアでの表現」です。それが「オブジェクト」という言葉の意味です。
さて、ペリフェラルに関する情報を、ペリフェラルとインターフェースする実際のコードから分離することは意味があるかもしれません。したがって、たとえば、Sensorには、ほとんどのインスタンス変数とハードウェアを必要としないいくつかのメソッドを含むSensorInfoがありますが、Sensorクラスは実際の物理センサーとの対話を担当します。コンピューターにセンサーがない限り、Sensor
はありませんが、SensorInfo
を持っている可能性があります。
問題は、この種の設計を(ほぼ)すべてのクラスに一般化できることです。したがって、注意する必要があります。たとえば、SensorInfoInfo
クラスは明らかにありません。また、Sensor
変数がある場合、SensorInfo
メンバーとやり取りすることで Demeterの法則 に違反する可能性があります。もちろん、これは致命的ではありませんが、API設計はライブラリ作成者だけのものではありません。独自のAPIをクリーンでシンプルに保つと、コードはより保守しやすくなります。
私の意見では、ディレクトリのようなファイルシステムリソースは、このEdgeに非常に近いと言えます。ローカルでアクセスできない、真のディレクトリを記述したい場合がありますが、平均的な開発者はおそらくそのような状況の1つではありません。このようにクラス構造を複雑にすることは、私の意見では役に立ちません。 pathlib
でのPythonのアプローチとの対比:「必要なものが最もありそうな」単一のクラスと、ほとんどの開発者が安全に無視できるさまざまな補助クラスがあります。ただし、本当に必要な場合は、具体的なメソッドを取り除いただけで、ほとんど同じインターフェースが提供されます。
高レベルのビジネスロジックコードと低レベルのモデル、アーキテクチャコンポーネントなどがあるので、コンテキスト/ドメインは重要だと思います...
「情報」、「データ」、「マネージャー」、「オブジェクト」、「クラス」、「モデル」、「コントローラー」などは、すべてのオブジェクトが何らかの情報またはデータを持っているため、特に下位レベルでは臭いサフィックスになることがあります。その情報は必要ありません。
ビジネスドメインのクラス名は、変に聞こえたり、100%正しい言語ではない場合でも、すべての利害関係者が話し合うようにする必要があります。
データ構造の適切なサフィックスは、たとえば「リスト」、「マップ」、および必要と思われる場合のヒントパターン「デコレータ」、「アダプタ」などです。
センサーのシナリオでは、SensorInfo
がセンサーを保存することは期待していませんが、SensorSpec
です。 Info
imhoはFileInfo
がサイズなどの派生情報である、保存しない、またはパスとファイル名から構築されるファイルパスなど.
別のポイント:
コンピュータサイエンスには、キャッシュの無効化と名前付けという2つの難しいことしかありません。
-フィルカールトン
それはいつも私にほんの数秒間名前について考えることを思い出させます、そして私が何も見つけなかったならば、私は奇妙な名前を使ってそれらに「TODO」マークを付けます。 IDEはリファクタリングのサポートを提供するため、後でいつでも変更できます。これは、企業のスローガンではなく、適切である必要があるたびに変更できるコードです。そのことを覚えておいてください。
これまでのところ、この質問の誰も、この命名規則の本当の理由を理解していないようです。
DirectoryInfo
はtheディレクトリではありません。それはa DTOであり、データaboutがディレクトリにあります。同じディレクトリを表すそのようなインスタンスが多数存在する可能性があります。それは実体ではありません。使い捨ての値オブジェクトです。 DirectoryInfo
は実際のディレクトリを表すものではありません。ディレクトリのハンドルまたはコントローラと考えることもできます。
Employee
という名前のクラスとは対照的です。これはORMエンティティオブジェクトである可能性があり、その従業員を説明する単一のオブジェクトです。 IDのない値オブジェクトの場合は、EmployeeInfo
と呼ぶ必要があります。 Employee
は実際に実際の従業員を表しています。 EmployeeInfo
と呼ばれる値のようなDTOクラスは、明らかに従業員を表すのではなく、従業員を表すか、従業員に関するデータを格納します。
実際には、両方のクラスが存在するBCLの例があります。ServiceController
は、Windowsサービスを記述するクラスです。各サービスには、このようなコントローラがいくつあってもかまいません。 ServiceBase
(または派生クラス)isは実際のサービスであり、個別にサービスの複数のインスタンスを持つことは概念的に意味がありませんサービス。
ThingInfoは、Thingの優れた読み取り専用プロキシとして機能します。
参照してください http://www.dofactory.com/net/proxy-design-pattern
プロキシ:「別のオブジェクトにアクセスを制御するためのサロゲートまたはプレースホルダーを提供します。」
通常、ThingInfoにはセッターのないパブリックプロパティがあります。これらのクラスとクラスのメソッドは安全に使用でき、バッキングデータ、オブジェクト、またはその他のオブジェクトへの変更をコミットしません。状態の変化やその他の副作用は発生しません。これらは、レポートやWebサービス、またはオブジェクトに関する情報が必要だが実際のオブジェクト自体へのアクセスを制限したい場所で使用できます。
可能な限りThingInfoを使用し、実際のThingの使用を、Thingオブジェクトを実際に変更する必要がある時間に制限します。このパターンに慣れると、読み取りとデバッグがかなり速くなります。