تعلّم كيفية توليد OpenAPI من السلوك باستخدام Claude Code، ثم قارنها مع تنفيذ الـ API وأنشئ أمثلة بسيطة للتحقق على العميل والخادم.

عقد OpenAPI هو وصف مشترك لواجهتك: أي نقاط نهاية موجودة، ماذا ترسل، ماذا تتلقى، وكيف تبدو الأخطاء. إنه الاتفاق بين الخادم وأي طرف يتصل به (تطبيق ويب، تطبيق جوال، أو خدمة أخرى).
المشكلة هي الانحراف. تتغير واجهة البرمجة العاملة، لكن المواصفة لا تتغير. أو تُنقّح المواصفة لتبدو أجمل من الواقع، بينما يستمر التنفيذ في إعادة حقول غريبة، أو رموز حالة مفقودة، أو أشكال أخطاء غير متسقة. مع مرور الوقت، يتوقف الناس عن الثقة في ملف OpenAPI، ويصبح مجرد وثيقة إضافية يتجاهلها الجميع.
الانحراف عادةً نتيجة ضغوط طبيعية: إصلاح سريع يُنشَر دون تحديث المواصفة، أو إضافة حقل اختياري "مؤقتًا"، أو تطوّر الترقيم الصفحي، أو تحديث فرق مصادر حقيقة مختلفة (كود الخلفية، مجموعة Postman، وملف OpenAPI).
الحفاظ على الأمانة يعني أن المواصفة تطابق السلوك الحقيقي. إذا كانت الواجهة تعيد أحيانًا 409 لصراع، فذلك يجب أن يكون في العقد. إذا كان الحقل قابلًا لأن يكون null فاذكر ذلك. إذا كانت المصادقة مطلوبة، لا تتركها غامضة.
سير عمل جيد يتركك مع:
النقطة الأخيرة مهمة لأن العقد يساعد فقط حين يتم فرضه. مواصفة صادقة مع فحوصات قابلة للتكرار تحول "توثيق API" إلى شيء يمكن للفرق الاعتماد عليه.
إذا بدأت بقراءة الكود أو نسخ المسارات، فستصف مواصفة OpenAPI ما يوجد اليوم، بما في ذلك عيوب قد لا تريد الالتزام بها. بدلًا من ذلك، صف ما يجب أن تفعله الواجهة للمتصل، ثم استخدم المواصفة للتحقق أن التنفيذ يطابقها.
قبل كتابة YAML أو JSON، اجمع مجموعة صغيرة من الحقائق لكل نقطة نهاية:
ثم اكتب السلوك كأمثلة. الأمثلة تجبرك على التحديد وتجعل من الأسهل صياغة عقد متسق.
لبناء واجهة مهام (Tasks API)، قد يكون مسار النجاح مثالياً: "أنشئ مهمة مع title واستلم id وtitle وstatus وcreatedAt." أضف حالات الفشل الشائعة: "غياب title يعيد 400 مع {\"error\":\"title is required\"}" و"بدون مصادقة يعيد 401." إذا كنت تعرف حالات حافة، أدرجها: هل العناوين المكررة مسموحة، وماذا يحدث عندما لا يوجد معرف مهمة.
سجّل القواعد كجمل بسيطة لا تعتمد على تفاصيل الكود:
title مطلوب وطوله 1-120 حرفًا."limit (الحد الأقصى 200)."dueDate بتنسيق ISO 8601 date-time."أخيرًا، قرر نطاق الإصدار الأول (v1). إذا لم تكن متأكدًا، اجعل v1 صغيرًا وواضحًا (إنشاء، قراءة، قائمة، تحديث الحالة). اترك البحث، التحديثات بالجملة، والمرشحات المعقدة لاحقًا حتى تظل المواصفة قابلة للتصديق.
قبل أن تطلب من Claude Code كتابة المواصفة، اكتب ملاحظات السلوك في صيغة صغيرة وقابلة للتكرار. الهدف أن تجعل من الصعب ملء الفجوات بالتخمينات.
قالب جيد قصير بما يكفي لكي تُستخدم فعلاً، لكن متسق بحيث يصف شخصان نفس نقطة النهاية بشكل متشابه. اجعله مركزًا على ما تفعله الواجهة، لا على كيفية تنفيذها.
استخدم كتلة واحدة لكل نقطة نهاية:
METHOD + PATH:
Purpose (1 sentence):
Auth:
Request:
- Query:
- Headers:
- Body example (JSON):
Responses:
- 200 OK example (JSON):
- 4xx example (status + JSON):
Edge cases:
Data types (human terms):
اكتب على الأقل طلبًا ملموسًا واستجابتين. أدرج رموز الحالة وأجسام JSON واقعية بأسماء حقول فعلية. إذا كان الحقل اختياريًا، أظهر مثالًا واحدًا يكون فيه مفقودًا.
سلّط الضوء على الحالات الحدية صراحةً. هذه هي النقاط التي يصبح فيها العقد غير حقيقي لاحقًا لأن الجميع افترض شيئًا مختلفًا: النتائج الفارغة، المعرفات غير الصالحة (400 مقابل 404)، التكرارات (409 مقابل سلوك معرفي)، فشل التحقق، وحدود التصفح.
أيضًا ضع أنواع البيانات بكلمات بسيطة قبل التفكير بالمخططات: سلاسل مقابل أرقام، تنسيقات التاريخ-الوقت، القيم البوليانية، والقوائم المحظورة (enums). هذا يمنع مخططًا "جميلًا" لا يطابق الحمولة الحقيقية.
يعمل Claude Code بأفضل شكل عندما تعامل معه كمحرر دقيق. أعطه ملاحظات السلوك وقواعد صارمة لكيفية شكل OpenAPI. إذا قلت فقط "اكتب مواصفة OpenAPI" فغالبًا ستحصل على تخمينات، أسماء غير متناسقة، وحالات خطأ مفقودة.
ألصق ملاحظاتك أولًا، ثم أضف كتلة تعليمات ضيقة. موجه عملي يبدو هكذا:
You are generating an OpenAPI 3.1 YAML spec.
Source of truth: the behavior notes below. Do not invent endpoints or fields.
If anything is unclear, list it under ASSUMPTIONS and leave TODO markers in the spec.
Requirements:
- Include: info, servers (placeholder), tags, paths, components/schemas, components/securitySchemes.
- For each operation: operationId, tags, summary, description, parameters, requestBody (when needed), responses.
- Model errors consistently with a reusable Error schema and reference it in 4xx/5xx responses.
- Keep naming consistent: PascalCase schema names, lowerCamelCase fields, stable operationId pattern.
Behavior notes:
[PASTE YOUR NOTES HERE]
Output only the OpenAPI YAML, then a short ASSUMPTIONS list.
بعد الحصول على المسودة، افحص ASSUMPTIONS أولًا. هناك تُربح أو تُفقد الأمانة. وافق على الصحيح، صحّح الخطأ، وأعد التشغيل مع ملاحظات محدثة.
للحفاظ على تسمية متسقة، اذكر الاتفاقيات مسبقًا وتمسك بها. على سبيل المثال: نمط operationId ثابت، أسماء الوسوم (tags) اسمية فقط، أسماء المخططات بصيغة المفرد، مخطط Error مشترك واحد، واسم واحد لنظام المصادقة مستخدم في كل مكان.
إذا عملت في بيئة تعامل سريع مثل Koder.ai، فمن المفيد حفظ YAML كملف حقيقي مبكرًا والتكرار بتغييرات صغيرة. يمكنك رؤية التغييرات التي جاءت من قرارات سلوك معتمدة مقابل تفاصيل خمنها النموذج.
قبل مقارنة أي شيء مع الإنتاج، تأكد أن ملف OpenAPI متناسق داخليًا. هذا أسرع مكان لالتقاط التفكير الأمنياتي والصياغات الغامضة.
اقرأ كل نقطة نهاية كما لو كنت مطوّر العميل. ركّز على ما يجب أن يرسله المستدعي وما يمكنه الاعتماد على استلامه.
جولة مراجعة عملية:
استجابات الأخطاء تستحق عناية إضافية. اختر شكلًا موحدًا وأعد استخدامه في كل مكان. بعض الفرق تحافظ على شكل بسيط جدًا ({ error: string })، بينما يستخدم آخرون كائنًا ({ error: { code, message, details } }). كلاهما قد يعمل، لكن لا تخلطهما عبر النقاط النهائية والأمثلة. إذا فعلت، سيجمع كود العميل حالات خاصة تدريجيًا.
سيناريو صحة سريع يساعد. إذا كان POST /tasks يتطلب title، فيجب أن يعلّم المخطط أنه مطلوب، واستجابة الفشل يجب أن تُظهر شكل جسم الخطأ فعليًا، وتوضح العملية بوضوح ما إذا كانت المصادقة مطلوبة.
بمجرد أن تقرأ المواصفة كسلوك مقصود، اعتبر API العامل حقيقة ما يواجهه العملاء اليوم. الهدف ليس "ربح" المناقشة بين المواصفة والكود، بل كشف الاختلافات مبكرًا واتخاذ قرار واضح لكل اختلاف.
للمرّة الأولى، عينات الطلبات/الاستجابات الحقيقية عادةً أبسط خيار. السجلات والاختبارات الآلية تعمل أيضًا إذا كانت موثوقة.
راقب الاختلافات الشائعة: نقاط نهاية موجودة في مكان وغير موجودة في آخر، اختلافات أسماء الحقول أو الأشكال، اختلافات رموز الحالة (200 مقابل 201، 400 مقابل 422)، سلوكيات غير موثقة (ترقيم صفحات، ترتيب، تصفية)، واختلافات المصادقة (المواصفة تقول عام، الكود يتطلب رمزًا).
مثال: تقول مواصفة OpenAPI إن POST /tasks يعيد 201 مع {id,title}. عند استدعاء API العامل تحصل على 200 مع {id,title,createdAt}. هذا ليس "قريبًا بما فيه الكفاية" إذا كنت تولّد SDKs من المواصفة.
قبل التعديل، قرر كيفية حل التعارضات:
اجعل كل تغيير صغيرًا وقابلًا للمراجعة: نقطة نهاية واحدة، استجابة واحدة، تعديل مخطط واحد. سيكون من الأسهل مراجعته وإعادة اختباره.
عندما تحصل على مواصفة تثق بها، حوّلها إلى أمثلة تحقق صغيرة. هذا ما يمنع الانحراف من العودة.
على الخادم، التحقق يعني الفشل السريع عندما لا يطابق الطلب العقد، وإرجاع خطأ واضح. هذا يحمي بياناتك ويجعل الأخطاء أسهل في الاكتشاف.
طريقة بسيطة للتعبير عن أمثلة التحقق على الخادم هي كتابتها كحالات ثلاثية: الإدخال، المخرجات المتوقعة، والخطأ المتوقع (رمز خطأ أو نمط رسالة، وليس نصًا حرفيًا).
مثال (العقد يحدد أن title مطلوب وطوله 1 إلى 120 حرفًا):
{
"name": "Create task without title returns 400",
"request": {"method": "POST", "path": "/tasks", "body": {"title": ""}},
"expect": {"status": 400, "body": {"error": {"code": "VALIDATION_ERROR"}}}
}
على العميل، التحقق يتعلق باكتشاف الانحراف قبل أن يلاحظه المستخدمون. إذا بدأ الخادم بإرجاع شكل مختلف، أو اختفى حقل مطلوب، يجب أن تُنبّه اختباراتك.
اجعل فحوصات العميل مركزة على ما تعتمد عليه فعليًا، مثل "المهمة لها id, title, status." تجنّب المطالبة بكل حقل اختياري أو الترتيب بالضبط. تريد فشلًا عند تغييرات مدمرة، لا عند إضافات غير ضارة.
بعض الإرشادات التي تحافظ على اختبارات قابلة للقراءة:
إذا بنيت باستخدام Koder.ai، يمكنك توليد هذه الحالات المثال وشبكها بجانب ملف OpenAPI، ثم تحديثها كجزء من نفس المراجعة عندما يتغير السلوك.
تخيّل API صغير بثلاث نقاط نهاية: POST /tasks لإنشاء مهمة، GET /tasks لقائمة المهام، وGET /tasks/{id} لاسترجاع مهمة واحدة.
ابدأ بكتابة بعض الأمثلة الملموسة لنقطة نهاية واحدة، كما لو كنت تشرحها لمختبر.
بالنسبة لـ POST /tasks، قد يكون السلوك المقصود:
{ "title": "Buy milk" } وتحصل على 201 مع كائن مهمة جديد يتضمن id وtitle وdone:false.{} وتحصل على 400 مع خطأ مثل { "error": "title is required" }.{ "title": "x" } (قصير جدًا) وتحصل على 422 مع { "error": "title must be at least 3 characters" }.عندما يصيغ Claude Code مواصفة OpenAPI، يجب أن تلتقط الشريحة الخاصة بهذه النقطة المخطط، رموز الحالة، وأمثلة واقعية:
paths:
/tasks:
post:
summary: Create a task
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateTaskRequest'
examples:
ok:
value: { "title": "Buy milk" }
responses:
'201':
description: Created
content:
application/json:
schema:
$ref: '#/components/schemas/Task'
examples:
created:
value: { "id": "t_123", "title": "Buy milk", "done": false }
'400':
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
missingTitle:
value: { "error": "title is required" }
'422':
description: Unprocessable Entity
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
tooShort:
value: { "error": "title must be at least 3 characters" }
اختلاف شائع دقيق: API العامل يعيد 200 بدلًا من 201، أو يعيد { "taskId": 123 } بدلًا من { "id": "t_123" }. هذا النوع من الفروقات "قريب لكنه مخرب" يكسر العملاء المولّدين.
اصلح ذلك باختيار مصدر حقيقة واحد. إذا كان السلوك المقصود صحيحًا، غيّر التنفيذ ليعيد 201 والشكل المتفق عليه. إذا كان سلوك الإنتاج مستخدمًا فعليًا، حدّث المواصفة (وملاحظات السلوك) لتطابق الواقع، ثم أضف التحقق واستجابات الأخطاء المفقودة حتى لا تُفاجأ العملاء.
يصبح العقد غير أمين عندما يتوقف عن وصف القواعد ويبدأ في وصف ما أعادته الـ API في يومٍ جيد واحد. اختبار بسيط: هل يمكن لتنفيذ جديد أن يجتاز هذه المواصفة دون نسخ عيوب اليوم؟
فخ واحد هو الإفراط في التخصيص. تلتقط استجابة واحدة وتحولها إلى قانون. مثال: تعيد الواجهة حاليًا dueDate: null لكل مهمة، فتجعل المواصفة الحقل دائمًا قابلًا لأن يكون null. لكن القاعدة الحقيقية قد تكون "مطلوب عندما تكون الحالة scheduled." يجب أن يعبر العقد عن القاعدة، لا عن مجموعة البيانات الحالية.
الأخطاء هي المكان الذي ينكسر فيه الصدق غالبًا. من المغري تحديد استجابات النجاح فقط لأنها نظيفة. لكن العملاء يحتاجون الأساسيات: 401 عند غياب الرمز، 403 للمنع، 404 للمعرفات المجهولة، وخطأ تحقق موحد (400 أو 422).
أنماط أخرى تسبب مشكلة:
taskId في مسار وآخر id في آخر، أو priority كنص في أحد الردود ورقم في آخر).string، كل شيء اختياري).عقدة جيدة قابلة للاختبار. إذا لم تتمكن من كتابة اختبار يفشل اعتمادًا على المواصفة، فالمواصفة ليست صادقة بعد.
قبل أن تعطي ملف OpenAPI لفريق آخر (أو تلصقه في الوثائق)، قم بجولة سريعة: "هل يمكن لشخص استخدام هذا دون قراءة عقلك؟"
ابدأ بالأمثلة. يمكن أن تكون المواصفة صحيحة لكنها عديمة الفائدة إذا كانت كل طلب واستجابة مجردة. لكل عملية، أدرج مثال طلب واقعي واحد ومثال استجابة نجاح واحد. للأخطاء، مثال واحد لكل فشل شائع (مصادقة، تحقق) عادةً يكفي.
ثم افحص الاتساق. إذا أعادت نقطة نهاية { "error": "..." } وأخرى { "message": "..." }، سيُجري العملاء منطقًا متشعبًا في كل مكان. اختر شكل خطأ واحد وأعد استخدامه، مع رموز حالة متوقعة.
قائمة تحقق قصيرة:
حيلة عملية: اختر نقطة نهاية، تظاهر بأنك لم ترَ الـ API من قبل، وأجب على "ماذا أرسل، ماذا أستقبل، وماذا ينكسر؟" إذا لم تستطع المواصفة الإجابة بوضوح، فهي ليست جاهزة.
هذا سير العمل يؤتي ثماره عندما يُشغّل بانتظام، ليس فقط أثناء هرج الإصدار. اختر قاعدة بسيطة والتزم بها: شغّلها عندما يتغير نقطة نهاية، وأعد تشغيلها قبل نشر مواصفة محدثة.
اجعل الملكية بسيطة. الشخص الذي يغيّر نقطة النهاية يحدث ملاحظات السلوك ومسودة المواصفة. شخص ثانٍ يراجع فرق المواصفة مقابل التنفيذ كما يفعل في مراجعة كود. زملاء QA أو الدعم غالبًا ما يكونون مراجعين جيدين لأنهم يلاحظون الاستجابات غير الواضحة وحالات الحافة بسرعة.
عامل تعديلات العقد كتعليمات برمجية. إذا كنت تستخدم بناة مدفوعة بالدردشة مثل Koder.ai، فالتقاط لقطة قبل التعديلات الخطرة واستخدام التراجع يبقي التكرار آمنًا. تدعم Koder.ai أيضًا تصدير شفرة المصدر، مما يسهل إبقاء المواصفة والتنفيذ جنبًا إلى جنب في المستودع.
روتين عملي يعمل عادة دون إبطاء الفرق:
الإجراء التالي: اختر نقطة نهاية موجودة. اكتب 5-10 سطور من ملاحظات السلوك (المدخلات، المخرجات، حالات الخطأ)، ولّد مسودة OpenAPI من تلك الملاحظات، حقّقها، ثم قارنها بالتطبيق العامل. صحّح اختلافًا واحدًا، أعد الاختبار، وكرر. بعد نقطة نهاية واحدة، عادةً ما تثبت العادة.
الانحراف في OpenAPI يحدث عندما لا تعكس المواصفة المشتركة واجهة البرمجة التي تعمل فعليًا. قد تكون المواصفة ناقصة حقول جديدة، رموز حالة، أو قواعد المصادقة، أو قد تصف سلوكًا "مثاليًا" لا يتبعه الخادم بالفعل.
هذا مهم لأن العملاء (التطبيقات، الخدمات الأخرى، SDKs المولّدة، الاختبارات) يتصرفون وفقًا للعقد، وليس بناءً على ما يفعله الخادم "عادةً".
تظهر أعطال العملاء بشكل عشوائي ويصعب تتبعه: تطبيق جوال يتوقع 201 ويحصل على 200، مكتبة SDK لا تستطيع فك تسلسل استجابة لأن حقلًا أعيد تسميته، أو فشل في معالجة الأخطاء لأن أشكال الأخطاء مختلفة.
حتى عندما لا يتعطل شيء، يفقد الفريقان الثقة ويتوقفان عن استخدام المواصفة، وبالتالي تزول آلية الإنذار المبكر.
لأن الكود يعكس السلوك الحالي، بما في ذلك العيوب العرضية التي قد لا ترغب في التزامها على المدى الطويل.
افتراض أفضل: اكتب السلوك المقصود أولًا (المدخلات، المخرجات، الأخطاء)، ثم تحقق من أن التنفيذ يطابقه. هذا يعطيك عقدًا يمكنك فرضه بدلًا من لقطة للحالة الحالية فقط.
لكل نقطة نهاية التقط:
إذا استطعت كتابة طلب ملموس وردّين، عادةً تكون كافياً لصياغة مسودة مواصفة صادقة.
اختر شكل جسم خطأ واحدًا وأعد استخدامه في كل مكان.
افتراض بسيط وعملي إما:
{ "error": "message" }، أو{ "error": { "code": "...", "message": "...", "details": ... } }ثم اجعلها متناسقة عبر النقاط النهائية والأمثلة. الاتساق أهم من التعقيد لأن العملاء سيعتمِدون على هذا الشكل.
أعطِ Claude Code ملاحظات السلوك وقواعد صارمة بعدم الاختراع، واطلب علامات TODO ضمن ASSUMPTIONS عندما تكون الأمور غامضة. إرشادات عملية:
راجع قائمة ASSUMPTIONS أولًا بعد التوليد—هناك يبدأ الكذب إذا قبلت التخمينات.
تحقق من صحة المواصفة داخليًا أولًا:
هذا يلتقط مواصفات "الأمنيات" قبل مقارنة الإنتاج.
عامل تنفيذ الخادم كحقيقة تجارب المستخدمين اليوم، وقرّر حالة بالملف:
اجعل التغييرات صغيرة وقابلة للمراجعة: نقطة نهاية واحدة أو استجابة واحدة في كل مرة.
التحقق على الخادم يرفض الطلبات التي تنتهك العقد ويعيد خطأًا واضحًا وصريحًا (رمز+شكل).
التحقق على العميل يكتشف تغييرات الاستجابة المكسرة مبكرًا عن طريق التأكد من ما تعتمد عليه فعليًا:
تجنب المطالبة بكل حقل اختياري حتى لا تفشل الاختبارات على إضافات غير ضارة.
روتين عملي يعمل دون إبطاء الفرق:
إذا كنت تستخدم Koder.ai، احتفظ بملف OpenAPI بجانب الكود، التقط لقطات قبل التعديلات، وتراجع إذا صار الفرق مربكًا.