Я оцениваю библиотеку, публичный 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
s, особенно когда это ставит под угрозу безопасность типов. (Учитывая 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
с - Это следует за рекомендуемым образцом для непрозрачных типов в C
Тем не менее, владелец проекта отказался от запроса на извлечение (перефразировал):
Лично мне не нравится идея разоблачения
struct engine
. Я все еще думаю, что нынешний путь чище и дружелюбнее.Первоначально я использовал другой тип данных для дескриптора хука, но затем решил переключиться на использование
enh
, чтобы все виды дескрипторов использовали один и тот же тип данных, чтобы было проще. Если это сбивает с толку, мы, безусловно, можем использовать другой тип данных.Посмотрим, что другие подумают об этом пиаре.
Эта библиотека в настоящее время находится в стадии приватного бета-тестирования, поэтому не нужно беспокоиться о коде пользователя (пока). Кроме того, я немного запутал имена.
Чем непрозрачный дескриптор лучше именованной непрозрачной структуры?
Примечание: я задал этот вопрос в Code Review , где он был закрыт.