MyFamilyTracker
Real-time family location sharing — Firebase Realtime DB for sub-second propagation, WorkManager + ForegroundService for OS-compliant background collection, geofencing via Google Maps API.
Clean Architecture is the default recommendation for Android. It's also frequently over-applied. Here's an honest take on when it earns its complexity and when it doesn't.
On this page
Clean Architecture is everywhere in Android. Every tutorial, every sample project, every job posting lists it as a requirement. It's also one of the most over-applied patterns in the ecosystem. Here's an honest breakdown.
It separates concerns into three layers:
The rule: inner layers don't know about outer layers. Domain doesn't import from Data. Presentation doesn't know about Data Sources.
The benefit is testability and replaceability. You can test domain logic without Android infrastructure. You can swap a Retrofit data source for a Room cache without touching the ViewModel.
Apps with complex business logic. If your ViewModel is doing significant data transformation, combining multiple sources, applying rules, or making decisions — a Use Case layer makes that logic testable and clear.
Apps with multiple data sources. Local cache + remote API + real-time updates. A Repository that coordinates these is cleaner than doing it in the ViewModel.
Teams where multiple people touch the same codebase. Clear layer boundaries reduce merge conflicts and make it obvious where new code belongs.
Long-lived apps. After two years of development, a ViewModel that directly calls a Retrofit service is harder to change than one that calls a Repository.
Simple CRUD apps. A screen that shows a list from an API and lets you delete items doesn't need a Use Case. The ViewModel calling the Repository directly is fine. Adding
GetItemsUseCaseSolo projects with tight timelines. Every layer is more files, more interfaces, more boilerplate. For an MVP or experiment, this overhead slows you down.
When the "domain model" is identical to the "data model." If your domain User looks exactly like your API User which looks exactly like your Room User — you're just copying data classes between layers for correctness theater.
For most Android apps, a practical approach:
Always use a Repository. Even for simple apps. It's a single interface between your data sources and the rest of the app. Low overhead, high payoff.
Add Use Cases only when they earn it. If a Use Case contains real logic — transformation, validation, combining sources — it belongs. If it's a one-liner that delegates to a Repository, delete it.
Keep the domain model separate only if you need it. If your API model and UI model are different shapes, a domain model that bridges them is useful. If they're the same, you're adding a mapping step that adds no value.
"If I remove this layer, what breaks?"
If the answer is "nothing, the ViewModel just calls the Repository directly" — the layer isn't earning its place.
If the answer is "the business logic is now scattered across the ViewModel" — the layer is doing real work.
Architecture should reflect the actual complexity of your problem, not an idealized version of what the problem could theoretically become.
After building 22+ apps: I always use Repositories. I add Use Cases when the ViewModel logic gets complicated. I add domain models when the API and UI shapes are genuinely different. Everything else is optional until it's needed.
Sudarshan Chaudhari
AI Systems Builder / Product Engineer
Bangkok, Thailand
Solo Android developer with 13+ years in QA, building Android apps, AI automation systems, and developer tools at SudarshanTechLabs.
Related Posts
Related Apps
Real-time family location sharing — Firebase Realtime DB for sub-second propagation, WorkManager + ForegroundService for OS-compliant background collection, geofencing via Google Maps API.
Building something? Available for Android dev and QA consulting.
Work with meComments — powered by Giscus
Real-time family location sharing — Firebase Realtime DB for sub-second propagation, WorkManager + ForegroundService for OS-compliant background collection, geofencing via Google Maps API.
ReadPrivate dream journal — structured entry capture, pattern tagging, and optional Claude-powered insight generation. All data stays on-device by default.
ReadWorkout tracker — exercise logging with set/rep/weight history, goal progression, and local Room DB persistence. No account, no cloud sync required.
Read