Saya mengevaluasi perpustakaan yang API publiknya saat ini terlihat seperti ini:
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);
Perhatikan bahwa itu enh
adalah pegangan umum, digunakan sebagai pegangan untuk beberapa tipe data yang berbeda ( mesin dan kait ).
Secara internal, sebagian besar API ini tentu saja melemparkan "pegangan" ke struktur internal yang telah mereka 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); }
Secara pribadi, saya benci menyembunyikan hal-hal di belakang typedef
, terutama ketika itu mengganggu keamanan jenis. (Diberikan enh
, bagaimana saya tahu apa yang sebenarnya dimaksud?)
Jadi saya mengirimkan permintaan tarik, menyarankan perubahan API berikut (setelah memodifikasi seluruh perpustakaan agar sesuai):
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);
Tentu saja, ini membuat implementasi API internal terlihat jauh lebih baik, menghilangkan gips, dan menjaga keamanan jenis ke / dari perspektif konsumen.
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);
}
Saya lebih suka ini karena alasan berikut:
- Keamanan tipe ditambahkan
- Kejelasan jenis dan tujuan yang ditingkatkan
- Gips dan
typedef
s dihapus - Ini mengikuti pola yang disarankan untuk jenis buram di C
Namun, pemilik proyek menolak keras permintaan tarik (diparafrasekan):
Secara pribadi saya tidak suka ide mengekspos
struct engine
. Saya masih berpikir cara saat ini lebih bersih & lebih ramah.Awalnya saya menggunakan tipe data lain untuk pegangan kait, tetapi kemudian memutuskan untuk beralih menggunakan
enh
, jadi semua jenis pegangan berbagi tipe data yang sama agar tetap sederhana. Jika ini membingungkan, kita tentu bisa menggunakan tipe data lain.Mari kita lihat apa pendapat orang lain tentang PR ini.
Perpustakaan ini saat ini dalam tahap beta pribadi, jadi tidak ada banyak kode konsumen yang perlu dikhawatirkan (belum). Juga, saya sedikit mengaburkan nama.
Bagaimana cara menangani buram lebih baik daripada yang disebut, struct buram?
Catatan: Saya mengajukan pertanyaan ini di Code Review , di mana ditutup.