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

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

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

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

ما هي سجلات القرارات المعمارية (ADRs)؟ وليش هي مهمة؟

بكل بساطة، الـ ADR هو وثيقة قصيرة، غالبًا ملف نصي (Markdown مثلًا)، يسجل قرارًا معماريًا واحدًا ومهمًا تم اتخاذه. الفكرة ليست في توثيق “ماذا” فعلنا فقط، بل الأهم هو توثيق “لماذا” فعلناه.

فكّر فيها كأنها “محضر اجتماع” لذاكرة مشروعك. عندما تتخذ قرارًا له تأثير كبير على النظام – مثل اختيار قاعدة بيانات، أو اعتماد نمط معماري معين (Microservices)، أو اختيار إطار عمل (Framework) – فإنك تقوم بكتابة ADR يشرح هذا القرار. هذه الوثيقة تصبح جزءًا لا يتجزأ من الكود المصدري نفسه، محفوظة في نظام التحكم بالإصدارات (مثل Git) بجانب الكود الذي تتأثر به.

“الـ ADR هو الذاكرة المؤسسية المكتوبة لفريقك التقني. إنه الجسر الذي يربط بين قرارات الماضي وتحديات المستقبل.”

أهميتها تكمن في حل مشاكل حقيقية نواجهها يوميًا:

  • تسهيل انضمام الأعضاء الجدد: بدلًا من أن يقضي المهندس الجديد أسابيع في محاولة فك طلاسم الكود وسؤال الجميع “ليش عملتوا هيك؟”، يمكنه ببساطة قراءة سجلات القرارات وفهم السياق التاريخي للمشروع بسرعة.
  • منع إعادة النقاشات القديمة: كم مرة أعدنا فتح نقاش حول قرار حُسم قبل أشهر لأننا نسينا الأسباب؟ الـ ADR يضع حدًا لهذا الأمر. إذا أراد أحدهم إعادة فتح النقاش، يجب أن يأتي بمعلومات جديدة لم تكن متاحة وقت اتخاذ القرار الأصلي.
  • تحسين التواصل والمواءمة: عملية كتابة ADR تجبر الفريق على التفكير بوضوح في خياراتهم وعواقبها، مما يؤدي إلى قرارات أفضل وتوافق أكبر بين أعضاء الفريق.

  • توفير سجل تاريخي: بعد سنوات، عندما تحتاج إلى تحديث جزء من النظام، يمكنك العودة إلى الـ ADRs لفهم القيود والافتراضات التي بُني عليها القرار الأصلي، مما يجعل عملية التحديث أكثر أمانًا وفعالية.

كيف تبدو بنية الـ ADR؟ (الهيكل الأساسي)

لا يوجد شكل مقدس للـ ADR، لكن معظم القوالب تتفق على عناصر أساسية. القالب الذي أفضّله، والمستوحى من عمل مايكل نايجارد (Michael Nygard)، بسيط وفعّال جدًا. دعونا نستعرض مكوناته:

العنوان (Title)

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

الحالة (Status)

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

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

السياق (Context)

هذا هو أهم جزء في رأيي. هنا تروي القصة. ما هي المشكلة التي نحاول حلها؟ ما هي الظروف والقوى (forces) التي تؤثر على القرار؟ ما هي المتطلبات التقنية أو متطلبات العمل التي دفعتنا للتفكير في هذا الأمر أصلًا؟

القرار (Decision)

هنا تذكر بوضوح وبشكل مباشر ما هو الحل الذي اخترته. جملة أو جملتان كافيتان. “سنقوم باستخدام مكتبة X لتنفيذ المهمة Y.”

الخيارات المطروحة (Options Considered)

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

العواقب (Consequences)

كل قرار له عواقب، إيجابية وسلبية (trade-offs). كن صريحًا وشفافًا هنا.

  • إيجابية: ما الذي سنكسبه من هذا القرار؟ (سرعة في التطوير، أداء أفضل، تكلفة أقل؟)
  • سلبية: ما الذي سنخسره أو ما هي المخاطر الجديدة التي ستظهر؟ (تعقيد إضافي، الاعتماد على طرف ثالث، صعوبة في التوسع مستقبلًا؟)

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

مثال عملي: خلّينا نكتب ADR مع بعض

لنعُد إلى قصة اجتماعنا، ولنتخيل أننا قررنا الآن توثيق قرارنا باختيار RabbitMQ. هكذا سيبدو الـ ADR:


# ADR-004: اعتماد RabbitMQ كوسيط رسائل للعمليات غير المتزامنة

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

