تخطَّ إلى المحتوى

اختيار نمط الوصول إلى البيانات

2.5.x ✅ 4.0.x ✅

أي نمط يجب أن أستخدم؟ تساعدك شجرة القرار هذه في الاختيار بين معالجات مباشرة وPattern Repository وService Layer و CQRS.


flowchart TD
START([ابدأ هنا]) --> Q1{مدى تعقيد<br/>وحدتك؟}
Q1 -->|CRUD بسيط<br/>1-3 كيانات| Q2{هل تحتاج<br/>اختبار أو محاكاة؟}
Q1 -->|معتدل<br/>4-10 كيانات| Q3{مصادر بيانات<br/>متعددة؟}
Q1 -->|معقد<br/>10+ كيانات| Q4{حركة مرور<br/>عالية أو عدم تناسق<br/>القراءة/الكتابة؟}
Q2 -->|لا| HANDLER[✅ معالج مباشر]
Q2 -->|نعم| REPO[✅ نمط المستودع]
Q3 -->|لا فقط قاعدة البيانات| REPO
Q3 -->|نعم APIs/cache| SERVICE[✅ طبقة الخدمة]
Q4 -->|لا| SERVICE
Q4 -->|نعم نحتاج<br/>تحجيم منفصل| CQRS[✅ نمط CQRS]
HANDLER --> DONE([اختر النمط])
REPO --> DONE
SERVICE --> DONE
CQRS --> DONE
style HANDLER fill:#c8e6c9,stroke:#2e7d32
style REPO fill:#bbdefb,stroke:#1565c0
style SERVICE fill:#fff9c4,stroke:#f9a825
style CQRS fill:#ffcdd2,stroke:#c62828

المعاييرمعالج مباشرالمستودعطبقة الخدمةCQRS
التعقيد⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
قابلية الاختبار❌ صعب✅ جيد✅ كبير✅ كبير
المرونة❌ منخفض✅ متوسط✅ عالي✅ عالي جداً
XOOPS 2.5.x✅ أصلي✅ يعمل✅ يعمل⚠️ معقد
XOOPS 4.0⚠️ مستهلك✅ مستحسن✅ مستحسن✅ للتوسع
حجم الفريق1 مطور1-3 مطورين2-5 مطورين5+ مطورين
الصيانة❌ أعلى✅ معتدل✅ أقل⚠️ يتطلب خبرة

✅ معالج مباشر (XoopsPersistableObjectHandler)

Section titled “✅ معالج مباشر (XoopsPersistableObjectHandler)”

الأفضل للـ: وحدات بسيطة وأنماط سريعة وتعلم XOOPS

// بسيط وكل شيء - جيد للوحدات الصغيرة
$handler = xoops_getModuleHandler('article', 'news');
$articles = $handler->getObjects(new Criteria('status', 1));

اختر هذا عندما:

  • بناء وحدة بسيطة مع 1-3 جداول قاعدة بيانات
  • إنشاء نموذج أولي سريع
  • أنت المطور الوحيد ولا تحتاج اختبارات
  • الوحدة لن تنمو بشكل كبير

القيود:

  • من الصعب اختبار الوحدة (الاعتماد العام)
  • الاقتران الوثيق بطبقة قاعدة بيانات XOOPS
  • منطق الأعمال يميل إلى التسرب إلى المتحكمات

الأفضل للـ: معظم الوحدات والفرق التي تريد قابلية الاختبار

// التجريد يسمح بالمحاكاة للاختبارات
interface ArticleRepositoryInterface {
public function findPublished(): array;
public function save(Article $article): void;
}
class XoopsArticleRepository implements ArticleRepositoryInterface {
private $handler;
public function __construct() {
$this->handler = xoops_getModuleHandler('article', 'news');
}
public function findPublished(): array {
return $this->handler->getObjects(new Criteria('status', 1));
}
}

اختر هذا عندما:

  • تريد كتابة اختبارات الوحدة
  • قد تتغير مصادر البيانات لاحقاً (قاعدة البيانات → API)
  • العمل مع 2+ مطورين
  • بناء وحدات للتوزيع

مسار الترقية: هذا هو النمط الموصى به لتحضير XOOPS 4.0.


الأفضل للـ: وحدات بمنطق أعمال معقد

