DEV Community

Cover image for ما هو تطوير واجهات برمجة التطبيقات بمنهجية المواصفات أولاً؟
Yusuf Khalidd
Yusuf Khalidd

Posted on • Originally published at apidog.com

ما هو تطوير واجهات برمجة التطبيقات بمنهجية المواصفات أولاً؟

معظم أخطاء واجهات برمجة التطبيقات (API) ليست أخطاء برمجية، بل أخطاء في العقد. الواجهة الأمامية تتوقع userId، والواجهة الخلفية ترسل user_id، ولا يكتشف أحد ذلك حتى QA. تطوير الـ API المعتمد على المواصفات أولًا يحل هذا بتعريف العقد قبل كتابة كود الخادم.

جرّب Apidog اليوم

في هذا الدليل ستكتب مواصفات OpenAPI صغيرة يدويًا، ثم تستخدم الملف نفسه لإنشاء mock server، واختبارات عقد، ووثائق API قبل تنفيذ أي endpoint. قد تسمع هذا الأسلوب بأسماء مثل: spec-first، design-first، أو contract-first. الفكرة واحدة: اتفق على الواجهة أولًا، ثم ابنِ عليها.

ما هو تطوير الـ API المعتمد على المواصفات أولًا؟

تطوير واجهات برمجة التطبيقات بالمواصفات أولًا يعني كتابة عقد قابل للقراءة آليًا، غالبًا باستخدام OpenAPI، قبل تنفيذ الـ endpoint.

هذا العقد يحدد:

  • المسارات مثل /users
  • معاملات الاستعلام والمسار
  • جسم الطلب requestBody
  • شكل الاستجابة
  • أكواد الحالة
  • المخططات المشتركة schemas

بدل أن تكون الوثائق نتيجة متأخرة للكود، تصبح المواصفات هي مصدر الحقيقة. الواجهة الأمامية تبني على mock generated من المواصفات، وQA يكتب اختبارات العقد منها، والواجهة الخلفية تنفذ بناءً عليها.

النتيجة العملية: مشاكل التكامل تظهر مبكرًا، قبل أن تصبح مكلفة.

دورة حياة spec-first مقابل code-first

ينتج النهجان في النهاية endpoints مشابهة، لكن الاختلاف في متى تظهر المشاكل ومن يستطيع البدء مبكرًا.

مقارنة دورة حياة spec-first و code-first

في code-first، غالبًا تكتب المعالجات أولًا ثم توثقها لاحقًا. في spec-first، تكتب العقد أولًا، ثم يعمل كل فريق بالتوازي بناءً على التعريف نفسه.

مثال عملي: إنشاء OpenAPI لـ /users

سنصمم endpoint بسيطة للمستخدمين. الهدف ليس بناء API كاملة، بل رؤية كيف يتحول ملف OpenAPI واحد إلى عقد قابل للاستخدام.

1. ابدأ برأس ملف OpenAPI

openapi: 3.0.3
info:
  title: Users API
  version: 1.0.0

servers:
  - url: https://api.example.com/v1
Enter fullscreen mode Exit fullscreen mode

هذا الجزء يحدد إصدار OpenAPI واسم الـ API ورابط الخادم الأساسي.

2. عرّف مخطط User

ضع الأشكال المشتركة داخل components/schemas حتى تعيد استخدامها لاحقًا باستخدام $ref.

components:
  schemas:
    User:
      type: object
      required:
        - id
        - email
        - createdAt
      properties:
        id:
          type: string
          format: uuid
        email:
          type: string
          format: email
        name:
          type: string
        createdAt:
          type: string
          format: date-time
Enter fullscreen mode Exit fullscreen mode

هذا المخطط يقول إن كائن User يجب أن يحتوي على:

  • id
  • email
  • createdAt

كما يحدد صيغًا مهمة مثل uuid وemail وdate-time.

3. أضف GET /users

paths:
  /users:
    get:
      summary: List users
      operationId: listUsers
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
            maximum: 100
      responses:
        "200":
          description: A list of users
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/User"
Enter fullscreen mode Exit fullscreen mode

