سلسلة المسؤولية: كود نظيف لمنطق أعمال معقد
خليني أحكي لك عن الدالة اللي كانت تطاردني في الكوابيس.
كل نظام، في مرحلة ما، بيوصل لدالة ما حدش عايز يلمسها. بتبدأ بسيطة: تشيك validation بسيط، if statement هنا، واحد تاني هناك. بعدين المتطلبات تتكوم، الـ stakeholders يطلبوا "استثناء صغير بس"، وفجأة تلاقي نفسك باصص على وحش 500 سطر مكتوب باللجنة (لأنه فعلاً كتب باللجنة).
وهنا بييجي نمط **Chain of Responsibility** للإنقاذ — مش بسحر، لكن بانضباط. خليني أشرح إزاي النمط الكلاسيكي ده يقدر يفك تشابك أعقد منطق أعمال عندك.
إيه هي سلسلة المسؤولية (Chain of Responsibility)؟
في جوهرها، السلسلة بتمشي على مبدأ إن الطلب يتمرر على سلسلة من الـ handlers لحد ما واحد فيهم يتعامل معاه. تخيلها زي طابور تصعيد خدمة العملاء — كل واحد يحاول يحل مشكلتك، لو ماقدرش يمررها للي بعده.
في الكود، بدل ما يكون عندك ميثود واحد ضخم بيمسك كل السيناريوهات، بتعمل سلسلة من الـ handlers الصغيرة والمركزة. كل handler إما بيمسك الطلب أو بيمرر لللي بعده في السلسلة.
سيناريوهات حقيقية بتلمع فيها السلسلة
معالجة الطلبات في التجارة الإلكترونية
تخيل: بتعمل منصة تجارة إلكترونية، ودالة `processOrder()` محتاجة تتعامل مع أكواد خصم، نقاط ولاء، عروض موسمية، حسابات شركات، حالة VIP، وشراكات خاصة. الدالة تكبر لمئات الأسطر مع conditionals متداخلة.
مع Chain of Responsibility، بتعمل معالجات منفصلة:
```javascript
class DiscountCodeHandler {
handle(order) {
// منطق الخصم
return next ? next.handle(order) : order;
}
}
class LoyaltyPointsHandler {
handle(order) {
// تطبيق نقاط الولاء
return next ? next.handle(order) : order;
}
}
```
كل Handler بيفكر في حاجة واحدة، فالتست والصيانة بقت سهلة جداً.
خط أنابيب مراقبة المحتوى
منصات السوشيال ميديا بيواجهوا workflows معقدة للمراقبة. بوست ممكن يتفحص ضد إرشادات المجتمع، يتسكان للكلام البغيض، يتفلجر للمحتوى السياسي، يراجع لحقوق النشر، ويتقيم للمعلومات المضللة — كله قبل النشر.
بدل ما تحشر كل حاجة في دالة مراقبة واحدة، تبني pipeline:
1. **Spam Detection Handler** – يفلتر السبام الواضح
2. **Hate Speech Handler** – يفلج اللغة المسيئة
3. **Copyright Handler** – يتفحص ضد مواد محمية بحقوق نشر
4. **Political Content Handler** – يوجّه البوستات السياسية الحساسة
5. **Final Review Handler** – مراجعة بشرية نهائية
كل خطوة إما بتتعامل مع المحتوى أو بتمريره للخطوة اللي بعده.
تدفق تصريح الدفع
معالجة الدفع بتتضمن طبقات كتير من التحقق والموافقة. بدل معالج دفع واحد ضخم، فكر في السلسلة دي:
1. **Fraud Detection Handler** – يحجب المعاملات المشبوهة
2. **Credit Limit Handler** – يتأكد من كفاية الرصيد
3. **Bank Verification Handler** – يؤكد صلاحية الحساب
4. **Currency Conversion Handler** – يتعامل مع المدفوعات الدولية
5. **Payment Gateway Handler** – ينفذ المعاملة فعلياً
النهج ده بيخلي إضافة خطوات تحقق جديدة سهلة من غير ما تلمس الكود الموجود.
تنفيذ أول سلسلة ليك
إليك تنفيذ عملي بـ JavaScript:
```javascript
// كلاس Handler أساسي
class BaseHandler {
constructor() {
this.nextHandler = null;
}
setNext(handler) {
this.nextHandler = handler;
return handler;
}
handle(request) {
if (this.nextHandler) {
return this.nextHandler.handle(request);
}
return null; // مفيش handler عالج الطلب
}
}
// Handlers حقيقية
class AuthenticationHandler extends BaseHandler {
handle(request) {
if (!request.user) {
return { error: 'Authentication required' };
}
console.log('Authentication passed');
return super.handle(request);
}
}
class AuthorizationHandler extends BaseHandler {
handle(request) {
if (request.user.role !== 'admin') {
return { error: 'Insufficient permissions' };
}
console.log('Authorization passed');
return super.handle(request);
}
}
class ValidationHandler extends BaseHandler {
handle(request) {
if (!request.data || Object.keys(request.data).length === 0) {
return { error: 'Invalid data' };
}
console.log('Validation passed');
return super.handle(request);
}
}
// الاستخدام
const authHandler = new AuthenticationHandler();
const authzHandler = new AuthorizationHandler();
const validationHandler = new ValidationHandler();
authHandler.setNext(authzHandler).setNext(validationHandler);
const result = authHandler.handle({
user: { role: 'admin' },
data: { amount: 100 }
});
```
فوائد فعلاً مهمة
**القابلية للصيانة**: كل handler بيعمل حاجة واحدة وبيدورها تمام. لما قواعد البيزنس تتغير، بتعدل الـ handler المعني بس.
**القابلية للاختبار**: الـ unit testing بقت مباشرة — بتختبر كل handler في عزلة بدل ما تعمل mock لسيناريوهات معقدة.
**المرونة**: محتاج تعيد ترتيب خطوات المعالجة؟ غير إعداد السلسلة بس. عايز routing مشروط؟ نفذ منطق مخصص في الـ handlers.
**التشخيص (Debugging)**: لما حاجة تتكسر، بتعرف بالظبط أي handler فشل لأن كل واحد بيسجل قراره.
أخطاء شائعة تجنبها
متقعش في فخ إن الـ handlers تكون عامة جداً أو محددة جداً. اضرب توازن يكون فيه كل handler بيمثل قاعدة أعمال ذات معنى. كمان، قاوم رغبة إن الـ handlers تعرف مكانها في السلسلة — خلهم يركزوا على مسؤوليتهم ويثقوا إن السلسلة هتمشي.
تذكر: Chain of Responsibility مش عن إنها تستبدل كل منطقك الشرطي. دي عن تنظيم workflows معقدة فيها خطوات معالجة متعددة ومتميزة محتاجة تتم بالتتابع.
أدوات وفريمووركس بتيجي مع السلسلة مدمجة
كتير من الفريمووركس الحديثة بتنفيذ أشكال مختلفة من النمط ده:
- **Express.js middleware** ([expressjs.com](https://expressjs.com)) بتستخدم نهج شبيه بالسلسلة
- **ASP.NET Core middleware pipeline** بتمشي على نفس المبادئ
- **Java Servlet Filters** بتنفيذ المعالجة بالتسلسل
حتى لو الفريموورك بتاعك مش بيستخدم CoR صراحة، فهم النمط ده بيساعدك تصمم middleware و interceptor architectures أفضل.
متستخدمش Chain of Responsibility لما...
السلسلة مش عصا سحرية. تجنبها لما:
- خطوات المعالجة مترابطة بقوة وبتتنفذ دايمًا مع بعض
- الأداء حرج ومحتاج تقلل overhead استدعاء الميثودز
- ترتيب المعالجة مش مهم أو ثابت
- عندك أقل من ثلاث خطوات معالجة متميزة
تخليها تمشي في كود بيس بتاعك
مستعد تدخل Chain of Responsibility لمشروعك؟ ابدأ בקטן:
1. حدد دالة معقدة واحدة الكل بيبعد عنها
2. قسمها لخطوات معالجة منطقية
3. اعمل كلاسات handler منفصلة لكل خطوة
4. وصلهم مع بعض في سلسلة
5. اختبر كويس قبل ما تتوسع لمناطق تانية
الاستثمار بيرجع بسرعة في وقت debug أقل وكود ريفيوز أنظف.
الأسئلة الشائعة
**س: أتعامل مع الأخطاء في السلسلة إزاي؟**
ج: كل handler إما ينجح في معالجة الطلب أو يرمي exception مناسب. فكر تحط error handler في نهاية السلسلة يمسك الطلبات اللي ما اتمعالجتش.
**س: الـ handlers ممكن تعدل الطلب وهو بيمر؟**
ج: طبعاً! الممارسة دي شائعة. كل handler يقدر يغني، يتحقق، أو يحول بيانات الطلب للـ handlers اللي بعده.
**س: إيه رأيك في المعالجة غير المتزامنة (asynchronous)؟**
ج: التنفيذ الحديث غالباً بيدعم async/await. بس تأكد إن كل handler بيستنى الـ handler اللي بعده في السلسلة بشكل صحيح.
**س: الفرق بينه وبين نمط Strategy إيه؟**
ج: Strategy باختار خوارزمية واحدة من كتير، بينما Chain of Responsibility بتجرب handlers كتير بالتسلسل لحد ما واحد يمسك الطلب.
جمال Chain of Responsibility في بساطته. مش بحل كل مشاكل المعمار، لكن لما بتتطبق صح، بتحول كود سباجيتي غير قابل للصيانة لمنطق منظم ومقروء إنت هتشكر نفسك عليه في المستقبل.
تكنولوجيا
Comments (0)
No comments yet. Be the first to comment!
Leave a Comment