🔍 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

Your build is currently configured to use incompatible Java 21.0.3 and Gradle 8.2.1. Cannot sync the project.

Error in Android Migration Gradle 7.5 to 8.5 - java.lang.NullPointerException: Cannot invoke "String.length()" because "" is null

Setting Up Jenkins for Flutter App on macOS