سجلات القرارات المعمارية (ADRs): كيف أنقذتنا من جحيم “لماذا فعلنا ذلك؟”

قبل كم سنة، كنت شغال على مشروع كبير ومعقد شوي، وكان الفريق مزيج بين خبرات قديمة وشباب جديدة متحمسة. في يوم من الأيام، إجا شب جديد على الفريق، خلينا نسميه “سامر”. سامر شب شاطر ونبيه، وبعد ما أخذ فترة يتعرف على الكود، إجا عليّ وحكالي بنبرة مستغربة: “أبو عمر، شو قصة الـ Caching Layer اللي عاملينها؟ ليش مستخدمين Redis بهالطريقة المعقدة بدل ما نستخدم In-Memory Cache بسيط؟ حاسسها over-engineering على الفاضي!”.

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

وهون بلشت المعاناة. قضينا يومين كاملين، أنا وسامر وكم شب من الفريق، نحفر في الـ Git history ونفتح الـ Pull Requests القديمة ونقرأ تعليقات وتذاكر Jira، زي اللي بدور على إبرة في كومة قش. بالنهاية، لقينا السبب. كان في خدمة طرف ثالث (third-party service) بنتعامل معها، وكانت بطيئة جداً وتفرض علينا عدد طلبات محدود بالدقيقة. الحل وقتها كان إنه نعمل aggressive caching لبياناتها في طبقة Redis مشتركة بين كل خوادم التطبيق عشان نقلل الطلبات عليها. المشكلة؟ هاي الخدمة تم الاستغناء عنها قبل 6 شهور! يعني السبب اللي بنينا عشانه كل هاي الطبقة المعقدة بطل موجود أصلاً.

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

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

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

أهمية الـ ADRs مش بس في “توثيق” القرار، الأهمية الحقيقية تكمن في توثيق “السياق” و“التبعات” المحيطة بالقرار. يعني باختصار، الـ ADRs بتجاوب على الأسئلة القاتلة:

  • لماذا؟ (السياق): ما هي المشكلة التي كنا نحاول حلها؟ ما هي الخيارات التي كانت أمامنا؟ ليش اخترنا هذا الخيار بالذات ورفضنا الخيارات الأخرى؟
  • ماذا؟ (القرار): ما هو القرار الذي اتخذناه بشكل واضح ومباشر؟
  • وماذا بعد؟ (التبعات): ما هي النتائج المترتبة على هذا القرار؟ الإيجابية والسلبية. هل هناك أي مخاطر جديدة؟ هل هناك عمل إضافي مطلوب نتيجة لهذا القرار؟

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

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

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

العنوان (Title)

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

الحالة (Status)

هاي مهمة جداً عشان نعرف وضع القرار الحالي. الحالات الشائعة هي:

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

السياق (Context)

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

القرار (Decision)

جملة أو فقرة واضحة ومباشرة تشرح القرار النهائي. بدون لف ودوران. “قررنا استخدام مكتبة X للتعامل مع التواريخ” أو “سنقوم ببناء خدمة مصغرة (microservice) منفصلة لمعالجة المدفوعات”.

التبعات (Consequences)

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

  • إيجابيات: سرعة في التطوير، أداء أفضل، تكلفة أقل.
  • سلبيات: زيادة في التعقيد، الحاجة لتعلم تقنية جديدة، صعوبة في الصيانة على المدى البعيد.
  • مخاطر: ممكن يصير “lock-in” مع مزود خدمة معين، ممكن المكتبة اللي اخترناها يتوقف دعمها.

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

مثال عملي: خلينا نكتب ADR سوا

تخيل إنه فريقنا بيبني تطبيق جديد، وفي نقاش حول المعمارية: هل نبدأ بـ Monolith (نظام متكامل) ولا نروح على Microservices (خدمات مصغرة) من أول يوم؟ بعد نقاش طويل، اتفقنا على حل وسط. خلينا نوثق القرار هاد بـ ADR.


