Android Architecture: Part 3 – Applying clean architecture on Android

So far in this series, we’ve covered some beginner’s mistakes and gone through the clean architecture. In this last part, we will cover the last piece of the puzzle: labels, or more precisely, components.

First, I’ll remove the stuff we don’t use on Android projects and I’ll add some stuff that we do use but that isn’t found in the original Uncle Bob’s diagram. It looks like this:

I’ll go from the most abstract center to the edges.

Entities

Entities, aka domain objects or business objects, are the core of the app. They represent the main functionality of the app, and you should be able to tell what the app is about just by looking at them. They contain business logic, but it’s constrained to them only—validation and stuff like that. They don’t interact with the gritty outside-world details, and they also don’t handle persistence. If you had a news app, the entities would be Category, Article, and Commercial, for example.

Use cases

Use cases, aka interactors, aka business services, are an extension of the entities, an extension of the business logic, that is. They contain the logic that isn’t constrained only to one entity but handle more of them. An indicator of a good use case is that you can describe what it does in a simple sentence using common language—for example, “Transfer money from one account to another.” You can even use such nomenclature to name the class, e.g., TransferMoneyUseCase.

Repositories

Repositories serve to persist the entities. It’s as simple as that. They are defined as interfaces and serve as output ports for the use cases that want to perform CRUD operations on entities. Additionally, they can expose some more complex operations related to persistence such as filtering, aggregating, and so on. Concrete persistence strategies, e.g., database or the Internet, are implemented in the outer layers. You could name the interface AccountRepository, for instance.

Presenters

Presenters do what you would expect them to do if you are familiar with the MVP pattern. They handle user interactions, invoke appropriate business logic, and send the data to the UI for rendering. There is usually some mapping between various types of models here. Some would use controllers here, which is fine. The presenter we use is officially called the supervising controller. We usually define one or two presenters per screen, depending on the screen orientation, and our presenters’ lifecycles are tied to that of a view. One piece of advice: try to name your methods on a presenter to be technology agnostic. Pretend that you don’t know what technology the view is implemented in. So, if you have methods named onSubmitOrderButtonClicked and onUserListItemSelected in the view, the corresponding presenter methods that handle those events could be named submitOrder and selectUser.

Device

This component has already been teased before in the notifications (again) example. It contains the implementations of the gritty Android stuff such as sensors, alarms, notifications, players, all kinds of *Managers, and so on. It is a two-part component. The first part is the interfaces defined in the inner circles that business logic uses as the output port for communication with the outer world. The second part, and that’s drawn in the diagram, are implementations of those interfaces. So, you can define, for example, interfaces named Gyroscope, Alarm, Notifications, and Player. Notice that the names are abstract and technology agnostic. Business logic doesn’t care how the notification will be shown, how the player will play the sound, or where the gyroscope data comes from. You can make an implementation that writes the notifications to the terminal, write the sound data to the log, or gather the gyroscope data from the predefined file. Such implementations are useful for debugging or creating a deterministic environment for you to program in. But you will, of course, have to make implementations such as AndroidAlarm, NativePlayer, etc. In most cases, those implementations will just be wrappers around Android’s manager classes.

DB & API

No philosophy here. Put the implementations of repositories in this component. All the under-the-hood persistence stuff should be here: DAOs, ORM stuff, Retrofit (or something else) stuff, JSON parsing, etc. You can also implement a caching strategy here or simply use in-memory persistence until you are done with the rest of the app. We had an interesting discussion in the team recently. The question was this: Should the repository expose methods such as fetchUsersOffline (fetchUsersFromCache) and fetchUsersOnline (fetchUsersFromInternet)? In other words, should business logic know where the data comes from? Having read everything from this post, the answer is simple: no. But there is a catch. If the decision about the data source is part of the business logic—if the user can choose it, for example, or if you have an app with explicit offline mode—then you CAN add such a distinction. But I wouldn’t define two methods for every fetch. I would maybe expose methods such as enterOfflineMode and exitOfflineMode on the repository. Or if it applies to all the repositories, we could define an OfflineMode interface with enter and exit methods and use it on the business logic side, leaving repositories to query it for the mode and decide it internally.

