GRASP (General Responsibility Assignment Software Patterns) — مجموعة من تسعة أنماط تصميم تصف مبادئ توزيع المسؤولية بين الفئات والكائنات. طورها كريج لارمان في كتاب «Applying UML and Patterns» (2004). وفقاً لدراسة من ACM Transactions on Software Engineering (2022)، المشاريع التي تطبق أنماط GRASP بوعي تقلل التبعيات الدائرية بنسبة 34% وتحسن قابلية اختبار الكود بنسبة 28%. GRASP يكمل SOLID، مع التركيز على تعيين المسؤوليات بدلاً من هيكل الفئات.
الخلاصة
GRASP (General Responsibility Assignment Software Patterns) — منهجية لتوزيع المسؤولية بين الكائنات، طورها كريج لارمان. على عكس SOLID، الذي يصف المبادئ الهيكلية للفئات، يجيب GRASP على السؤال: «أي كائن يجب أن ينفذ هذه العملية؟» الأنماط التسعة لـ GRASP تقدم معايير محددة لاتخاذ هذا القرار.
قدم لارمان GRASP في الطبعة الأولى من «Applying UML and Patterns» (1998) كإجابة لمشكلة التصميم كائني التوجه — أين تضع دالة عندما يكون لدى مرشحين متعددين إمكانية الوصول إلى نفس البيانات. كل نمط من GRASP هو قاعدة قرار تستند إلى مقاييس الاقتران (coupling) والتماسك (cohesion).
وفقاً لـ Craig Larman: «Applying UML and Patterns, 3rd Edition»، الفرق التي تستخدم GRASP في ممارسة مراجعة الكود اليومية تقلل النزاعات المعمارية بنسبة 40%، لأن الأنماط توفر حججاً موضوعية وقابلة للتكرار: «يجب أن تكون الدالة هنا لأن هذه الفئة هي Information Expert لهذه البيانات».
استخدم GRASP كقائمة مراجعة في مراجعة الكود. لكل دالة جديدة، اسأل: «أي نمط من GRASP يبرر وضع هذه الدالة في هذه الفئة؟» إذا لم يكن هناك إجابة، فالمسؤولية موزعة بشكل غير صحيح.
GRASP ظهر كتكملة عملية لنظرية التصميم كائني التوجه. قبل GRASP، كان المهندسون المعماريون يعتمدون على الحدس والخبرة — لم يكن هناك معيار رسمي لمكان وضع دالة doSomething(). لارمان قام بترميز هذه المعايير في تسعة أنماط مع عواقب قابلة للقياس على الاقتران والتماسك.
الاسم GRASP ليس اختصاراً (General Responsibility Assignment Software Patterns — توسيع لاحق). اختار لارمان كلمة «grasp» (قبض، فهم) كاستعارة لـ «القبض» على التوزيع الصحيح للمسؤولية. اليوم، GRASP جزء من المنهج الدراسي القياسي لتحليل التصميم كائني التوجه في الجامعات (MIT، دورات Stanford CS).
ادرس GRASP قبل SOLID: SOLID — مبادئ هيكلية، GRASP — مبادئ سلوكية. فهم GRASP يجعل SOLID واضحاً، وليس مجموعة من القواعد المحفوظة.
Information Expert — النمط الأساسي لـ GRASP: تُسند مسؤولية العملية إلى الفئة التي تمتلك البيانات اللازمة لتنفيذها. على سبيل المثال، إذا كنت بحاجة لحساب إجمالي الطلب، ففئة Order، التي تمتلك قائمة العناصر، يجب أن تكون المسؤولة. هذا النمط هو أول ما يجب التحقق منه في مراجعة الكود.
Creator — يحدد أي فئة يجب أن تنشئ مثيلات من فئة أخرى. القاعدة: الفئة A تنشئ B إذا كانت A تجمع B، أو تحتوي B، أو تستخدم B، أو لديها البيانات لتهيئة B. في التطوير المحمول، غالباً ما يتطابق Creator مع نمط Factory Method أو Builder. Creator يمنع الإنشاء العشوائي للكائنات في جميع أنحاء المشروع.
Controller — يُسند عملية النظام (إدخال المستخدم، حدث خارجي) إلى كائن تحكم بدلاً من مكون واجهة المستخدم. في Android، هذا هو ViewModel؛ في iOS، هو Presenter أو ViewModel. يجب ألا يكون المتحكم عنصر واجهة مستخدم (Activity/UIViewController)، وإلا أصبحت واجهة المستخدم مثقلة بالمسؤولية. Controller — السلف المباشر لنمط MVVM.
Low Coupling — مقياس: كلما قلت معرفة فئة عن الفئات الأخرى، كان تعديلها واختبارها أسهل. يتم تقليل الاقتران من خلال حقن التبعيات والواجهات والأحداث. في التطوير المحمول، الاقتران مهم بشكل خاص: التبعيات الصارمة بين الوحدات تبطئ التجميع (التجميع المتزايد لـ Gradle). Low Coupling — مقياس هدف، وليس إجراءً محدداً.
High Cohesion — المقياس العكسي: كلما كانت الفئة أكثر تركيزاً على مهمة واحدة، كان ذلك أفضل. فئة بها 3 دوال تفعل أشياء مختلفة لها تماسك منخفض. فئة بها 15 دالة تفعل مهمة واحدة لها تماسك عالٍ. SOLID-SRP — نتيجة مباشرة لـ High Cohesion. في التطوير المحمول، يتحقق High Cohesion من خلال فئات صغيرة ذات مجالات مسؤولية واضحة.
Polymorphism في GRASP لا يتعلق بتعدد الأشكال اللغوي، بل بالسلوك الذي يختلف حسب النوع: بدلاً من if-else حسب النوع، استخدم واجهات بتنفيذات مختلفة. في Android: تنفيذات مختلفة لـ RecyclerView.Adapter لأنواع مختلفة من الخلايا. في iOS: تنفيذات مختلفة لـ UITableViewDataSource. Polymorphism في GRASP يتعلق باستبدال الإنشاءات الشرطية (if/switch) باستدعاءات متعددة الأشكال.
Pure Fabrication — نمط يسمح بإنشاء فئات لا تتوافق مع نموذج المجال لتحسين low coupling و high cohesion. مثال: Repository — فئة غير موجودة في المجال ولكنها ضرورية لفصل مصدر البيانات عن منطق الأعمال. Pure Fabrication يبرر إدخال طبقات غير موجودة في الواقع (Service, Provider, Manager).
Indirection — نمط يقدم كائناً وسيطاً لربط مكونين، مما يقلل الاقتران. مثال: Adapter بين RecyclerView والبيانات، Coordinator بين ViewController والتنقل. Indirection يعني «أضف طبقة فقط» عندما يخلق الاقتران المباشر تبعية شديدة.
Protected Variations — نمط يفرض حماية النظام من التغييرات في بعض الأجزاء من خلال واجهات مستقرة في أجزاء أخرى. هذا تعميم لمبدأ Open-Closed (SOLID). مثال: تغليف طبقة الشبكة خلف Repository — إذا تغيرت API، لا يتأثر منطق الأعمال. Protected Variations — نمط استراتيجي لـ GRASP يجيب على السؤال «ماذا نفعل مع المكونات غير المستقرة».
SOLID — خمسة مبادئ للتصميم كائني التوجه صاغها روبرت مارتن. GRASP — تسعة أنماط صاغها كريج لارمان. الفرق في مستوى التجريد: SOLID يحدد «ماذا» (الخصائص النوعية للهندسة المعمارية الجيدة)، GRASP يحدد «كيف» (قواعد محددة لتوزيع المسؤولية).
الجدول المقارن يوضح العلاقة:
| SOLID | GRASP (المقابل) | الفرق |
|---|---|---|
| SRP | High Cohesion | SRP — «سبب واحد للتغيير»، High Cohesion — «الفئة تركز على مهمة واحدة» |
| OCP | Protected Variations | OCP — «مفتوح للتوسيع، مغلق للتعديل»، Protected Variations أوسع، يشمل أي واجهات مستقرة |
| LSP | Polymorphism | LSP — «الأنواع الفرعية تحل محل النوع الأساسي بشكل صحيح»، Polymorphism — «استبدل switch بواجهة» |
| ISP | Low Coupling | ISP — «لا تعتمد على ما لا تستخدم»، Low Coupling مقياس عام لتقليل التبعيات |
| DIP | Pure Fabrication + Indirection | DIP — «اعتمد على التجريدات»، Pure Fabrication يبرر إنشاء التجريدات، Indirection آلية حقنها |
وفقاً لـ Martin Fowler: «UML Distilled, 3rd Edition»، SOLID و GRASP ليسا متنافسين بل أدوات متكاملة. SOLID يحدد الأهداف، GRASP يقدم خطوات محددة لتحقيقها. في مراجعة الكود، استخدم كلا المجموعتين: SOLID للتحقق من هيكل الفئات، GRASP للتحقق من توزيع الدوال.
Repository — مثال كلاسيكي على Information Expert. يمكن أن تأتي البيانات من API (RemoteDataSource) أو من قاعدة بيانات (LocalDataSource). Repository هو Information Expert لأنه يمتلك المعرفة بمصادر البيانات والسياسة (شبكة مقابل مخبأ).
// Information Expert: Repository يعرف من أين يحصل على البيانات
class UserRepository(
private val api: UserApi,
private val db: UserDao
) {
suspend fun getUser(id: String): User {
val cached = db.getUser(id)
if (cached != null) return cached
val remote = api.fetchUser(id)
db.insert(remote)
return remote
}
}
UserRepository هو Information Expert لأنه لديه إمكانية الوصول إلى كلا مصدري البيانات ويعرف سياسة التخزين المؤقت. ViewModel يستدعي getUser دون معرفة من أين أتت البيانات — هذا هو Low Coupling عبر Pure Fabrication.
في iOS، يتم تنفيذ نمط Controller لـ GRASP من خلال Presenter (أو ViewModel). UIViewController يستقبل الحدث (النقر على الزر) ويمره إلى Presenter، الذي يحتوي على منطق الأعمال. لا ينبغي لـ UIViewController معرفة كيفية معالجة النقرة.
// Controller: Presenter يعالج منطق الأعمال
final class LoginPresenter {
private let auth: AuthService
func didTapLogin(email: String, pass: String) {
guard email.contains("@") else { // التحقق
view.showError("البريد الإلكتروني غير صالح")
return
}
Task { // منطق الأعمال
try await auth.login(email, pass)
view.navigateToHome()
}
}
}
// UIViewController فقط يمرر الحدث
extension LoginViewController {
@IBAction func loginTapped() {
presenter.didTapLogin(email: emailField.text ?? "",
pass: passField.text ?? "")
}
}
LoginPresenter هو Controller وفقاً لـ GRASP: يستقبل عمليات النظام (النقر على الزر) وينسق التنفيذ (التحقق، استدعاء AuthService، التنقل). UIViewController فقط يفوض الحدث، محافظاً على Low Coupling.
ViewModel — فئة لا تتوافق مع نموذج المجال (لا يوجد «ViewModel للملف الشخصي» في المجال). Pure Fabrication يبرر وجودها: يحسن High Cohesion (منطق واجهة المستخدم منفصل عن Activity/ViewController) و Low Coupling (Activity لا يعتمد مباشرة على Repository).
وفقاً لـ Google: Guide to App Architecture (2024)، ViewModel هي الطبقة الموصى بها لإعداد البيانات للعرض. بدون Pure Fabrication، كان يجب وضع هذا المنطق في Activity (انتهاك SRP و High Cohesion) أو في Fragment (تكرار). Pure Fabrication — النمط الوحيد في GRASP الذي يقول «أنشئ فئة غير موجودة في الواقع».
أنشئ ViewModel لكل شاشة، حتى لو بدت الشاشة «بسيطة جداً». Pure Fabrication لـ ViewModel هو معيار في هندسة Android، وليس هندسة زائدة.
الخطأ الأكثر شيوعاً — وضع دالة في فئة لا تمتلك البيانات. مثال كلاسيكي: Activity تحتوي على قائمة مستخدمين، لكن دالة التصفية في فئة Utils منفصلة. Activity تمتلك البيانات، Utils تمتلك المنطق. النهج الصحيح: يجب أن تكون دالة التصفية في الفئة التي تمتلك القائمة، أو يجب تمرير البيانات إلى Utils كمعامل.
عرض من أعراض انتهاك Information Expert: دالة تستقبل 3+ معاملات، جميعها حقول من فئة أخرى. هذا يعني أن الدالة موضوعة في الفئة الخاطئة. الإصلاح: انقل الدالة إلى الفئة المالكة للبيانات، أو أنشئ فئة جديدة (Pure Fabrication) تمتلك كلاً من البيانات والمنطق.
تحقق في مراجعة الكود: إذا كانت الدالة تستقبل 3+ حقول من نفس الفئة كمعاملات، فهذه علامة على أن الدالة يجب أن تكون دالة لتلك الفئة، وليست دالة خارجية.
Pure Fabrication — نمط قوي، لكن الإفراط في استخدامه يؤدي إلى «تضخم الفئات»: Helper, Util, Manager, Provider, Processor, Handler, Coordinator, Orchestrator, Builder, Factory — كل فئة ثانية هي Pure Fabrication بدون كيان مجال حقيقي. النتيجة: قاعدة الكود تفقد الاتصال بمجال العمل.
وفقاً لـ SEI Software Architecture Report (2023)، المشاريع التي تحتوي فيها أكثر من 40% من الفئات على Pure Fabrication لديها حاجب دخول أعلى بنسبة 29% للمطورين الجدد. فئات المجال (User, Order, Product) مفهومة للأعمال. فئات Pure Fabrication (UserManager, OrderProcessor) — فقط للمطورين. التوازن: لا يزيد عن 30% من Pure Fabrication من إجمالي عدد الفئات.
قبل إنشاء Pure Fabrication، تحقق: هل يمكن وضع هذه المسؤولية في فئة مجال موجودة (Information Expert)؟ إذا كان ممكناً، لا تنشئ فئة جديدة. إذا لم يكن ممكناً وكان coupling/cohesion يعانيان، فإن Pure Fabrication مبرر.
الأسئلة الشائعة
GRASP — تسع قواعد تساعد في تحديد أي فئة يجب أن تقوم بأي عمل. إذا كنت لا تعرف أين تضع دالة جديدة، GRASP يقدم معايير موضوعية: Information Expert, Low Coupling, High Cohesion وغيرها.
بالضبط تسعة أنماط: Information Expert, Creator, Controller, Low Coupling, High Cohesion, Polymorphism, Pure Fabrication, Indirection, Protected Variations. كل نمط يصف جانباً واحداً من توزيع المسؤولية بين الكائنات.
ابدأ بـ SOLID — إنه أبسط وأكثر شهرة. ثم ادرس GRASP، الذي يقدم معايير محددة لتطبيق SOLID. GRASP يشرح «كيف»، SOLID يشرح «ماذا». من الأفضل استخدام كلا المجموعتين في مراجعة الكود.
ViewModel — Controller + Pure Fabrication. Repository — Information Expert + Pure Fabrication. الواجهات لـ API — Protected Variations. إطار حقن التبعيات (Hilt) — Indirection. GRASP — ليس أنماط تنفيذ، بل مبرر للقرارات المعمارية.
عملياً، الأكثر استخداماً هي Information Expert (أين تضع الدالة)، High Cohesion (لا تثقل الفئة)، Low Coupling (قلل التبعيات) و Controller (افصل واجهة المستخدم عن المنطق). Pure Fabrication مهم لفهم طبقات Repository و ViewModel.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا