اصول و روشهای معماری — مجموعهای از قوانین و توصیهها هستند که به توسعهدهندگان کمک میکنند کد قابل نگهداری، مقیاسپذیر و قابل فهم ایجاد کنند. بر اساس TIOBE Index (2025)، پروژههایی که از اصول معماری پیروی میکنند 40٪ نقصهای بحرانی کمتری دارند. در این مقاله به بررسی SOLID، GRASP، DRY، KISS، YAGNI و سایر اصول میپردازیم و همچنین در مورد بدهی فنی و Code Smell بحث میکنیم.
نکات کلیدی
اصول معماری — پایه و اساس کد با کیفیت هستند. SOLID یک سرواژه است که توسط رابرت مارتین («عمو باب») معرفی شده و پنج اصل طراحی شیءگرا را توصیف میکند. پیروی از SOLID کد را انعطافپذیرتر، قابل تستتر و مقاوم در برابر تغییرات میکند. نقض اصول معماری یکی از دلایل اصلی بدهی فنی است.
بیایید هر اصل را بررسی کنیم. Single Responsibility Principle (SRP) — هر کلاس باید تنها یک دلیل برای تغییر داشته باشد. Open/Closed Principle (OCP) — کلاسها برای گسترش باز اما برای تغییر بسته هستند. Liskov Substitution Principle (LSP) — اشیاء زیرنوع باید بتوانند اشیاء نوع پایه را بدون شکستن منطق جایگزین کنند. Interface Segregation Principle (ISP) — چندین رابط تخصصی بهتر از یک رابط عمومی است. Dependency Inversion Principle (DIP) — به انتزاعات وابسته باشید، نه به پیادهسازیهای عینی.
بر اساس تحلیل SonarQube (2025)، نقض اصول SOLID در 68٪ پروژههای تجاری رخ میدهد. شایعترین مشکلات نقض SRP (35٪) و ISP (22٪) است. در IT Sectr، ما SOLID را در مرحله بازبینی معماری پیادهسازی میکنیم — این به شناسایی مشکلات قبل از تبدیل شدن به بدهی فنی کمک میکند.
SRP (اصل مسئولیت واحد) — مهمترین و در عین حال پرنقضترین اصل SOLID. میگوید: یک کلاس باید تنها یک دلیل برای تغییر داشته باشد. اگر یک کلاس کارهای زیادی انجام دهد، تست، تغییر و درک آن دشوار است.
یک نقض معمولی کلاسی است که همزمان دادهها را پردازش میکند، در پایگاه داده ذخیره میکند و اعلانهای ایمیل ارسال میکند. مثال زیر نقض SRP را در Kotlin و نحوه رفع آن نشان میدهد.
// نقض SRP — کلاس سه کار متفاوت انجام میدهد
class UserService {
fun registerUser(email: String, name: String) {
// 1. اعتبارسنجی داده
if (!email.contains("@")) throw IllegalArgumentException("Invalid email")
// 2. ذخیره در پایگاه داده
val user = User(email, name)
database.save(user)
// 3. ارسال اعلان
emailService.sendWelcomeEmail(email, name)
}
}
// رفع — تقسیم به سه کلاس
class UserRegistrationService {
fun register(email: String, name: String) {
UserValidator().validate(email)
val user = User(email, name)
UserRepository().save(user)
NotificationService().sendWelcome(user)
}
}
در نسخه تصحیحشده، هر کلاس مسئول وظیفه خود است: UserValidator — برای اعتبارسنجی، UserRepository — برای ذخیره، NotificationService — برای اعلانها. این کد را قابل تست و قابل استفاده مجدد میکند — میتوانید پیادهسازی پایگاه داده را بدون تغییر منطق اعتبارسنجی تعویض کنید.
GRASP (General Responsibility Assignment Software Patterns) — نه اصل معماری برای توزیع مسئولیت بین اشیاء، توصیف شده توسط کریگ لارمن. برخلاف SOLID، GRASP به این سؤال پاسخ میدهد «کدام کلاس باید این متد را داشته باشد؟». الگوهای کلیدی: Information Expert, Creator, Controller, Low Coupling, High Cohesion, Polymorphism, Pure Fabrication, Indirection, Protected Variations.
Law of Demeter (LoD، اصل حداقل وابستگی) — یک قانون ساده: یک شیء باید فقط با همسایگان مستقیم خود ارتباط برقرار کند. نباید a.getB().getC().doSomething() نوشت — این وابستگی شدید بین کلاسها ایجاد میکند. LoD قابلیت استفاده مجدد را بهبود میبخشد و تست را ساده میکند.
در IT Sectr، ما انطباق با LoD را در بازبینی کد بررسی میکنیم. اگر یک متد از سه شیء یا بیشتر «عبور» کند، این نشانهای است که معماری نیاز به سادهسازی دارد. نقض LoD یکی از رایجترین Code Smellها در پروژههای بزرگ است.
DRY (Don't Repeat Yourself), KISS (Keep It Simple, Stupid) و YAGNI (You Ain't Gonna Need It) — سه اصل معماری پایه که هر توسعهدهندهای میشناسد. علیرغم سادگی، نقض آنها دائماً رخ میدهد.
DRY — کد را تکرار نکنید. اگر منطق یکسان در دو مکان ظاهر شد، آن را به یک متد یا کلاس مشترک استخراج کنید. تکرار منبع اصلی باگها است: اصلاح در یک مکان فراموش میشود در مکان دیگر اعمال شود. DRY به این معنی نیست که نمیتوانید کد مشابه داشته باشید — مهم این است که منطق کسبوکار تکرار نشود.
KISS — هر چه سادهتر، بهتر. راهحلهای پیچیده با انتزاعات و وراثتهای زیاد اغلب بیش از حد هستند. با یک راهحل ساده شروع کنید و فقط در صورت لزوم پیچیدهتر کنید. YAGNI — برای عملکردی که ممکن است «یک روز بعد» نیاز باشد کد ننویسید. این منجر به باد کردن پایگاه کد و افزایش پیچیدگی نگهداری میشود.
DRY — این فقط عدم وجود کپی-پیست نیست. این اصلی است که بر اساس آن هر قطعه دانش یا منطق باید یک نمایش واحد و بدون ابهام در سیستم داشته باشد. تکرار میتواند آشکار (کد کپی شده) و ضمنی (منطق یکسان در لایههای مختلف) باشد.
در IT Sectr، ما از معیارهای تحلیل کد برای تشخیص تکرار استفاده میکنیم. ابزارهایی مانند SonarQube و Detekt درصد کد تکراری را نشان میدهند. مقدار بالای 5٪ دلیلی برای بازسازی (refactoring) است. با این حال، مهم است به خاطر داشته باشید: DRY نباید به قیمت انتزاعات اشتباه به دست آید — گاهی بهتر است دو قطعه کد مشابه را همانطور که هستند رها کنید اگر ترکیب آنها درک را پیچیده کند.
Separation of Concerns (SoC) — یک اصل معماری که در آن سیستم به بخشهای مستقل (concerns) تقسیم میشود، هر کدام وظیفه خود را حل میکنند. یک مثال کلاسیک تقسیم به لایهها است: نمایش، منطق کسبوکار، دسترسی به داده. هر لایه فقط به لایه پایینی خود وابسته است.
Modularity (ماژولار بودن) — درجهای که سیستم میتواند به ماژولها تقسیم شود. یک ماژول گروهی از کلاسهای مرتبط منطقی با یک رابط به خوبی تعریف شده است. ماژولها باید دارای وابستگی کم (low coupling) و انسجام بالا (high cohesion) باشند.
Cohesion (انسجام) — معیاری از اینکه عناصر درون یک ماژول چقدر با یکدیگر مرتبط هستند. انسجام بالا خوب است: یک کلاس یک کار انجام میدهد و آن را به خوبی انجام میدهد. Low coupling (وابستگی کم) — معیاری از اینکه ماژولها چقدر از یکدیگر مستقل هستند. وابستگی کم خوب است: تغییر یک ماژول ماژولهای دیگر را نمیشکند.
معماری ایدهآل انسجام بالا و وابستگی کم است. در عمل، این بدان معناست: یک کلاس شامل متدهایی است که روی دادههای مشابه کار میکنند (انسجام) و فقط به انتزاعات وابسته است، نه به پیادهسازیهای عینی (وابستگی). عدم تعادل منجر به «اشیاء خدا» (God Object) یا «کد اسپاگتی» میشود.
بدهی فنی (Technical Debt) — استعارهای که توسط وارد کانینگهام معرفی شد و «بهرهای» را توصیف میکند که یک تیم برای تصمیمات معماری غیربهینه و نقض اصول معماری میپردازد. مانند بدهی مالی، بدهی فنی میتواند عمدی (تصمیم گرفتیم سریع انجام دهیم، بعداً دوباره انجام میدهیم) و غیرعمدی (معماری بد به دلیل کمبود تجربه) باشد.
Code Smell — نشانههای سطحی از مشکلات عمیق در کد. این اصطلاح توسط مارتین فاولر در کتاب «Refactoring» رایج شد. Code Smellهای معمولی: متدهای طولانی، کلاسهای بزرگ، زنجیرههای فراخوانی طولانی، تکرار کد، استفاده بیش از حد از کامنتها (به جای کد واضح).
در IT Sectr، بدهی فنی در Jira به عنوان وظایف جداگانه پیگیری میشود. هر اسپرینت، ما 20٪ از زمان را به بازسازی و پرداخت بدهی اختصاص میدهیم. کار سیستماتیک با بدهی فنی تنها راه اجتناب از وضعیتی است که افزودن یک ویژگی جدید بیشتر از توسعه آن از ابتدا زمان میبرد.
سوالات متداول
Single Responsibility Principle (SRP) — مهمترین است، زیرا نقض آن به طور خودکار به نقض سایر اصول منجر میشود. کلاسی با چندین مسئولیت تست، گسترش و نگهداری آن دشوار است. با SRP شروع کنید — بقیه به دنبال آن خواهند آمد.
Cohesion (انسجام) — ارتباط درون یک ماژول (هر چه بالاتر، بهتر). Coupling (وابستگی) — ارتباط بین ماژولها (هر چه کمتر، بهتر). معماری خوب به دنبال انسجام بالا و وابستگی کم است.
خیر، اصول راهنما هستند، نه قوانین مطلق. در پروژههای کوچک یا نمونههای اولیه، پیروی بیش از حد از SOLID میتواند به مهندسی بیش از حد منجر شود. مهم است تعادلی بین معماری «به اندازه کافی خوب» و سرعت توسعه پیدا کنید.
از تحلیلگرهای ایستا (SonarQube, Detekt, ESLint)، بازبینی کد و معیارهای کد استفاده کنید. نشانههای بدهی: کد به سختی تست میشود، تغییرات در یک مکان مکان دیگر را میشکند، زمان افزودن یک ویژگی جدید از اسپرینتی به اسپرینت دیگر افزایش مییابد. بازسازی (refactoring) منظم تنها راه کنترل بدهی است.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.