What? One another architecture pattern for Android? Yup. Make way for Clean Architecture (don’t worry – MVVM isn’t obsolete).
Just over a year ago, I learned the MVVM Architecture and thought that I am doing good with Android development. The code looked organized and the debate seemed to have settled. I got a hang of the MVVM architecture and its layers such that I would not breach the thumb rules and the separation of concern would happen when adding a new feature or refactoring the code. But suddenly, after some architecture meets within the organization, the code didn’t look much organized. When we analyzed and went over the classes, the ViewModels looked bloated with lots of logic in them. So naturally, we decided to make our lives hell for the next couple of months or so. We explored the different architectural patterns and did our research on the – ‘Clean Architecture’.
Clean Architecture did look organized. But at that moment, I wanted to find flaws in it when compared with the MVVM architecture so that we can hold onto our current codebase of flawed-but-working MVVM architecture. Soon I calmed down and thought professionally :p. The curiosity to learn something new and complex took over so I started taking interest in it. And for the benefit of the larger team, I wanted to contribute towards laying down the first of the features in Clean Architecture so other teams could follow. I hope this would’ve been a satisfactory explanation as to why I moved from MVVM Architecture to adopting Clean Architecture. TL;DR; Clean Architecture is the way to go when building large-scale, enterprise-level applications. MVVM works well for small-scale applications as Clean Architecture would be an overkill in that scenario.
Let’s begin!
Clean Architecture
If you are coming here with the knowledge of MVVM Architecture, then you have a benefit. Clean Architecture is more like an extension and fine-grained implementation of MVVM with the addition of a ‘UseCase’ layer. There are some more changes to prevent inverse dependency across the layers and to make it more loosely coupled, which eventually helps in developing & testing the modules independently. If you do not know about MVVM architecture, I would recommend you to understand MVVM before diving into Clean Architecture. I wrote a few articles in Java & Kotlin on MVVM architecture and MindOrks has a detailed explanation of the architecture here.
Theory
I will take the freedom to expand on the lines of the different layers and why it’s needed to get a better understanding. It’s always good to start slow when learning a new architecture.
In Clean architecture, we will have three layers – presentation, domain, and data layer.
Anything and everything related to view and user interaction will lie in the presentation layer (i.e. Views, ViewModels, Livedatas, UI state models, etc.).
Business logic and the abstract layer to access the data will be a part of the domain layer (i.e. use cases, managers – implementation details, models, repository interfaces, etc.).
Anything to do with data – accessing remote, local, in-memory data will happen in the data layer. It will provide the implementation of the interface defined in the domain layer.
Further to this, we will not share model classes across the different layers. Each layer will have its own model and we would implement mappers to convert the x layer model class to y layer model class. This is mostly done in the presentation layer where we convert the domain model to the UI state model and in the domain layer where we convert the DB/API data model to the domain model.
By this, we will separate out the androidx.* (I hope everyone here has already migrated to androidX by now) and it’ll be present only in the presentation layer.
Our ViewModels will now be lightweight and will have only the logic necessary for the UI. It will handle the button click or any observables to be updated for the UI through a live data trigger from the backend (domain layer). Further, we will have only one VM per View. The VMs will no longer have the business logic or access the repository directly. It’s now abstracted.
The VMs can use the Usecase Factory which provides access to the specific usecases. The usecase can be fine-grained. It can have a method or two or in some cases 4-5 methods. It’s convenient to have more usecase classes than more methods in a single usecase as it makes the code more readable.
Some usecase will implement the business logic in it or in other cases, we will use managers to handle it. The manager resides in the domain layer and the usecase factory will provide a reference to it. The usecase can access the repository (data layer) through the repository interface in the domain layer.
Now it becomes quite clear that we do not jump over the layers and it’s always that a layer only accesses the layer below it. We will also prevent any inverse dependency case and not access any layer in the outwards direction. This diagrammatic representation will help you understand the flow of control –
Conclusion
I think I’ll end the first part of the Clean Architecture series here. Now that we have understood the theory aspect of it, it might actually be making sense to shift from MVVM architecture to Clean Architecture if you are working on an enterprise-level application. For small-scale applications, I still feel that MVVM architecture makes our codebase organized but the Clean Architecture would be an overkill for it.
While implementing Clean Architecture, there would be places where we’ll feel that we are going around a lot of layers to accomplish a simple task and that it’s overkill but in the end, it would make the codebase organized and very readable. This in turn will boost the productivity across the teams as they will be able to work independently on the modules and different layers.
In the next part, we will dive into code samples and better understand package structuring and practical working of the Clean Architecture.