حكايتي مع الفوضى: كيف أنقذ التصميم الموجه بالمجال (DDD) مشروعنا من جحيم التداخل

يا جماعة الخير، السلام عليكم ورحمة الله وبركاته.

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

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

في هداك اليوم، حسيت إن المشروع “فرطت مسبحته”. كل قسم عنده تعريف مختلف لنفس الكلمة “عميل”. المخزن عنده “منتج” له رقم تسلسلي ووزن وموقع، وقسم التسويق عنده “منتج” له صور ووصف جذاب وسعر. كانت فوضى لغوية حقيقية انعكست على الكود وصار عبارة عن كتلة متداخلة من الشروط (if-statements) اللي بتحاول ترضي كل الأطراف، والنتيجة كانت كارثية: بجات (Bugs) بالهبل، وصعوبة خرافية في إضافة أي ميزة جديدة.

هنا، وبعد ما كنا على وشك نعلن فشل المشروع، تذكرت كتاب كنت قرأته لإريك إيفانز اسمه “Domain-Driven Design”. وقتها قررنا نعمل “قعدة عرب” ونطبق مبادئه. هاي القصة هي حكايتي مع هذا المنهج اللي أنقذنا من جحيم التداخل.

ما هو “التصميم الموجه بالمجال” (DDD)؟ وليش وجع الراس هاد كله؟

قبل ما نفوت في التفاصيل، خليني أبسط الموضوع. التصميم الموجه بالمجال (أو DDD اختصاراً) مش لغة برمجة جديدة ولا مكتبة بتنزلها. هو عبارة عن “فلسفة” أو طريقة تفكير في بناء البرمجيات، خصوصاً الكبيرة والمعقدة منها.

الفكرة الأساسية بسيطة جداً: خلي تصميم الكود تبعك يعكس حقيقة “البيزنس” اللي بتشتغل عليه. يعني بدل ما نفكر كمهندسين بس (قواعد بيانات، واجهات برمجية، كلاسات…)، لازم نفكر زي أهل البيزنس نفسهم. لازم الكود “يحكي” لغة الخبراء في المجال (Domain Experts)، اللي هم مدراء الأقسام والموظفين اللي فاهمين الشغل على أصوله.

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

اللغة الموحدة (Ubiquitous Language): الحكي صار إلو معنى!

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

في قصتنا، كلمة “عميل” (Customer) كانت هي المشكلة. الحل ما كان إننا نلاقي تعريف واحد يرضي الجميع، لأنه هذا مستحيل. الحل كان الاعتراف بأن “عميل المبيعات” شيء، و”عميل الدعم الفني” شيء آخر. وهذا بودينا للنقطة التالية والأهم.

نصيحة من خبرة أبو عمر

لا تستهين بقوة الكلمات. عقد ورشة عمل في بداية المشروع هدفها الوحيد هو بناء “قاموس” للمشروع أو ما يسمى بالـ Ubiquitous Language. اكتب كل مصطلح وتوافق على تعريفه مع كل الأطراف المعنية. هذه الوثيقة ستكون دستور المشروع.

السياقات المحدودة (Bounded Contexts): كل مين إلو سياقه

هون صار السحر الحقيقي. مفهوم “السياق المحدود” بقول لك: بدل ما تحاول تبني نموذج واحد عملاق لكل الشركة، قسّم “عالم” الشركة الكبير إلى “عوالم” أصغر ومستقلة، كل عالم له قانونه الخاص ولغته الخاصة.

تخيلها زي خريطة عليها دول، كل دولة إلها حدودها ولغتها وعملتها الخاصة:

  • سياق المبيعات (Sales Context): في هذا السياق، “العميل” هو شخص محتمل (Lead) عنده فرصة بيعية (Opportunity). اللغة هنا هي لغة البيع والتفاوض.
  • سياق الدعم الفني (Support Context): في هذا السياق، “العميل” هو مستخدم عنده تذاكر دعم (Tickets) وسجل خدمة. اللغة هنا هي لغة حل المشاكل.
  • سياق الشحن (Shipping Context): في هذا السياق، “العميل” هو مجرد اسم وعنوان ورقم هاتف. ما بهمنا تاريخه البيعي ولا تذاكر الدعم تبعه.

فجأة، اختفى الصراع! صار طبيعي جداً يكون عنا كلاس اسمه Sales.Customer وكلاس ثاني اسمه Support.Customer. كل واحد منهم عايش في عالمه الخاص (سياقه المحدود)، ومصمم ليخدم غرض محدد وواضح.

كيف طبقناها عمليًا؟

اللي عملناه هو إننا رسمنا حدود واضحة بين الأنظمة الفرعية. كل سياق محدود صار عبارة عن مشروع صغير (Microservice أو Module) له قاعدة بياناته الخاصة أو مخططه (Schema) الخاص.

كمثال توضيحي بسيط بلغة C# (أو أي لغة كائنية التوجه)، صار الكود عنا يشبه هذا:


// في سياق المبيعات (Sales Bounded Context)
namespace SalesContext 
{
    public class Customer 
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public decimal PotentialValue { get; set; } // مهم في المبيعات
        public string NegotiationHistory { get; set; } // مهم في المبيعات
    }
}

