# رحلة Shoprocket نحو الخدمات المصغّرة، الجزء 1: ما أخطأتُ فيه عند تفكيك النظام الأحادي

> مقال من فريق الهندسة في سنوات Shoprocket الأولى عن أول محاولة لاستخراج خدمة من نظام PHP أحادي. لماذا اخترت الخدمة الأولى الخاطئة، وماذا علّمني الترابط الشديد، ونصيحة Newman التي كان عليّ أن آخذ بها مبكرًا.

Winston Berty  - 17 مارس 2016 - القراءة في 5 دقيقة

بعد بضعة أشهر من انضمامي إلى Shoprocket، بدأت أشعر بالإحباط. كان لدينا تطبيق PHP يعمل عليه فريق صغير من المطورين البارعين المنتشرين حول العالم، وبدا لي أن إصلاح الأخطاء يولّد أخطاء جديدة، وأن دمج الميزات الجديدة ليس بالسهولة التي ينبغي، وأن عمليات النشر نادرة ومرهقة. والسبب: كود شديد الترابط.

كان لدينا تطبيق أحادي، موجود تقريبًا بالكامل في مستودع GitHub واحد. وغالبًا ما كان تحديث ميزة أو إصلاحها يتطلب تعديلات في عدة أماكن. وللاختبار كانت لدينا عملية مراجعة نظراء يجب أن يوافق فيها مطوران آخران على الأقل على الفرع قبل دمجه في master ونشره. كل هذا يعني أنه حين يتسلل خطأ، يصعب غالبًا تحديد التغيير الذي كسر الأمور. وحين نجده، يمر الإصلاح بالعملية نفسها، ويُعاد نشر التطبيق كله.

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

## ما ظننته عن الخدمات المصغّرة

