التماسك هو مقياس يوضح مدى ارتباط العناصر داخل وحدة أو فئة واحدة. وفقاً لـ Wikipedia، فإن التماسك العالي هو سمة الوحدة جيدة التصميم، حيث تعمل جميع الأساليب والحقول على مهمة واحدة. التماسك يؤثر بشكل مباشر على قابلية صيانة الكود ويقابل بالاقتران — الارتباط بين الوحدات.
النقاط الرئيسية
التماسك هو مقياس يقيم مدى الارتباط المنطقي بين الأساليب والحقول والخصائص داخل فئة أو وحدة واحدة. الوحدة عالية التماسك تؤدي مهمة واحدة وتحتوي فقط على العناصر اللازمة لإنجازها. الوحدة منخفضة التماسك تحاول فعل عدة أشياء في وقت واحد — أساليبها ضعيفة الارتباط من حيث المعنى.
في سياق البرمجة كائنية التوجه، يرتبط التماسك ارتباطاً وثيقاً بمبدأ المسؤولية الواحدة (S). إذا كانت الفئة لها مسؤولية واحدة واضحة، فإن تماسكها عالٍ بشكل عام. إذا كانت الفئة تتعامل مع واجهة المستخدم ومنطق الأعمال والشبكات في نفس الوقت — فإن التماسك منخفض، ويجب تقسيم هذه الفئة إلى عدة فئات منفصلة بمسؤوليات أضيق.
فهم التماسك يساعد المطورين على اتخاذ قرارات إعادة الهيكلة. عندما ترى أسلوباً في فئة لا يستخدم أي حقول من الفئة، فهذه علامة على انخفاض التماسك. هذا الأسلوب إما في غير مكانه في الفئة، أو أن الفئة مصممة بشكل سيء. السعي لتحقيق التماسك العالي هو جهد مستمر لتحسين البنية على كل مستوى من مستويات الكود.
في هندسة البرمجيات، يتم تمييز سبعة مستويات من التماسك، مرتبة من الأسوأ إلى الأفضل. فهم هذا المقياس يسمح لك بتقييم جودة الوحدة بشكل موضوعي وتحديد اتجاه إعادة الهيكلة. كلما ارتفع المستوى، كان الكود أكثر قابلية للصيانة والفهم.
المصادفي — أسوأ مستوى، حيث يتم تجميع العناصر في وحدة بشكل عشوائي دون أي اتصال منطقي. مثال: فئة Utilities تحتوي على أساليب لتنسيق التواريخ وإرسال البريد الإلكتروني وحساب الخصومات. لا يمكن فهم هذه الفئة دون قراءة جميع أساليبها، وتغيير أسلوب واحد قد يكسر آخرين فقط لوجودهم معاً.
المنطقي — العناصر تؤدي مهاماً مرتبطة منطقياً لكنها مختلفة جوهرياً. فئة بأساليب parseJSON وparseXML وparseCSV مرتبطة منطقياً بموضوع «التحليل»، لكن كل أسلوب يقوم بعمل مختلف جوهرياً. المشكلة: عند إضافة تنسيق جديد (YAML)، تنمو الفئة وتصبح واجهتها منتفخة.
الزمني — يتم تجميع العناصر حسب وقت التنفيذ. فئة AppInitializer التي تُعد قاعدة البيانات وتحمّل الإعدادات وتهيئ التحليلات — كل هذا يحدث عند بدء التطبيق، لكن المهام نفسها غير مرتبطة. من الأفضل تقسيمها إلى Initializers منفصلة لكل مجال مسؤولية.
الإجرائي — يحدث عندما تتحد العناصر بتسلسل التنفيذ. وحدة «معالجة الطلب» تحتوي على أساليب validateCart وprocessPayment وsendConfirmation — كل أسلوب يُستدعى بدقة بعد السابق. هذا أفضل من التماسك المصادفي أو المنطقي، لكنه لا يزال غير مثالي: يمكن استخراج كل خطوة في وحدة منفصلة.
التواصلي — العناصر تعمل مع نفس البيانات. فئة UserService بأساليب getUser وupdateUser وdeleteUser متحدة بكيان User المشترك. هذا أفضل بشكل ملحوظ من التماسك الإجرائي: الفئة لها مجال واضح. معظم فئات Repository في المشاريع المحمولة لها تماسك تواصلي.
الوظيفي — أعلى مستوى، حيث يشارك كل عنصر في الوحدة في أداء مهمة واحدة. فئة PasswordValidator بأسلوب واحد validate يتحقق من الطول ووجود الأحرف وتعقيد كلمة المرور هي مثال على التماسك الوظيفي. إذا تغيرت هذه الفئة، فذلك فقط لأن قواعد التحقق من كلمة المرور قد تغيرت.
تحقيق التماسك الوظيفي هو الهدف الأساسي لإعادة الهيكلة المعمارية. يجب أن يكون لكل فئة سبب واحد تماماً للتغيير. في تطوير التطبيقات المحمولة، يتم تحقيق التماسك الوظيفي من خلال استخراج حالات استخدام منفصلة وعروض مخصصة ومنسقين ومدققي تحقق. كل فئة من هذه الفئات هي لبنة بناء كاملة بمجال مسؤولية واضح.
التماسك والاقتران وجهان لعملة واحدة. كلما زاد التماسك داخل الوحدة، قل الاقتران بين الوحدات. النظام جيد التصميم يسعى في نفس الوقت إلى تماسك داخلي عالٍ واقتران خارجي ضعيف. تم الاعتراف بهذا المبدأ كأساسي في هندسة البرمجيات منذ السبعينيات.
يمكن اعتبار علاقة التماسك-الاقتران كتوازن. إذا ضحى المطور بالتماسك بدمج عدة مهام في فئة واحدة، تحصل الوحدات المجاورة على تبعيات أكثر — تضطر للوصول إلى هذه الفئة المثقلة لأغراض مختلفة، مما يزيد الاقتران. وعلى العكس، التقسيم إلى فئات صغيرة عالية التماسك يقلل نقاط التفاعل بين الوحدات.
في الممارسة، هذا يعني: عندما تستخرج فئة جديدة ذات تماسك وظيفي، فأنت في نفس الوقت تحرر الوحدات الأخرى من الحاجة لمعرفة تفاصيل تنفيذها. على سبيل المثال، استخراج EncryptionManager في فئة منفصلة ذات تماسك وظيفي يوفر للوحدات الأخرى واجهة بسيطة encrypt/decrypt دون الحاجة لفهم تفاصيل خوارزمية التشفير.
// تماسك منخفض — الفئة تفعل كل شيء في وقت واحد
class UserManager {
fun fetchAndSaveUser(id: String) { }
fun parseUserJson(json: String): User { }
fun displayUserName(user: User): String { }
fun validateEmail(email: String): Boolean { }
}
// تماسك عالٍ — كل فئة تحل مهمة واحدة
class UserRepository {
fun fetchUser(id: String): User { }
}
class UserJsonParser {
fun parse(json: String): User { }
}
class UserNameFormatter {
fun format(user: User): String { }
}
class EmailValidator {
fun isValid(email: String): Boolean { }
}
المثال يوضح الفرق: UserManager لديه تماسك منطقي — جميع الأساليب حول المستخدمين، لكن كل واحد يقوم بعمل مختلف جوهرياً. بعد إعادة الهيكلة، كل فئة لها تماسك وظيفي، ويقل الاقتران لأن الوحدات الأخرى تعتمد فقط على الفئة التي تحتاجها، وليس على UserManager بأكمله.
LCOM (نقص تماسك الأساليب) هو المقياس الأكثر شهرة لقياس تماسك الفئة. LCOM يحسب عدد أزواج الأساليب التي لا تشارك حقولاً مشتركة. القيمة 0 تعني تماسكاً مثالياً (جميع الأساليب تعمل مع نفس الحقول)، بينما القيمة العالية تشير إلى تماسك منخفض. LCOM4 (نسخة محسنة) يأخذ في الاعتبار الاتصالات المتعدية عبر أساليب أخرى.
في تطوير Android، يمكن الحصول على مقاييس التماسك من خلال Detekt بقاعدة TooManyFunctions. الفئات ذات العشرات من الأساليب التي تستخدم مجموعات مختلفة من الحقول غالباً ما يكون لها تماسك منخفض. في iOS، SwiftLint لديه قواعد file_length وfunction_body_length — مؤشرات غير مباشرة: الملفات والطرق الطويلة غالباً ما تشير إلى تماسك منخفض.
طريقة تقييم يدوية: اسأل السؤال «هل ستتغير هذه الفئة لسبب واحد أو لأسباب متعددة؟» إذا كان بإمكانك تسمية أكثر من سبب مستقل — الفئة ذات تماسك منخفض. اختبار ثانٍ: «هل يمكن تقسيم هذه الفئة إلى فئتين مستقلتين؟» إذا كان الجواب نعم — افعلها. فحص التماسك بانتظام في مراجعات الكود يمنع ظهور الفئات الضخمة ويقلل الديون الفنية.
الخطوة الأولى — تطبيق مبدأ المسؤولية الواحدة. يجب أن يكون لكل فئة مسؤولية واحدة واضحة. إذا كانت الفئة تحتوي على أسلوب لا يتعلق بمهمتها الرئيسية، استخرجه إلى فئة منفصلة. تقنية Extract Class أو Extract Delegate في بيئات التطوير تؤتمت هذه العملية. بعد الاستخراج، تحقق مما إذا كانت الفئة الأصلية أصبحت أكثر تركيزاً.
الخطوة الثانية — استخدام نمط Facade لتبسيط الواجهة. إذا كانت الفئة توفر 20 أسلوباً لكن العملاء يستخدمون فقط 3-4، فقد يكون للفئة تماسك منخفض — إنها تقدم وظائف متنوعة جداً. جمّع الأساليب حسب الموضوع، واستخرج فئات منفصلة لكل مجموعة، واجعل الفئة الأصلية واجهة أو احذفها.
الخطوة الثالثة — الانتباه إلى مجموعات الحقول. إذا كانت الفئة تحتوي على حقول تُستخدم فقط من قبل مجموعة فرعية من الأساليب — فهذا مؤشر على تماسك منخفض. قسّم الفئة حسب مجموعات الحقول. على سبيل المثال، إذا كانت فئة تحتوي على حقول userRepository وnetworkClient وanalyticsTracker، لكن المجموعة الأولى من الأساليب تستخدم فقط userRepository بينما الثانية تستخدم networkClient — فهاتان فئتان مختلفتان.
الخطوة الرابعة — تجنب إنشاء فئات «أدوات» بأساليب static عشوائية. كل أسلوب static موجود في فئة Utils أو Helpers هو مرشح للاستخراج إلى فئة متخصصة. FormatUtils.dateToString من الأفضل نقله إلى DateFormatter، وValidationUtils.isValidEmail إلى EmailValidator. هذا يزيد تماسك كل فئة ويجعل الكود موثقاً ذاتياً.
الأسئلة الشائعة
دائماً تقريباً. التماسك الوظيفي يجعل الكود واضحاً وقابلاً للتنبؤ. ومع ذلك، قد يؤدي أخذه إلى أقصى الحدود إلى تجزئة مفرطة: إنشاء فئة منفصلة لكل عملية، مما يجعل البنية معقدة بشكل مفرط. التوازن هو بضع فئات لكل ميزة، كل منها ذات تماسك وظيفي.
التماسك هو مقياس للاتساق الداخلي لوحدة أو فئة واحدة. النمطية هي مبدأ معماري حيث يتم تقسيم التطبيق إلى وحدات مادية. التماسك العالي هو هدف عند تصميم كل من الفئات الفردية والوحدات الكاملة.
Detekt لنظام Android وXcode Analyzer لنظام iOS يسلطان الضوء على الفئات التي تحتوي على عدد كبير بشكل مريب من الأساليب أو الحقول. IntelliJ IDEA وAppCode لديهما تصور للتبعيات — يمكنك رؤية رسم بياني للاتصالات واكتشاف الفئات ذات التماسك المنخفض. SonarQube يحسب مقاييس LCOM تلقائياً.
نعم. واجهة بأساليب connect وdisconnect وisConnected لها تماسك عالٍ — جميع الأساليب تتعلق بإدارة الاتصال. واجهة بأساليب connect وparseData وrenderUI لها تماسك منخفض. مبدأ فصل الواجهات (SOLID) يتطلب إنشاء واجهات ضيقة التركيز ذات تماسك عالٍ.
اسأل ثلاثة أسئلة: هل يمكن وصف الغرض من الفئة في جملة واحدة؟ هل تدعم جميع الأساليب هذا الغرض؟ هل هناك حقول في الفئة لا تستخدمها بعض الأساليب؟ إذا كانت الإجابة على أي سؤال بالنفي — فالتماسك منخفض، ويجب تقسيم الفئة.
الخلاصة
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا