web-dev-qa-db-ja.com

個別のゲッターではなく、列挙値を取る多目的ゲッターを使用するのはなぜですか?

私は、さまざまな値に対して約12個のゲッター関数を持つC APIを設計しています。何かのようなもの:

bool getSomeBool();
bool getSomeOtherBool();
...
int getSomeNumber();
int getSomeOtherNumber();
...

これは、それを実行する簡単な方法、実装が簡単、文書化が簡単、誤って使用するのが難しいように思えます。

ただし、OpenGLのようなAPIでは、次のような(簡略化された)何かが発生します。

typedef unsigned int GLenum;

bool glGetBool(GLenum pname);
int glGetInteger(GLenum pname);

#define GL_BLEND           0x0BE2  /* may be passed to glGetBool    */
#define GL_ACTIVE_TEXTURE  0x84E0  /* may be passed to glGetInteger */

これには、enum値が渡される関数と一致する必要があること、およびenum値が最初から有効なenum値である必要があるという明らかな欠点があります。

確かに、このアプローチにはいくつかの利点もあるのでしょうか?

拡張性が頭に浮かびます。新しい関数を追加することなく、新しい列挙値を追加できるようになりましたが、関数を追加するよりも優れているとは思いません。

5
Thomas

拡張性が頭に浮かびます。新しい関数を追加することなく、新しい列挙値を追加できるようになりましたが、関数を追加するよりも優れているとは思いません。

実際、それはdoes拡張性を促進します。

関数を追加するには、APIのクライアントがコンパイル時に常にAPIのバージョンと一致する必要があります。 enumを使用すると、適切に記述されたクライアントは、APIの新しい実装の機能を利用できるかどうかを実行時に決定できます。

これには、クライアントで利用可能な機能をクエリできるAPIを使用する、APIがサポートしていないオプションに対して既知の値を返すだけでよいなどのAPIの規則が必要です。

これは、APIが共有ライブラリに実装される場合、またはシステムによって提供されるDLL)の場合に役立ちます。それは、物事を台無しにしないようにクライアントに少し負担をかけます。

4
Adrian McCarthy

[私は推測を提供します。]

コンパイル時に、API(クライアントコード)を使用するコードは、APIから取得するパラメーターを認識していません。おそらく、パラメーターは実行時に指定されます。 APIの設計者がそのような実行時の柔軟性を実現できる1つの方法は、クライアントコードが実行時に参照できる「プロパティディクショナリ」を作成することです。

もちろん、これがそのような柔軟性を実現する唯一の方法ではありません。さらに2つ思い浮かびます:ゲッターへの関数ポインター、リフレクション(Cはリフレクションをサポートしていません)。

1
Nick Alexeev