هنا عرّفنا endpoint ترجع قائمة مستخدمين، مع query parameter اسمه limit وحده الأقصى 100.

4. أضف POST /users

paths:
  /users:
    post:
      summary: Create a user
      operationId: createUser
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - email
              properties:
                email:
                  type: string
                  format: email
                name:
                  type: string
      responses:
        "201":
          description: User created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/User"
        "400":
          description: Invalid request body
Enter fullscreen mode Exit fullscreen mode

هذه العملية تحدد أن إنشاء المستخدم يتطلب email، ويمكن أن يحتوي اختياريًا على name. عند النجاح ترجع 201 وكائن User. عند الخطأ ترجع 400.

5. الملف الكامل

استخدم هذا الملف كنقطة بداية قابلة للتشغيل:

openapi: 3.0.3

info:
  title: Users API
  version: 1.0.0

servers:
  - url: https://api.example.com/v1

paths:
  /users:
    get:
      summary: List users
      operationId: listUsers
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
            maximum: 100
      responses:
        "200":
          description: A list of users
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/User"

    post:
      summary: Create a user
      operationId: createUser
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - email
              properties:
                email:
                  type: string
                  format: email
                name:
                  type: string
      responses:
        "201":
          description: User created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/User"
        "400":
          description: Invalid request body

components:
  schemas:
    User:
      type: object
      required:
        - id
        - email
        - createdAt
      properties:
        id:
          type: string
          format: uuid
        email:
          type: string
          format: email
        name:
          type: string
        createdAt:
          type: string
          format: date-time
Enter fullscreen mode Exit fullscreen mode

بهذا أصبح لديك عقد يحدد الحقول، الأنواع، القيود، وأكواد الحالة قبل كتابة أي كود backend.

ماذا تفعل بهذا الملف؟

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

1. إنشاء Mock Server

خادم الـ mock يقرأ مواصفات OpenAPI ويعيد استجابات مطابقة للمخططات.

مثال: الواجهة الأمامية يمكنها استدعاء:

GET /users?limit=20
Enter fullscreen mode Exit fullscreen mode

وتحصل على استجابة مثل:

[
  {
    "id": "4c84f9a2-8c9c-4e6e-b1c3-123456789abc",
    "email": "user@example.com",
    "name": "Ahmed",
    "createdAt": "2026-06-02T10:00:00Z"
  }
]
Enter fullscreen mode Exit fullscreen mode

هذا يسمح لفريق frontend بالبدء قبل توفر التنفيذ الحقيقي.

2. كتابة اختبارات عقد Contract Tests

بما أن المواصفات تحدد أنواع الحقول والاستجابات، يمكنك استخدامها للتحقق من أن التنفيذ الحقيقي لا يخرج عن العقد.

أمثلة على ما يجب اختباره:

  • POST /users يرجع 201 عند إرسال email صالح.
  • الاستجابة تطابق مخطط User.
  • الطلب بدون email يرجع 400.
  • GET /users يرجع array من كائنات User.
  • limit لا يتجاوز 100.

الفكرة ليست اختراع assertions جديدة، بل التحقق من أن الكود يطابق ما اتفق عليه الفريق.

3. توليد الوثائق

وثائق الـ API يمكن عرضها مباشرة من ملف OpenAPI. كل endpoint وparameter وschema يظهر من المصدر نفسه، لذلك لا تحتاج إلى نسخة وثائق منفصلة يمكن أن تصبح قديمة.

هذا يتكامل جيدًا مع سير عمل واجهة برمجة التطبيقات الأصلي لـ Git: المواصفات ملف نصي، وكل تغيير يظهر كـ diff يمكن مراجعته في pull request.

تنفيذ ذلك في Apidog

يدعم Apidog هذا الأسلوب من خلال وضع المواصفات أولًا Spec-First Mode. بدل التعامل مع OpenAPI كتصدير نهائي، يتعامل معه كمصدر المشروع.

وضع المواصفات أولًا في Apidog

