Clean Architecture — بنیادی باتیں، Entities، Use Cases اور Gateways کی پرتیں

مصنف: IT Sectr اشاعت: 2026-02-17 مطالعے کا وقت: 10 منٹ

Clean Architecture — رابرٹ مارٹن (انکل باب) نے 2012 میں تجویز کردہ ایک کثیر الطبقاتی فن تعمیر، جو ایپلیکیشن کو آزاد پرتوں میں تقسیم کرتا ہے: Domain (Entities، Use Cases)، Data (Repositories، DataSources) اور Presentation (ViewModels، Views)۔ بنیادی اصول انحصار کا قاعدہ (Dependency Rule) ہے: انحصار اندر کی طرف اشارہ کرتے ہیں، بیرونی پرتیں اندرونی پرتوں پر منحصر ہوتی ہیں، لیکن اس کے برعکس نہیں۔ Clean Architecture موبائل ڈویلپمنٹ میں اعلیٰ کاروباری منطق کی پیچیدگی والے منصوبوں کے لیے استعمال ہوتی ہے۔ مزید تفصیلات کتاب The Clean Architecture میں دیکھیں۔

اہم نکات

  • Clean Architecture — تین پرتیں: Domain (کاروباری منطق)، Data (ڈیٹا)، Presentation (UI) انحصار کے قاعدے کے ساتھ
  • انحصار کا قاعدہ — انحصار اندر کی طرف اشارہ کرتے ہیں، Domain Data اور Presentation کے بارے میں نہیں جانتا
  • استعمال کے معاملات (انٹریکٹرز) — کاروباری منطق کے منظرنامے، ہر Use Case ایک کلاس ہے جس کا ایک طریقہ ہے
  • Repository Interface — Domain میں ڈیٹا کا تجرید، نفاذ Data پرت میں
  • جانچ پڑتال کی اہلیت — Domain اور Use Cases کو Android SDK اور iOS UIKit کے بغیر یونٹ ٹیسٹ سے جانچا جاتا ہے

Clean Architecture — کثیر الطبقاتی فن تعمیر کے بنیادی اصول

Clean Architecture — رابرٹ مارٹن (انکل باب) نے 2012 میں وضع کردہ ایک آرکیٹیکچرل پیٹرن۔ بنیادی خیال سخت انحصار کے قاعدے کے ساتھ ایپلیکیشن کو پرتوں میں تقسیم کرنا ہے: پرت کے اندر کا کوڈ باہر کے کوڈ کے بارے میں نہیں جانتا۔ بیرونی پرتیں (UI، فریم ورک، DB) نفاذ کی تفصیلات ہیں۔ اندرونی پرتیں (کاروباری منطق، کاروباری اصول) ایپلیکیشن کا جوہر ہیں۔

موبائل ڈویلپمنٹ میں Clean Architecture کی پرتیں: 1) Domain — Entities (کاروباری اشیاء) اور Use Cases (استعمال کے منظرنامے)؛ 2) Data — RepositoryImpl (ذخیرہ گاہوں کا نفاذ)، DataSources (نیٹ ورک، DB، کیش)؛ 3) Presentation — ViewModels، Views (Compose/SwiftUI)۔ Domain سب سے اندرونی پرت ہے جس کا کوئی انحصار نہیں ہے۔ Data Domain پر منحصر ہے (ذخیرہ گاہ کے انٹرفیس کو نافذ کرتا ہے)۔ Presentation Domain پر منحصر ہے (Use Cases کو کال کرتا ہے، نتائج کو سبسکرائب کرتا ہے)۔

پرتشامل ہےانحصار
DomainEntities، Use Cases، Repository Interfacesکوئی نہیں (خالص Kotlin/Swift)
DataRepositoryImpl، DataSources (API، DB، کیش)Domain، Retrofit، Room، Ktor
PresentationViewModels، Views، ComposablesDomain، Jetpack، SwiftUI