UI

Even less philosophy here. Put everything related to the Android UI here. Activities, fragments, views, adapters, etc. Done.

Modules

The following diagram shows how have we divided all these components into Android Studio modules. You might find another division more appropriate.

graph-2

We group entities, use cases, repositories, and device interfaces into the domain module. If you want an extra challenge with a reward of eternal glory and a totally clean design, you can make that module a pure Java module. It will prevent you from taking shortcuts and putting something related to the Android here.

The device module should have everything related to Android that’s not data persistence and UI. The data module should hold everything related to data persistence, as we’ve already said. You cannot make those two into Java modules because they need access to various Android stuff. You can make them into Android library.

Finally, we group everything related to the UI (including presenters) into the UI module. You can explicitly name it UI but because of all the Android stuff here, we leave it named “app,” just as Android Studio named it during the creation of the project.

Is it better?

To answer that question, I’ll ditch Uncle Bob’s diagram and sprawl the components described before into a diagram like those we have used to rate previous types of architectures. After doing that, we get this:

graph-3

Now let’s apply the same criteria that we have used on previous architectures.

graph-4

It’s all neatly separated by module level, package level, and class level. So SRP should be satisfied.

graph-5

We have pushed Android and the real-world stuff as far out on the outskirts as we can. Business logic doesn’t touch the Android directly anymore.

graph-6

We have nicely separated classes that are easy to test. Classes touching the world can be tested using Android test cases; the one not touching it can be tested using JUnit. Someone malevolent would maybe call that class explosion. I call it testable. :)

graph-7

It may be complicated – but it’s worth it

I hope that my carefully chosen criteria, which was not made up just to favor the clean architecture, will convince you to give it a try. It seems complicated, and there are lots of details here, but it’s worth it. Once you wire it all up, testing is much easier, bugs are easier to isolate, new features are easy to add, code is more readable and maintainable, everything works perfectly, the universe is satisfied.

