オブジェクト指向設計のアドバイスを探しています


12

私は産業環境でバルブを開閉するために使用されるアプリを開発しており、このような単純なことを考えていました:-

public static void ValveController
{
    public static void OpenValve(string valveName)
    {
        // Implementation to open the valve
    }

    public static void CloseValve(string valveName)
    {
        // Implementation to close the valve
    }
}

(実装は、バルブを制御するためにシリアルポートに数バイトのデータを書き込みます-バルブ名から派生した「アドレス」、およびバルブを開閉する「1」または「0」)。

別の開発者は、代わりに物理的なバルブごとに個別のクラスを作成するかどうかを尋ねました。のようなコードを書く方が良いと思いますPlasmaValve.Open()ValveController.OpenValve("plasma")、これはやり過ぎですか?

また、私はいくつかの仮説的な将来の要件を念頭に置いて設計に取り組む最善の方法を疑問に思っていました:

  1. バルブの開閉に異なる値を必要とする新しいタイプのバルブ(0と1ではありません)をサポートするよう求められています。
  2. 単に「開く」または「閉じる」のではなく、0〜100の任意の位置に設定できるバルブをサポートする必要があります。

通常、この種のことには継承を使用しますが、最近、「継承を超える構成」に頭を悩まし始め、構成を使用するスリッカーソリューションがあるのではないかと考え始めました。


2
特定のバルブ(文字列ではなく、おそらく列挙型)の識別子と、OpenValve / CloseValveメソッド内の制御フローに必要な情報を持つ汎用バルブクラスを作成します。あるいは、valvクラスを抽象化し、それぞれに個別の実装を行うこともできます。この場合、開閉バルブは、異なるバルブに異なる開閉機構があるイベントに対して、指定されたバルブクラス内のロジックを呼び出すだけです。共通のメカニズムは、基本クラスで定義されます。
ジミー・ホッファ

2
将来の仮想要件について心配する必要はありません。ヤグニ。
pdr

3
@pdr YAGNIは両刃のブレードです。一般的にはフォローする価値があると思いますが、極端に言えば、将来の保守性や可読性を支援するために何かをすることはYAGNIに違反していると言えます。たくさんの。そうは言っても、多くの人々は、YAGNIをどこで使用し、どこでそれを投げるのかを認識しています。将来を考慮すれば、深刻な痛みが軽減されるからです。あなたが彼らがそのスペクトルのどこに着くかわからないとき、人々がYAGNIに従うことを提案することは慎重にすべきだと思う。
ジミー・ホッファ

2
男、「相続に対する構成」は過大評価されています。Valve抽象クラス/インターフェースを作成し、それらをPlasmaValveにサブクラス化します。そして、ValveControllerがValveで動作することを確認し、それらが正確にどのサブクラスであるかを気にしません。
MrFox

2
@suslik:もちろんです。また、固い原則を理解していない人々によって、スパゲッティと呼ばれる優れたコードを見てきました。これで永遠に続けることができました。私の要点は、長年の経験から生まれた確立された原則を手に負えないことによって引き起こされる問題は、過度の遵守によって引き起こされるものよりも多く見られるということです。しかし、私は両方の極端が危険であることに同意します。
pdr

回答:


12

バルブオブジェクトの各インスタンスがこのValveControllerと同じコードを実行する場合、単一のクラスの複数のインスタンスが適切な方法であるように思われます。この場合、バルブオブジェクトのコンストラクターで制御するバルブ(および方法)を設定するだけです。

ただし、各バルブコントロールの実行に異なるコードが必要であり、現在のValveControllerがバルブのタイプに応じて異なる処理を行う巨大なswitchステートメントを実行している場合、ポリモーフィズムの再実装が不十分です。その場合、共通のベース(それが理にかなっている場合)を使用して複数のクラスに書き換え、単一の責任原則を設計ガイドにします。


1
タイプベースのswitchステートメントをコードの匂いとして言及するための+1。開発者がKISSをフォローしているだけだと主張するようなswitchステートメントを頻繁に見ます。設計原理は倒錯あわやことができる方法の完璧な例
ジミー・ホッファ

2
複数のインスタンスを使用すると、シーケンス内のバルブをリンクしやすくなり、実際のプラントの配管をコード内の有向グラフとしてモデル化できます。また、圧力の蓄積を避けるために別のバルブが閉じたときに1つのバルブを開く、または「ウォーターハンマー」効果が得られないようにすべてのダウンストリームバルブを閉じるなどの操作が必要な場合は、クラスにビジネスロジックを追加することもできますバルブが再び開かれたとき。
TMN

1

私の主な不満は、バルブを識別するパラメーターに文字列を使用していることです。

少なくとも、基礎となる実装に必要な形式のValveクラスを作成し、getAddressそれらを渡して、ValveController存在しないバルブを作成できないようにします。これにより、openメソッドとcloseメソッドのそれぞれで間違った文字列を処理する必要がなくなります。

オープンとクローズを呼び出す便利なメソッドを作成するかどうかはあなた次第ValveControllerですが、正直に言うと、シリアルポートへのすべての通信(エンコードを含む)は、必要に応じて他のクラスが呼び出す単一のクラスに保持します。これは、新しいコントローラーに移行する必要がある場合、1つのクラスのみを変更する必要があることを意味します。

テストが好きな場合はValveController、シングルトンを作成して、モック(またはオペレーター用のトレーニングマシンを作成)できるようにする必要があります。


これまでに、テストのためにシングルトンを推奨する人は誰もいませんでした。通常は逆です。
カザーク

正直なところ、シングルトンは静力学を避けるためのものであり、したがって通信を同期することができます
ラチェットフリーク
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.