انحصار کا قاعدہ — Clean Architecture کا واحد سخت قاعدہ۔ سورس کوڈ صرف اپنے اندر کی پرت یا نیچے کی پرت (مرکز کے قریب) کا حوالہ دے سکتا ہے۔ Presentation Domain کو درآمد کرتا ہے۔ Domain Data یا Presentation کو درآمد نہیں کرتا۔ یہ انحصار الٹنے کے اصول (Dependency Inversion Principle) کے ذریعے حاصل کیا جاتا ہے: Domain Repository انٹرفیس کی وضاحت کرتا ہے، Data اسے نافذ کرتا ہے۔ Presentation کسی مخصوص ذخیرہ گاہ پر نہیں بلکہ UseCase کے تجرید پر منحصر ہے۔

Domain پرت: Entities، Use Cases اور Repository Interfaces

Domain — ایپلیکیشن کی سب سے مستحکم پرت۔ Entities فریم ورک سے آزاد کاروباری اشیاء ہیں: User، Product، Order۔ Use Cases ایک واحد invoke طریقہ (یا Kotlin میں operator fun invoke) والی کلاسیں ہیں، جو ایک منظر نامہ نافذ کرتی ہیں: GetUserUseCase، PlaceOrderUseCase، CalculateTotalUseCase۔ Repository Interfaces Domain میں بیان کردہ ڈیٹا تک رسائی کے تجرید ہیں، جو Data میں نافذ کیے گئے ہیں۔ Domain میں Android SDK، iOS UIKit، Retrofit، Room شامل نہیں ہے — صرف خالص Kotlin یا Swift۔

swift
// Entity — کاروباری شے (Domain)
struct User: Equatable {
    let id: Int
    let name: String
    let email: String
}

// Repository Interface — ڈیٹا کا تجرید (Domain)
protocol UserRepository {
    func getUser(id: Int) async throws -> User
    func getUsers() async throws -> [User]
}

// Use Case — ایک منظر نامہ (Domain)
final class GetUserUseCase {
    private let repository: UserRepository

    init(repository: UserRepository) {
        self.repository = repository
    }

    func execute(id: Int) async throws -> User {
        return try await repository.getUser(id: id)
    }
}

Use Case — «ایک طریقہ والی کلاس» کوئی عقیدہ نہیں بلکہ ایک عملی سفارش ہے۔ جب Use Case زیادہ پیچیدہ ہو جاتا ہے (تصدیق + لاگنگ + ذخیرہ گاہ کال)، تو اس کے طریقوں کو معنی کے مطابق گروپ کیا جاتا ہے: UserUseCase.getUser، UserUseCase.searchUsers، UserUseCase.deleteUser۔ اہم بات یہ ہے کہ Use Case کو یہ نہیں جاننا چاہیے کہ ڈیٹا کہاں سے آتا ہے (نیٹ ورک، DB، کیش) یا کون اسے ظاہر کرتا ہے (Compose، SwiftUI)۔ IT Sectr میں ہم ہر اس آپریشن کے لیے Use Case مختص کرتے ہیں جس میں کاروباری اصول، تصدیق یا دو ذرائع سے ڈیٹا کا امتزاج ہو۔

Domain کی پاکیزگی پرت کی حدود میں DTO میپنگ کے ذریعے حاصل کی جاتی ہے۔ Data پرت JSON ماڈل (DTO) وصول کرتی ہے، انہیں Domain Entity میں میپ کرتی ہے۔ Presentation Domain Entity وصول کرتا ہے، ViewModel (DisplayItem) میں میپ کرتا ہے۔ Domain Entity میں کبھی بھی Retrofit، Room یا Codable کے نوٹیشن شامل نہیں ہوتے — یہ ضمانت دیتا ہے کہ DB کو Room سے Realm میں تبدیل کرنے یا Retrofit کو Ktor سے تبدیل کرنے پر پرت کو تبدیل کرنے کی ضرورت نہیں ہوگی۔

