چسبندگی (Cohesion) در توسعه موبایل: مبانی، سطوح و راههای افزایش

نویسنده: IT Sectr منتشر شده: 2026-05-13 زمان مطالعه: 9 دقیقه

Cohesion (چسبندگی) — متریکی است که نشان می‌دهد چقدر المان های داخل یک ماژول یا کلاس به هم پیوسته هستند. به گزارش ویکی‌پدیا، چسبندگی بالا نشانه یک ماژول خوب طراحی شده است که تمام روش‌ها و فیلدها بر روی یک وظیفه کار می‌کنند. Cohesion مستقیماً بر قابلیت حفظ کد تأثیر می‌گذارد و در مقابل coupling — پیوستگی بین ماژول‌ها — قرار می‌گیرد.

نکات کلیدی

  • Cohesion — اندازه‌گیری از اینکه چقدر المان های داخل ماژول با یک هدف مشترک مرتبط هستند
  • چسبندگی بالا درک کد، آزمایش و ایجاد تغییرات را آسان‌تر می‌کند
  • چسبندگی پایین به معنی است که ماژول چندین وظیفه غیرمرتبط انجام می‌دهد
  • Cohesion و coupling — متریک‌های متقابل: هر چقدر cohesion بالاتر، coupling پایین‌تر
  • چسبندگی وظیفه‌ای — بالاترین سطحی است که باید به آن بیشتر تلاش کنید

Cohesion چیست

Cohesion (چسبندگی) — متریکی است که ارزیابی می‌کند چقدر روش‌ها، فیلدها و ویژگی‌های داخل یک کلاس یا ماژول از نظر منطقی به هم مرتبط هستند. یک ماژول با چسبندگی بالا یک وظیفه انجام می‌دهد و تنها المان‌هایی را شامل می‌شود که برای انجام آن لازم است. یک ماژول با چسبندگی پایین سعی می‌کند چند چیز را به طور همزمان انجام دهد — روش‌ها از نظر معنایی ضعیفاً مرتبط هستند.

در بزرگ برنامه‌نویسی شیگرایی cohesion با Single Responsibility Principle (S) ارتباط نزدیکی دارد. اگر یک کلاس یک مسئولیت واضح داشته باشد، اگلب چسبندگی آن بالاست. اگر یک کلاس هم با UI، هم با منطق کسب‌وکار و هم با کار شبکه سروکار دارد — cohesion پایین است و چنین کلاسی را باید به چند کلاس جداگانه با مسئولیت محدودتر تقسیم کرد.

درک cohesion به برنامه‌نویس در تصمیم‌گیری درباره بازآرایی کمک می‌کند. وقتی می‌بینید در یک کلاس روشی وجود دارد که از فیلدهای کلاس استفاده نمی‌کند، این نشانه چسبندگی پایین است. چنین روشی یا در کلاس اضافی است یا کلاس به طور نادرست طراحی شده است. تلاش برای چسبندگی بالا کاری مداوم برای بهبود معماری در هر سطح کد است.

نوع‌ها و سطوح چسبندگی

در مهندسی نرم‌افزار هفت سطح cohesion وجود دارد که از بدترین تا بهترین مرتب شده‌اند. درک این مقیاس به شما امکان می‌دهد کیفیت ماژول را به صورت عینی ارزیابی کرده و تعیین کنید در چه جهتی در بازآرایی حرکت کنید. هر چقدر سطح بالاتر باشد، کد قابل حفظ‌تر و قابل فهم‌تر خواهد بود.

چسبندگی پایین: تصادفی، منطقی و زمانی

تصادفی (coincidental) — بدترین سطح، زمانی که المان‌ها در ماژول به صورت تصادفی و بدون هیچ ارتباط منطقی گروه‌بندی شده‌اند. مثال: کلاس Utilities که شامل روش‌های فرمت‌دهی تاریخ، ارسال ایمیل و محاسبه تخفیف است. چنین کلاسی را بدون خواندن تمام روش‌ها نمی‌توان فهمید و تغییر یک روش می‌تواند دیگران را فقط به دلیل اینکه در کنار هم قرار دارند تخریب کند.

