عندما يضغط المستخدم زرًا في تطبيق، أو يرسل طلبًا من واجهة Frontend، أو يطلب بوت بيانات من الخادم، يبدو الأمر بسيطًا: طلب يدخل، وبيانات تخرج. لكن خلف هذا السطر البسيط توجد سلسلة كاملة من العمليات. وهنا تبدأ هندسة الـBackend. الـAPI ليست مجرد رابط كثير من المطورين في بداياتهم يتعاملون مع الـAPI على أنها مجرد URL نرسل إليه Request ونحصل منه على JSON. هذا صحيح، لكنه وصف سطحي جدًا. الـAPI هي عقدة اتصال (Contract) بين أجزاء مختلفة من النظام. عندما يرسل العميل: GET /api/books/42 فهو لا يقول للخادم فقط: “أعطني الكتاب رقم 42”. بل يلتزم بمجموعة من القواعد: * ما هو الـHTTP Method المستخدم؟ * ما شكل الـURL؟ * هل يحتاج الطلب إلى Authentication؟ * ما البيانات التي يمكن إرسالها؟ * ما شكل الاستجابة؟ * ماذا يحدث إذا لم يجد الخادم المورد؟ * ما الأخطاء التي يمكن أن يعيدها؟ كل هذه التفاصيل تشكل الـAPI Contract. رحلة Request واحدة لنأخذ مثالًا بسيطًا. لنفترض أن لدينا تطبيقًا يحتوي على مكتبة كتب، ويريد المستخدم فتح كتاب معين. يرسل التطبيق: GET /api/books/42 Authorization: Bearer <token> الطلب يبدأ من العميل، لكنه لا يصل مباشرة إلى دالة Python. قد يمر أولًا عبر: Client ↓ DNS ↓ Nginx ↓ Application Server ↓ Flask / FastAPI ↓ Authentication ↓ Business Logic ↓ Database ↓ Response ↓ Client كل طبقة هنا لها مسؤولية مختلفة. وهذا أحد أهم المفاهيم التي يجب فهمها في تطوير الـBackend: الكود الذي يعالج الطلب ليس النظام كله. لماذا لا نضع كل شيء داخل Route؟ من السهل كتابة شيء مثل: @app.get("/books/<int:book_id>") def get_book(book_id): book = db.query(Book).filter(Book.id == book_id).first() if not book: return {"error": "Book not found"}, 404 return { "id": book.id, "title": book.title } وسيعمل. لكن عندما يكبر المشروع، تبدأ المشكلة. ماذا لو احتجنا إلى: * التحقق من صلاحيات المستخدم؟ * تسجيل العملية في Audit Log؟ * استخدام Redis؟ * تطبيق Rate Limiting؟ * استدعاء خدمة خارجية؟ * إعادة استخدام منطق البحث في أكثر من Endpoint؟ * تغيير قاعدة البيانات لاحقًا؟ هنا تظهر أهمية فصل المسؤوليات (Separation of Concerns). فالـRoute يجب ألا يتحول إلى المكان الذي يعيش فيه النظام بأكمله. يمكن أن تصبح البنية مثلًا: Route ↓ Service ↓ Repository ↓ Database الـRoute يستقبل الطلب. الـService يحتوي منطق العمل. والـRepository يتعامل مع الوصول إلى البيانات. ليست هذه البنية الوحيدة الصحيحة، وليست قاعدة يجب تطبيقها على كل مشروع، لكنها تصبح مفيدة عندما يبدأ النظام في النمو. REST ليس مجرد استخدام GET وPOST من الأخطاء الشائعة اختزال REST في HTTP Methods. REST في الأساس أسلوب معماري يعتمد على التعامل مع Resources. فبدلًا من التفكير: /getBook /createBook /deleteBook يمكن التفكير في المورد نفسه: GET /books/42 POST /books PATCH /books/42 DELETE /books/42 هنا الـURL يمثل المورد، بينما الـHTTP Method يحدد العملية المطلوبة عليه. لكن حتى هذا لا يعني أن كل API يجب أن تكون RESTful بشكل صارم. الهدف من التصميم الجيد ليس الالتزام بشعارات معمارية، وإنما بناء واجهة واضحة، متوقعة، وقابلة للصيانة. المشكلة الحقيقية تبدأ عندما يكبر النظام في مشروع صغير، يمكنك كتابة API خلال ساعات. لكن النظام الحقيقي يفرض أسئلة أصعب: ماذا يحدث عند وجود آلاف الطلبات؟ ماذا لو أصبحت قاعدة البيانات عنق الزجاجة؟ ماذا لو تكرر نفس الطلب آلاف المرات؟ ماذا لو توقف أحد الـServices؟ كيف نراقب الأخطاء؟ كيف نمنع إساءة استخدام الـAPI؟ كيف نحافظ على التوافق مع العملاء القدامى عندما نغير الـAPI؟ هنا تنتقل من مجرد كتابة Endpoint إلى هندسة نظام. ولهذا فإن فهم الـAPI لا يبدأ من كتابة: @app.get(...) بل من فهم الرحلة الكاملة للطلب، والمسؤوليات الموجودة حوله، والقرارات التي تجعل النظام قابلًا للاستمرار. ⸻ خاتمة الـBackend ليس مجموعة Routes. والـAPI ليست مجرد JSON. والخادم ليس مجرد مكان نضع فيه الكود. هذه كلها أجزاء من منظومة أكبر. كلما فهمت العلاقة بين الـHTTP، والـApplication Server، والـBusiness Logic، وقاعدة البيانات، والـCaching، والـAuthentication، والـInfrastructure، بدأت تنظر إلى البرمجة بطريقة مختلفة. وهذا هو الهدف من بروتوكول: ألا نكتفي بشرح كيف نكتب الكود، بل نفهم لماذا بُني بهذه الطريقة، وماذا يحدث خلفه، ومتى يصبح هذا التصميم مشكلة.