どちらが良いですか:選択文字列パラメータを持つゲッターの束または1つのメソッド?


15

私たちの知識領域には、素足で圧力記録プレートの上を歩く人々が含まれます。センサーデータで人間の足が認識されると、「Foot」クラスのオブジェクトを生成する画像認識を行います。

足のデータに対して実行する必要がある計算がいくつかあります。

さて、どのAPIの方が良いでしょう:

class Foot : public RecognizedObject  { 
  MaxPressureFrame getMaxPressureFrame();
  FootAxis getFootAxis();
  AnatomicalZones getAnatomicalZones();

  // + similar getters for other calculations

  // ...
}

または:

class Foot : public RecognizedObject {
  virtual CalculationBase getCalculation(QString aName);

  // ...
}

今、私が思いつくことができる多くの賛否両論がありますが、どれが最も重要かを本当に決めることはできません。これはエンドユーザーアプリケーションであり、当社が販売するソフトウェアライブラリではありません。

何かアドバイス?

最初のアプローチのプロには次のようなものがあります。

  • KISS-すべてが非常に具体的です。APIですが、実装も同様です。
  • 強く型付けされた戻り値。
  • このクラスを継承するのは簡単です。上書きすることはできず、追加するだけです。
  • APIは非常に閉じられており、何も入れられず、オーバーライドされることもありません。

いくつかの短所:

  • 新しい計算がリストに追加されるたびに、ゲッターの数が増えます
  • APIは変更される可能性が高く、重大な変更が導入された場合、新しいAPIバージョンであるFoot2が必要です。
  • 他のプロジェクトでクラスを再利用する場合、すべての計算が必要になるとは限りません

2番目のアプローチのプロ:

  • より柔軟に
  • APIは変更される可能性が低くなります(抽象化が正しいと仮定すると、変更されないとしても変更にかかるコストが高くなります)

いくつかの短所:

  • 緩やかに入力されます。すべての呼び出しでキャストが必要です。
  • 文字列パラメータ-私はそれについて悪い感情を持っています(文字列値の分岐...)
  • 追加の柔軟性を要求する現在のユースケース/要件はありませんが、将来的には存在する可能性があります。
  • APIは制限を課します。すべての計算は基本クラスから派生する必要があります。計算を取得することは、この1メソッドを介して強制されます。さらに動的で、柔軟性が高く、複雑さをさらに高めるパラメーターを渡す方法を考案しない限り、追加のパラメーターを渡すことはできません。

5
を作成し、enumその値をオンにすることができます。それでも、2番目の選択肢はKISSから逸脱しているため、悪だと思います。
ヴォラック14年

文字列パラメーターを使用してトリガーすると、特定の計算のすべての使用法を見つけるのが難しくなります。100%になるのは難しいでしょう。
コンラッドモラウスキー14年

2つの世界の最高のものを取り、たくさんのゲッターが呼び出すファサードを書きgetCalculation()ます。
nalply 14年

1
列挙型は文字列よりも間違いなく優れています!私はこれを考えていませんでした。APIを制限し、文字列パラメーター(トークンの連結やその他のがらくたのような)の乱用を防ぎます。したがって、比較は文字列ではなくenumを使用したオプション1とオプション2の間であると思います。
Bgie 14

回答:


6

私は最初のアプローチで報われると思います。マジックストリングは、次の問題を引き起こす可能性があります:入力エラー、誤用、非自明な戻り値の型の安全性、コード補完の欠如、不明瞭なコード(このバージョンはその機能を備えていましたか?実行時にわかります)。列挙型を使用すると、これらの問題の一部が解決されますが、挙げた短所を見てみましょう。

  • 新しい計算がリストに追加されるたびに、ゲッターの数が増えます

確かに、それは面倒なことがありますが、物事を厳しくし、最新のIDEのプロジェクトのどこにでもコード補完を提供し、列挙よりもはるかに便利な見出しコメントを使用できます。

  • APIは変更される可能性が高く、重大な変更が導入された場合、新しいAPIバージョンであるFoot2が必要です。

確かに、それは実際には巨大なプロです;)部分的なAPIのインターフェースを定義することができます。そして、新しいAPIの影響を受けない依存クラスを再コンパイルする必要はありません(Foot2は不要です)。これにより、デカップリングが改善され、依存関係は実装ではなくインターフェイスになりました。さらに、既存のインターフェイスが変更されると、依存クラスでコンパイルエラーが発生します。これは、古いコードを防ぐのに最適です。

  • 他のプロジェクトでクラスを再利用する場合、すべての計算が必要になるとは限りません

魔法の文字列や列挙型を使用することでそれがどのように役立つかわかりません...正しく理解できれば、コードをFootクラスに含めるか、いくつかの小さなクラスに分解します。これは両方のオプションに当てはまります。


インターフェイスを使用した部分的なAPIのアイデアが好きです。私はそれで行きます。ありがとうございました。あまりにも雑然とする必要がある場合(フットの実装が多すぎる)、いくつかの小さなアダプタークラスを使用すると、さらに柔軟になります。それぞれが1つのGUIウィジェットがそれらのすべてと連携できるようにするために...
Bgie 14

コマンドセレクターを使用する利点は、インターフェイスで提供される静的ヘルパーメソッドの呼び出しが理解できないコマンドを受け取る実装を使用できることです。コマンドが汎用アプローチを使用してほぼすべての実装で実行できるものを表しているが、一部の実装ではより良い手段で実行できる場合[考慮IEnumerable<T>.Count]、そのようなアプローチにより、コードは新しいそれらをサポートする実装を使用する場合のインターフェース機能、ただし古い実装との互換性を維持します。
supercat

12

オプション3をお勧めします:計算はの抽象化の本質的な部分ではなくFoot、それを操作することを明確にします。次にFoot、次のように、計算を個別のクラスに分割できます。

class Foot : public RecognizedObject {
public:
    // Rather low-level API to access all characteristics that might be needed by a calculation
};

class MaxPressureFrame {
public:
    MaxPressureFrame(const Foot& aFoot); // Performs the calculation based on the information in aFoot
    //API for accessing the results of the calculation
};

// Similar classes for other calculations

この方法では、計算の型付けが強力であり、既存のコードに影響を与えることなく新しい計算を追加できます(によって公開される情報の量に重大なエラーを犯さない限りFoot)。


オプション1および2よりも明らかに優れています。これは、戦略設計パターンを利用することからほんの少しの距離です。
ブライアン14年

4
これが適切な場合があります。これはやり過ぎかもしれません。計算の複雑さによって異なります。MaxPressureFrameStrategyとMaxPressureFrameStrategyFactoryを追加しますか?そして、それは足を貧血オブジェクトに変える傾向があります。
user949300 14年

これは素晴らしい代替手段ですが、この場合、依存関係を逆にすることはできません。また、足はある種のメディエーターとして機能する必要があります。別の計算が変更された場合(ユーザーがパラメーターを変更したなどの理由により)いくつかの計算を再計算する必要があるためです。
Bgie 14

@Bgie:計算間にこのような依存関係があるため、@ user116462には最初のオプションが最適であることに同意します。`-
バートヴァンインゲン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.