چسبندگی منطقی (logical) — المان‌ها وظایف منطقیاً مرتبط ولی از نظر ماهیت متفاوت انجام می‌دهند. کلاسی با روش‌های parseJSON، parseXML و parseCSV از نظر منطقی به موضوع «پارسینگ» مرتبط است، اما هر روش کاری اساساً متفاوت انجام می‌دهد. مشکل: با افزودن فرمت جدید (YAML)، کلاس بزرگ‌تر شده و اینترفیس آن متورم می‌شود.

چسبندگی زمانی (temporal) — المان‌ها بر اساس زمان اجرا گروه‌بندی شده‌اند. کلاس AppInitializer که پایگاه داده را تنظیم می‌کند، کونفیگ را بارگیری می‌کند، آنالیتیک را اهلیه می‌کند — همه اینها در زمان راه‌اندازی اتفاق می‌افتد، اما وظایف با هم مرتبط نیستند. بهتر است آنها را به Initializerهای جداگانه برای هر حوزه مسئولیت تقسیم کرد.

چسبندگی میانه: رویه‌ای و ارتباطی

چسبندگی رویه‌ای (procedural) زمانی ایجاد می‌شود که المان‌ها با تسلسل اجرا متحد شوند. ماژول «پردازش سفارش» شامل روش‌های validateCart، processPayment، sendConfirmation است — هر روش بطور حتمی بعد از قبلی فراخوانده می‌شود. این از چسبندگی تصادفی یا منطقی بهتر است، اما هنوز ایدئال نیست: هر قدم را می‌توان به یک ماژول جداگانه منتقل کرد.

چسبندگی ارتباطی (communicational) — المان‌ها با داده‌های یکسان کار می‌کنند. کلاس UserService با روش‌های getUser، updateUser، deleteUser با نهاد مشترک User متحد شده است. این به مراتب از چسبندگی رویه‌ای بهتر است: کلاس یک حوزه موضوعی واضح دارد. اکثر کلاس‌های Repository در پروژه‌های موبایل چسبندگی ارتباطی دارند.

چسبندگی بالا: وظیفه‌ای

چسبندگی وظیفه‌ای (functional) — بالاترین سطح، زمانی که هر عنصر ماژول در انجام یک وظیفه شرکت می‌کند. کلاس PasswordValidator با تک روش validate که طول، وجود شرایط و پیچیدگی رمز عبور را بررسی می‌کند — نمونه چسبندگی وظیفه‌ای است. اگر چنین کلاسی تغییر کند، فقط به دلیل تغییر قوانین اعتبارسنجی رمز عبور است.

دستیابی به چسبندگی وظیفه‌ای هدف اصلی بازآرایی معماری است. هر کلاس باید دقیقاً یک دلیل برای تغییر داشته باشد. در توسعه موبایل، چسبندگی وظیفه‌ای با جداسازی Use Caseهای مجزا، Viewهای سفارشی، فرمت‌دهنده‌ها و اعتبارسنج‌ها به دست می‌آید. هر چنین کلاسی یک بلوک ساختمانی کامل با یک حوزه مسئولیت واضح است.

Cohesion vs Coupling

Cohesion و coupling — دو جنبه یک کیفیت. هر چقدر cohesion داخل ماژول بالاتر باشد، coupling بین ماژول‌ها پایین‌تر است. یک سیستم خوب طراحی شده همزمان به چسبندگی بالا در داخل و پیوستگی ضعیف در خارج گرایش دارد. این قاعده از سال‌های 1970 در مهندسی نرم‌افزار بنیادین تلقی می‌شود.

نسبت cohesion-coupling را می‌توان به عنوان یک تعادل در نظر گرفت. اگر برنامه‌نویس با ادغام چند وظیفه در یک کلاس، cohesion را قربان می‌دهد، ماژول‌های مجاور وابستگی بیشتری پیدا می‌کنند — آنها باید برای اهداف مختلف به این کلاس پربار مراجعه کنند که coupling را افزایش می‌دهد. و برعکس، تقسیم به کلاس‌های کوچک با چسبندگی بالا تعداد نقاط تعامل بین ماژول‌ها را کاهش می‌دهد.

