ذاكرة فريقنا المعمارية قصيرة: كيف أنقذتنا ‘سجلات القرارات المعمارية’ (ADRs) من جحيم إعادة اكتشاف العجلة؟

السلام عليكم يا جماعة الخير،

قبل سنتين تقريبًا، كنا في خضم مشروع كبير وحساس. الفريق كان شعلة من النشاط، والكل يعمل بجد. انضم إلينا في تلك الفترة مهندس جديد، شاب ذكي ومتحمس اسمه “سعيد”. بعد أسبوع من انضمامه، وأثناء اجتماع التخطيط، طرح سعيد سؤالًا بريئًا لكنه كان كالقنبلة: “يا جماعة، أنا أرى أننا نستخدم RabbitMQ لإدارة الطوابير (Queues)، بس ليش ما بنستخدم Kafka؟ الكل بيحكي إنه أسرع وأقوى للمشاريع الكبيرة.”

ساد صمت في الغرفة. نظرتُ أنا وكبير المهندسين الآخر لبعضنا البعض، وظهرت على وجوهنا علامات حيرة… حقيقةً، لم نتذكر السبب الدقيق! نعرف أننا عقدنا اجتماعات مطولة قبل عام كامل، وقمنا بعمل مقارنات واختبارات، وفي النهاية اخترنا RabbitMQ لسبب وجيه. لكن ما هو هذا السبب الآن؟ هل كان يتعلق ببساطة الإعداد؟ أم بنمط معين من الرسائل كنا نحتاجه؟ لا أحد يتذكر التفاصيل.

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

ما هي “ذاكرة الفريق المعمارية القصيرة”؟

هذا المصطلح ليس مصطلحًا علميًا، بل هو وصفي لحالة شائعة جدًا في فرق البرمجيات. ببساطة، هو ميل الفرق مع مرور الوقت إلى نسيان “لماذا” تم اتخاذ القرارات المعمارية الهامة. نتذكر “ماذا” قررنا (نستخدم قاعدة بيانات PostgreSQL)، لكننا ننسى “لماذا” (لأننا كنا بحاجة لدعم قوي للبيانات الجغرافية وتوابع الـ Full-Text Search المتقدمة، وفضلناها على MySQL لذلك السبب).

هذه الظاهرة لها عواقب وخيمة، منها:

  • إعادة اختراع العجلة: كما حصل معنا في قصة سعيد و RabbitMQ، نقضي وقتًا ثمينًا في إعادة تقييم قرارات تم حسمها بالفعل.
  • صعوبة تدريب الأعضاء الجدد: لا يستطيع الأعضاء الجدد فهم السياق التاريخي للنظام، مما يجعلهم يكررون نفس الأسئلة أو يقترحون حلولًا تم استبعادها سابقًا لأسباب وجيهة.
  • تآكل المعمارية (Architectural Drift): عندما تُنسى المبادئ الأساسية، تبدأ القرارات الجديدة بالانحراف عن الرؤية الأصلية، مما يؤدي إلى نظام غير متجانس ومليء بالديون التقنية.
  • الخوف من التغيير: عندما لا نفهم لماذا تم بناء شيء بطريقة معينة، نخشى لمسه أو تعديله، مما يؤدي إلى جمود النظام وتوقفه عن التطور.

الحل السحري (والمملّ قليلًا): سجلات القرارات المعمارية (ADRs)

بعد حادثة Kafka، قررت أن هذا الوضع لا يمكن أن يستمر. بدأت البحث عن حلول، ووجدت ضالتي في مفهوم بسيط لكنه عبقري: Architectural Decision Records (ADRs) أو “سجلات القرارات المعمارية”.

الـ ADR هو ببساطة مستند نصي قصير (عادةً ملف Markdown) يوثّق قرارًا معماريًا واحدًا ذا أهمية. الفكرة ليست في كتابة توثيق شامل وممل من 100 صفحة، بل في إنشاء سجلات صغيرة ومركزة وسهلة القراءة تجيب على سؤال “لماذا؟”.

“الـ ADR هو رسالة تكتبها إلى نفسك وفريقك في المستقبل.”

الجميل في الـ ADRs أنها تعيش مع الكود. أفضل مكان لحفظها هو في مجلد خاص (مثل docs/adrs) داخل مستودع الكود (Git Repository) نفسه. بهذا، يصبح تاريخ القرارات جزءًا لا يتجزأ من تاريخ المشروع.

تشريح سجل القرار المعماري (ADR)

معظم الـ ADRs تتبع هيكلًا بسيطًا وموحدًا لسهولة القراءة. أشهر النماذج هو الذي اقترحه مايكل نايجارد (Michael Nygard). يتكون السجل عادةً من الأجزاء التالية:

العنوان (Title)

جملة قصيرة وواضحة تصف القرار. على سبيل المثال: “ADR-001: استخدام PostgreSQL كقاعدة بيانات أساسية”. الرقم يساعد في الترتيب والإشارة.

