現在公開APIが次のようになっているライブラリを評価しています。
libengine.h
/* Handle, used for all APIs */ typedef size_t enh; /* Create new engine instance; result returned in handle */ int en_open(int mode, enh *handle); /* Start an engine */ int en_start(enh handle); /* Add a new hook to the engine; hook handle returned in h2 */ int en_add_hook(enh handle, int hooknum, enh *h2);
enh
は、いくつかの異なるデータ型(エンジンとフック)へのハンドルとして使用される汎用ハンドルであることに注意してください。
内部的には、これらのAPIのほとんどはもちろん、「ハンドル」を内部構造にキャストしますmalloc
。
engine.c
struct engine { // ... implementation details ... }; int en_open(int mode, *enh handle) { struct engine *en; en = malloc(sizeof(*en)); if (!en) return -1; // ...initialization... *handle = (enh)en; return 0; } int en_start(enh handle) { struct engine *en = (struct engine*)handle; return en->start(en); }
個人的にはtypedef
、特に型の安全性を損なう場合、背後にあるものを隠すことは嫌いです。(与えられたenh
、それが実際に何を参照しているかをどのように知るのですか?)
そこで、次のAPIの変更を提案するプル要求を送信しました(準拠するようにライブラリ全体を変更した後)。
libengine.h
struct engine; /* Forward declaration */
typedef size_t hook_h; /* Still a handle, for other reasons */
/* Create new engine instance, result returned in en */
int en_open(int mode, struct engine **en);
/* Start an engine */
int en_start(struct engine *en);
/* Add a new hook to the engine; hook handle returned in hh */
int en_add_hook(struct engine *en, int hooknum, hook_h *hh);
もちろん、これにより、内部API実装の外観が大幅に改善され、キャストが排除され、消費者の観点からの型安全性が維持されます。
libengine.c
struct engine
{
// ... implementation details ...
};
int en_open(int mode, struct engine **en)
{
struct engine *_e;
_e = malloc(sizeof(*_e));
if (!_e)
return -1;
// ...initialization...
*en = _e;
return 0;
}
int en_start(struct engine *en)
{
return en->start(en);
}
私は次の理由でこれを好みます:
- 型の安全性を追加
- 型とその目的の改善された明瞭さ
- キャストと
typedef
sを削除しました - Cの不透明(OPAQUE)型の推奨パターンに従います
ただし、プロジェクトの所有者はプルリクエストを拒否しました(言い換え)。
個人的には、を公開するという考えは好きではありません
struct engine
。私は今でも、現在の方法はよりクリーンでよりフレンドリーだと思います。最初はフックハンドルに別のデータ型を使用していましたが
enh
、useに切り替えることで、すべての種類のハンドルが同じデータ型を共有してシンプルにしています。これがわかりにくい場合は、別のデータ型を使用できます。他の人がこのPRについてどう思うか見てみましょう。
このライブラリは現在プライベートベータ段階にあるため、(まだ)気にする消費者コードはあまりありません。また、名前を少し難読化しました。
名前付きの不透明な構造体よりも不透明なハンドルはどのように優れていますか?
注:私はこの質問をCode Reviewで尋ねました。