در عمل این یعنی: وقتی یک کلاس جدید با چسبندگی وظیفه‌ای جدا می‌کنید، دیگر ماژول‌ها را از لزوم دانستن جزئیات پیاده‌سازی آن آزاد می‌کنید. به عنوان مثال، با جداسازی EncryptionManager به یک کلاس جداگانه با چسبندگی وظیفه‌ای، به دیگر ماژول‌ها یک اینترفیس ساده encrypt/decrypt بدون نیاز به درک جزئیات الگوریتم تشفیر می‌دهید.

kotlin
// چسبندگی پایین — کلاس هر چیزی را با هم انجام می‌دهد
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 چسبندگی منطقی دارد — تمام روش‌ها مربوط به کاربران است، اما هر کدام کاری اساساً متفاوت انجام می‌دهند. پس از بازآرایی، هر کلاس چسبندگی وظیفه‌ای دارد و coupling کاهش می‌یابد، زیرا دیگر ماژول‌ها فقط به کلاس مورد نیاز خود وابسته هستند، نه به کل مجموع UserManager.

چگونه چسبندگی را در کد اندازه‌گیری کنیم

LCOM (Lack of Cohesion of Methods) — معروف‌ترین متریک برای اندازه‌گیری چسبندگی کلاس است. LCOM تعداد زوج‌روش‌هایی را که از فیلدهای مشترک استفاده نمی‌کنند شمارش می‌کند. مقدار 0 به معنای چسبندگی ایدئال است (تمام روش‌ها با فیلدهای یکسان کار می‌کنند)، مقدار بالا به معنای چسبندگی پایین است. LCOM4 (نسخه بهبود یافته) ارتباطات انتقالی از طریق سایر روش‌ها را نیز در نظر می‌گیرد.

در توسعه Android می‌توان متریک‌های چسبندگی را از طریق Detekt با قاعده TooManyFunctions به دست آورد. کلاس‌هایی با دهها روش که از گروه‌های فیلدی مختلف استفاده می‌کنند به احتمال زیاد چسبندگی پایینی دارند. در iOS، SwiftLint قواعد file_length و function_body_length را دارد — نشان‌دهندگان غیرمستقیم: فایل‌ها و روش‌های طولانی اغلب چسبندگی پایین را نشان می‌دهند.

روش دستی ارزیابی: سوال «آیا این کلاس به یک دلیل تغییر می‌کند یا چند دلیل؟» را بپرسید. اگر می‌توانید بیش از یک دلیل مستقل نام ببرید — کلاس چسبندگی پایینی دارد. آزمایش دوم: «آیا می‌توان این کلاس را به دو کلاس مستقل تقسیم کرد؟» اگر بله — این کار را انجام دهید. بررسی منظم cohesion در بازبینی کد از ایجاد کلاس‌های God جلوگیری می‌کند و بدهی فنی را کاهش می‌دهد.

چگونه Cohesion را در پروژه موبایل افزایش دهیم

گام اول — Single Responsibility Principle را اعمال کنید. هر کلاس باید یک مسئولیت واضح داشته باشد. اگر در کلاس روشی وجود دارد که به وظیفه اصلی آن مربوط نیست، آن را به یک کلاس جداگانه منتقل کنید. تکنیک Extract Class یا Extract Delegate در IDE این فرآیند را خودکار می‌کند. پس از جداسازی بررسی کنید که آیا کلاس اصلی متمرکزتر شده است.

گام دوم — از الگوی Facade برای ساده‌سازی اینترفیس استفاده کنید. اگر یک کلاس 20 روش ارائه می‌دهد و مشتریان فقط از 3-4 تا آن استفاده می‌کنند، احتمالاً کلاس چسبندگی پایینی دارد — فقره بسیار کارکرد مختلف است. روش‌ها را بر اساس موضوع گروه‌بندی کرده و برای هر گروه کلاس‌های جداگانه ایجاد کنید، و کلاس اصلی را به یک facade تبدیل کنید یا حذف کنید.

گام سوم — به گروه‌های فیلدی توجه کنید. اگر کلاس فیلدهایی دارد که فقط بخشی از روش‌ها استفاده می‌کنند — این نشانگر چسبندگی پایین است. کلاس را بر اساس گروه‌های فیلدی تقسیم کنید. به عنوان مثال، اگر کلاس شامل فیلدهای userRepository، networkClient و analyticsTracker است، اما روش‌های گروه اول فقط از userRepository و گروه دوم فقط از networkClient استفاده می‌کنند — اینها دو کلاس متفاوت هستند.