**السياق (Context):**
مع نمو تطبيقنا للتجارة الإلكترونية، زادت الحاجة إلى تنفيذ بعض العمليات بشكل غير متزامن (Asynchronously) لتحسين تجربة المستخدم وضمان استقرار النظام. عمليات مثل إرسال رسائل تأكيد الطلب عبر البريد الإلكتروني، تحديث المخزون، ومعالجة الدفع، كانت تسبب بطئًا في الاستجابة للمستخدم عند تنفيذها بشكل متزامن. نحتاج إلى نظام وسيط رسائل (Message Broker) موثوق لفصل هذه العمليات عن تدفق الطلب الرئيسي.

**القرار (Decision):**
سنقوم باعتماد RabbitMQ كحل أساسي لوساطة الرسائل في نظامنا. سيتم استخدامه لإدارة قوائم انتظار المهام (Task Queues) بين الخدمات المصغرة (Microservices).

**الخيارات المطروحة (Options Considered):**

1.  **Apache Kafka:**
    *   *الإيجابيات:* أداء عالٍ جدًا، مصمم للتعامل مع تدفقات البيانات الضخمة (Streaming)، ويحتفظ بالرسائل لفترات طويلة (Log-based).
    *   *السلبيات:* أكثر تعقيدًا في الإعداد والإدارة مقارنة بـ RabbitMQ. نموذجه (Log) ليس الأنسب لسيناريوهات قوائم المهام البسيطة التي نحتاجها حاليًا. يتطلب إدارة Zookeeper (في الإصدارات القديمة) مما يضيف طبقة أخرى من التعقيد.

2.  **Amazon SQS (Simple Queue Service):**
    *   *الإيجابيات:* خدمة مُدارة بالكامل (Fully Managed)، لا داعي للقلق بشأن الصيانة أو التوسع. تكامل ممتاز مع باقي خدمات AWS.
    *   *السلبيات:* يقيدنا ببنية AWS التحتية (Vendor Lock-in)، وهو ما نحاول تجنبه للمكونات الأساسية في هذه المرحلة من عمر المشروع. قد يكون أكثر تكلفة على المدى الطويل.

3.  **RabbitMQ:**
    *   *الإيجابيات:* ناضج ومستقر جدًا ومستخدم على نطاق واسع. يدعم بروتوكولات متعددة (AMQP, MQTT, STOMP). يوفر نماذج توجيه (Routing) مرنة جدًا (direct, topic, fanout, headers) تلبي احتياجاتنا الحالية والمستقبلية. لدى بعض أعضاء الفريق خبرة سابقة معه، مما يسرّع من عملية التطبيق.
    *   *السلبيات:* يتطلب إدارة ذاتية (Self-hosted) إذا لم نستخدم نسخة سحابية. قد لا يضاهي أداء Kafka في سيناريوهات تدفق البيانات بكميات هائلة جدًا.

**العواقب (Consequences):**

*   **إيجابية:**
    *   سنتمكن من تنفيذ الحل بسرعة بسبب خبرة الفريق المسبقة.
    *   المرونة العالية في توجيه الرسائل ستسمح لنا ببناء أنماط تواصل معقدة مستقبلًا بسهولة.
    *   كونه مفتوح المصدر ومستقلًا عن أي مزود سحابي يمنحنا حرية أكبر في النشر.

*   **سلبية:**
    *   سنتحمل مسؤولية إعداد ومراقبة وصيانة خوادم RabbitMQ.
    *   نحن نقبل بالمقايضة بأننا قد نحتاج إلى إعادة تقييم هذا القرار إذا تحولت متطلباتنا بشكل جذري نحو تحليل تدفقات البيانات في الوقت الفعلي (Real-time data streaming) على نطاق واسع جدًا، حيث قد يكون Kafka خيارًا أفضل في تلك الحالة.

