خلاصة القول (TL;DR)
يجب أن تكون أسماء موارد واجهة برمجة تطبيقات REST بصيغة الجمع. استخدم /pets/{id} بدلاً من /pet/{id}. تمثل الأسماء الجمع المجموعات بشكل متسق، وتتوافق مع دلالات HTTP، وتطابق طريقة تفكير المطورين حول الموارد. يستخدم Modern PetstoreAPI أسماء الجمع في جميع أنحاء تصميم واجهة برمجة تطبيقاته، متبعًا أفضل ممارسات الصناعة.
مقدمة
أنت تصمم واجهة برمجة تطبيقات REST. تحتاج إلى نقطة نهاية للحصول على مستخدم بواسطة المعرّف (ID). هل تستخدم /user/123 أم /users/123؟ لقد أثار هذا السؤال عددًا لا يحصى من النقاشات، ومواضيع Stack Overflow، والخلافات بين الفرق.
الجواب واضح: استخدم صيغة الجمع. ولكن فهم السبب أهم من حفظ القاعدة. يرتبط هذا المنطق بكيفية عمل REST، وكيف تتصرف المجموعات، وكيف يفكر المطورون في الموارد.
أخطأ Swagger Petstore القديم في هذا، حيث استخدم /pet/{id} بدلاً من /pets/{id}. وقد علّمت هذه التناقضات ملايين المطورين النمط الخاطئ. يقوم Modern PetstoreAPI بتصحيح هذا من خلال استخدام أسماء الجمع بشكل متسق عبر جميع نقاط النهاية.
في هذا الدليل، ستتعلم لماذا الأسماء الجمع هي الخيار الصحيح، وكيف تتماشى مع مبادئ REST، وكيفية تنفيذها بشكل صحيح باستخدام Modern PetstoreAPI كمرجع.
نقاش الأسماء الجمع مقابل المفرد
يوجد النقاش لأن كلا النهجين يبدوان منطقيين للوهلة الأولى.
الحجة للمفرد
"عندما أطلب /user/123، أحصل على مستخدم واحد، وليس عدة مستخدمين. المفرد منطقي."
يركز هذا المنطق على الاستجابة—أنت تحصل على مورد واحد، لذا يجب أن يكون عنوان URL مفردًا.
الحجة للجمع
"يمثل عنوان URL مجموعة. /users هي مجموعة جميع المستخدمين. /users/123 هو العنصر 123 في تلك المجموعة."
يركز هذا المنطق على بنية المورد—تمثل عناوين URL المجموعات، وأنت تصل إلى عناصر داخل تلك المجموعات.
لماذا هذا مهم
اختيارك يؤثر على:
- اتساق واجهة برمجة التطبيقات (API consistency) - التسمية المختلطة تربك المطورين
- النماذج الذهنية (Mental models) - كيف يفهم المطورون بنية واجهة برمجة التطبيقات الخاصة بك
- توليد الكود (Code generation) - الأدوات تولد كود العميل بناءً على أسماء الموارد
- وضوح الوثائق (Documentation clarity) - تحتاج الوثائق لشرح منطق التسمية الخاص بك
لماذا تفوز الأسماء الجمع
تتماشى أسماء الموارد بصيغة الجمع مع مبادئ REST ودلالات HTTP. إليك السبب.
1. المجموعات تكون بصيغة الجمع
في REST، الموارد هي مجموعات. عندما تصل إلى /users، فأنت تصل إلى مجموعة المستخدمين. عندما تصل إلى /users/123، فأنت تصل إلى العنصر 123 في مجموعة المستخدمين.
GET /users ← مجموعة المستخدمين
GET /users/123 ← العنصر 123 في مجموعة المستخدمين
POST /users ← إضافة إلى مجموعة المستخدمين
DELETE /users/123 ← إزالة العنصر 123 من مجموعة المستخدمين
هذا النموذج الذهني متسق. المجموعة هي دائمًا /users، سواء كنت تصل إلى جميع العناصر أو عنصر واحد.
مع الأسماء المفردة، ينهار النموذج الذهني:
GET /user ← أي مستخدم؟
GET /user/123 ← هذا منطقي
POST /user ← إضافة إلى... ماذا؟
2. عمليات HTTP تعمل على المجموعات
تصف عمليات HTTP العمليات على المجموعات:
GET /users- استرداد المجموعةPOST /users- إضافة إلى المجموعةGET /users/123- استرداد العنصر 123 من المجموعةPUT /users/123- استبدال العنصر 123 في المجموعةDELETE /users/123- إزالة العنصر 123 من المجموعة
المجموعة هي المورد. العناصر الفردية هي أعضاء في تلك المجموعة.
3. الاتساق عبر نقاط النهاية
تخلق الأسماء الجمع الاتساق:
GET /pets ← مجموعة
GET /pets/123 ← عنصر في المجموعة
GET /orders ← مجموعة
GET /orders/456 ← عنصر في المجموعة
الأسماء المفردة تجبرك على التبديل بين المفرد والجمع:
GET /pet ← غير منطقي
GET /pet/123 ← منطقي
GET /pets ← انتظر، الآن أصبح جمعًا؟
4. معايير الصناعة
تستخدم واجهات برمجة التطبيقات الكبرى أسماء الجمع:
- GitHub API:
/repos,/users,/issues - Stripe API:
/customers,/charges,/subscriptions - Twilio API:
/accounts,/messages,/calls - Google APIs:
/users,/groups,/files
يتبع Modern PetstoreAPI هذا المعيار باستخدام /pets، /orders، /users.
النموذج الذهني للمجموعات
يساعدك فهم المجموعات في تصميم واجهات برمجة تطبيقات أفضل.
المجموعات في REST
المجموعة هي مجموعة من الموارد. في واجهة برمجة تطبيقات لمتجر حيوانات أليفة:
/pets- مجموعة جميع الحيوانات الأليفة/orders- مجموعة جميع الطلبات/users- مجموعة جميع المستخدمين
كل مجموعة تدعم العمليات:
GET /pets ← قائمة الحيوانات الأليفة (مع التصفية والترقيم)
POST /pets ← إنشاء حيوان أليف جديد
GET /pets/{id} ← الحصول على حيوان أليف معين
PUT /pets/{id} ← تحديث حيوان أليف معين
DELETE /pets/{id} ← حذف حيوان أليف معين
المجموعات الفرعية
يمكن أن تحتوي المجموعات على مجموعات فرعية:
GET /pets/{id}/photos ← مجموعة صور للحيوان الأليف {id}
POST /pets/{id}/photos ← إضافة صورة للحيوان الأليف {id}
GET /pets/{id}/photos/{photoId} ← صورة معينة
النمط يبقى متسقًا: المجموعات تكون بصيغة الجمع، ويتم الوصول إلى العناصر بواسطة المعرّف (ID).
مثال Modern PetstoreAPI
يقوم Modern PetstoreAPI بتنفيذ هذا بشكل صحيح:
GET /pets
GET /pets/{petId}
GET /pets/{petId}/photos
POST /pets/{petId}/vaccinations
GET /orders
GET /orders/{orderId}
GET /orders/{orderId}/items
كل مجموعة تكون بصيغة الجمع. كل وصول إلى عنصر يستخدم {id} ضمن تلك المجموعة.
كيف يستخدم Modern PetstoreAPI أسماء الجمع
دعنا نرى أمثلة حقيقية من Modern PetstoreAPI.
موارد الحيوانات الأليفة
GET /pets ← سرد جميع الحيوانات الأليفة
POST /pets ← إنشاء حيوان أليف جديد
GET /pets/{petId} ← الحصول على حيوان أليف معين
PUT /pets/{petId} ← تحديث الحيوان الأليف
DELETE /pets/{petId} ← حذف الحيوان الأليف
GET /pets?status=AVAILABLE ← تصفية الحيوانات الأليفة حسب الحالة
موارد الطلبات
GET /orders ← سرد جميع الطلبات
POST /orders ← إنشاء طلب
GET /orders/{orderId} ← الحصول على طلب معين
PUT /orders/{orderId} ← تحديث الطلب
DELETE /orders/{orderId} ← إلغاء الطلب
موارد المستخدمين
GET /users ← سرد المستخدمين
POST /users ← إنشاء مستخدم
GET /users/{userId} ← الحصول على مستخدم معين
PUT /users/{userId} ← تحديث المستخدم
DELETE /users/{userId} ← حذف المستخدم
الموارد المتداخلة
GET /pets/{petId}/photos ← صور الحيوان الأليف
POST /pets/{petId}/photos ← إضافة صورة
GET /pets/{petId}/vaccinations ← تطعيمات الحيوان الأليف
POST /pets/{petId}/vaccinations ← تسجيل تطعيم
GET /orders/{orderId}/items ← عناصر الطلب
تحقق من وثائق واجهة برمجة تطبيقات REST الكاملة للحصول على قوائم نقاط النهاية الكاملة.
حجج شائعة لصيغة المفرد (ولماذا هي خاطئة)
دعنا نتناول الحجج الشائعة لأسماء المفرد.
الحجة 1: "الاستجابة مفردة"
الادعاء: "عندما أطلب /user/123، أحصل على مستخدم واحد. المفرد منطقي."
الرد: يمثل عنوان URL موقع المورد، وليس الاستجابة. /users/123 تعني "العنصر 123 في مجموعة المستخدمين". كون الاستجابة مفردة لا يغير بنية المجموعة.
الحجة 2: "تبدو أفضل في الكود"
الادعاء: "قراءة getUser(id) أفضل من getUsers(id)."
الرد: تسمية كود العميل الخاص بك مستقلة عن بنية عنوان URL. يمكنك الحصول على:
// عنوان URL: GET /users/123
function getUser(id) {
return api.get(`/users/${id}`);
}
اسم الدالة لا يحتاج إلى مطابقة عنوان URL.
الحجة 3: "المفرد يتجنب مشاكل القواعد اللغوية"
الادعاء: "ماذا عن الموارد مثل 'status' أو 'information' التي ليس لها صيغ جمع واضحة؟"
الرد: هذه عادةً موارد فردية (singleton)، وليست مجموعات. استخدم المفرد للموارد الفردية:
GET /status ← حالة النظام (مورد فردي)
GET /configuration ← تهيئة التطبيق (مورد فردي)
GET /users ← مجموعة المستخدمين (جمع)
الحجة 4: "نظام ORM الخاص بي يستخدم أسماء جداول مفردة"
الادعاء: "جداول قاعدة بياناتي مفردة (user، order)، لذا يجب أن تتطابق واجهة برمجة التطبيقات الخاصة بي."
الرد: يجب ألا يتسرب تصميم واجهة برمجة التطبيقات الخاصة بك تفاصيل تنفيذ قاعدة البيانات. تمثل واجهات برمجة تطبيقات REST الموارد، وليس جداول قاعدة البيانات. استخدم صيغة الجمع للمجموعات بغض النظر عن مخطط قاعدة بياناتك.
اختبار تسمية الموارد باستخدام Apidog
يساعدك Apidog في التحقق من اتفاقيات تسمية الموارد واختبارها.
استيراد Modern PetstoreAPI
- استيراد مواصفات Modern PetstoreAPI OpenAPI
- يكتشف Apidog أنماط الموارد تلقائيًا
- مراجعة تسمية نقاط النهاية للتأكد من الاتساق
إنشاء اختبارات اتفاقيات التسمية
// نص اختبار Apidog
pm.test("Resource names are plural", function() {
const path = pm.request.url.getPath();
const segments = path.split('/').filter(s => s);
// التحقق من أن المقطع الأول بصيغة الجمع
const resource = segments[0];
pm.expect(resource).to.match(/s$/); // ينتهي بـ 's'
});
التحقق من الاتساق
يمكن لـ Apidog التحقق من:
- جميع نقاط نهاية المجموعة تستخدم أسماء الجمع
- الموارد الفرعية تتبع نفس النمط
- عدم وجود خلط بين المفرد والجمع في نفس واجهة برمجة التطبيقات
الاختبار باستخدام طلبات حقيقية
GET https://api.petstoreapi.com/v1/pets
GET https://api.petstoreapi.com/v1/pets/019b4132-70aa-764f-b315-e2803d882a24
GET https://api.petstoreapi.com/v1/orders
يتحقق Apidog من الاستجابات ويساعدك على ضمان اتساق التسمية عبر واجهة برمجة التطبيقات الخاصة بك.
الحالات الخاصة والاستثناءات
بعض الموارد لا تتناسب مع نمط الجمع.
الموارد الفردية (Singleton)
الموارد التي توجد مرة واحدة فقط يجب أن تكون بصيغة المفرد:
GET /status ← حالة النظام
GET /configuration ← تهيئة التطبيق
GET /health ← فحص الصحة
GET /metrics ← مقاييس النظام
هذه ليست مجموعات، لذا لا ينطبق عليها الجمع.
موارد التحكم (Controller Resources)
الإجراءات التي لا تتناسب مع عمليات CRUD:
POST /login ← إجراء المصادقة
POST /logout ← إنهاء الجلسة
POST /search ← عملية بحث معقدة
هذه استثناءات مقبولة لأنها تمثل إجراءات وليست موارد.
الأسماء غير القابلة للعد
بعض الأسماء ليس لها صيغ جمع واضحة:
GET /information ← مفرد (غير قابل للعد)
GET /data ← مفرد (غير قابل للعد)
GET /equipment ← مفرد (غير قابل للعد)
استخدم المفرد للأسماء غير القابلة للعد، لكن هذه نادرة في واجهات برمجة التطبيقات النموذجية.
نهج Modern PetstoreAPI
يتعامل Modern PetstoreAPI مع هذه الحالات:
# مجموعات (جمع)
GET /pets
GET /orders
GET /users
# موارد فردية (مفرد)
GET /health
GET /metrics
# إجراءات (أفعال مفردة)
POST /login
POST /logout
الخلاصة
يجب أن تكون أسماء موارد واجهة برمجة تطبيقات REST بصيغة الجمع. يتماشى هذا مع دلالات المجموعات، وعمليات HTTP، ومعايير الصناعة. يوضح Modern PetstoreAPI هذا النمط بشكل صحيح عبر جميع نقاط النهاية.
النقاط الرئيسية:
- استخدم أسماء الجمع للمجموعات (
/pets،/orders،/users) - يتم الوصول إلى العناصر الفردية ضمن المجموعات (
/pets/123) - يمكن أن تكون الموارد الفردية بصيغة المفرد (
/status،/health) - الاتساق أهم من الكمال
- اختبر اتفاقيات التسمية الخاصة بك باستخدام Apidog
لقد حُسم نقاش الجمع مقابل المفرد. اتبع معيار الصناعة، استخدم أسماء الجمع، وقم ببناء واجهات برمجة تطبيقات يفهمها المطورون بشكل بديهي.
الخطوات التالية:
- راجع نقاط نهاية واجهة برمجة التطبيقات الخاصة بك للتأكد من اتساق التسمية
- تحقق من وثائق Modern PetstoreAPI لأنماط المرجع
- استخدم Apidog للتحقق من تصميم واجهة برمجة التطبيقات الخاصة بك
- قم بتحديث مواصفات OpenAPI الخاصة بك بأسماء موارد الجمع
الأسئلة الشائعة
هل يجب علي تغيير API الحالي الخاص بي من المفرد إلى الجمع؟
إذا كانت واجهة برمجة التطبيقات الخاصة بك قيد الإنتاج بالفعل، فإن تغيير أسماء الموارد يُعد تغييرًا جذريًا. فكر في:
- إضافة نقاط نهاية v2 جديدة بأسماء الجمع
- الحفاظ على التوافق مع الإصدارات السابقة باستخدام عمليات إعادة التوجيه
- توثيق اتفاقية التسمية بوضوح
لا تقم بكسر العملاء الحاليين من أجل اتساق التسمية وحده.
ماذا عن الموارد التي هي بالفعل بصيغة الجمع؟
إذا كان اسم المورد بصيغة الجمع بطبيعته (مثل "analytics" أو "series")، فاحتفظ به كما هو:
GET /analytics ← جمع بالفعل
GET /series ← جمع بالفعل
GET /species ← جمع بالفعل
كيف أتعامل مع الموارد المتداخلة؟
اجعل كلا المستويين بصيغة الجمع:
GET /users/{userId}/orders ← كلاهما جمع
GET /pets/{petId}/vaccinations ← كلاهما جمع
GET /orders/{orderId}/items ← كلاهما جمع
ماذا لو فضل فريقي المفرد؟
الاتساق داخل واجهة برمجة التطبيقات الخاصة بك هو الأهم. إذا كان فريقك قد قام بالفعل بتوحيد استخدام الأسماء المفردة، وكان التغيير سيسبب ارتباكًا، فالتزم بالمفرد. ولكن بالنسبة لواجهات برمجة التطبيقات الجديدة، استخدم الجمع.
هل يستخدم GraphQL صيغة الجمع أم المفرد؟
يستخدم GraphQL عادةً المفرد لاستعلامات العنصر الواحد والجمع للقوائم:
query {
user(id: "123") { ... } # مفرد
users(limit: 10) { ... } # جمع
}
هذا يختلف عن REST لأن استعلامات GraphQL صريحة بشأن إرجاع عنصر واحد أو العديد.
كيف يتعامل Modern PetstoreAPI مع هذا؟
يستخدم Modern PetstoreAPI أسماء الجمع بشكل متسق عبر جميع نقاط نهاية REST. تحقق من دليل واجهة برمجة تطبيقات REST للحصول على أمثلة كاملة.
هل يمكنني اختبار اتفاقيات التسمية تلقائيًا؟
نعم، يمكن لـ Apidog تشغيل اختبارات آلية للتحقق من أنماط تسمية الموارد عبر واجهة برمجة التطبيقات بأكملها. قم باستيراد مواصفات OpenAPI الخاصة بك وإنشاء حالات اختبار لاتفاقيات التسمية.
ماذا عن واجهات برمجة التطبيقات غير الإنجليزية؟
تنطبق قاعدة الجمع بغض النظر عن اللغة. إذا كانت واجهة برمجة التطبيقات الخاصة بك تستخدم أسماء موارد فرنسية، فاستخدم صيغ الجمع الفرنسية. إذا كانت تستخدم اليابانية، فاتبع قواعد اللغة اليابانية. المبدأ (المجموعات تكون بصيغة الجمع) يبقى كما هو.