Data پرت: Repository کا نفاذ اور DataSources

Data پرت — Domain میں بیان کردہ انٹرفیس کا نفاذ۔ اس میں RepositoryImpl (UserRepository کو نافذ کرنے والی کلاسیں) اور DataSources (RemoteDataSource — API، LocalDataSource — DB، CacheDataSource — SharedPreferences/NSUserDefaults) شامل ہیں۔ Data پرت Domain (ذخیرہ گاہ کے انٹرفیس اور Entities درآمد کرتی ہے) اور فریم ورک (Retrofit، Room، Ktor، CoreData) پر منحصر ہے۔ RepositoryImpl Domain سے ڈیٹا کا ذریعہ چھپاتا ہے — Use Case نہیں جانتا کہ ڈیٹا نیٹ ورک سے آیا یا کیش سے۔

kotlin
// DTO — نیٹ ورک کے لیے ماڈل (Data)
data class UserDto(
    @SerializedName("id") val id: Int,
    @SerializedName("first_name") val firstName: String,
    @SerializedName("last_name") val lastName: String,
    @SerializedName("email") val email: String
)

// RepositoryImpl — نفاذ (Data)
class UserRepositoryImpl(
    private val remoteDataSource: UserRemoteDataSource,
    private val localDataSource: UserLocalDataSource
) : UserRepository {

    override suspend fun getUser(id: Int): User {
        // کیش سے حاصل کرنے کی کوشش
        localDataSource.getUser(id)?.let { return it.toDomain() }
        // اگر نہ ہو — نیٹ ورک سے لوڈ کریں
        val dto = remoteDataSource.fetchUser(id)
        val user = dto.toDomain()
        localDataSource.saveUser(user)
        return user
    }

    override suspend fun getUsers(): List<User> {
        return remoteDataSource.fetchAllUsers().map { it.toDomain() }
    }
}

// Mapper — DTO ↔ Domain تبدیلی
fun UserDto.toDomain() = User(
    id = id,
    name = "$firstName $lastName",
    email = email
)

Data پرت میں کیشنگ کی حکمت عملی: RepositoryImpl پہلے مقامی ذخیرہ کو چیک کرتا ہے؛ اگر ڈیٹا نہ ملے تو نیٹ ورک سے لوڈ کرتا ہے اور مقامی طور پر محفوظ کرتا ہے۔ اگر نیٹ ورک دستیاب نہ ہو تو isStale پرچم کے ساتھ پرانا ڈیٹا لوٹاتا ہے۔ Domain میں Use Case حکمت عملی کے بارے میں نہیں جانتا — یہ Repository.getUser(id) کے ذریعے User وصول کرتا ہے۔ حکمت عملی تبدیل کرنا (مثلاً، ہر 15 منٹ میں کیش کو باطل کرنا) Domain اور Presentation کو متاثر نہیں کرتا۔

Android میں ماڈیولریٹی — Kotlin Multiplatform Android SDK کے انحصار کے بغیر Domain کو علیحدہ KMP ماڈیول میں نکالنے کی اجازت دیتا ہے۔ Data Domain پر انحصار کے ساتھ ایک علیحدہ ماڈیول ہے۔ Presentation Domain پر انحصار کے ساتھ ایک Android ماڈیول ہے۔ Gradle انحصار: domain (خالص Kotlin)، data (domain + Retrofit + Room)، app (domain + presentation + Hilt)۔ بڑے منصوبوں کے لیے اس طرح کی ماڈیولریٹی ضروری ہے — CI Domain کو علیحدہ بناتا ہے، Domain یونٹ ٹیسٹ کے لیے Android ایمولیٹر کی ضرورت نہیں ہوتی۔

Presentation پرت: ViewModels اور Views

