πŸ” What is Tight Coupling and Loose Coupling? (Android Developer Explanation)

✅ Tight Coupling

Two classes/components are tightly coupled when they depend on each other directly.
If one changes, the other must also change.
It reduces flexibility and reusability.

πŸ“Œ Example (Bad Practice – Tight Coupling)

class UserRepository {
    fun getUser() = "Android Developer"
}

class UserViewModel {
    private val repository = UserRepository() // Direct object creation → TIGHT COUPLING

    fun printUser() {
        println(repository.getUser())
    }
}

πŸ”΄ Problems:

  • UserViewModel cannot work without UserRepository

  • Hard to unit test (cannot inject mock repo)

  • If repository changes, viewmodel breaks

  • Not reusable


Loose Coupling

Two classes are loosely coupled when they depend on abstractions (interfaces) instead of concrete classes.
You can replace dependency without modifying main logic → more flexible.

πŸ“Œ Example (Good Practice – Loose Coupling with DI)

interface UserRepository {
    fun getUser(): String
}

class UserRepositoryImpl : UserRepository {
    override fun getUser() = "Android Developer"
}

class UserViewModel(private val repository: UserRepository) {
    fun printUser() {
        println(repository.getUser())
    }
}

✅ Benefits:

  • You inject dependency, not create it

  • Easier unit testing (can pass fake/mock repo)

  • Supports dependency injection (Hilt, Koin, Dagger)

  • Better for Clean Architecture

Unit Test Example:

class FakeRepo : UserRepository {
    override fun getUser() = "Test User"
}

val viewModel = UserViewModel(FakeRepo())

πŸ” Comparison Table

Feature Tight Coupling Loose Coupling
Flexibility ❌ Low ✅ High
Testability ❌ Hard ✅ Easy
Uses interface? ❌ No ✅ Yes
Dependency created inside class? ✅ Yes ❌ No (Injected)
Works well with DI (Hilt/Koin)? ❌ No ✅ Yes

πŸ— Real Android Example of Loose Coupling (Hilt)

@Module
@InstallIn(SingletonComponent::class)
object AppModule {
    @Provides
    fun provideUserRepo(): UserRepository = UserRepositoryImpl()
}

@HiltViewModel
class UserViewModel @Inject constructor(
    private val repository: UserRepository
) : ViewModel() {
    fun getUserName() = repository.getUser()
}

✅ ViewModel doesn’t know which implementation is injected
✅ Can switch to MockUserRepo() easily for testing
✅ Architecture-friendly


πŸ’‘ Simple Definition for Interview

Tight coupling = classes depend directly on each other
Loose coupling = classes communicate through interfaces or injected dependencies



Comments

Popular posts from this blog

SwiftUI - Tutorial 2 - 🧡 Understanding @MainActor in SwiftUI — A Beginner’s Guide

SonarQube With Angular 19 on Windows: A Complete Setup and Integration Guide

Setting Up Jenkins for Flutter App on macOS