گام چهارم — از ایجاد کلاس‌های «ابزاری» با روش‌های static تصادفی خودداری کنید. هر روش static در کلاس Utils یا Helpers کاندیدای جداسازی به یک کلاس تخصصی است. FormatUtils.dateToString را به DateFormatter و ValidationUtils.isValidEmail را به EmailValidator منتقل کنید. این کار cohesion هر کلاس را افزایش می‌دهد و کد را خودمستند می‌سازد.

سوالات متداول

آیا چسبندگی بالا همیشه خوب است؟

تقریباً همیشه. چسبندگی وظیفه‌ای کد را قابل فهم و قابل پیش‌بینی می‌کند. اما افراط در این کار می‌تواند منجر به تقسیم افراطی شود: زمانی که برای هر عملیات یک کلاس جداگانه ایجاد شود و معماری بیش از حد پیچیده گردد. تعادل — چند کلاس برای یک ویژگی، هر کدام با چسبندگی وظیفه‌ای.

Cohesion چه تفاوتی با modularity دارد؟

Cohesion — متریک توافق داخلی یک ماژول یا کلاس است. Modularity — اصل معماری که بر اساس آن اپلیکیشن به ماژول‌های فیزیکی تقسیم می‌شود. Cohesion بالا هدفی در طراحی هم کلاس‌های جداگانه و هم ماژول‌های کامل است.

ابزارهای تحلیل کد چگونه در مورد cohesion کمک می‌کنند؟

Detekt برای Android و Xcode Analyzer برای iOS کلاس‌هایی را که تعداد مشکوکی زیاد روش یا فیلد دارند برجسته می‌کنند. IntelliJ IDEA و AppCode نمایش وابستگی‌ها را دارند — می‌توانید گراف ارتباطات را مشاهده کرده و کلاس‌های با چسبندگی پایین را کشف کنید. SonarQube متریک‌های LCOM را به صورت خودکار محاسبه می‌کند.

آیا یک اینترفیس می‌تواند چسبندگی بالا داشته باشد؟

بله. یک اینترفیس با روش‌های connect، disconnect و isConnected چسبندگی بالایی دارد — تمام روش‌ها مربوط به مدیریت اتصال است. یک اینترفیس با روش‌های connect، parseData و renderUI چسبندگی پایینی دارد. اصل Interface Segregation (SOLID) ایجاد اینترفیس‌های متخصص با چسبندگی بالا را ایجاب می‌کند.

چگونه cohesion را در بازبینی کد بررسی کنیم؟

سه سوال بپرسید: آیا می‌توان هدف کلاس را با یک جمله توصیف کرد؟ آیا تمام روش‌ها از این هدف پشتیبانی می‌کنند؟ آیا در کلاس فیلدهایی وجود دارد که توسط بخشی از روش‌ها استفاده نمی‌شوند؟ اگر پاسخ به هر کدام از سوالات منفی است — cohesion پایین است و کلاس باید تقسیم شود.

نتیجه‌گیری

  • Cohesion — متریک توافق داخلی ماژول، نشان می‌دهد چقدر المان‌های آن با یک هدف مشترک مرتبط هستند
  • چسبندگی وظیفه‌ای — بالاترین سطح، زمانی که تمام المان‌های ماژول بر روی یک وظیفه کار می‌کنند
  • چسبندگی تصادفی و منطقی — بدترین سطوح، نشان‌دهنده نیاز به بازآرایی
  • Cohesion و coupling معکوساً متناسب هستند: هر چقدر چسبندگی داخلی بالاتر، پیوستگی خارجی ضعیف‌تر
  • LCOM — متریک برای ارزیابی عددی cohesion، موجود در تحلیل‌گرهای ستاتیک
  • Single Responsibility Principle — ابزار عملی برای دستیابی به چسبندگی بالا
  • کلاس‌های ابزاری Utils خودداری کنید — هر روش چنین کلاسی باید به یک کلاس تخصصی جداگانه تبدیل شود

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید