خمسة مستويات للغوص في نظام معقد

كيف تفهم بنية النظام عندما تفتح مشروعا جديدا للمرة الأولى، أو تعود إلى الكود الخاص بك بعد أشهر عدة؟

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

تنقل AOA هذا الأسلوب من رأس المطور الخبير إلى بنية النظام نفسه. ومن مشروع إلى آخر، تحافظ AOA على الركائز الخمس ذاتها: Domain وAction وContract وPipeline وCode. تتحول كل ركيزة إلى مستوى غوص مستقل، ومعا ترسم مسارا متسلسلا من الصورة الكاملة إلى السلوك الفعلي.

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

التوثيق ↗

عندما تختلط كل مستويات السياق

ما الذي يمنع رؤية الصورة الكاملة حين تتوفر كل التفاصيل في آن واحد؟

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

كيف يؤثر غياب الصورة الكاملة في العمل

تعرض أدناه المجموعة نفسها من المعلومات في حالتين: في الأولى ممتزجة، وفي الثانية مرتبة في خمسة أسئلة متتابعة. لنبدأ بالسؤال الأول: أين تكمن المسؤولية في النظام؟

قاعدة كود مسطحة · حقائق جديدة بلا إطار
orders.pyBillingServiceapi.pycreate_orderreserve_stockOrderModelsend_mailutils.pydb.py
خمسة مستويات · يبنى السياق تباعا
01Domainأين تكمن المسؤولية
02Actionما الذي يستطيعه النظام
03Contractماذا تتطلب العملية وبماذا تعد
04Pipelineكيف يتطور السيناريو
05Codeأين يقع السلوك الفعلي
التوثيق الكامل ↗

أولا — خريطة المسؤولية

أين تكمن المسؤولية؟

الركيزة الأولى هي خريطة المسؤولية. فهي تجمع وحدات التحكم والخدمات ونماذج البيانات ومهايئات البنية التحتية وسلاسل الاستدعاءات حول المجالات الرئيسية للنظام — وهي هيكل يمكن أن تربط به لاحقا العمليات والبيانات والكود.

تقسم Domain النظام لا حسب الطبقات التقنية، بل حسب مجالات مسؤولية ثابتة: الطلبات، والمدفوعات، والتواصل، والتحليلات. ومكان مئات الملفات المتساوية الأهمية، تظهر أول طوبولوجيا يمكن الإحاطة بها.

ما الذي تقدمه خريطة Domain

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

4 × ActionStoreDomain

مسؤول عن السلة والطلب وتسليمه إلى التوصيل

3 × ActionBillingDomain

مسؤول عن المدفوعات والفواتير والمبالغ المستردة

3 × ActionMessagingDomain

مسؤول عن التواصل مع العميل والـ webhooks

3 × ActionAnalyticsDomain

مسؤول عن الأحداث ومتاجر البيانات والتقارير التجارية

التوثيق الكامل ↗

الخريطة تتحول إلى كتالوج للقدرات

ما الذي يستطيعه النظام؟

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

Action هو قدرة علنية مسماة تابعة لـ Domain. لا يعرض الكتالوج الدوال الداخلية، بل العمليات التي يوفرها Domain لبقية النظام، والعلاقات الموجهة بينها. تتحول كل Action إلى نقطة استدعاء واحدة: يختار الطرف المستدعي القدرة التي يحتاجها بحسب معناها، دون تجميع العملية من طرق منفصلة.

ما الذي يقدمه كتالوج Action

يبرز المخطط CreateOrderAction — وهو Action الذي يطلق إنشاء الطلب. وتظهر بجواره Actions أخرى تابعة لـ StoreDomain والعلاقات بينها. قد تعتمد عملية على أخرى، لكن التبعيات موجهة ولا تنغلق في دورة. لا يرى عند هذا المستوى سوى أسماء Action والعلاقات بينها؛ أما المدخلات والنتيجة والسيناريو والكود فستكشف لاحقا.

StoreDomainقدرات تنفيذية مسماة
CreateOrderAction

إنشاء طلب: التحقق والحجز والدفع

→ ChargePaymentAction

GetOrderAction

الحصول على الحالة الراهنة للطلب

CancelOrderAction

إلغاء الطلب وبدء عملية الاسترداد

→ RefundPaymentAction

ShipOrderAction

تسليم الطلب المؤكد إلى التوصيل

التوثيق الكامل ↗

تثبيت حدود العملية

ماذا تتطلب العملية وبماذا تعد؟

أصبح للقدرة الآن اسم وموضع في النظام. ولاستخدامها بوصفها «صندوقا أسود»، لا بد من معرفة البيانات التي تقبلها بدقة، والنتيجة التي يتحتم عليها إرجاعها.