الحالة (Status)

توضح المرحلة التي يمر بها القرار. الحالات الشائعة هي:

  • مقترح (Proposed): القرار مطروح للنقاش ولم يتم اعتماده بعد.
  • مقبول (Accepted): تم الاتفاق على القرار ويجب الالتزام به.
  • مرفوض (Rejected): تم رفض الاقتراح بعد النقاش.
  • مُستبدَل (Superseded by ADR-XXX): تم اتخاذ قرار جديد يلغي هذا القرار (مع الإشارة إلى رقم الـ ADR الجديد).

السياق (Context)

هذا هو أهم جزء في الـ ADR. هنا تشرح المشكلة التي تحاول حلها، والقوى المؤثرة، والظروف المحيطة. إنه قسم الـ “لماذا”. لماذا نفكر في هذا التغيير أصلًا؟ ما هي المتطلبات والقيود؟

القرار (Decision)

هنا تصف بوضوح “ماذا” قررت. يجب أن يكون هذا القسم مباشرًا ومختصرًا. مثال: “سنقوم باستخدام مكتبة `React` لبناء واجهات المستخدم الأمامية لجميع المشاريع الجديدة.”

العواقب (Consequences)

لا يوجد قرار مثالي. كل خيار له إيجابيات وسلبيات. هذا القسم هو مكان الصدق والشفافية. هنا تذكر النتائج المترتبة على قرارك، الجيدة والسيئة.

  • إيجابية: “سنستفيد من النظام البيئي الضخم لـ React، وسهولة توظيف المطورين الذين يمتلكون هذه المهارة.”
  • سلبية: “هذا يضيف تعقيدًا في عملية الـ Build، ويتطلب من الفريق تعلم JSX ومفاهيم State Management.”

ذكر العواقب السلبية يثبت أنك فكرت في المقايضات (Trade-offs) واتخذت قرارًا مستنيرًا، وليس مجرد اتباع للموضة التقنية.

مثال عملي: “ليش اخترنا RabbitMQ؟”

لو كنا نستخدم الـ ADRs في ذلك الوقت، لكان بإمكاني ببساطة إرسال رابط لـ “سعيد” يشبه التالي:


# ADR-004: استخدام RabbitMQ كوسيط للرسائل (Message Broker)

**الحالة:** مقبول (Accepted)

**التاريخ:** 2021-03-15

## السياق (Context)

نحتاج إلى طريقة للتواصل غير المتزامن بين خدماتنا المصغرة (Microservices) مثل خدمة الطلبات (Orders) وخدمة الإشعارات (Notifications). المتطلبات الأساسية هي ضمان وصول الرسائل (Guaranteed Delivery)، ودعم أنماط توجيه معقدة (Complex Routing مثل topic-based)، وسهولة المراقبة والإدارة. تم تقييم كل من RabbitMQ و Apache Kafka.

## القرار (Decision)

قررنا اعتماد RabbitMQ كوسيط الرسائل الأساسي في نظامنا. سيتم استخدامه لجميع الاتصالات غير المتزامنة بين الخدمات. سنستخدم بروتوكول AMQP 0-9-1 للتوافقية العالية.

## العواقب (Consequences)

### الإيجابيات:
- يوفر RabbitMQ مرونة عالية في توجيه الرسائل (Exchanges, Bindings, Queues) وهو ما نحتاجه لسيناريوهات مثل "إرسال إشعار فقط للطلبات التي تزيد قيمتها عن 100 دولار".
- أسهل في الإعداد والإدارة والتشغيل لفرق صغيرة مقارنة بـ Kafka الذي يتطلب Zookeeper (في الإصدارات القديمة) وفهمًا أعمق لمفاهيم الـ Partitions و Offsets.
- له واجهة إدارة ممتازة تأتي مدمجة معه، تسهل تصحيح الأخطاء ومراقبة تدفق الرسائل.
- نضج المكتبات الخاصة به في لغات البرمجة التي نستخدمها (Node.js و Python).

### السلبيات:
- أداؤه (Throughput) أقل من Kafka في سيناريوهات تدفق البيانات الهائلة (High-volume streaming). حاليًا، حجم بياناتنا لا يتطلب قدرات Kafka القصوى.
- في حالة فشل الـ Broker الرئيسي، عملية الانتقال للـ Broker الاحتياطي (Failover) تتطلب إعدادات إضافية.
- RabbitMQ مصمم كنظام طوابير ذكي، وليس كسجل دائم للبيانات (Persistent Log) مثل Kafka. لا يمكننا إعادة قراءة الرسائل القديمة بعد استهلاكها بسهولة.

**الزبدة:** اخترنا RabbitMQ لأنه يمثل التوازن الأفضل بين المرونة وسهولة التشغيل لاحتياجاتنا الحالية. إذا تغير حجم بياناتنا بشكل جذري في المستقبل، يمكننا إعادة تقييم هذا القرار.