لا يوجد تعريف رسمي للخدمات المصغّرة، لكنني خرجت من بحثي بأن بنية الخدمات المصغّرة هي طريقة لتصميم التطبيقات كأنظمة موزعة من خدمات مستقلة، كل منها شديد التخصص ولها دورة حياة خاصة بها. وللحصول على مقدمة مفصلة، [مقال](https://martinfowler.com/articles/microservices.html) مارتن فاولر ممتاز.

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

اقتنعت تمامًا. كانت Shoprocket ستفكك نظامها الأحادي. وهذا هو الجزء 1 من سلسلة قصيرة تتبع الرحلة. آمل أن يتعلم القراء الذين يخططون لانتقال مماثل أو يمرون به من نجاحاتنا وإخفاقاتنا.

## التحدي الأول كان بشريًا لا تقنيًا

كان عليّ أن أقنع بقية الفريق بالفكرة. كانوا فضوليين لكنهم لم يشاركوني الحماس، وترددوا في التخلي عن ساعات التطوير في هذه المرحلة المبكرة من عمر المنتج. ولحسن الحظ، أراد مدير التقنية أن أنظر في إدارة الجلسات لدينا، فاغتنمت الفرصة: أقنعته بأنني أستطيع فصل خدمة للجلسات.

بأثر رجعي، كان هذا اختيارًا سيئًا للخدمة الأولى. يتضمن منتجنا أداة JavaScript [تتيح التجارة الإلكترونية على أي موقع](https://v3.shoprocket.io/ar/features/sell-on-any-website.md). نتعامل مع الجلسات كمورد، ونحفظ معلومات الجلسة في قاعدة البيانات لتحليل التخلي عن السلال ومؤشرات أداء أخرى. لكن هذا المورد ليس ملموسًا كالطلبات أو بنود الطلب، وكنا نستخدم الجلسات في كل تغيير تقريبًا في حالة التطبيق. هذا يعني أن الخدمة ستكون حتمًا كثيرة الحديث مع بقية التطبيق، وهو أمر لم أتوقعه وجعل مهمتي أصعب.

## ما تعلمته من البناء الفعلي

كثّفت بحثي. وإلى جانب فاولر، تبيّن أن كتاب سام نيومان **Building Microservices** مرجع لا غنى عنه.

نصيحة نيومان، بأثر رجعي، هي النصيحة التي كان عليّ اتباعها: أعد أولًا هيكلة التطبيق القائم إلى وحدات تعكس السياقات المحدودة للمجال. وحين يرضى المطورون عن الحدود، *عندها* افصل الوحدات إلى خدماتها الخاصة. والسبب أن تفكيك وإعادة كتابة وحدات ذات حدود سيئة أسهل بكثير من تفكيك وإعادة كتابة خدمات كاملة بكل ما فيها من كود ربط إضافي وموارد دائمة.

لم أتبع تلك النصيحة. ومن شدة رغبتي في بناء مكوّن خاص بي، مضيت في خدمة الجلسات.

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

تبيّن أن إدارة الجلسات شديدة الترابط ببقية الكود. استبدال استدعاءات الدوال باستدعاءات API كان عملًا بطيئًا. ولأن لخدمة الجلسات والنظام الأحادي مخططي قاعدة بيانات منفصلين، اضطررت إلى إعادة كتابة كل منطق في النظام الأحادي يستخدم موارد الجلسة من القاعدة القديمة، وإعادة هيكلة البيانات عند حدود التطبيق للحفاظ على توافق العملاء مثل أداة JavaScript لدينا.

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

## التقييم الصريح

قد تدخل الخدمة الإنتاج قريبًا. لكنني أشعر الآن أنه كان عليّ اتباع نصيحة نيومان وتوجيه جهدي إلى تقسيم التطبيق القائم إلى وحدات أولًا. فائدة وجود خدمة واحدة تعيش وحدها هامشية. الفائدة الحقيقية تأتي من تفكيك المنظومة كلها، على الأقل إلى خدمات كبيرة الحجم تتحدث مع بعضها أقل ما يمكن. وهذا يتطلب حدودًا مدروسة جيدًا بين المكونات، ولم نكن قد وصلنا إلى ذلك بعد.

ما زلت مقتنعًا بالخدمات المصغّرة كفكرة. وأرى محاولتي تجربة مفيدة. تعلمت الكثير عن بنية التطبيقات ونمذجة المجال ومبادئ REST، وكان لتلك الدروس أثر ممتد في أجزاء أخرى من كودنا.

لكل من يفكر في انتقال مماثل، هذه توصياتي الصريحة:

- اقرأ عن الموضوع قدر المستطاع قبل الالتزام
- أجّل العمل حتى تصبح واثقًا فعلًا من قاعدة الكود الحالية ونموذج المجال لديك
- تذكّر أن هناك طرقًا أخرى لإضفاء الاستقرار والمرونة على نظام أحادي. الاختبارات الآلية للوحدات والوظائف تساعد كثيرًا. والتطوير الموجّه بالاختبار يقلل الانحدارات. والتوسع الأفقي يجعل عمليات النشر أقل إيلامًا
- ابدأ بتقسيم نظامك الأحادي إلى وحدات قبل استخراج الخدمات

ستواصل Shoprocket رحلتها. الجزء 2 هو حيث تصبح الأمور أكثر إثارة.

---

*نُشر في الأصل بوصفه الأول في سلسلة قصيرة توثّق انتقال Shoprocket المبكر بعيدًا عن نظام PHP أحادي. واستمرت الرحلة الكاملة، بما فيها الأخطاء التي صُحّحت في تكرارات لاحقة، عبر كل إعادة كتابة كبرى للمنصة منذ ذلك الحين.*

---

- HTML version: https://v3.shoprocket.io/ar/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith
- Language: العربية (ar)
- Also in: [Deutsch](https://v3.shoprocket.io/de/blog/shoprocket-microservices-teil-1-monolith-zerlegen-fehler.md), [Ελληνικά](https://v3.shoprocket.io/el/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md), [English](https://v3.shoprocket.io/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md), [Español](https://v3.shoprocket.io/es/blog/shoprocket-microservicios-parte-1-lo-que-hice-mal-monolito.md), [Français](https://v3.shoprocket.io/fr/blog/shoprocket-vers-les-microservices-partie-1-decouper-le-monolithe.md), [עברית](https://v3.shoprocket.io/he/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md), [हिन्दी](https://v3.shoprocket.io/hi/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md), [Bahasa Indonesia](https://v3.shoprocket.io/id/blog/perjalanan-shoprocket-menuju-microservices-bagian-1-salah-memecah-monolit.md), [Italiano](https://v3.shoprocket.io/it/blog/viaggio-di-shoprocket-verso-i-microservizi-parte-1-cosa-ho-sbagliato-sul-monolite.md), [日本語](https://v3.shoprocket.io/ja/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md), [Lietuvių](https://v3.shoprocket.io/lt/tinklarastis/shoprocket-kelione-i-mikropaslaugas-1-dalis.md), [Norsk](https://v3.shoprocket.io/nb/blogg/shoprockets-vei-mot-mikrotjenester-del-1-hva-jeg-tok-feil-av.md), [Nederlands](https://v3.shoprocket.io/nl/blog/shoprocket-microservices-deel-1-monoliet-opknippen.md), [Polski](https://v3.shoprocket.io/pl/blog/droga-shoprocket-do-mikroserwisow-czesc-1-rozbijanie-monolitu.md), [Português](https://v3.shoprocket.io/pt/blog/jornada-do-shoprocket-para-microsservicos-parte-1-o-que-errei-ao-quebrar-o-monolito.md), [Română](https://v3.shoprocket.io/ro/blog/drumul-shoprocket-spre-microservicii-partea-1-ce-am-gresit-cu-monolitul.md), [Русский](https://v3.shoprocket.io/ru/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md), [ไทย](https://v3.shoprocket.io/th/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md), [Türkçe](https://v3.shoprocket.io/tr/blog/shoprocket-mikroservis-yolculugu-1-monoliti-parcalarken-yanlis-yaptiklarim.md), [中文](https://v3.shoprocket.io/zh/blog/shoprockets-journey-to-microservices-part-1-what-i-got-wrong-about-breaking-up-the-monolith.md)
