HomeAndroidSOLID Principles in Android with Kotlin Examples

SOLID Principles in Android with Kotlin Examples

-

Recently I had an interview experience where I went blank when the interviewer posed an Interesting Question – Explain SOLID Principles and how they are applicable in Android. Like many other blackboxes I use to skip while programming, I never bothered about learning the SOLID Principles. That interview was an eye opener for me and I took a while to understand the SOLID Principles and decided to share my findings and notes with the Android Community so that it might help someone. Let’s dive into knowing them without further delay.

Why to bother about SOLID Principles?

Before discussing about SOLID principles, here is the quote I found interesting and helpful in understanding why we need SOLID Principles.

“The only constant in life is change”-Heraclitus.

As we all know that Software Industry is a fast paced industry with rapid changes, the components which we use today will become outdated only in matter of small time. Our app requirements changes as time passes. Our codebase will be continuously updated.

Let us imagine all our android code written into a single activity or fragment. While the class becomes lengthy, that is not the only case. We have to deal with several problems like modifying large part of the app or rewriting the entire app if your manager tells us to change business logic or switch from one component to another ( eg. sqlite to other db).

What separates from a novice programmer to an experienced programmer is this SOLID principles application and writing the code keeping them always in our mind.

SOLID unites all the best practices of software development over the years to deliver good quality apps. Understanding SOLID Principles will help us write clean and elegant code. It helps us write the code with SOC (Separation of Concerns).

What is the definition of SOLID?

SOLID is an acronym for five basic Object Oriented Principles –

S Stands for Single Responsibility Principle (SRP)

A class should have only one reason to change.

We can understand the above in this way: A class should have only one responsibility. If it is updating the view, it should be concerned about updating the view only. It should not contain the logic of calculations or data conversions. Let us see with an Android example using Kotlin.

In the above example, we see that from line 7, we are iterating through hashtags and appending them to string. This puts the burden on the above method where its single responsibility is to update the view. Hence here it violates the Single Responsibility Principle. Therefore, to solve this, we will delegate that logic to other classes such as Utility classes. Now after modification, our method looks like:

Another example is: using ViewModel which is a part of Lifecycle Library. Separating our app’s UI data from your Activity and Fragment classes lets us better follow the single responsibility principle: Our activities and fragments are responsible for drawing data to the screen, while our ViewModel can take care of holding and processing all the data needed for the UI.

O Stands for Open-Closed Principle

Software entities such as classes, functions, modules should be open for extension but closed for modification.

It means that whenever we are writing a new functionality, we should not modify existing code. We should rather write new code which will be used by existing code.

For example, in Android, we will write a custom adapter class on top of Android’s Adapter class for our implementation.

Let us see another Kotlin example:

Here PriceFactory class is checking if the Hotel is Mariott or whether it is Taj. If it is not, it simply throws “Hotel Not Listed”. Hence every time we add a new Hotel, we need to touch PriceFactory Class to modify its content which violates Open/Closed Principle.

You may also find useful:

Android Interview Questions and Answers

To make it obey the above Principle, we need to modify the above example as shown in below:

L stands for Liskov Substitution Principle (LSP)

The derived class must be usable through the base class interface, without the need for the user to know the difference.

Liskov Substitution Principle suggests that we can replace a Parent Class with a Child class without altering the correctness of the application. It was named of renowned computer scientist – Barbara Liskov. 

Let us take a standard example to understand. Let us examine where LSP fails.

In the above code block, we have a Bird class as open class. Now two birds – Eagle and Penguin are extending Bird feature and therefore inherits all the features of the bird. But we know that Penguin cannot fly. Therefore instead of properties we need to segregate classes by Behaviours. Let us next see how we can fix the above scenario.

Here we separated the characteristics of a Flying bird and we extended Eagle class with it, thus obeying Liskov Substitution Principle. In other words, a subclass should override the parent class’s methods in a way that does not break functionality.

An elegant example in android is – using repository to fetch either from local or remote. We will only call Repository to fetch the data. We as a dependent on the Repo should not know whether the data is being fetched from local or remote.

I stands for Interface Segregation

Interface Segregation states that:

No client should be forced to depend on methods it does not use.

It means that a class should contain as many minimum methods as possible. Any interface that class inherits should consist of methods which are required by the class.

Now let us fix the above code. We will segregate the interfaces of hot food items and cold food items from food.

Here we can see that we introduced two additional interfaces which will help us reduce the methods which are not required. This helps us understanding Interface Segregation Principle.

D stands for Dependency Inversion

According to Robert C. Martin, Dependency Inversion Principle consists of two

1. High-level modules should not depend on low-level modules. Both should depend on abstractions.
2. Abstractions should not depend on details. Details should depend on abstractions.

To understand this example, let us take a common scenario from Android Development. User has an option to enable dark mode and if he clicked on it, we need to store his preference for future purpose. Currently our business asked us to store it in local. Hence we opted to store in shared preferences.

Below is the code snippet for it:

Now our business came with a new plan to change the logic to server. This will impact our existing code as we need to modify it.

To tackle this problem, let us divide our code base into 2 modules – UI module and Repository Module. This is a perfect example of Separation of Concerns (SOC). Now if we see our code, UI module depends upon Repository module.

Now lets alter the code to fit them into respective modules as follows. Our UI Module consists of Activity and ViewModel and the code is refactored as follows:

Now we moved our data model into PrefRepo as follows:

The implementation of it for our local data source is as follows:

If we carefully observe the above implementation, we can clearly see that our dependencies are inverted – our Repository Layer now depends on UI layer. Thus we created abstraction wherever we think the code changes are frequent thus making our code more maintainable.

The Dependency Inversion project is available in my GitHub repository. Drop a star if you find it useful.


Though SOLID Principles seems a bit overwhelming at the first time, learning them and using them as a Software developer makes our code more robust and maintainable protecting us from future changes. 

 

Vamsi Tallapudi
Architect Technology at Cognizant | Full Stack Engineer | Technical Blogger | AI Enthusiast

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.

LATEST POSTS

Top 5 Software Courses to land into Highest Paying Jobs

The software industry has been emerging as a big player in recent decades. It is the second most active contributor of the economy after Medical...

Building a Multi Module App in Android | Modularization in Android #1

Recently, I was in requirement for developing a Multi Module app in Android and I was going through this great lecture on it. This article...

Using Static Factory Methods – Learning Effective Java Item 1

In this series, we will learn how to apply concepts of highly popular Java book, Effective Java, 2nd Edition. In the first article, we will...

Lambda function in Kotlin with Examples

Lambda function is powerful feature in any Programming language and Lambda function in Kotlin is no exception. In this article, we will look at how...
Exit mobile version