このクラスを開閉するのが難しい


8

これが私の問題です。ゲームパッド、よくレースする、ジョイスティックなど、さまざまなHIDデバイスからの入力を読みたいのですが、ほとんどすべてのゲームコントローラです。問題は、それらすべてに異なる入力があることです。

ゲームパッドにはボタン、スイッチ、スティックがあり、レースウェルにはギアスティックが付いている場合があります。これらのさまざまなコンポーネントをすべて3つに抽象化して、可能なすべての組み合わせを持つ基本クラスを作成するのではなく、

abstract class Device
    {
    public Buttons Buttons;
    public Axes Axes;
    public Switches Switches;
    public GearSticks GearSticks;
    //many more
    }

私は今持つことができます:

abstract class Device
{
public Buttons Buttons;   //on or off
public Axes Axes;         //range [-100%:100%]
public Switches Switches; //multiple states
}

すべての入力を3種類に抽象化できるため、すべての具体的な実装を介して拡張に対して開かれている間、クラスを閉じたままにできるため、最初はこれに満足しました。

しかしその後、私は自分自身にかかわらず、私は避けられないが遅延していた場合にどのような?ある日Deviceクラスに別のフィールドを追加する必要がある場合はどうなりますか?トラックボールのようなものはサポートしていません!

このクラスを将来証明できる方法はありますか?私がそれを見る方法では、私はこのようなものになるでしょう:

public Device1 : Device
{
//buttons
//trackball
}

public Device2 : Device
{
//Switch
//Axis
}

public Device3 : Device
{
//trackball
//switch
}

また、実装する何か新しいものがあるたびに、基本クラスにプロパティを追加し続ける必要があります。


このようなクラスを将来にわたって完全に保証する唯一の方法は、キーと値のペアを文字列として格納し、プロトコルバッファーなどのある種のタイプのないプロトコルでクラスの周りに値を渡すことです。しかし、HIDはそれよりも具体的です。どのプラットフォームにいますか?このプロセスを容易にするヘルパーライブラリがいくつかあります。これが.NET Frameworkの1つです:github.com/mikeobrien/HidLibrary。または、これ:github.com/jcoenraadts/hid-sharp
Robert Harvey

これは優れたソフトウェアエンジニアリングの質問であり、なぜあなたが反対票を投じたのかはわかりません。
Doc Brown、

@RobertHarveyあなたがキーと値のペアを言ったとき、私の心の中で何かが意味を持ち始めましたが、タイプレスプロトコルとはどういう意味ですか?私はUWPプラットフォームにいます。
Mihai Bratulescu 2018

:型なしプロトコルは、URLを使用するものと同様、文字列のペアに完全に動作するものであるparameter1=value1&parameter2=value2、など
ロバート・ハーヴェイ

回答:


7

これは、abstractのような概念InputChannelと、構成可能な入力チャネルのリストを持つデバイスを導入することで実現できると確信しています。入力チャネルには名前、タイプ、おそらくメタデータがあり、そのタイプに適合する「状態」を生成できる必要があります。ボタン、斧、スイッチなどの事前定義されたチャネル、または現在知らないいくつかの新しいチャネルがある可能性があります(ただし、新しいInputChannel子クラスを導入することで後で追加される場合があります)。

このように、デバイスはある種のメタモデルになり、デバイスの入力チャネルのリストに対応する必要があるデバイスの状態を管理する方法も必要になります。

ただし、そのような一般的なアプローチには、オーバーエンジニアリングのリスクがあります。これは、内部プラットフォーム効果としても知られています。たとえば、このような汎用デバイスに特定の機能を追加したり、特定のイベントや、異なる入力チャネル間の相互作用を追加したりするのは簡単ではない場合があります。また、汎用デバイスライブラリのユーザーにとっては、使用や理解が難しい場合もあります。

可能な限り抽象的なソリューションを作成することが常に有益であるとは限らないことに注意してください。ハードウェアの要件を変更するには、通常、対応するソフトウェアよりもハードウェア自体に実装するのに多くの労力が必要です。そのため、多くの場合、ソフトウェアのより具体的なソリューションに固執し、必要に応じてソフトウェアを変更することをお勧めします。


InputChannel缶の仕事は、私はそれを行うために必要なのは、それの状態を更新し、高めることですonChangedEvent。しかし、あなたは過剰なエンジニアリングについて正しいかもしれません...私はこれを覚えておきます。時々クラスに別のフィールドを追加することは許容できると思いますか?
Mihai Bratulescu 2018

1
@MihaiBratulescu:作成するソフトウェアの種類によって異なります-自分またはチームのゲームフレームワークで、ユースケースがわかっていて、要件が変更されたときに対応できる場合や、Qtや.Netフレームワークなどの一般的なフレームワーク予期せぬ状況で何十万人もの開発者が使用しています。後者の場合、非常に一般的なSOLIDソリューションが前者よりもはるかに重要です。
Doc Brown

道標-次の目的地、トワイライトゾーン「このライブラリのサポートは非​​常に制限されています。非常に多くのデバイスと構成に関する問題のトラブルシューティングはほとんど不可能です。」 これはhidLibrary @RobertHarvey refsによるものです。統一された場の理論
レーダーボブ

3

オープンクローズの原則の背後にある考え方は、既存のクラスを変更するのではなく、継承を通じて新しい機能を実装する場合、既存の機能を壊す可能性が低いということです。そして、あなたはHidから継承することでそうすることができます。1年と2、3か月で、Hidを継承し、2019年の第4四半期に発明されるトラックボールのサポートを追加するHid2020を作成できます。2023年にスクイーズ検出器が発明されて普及した後、次のようなHid2024クラスを作成できます。 Hid2019の子孫です。

それは防御的なアプローチでしょう。しかし、それはまた、クリーンなデザインの観点から少しずさんなものになります。あなたの場合、私は違反しているOによって眠りを失うことはなく、あなたの周りの世界が変化するにつれて基本クラスを変更するだけです。トラックボールやその他の新しいタイプのコントロールの実装が、ボタンの押下を処理したり、ステータスの変更を切り替えたりする方法に影響するようには見えません。


2番目の段落の同上。コヒーレントなデザインが重要です。そして、首尾一貫して言えば、O / Cはここですでにその目的を果たしています。おそらくO / Cを考慮すると、おそらく設計が不十分なために、クラスが頻繁に開かれる(変更される)ことに気付くでしょう。IMOこれは、オープン/クローズド原則の存在理由です。
レーダーボブ2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.