Presentation پرت — Clean Architecture کی سب سے بیرونی پرت۔ اس میں ViewModels (Android) / ObservableObject (iOS) اور Views (Compose/SwiftUI) شامل ہیں۔ ViewModel Use Case کو کال کرتا ہے، نتیجہ وصول کرتا ہے اور UI حالت میں تبدیل کرتا ہے۔ View حالت کو سبسکرائب کرتا ہے اور پیش کرتا ہے۔ Presentation Domain پر منحصر ہے — Use Cases اور Entities درآمد کرتا ہے۔ Presentation Data Layer درآمد نہیں کرتا — ڈیٹا Use Case کے ذریعے آتا ہے، جو اندرونی طور پر Repository استعمال کرتا ہے۔

Clean Architecture میں ViewModel میں کاروباری منطق شامل نہیں ہے — یہ Use Case کو کال کرتا ہے۔ اگر Use Case User لوٹاتا ہے، تو ViewModel اسے UserDisplayItem (name، emailFormatted، avatarUrl) — خالص پیشکشی ماڈل میں تبدیل کرتا ہے۔ Use Case DisplayItem کے بارے میں نہیں جانتا — یہ Entity لوٹاتا ہے۔ یہ علیحدگی UI کے بغیر Use Case اور UseCase کے بغیر ViewModel (ماک کے ذریعے) کی جانچ کی اجازت دیتی ہے۔ IT Sectr میں ہم سختی سے پیروی کرتے ہیں: Use Case — کاروباری منطق، ViewModel — صرف پیشکش، View — صرف نمائش۔

kotlin
// Use Case (Domain) — خالص کاروباری منطق
class GetUserUseCase(
    private val repository: UserRepository
) {
    suspend operator fun invoke(id: Int): User {
        return repository.getUser(id)
    }
}

// ViewModel (Presentation) — صرف پیشکش
class UserViewModel(
    private val getUserUseCase: GetUserUseCase
) : ViewModel() {

    private val _state = MutableStateFlow<UserScreenState>(UserScreenState.Loading)
    val state: StateFlow<UserScreenState> = _state.asStateFlow()

    fun loadUser(id: Int) {
        viewModelScope.launch {
            _state.value = UserScreenState.Loading
            val user = getUserUseCase(id)
            val displayItem = UserDisplayItem(
                name = user.name,
                email = user.email,
                initials = user.name.split(" ").joinToString("") { it.first().toString() }
            )
            _state.value = UserScreenState.Success(displayItem)
        }
    }
}

data class UserDisplayItem(
    val name: String,
    val email: String,
    val initials: String
)

sealed interface UserScreenState {
    data object Loading : UserScreenState
    data class Success(val displayItem: UserDisplayItem) : UserScreenState
    data class Error(val message: String) : UserScreenState
}

نیویگیشن Presentation پرت میں بھی بیرونی حلقے کا حصہ ہے۔ Clean Architecture کوئی نیویگیشن میکانزم مقرر نہیں کرتی — یہ NavController (Compose)، NavigationStack (SwiftUI)، Coordinator (UIKit) یا Router (VIPER) ہو سکتا ہے۔ اہم بات یہ ہے کہ نیویگیشن کے فیصلے Presentation کرتا ہے، لیکن نیویگیشن کو Use Case میں داخل نہیں ہونا چاہیے۔ Use Case نتیجہ لوٹاتا ہے، ViewModel فیصلہ کرتا ہے کہ کس اسکرین پر جانا ہے۔ Clean Architecture میں، نیویگیشن ایک تفصیل ہے جسے Domain تبدیل کیے بغیر تبدیل کیا جا سکتا ہے۔

iOS اور Android پر Clean Architecture: کوڈ کی مثالیں

