मैं एक ऐसे पुस्तकालय का मूल्यांकन कर रहा हूँ जिसका सार्वजनिक एपीआई वर्तमान में इस तरह दिखता है:
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
एक सामान्य संभाल है, जिसे कई अलग-अलग डेटाटिप्स ( इंजन और हुक ) के हैंडल के रूप में उपयोग किया जाता है ।
आंतरिक रूप से, इनमें से अधिकांश APIs ने "हैंडल" को एक आंतरिक संरचना में डाला है, जो उन्होंने malloc
'd'
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
, मुझे कैसे पता चलेगा कि यह वास्तव में क्या है?)
इसलिए मैंने एक पुल निवेदन प्रस्तुत किया, जिसमें निम्नलिखित एपीआई परिवर्तन का सुझाव दिया गया ( पूरे पुस्तकालय को संशोधित करने के बाद ):
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);
बेशक, यह आंतरिक एपीआई कार्यान्वयन को बेहतर बनाता है, जातियों को समाप्त करता है, और उपभोक्ता के दृष्टिकोण से / के लिए प्रकार की सुरक्षा बनाए रखता है।
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
, इसलिए सभी प्रकार के हैंडल समान डेटा प्रकार को सरल रखने के लिए साझा करते हैं। यदि यह भ्रामक है, तो हम निश्चित रूप से दूसरे डेटा प्रकार का उपयोग कर सकते हैं।आइए देखें कि अन्य लोग इस पीआर के बारे में क्या सोचते हैं।
यह लाइब्रेरी वर्तमान में एक निजी बीटा चरण में है, इसलिए इसके बारे में (अभी तक) चिंता करने के लिए बहुत अधिक उपभोक्ता कोड नहीं है। इसके अलावा, मैंने नामों को थोड़ा आगे बढ़ाया है।
नाम, अपारदर्शी संरचना की तुलना में एक अपारदर्शी संभाल कैसे बेहतर है?
नोट: मैंने यह सवाल कोड रिव्यू में पूछा था, जहां इसे बंद कर दिया गया था।