واجهة برمجة تطبيقات Python جديدة

يسعدني أن أشارككم fluent-discourse، وهي حزمة بايثون جديدة لاستهلاك واجهة برمجة تطبيقات Discourse.

توجد بالفعل بضع حزم أخرى لاستهلاك واجهة برمجة تطبيقات Discourse عبر بايثون. إذن، لماذا نبني حزمة أخرى؟

تميل الحزم الأخرى المتاحة لـ Discourse إلى معالجة المشكلة بطريقة متشابهة — إنشاء دالة بايثون فريدة لكل نقطة نهاية (endpoint) في الواجهة.

لكن هذا الأسلوب يحمل بعض العيوب:

  1. من الصعب جدًا تحقيق تكافؤ كامل في الميزات مع الواجهة. فواجهة برمجة تطبيقات Discourse غير موثقة بشكل كافٍ في بعض الأحيان، وغالبًا ما تحتاج إلى عكس هندسة نقاط النهاية. علاوة على ذلك، توجد العديد من الإضافات التي تعرض نقاط نهاية للواجهة لا تعد جزءًا من النواة الأساسية. وهذا يضع مستخدم المكتبة أمام خيار صعب: إما تقديم طلبات دمج (pull requests) لإضافة النقاط التي يحتاجها إلى المكتبة، أو بناء حل مخصص للنقاط الإضافية.
  2. يجب عليك تعلم واجهة برمجة تطبيقات أخرى. فبالإضافة إلى تعلم الدوال ونقاط نهاية واجهة برمجة تطبيقات Discourse، يجب عليك معرفة استدعاء الدالة المطابق في بايثون.
  3. هناك الكثير من الكود الذي يحتاج إلى اختبار، مما يجعل تحقيق تغطية اختبار بنسبة 100% أمرًا أصعب. وبالتالي، تقل الثقة في جودة البرمجيات المنتجة.

على النقيض من هذا الأسلوب، استخدمتُ واجهة “تدفق” (fluent interface)، حيث يمكنك استخدام ربط الدوال (method chaining) لبناء الطلبات. لنأخذ مثالًا.
للحصول على أحدث المواضيع في فئة معينة اسمها ‘foo’ ومعرفها 5، تستخدم نقطة النهاية هذه:
GET /c/foo/5.json.
ولإجراء هذا الطلب باستخدام هذه المكتبة، ما عليك سوى استدعاء:
client.c.foo[5].json.get()

يمكنك ملاحظة وجود تكافؤ دلالي بين نقطة نهاية الواجهة والاستدعاء المقابل في بايثون.

ويتميز هذا الأسلوب بما يلي:

  1. يحقق تكافؤًا كاملًا في الميزات مع واجهة برمجة تطبيقات Discourse من البداية، بما في ذلك النقاط غير الموثقة، ونقاط نهاية الإضافات، والنقاط التي لم تُعرّف بعد (مستقبلي الصلاحية).
  2. لا تحتاج إلا إلى تعلم واجهة برمجة تطبيقات Discourse. فمن السهل ترجمة أي استدعاء للواجهة بهذه الطريقة، وبالتالي لا تحتاج إلى البحث عن الدالة المطابقة له.
  3. يتكون كل المكتبة من حوالي 150 سطرًا من الكود فقط. وهذا يجعل تحقيق تغطية اختبار بنسبة 100% أمرًا تافهًا.

توجد تغطية اختبار بنسبة 100% مع عدد قليل من اختبارات التكامل ضد خادم Discourse نشط.

إذا بدا هذا جذابًا لك، آمل أن تجرب هذه الحزمة!

21 إعجابًا

هذه نهج مثير للاهتمام..

لتنفيذ شيء مشابه في PHP، سيكون علينا الاعتماد على الدوال السحرية (magic methods)، مما يعني فقدان ميزة الإكمال التلقائي في بيئات التطوير المتكاملة (IDE) وما شابه. لكن قد يكون هذا ثمنًا يستحق الدفع.

ما هي ميزة هذا النهج مقارنة بتمرير عنوان URL كمعامل ببساطة: client.get(url)؟

هذه نقطة جيدة، فميزة الإكمال التلقائي في بيئة التطوير لن تكون مفيدة كثيرًا هنا. قد يستحق الأمر استخدام مكتبة مختلفة إذا كان ذلك مهمًا بالنسبة لك.

بما أن كل سلسلة من الدوال تعيد عميلًا جديدًا، فإن إحدى المزايا التي يمكنني التفكير فيها هي تخزين سلسلة محددة من الدوال في متغير وإعادة استخدامها في المكالمات اللاحقة. على سبيل المثال، لنفترض أن لديك قائمة ببيانات المنشورات الجديدة التي ترغب في إنشائها.

post_data = [
  {
    "raw": "Hello World!",
    "topic_id": 123,
    ...
  },
  {
    "raw": "Tester",
    "topic_id": 501,
    ...
  },
  ...
]

يمكنك تخزين سلسلة دوال “منشور جديد” وإعادة استخدامها لإنشاء كل منشور في القائمة.

new_post_endpoint = client.posts.json

for post in post_data:
  new_post_endpoint.post(data=post) 

قد تتمكن من تخيل سيناريوهات أخرى حيث يمكن أن تكون هذه القدرة على إعادة استخدام العميل مفيدة. بخلاف ذلك، لا توجد ميزة كبيرة مقارنة بتمرير عنوان URL كما اقترحت. أشجعك على الاطلاع على مكتبة العميل الشامل التي تحتوي على بعض المعلومات حول المنطق وراء هذا النوع من النهج.

أيضًا، للحصول على تنفيذ خاص بـ PHP لهذا النهج، راجع واجهة برمجة تطبيقات SendGrid لـ PHP. لقد استوحيت فكرة بناء هذا عندما قرأت عن واجهة برمجة تطبيقات SendGrid لـ Python.

3 إعجابات