UseCase Best Practices in Kotlin

UseCase Best Practices in Kotlin (Clean Architecture Guide)
If you’re building Android or backend applications using Clean Architecture, you’ve probably heard about UseCases (also called Interactors).
UseCases are one of the most important parts of Clean Architecture. When implemented correctly, they:
Keep business logic clean
Improve testability
Reduce coupling
Make code easier to maintain
Improve scalability
In this beginner-friendly guide, you’ll learn:
What a UseCase is in Kotlin
Why UseCases are important
Where UseCases fit in Clean Architecture
Best practices for writing UseCases
Common mistakes
Real-world examples
Testing strategies
Let’s get started
What Is a UseCase in Clean Architecture?
A UseCase represents a single piece of business logic in your application.
Think of it as:
One action your application can perform.
Examples:
LoginUserUseCase
GetUserProfileUseCase
AddToCartUseCase
SubmitOrderUseCase
Each UseCase should have one clear responsibility.
Where Do UseCases Fit in Clean Architecture?
In Clean Architecture, UseCases belong to the Domain Layer.
Typical structure:
The dependency rule says:
Presentation depends on Domain
Data depends on Domain
Domain depends on nothing
UseCases should not depend on Android, Retrofit, Room, or any framework.
Basic Example of a UseCase
The UseCase:
Calls repository
Applies business rules
Returns domain model
It contains no UI code.
Why UseCases Are Important
Without UseCases, developers often:
Put business logic inside ViewModel
Mix UI and domain logic
Create tightly coupled code
UseCases solve this by:
- Separating concerns
- Improving testability
- Encouraging single responsibility
- Making code reusable
UseCase Best Practices (Step-by-Step)
Let’s explore the most important best practices.
One UseCase = One Responsibility
Each UseCase should do only one thing.
Bad Example:
Too many responsibilities.
Good Example:
Each class handles one action.
Keep UseCases Framework-Free
UseCases should NOT import:
Android classes
ViewModel
Context
Retrofit
Room
Avoid this:
Domain layer must remain pure Kotlin.
Inject Repository Interfaces, Not Implementations
UseCases depend on interfaces.
Inject implementation from data layer.
This follows Dependency Inversion Principle.
Use Operator Function for Clean Syntax
Kotlin allows using operator fun invoke().
Instead of:
Use:
Example:
Cleaner and more idiomatic Kotlin.
Handle Errors Inside UseCase
Business-level errors should be handled in UseCase.
Example:
Do not let UI handle business logic errors.
Keep UseCases Small and Focused
A UseCase should be short and readable.
If it grows too large:
Split it
Extract helper classes
Clean code is maintainable code.
Use Data Models from Domain Layer
Avoid passing API models to UseCases.
Bad:
Good:
Domain models should be independent.
Make UseCases Easy to Test
UseCases should be:
Simple
Independent
Easy to mock dependencies
Example test:
No Android dependencies needed.
Real-World Example – Login Flow
UseCase:
ViewModel:
Business validation stays inside UseCase.
Common Beginner Mistakes
Putting Business Logic in ViewModel
Move it to UseCase.
Creating Too Many Dependencies
Keep UseCase lightweight.
Combining Multiple Responsibilities
One UseCase, one action.
Using Android Context in Domain Layer
Never import Android in domain.
UseCase vs Repository
| Feature | UseCase | Repository |
|---|---|---|
| Contains business rules | Yes | No |
| Handles data source | No | Yes |
| Calls API/Database | No | Yes |
| Used by ViewModel | Yes | No |
UseCase orchestrates. Repository fetches data.
Naming Conventions for UseCases
Follow consistent naming:
Verb + Entity + UseCase
LoginUserUseCase
GetProductListUseCase
UpdateProfileUseCase
Avoid generic names like:
Manager
Handler
Processor
Be explicit.
Advanced UseCase Patterns
UseCase with Parameters Data Class
Improves scalability.
When Should You Use UseCases?
Use UseCases when:
Following Clean Architecture
Working on medium/large apps
Needing testable business logic
Working in teams
Avoid unnecessary complexity for tiny apps.
Frequently Asked Questions (FAQs)
1. What is a UseCase in Clean Architecture?
A UseCase represents a single piece of business logic in the domain layer.
2. Should UseCases contain Android code?
No, UseCases must remain framework-independent.
3. Why use operator invoke in UseCase?
It improves readability and provides cleaner syntax.
4. How many responsibilities should a UseCase have?
Only one responsibility.
5. Are UseCases mandatory in small projects?
Not mandatory, but recommended for scalability.
Conclusion
UseCases are the backbone of Clean Architecture in Kotlin.
You learned:
What UseCases are
Where they belong
Best practices
Common mistakes
Testing strategies
Mastering UseCase design will make your applications cleaner, more testable, and scalable.
