私たちの知識領域には、圧力記録プレートの上を素足で歩く人々が含まれます。センサーデータで人間の足が認識された場合、「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);
// ...
}
さて、思いつくことのできるプロとコンはたくさんありますが、どれが最も重要であるか本当に決めることはできません。これはエンドユーザーアプリケーションであり、販売しているソフトウェアライブラリではありません。
何かアドバイス?
最初のアプローチのいくつかのプロは次のようになります:
いくつかの短所:
2番目のアプローチのいくつかのプロ:
いくつかの短所:
最初のアプローチで成果が上がると思います。マジックストリングは次の問題を引き起こす可能性があります:入力ミス、誤用、重要な戻り値の型安全性、コード補完の欠如、コードの不明確(このバージョンにその機能はありましたか?実行時に確認します)。列挙型を使用すると、これらの問題のいくつかが解決されますが、発生した短所を見てみましょう。
確かに、これは煩わしいかもしれませんが、物事を適切かつ厳密に保ち、列挙型よりもはるかに有用な優れた見出しコメントを付けて、プロジェクトのどこでも最新のIDEでコードを補完できます。
確かに、しかしそれは実際には巨大なプロです;)あなたは部分的なAPIのためのインターフェースを定義することができ、それからあなたは新しいAPIの影響を受けない依存クラスを再コンパイルする必要はありません(従ってFoot2の必要はありません)。これにより、より良い分離が可能になり、依存関係は実装ではなくインターフェースになりました。さらに、既存のインターフェイスが変更されると、依存クラスでコンパイルエラーが発生し、古くなったコードを防ぐのに役立ちます。
マジックストリングまたは列挙型の使用がそれでどのように役立つかわかりません...正しく理解できれば、コードをFootクラスに含めるか、それをいくつかの小さなクラスに分割して、両方のオプションに当てはまります。
オプション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
によって公開された情報量に重大なエラーがない限り)。