يا أهلاً وسهلاً فيكم جميعاً، معكم أبو عمر.
قبل كم سنة، كنا شغالين على مشروع ضخم ومعقد، وكان الفريق بيكبر بسرعة. في يوم من الأيام، انضم إلنا مطور جديد، شب شاطر اسمه “رامي”. بعد أول أسبوع، وإحنا قاعدين بنشرب فنجان قهوة الصبح، سألني رامي سؤال بسيط ولكنه عميق: “يا أبو عمر، ليش إحنا بنستخدم RabbitMQ كوسيط للرسائل (Message Broker) بين الخدمات المصغرة (Microservices)؟ ليش ما استخدمنا Kafka مثلاً؟”.
والله يا جماعة الخير، إني صفنت. تذكرت إنه كان في نقاش طويل وحاد حول هالموضوع قبل حوالي سنة ونص، بس تفاصيل النقاش والأسباب الدقيقة اللي خلتنا نختار RabbitMQ كانت ضبابية في ذاكرتي. الشخص اللي كان بقود النقاش ترك الشركة، والتوثيق الوحيد اللي كان موجود هو سطر يتيم في محضر اجتماع قديم. قضيت أنا ورامي حوالي ساعة كاملة بنحاول “نعيد هندسة” القرار ونستنتج الأسباب. كانت ساعة ضايعة، وكان ممكن تتكرر مع كل مطور جديد بنضم للفريق.
هذا الموقف، اللي ممكن تشوفوه بسيط، كان بمثابة جرس إنذار. تاريخ قراراتنا كان بضيع، وذاكرة الفريق كانت بتنزف مع كل شخص بغادر. كنا محتاجين حل جذري، حل يوثّق “لماذا” وراء قراراتنا، وهنا كانت بداية رحلتنا مع ما يُعرف بـ “سجلات القرارات المعمارية” أو Architectural Decision Records (ADRs).
ما هي مشكلة “الذاكرة المفقودة” في المشاريع؟
قبل ما نغوص في الحل، خلينا نفصّل المشكلة أكتر. في أي مشروع برمجي بعيش أكتر من ست شهور، بتواجهنا ظاهرة بسميها “الذاكرة المؤسسية المفقودة”. هاي المشكلة إلها عدة أوجه:
- أسئلة متكررة: كل عضو جديد في الفريق يسأل نفس الأسئلة حول القرارات التقنية القديمة، مما يستهلك وقت الأعضاء القدامى.
- إعادة اختراع العجلة: في غياب السياق، قد يحاول الفريق حل مشكلة تم حلها بالفعل، أو يقع في نفس الأخطاء التي وقع فيها سابقوه.
- الخوف من التغيير: عندما لا نفهم سبب وجود نظام معين، نخاف من تعديله أو تحسينه، مما يؤدي إلى جمود تقني وتراكم للديون التقنية (Technical Debt).
- قرارات غير متسقة: بدون سجل واضح، قد يتخذ الفريق قرارات جديدة تتعارض مع المبادئ التي تم الاتفاق عليها سابقاً، مما يؤدي إلى معمارية فوضوية.
باختصار، إحنا بنكون خبراء في “ماذا” فعلنا (الكود موجود)، لكننا نصبح هواة في تذكر “لماذا” فعلناه. وهذا هو الجحيم اللي كانت ADRs هي طوق النجاة منه.
المنقذ: سجلات القرارات المعمارية (ADRs)
بكل بساطة، الـ ADR هو عبارة عن ملف نصي قصير (غالباً بصيغة Markdown) يسجل قراراً معمارياً واحداً مهماً. الفكرة هي إنشاء سجل تاريخي للقرارات الهامة التي تشكل بنية النظام، بحيث يمكن لأي شخص في المستقبل فهم السياق والقرار والتبعات.
الفكرة مش جديدة، وصاغها بشكلها الحديث مايكل نايجارد (Michael Nygard) في مدونته. جمالها يكمن في بساطتها الشديدة. ما بتحتاج أدوات معقدة ولا برامج غالية، كل اللي بيلزمك هو محرر نصوص والتزام من الفريق.
تشريح سجل القرار المعماري (Anatomy of an ADR)
معظم الـ ADRs بتتبع قالب بسيط وموحد لضمان سهولة القراءة والفهم. هذا هو القالب اللي استقرينا عليه في فريقنا، وهو الأكثر شيوعاً:
- العنوان (Title): جملة قصيرة وواضحة تصف القرار. مثلاً: “استخدام PostgreSQL كقاعدة بيانات أساسية”.
- الحالة (Status): حالة السجل الحالي. ممكن تكون:
- مقترح (Proposed): القرار لا يزال قيد النقاش.
- مقبول (Accepted): تم الاتفاق على القرار وسيتم تنفيذه.
- مرفوض (Rejected): تم رفض الاقتراح بعد النقاش.
- مهمل (Deprecated): القرار كان مقبولاً في الماضي ولكنه لم يعد يُنصح به.
- مُستبدَل (Superseded by ADR-XXX): تم اتخاذ قرار جديد يحل محل هذا القرار.
- السياق (Context): هذا هو أهم جزء. هنا نصف المشكلة التي نحاول حلها، والقوى المؤثرة، والقيود. هذا القسم يجيب على سؤال “ما هي الظروف التي دفعتنا للتفكير في هذا القرار؟”.
- القرار (Decision): هنا نذكر بوضوح ما قررنا فعله. يجب أن تكون هذه الجملة مباشرة وموجزة. هذا القسم يجيب على سؤال “ماذا قررنا؟”.
- التبعات (Consequences): لكل قرار تبعات، إيجابية وسلبية. يجب أن نكون صادقين وشفافين هنا. ما هي المزايا التي سنحصل عليها؟ وما هي المقايضات (Trade-offs) أو السلبيات التي قبلنا بها؟ هذا القسم يجيب على سؤال “ماذا سيحدث نتيجة لقرارنا؟”.
مثال عملي: قرار اختيار قاعدة البيانات
لنتخيل أننا نبني خدمة جديدة ونحتاج لاختيار قاعدة بيانات. بعد نقاش، قررنا استخدام PostgreSQL. إليكم كيف سيبدو الـ ADR الخاص بهذا القرار:
# ADR-001: استخدام PostgreSQL كقاعدة بيانات أساسية للخدمات الجديدة
**الحالة:** مقبول (Accepted)
**السياق (Context):**
نحن بصدد بناء خدمات مصغرة جديدة تتطلب تخزين بيانات مترابطة (Relational Data). فريقنا لديه خبرة متفاوتة في قواعد البيانات، ولكن معظم المطورين تعاملوا مع قواعد بيانات SQL في الماضي. المتطلبات الأساسية هي الموثوقية العالية، ودعم المعاملات (Transactions) بشكل قوي (ACID compliance)، ووجود نظام بيئي (ecosystem) ناضج من الأدوات والمكتبات. تم النظر في خيارات أخرى مثل MySQL و MongoDB.
**القرار (Decision):**
سنعتمد قاعدة بيانات PostgreSQL كخيار افتراضي لجميع الخدمات المصغرة الجديدة التي تتطلب تخزين بيانات منظمة ومترابطة. سيتم استخدام نسخة مُدارة (Managed Service) من PostgreSQL على منصة الحوسبة السحابية التي نستخدمها لتقليل العبء التشغيلي.
**التبعات (Consequences):**
**الإيجابيات:**
* **موثوقية عالية:** PostgreSQL مشهورة باستقرارها والتزامها بمعايير SQL.
* **ميزات متقدمة:** تدعم أنواع بيانات معقدة مثل JSONB، مما يمنحنا بعض مرونة قواعد بيانات NoSQL داخل بيئة SQL.
* **خبرة الفريق:** معظم أعضاء الفريق لديهم معرفة مسبقة بـ SQL، مما يقلل من منحنى التعلم.
* **نظام بيئي ناضج:** تتوفر العديد من الأدوات والمكتبات وORM التي تدعم PostgreSQL بشكل ممتاز.
**السلبيات:**
* **صعوبة التوسع الأفقي (Horizontal Scaling):** على عكس بعض قواعد بيانات NoSQL مثل Cassandra، فإن التوسع الأفقي لـ PostgreSQL أكثر تعقيداً. لقد قبلنا بهذه المقايضة لأننا لا نتوقع حجم بيانات هائلاً في المدى القريب، ويمكننا معالجة هذه المشكلة لاحقاً إذا لزم الأمر.
* **صلابة المخطط (Schema Rigidity):** يتطلب أي تغيير في بنية الجداول عملية ترحيل (migration)، مما قد يبطئ من وتيرة التطوير مقارنة بقواعد بيانات schemaless.
تخيلوا لو كان هذا الملف موجوداً عندما سألني رامي! كنت ببساطة سأرسل له رابط الملف، وكان سيحصل على إجابة كاملة ومفصلة في دقيقتين بدلاً من ساعة من التخمين. هذا هو سحر الـ ADRs.
نصائح أبو عمر العملية لبدء استخدام ADRs
بعد ما “تبهدلنا” في البداية، تعلمنا كم درس مهم. اسمحولي أشاركم شوية نصائح من القلب عشان تبدأوا صح:
1. ابدأ ببساطة ومع القرار القادم
لا تحاول توثيق كل القرارات التي اتخذتها في تاريخ المشروع بأثر رجعي. هذه مهمة مرهقة ومحبطة. بدلاً من ذلك، التزم بكتابة ADR لأول قرار معماري مهم ستتخذه ابتداءً من اليوم. مع الوقت، ستجد أن لديك سجلاً غنياً ومفيداً.
2. احتفظ بها بجانب الكود
“التوثيق الذي يعيش بعيداً عن الكود، يموت وحيداً.”
هذه مقولة أؤمن بها بشدة. أفضل مكان لحفظ ملفات الـ ADRs هو داخل مستودع الكود (Git repository) نفسه، في مجلد مخصص مثل docs/adrs أو architecture/decisions. هذا يضمن أن التوثيق المعماري يتم التعامل معه كجزء من الكود: يتم تحديثه بنفس الطريقة، مراجعته عبر Pull Requests، وتاريخه محفوظ في Git.
3. استخدم الـ Pull Requests للنقاش
عندما يقترح أحد أعضاء الفريق قراراً جديداً، يمكنه فتح Pull Request (أو Merge Request) بملف ADR جديد حالته “مقترح” (Proposed). يصبح الـ PR هو ساحة النقاش. يمكن للجميع التعليق، اقتراح تعديلات، والتصويت. بمجرد التوصل إلى اتفاق، يتم دمج الـ PR وتغيير حالة الـ ADR إلى “مقبول” (Accepted). هذه العملية تجعل القرارات ديمقراطية وشفافة وموثقة تلقائياً.
4. لا تبالغ في التوثيق
مش كل قرار بيحتاج ADR. تغيير اسم متغير أو إضافة حقل بسيط لجدول لا يستدعي كل هذه العملية. القاعدة الأساسية هي: اكتب ADR للقرارات التي لها تأثير معماري كبير، أو يصعب عكسها، أو تؤثر على عدة أجزاء من النظام. أمثلة:
- اختيار إطار عمل (Framework) جديد.
- اعتماد نمط معماري معين (مثل Microservices أو CQRS).
- اختيار تقنية أساسية (مثل قاعدة بيانات، وسيط رسائل، منصة سحابية).
- تحديد كيفية تواصل الخدمات مع بعضها (REST vs. gRPC vs. GraphQL).
الخلاصة يا جماعة الخير 📝
سجلات القرارات المعمارية (ADRs) ليست مجرد “توثيق” ممل. إنها ذاكرة فريقك الحية. هي الأداة التي حولت تاريخ قراراتنا من ضباب كثيف إلى سجل واضح ومنظم. لقد وفرت علينا ساعات لا تحصى من النقاشات المكررة، وسرّعت من عملية تأقلم المطورين الجدد، وجعلت قراراتنا أكثر نضجاً واتساقاً.
نصيحتي الأخيرة لكم: لا تستهينوا بقوة توثيق الـ “لماذا”. ابدأوا اليوم، حتى لو بملف نصي واحد. ابدأوا بالقرار القادم. فريقكم في المستقبل، والشخص الذي ستكون عليه أنت بعد عام من الآن، سيشكرونكم على هذه الخطوة البسيطة والعملاقة في نفس الوقت. يلا، شدّوا حيلكم! ✅