// في سياق الدعم الفني (Support Bounded Context)
namespace SupportContext 
{
    public class Customer 
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public List<Ticket> SupportTickets { get; set; } // مهم في الدعم
        public SatisfactionRating Rating { get; set; } // مهم في الدعم
    }
}

لاحظ كيف أن لكل “Customer” خصائص مختلفة تماماً تعكس احتياجات سياقه. ما عاد في كلاس “عميل” عملاق وفوضوي.

ربط السياقات ببعضها: الجيران وكيف بتصالحوا

طيب، السؤال اللي بيطرح نفسه: إذا فصلناهم عن بعض، كيف بدهم يحكوا مع بعض؟ كيف سياق الدعم الفني بده يعرف إنه هذا العميل اشترى منتج معين من سياق المبيعات؟

هنا يأتي دور “خرائط السياق” (Context Maps)، وهي عبارة عن أنماط بتحدد طبيعة العلاقة بين السياقات المختلفة. أهم نمط استخدمناه هو “الطبقة المضادة للفساد”.

نمط الطبقة المضادة للفساد (Anti-Corruption Layer – ACL)

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

لما سياق الدعم الفني يحتاج معلومة من سياق المبيعات، ما بكلمه مباشرة. بكلم “المترجم” (ACL). المترجم بروح بجيب المعلومة من سياق المبيعات (بالإنجليزي)، وبترجمها وبنظفها وبعطيها لسياق الدعم الفني بالشكل والطريقة اللي بفهمها (بالعربي).

هذا “المترجم” يحمي سياق الدعم الفني من “فساد” النموذج اللغوي تبع سياق المبيعات. بيضمن إنه كل سياق يظل نقي ومستقل في نموذجه الداخلي.

مثال عملي: لما يتم إنشاء تذكرة دعم جديدة، نظام الدعم بيسأل الـ ACL: “أعطيني معلومات العميل صاحب الرقم 123”. الـ ACL بدوره يذهب إلى نظام المبيعات، يأخذ كائن Sales.Customer، يستخرج منه فقط الاسم والإيميل (لأن هذا كل ما يهم الدعم في هذه اللحظة)، ويبني كائن Support.Customer جديد ويعيده لنظام الدعم.

نصائح من خبرة أبو عمر

بعد هالتجربة وغيرها، اسمحولي أقدم لكم كم نصيحة عملية من القلب:

  1. ابدأ بالبيزنس، مش بالكود: قبل ما تكتب سطر كود واحد، اقعد مع أهل الاختصاص. ارسم على الوايت بورد، اعمل ورشات عمل، افهم شغلهم مية بالمية. DDD هو عن فهم المجال أولاً وأخيراً.
  2. لا تفرط في استخدامها (Don’t over-engineer): الـ DDD مش حل لكل المشاكل. لو بتعمل تطبيق بسيط أو موقع شخصي، استخدامه رح يكون زي اللي بصيد سمكة بمدفع. هو يلمع ويتألق في الأنظمة الكبيرة والمعقدة اللي فيها منطق عمل (Business Logic) حقيقي.
  3. اللغة الموحدة عملية مستمرة: القاموس اللي عملتوه مش قرآن منزل. البيزنس بتطور واللغة بتتطور معه. راجعوا القاموس باستمرار وحدثوه.
  4. ارسم الخرائط: حرفياً، ارسموا السياقات المحدودة على لوح كبير، وارسموا خطوط بينهم ووضحوا طبيعة العلاقة (شراكة، عميل-مورد، طبقة مضادة للفساد…). هاي الخريطة بتصير مرجع لكل الفريق.

الخلاصة: من الفوضى إلى النظام 💡

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

نعم، الطريق في البداية كان صعب ويحتاج صبر ونقاشات طويلة، لكن النتيجة كانت نظاماً قوياً، قابلاً للتطوير، وأسهل بكثير في الصيانة. كل قسم صار عنده استقلاليته، وكل فريق صار مسؤول عن “دولته” الصغيرة، والتواصل بين الدول صار منظم وواضح.

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

أبو عمر

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

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

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

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

آخر المدونات

تسويق رقمي

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

في هذه المقالة، أشارككم قصة حقيقية عن كيفية تسبب أدوات حظر الإعلانات في فقدان بياناتنا التسويقية، وكيف كان "التتبع من جانب الخادم" (Server-Side Tracking) هو...

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

كان كل زر بلون مختلف: كيف أنقذنا ‘نظام التصميم’ (Design System) من جحيم الفوضى البصرية؟

أشارككم قصة حقيقية من ميدان البرمجة، كيف تحول مشروعنا من فوضى بصرية عارمة إلى واجهة متناسقة ومنظمة. هذه رحلتنا في بناء "نظام تصميم" (Design System)...

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

كانت فواتيرنا السحابية تلتهم ميزانيتنا: كيف أنقذتنا استراتيجية FinOps من جحيم الإنفاق غير المراقب؟

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

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

كانت مقابلاتنا التقنية تطرد أفضل المواهب: كيف أنقذنا ‘الاختبار المنزلي الواقعي’ عملية التوظيف؟

كنت أرى أفضل المبرمجين يفشلون في مقابلاتنا بسبب ألغاز السبورة البيضاء السخيفة. في هذه المقالة، أشارككم قصة كيف تخلينا عن هذا النهج وتبنينا "الاختبار المنزلي...

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