Make your Android application rock SOLID — Single Responsibility

Jorge Nicolás Nogueiras
ProAndroidDev
Published in
7 min readAug 28, 2019

Discover, discuss and put in practice the SOLID principles.

Make your Android Application rock SOLID.

Have you ever found yourself navigating through the code you were working on for several days, trying to fix some sneaky bug you couldn’t find? Have you ever felt disappointed with the amount of time you spent when adding some new features to your code?

If this is a common scenario for you, it might be time to review your design.
But hey, don’t panic! Your Android app is not completely dead. There’s something you can still do about it. Let’s discuss how.

As an Android engineer, software quality has been one of my biggest priorities. Architectural patterns, good practices, and testing are all relevant (among other topics) in order to achieve robust Android applications. There are lots of papers, videos, and documents about this topic that you can easily find surfing the web, some of them really good ones.

But although there is a lot of information around the web, what is harder to find are examples of these, good ones… if you know what I mean.

What is all this about?

This series of posts is all about SOLID principles, didn’t I tell you already?

“The SOLID principles tell us how to arrange our functions and data structures into classes, and how those classes should be interconnected”; Robert Martin, aka Uncle Bob.

As I mentioned before, I am always pursuing high-quality code by creating the best solutions possible and good examples to validate that these practices actually work.

I have seen different kinds of apps all over my career, some of them very fragile ( we’ll discuss this concept later ), rigid, unable to tolerate changes and I can assure you that good design and code quality are at the end, the best option against the excuse of “not having time to make it right”.

This is the first of several posts I intend to write in which I will present to you some of the concepts you may already know about SOLID or even apply in your daily work without even noticing. We are going to name them, identifying them in the Android code and discuss how these patterns and practices can improve not only our code quality but ourselves as engineers.

What does SOLID mean?

SOLID is basically all the best practices and principles presented and practiced over the years which deliver good-quality apps put together.

In resume, the SOLID is the acronym of:

Single Responsibility Principle

This principle tells us that no matter if you are dealing with a block of code, a class or even an entire module, it should have one and only one reason to change.

Open-Closed Principle

This principle is more related to code design. It basically says that for a given system, in order to change its behavior you should add new code instead of changing existing code. It must be Open for extension and Closed for modification.

Liskov Substitution Principle

Maybe this is the most complicated principle to understand. However, we will discuss it deeply in future posts. In short, this principle says that if we are building a system with interchangeable parts, those parts must agree to a contract that allows them to be substituted for another.

Interface Segregation Principle

I believe this is one of the most violated principles by the Android framework and for Android developers. This principle prevents developers to depend on things they do not really need.

Dependency Inversion Principle

This is the most valuable principle in order to decouple your Android app from code you may change in the future due to strategical decisions. We’ll be clarifying this in future posts but, strictly speaking, the principle says that the code which implements high-level policies must not depend on code that implements low-level policies.

Take a deep breath… Take another one… Read the principles again… Ok, they are probably making more sense now… Great! You are prepared to start now. Let’s rock!

SRP: Single Responsibility Principle

Single Responsibility Principle, as known as the S in SOLID, seems to be the easiest to understand among the other principles. But, instead of being that, it is the most violated.

When you read the definition you may think… “this thing should DO one and only one thing only” and then try to act in consequence. However, the SRP tells us that given a piece of code it should have one and only one reason to change.

You may be thinking what a “piece of code” exactly means in an Android application and there is not a single answer for that. SRP is applied to several levels:

Modules

I imagine you are still here because you are an Android developer and something in you (or in your project) kept you reading this article. I invite you to take a look at your app design, precisely your modules and to compare them with the image below.

SRP violated at a module level.

This is a snapshot of an Android application with some modules. Let’s say that this app is about generating billings for a given company. A user can generate a bill, send it to the client, generate reports for the company and also generate reports to send to our clients with all the bills we made to them in a given period of time.

Whether you are satisfied or not with the number of modules, let’s assume this is the application design. Reviewing the modules in the app, we can see that there is a rest module which intends to handle all the things related to API communication. Why would you change something in this module? Probably if something related to the communication itself needs to be changed. You should avoid including other stuff in this module not related to the rest communication. Finally, the rest module has one and only one reason to change.

On the other hand, the common module seems to contain stuff related to all the other modules. This means that it has many reasons to change and violates the Single Responsibility Principle.

The company which this application belongs to has a new request for the developer team. They want to change something in the report the app delivers to the clients. We need to change the billing module to satisfy the company's requirements. This module also has the responsibility to handle generate and store the billings, as well as send reports to the company. Don’t you think it's doing more than one thing? What if a new need about the company’s report arrives. Would we have to change it again? Well… it surely has a lot of reasons to change.

Avoiding this kind of problem is a must if we want to have a scalable and maintainable application. The billing module does more than one thing and in consequence, has more than one reason to change. If we do correctly, splitting it into more modules could solve the problem.

A possible solution would be to extract two different modules for reporting. One from the client perspective and the other from the app owner (our client) perspective where every module consumes data from the billing module. In future updates, adding a column or modifying a row in a report won’t require any changes in other modules.

Classes

Classes are usually another commonplace for SRP violation. If your project is full of classes named Manager, Engine or Service it would be the first place to look. Let’s see an example:

Example of a class that violates SRP.

According to its name, this class manages billing stuff. Yet, it can change because of many reasons (the report changes, something in the payment process changes and so on). Like we did with the module sample, splitting these kinds of classes would solve the problem. You’ll have more classes in your project, but every class will only do one thing and have only one reason to change. Don’t be afraid of creating classes to bring clarity to your project.

Methods

Wait, did you think you were already done?

Let’s say that you achieved the SRP with your classes by splitting them into several ones. Now it is time to review your methods as well. We could have more work to do there!

Whether you are using an MVP or MVVM pattern, a possible Interactor from the BillingManager class could be PayBilling.

A method that violates the SRP.

The public method in this class has some parameters which give us a clue that this method violates the SRP. Yes, it’s the boolean one.

This kind of parameter forces us to have an if statement to decide which path to take between two possible outcomes. In this case, the decision is whether we have to pay the last billing or pay the billing with the number received in the second parameter. This method does more than one thing.

A better design would avoid this problem by splitting the method. But, before that, we need to make another change to our class before taking care of the method. When the problem is in the public method of the Interactor, it means that the Interactor itself has to be split. Creating the PayLastBilling and moving all the related code to that class will do the job.

A class created from the previous version that respects SRP.

Now that we have split the class we can focus on the public method. Splitting the method again would finally solve or problem. We will have two new private methods which will do one simple thing each.

SRP applied to a method

Conclusion

We have learned what SOLID principles are and why we should apply them all around our apps to keep them flexible, maintainable and better prepared for any future change.

We agreed that no matter how complex our Android applications are, we can improve our designs by applying the SRP at several levels. At every level, it's important to have well-defined responsibilities.

Check the second part of this series in the link below:

I invite you to check my other posts in my profile too and, as I always say, If you find this article useful please support with a 👏.

Published in ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

Written by Jorge Nicolás Nogueiras

Android Engineer | Principal Engineer @ Etermax

Responses (1)

Write a response