# ADR-004: اعتماد معمارية "المونوليث النمطي" (Modular Monolith) كنقطة بداية

*   **الحالة:** مقبول (Accepted)
*   **التاريخ:** 2023-10-26

## السياق (Context)

نحن بصدد بناء منتج جديد (MVP). الفريق صغير (4 مطورين)، والميزانية محدودة، والهدف هو إطلاق نسخة أولية للسوق بأسرع وقت ممكن لجمع آراء المستخدمين.
الخيارات المتاحة كانت:
1.  **معمارية الخدمات المصغرة (Microservices):** توفر قابلية ممتازة للتوسع والتطوير المستقل للخدمات، لكنها تتطلب تكاليف تشغيلية (operational overhead) عالية في البداية (إدارة الشبكات، التوزيع، المراقبة...).
2.  **المعمارية المتكاملة التقليدية (Traditional Monolith):** بسيطة في البداية وسهلة النشر، لكنها قد تتحول إلى "كرة طين كبيرة" (Big Ball of Mud) يصعب صيانتها وتطويرها مع نمو التطبيق.
3.  **المونوليث النمطي (Modular Monolith):** هو نظام متكامل واحد، لكنه مقسم داخلياً إلى وحدات (modules) مستقلة ومنفصلة بشكل جيد، ولكل وحدة مسؤوليتها الخاصة (مثل إدارة المستخدمين، الفواتير، المنتجات).

المفاضلة الأساسية هي بين سرعة الإطلاق الأولية وسهولة الصيانة والتوسع في المستقبل.

## القرار (Decision)

سنعتمد معمارية **"المونوليث النمطي" (Modular Monolith)**.
سنقوم ببناء التطبيق كعملية نشر واحدة (single deployable unit)، ولكن مع فرض حدود صارمة بين الوحدات البرمجية داخل الكود. التواصل بين الوحدات يجب أن يتم من خلال واجهات برمجية (APIs) معرفة بشكل واضح، كما لو كانت خدمات منفصلة.

## التبعات (Consequences)

### الإيجابيات:
*   **سرعة التطوير الأولية:** أسرع بكثير من بناء بنية تحتية للخدمات المصغرة.
*   **بساطة النشر والتشغيل:** عملية نشر واحدة، وقاعدة بيانات واحدة في البداية، مما يقلل التعقيد التشغيلي.
*   **سهولة الاختبارات المتكاملة (End-to-End testing).**
*   **يترك الباب مفتوحاً للمستقبل:** إذا تم تصميم الوحدات بشكل صحيح، يمكن مستقبلاً استخراج أي وحدة وتحويلها إلى خدمة مصغرة (microservice) خاصة بها بأقل جهد ممكن عند الحاجة.

### السلبيات والمخاطر:
*   **يتطلب انضباطاً عالياً من الفريق:** هناك خطر كبير من كسر الحدود بين الوحدات والتسبب في تداخل الكود (tight coupling) إذا لم يكن الفريق منضبطاً.
*   **قابلية التوسع المحدودة:** كل النظام يتوسع كوحدة واحدة. لا يمكننا توسيع "وحدة المنتجات" فقط إذا زاد عليها الضغط.
*   **مخاطرة تقنية:** أي خطأ فادح في أي وحدة قد يؤثر على النظام بأكمله ويتسبب في توقفه.

نحن نقبل بهذه المخاطر في المرحلة الحالية مقابل سرعة الوصول إلى السوق. سنقوم بمراجعة هذا القرار بعد 6 أشهر أو عند وصول عدد المستخدمين إلى 50,000 مستخدم.

كيف تبدأ باستخدام ADRs في فريقك؟ نصايح من أبو عمر

بعد ما شفت قوة الـ ADRs، صرت أنصح فيها كل الفرق اللي بشتغل معها. وهي شوية نصايح عملية من خبرتي عشان تبدأ صح:

