Feature Chain — تتبع الـ full stack بـ operationId واحد

ما الملفات التي يجب تعديلها لتغيير ميزة واحدة؟ أدخل operationId واحداً وستحصل على الإجابة.


المشكلة

في تطبيقات الـ full stack، “الميزة الواحدة” لا تقع في ملف واحد.

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

كانت هناك طريقتان تقليديتان لفهم هذا النطاق الكامل:

  1. تشغيل Grep عشرات المرات
  2. تتبع الكود يدوياً

كلتاهما بطيئة، وكلتاهما تُفضي إلى إغفال بعض العناصر. تتبع المراجع العابرة للطبقات بشكل بشري — من مواصفات API إلى الخدمة، ومن الخدمة إلى مخطط قاعدة البيانات، ومن الخدمة إلى سياسات التفويض — أمر صعب التطبيق في الواقع العملي.

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


ما هو Feature Chain

Feature Chain هو استخراج جميع عُقد المصادر المرتبطة بميزة API واحدة (operationId).

انطلاقاً من operationId واحد كنقطة بداية، يتتبع المراجع الرمزية بين المصادر ويُخرج جميع الملفات وأرقام الأسطر المرتبطة دفعةً واحدة. عشرات تشغيلات Grep تُستبدل بأمر واحد.

fullend chain AcceptProposal specs/
── Feature Chain: AcceptProposal ──

  OpenAPI    api/openapi.yaml:296                          POST /proposals/{id}/accept
  SSaC       service/proposal/accept_proposal.ssac:19      @get @empty @auth @state @put @call @post @response
  DDL        db/gigs.sql:1                                 CREATE TABLE gigs
  DDL        db/proposals.sql:1                            CREATE TABLE proposals
  DDL        db/transactions.sql:1                         CREATE TABLE transactions
  Rego       policy/authz.rego:3                           resource: gig
  StateDiag  states/gig.md:7                               diagram: gig → AcceptProposal
  StateDiag  states/proposal.md:6                          diagram: proposal → AcceptProposal
  FuncSpec   func/billing/hold_escrow.go:8                 @func billing.HoldEscrow
  Gherkin    scenario/gig_lifecycle.feature:4              Scenario: Happy Path - Full Gig Lifecycle
  Gherkin    scenario/gig_lifecycle.feature:42             Scenario: Unauthorized Access

يظهر الهيكل الكامل لميزة واحدة في شاشة واحدة. الطبقات غير المرتبطة لا تُعرض.


لماذا هذا ممكن

هذا ليس سحراً. إنه ممكن لأن المصادر تشير بعضها إلى بعض أصلاً.

في إطار عمل fullend، كل طبقة SSOT (Single Source of Truth) تشير رمزياً إلى الطبقات الأخرى:

  • SSaC الخاص بـ @get Model.Method ← جداول DDL
  • SSaC الخاص بـ @auth action resource ← سياسات تفويض Rego
  • SSaC الخاص بـ @state diagramID ← مخططات حالة Mermaid
  • SSaC الخاص بـ @call pkg.Func ← تنفيذات Func Spec
  • OpenAPI الخاص بـ operationId ← اسم ملف SSaC
  • Gherkin الخاص بخطوة action ← operationId
  • STML الخاص بـ endpoint ← مسار OpenAPI

هذه المراجع صُمِّمت أصلاً لـ crosscheck — أداة التحقق من اتساق SSOT. بما أن crosscheck يُحلِّل هذه المراجع مسبقاً، فإن إعادة استخدام نفس البنية التحتية يكفي لاستخراج feature chain عبر استكشاف الرسم البياني فحسب.


مسار الاستكشاف

انطلاقاً من operationId كنقطة بداية، يتمدد رسم المراجع البيانية على النحو التالي:

operationId (نقطة البداية)
├── OpenAPI → path + method
├── SSaC → ملف دالة الخدمة
│   ├── @get → جداول DDL
│   ├── @auth → قواعد سياسة Rego
│   ├── @state → انتقالات stateDiagram في Mermaid
│   ├── @call → تنفيذات Func Spec
│   └── @publish → مشتركو قائمة الانتظار
├── Gherkin → السيناريوهات التي تشير إلى operationId
└── STML → ملفات الـ frontend التي تشير إلى الـ endpoint

كل فرع يتبع مستوى واحداً فقط من المراجع الرمزية. الاستكشاف عرضي لا عمقي. تتكشف آثار الميزة في جميع الطبقات بالكامل.


ما الذي يتغير

تحديد نطاق التعديل

