قبل كم سنة، كنت شغال في فريق على مشروع ضخم ومعقد. إحنا خمس مطورين، وكل واحد فينا ماسك جزء من النظام. الأمور كانت ماشية، بس زي ما بيقولوا “على البركة”. ذاكرتنا الجماعية كانت هي الوثيقة الوحيدة، وكل نقاشاتنا وقراراتنا المهمة كانت تتم في “قعدة شاي” أو على السريع في الممر. ما كنا ندوّن اشي.
في يوم من الأيام، استقال “خالد”، أقدم مطور في الفريق والعقل المدبر وراء جزء كبير من معمارية النظام. بعد شهرين، طلب منا العميل تعديل كبير على نظام الدفع. لما فتحنا الكود، صُعقنا. كان في تعقيد غريب واختيار تقني غير مألوف بالمرة. ولعت بين المطورين، وكل واحد صار يحلل على كيفه. “ليش خالد عمل هيك؟”، “شو القصة؟ أكيد في سبب بس شو هو؟”، “هذا الشغل ما بنفع، لازم نعيد كتابة كل إشي”.
قضينا أسبوعين كاملين، مش بنكتب كود، لأ… بنحاول نعمل “هندسة عكسية” لعقل خالد! ليش اختار مكتبة X بدل Y المعروفة؟ ليش استخدم هذا النمط المعماري الغريب؟ خسرنا وقت، وجهد، وأعصاب، وفي الأخير اكتشفنا – بعد ما قدرنا نتواصل معاه بصعوبة – إنه كان في متطلب أمني نادر جداً من العميل، والاختيار اللي عمله كان هو الحل الوحيد الممكن وقتها. لو كان في سطر واحد مكتوب يوضح “ليش”، كان وفرنا على حالنا كل هالجحيم. هاي اللحظة كانت نقطة تحول. قررنا إنه ذاكرة الأشخاص لا يمكن أن تكون أساساً لبناء برمجيات مستدامة.
المعرفة القبلية (Tribal Knowledge): المقبرة الصامتة للمشاريع
القصة اللي حكيتها مش حالة نادرة. هاي هي “المعرفة القبلية” أو “المعرفة العشائرية”. هي كل المعلومات والقرارات والسياقات الهامة اللي بتعيش بس في عقول أعضاء الفريق. لما يغيب واحد منهم، بتغيب معاه قطعة من ذاكرة المشروع.
المشاكل اللي بتسببها هاي الظاهرة كارثية:
- صعوبة انضمام الأعضاء الجدد: كل مطور جديد بيحتاج “مترجم” أو “مرشد” يظل قاعد جنبه شهور عشان يفهم “ليش الأشياء معمولة بهاي الطريقة”.
- عامل الحافلة (The Bus Factor): لو أهم شخص في الفريق “دعسته حافلة” (لا سمح الله)، هل المشروع بينهار؟ إذا الجواب نعم، فأنتم في خطر حقيقي.
- تكرار النقاشات (والأخطاء): بدون سجل، الفريق بيظل يعيد نفس النقاشات مراراً وتكراراً كل 6 أشهر، وممكن يوصلوا لنفس القرار الغلط اللي وصلوله قبل سنة ونسيوا ليش كان غلط.
- الخوف من التغيير: لما ما تكون فاهم “ليش” النظام مبني بهالشكل، بتصير تخاف تلمس أي جزء منه، وهذا يؤدي إلى تدهور جودة الكود وتراكم الديون التقنية.
طيب يا أبو عمر، شو الحل؟ هل نكتب وثائق بالمئات من الصفحات اللي ما حدا رح يقرأها؟ لأ طبعاً. الحل أبسط وأكثر عملية بكثير.
المنقذ: سجلات القرارات المعمارية (Architectural Decision Records – ADRs)
ببساطة شديدة، الـ ADR هو ملف نصي صغير وخفيف، بيوصف قرار معماري “مهم” واحد فقط. الأهم من كل إشي، إنه مش بس بيحكي “شو” قررنا، بل بيشرح بالتفصيل “ليش” قررنا هيك.
الفكرة عبقرية في بساطتها. بدل ما نوثق “كل” النظام، إحنا بنوثق “نقاط التحول” في حياة النظام. كل قرار مهم غيّر مسار المشروع يتم تسجيله في ملف منفصل ووضعه مع الكود المصدري في نظام إدارة النسخ (زي Git).
تشريح سجل قرار معماري (ADR)
معظم الـ ADRs بتتبع هيكل بسيط وموحد. خلينا نشوف أشهر قالب، اللي اقترحه Michael Nygard:
- العنوان (Title): جملة قصيرة وواضحة بتلخص القرار. مثال: “ADR-001: استخدام PostgreSQL كقاعدة بيانات أساسية”.
- الحالة (Status): هل القرار “مقترح” (Proposed)، “مقبول” (Accepted)، “مرفوض” (Rejected)، أو “تم استبداله” (Superseded) بقرار آخر.
- السياق (Context): هاي هي “القصة”. شو المشكلة اللي بنحاول نحلها؟ شو القيود اللي عنا (وقت، ميزانية، خبرة الفريق)؟ شو هي القوى اللي بتدفعنا باتجاهات مختلفة؟ هذا الجزء هو أهم جزء لفهم “ليش”.
- القرار (Decision): جملة واضحة ومباشرة بتوصف الحل اللي اخترناه. “نحن قررنا أن نستخدم…”.
- العواقب (Consequences): هون بنكون شفافين مع أنفسنا في المستقبل. كل قرار له جانب إيجابي وسلبي. شو كسبنا من هذا القرار؟ وشو خسرنا؟ هل صار في تعقيد جديد؟ هل في مخاطر لازم ننتبه لها؟ هذا الجزء بيمنع “المفاجآت” في المستقبل.
نصيحة من أبو عمر: الجزء الأهم في أي ADR هو “السياق” و “العواقب”. الـ “شو” سهل تعرفه من الكود، لكن الـ “ليش” هو الكنز الحقيقي اللي بيضيع مع الزمن.
مثال على قالب ADR
هذا هو شكل ملف ADR بسيط بصيغة Markdown، ممكن تحفظه كقالب وتبدأ باستخدامه اليوم:
# ADR-XXX: [عنوان القرار هنا]
**الحالة:** مقترح | مقبول | مرفوض | تم استبداله
**التاريخ:** YYYY-MM-DD
## السياق
[اشرح المشكلة هنا. ما هي الخلفية؟ ما هي الخيارات المتاحة؟ ما هي القيود التي تواجهنا؟]
## القرار
[صف القرار الذي تم اتخاذه بشكل واضح ومباشر. ابدأ بـ "نحن قررنا أن..."]
## العواقب
[صف النتائج المترتبة على هذا القرار، الإيجابية والسلبية.]
### إيجابيات:
* [الفائدة الأولى]
* [الفائدة الثانية]
### سلبيات:
* [المقايضة الأولى أو الخسارة]
* [المخاطرة التي نقبلها]
مثال من أرض الواقع: قرار استخدام Monolith بدل Microservices
لنفترض أن فريقك يبدأ مشروعًا جديدًا. النقاش الأزلي يظهر: هل نبدأ ببنية متجانسة (Monolith) أم بخدمات مصغرة (Microservices)؟ بعد نقاش طويل، توصلتم لقرار. هكذا يمكنكم توثيقه:
# ADR-001: البدء ببنية متجانسة نمطية (Modular Monolith)
**الحالة:** مقبول
**التاريخ:** 2023-10-26
## السياق
نحن بصدد بناء الإصدار الأول من منتجنا (MVP). الفريق صغير (4 مطورين)، والوقت محدود جدًا للوصول إلى السوق. الهدف الأساسي هو التحقق من فكرة المنتج بأسرع وقت ممكن. النقاش الرئيسي كان بين البدء ببنية خدمات مصغرة (Microservices) لتسهيل التوسع المستقبلي، أو بنية متجانسة (Monolith) لسرعة التطوير الأولية.
**الخيارات المطروحة:**
1. **بنية الخدمات المصغرة:** تمنح استقلالية للفرق وتوسعاً أفقياً مرناً، لكنها تضيف تعقيداً كبيراً في البداية (Deployment,
CI/CD, Monitoring, Inter-service communication).
2. **البنية المتجانسة التقليدية:** سريعة في البداية ولكنها قد تتحول إلى "كرة طين كبيرة" (Big Ball of Mud) يصعب صيانتها وتطويرها.
3. **البنية المتجانسة النمطية (Modular Monolith):** تطبيق واحد متجانس، ولكنه مقسم داخليًا إلى وحدات (Modules) منفصلة منطقيًا مع حدود واضحة بينها.
## القرار
نحن قررنا أن نبدأ المشروع باستخدام **بنية متجانسة نمطية (Modular Monolith)**. سنقوم بفرض حدود صارمة بين الوحدات على مستوى الكود لضمان عدم تداخلها، مما يسهل عملية تفكيكها إلى خدمات مصغرة في المستقبل إذا دعت الحاجة.
## العواقب
### إيجابيات:
* **سرعة التطوير:** أسرع بكثير في المراحل الأولى للمشروع.
* **بساطة العمليات:** عملية بناء ونشر واختبار موحدة وبسيطة.
* **لا يوجد تعقيد شبكي:** كل الاتصالات بين الوحدات تتم داخل نفس العملية (In-process calls).
* **بيئة تطوير موحدة:** من السهل على أي مطور تشغيل المشروع بأكمله على جهازه.
### سلبيات:
* **التوسع المحدود:** النظام بأكمله يتوسع كوحدة واحدة. لا يمكننا توسيع "وحدة المستخدمين" بشكل منفصل عن "وحدة الفواتير".
* **مخاطرة الالتزام بتقنية واحدة:** كل الوحدات يجب أن تستخدم نفس حزمة التقنيات (e.g., نفس اللغة، نفس قاعدة البيانات).
* **مخاطرة كسر الحدود:** يتطلب انضباطًا عاليًا من الفريق للحفاظ على الحدود بين الوحدات وعدم تحويلها إلى فوضى. نحن نقبل هذا الخطر وسنراقبه من خلال مراجعات الكود (Code Reviews).
**الخلاصة:** هذا القرار يمنحنا السرعة التي نحتاجها الآن، مع ترك الباب مفتوحًا للتحول إلى خدمات مصغرة في المستقبل بطريقة منظمة بدلاً من إعادة كتابة كارثية.
كيف تبدأ باستخدام ADRs في فريقك؟
الأمر أسهل مما تتخيل. لا تحتاج إلى برامج معقدة أو موافقات إدارية عليا.
- ابدأ ببساطة:** أنشئ مجلداً جديداً في مشروعك على Git اسمه
docs/adrsأوarchitecture-decisions. - خذ آخر قرار مهم:** تذكروا آخر نقاش تقني كبير في الفريق (مثلاً، اختيار مكتبة جديدة، أو تغيير طريقة التعامل مع الـ Caching). اكتبوا أول ADR عنه.
- اجعلها جزءاً من العملية:** هل هناك قرار جديد قيد النقاش؟ اقترح على الفريق: “يا جماعة، خلينا نكتب ADR مقترح ونناقشه من خلال Pull Request”. هذا يفتح النقاش للجميع ويوثقه في نفس الوقت.
- استخدم الأدوات المساعدة (اختياري):** هناك أدوات بسيطة في سطر الأوامر مثل adr-tools يمكنها أن تساعدك في إنشاء ملفات ADR جديدة بالترقيم والقالب الصحيحين.
نصيحة من أبو عمر: لا تحاولوا توثيق كل القرارات القديمة بأثر رجعي. هذا مجهود ضائع. ابدأوا من اليوم. وثّقوا القرار المهم القادم، واستمروا. مع الوقت، ستجدون أنفسكم قد بنيتم مكتبة لا تقدر بثمن من المعرفة.
الخلاصة: ذاكرة لا تصدأ ✅
سجلات القرارات المعمارية ليست مجرد “توثيق”. إنها ذاكرة فريقك المكتوبة. هي الحارس الأمين الذي يحميكم من إعادة اختراع العجلة، ومن النقاشات التي لا تنتهي، ومن فوضى رحيل الأعضاء أو انضمامهم.
في البداية، قد تشعر أنها خطوة إضافية، لكن صدقني، بعد بضعة أشهر، عندما يأتي مطور جديد ويسأل “ليش استخدمنا هاي التقنية الغريبة؟”، وبدل ما تقضي ساعة في الشرح، ترسل له رابط ملف الـ ADR في ثوانٍ، ستشعر بقيمة ما فعلت.
يا جماعة، التوثيق مش رفاهية، هو طوق النجاة في بحر البرمجيات المتلاطم. ابدأوا اليوم، ولو بقرار واحد. مستقبلكم (وفريقكم) سيشكركم. 🚀