Android پر Clean Architecture Gradle ماڈیولز کے ذریعے نافذ کی جاتی ہے: domain (خالص Kotlin)، data (domain + Retrofit + Room)، presentation (domain + Compose)۔ فولڈر کا ڈھانچہ: domain/user/User.kt، GetUserUseCase.kt، UserRepository.kt؛ data/remote/UserRemoteDataSource.kt، local/UserDao.kt، repository/UserRepositoryImpl.kt؛ presentation/ui/user/UserViewModel.kt، UserScreen.kt۔ DI (Hilt) پرتوں کو جوڑتا ہے: UserRepositoryImpl domain ماڈیول میں UserRepository انٹرفیس سے منسلک ہوتا ہے۔

iOS پر Clean Architecture Xcode کی حدود کی وجہ سے علیحدہ ماڈیولز کے بغیر SPM یا Xcode گروپس استعمال کرتی ہے۔ Domain — ایک فولڈر جس میں فائلیں UIKit یا SwiftUI درآمد نہیں کرتیں۔ Data — APIClient، CoreDataStack، RepositoryImpl والا فولڈر۔ Presentation — ViewModels اور SwiftUI Views والا فولڈر۔ DI کنسٹرکٹر یا ایپ میں اسمبلی کے ذریعے۔ اہم کال UI اپ ڈیٹس کے لیے MainActor چیک کے ساتھ UseCase.execute() کے ذریعے async/await ہے۔

swift
// Data Layer: Remote DataSource (iOS)
final class UserRemoteDataSource {
    private let apiClient: APIClient

    func fetchUser(id: Int) async throws -> UserDTO {
        return try await apiClient.get("/users/\(id)")
    }
}

// Repository Implementation (Data)
final class UserRepositoryImpl: UserRepository {
    private let remote: UserRemoteDataSource
    private let local: UserLocalDataSource

    func getUser(id: Int) async throws -> User {
        if let cached = try await local.getUser(id) {
            return cached
        }
        let dto = try await remote.fetchUser(id)
        let user = dto.toDomain()
        try await local.saveUser(user)
        return user
    }
}

// Presentation: ViewModel + SwiftUI View
@MainActor
final class UserViewModel: ObservableObject {
    @Published private(set) var state: UserScreenState = .loading
    private let getUserUseCase: GetUserUseCase

    func loadUser(id: Int) {
        Task {
            state = .loading
            if let user = try? await getUserUseCase.execute(id: id) {
                state = .success(user)
            } else {
                state = .error("Failed to load")
            }
        }
    }
}

IT Sectr منصوبوں میں Clean Architecture — 30 دن سے منصوبوں کے لیے ہمارا معیار۔ ہم 2022 سے Android/iOS کے لیے Kotlin Multiplatform کے ساتھ تین پرتوں والے فن تعمیر کا استعمال کر رہے ہیں۔ Domain — ایک مشترکہ KMP ماڈیول، Data — پلیٹ فارم ماڈیول (Android پر Retrofit، iOS پر URLSession)، Presentation — مقامی UI۔ یہ iOS اور Android کے درمیان 60–80% مشترکہ کاروباری منطق کوڈ فراہم کرتا ہے، جو دو علیحدہ نفاذ کے مقابلے میں ترقی کے وقت کو 30–40% کم کرتا ہے۔

اکثر پوچھے گئے سوالات

Clean Architecture میں کتنی پرتیں ہونی چاہئیں؟

کم از کم تین: Domain، Data، Presentation۔ بڑے منصوبوں کے لیے Framework (Android SDK/iOS UIKit انحصار) اور Device (GPS، کیمرہ، سینسر) شامل کیے جاتے ہیں۔ پرتوں کی تعداد کوئی سخت قاعدہ نہیں بلکہ سہولت کا معاملہ ہے۔ اہم بات انحصار کے قاعدے پر عمل کرنا ہے: انحصار اندر کی طرف، Domain کی طرف جاتے ہیں۔ آپ تین سے شروع کر سکتے ہیں اور منصوبہ بڑھنے کے ساتھ پرتیں شامل کر سکتے ہیں۔

کیا Clean Architecture کوڈ کی مقدار بڑھاتی ہے؟

