عندما تختلط كل مستويات السياق
ما الذي يمنع رؤية الصورة الكاملة حين تتوفر كل التفاصيل في آن واحد؟
لا يفصل المستودع العادي المعلومات بحسب المقياس: مجالات العمل، والعمليات، ونماذج البيانات، وترتيب الاستدعاءات، والبنية التحتية، وأسطر محددة من الكود — كلها تعرض في آن واحد. تضطر الذاكرة العاملة إلى الاحتفاظ بحقائق من مستويات مختلفة وإعادة بناء العلاقات بينها بنفسها. ينتقل الانتباه باستمرار بين بنية النظام والتفاصيل المحلية، لذا يتفكك الفهم بسرعة بعد أي انقطاع.
كيف يؤثر غياب الصورة الكاملة في العمل
تعرض أدناه المجموعة نفسها من المعلومات في حالتين: في الأولى ممتزجة، وفي الثانية مرتبة في خمسة أسئلة متتابعة. لنبدأ بالسؤال الأول: أين تكمن المسؤولية في النظام؟
أولا — خريطة المسؤولية
أين تكمن المسؤولية؟
الركيزة الأولى هي خريطة المسؤولية. فهي تجمع وحدات التحكم والخدمات ونماذج البيانات ومهايئات البنية التحتية وسلاسل الاستدعاءات حول المجالات الرئيسية للنظام — وهي هيكل يمكن أن تربط به لاحقا العمليات والبيانات والكود.
تقسم Domain النظام لا حسب الطبقات التقنية، بل حسب مجالات مسؤولية ثابتة: الطلبات، والمدفوعات، والتواصل، والتحليلات. ومكان مئات الملفات المتساوية الأهمية، تظهر أول طوبولوجيا يمكن الإحاطة بها.
ما الذي تقدمه خريطة Domain
في المخطط، تشكل أربعة Domain المستوى الأعلى للتطبيق. من هنا سنكشف StoreDomain تباعا: أولا Actions الخاصة به، ثم عقد عملية واحدة، وسيناريوها، وتنفيذها الفعلي.
StoreDomainمسؤول عن السلة والطلب وتسليمه إلى التوصيل
BillingDomainمسؤول عن المدفوعات والفواتير والمبالغ المستردة
MessagingDomainمسؤول عن التواصل مع العميل والـ webhooks
AnalyticsDomainمسؤول عن الأحداث ومتاجر البيانات والتقارير التجارية
الخريطة تتحول إلى كتالوج للقدرات
ما الذي يستطيعه النظام؟
تظهر خريطة Domain أين تكمن المسؤولية، لكنها لا تخبر بعد بما يستطيع النظام فعله. ولمعرفة ذلك، ينفتح كل Domain على هيئة كتالوج Action — قدرات مسماة يوفرها لبقية النظام.
Action هو قدرة علنية مسماة تابعة لـ Domain. لا يعرض الكتالوج الدوال الداخلية، بل العمليات التي يوفرها Domain لبقية النظام، والعلاقات الموجهة بينها. تتحول كل Action إلى نقطة استدعاء واحدة: يختار الطرف المستدعي القدرة التي يحتاجها بحسب معناها، دون تجميع العملية من طرق منفصلة.
ما الذي يقدمه كتالوج Action
يبرز المخطط CreateOrderAction — وهو Action الذي يطلق إنشاء الطلب. وتظهر بجواره Actions أخرى تابعة لـ StoreDomain والعلاقات بينها. قد تعتمد عملية على أخرى، لكن التبعيات موجهة ولا تنغلق في دورة. لا يرى عند هذا المستوى سوى أسماء Action والعلاقات بينها؛ أما المدخلات والنتيجة والسيناريو والكود فستكشف لاحقا.
CreateOrderActionإنشاء طلب: التحقق والحجز والدفع
→ ChargePaymentAction
GetOrderActionالحصول على الحالة الراهنة للطلب
CancelOrderActionإلغاء الطلب وبدء عملية الاسترداد
→ RefundPaymentAction
ShipOrderActionتسليم الطلب المؤكد إلى التوصيل
تثبيت حدود العملية
ماذا تتطلب العملية وبماذا تعد؟
أصبح للقدرة الآن اسم وموضع في النظام. ولاستخدامها بوصفها «صندوقا أسود»، لا بد من معرفة البيانات التي تقبلها بدقة، والنتيجة التي يتحتم عليها إرجاعها.
يجعل Contract حدود Action محددة النوع وغير ملتبسة. يصف Params كل ما تقبله العملية، ويصف Result كل ما يجب عليها إرجاعه. ويعتمد الكود المستدعي على هذا الوعد، لا على بنية Action الداخلية. ويمكن تغيير التنفيذ الفعلي ما دام المدخل والمخرج والسلوك القابل للملاحظة محافظين على التوافق.
ما الذي يقدمه عقد Action
يحصل CreateOrderAction المألوف الآن على توقيع كامل: CreateOrderParams من جهة، وCreateOrderResult من الجهة الأخرى. لم تعد الحقول موجودة كنماذج بيانات مجردة — بل أصبحت تخص عملية محددة بموضع وغرض واضحين. وما زال باطن Action غير ضروري لاستخدامه.
CreateOrderParamsitems: list[Item]
currency: str
CreateOrderActionتنسيق إنشاء الطلب خلف حدود معلنة واحدة
CreateOrderResultpayment_id: str
status: OrderStatus
توسيع العملية إلى سيناريو
كيف يتطور السيناريو؟
يثبت العقد بداية العملية ونهايتها، لكنه لا يظهر كيف تتحول إحداهما إلى الأخرى. ولمعرفة ذلك، نكشف المسار الداخلي لسيناريو العمل.
يجعل Pipeline سيناريو العمل الرئيسي خطيا ومرئيا: التحقق من المدخل، وحجز المخزون، وتنفيذ الدفع، وتجميع النتيجة. وهذا لا يعني غياب الأخطاء والتفرعات والتعويضات من الواقع؛ بل تحصل على موضع صريح بالنسبة إلى الخط الرئيسي. ولكل خطوة أيضا عقد محلي: فهي تعلن ما تقرؤه من Params وState وContext، وما تضيفه إلى State لأجل المراحل التالية.
ما الذي يقدمه سيناريو العملية
منح Domain السيناريو موضعا، وAction اسما، وContract بداية ونتيجة موعودة. ويضيف Pipeline ترتيبا سببيا وحدودا داخلية. وتعزل خطوة reserve_inventory بوصفها تغييرا مستقلا في الحالة: فهي تستقبل بيانات تم التحقق منها بالفعل، وتترك reservation_id لمتابعة السيناريو.
الآن فقط — السلوك الفعلي
أين يقع السلوك الفعلي؟
يحدد Pipeline الموضع الدقيق للسلوك المطلوب، ويضيق منطقة البحث بشدة. ويمكن الآن فتح خطوة واحدة معروفة الغرض والمدخل والمخرج مسبقا، لا المستودع بأكمله ولا حتى Action بأكمله.
يصبح Code هو المستوى الخامس لا لأن التفاصيل غير مهمة، بل لأنها أصبحت الآن محاطة بالمعنى. فمن المعروف مسبقا أي Domain يملك هذا السلوك، وأي قدرة ينفذها Action، وبم يعد Contract، وأي موضع يشغله reserve_inventory داخل Pipeline. ويقرأ التنفيذ كإجابة محلية عن مهمة محددة، لا كمدخل إلى تحقيق لا ينتهي في المستودع.
ما الذي يقدمه عزل السلوك في خطوة منفردة
عند فتح reserve_inventory، نعرف مسبقا مقصده ومدخلاته وموضعه في السيناريو. ويبقى المبدأ نفسه: يجب أن تمر التأثيرات الخارجية عبر Resource معلنة وActions علنية. وتجعل القواعد المعمارية أي انحراف مرئيا وقابلا للتحقق، دون التظاهر بأن نص الوصف وحده يمنع فعليا أي التفاف.
$ uv run python store/actions/create_order.pyلا تخفي المستويات الخمس الكود، ولا تختزل النظام إلى مخطط. بل تحافظ على المسار من النموذج العام إلى التفصيل. يبني المبتدئ سياقه تدريجيا، ويدير المعماري القواعد والحدود بدلا من كل ملف على حدة، ويؤدي وكيل AI عملا محليا ضمن قواعد معلنة: يصمم الإنسان لغة النظام، وتتصرف الآلة وفق هذه اللغة.