نصائح من أبو عمر: كيف تنجح في تطبيق ADRs في فريقك

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

  • ابدأ ببساطة: لا تعقّد الأمور. كل ما تحتاجه هو مجلد جديد في مستودع الكود الخاص بك، سمّه docs/adr أو architecture/decisions، وابدأ بإنشاء ملفات Markdown. لا تحتاج إلى أدوات معقدة في البداية.
  • اجعلها جزءًا من الروتين: أفضل طريقة لضمان الالتزام هي ربط الـ ADRs بعملية مراجعة الكود (Code Review). هل يقوم طلب السحب (Pull Request) بإدخال تغيير معماري كبير؟ إذًا يجب أن يتضمن هذا الـ PR ملف ADR جديد أو تحديثًا لملف قديم.
  • لا توثّق كل شيء: الـ ADRs ليست للقرارات الصغيرة. اختيار اسم متغير أو استخدام دالة مساعدة لا يحتاج إلى ADR. القاعدة التي أتبعها هي: “هل هذا القرار سيكون مكلفًا أو صعبًا للتراجع عنه في المستقبل؟”. إذا كانت الإجابة “نعم”، فهو مرشح جيد لـ ADR.
  • النقاش أولاً، ثم التوثيق: الـ ADR هو سجل للقرار النهائي، وليس ساحة للنقاش. دع النقاش يحدث في الاجتماعات، أو على Slack، أو في تعليقات الـ PR. بمجرد التوصل إلى اتفاق، يقوم شخص واحد (غالبًا قائد الفريق أو المهندس الذي اقترح الحل) بكتابة الـ ADR لتوثيق النتيجة.
  • اجعلها قابلة للاكتشاف: تأكد من أن كل أعضاء الفريق يعرفون أين يجدون الـ ADRs. يمكنك وضع رابط للمجلد في ملف README.md الخاص بالمشروع.

الخلاصة: ذاكرة من حديد لا يطالها النسيان 🧠

في عالم تطوير البرمجيات سريع التغير، حيث يأتي المطورون ويذهبون، وتتغير المتطلبات، فإن أكبر خطر يواجه أي مشروع طويل الأمد هو فقدان “السياق”. سجلات القرارات المعمارية (ADRs) هي ترياق بسيط وفعال لهذا الخطر.

إنها تحول الفوضى والأسئلة المحيرة مثل “لماذا بحق الجحيم فعلنا ذلك؟” إلى وضوح وثقة وإجابات موثقة مثل “هذا ما قررناه، وهذه هي الأسباب، وهذه هي المقايضات التي قبلنا بها بوعي كامل.”

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

يعطيكم ألف عافية!

أبو عمر

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

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

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

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

آخر المدونات

ذكاء اصطناعي

نموذجنا كان قاضيًا صامتًا: كيف أنقذنا ‘الذكاء الاصطناعي القابل للتفسير’ (XAI) من جحيم القرارات الغامضة؟

أشارككم قصة حقيقية من قلب معركة تطوير البرمجيات، حيث تحول نموذج الذكاء الاصطناعي لدينا إلى قاضٍ غامض يصدر أحكاماً لا نفهمها. اكتشفوا معنا كيف كانت...

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

ميزانيتنا كانت تتبخر: كيف أنقذتنا ‘نماذج الإحالة المبنية على البيانات’ من جحيم مكافأة القناة الخطأ؟

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

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

واجهاتنا كانت فوضى: كيف أنقذنا “نظام التصميم” (Design System) من جحيم عدم الاتساق؟

أتذكر جيدًا ذلك الاجتماع الذي كاد أن يدفن مشروعنا. من فوضى الألوان والأزرار إلى واجهة متناغمة وفعّالة، أشارككم تجربتي العملية في بناء نظام تصميم (Design...

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

بياناتنا كانت تتضارب في صمت: كيف أنقذنا ‘التحكم في الوصول المتزامن’ من جحيم تلف البيانات؟

أشارككم قصة حقيقية من قلب المعركة البرمجية، حين كادت بياناتنا أن تضيع في فوضى صامتة. سنغوص معاً في عالم "التحكم في الوصول المتزامن" (Concurrency Control)...

20 أبريل، 2026 قراءة المزيد
الشبكات والـ APIs

نقرة واحدة، دفعات متعددة: كيف أنقذتنا ‘مفاتيح عدم التكرار’ (Idempotency Keys) من جحيم العمليات المكررة؟

في هذه المقالة، يسرد أبو عمر، مطور برمجيات فلسطيني، قصة واقعية عن كارثة مدفوعات متكررة وكيف كان الحل في مفهوم بسيط وقوي يُدعى "مفاتيح عدم...

20 أبريل، 2026 قراءة المزيد
الحوسبة السحابية

كل نقرة في واجهة السحابة كانت مغامرة: كيف أنقذتنا ‘البنية التحتية كشيفرة’ (IaC) من جحيم التكوينات اليدوية؟

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

20 أبريل، 2026 قراءة المزيد
التوظيف وبناء الهوية التقنية

مقابلاتي التقنية كانت صمتًا مُطبقًا: كيف أنقذني ‘التفكير بصوت عالٍ’ من جحيم الإجابات الفارغة؟

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

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