“ما الذي يجب تعديله لإصلاح هذه الميزة؟”

للإجابة عن هذا السؤال كنا نقرأ الكود ونشغّل grep ونسأل الزملاء. Feature Chain يستبدل هذا السؤال بأمر واحد. لا يفوت أي ملف — طالما توجد مرجع رمزي.

تعديل الكود بالذكاء الاصطناعي

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

مع Feature Chain يختلف الأمر. يكفي تحديد operationId واحد لتحديد نطاق التعديل الكامل تلقائياً. السياق الذي يُنقل إلى الذكاء الاصطناعي يكون مكتملاً دون إغفال.

مراجعة الكود

عند مراجعة PR، الشك القائل “إذا عدّلت هذه الميزة أفلا يجب أن يتغير ذاك الملف أيضاً؟” يمكن التحقق منه فوراً بمقارنته بالـ chain. البنية تتولى اكتشاف التناقضات بين الطبقات عوضاً عن الإنسان.

الإعداد للعمل

عندما يقول مطور جديد “أريد أن أفهم كيف تعمل AcceptProposal”، يكفي أن تُريه Feature Chain واحداً. من API حتى قاعدة البيانات، ومن سياسات التفويض حتى سيناريوهات الاختبار — التضاريس الكاملة للميزة تظهر دفعة واحدة.


لماذا operationId

نقطة البداية مهمة. اختارت Feature Chain operationId.

السبب بسيط. في تطبيقات الـ full stack، وحدة الميزة هي نقطة نهاية API. عندما يضغط المستخدم زراً يُستدعى API، وذاك API ينفّذ منطق الخدمة، ويقرأ قاعدة البيانات، ويتحقق من التفويض، وينقل الحالة. نقطة بداية هذا التدفق كله هي operationId.

operationId محدَّد مسبقاً في مواصفة OpenAPI، وهو الاسم الذي يشترك فيه الفريق بأكمله. عندما تقول “يجب تعديل AcceptProposal” يتخيّل مطور الـ backend ومطور الـ frontend وفريق QA الشيء نفسه. اختراق الـ stack بأكمله باسم عالمي واحد هو تصميم Feature Chain.


المتطلبات الأساسية

لكي تعمل Feature Chain، ثمة شروط مسبقة:

  1. يجب أن تشير المصادر بعضها إلى بعض رمزياً. توجيهات @get و@auth و@state و@call في SSaC يجب أن تشير صراحةً إلى SSOT الأخرى. إذا كانت المراجع ضمنية — مثل وجود اسم جدول قاعدة البيانات كسلسلة نصية فقط داخل الكود — فلا يمكن التتبع.

  2. يجب اجتياز crosscheck. بما أن Feature Chain تتبع المراجع الرمزية، فإن المراجع غير الصالحة ستُنتج نتائج خاطئة. crosscheck يضمن اتساق المراجع، وFeature Chain تستكشف فوقها.

هذا هو سبب كون Feature Chain ليست أداةً عامة. لا يمكن تطبيقها على أي مشروع. تعمل فقط في مشاريع مُصمَّمة بمراجع بين المصادر — هياكل مثل fullend حيث تشير SSOT بعضها إلى بعض صراحةً.


المستقبل: GEUL + SILK

حالياً تستكشف Feature Chain بالمرور على كل مُحلِّل SSOT. تستدعي مُحلِّل SSaC ومُحلِّل DDL ومُحلِّل Rego ومُحلِّل Mermaid كل منها على حدة وتجمع النتائج.

عندما تتحول جميع SSOT إلى رسم بياني GEUL، ستصبح Feature Chain استعلاماً على فهرس واحد. بعملية AND البِتِّية على SIDX في SILK، يمكن استخراج جميع العُقد المرتبطة بـ operationId باستعلام واحد.

من المرور على المُحلِّلات إلى استعلام الرسم البياني. واجهة Feature Chain تبقى كما هي، لكن ما بداخلها يتغير جذرياً.


خلاصة

في تطبيقات الـ full stack، “الميزة” لا تقع في ملف واحد. إنها ممتدة عبر طبقات متعددة تشير بعضها إلى بعض. Feature Chain تتبع هذه المراجع وتستخرج النطاق الكامل لميزة واحدة تلقائياً.

أدخل operationId واحداً، ومن مواصفات API حتى مخطط قاعدة البيانات، ومن سياسات التفويض حتى سيناريوهات الاختبار — تُستبدل عشرات تشغيلات Grep بأمر واحد.

الكود: github.com/park-jun-woo/fullend