C ライブラリでエラーを一貫した方法で処理する場合の「ベスト プラクティス」とは何でしょうか。
私が考えていた方法は2つあります。
常にエラー コードを返します。一般的な関数は次のようになります。
MYAPI_ERROR getObjectSize(MYAPIHandle h, int* returnedSize);
常にエラー ポインター アプローチを提供します。
int getObjectSize(MYAPIHandle h, MYAPI_ERROR* returnedError);
最初のアプローチを使用する場合、エラー処理チェックを関数呼び出しに直接配置する次のようなコードを記述できます。
int size;
if(getObjectSize(h, &size) != MYAPI_SUCCESS) {
// Error handling
}
これは、ここでのエラー処理コードよりも優れているように見えます。
MYAPIError error;
int size;
size = getObjectSize(h, &error);
if(error != MYAPI_SUCCESS) {
// Error handling
}
ただし、データを返すために戻り値を使用すると、コードがより読みやすくなると思います。2 番目の例では、サイズ変数に何かが書き込まれたことは明らかです。
これらのアプローチのいずれかを優先すべき理由、あるいはそれらを組み合わせたり、他のものを使用したりすべき理由について、何かアイデアはありますか? 私はグローバル エラー状態が好きではありません。ライブラリのマルチスレッド使用がはるかに困難になる傾向があるためです。
編集: 現時点では私にとっては選択肢ではないので、例外を伴わない限り、これに関する C++ 固有のアイデアも興味深いと思います...
ベストアンサー1
私は両方のアプローチを試しましたが、どちらもうまくいきました。どちらを使用する場合でも、常に次の原則を適用するようにしています。
起こり得るエラーがプログラマーのエラーだけである場合は、エラー コードを返さず、関数内でアサートを使用します。
入力を検証するアサーションは関数が期待するものを明確に伝えますが、エラー チェックが多すぎるとプログラム ロジックがわかりにくくなる可能性があります。さまざまなエラー ケースすべてに対して何をするかを決定すると、設計が非常に複雑になる可能性があります。プログラマーが null ポインターを決して渡さないようにできるのであれば、functionX が null ポインターをどのように処理するかを考える必要はありません。