تخيلوا قوة هذا المستند! في دقيقتين، كان “سعيد” سيفهم السياق والقرار والمقايضات، وربما كان سيضيف ملاحظة قيمة بدلًا من أن نبدأ النقاش من الصفر.

نصائح من مطبخ أبو عمر: كيف تبدأ باستخدام الـ ADRs؟

بعد ما حكيت لكم القصة كلها، أكيد بدكم تعرفوا كيف تبدأوا. الموضوع أبسط مما تتخيلوا:

  1. ابدأ بسيطًا جدًا: لا تعقد الأمور. كل ما تحتاجه هو إنشاء مجلد جديد في مشروعك اسمه docs/adrs. أول قرار تتخذه، أنشئ ملفًا جديدًا باسم 0001-record-architecture-decisions.md واكتب فيه أنكم قررتم استخدام الـ ADRs!
  2. اجعلها جزءًا من عملية مراجعة الكود (Code Review): هل يقوم أحد المطورين بتقديم Pull Request يضيف مكتبة جديدة أو يغير بنية أساسية؟ اطلب منه إرفاق ADR مقترح مع الـ PR. هذا يفتح نقاشًا معماريًا موثقًا.
  3. لا توثق كل شاردة وواردة: الـ ADRs ليست للقرارات الصغيرة (مثل “لماذا سمينا هذا المتغير x؟”). احتفظ بها للقرارات ذات التأثير الكبير: اختيار قواعد البيانات، الأطر البرمجية (Frameworks)، أنماط التواصل بين الخدمات، اختيار مزود الخدمات السحابية، إلخ.
  4. كن صادقًا في “العواقب”: أصعب وأهم جزء. لا تخف من كتابة الجوانب السلبية لقرارك. هذا يظهر نضجًا هندسيًا ويبني الثقة.
  5. استخدم أدوات مساعدة (اختياري): هناك أدوات بسيطة في سطر الأوامر مثل adr-tools يمكنها مساعدتك في إنشاء ADRs جديدة بترقيم وتسلسل صحيحين. أمر بسيط مثل adr new "Use GraphQL for the public API" ينشئ لك ملفًا جديدًا بالقالب الصحيح.

الخلاصة، يا جماعة الخير 🚀

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

لا تنتظروا حتى تقعوا في فخ “إعادة اختراع العجلة” كما وقعنا. ابدأوا اليوم، ولو بـ ADR واحد. فريقكم في المستقبل (وربما أنت نفسك بعد ستة أشهر) سيشكركم على ذلك.

أبو عمر

سجل دخولك لعمل نقاش تفاعلي

كافة المحادثات خاصة ولا يتم عرضها على الموقع نهائياً

آراء من النقاشات

لا توجد آراء منشورة بعد. كن أول من يشارك رأيه!

آخر المدونات

أدوات وانتاجية

كانت واجهة الأوامر تبطئني: كيف أنقذني ‘الباحث التقريبي’ (Fuzzy Finder) من جحيم البحث عن الملفات والأوامر؟

كنت أقضي دقائق ثمينة في البحث عن ملفات وأوامر قديمة في واجهة الأوامر، مما كان يقتل إنتاجيتي. في هذه المقالة، أشارككم قصتي مع أداة 'الباحث...

29 مايو، 2026 قراءة المزيد
خوارزميات

كان التحقق من تفرد البيانات يقتل أداءنا: كيف أنقذنا ‘مرشح بلوم’ (Bloom Filter) من جحيم الاستعلامات المكلفة؟

في إحدى الليالي الطويلة والمُرهقة، كان أداء نظامنا ينهار تحت ضغط استعلامات التحقق من التفرد. في هذه المقالة، أسرد لكم كيف أنقذنا هيكل بيانات احتمالي...

29 مايو، 2026 قراءة المزيد
تسويق رقمي

كان موقعنا يخاطب الجميع ولا يخاطب أحداً: كيف أنقذنا ‘التقسيم السلوكي الديناميكي’ من جحيم التجربة العامة؟

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

29 مايو، 2026 قراءة المزيد
تجربة المستخدم والابداع البصري

عربات التسوق المهجورة: كيف أنقذنا متجرًا إلكترونيًا بـ’تأثير الطُعم’؟ قصة من قلب الميدان

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

29 مايو، 2026 قراءة المزيد
برمجة وقواعد بيانات

كانت استعلاماتنا تزحف كالسلحفاة: كيف أنقذتنا ‘الفهرسة الإستراتيجية’ من جحيم عمليات المسح الكامل للجدول (Full Table Scan)؟

أتذكر جيدًا ذلك اليوم الذي كاد فيه أحد المشاريع أن ينهار بسبب بطء قاتل في لوحة التحكم. في هذه المقالة، أشارككم قصة كيف أنقذتنا الفهرسة...

29 مايو، 2026 قراءة المزيد
البودكاست