// خدمة تنسق مستودعات متعددة وتحتوي على قواعد عمل
class ArticlePublicationService {
public function __construct(
private ArticleRepositoryInterface $articles,
private NotificationServiceInterface $notifications,
private CacheInterface $cache
) {}
public function publish(int $articleId): void {
$article = $this->articles->find($articleId);
$article->setStatus('published');
$article->setPublishedAt(new DateTime());
$this->articles->save($article);
$this->notifications->notifySubscribers($article);
$this->cache->invalidate("article:{$articleId}");
}
}

اختر هذا عندما:

  • العمليات تمتد عبر مصادر بيانات متعددة
  • قواعد الأعمال معقدة
  • تحتاج إدارة المعاملات
  • أجزاء متعددة من التطبيق تفعل نفس الشيء

مسار الترقية: اجمع مع المستودع لعمارة قوية.


⚠️ CQRS (فصل مسؤولية الأمر والاستعلام)

Section titled “⚠️ CQRS (فصل مسؤولية الأمر والاستعلام)”

الأفضل للـ: وحدات عالية الحجم مع عدم توازن القراءة/الكتابة

// الأوامر تعديل الحالة
class PublishArticleCommand {
public function __construct(
public readonly int $articleId,
public readonly int $publisherId
) {}
}
// الاستعلامات تقرأ الحالة (يمكن استخدام نماذج قراءة غير معايرة)
class GetPublishedArticlesQuery {
public function __construct(
public readonly int $limit = 10
) {}
}

اختر هذا عندما:

  • القراءات تفوق الكتابات بكثير (100:1 أو أكثر)
  • تحتاج تحجيم مختلف للقراءات مقابل الكتابات
  • متطلبات التقارير/التحليلات المعقدة
  • سوف يستفيد sourcing الأحداث من مجالك

تحذير: يضيف CQRS تعقيداً كبيراً. معظم وحدات XOOPS لا تحتاجه.


flowchart LR
H0["معالج مباشر<br/>(XOOPS 2.5.x اليوم)"]
R["نمط المستودع<br/>(الخطوة التالية الموصى بها)"]
S["+ طبقة الخدمة<br/>(عندما ينمو التعقيد)"]
C["+ CQRS<br/>(فقط إذا كان التحجيم يتطلبها)"]
H0 -->|"الخطوة 1"| R
R -->|"الخطوة 2"| S
S -->|"الخطوة 3<br/>(نادر)"| C
style H0 fill:#ffcdd2
style R fill:#c8e6c9
style S fill:#bbdefb
style C fill:#fff9c4

الخطوة 1: لف المعالجات في المستودعات (2-4 ساعات)

Section titled “الخطوة 1: لف المعالجات في المستودعات (2-4 ساعات)”
  1. أنشئ واجهة لاحتياجات وصول البيانات
  2. طبقها باستخدام المعالج الموجود
  3. اضخ المستودع بدلاً من استدعاء xoops_getModuleHandler() مباشرة

الخطوة 2: أضف طبقة الخدمة عند الحاجة (1-2 يوم)

Section titled “الخطوة 2: أضف طبقة الخدمة عند الحاجة (1-2 يوم)”
  1. عندما يظهر منطق العمل في المتحكمات، استخرج إلى خدمة
  2. الخدمة تستخدم المستودعات وليس المعالجات مباشرة
  3. المتحكمات تصبح رقيقة (المسار → الخدمة → الاستجابة)

الخطوة 3: فكر في CQRS فقط إذا (نادر)

Section titled “الخطوة 3: فكر في CQRS فقط إذا (نادر)”
  1. لديك ملايين القراءات يومياً
  2. نماذج القراءة والكتابة مختلفة بشكل كبير
  3. تحتاج sourcing الأحداث للمسارات التدقيق
  4. لديك فريق ذو خبرة في CQRS

السؤالالإجابة
”أنا فقط بحاجة للحفظ/التحميل”معالج مباشر
”أريد كتابة الاختبارات”نمط المستودع
”لدي قواعد أعمال معقدة”طبقة الخدمة
”أحتاج للتحجيم قراءات بشكل منفصل”CQRS
”أستعد لـ XOOPS 4.0”نمط المستودع + طبقة الخدمة


#patterns #data-access #decision-tree #best-practices #xoops