يجعل Contract حدود Action محددة النوع وغير ملتبسة. يصف Params كل ما تقبله العملية، ويصف Result كل ما يجب عليها إرجاعه. ويعتمد الكود المستدعي على هذا الوعد، لا على بنية Action الداخلية. ويمكن تغيير التنفيذ الفعلي ما دام المدخل والمخرج والسلوك القابل للملاحظة محافظين على التوافق.

ما الذي يقدمه عقد Action

يحصل CreateOrderAction المألوف الآن على توقيع كامل: CreateOrderParams من جهة، وCreateOrderResult من الجهة الأخرى. لم تعد الحقول موجودة كنماذج بيانات مجردة — بل أصبحت تخص عملية محددة بموضع وغرض واضحين. وما زال باطن Action غير ضروري لاستخدامه.

CreateOrderParams
customer_id: str
items: list[Item]
currency: str
CreateOrderAction

تنسيق إنشاء الطلب خلف حدود معلنة واحدة

Params → Result
CreateOrderResult
order_id: str
payment_id: str
status: OrderStatus
التوثيق الكامل ↗

توسيع العملية إلى سيناريو

كيف يتطور السيناريو؟

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

يجعل Pipeline سيناريو العمل الرئيسي خطيا ومرئيا: التحقق من المدخل، وحجز المخزون، وتنفيذ الدفع، وتجميع النتيجة. وهذا لا يعني غياب الأخطاء والتفرعات والتعويضات من الواقع؛ بل تحصل على موضع صريح بالنسبة إلى الخط الرئيسي. ولكل خطوة أيضا عقد محلي: فهي تعلن ما تقرؤه من Params وState وContext، وما تضيفه إلى State لأجل المراحل التالية.

ما الذي يقدمه سيناريو العملية

منح Domain السيناريو موضعا، وAction اسما، وContract بداية ونتيجة موعودة. ويضيف Pipeline ترتيبا سببيا وحدودا داخلية. وتعزل خطوة reserve_inventory بوصفها تغييرا مستقلا في الحالة: فهي تستقبل بيانات تم التحقق منها بالفعل، وتترك reservation_id لمتابعة السيناريو.

regularvalidatevalidated_items
regularreserve_inventoryreservation_id
regularcharge_paymentpayment_id
summarycreate_resultOrderResult
التوثيق الكامل ↗

الآن فقط — السلوك الفعلي

أين يقع السلوك الفعلي؟

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

يصبح Code هو المستوى الخامس لا لأن التفاصيل غير مهمة، بل لأنها أصبحت الآن محاطة بالمعنى. فمن المعروف مسبقا أي Domain يملك هذا السلوك، وأي قدرة ينفذها Action، وبم يعد Contract، وأي موضع يشغله reserve_inventory داخل Pipeline. ويقرأ التنفيذ كإجابة محلية عن مهمة محددة، لا كمدخل إلى تحقيق لا ينتهي في المستودع.

ما الذي يقدمه عزل السلوك في خطوة منفردة

عند فتح reserve_inventory، نعرف مسبقا مقصده ومدخلاته وموضعه في السيناريو. ويبقى المبدأ نفسه: يجب أن تمر التأثيرات الخارجية عبر Resource معلنة وActions علنية. وتجعل القواعد المعمارية أي انحراف مرئيا وقابلا للتحقق، دون التظاهر بأن نص الوصف وحده يمنع فعليا أي التفاف.

store/actions/create_order.py
@regular_aspect("Reserve inventory")@result_string("reservation_id", required=True)@context_requires("user.tenant_id", "env.inventory_region")async def reserve_inventory_aspect(    self, params, state, box, connections, ctx):    inventory = box.resolve(InventoryResource)    reservation_id = await inventory.reserve(        tenant_id=ctx.get("user.tenant_id"),        region=ctx.get("env.inventory_region"),        items=state["validated_items"],    )    return {"reservation_id": reservation_id}
$ uv run python store/actions/create_order.py
الناتج
التوثيق الكامل ↗

لا تخفي المستويات الخمس الكود، ولا تختزل النظام إلى مخطط. بل تحافظ على المسار من النموذج العام إلى التفصيل. يبني المبتدئ سياقه تدريجيا، ويدير المعماري القواعد والحدود بدلا من كل ملف على حدة، ويؤدي وكيل AI عملا محليا ضمن قواعد معلنة: يصمم الإنسان لغة النظام، وتتصرف الآلة وفق هذه اللغة.

خمسة مستويات للغوص في نظام معقد · aoa.run