So, this is it. If you still haven’t done so, look at the previous articles in the series: Mistakes and Clean Architecture. If you have any comments or questions, leave feedback below. We are always interested in hearing what you think.

 

  • Pingback: Android Architecture: Part 2 - the clean architecture • Five()

  • Waleed sarwar

    I think i have read every blog related to Clean Architecture for Android on Internet.But So far this is one of best explanation of Clean Architecture in Android.

    • Tomo

      Thanks :)

  • Pingback: Swift Tutorial: An Introduction to the MVVM Design Pattern - Cible()

  • Pingback: Best Writing Service()

  • Patrick Egashira

    So far the best article i have read. Thank you for sharing! please keep writing.. i still havent found a better way for handling multiple views, for example an activity housing login and register fragments. i would appreciate a write up on this :)

    • Tomo

      Thank you very much :) Yes, activities, fragments, presenters and life-cycles. That’s a bit painful area :) We tried several approaches. The constant that remained the same is that we treat fragments as views, so presenters are tied to fragments. We treat activity just as a host for fragments. Currently the presenters are strongly coupled to fragments’ life-cycles, so when fragment goes to sleep, his presenter does so too, when fragment dies, we bury the presenter too. That introduces some problems when rotating the screen for example, because we cancel all the requests when rotating and reestablishing the connection again when showing rotated fragment. That’s good from the theoretical perspective, less side-effects, but users don’t actually care about side-effects :) But some of the guys in the team made some pretty nice RxJava sorcery that solved that problem and it behaves ok.

      • Suresh Joshi

        @disqus_6YW6LsKuLH:disqus Have you experimented at all with using MVVM instead of MVP for the UI layer? I’m more familiar with MVVM from my C# and Angular time – and I feel like it -could- work with all the data-binding we have access to now… Just haven’t tried it. Will be testing on an upcoming project.

        • Patrick Egashira

          Please let us know how the pieces fit in i could leverage my MVVM skills in this case too.

          • Tomo

            I’ve also tried MVVM with Xamarin and it works fine. I see no reason why it couldn’t be applied here. The roles are a bit reversed, data flows a bit differently, but the key is in both approaches imho to clearly hide the view behind the interface to be able to switch it and/or mock it. Both approaches work then. And that’s only UI layer, the rest of the layers are indifferent to you using MVVM, MVP, MVC , test environment, console, or PHP :) Kidding for last one, don’t go there :)

  • Pedro

    Nice overview on Clean. I think you nailed down its intent. Do you mind to explain how you handle models in this architecture? I’m interested to know if you have different models and mappers per layer.

    • Tomo

      Thanks. Yes, we have different models, but I didn’t want to make it even more complex here, it think it would draw attention from the more important stuff. I mentioned here only business models, or entities, but in reality we also have db models that ORM uses, and api models that Gson uses to fetch the data from the server. Because of that we also have DbMappers and APiMappers, that are usually very simple classes. If you are using Kotlin and / or RxJava, you can design mappers to use their map functions. Some methods become one liners in that a way.

      • Suresh Joshi

        For the mapper discussion, I can’t recall where I saw it, but I liked (but have never used) a pattern where there was a Mapper interface accepting templates – and at every level (data, domain, device, ui) there were a bunch of these mappers with 1-2 methods on them.

        Felt like overhead at the time, but then I realized I’m doing that already today in my designs – except instead of using a generic Mapper – I’m tightly coupling models via static methods or extensions.

        • Tomo

          We have an interface, but not so granular. Ours are a bit larger, have couple of methods. But yeah, this sounds good. If you saw that in some article feel free to post it.

  • narendra techguy

    Waiting for 4th part where i could see real code it would be better if you show it using some complex project that does not have simple usecases

    • Tomo

      The repo with real code is slowly loading :)

      • slickorange

        Great post!! Thank you for your effort and clear explanation – but I think it will only really set in if I can see an actual code base structured like this. Is there anywhere we can sign up to be notified when the real repo is ready?

        • Tomo

          Hmm, not sure actually :) There is some kind of subscribe button down on the bottom of the blog, but that might be only for Disqus. I guess you could follow our FB page, we announce new blog posts there, so once we announce it it will pop on your wall eventually, but that’s on the other hand maybe too assertive :) Or some good soul could take a couple of minutes and throw a comment with tags in this thread once it’s out…

          • slickorange

            Thanks! I have liked the Facebook page – will keep an eye on it. I know it is hard to give a timeline on these things, but do you think it will be days, weeks or months?

          • Tomo

            It’s not me who’s on it, but I wouldn’t say months.

  • Suresh Joshi

    Easily the best practical explanation of Clean – would you happen to have an associated Github repo?
    Also, in the onion drawing – you’ve grouped Repos into the domain, whereas in one of the later drawings, the Repo is part of Data. Is that to specify a concrete implementation?

    • Tomo

      Thanks, there will be a repo soon. Good catch on Repositories. Well, same as devices, they are two-part. Repository interfaces are defined in the domain, because business logic talks only to that interfaces, and concrete implementations are defined in the Data module, just as you said.

      • Suresh Joshi

        @disqus_6YW6LsKuLH:disqus Just to check something here – your ‘app’ module does take a dependency on the domain, data, and devices – correct? I can’t figure out any other way around the dependency injection otherwise.

        • Tomo

          Hey Suresh. Yes it does, it has to. It’s let’s say “main” module. It also has the stuff related to dependency injection there, it assembles object graph, etc…

          • Suresh Joshi

            Great, thanks! I figured that, but just wanted to confirm that I wasn’t missing something obvious.
            I also use the activities/fragments as a host for Injection points… Interestingly, I’m using Kotlin and I haven’t even needed Dagger (yet) because Kotlin facilitates constructor injection cleanly). I’ll probably have a post about that referencing you guys in a month or two on my blog.

          • Tomo

            Yup, I wasn’t completely clear about that, it might have make an article even more complicated. We have also tried Kotlin, but with Dagger, we used Java with and without Dagger. If you are being careful, and use your object graph factory, you can survive without Dagger without any problems, it’s maybe even more clear what’s going on under the hood, especially if you are using such a nice, slick language as Kotlin that actually helps you with some of the stuff. And thanks for referencing us :)

  • Joao Sousa

    Nice article! Please do share some code :)

    • Tomo

      Thanks, there will be some, but I cannot exactly say when, as I’m not doing it.

  • Phillipp

    I can only agree with what has just been said: really great post! :)
    Currently, I am working on a private project with real time data. Therefore I have to implement a web socket client that listens to events from the server handles them. Where should the web socket client be placed in the clean architecture modules (data?)? Should there be appropriate use cases for each event that can come in? Who should be responsible to start and stop the web socket client, also the domain layer?
    Furthermore, the app should persist all the data, so it can be used offline.
    Thank you very much in advance :)

    • Tomo

      Hi Phillipp. Thanks to nice words :) I would definitely put the web socket client and all the data logic in the data module. Domain only needs to get data, or better said, needs to be pushed with data, regardless of where the data comes from – cache, net, whatever. Business use case can only be – ListenForEventUseCase with Observable execute() method for example.

      Activation / deactivation. Well it depends on the communication that you use for the communication between layers. If you are using RxJava you can make an Observable in data layer that enables you to react to event of unsubscribing. That enables you to clean up the resources, one of them being web socket client. If you don’t use RxJava you will have to equip the calls with some kind of life-cycle. How long will it live depends on you, well basically the same thing you have to decide upon when you choose when do you want to unsubscribe from the observable if you are using RxJava. Do you want to listen for the whole life of the app? Just while a screen is shown. During the click of the button (probably not :) )? Maybe user can click listen and stop listening. That’s a business decision and you will probably use the use case to call a methods on the data layer that initialize or destroy the web socket client.

      Persistence is also par of the data layer. There is a nice pattern for data synchronization described on slideshare. I think you need (didn’t read it for some time) just 2 extra fields on every table – timestamp and version. With that you can implement couple of strategies for the data sync, replication, collision resolution, etc… Write “open-source patterns and code for data synchronization in mobile apps” in slideshare search bar and take the first result. This is my third attempt at submitting the post btw, because I’ve put direct link in my previous two and I suppose I shouldn’t do that :)

      • Phillipp

        Thanks for your detailed answer Tomo!
        Of course I am using RxJava, is it even possible to write apps without it? ;)

        I have to listen to the events during the hole life of the app, until the user is logged in. So I just was wondering how to implement this in a clean way. Putting the Event models to the domain layer seems to be wrong, because they are api specific. My approach would be to create a EventManager (e.g.) interface that just provides a `start` and end `method` that will be implemented in de data layer. Should this manager implementation use the repositories to store/modify the data locally (I need to do that) or should just the use cases talk to repositories?

        Unfortunately there are some more uncertainties from my side :/ Maybe you can give me some advices.

        1. should/can a use case contain another use case as dependency? Sometimes use cases shares some logic. E.g.: I have a StopEventsUseCase and a LogoutUseCase. During logout I need to stop listening to events. Should I invoke StopEventsUseCase within LogoutUseCase or should I implement some kind of BusinessLogic class and composite that implementation within both use cases?

        2. In most cases the api models significantly differs from my domain models.
        E.g. my Api Model just contains id’s to related entities and the domain models directly relates to other entities. That’s why I need to retrieve these dependencies somehow (from api and or local database) during mapping in the repository to store the data in the local data base. Can I call another repository within a repository to get the needed data (similar question to 1.)? Or is there a better way (always using flat model hierarchy)?

        3. How to handle rest api authorization (basic auth)? Currently i have a RequestInterceptor that automatically adds an appropriate authorization header to each request through a CredentialsManager that is just used within the data layer.

        Thank you very much again :)

  • Alexey Ershov

    One of the best posts about Clean Architecture, with attention to details and practical questions.
    I have a question, if you don’t mind. I have some Web API, and all requests for data go though a Repository, that’s no problem. But what about those API calls that actually do something? Like “submit order” or “send message”. Should I call them directly from my UseCases, or through some interface like OrderManager, implemented with those API calls? What’s your opinion on that? Thanks in advance!
    UPD: and in case of OrderManager approach, do I really need UseCases? It seems they will only be forwarding calls to Repositories and SomethingManagers.

    • Tomo

      Hey Alexey. I would use SubmitOrderUseCase that builds the order and calls save on OrderRepository with that newly created order. OrderManager is ok if there is some more complex logic around orders involved. For example if it needs to be involved in some kind of workflow that puts it through the stages of approval or something, if there are different strategies involved depending on the order type, etc. In your case order just needs to be saved, and for that OrderRepository is enough. But that’s a start, if it turns out that you’ll need to have more complicated process in the future, it’s easy to introduce OrderManager that handles the complicated stuff. Note that in that case OrderManager won’t die, it can still be used to persist the order, but it will be called from OrderManager instead of SubmitOrderUseCase.

      Yes, in most of the situations use cases delegate stuff to repositories. That’s because our mobile apps usually don’t have lots of business logic, the logic is to fetch or save. Maybe do some filtering, grouping and that’s it. And in that case, if you are using Kotlin for example you’re still gonna have one liners in your execute methods :) But that’s ok, that means that everything is neatly broken up by responsibility criteria. One benefit is that if you notice that there is lots of logic piling up in your use case you can start thinking about it – is all of that business logic?

      • Alexey Ershov

        Now that is an extended answer, thanks :)
        My app is actually pretty complex (I wouldn’t be asking questions otherwise), and it does have something except “fetch this” and “save that”. A better example of an API call I’m interested in would be “send verification code to phone XXX”, that accepts some phone number and makes the server send SMS to that number if some condition is satisfied. I’m not saving this number to a repository, and I’m not retrieving that code from the method.
        For my UseCase to be truly independent of an API I probably need some PhoneVerificator interface with verify(String phone) method, which will be implemented with an API call. My UseCase can depend on the interface, and call this method. Is this what the Clean approach suggests?
        To be more specific, is the following correct: all external services implementation should be hidden by appropriate interfaces (LocationProvider, PhoneVerificator, NotifiicationManager, etc.), and Use Cases depend on these interfaces, and serve only to glue together all calls to external services?

        • Tomo

          Yes, that’s pretty much it, all external services implementation are hidden by appropriate interfaces, including your PhoneVerificator. In haven given examples of the interfaces that are most common, and that are used the most in the typical mobile app, that would be all kind of sensors, persistence, etc, but your example is perfect because it shows us that the mobile app doesn’t have to be just a wrapper around the (online) database. In this case the use case will be more complicated, although not much. It can use LocationProvider to fetch the location, based on that decided to verify the phone using PhoneVerificator, show the appropriate message to the user using NotificationManager, and save the status in local db using PhoneNumberRepository.

          But the main point about that PhoneVerificator is that it can send SMS to verify the number, it can go to the API, it can be mocked, it can implement what ever strategy you want for verifying the phone. Now I’m repeating most of the things you’ve said, but I’m trying to emphasize that you’re right :) And I like that kind of interface names, it’s clear what does it do, comparing it to e.g. PhoneVerificationManager :) That’s why I like to name the other interfaces in the similar manner, Notifications, Alerts, Locations, etc…, but that’s my personal style, the most important is that teams agrees upon whatever naming you use.

          Google (or YT) “Uncle Bob clean architecture lecture”, pick some video with ok recording, skip first 10-15 minutes where he talks about the stuff totally unrelated to the topic (or listen for it if you have time, it’s interesting too :) ), and listen what’s man got to say. Clean is also sometimes called plugin architecture, because all of those interfaces that we inject (or plug into) to use cases (business logic) are plugins.

          • Alexey Ershov

            I’m glad that my thoughts go in the right direction) I’ve watched plenty of videos and read many articles, but this ‘Clean architectire’ topic is one of those where you have the ‘Aha! I finally got it!’ moment only after learning 100 slightly different opinions on it.

            Thanks a lot, your article and replies were very helpful!

          • Tomo

            Yeah, everybody has a bit different version, but just as you said, when you figure out the main point everything becomes the same thing :) Cheers!

  • Mohammed Alhammouri

    Great article, I have built two apps using Clean architecture/Rxjava/MVP I am very happy with the results, but I have one question that still looking for an answer to, Do I have to make entity/model/viewModel for each layer and mapper for each entity/viewModel (data/domain/Presentation) ?
    I found the benefits of it are real and I am convinced that I should separate each layer with it’s own POJOs.

    My other question do I really have to make this POJO separation in ANDROID because , it’s really annoying that every POJO I add I have to make mapper for it and everytime I change an attribute I change it in 3 classes instead of one ?

    • Tomo

      Hi @mohammedalhammouri:disqus, well, yes, it’s tiresome to keep all the POJOS, mapper, entities and (view)models separated. I used to insist on that separation, but if you and your team are disciplined enough I think you might take the pragmatic may and use the same model (domain model) even in outer layer, just always hold in your mind that logical separation and that one class plays domain model role in one layer and for example view model role when it arrives to the UI layer. And of course, if things get more complicated and you notice that you have started to mix the various layers logic in one class split it immediately into multiple models until it becomes too late.

  • Team Tiger

    Hi @disqus_6YW6LsKuLH:disqus,
    Thanks for your sharing!
    I have some concerns that I got on my own project.
    I would like to store the current user’s logged in state. Some where in my code (Ex: activity, fragment, presenters,…), I would like to check this state then process the next step like:
    if (userSession.isLoggedIn()) {
    // Navigate to home
    } else {
    // Open Login page
    }
    I have no idea which layer should it be and how to access this. Please give your advices!
    Thanks!

    • Tomo

      Hi @teamtiger:disqus,

      I would store it in data layer. Now which specific technology to use is up to you. The simplest way is probably to store the logged in user id in the preferences. If your session has some other data besides the logged in user, such as session length stored for analytics, then you can store serialized session object in the preferences. Either way you can have a SessionRepository with getCurrent() method that gives you back the current session – it should have loaded user id (or whole user object if you need it) in it. After that you can call isLoggedIn() method that simply checks is current user null, or current user id empty string.

  • Hoang Lang

    I get confuse where those things belong to:
    – android service
    – utilities, helper class
    – customized view class (custom layout, custom imageview…)

    Could you share your opinion?!

    • Tomo

      Hey @hoanglang:disqus. In my opinion:

      – android service – I would put it the app module. Lately I don’t have any logic in the service, I just start it sometimes to prevent the app for dying if I need to do something in the background, but business classes are the real work horses.

      – utilities, helper classes – you can make some common java lib that all the rest have ref to. That is if your utils and helpers are being used by all the other modules. If not you can put it where you use it. For example you can have StringUtils that everybody uses and it can go to the common module, on the other hand DatabaseUtils should probably go to data.util package (data module)

      – customized view classes – I would but those to the app module.

      • Hoang Lang

        Thank so much for your sharing @disqus_6YW6LsKuLH:disqus :)

        • Tomo

          You’re welcome :)

  • vikram singh (Thegreat004)

    @disqus_6YW6LsKuLH:disqus, excellent way for people to understand it. But it would be nice if you can share code without dependency injection like dagger. Waiting with eager for your positive response.

    • Tomo

      Hi @vikramsinghthegreat004:disqus, colleague of mine is working on the samples, I’m not sure does he use Dagger. On the other hand some people want to see it with Dagger as that is real world example in the most of the cases. In my opinion, if you are disciplined enough to handle object graph lifecycle properly, you don’t need Dagger.

      • vikram singh (Thegreat004)

        @disqus_6YW6LsKuLH:disqus, Basically i am also a new one to MVP and the reason is that if you are new one then you must go for basics that’s why i was asking for without Dagger.

        • Tomo

          Hmm yeah, I understand. You can try to ignore it when looking into examples, and when doing your app just use the factory instead.

          • vikram singh (Thegreat004)

            I don’t know the factory methods, that’s why I asked for demo app without dependency injection.

          • Tomo

            Aha, uh, :) Well ignore factory methods, or abstract factories and such a “fancy” stuff, imagine that you are allowed to use “new” keyword in just one class and that’s it :) Create all of your stuff in that class and call it a factory. Yes, it goes more complicated later on, but that’s a good approximation for start.

  • Dmitriy Khaver

    Hey @disqus_6YW6LsKuLH:disqus !
    Thank you and everyone who works for providing these awesome explanations. (:

    I would love to look on GitHub repo, tell me please, when it would be ready ?