ہاں — ذخیرہ گاہ کے انٹرفیس، Use Cases اور میپرز کے نکالنے کی وجہ سے MVVM کے مقابلے میں 30–50% تک۔ ایک سادہ CRUD ایپلیکیشن کے لیے یہ ضرورت سے زیادہ ہے۔ Clean Architecture پیچیدہ کاروباری منطق والے منصوبوں کے لیے جائز ہے جہاں جانچ پڑتال کی اہلیت اور پرت کی علیحدگی ترقی کی رفتار سے زیادہ اہم ہے۔ MVP یا پروٹوٹائپ کے لیے MVVM استعمال کریں — Clean Architecture آغاز کو سست کر دے گی۔

کیا Clean Architecture کو MVI کے ساتھ ملایا جا سکتا ہے؟

ہاں، یہ عام رواج ہے۔ Use Cases Domain میں رہتے ہیں، جبکہ Presentation MVI سائیکل (Intent → Reducer → State) استعمال کرتا ہے۔ Data Layer وہی رہتا ہے، Domain وہی رہتا ہے۔ Presentation میں MVI پیشین گوئی کے قابل اسکرین اسٹیٹ فراہم کرتا ہے، Clean Architecture کاروباری منطق کی علیحدگی فراہم کرتا ہے۔ یہ امتزاج درجنوں ڈویلپرز والے بڑے منصوبوں میں استعمال ہوتا ہے۔

کیا ہر ڈیٹا کی درخواست کے لیے Use Cases کی ضرورت ہے؟

Use Case کی ضرورت ہے جب آپریشن میں کاروباری اصول شامل ہو: تصدیق، دو ذرائع سے ڈیٹا کا امتزاج، حساب، لاگنگ، رسائی کی اجازت کی جانچ۔ اضافی منطق کے بغیر ایک سادہ getUser(id) درخواست براہ راست ViewModel سے Repository کو کال کر سکتی ہے۔ تاہم، آرکیٹیکچرل مستقل مزاجی کے لیے، بہت سی ٹیمیں Repository کے ہر عوامی طریقہ کے لیے Use Case بناتی ہیں — اس سے 5–10% کوڈ بڑھتا ہے لیکن پڑھنا آسان ہو جاتا ہے۔

Clean Architecture کی جانچ کیسے کریں؟

Domain: ماک Repository کے ساتھ Use Cases کے یونٹ ٹیسٹ — Android SDK کے بغیر خالص Kotlin/Swift۔ Data: ماک/جعلی DataSource کے ساتھ RepositoryImpl کے انٹیگریشن ٹیسٹ۔ Presentation: ماک UseCase کے ساتھ ViewModel ٹیسٹ۔ انحصار کے قاعدے کی بدولت، ہر پرت کو علیحدہ جانچا جاتا ہے۔ IT Sectr میں، Domain کوریج 95%، Data — 70–80%، Presentation — 60–70% تک پہنچتی ہے۔

خلاصہ

  • Clean Architecture — تین پرتیں (Domain، Data، Presentation) انحصار کے قاعدے کے ساتھ اندر کی طرف
  • انحصار کا قاعدہ — Domain Data اور Presentation کو نہیں جانتا، انٹرفیس کے ذریعے علیحدگی
  • Domain — Entities، Use Cases، Repository Interfaces — فریم ورک کے بغیر خالص Kotlin/Swift
  • Data — RepositoryImpl، DataSources (نیٹ ورک، DB، کیش) — Domain انٹرفیس کا نفاذ
  • Presentation — ViewModels، Views — صرف نمائش، کاروباری منطق Use Cases میں
  • جانچ — Domain یونٹ ٹیسٹ سے 90–95% کور ہوتا ہے
  • KMP — Kotlin Multiplatform کے ساتھ Clean Architecture 60–80% مشترکہ iOS + Android کوڈ دیتی ہے

ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے

IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔

پروجیکٹ پر بحث کریں

مزید پڑھیں