Android S — SOLID

Abdul Rahman
AndroidPub
4 min readMay 3, 2018

--

This is the first of the series of blogs on SOLID principles.

S is Single responsibility principle, one of the principles in SOLID principles. If you’ve wondered how you can better manage your code base please stay and read this. At the end of the article we should have a fair understanding of What, Why and How SRP in order to manage your code better.

Let us start the article by creating a simple application, which can be used to log the calories that we intake and see sum of calories. Let us not make the app complicated for now and hence have a single screen to accomplish both the tasks.

Since we need just one screen, we will go with a single Activity named CalorieTrackerActivity instead of MainActivity(emphasizing naming the activity correctly), as we are trying to track our calorie in the activity and a layout acivity_main.xml.

Let us create a LinearLayout with EditText and Button, to get calories from user and ProgressBar to see the calories we in took (with 100% as 1k calories).

Hence the code will look like this:

Object Oriented Principles (OOP), enforces us to have Real time entities as Objects. We understand that an object can have instance variables which satisfies ‘has-a’ relationship in real world. And can have methods that the object can do in real world.

Debriefing the above said with an instance. If we create a Student object, it should only have methods like study, read, play and so on. It shouldn’t have methods like print, readFromConsole, getInput as a Student essentially can’t get input. And Student can have attributes like name, age, gender, but can’t have attributes like button, system. As the Student can’t have a button, but a student’s shirt can only have a button :P .

Here we have our real time entity as a CalorieTrackerActivity, which has two fields and a method to handle submit.

Now let us answer the questions:

  1. Can CalorieTrackerActivity have calorieEditTextView, calorieProgressBar?
  2. Can CalorieTrackerActivity updateCalories?

Answers to these questions are subjective, as CalorieTrackerActivity isn’t a real time entity objects, rather it’s a view object. With the problem statement in mind, we say a yes. Having yes to these questions are prerequisite to adhere to SRP, as we need to follow OOP in order to follow SRP.

Let us now try to relate to SRP, for that let us brief what is SRP:

Single responsibility principle (SRP) enforces that classes/objects in the code base should have only a single responsibility of the functionality the app gives.

Adding to it, Robert C. Martin explains SRP as a reason to change.

For instance, a Person object can speak, write, run, drive, manage. It doesn’t mean that all these methods should be in the person class, as this would bloat up the person class and end up with a highly coupled functionalities. Rather it should be split up into classes like Manager, Driver, Speaker, so that we don’t end up changing person class for all the functionality changes.

Going back to our problem statement, our app in basic has two functionalities, one to get input from the user and other to display the calorie intake by adding the input with the existing calorie value. These functionalities may be trivial but to understand SRP let us agree those as two different functionalities.

In both the cases of changing the way we get the input or the way we output the number of calories we in took, we will have to make changes to CalorieTrackerActivity. Hence we infer CalorieTrackerActivity violates SRP.

One of the possible solutions is to have two fragment one for each functionalities. Hence code becomes:

By doing this refactoring, we have adhered to OOP:

  1. CalorieTrackerActivity doesn’t do anything other than adding the two fragments into the screen.
  2. CalroieOutputFragment can setCalorieProgress
  3. CalroieInputFragment can handleCalorieInput

SRP is also honored:

  1. If we want to change input functionality, we will change CalroieInputFragment
  2. If we want to change output functionality, we change CalroieOutputFragment.

We can attain SRP by using custom views too. The code will be like this, if we chose custom view instead of fragments.

Even in this code, To change the way we input, we will change CalorieInputView and we will change CalorieOutputView to change the way we output.

Custom view vs Fragment is an ongoing discussion, Even though Fragment will Fragment the code base well , I prefer fragmenting using custom views, as we need not worry about the fragment life cycles, problems of nested fragments etc, but still be able to fragment the code. (Doesn’t para sound like a poem? :P)

Having discussed what, how aspects of SRP, let us conclude with when, where and why aspects:

If we don’t follow SRP, which is the basic for better design, we may end up in a highly coupled code base, where any enhancement to the app will take more time than it should be taking. Hence Flexibility, Re-usability of the code will reduce. There are so many things we will loose if code is highly coupled.

Uncle Bob says SRP should be at class / module level. I will extend it to even methods. Each method should do what it says, for instance print method shouldn’t increment a counter. We need to think twice to even set the Listener ‘s to the views in an unrelated method.

It would be better to keep SRP always in mind whenever we code. As said earlier it’s the key to well organized and easily maintainable code.

If you like the article please don’t forget to clap. Feel free to share your thoughts as comments.

--

--