سير العمل العملي يكون كالتالي:

  1. اكتب أو الصق مواصفات /users في محرر OpenAPI.
  2. يحلل Apidog الملف وينشئ endpoints بناءً عليه.
  3. يتم إنشاء mock server للعمليات الموجودة في المواصفات.
  4. تبدأ الواجهة الأمامية باستخدام الـ mock.
  5. يتم توليد الوثائق من المواصفات نفسها.
  6. عند جاهزية backend، شغّل العمليات كحالات اختبار.
  7. تحقق من أن الاستجابات الحقيقية تطابق schemas المعلنة.

الميزة المهمة هنا هي مزامنة Git ثنائية الاتجاه. تعيش المواصفات في المستودع، وتتم مراجعة التغييرات كـ commits. إذا عدّلت YAML في محررك ودفعت التغيير، يستطيع Apidog مزامنته. وإذا عدّلت داخل Apidog، يمكن أن تهبط التغييرات كتثبيت يمكن للفريق مراجعته.

للمقارنة الأعمق بين هذا النهج ونهج التصميم أولًا، راجع: المواصفات أولًا مقابل التصميم أولًا في Apidog.

قائمة مراجعة قبل اعتماد المواصفات

قبل أن يبدأ الفريق بالبناء على ملف OpenAPI، تحقق من التالي:

  • ملف OpenAPI صالح ولا يحتوي على أخطاء schema.
  • كل endpoint يحتوي على response نجاح واحد على الأقل.
  • كل endpoint يحتوي على response خطأ واحد على الأقل.
  • الأشكال المشتركة موجودة في components/schemas.
  • يتم استخدام $ref بدل نسخ schemas في أكثر من مكان.
  • الحقول المطلوبة محددة بـ required.
  • الصيغ مثل uuid وemail وdate-time مضبوطة عند الحاجة.
  • معاملات الاستعلام لها أنواع وحدود واضحة.
  • ملف المواصفات محفوظ في Git.
  • التغييرات على العقد تتم مراجعتها عبر pull requests.
  • mock server يعمل من نفس المواصفات.
  • اختبارات العقد تتحقق من الاستجابات الحقيقية.
  • الوثائق المنشورة مولدة من الملف نفسه.

إذا تحققت هذه النقاط، يمكن للفرق العمل بالتوازي بناءً على عقد واحد بدل الاعتماد على افتراضات مختلفة.

الأسئلة الشائعة

هل spec-first هو نفسه design-first؟

غالبًا نعم. مصطلحات spec-first وdesign-first وcontract-first تشير إلى المبدأ نفسه: تعريف الواجهة قبل التنفيذ. الاختلاف أن spec-first يركز على ملف المواصفات نفسه، مثل OpenAPI، كمخرج عملي قابل للاستخدام.

هل يجب كتابة YAML يدويًا؟

لا. يمكنك استخدام محرر مرئي لإنتاج OpenAPI، أو كتابة YAML مباشرة. المهم أن يكون العقد موجودًا ومتفقًا عليه قبل تنفيذ الكود.

في فرق كثيرة، يبدأ التصميم بصريًا ثم تتم مراجعة YAML في Git قبل التنفيذ.

كيف أمنع تباعد المواصفات عن الكود؟

اجعل المواصفات مصدر الحقيقة، ثم افرضها آليًا:

  • خزّن ملف OpenAPI في Git.
  • راجع أي تغيير في العقد عبر pull request.
  • شغّل contract tests في CI.
  • افشل build إذا لم تطابق الاستجابة المخطط.
  • استخدم مزامنة ثنائية الاتجاه إذا كان الفريق يحرر المواصفات من أكثر من مكان.

الخلاصة

تطوير الـ API بالمواصفات أولًا هو تغيير بسيط في الترتيب: اكتب العقد، راجعه، ثم نفّذ الكود. لكنه يقلل أخطاء التكامل، ويسمح للواجهة الأمامية وQA والواجهة الخلفية بالعمل بالتوازي.

إذا أردت تجربة الدورة كاملة، افتح وضع المواصفات أولًا Spec-First Mode في Apidog واربطه بمستودعك.

Top comments (0)