ابدأ ببساطة (Start Simple)

ما في داعي تعقدها. أنشئ مجلد جديد اسمه `docs/adr` أو `architecture/decisions` في مستودع الكود (Git repository) تبعكم. اعمل ملف `template.md` فيه القالب الأساسي اللي حكينا عنه. وهيك بتكون جاهز. البساطة هي مفتاح الاستمرارية.

اجعلها جزءاً من الـ Workflow

أفضل طريقة لضمان كتابة الـ ADRs هي ربطها بعملية مراجعة الكود (Code Review). هل التغيير اللي بتعمله كبير وبأثر على المعمارية؟ ممتاز، افتح Pull Request وفي قلبه شغلتين: الكود الجديد، وملف ADR جديد يشرح القرار. هيك بصير النقاش حول الـ ADR جزء من النقاش حول الكود نفسه.

لا توثّق كل إشي (Don’t document everything)

مش كل قرار بيحتاج ADR. قرار “تغيير لون الزر من أزرق لأخضر” ما بيستاهل. ركز على القرارات المهمة:

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

استخدم أدوات مساعدة (Use tools)

في أدوات بسيطة ممكن تسهل حياتك. مثلاً، أداة سطر الأوامر adr-tools. بتسمحلك تعمل ADR جديد بأمر واحد، وهو بحطلك الرقم والتاريخ والعنوان تلقائياً.


# مثال على استخدام adr-tools
adr new "Use RabbitMQ for asynchronous communication"
# هذا الأمر سينشئ ملف مثل: 005-use-rabbitmq-for-asynchronous-communication.md

الـ ADRs وثائق حية (ADRs are living documents)

لا تفكر بالـ ADR كإشي بتكتبه وبتنساه. مع تطور المشروع، ممكن قرار قديم يبطل مناسب. وقتها، لا تعدل على الـ ADR القديم، بل اعمل ADR جديد يستبدله. وفي الـ ADR الجديد، اذكر إنه “يستبدل ADR-XXX”، وفي الـ ADR القديم، غير حالته لـ “Superseded by ADR-YYY”. هيك بتحافظ على سجل تاريخي كامل للقرارات وتطورها.

الخلاصة: وداعاً لـ “ليش عملنا هيك؟” 👋

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

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

أبو عمر

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

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

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

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

آخر المدونات

تجربة المستخدم والابداع البصري

من الشاشات البيضاء إلى الحوار: فن تصميم حالات الواجهة (Loading, Empty, Error)

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

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

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

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

21 مايو، 2026 قراءة المزيد
التوسع والأداء العالي والأحمال

كانت طلباتنا تتعثر في أوقات الذروة: كيف أنقذتنا ‘طوابير الرسائل’ (Message Queues) من جحيم الاختناقات؟

أشارككم قصة حقيقية من قلب المعركة البرمجية، كيف كاد تطبيقنا أن ينهار تحت ضغط المستخدمين في يوم إطلاق مهم، وكيف كانت "طوابير الرسائل" (Message Queues)...

21 مايو، 2026 قراءة المزيد
التكنلوجيا المالية Fintech

كانت بياناتنا المالية سجينة البنوك: كيف حررتها واجهات ‘الصيرفة المفتوحة’ (Open Banking)؟

من واقع تجربتي كمبرمج، كانت بياناتنا المالية حبيسة جدران البنوك الرقمية. في هذه المقالة، أسرد لكم كيف حولت واجهات برمجة التطبيقات للصيرفة المفتوحة (Open Banking)...

21 مايو، 2026 قراءة المزيد
البنية التحتية وإدارة السيرفرات

كانت سجلاتنا متناثرة وضائعة: كيف أنقذنا التجميع المركزي (ELK/Loki) من جحيم تتبع الأخطاء؟

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

21 مايو، 2026 قراءة المزيد
ادارة الفرق والتنمية البشرية

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

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

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