Exploring S.O.L.I.D Principle in Android
We must all have heard about the S.O.L.I.D principle when developing software tools. I recently had a interview experience where this was asked and I wasn’t very clear on it. So I took the the time to fully understand what S.O.L.I.D means. I just wanted to highlight the basics of the principle and provide some examples on how this would be applicable to Android development.
So let’s begin by stating the 5 principles of S.O.L.I.D.
S — The Single Responsibility Principle (SRP):
A class should have only one reason to change
What I understood :This means that one class should only have one responsibility.
Scenario: Let’s take the OnBindViewHolder
method in RecyclerView.Adapter
class. The role of the OnBindViewHolder
is to map an list item to a view. There should be no logic in this method.
Let’s look at the below example to see how the SRP principle is violated in the OnBindViewHolder
method in this scenario:
Now, let’s look at the correct way to implement the OnBindViewHolder
method using SRP principle:
O — The Open-Closed Principle (OCP):
Software entities such as classes, functions, modules should be open for extension but not modification.
What I understood: This means that if we are required to add a new feature to the project, it is good practice to not modify the existing code but rather write new code that will be used by the existing code.
Scenario: Let’s say we have a class called TimeOfDayGreeting
with a single method getGreetingFromTimeOfDay
. We would like to display a greeting message when the user opens the app. This message must be based on the time of the day.
Let’s look at the below example to see how the OCP principle is violated in this scenario:
Now, let’s look at the correct way to implement this feature using the OCP principle:
L —The Liskov Substitution Principle (LSP):
Child classes should never break the parent class’ type definitions.
What I understood: This means that a sub class should override the methods from a parent class that does not break the functionality of the parent class.
Scenario: Let’s say we have a interface ClickListener
. This interface is implemented by the fragments 1 & 2. We would need to implement the ClickListener
interface in both the fragments. Our requirement is to increment click count in fragment 2 but decrement click count in fragment 1.
Let’s look at the below example to see how the LSP principle is violated in this scenario:
Now, let’s look at the correct way to implement this feature using the LSP principle:
I — The Interface Segregation Principle (ISP):
The interface-segregation principle (ISP) states that no client should be forced to depend on methods it does not use.
What I understood: This means that if an interface becomes too fat, then it should be split into smaller interfaces so that the client implementing the interface does not implement methods that are of no use to it.
Scenario: Let’s take the TextWatcher
interface in Android. We know that the TextWatcher
interface has 3 methods. This is an example of how this principle is violated, since we only use one of the methods most of the time.
Now, let’s look at the correct way to implement this feature using the ISP principle:
D — The Dependency Inversion Principle (DIP):
High-level modules should not depend on low-level modules. Both should depend on abstractions.
Abstractions should not depend upon details. Details should depend upon abstractions.
What I understood: If you use a class insider another class, this class will be dependent of the class injected.
Scenario: Let’s say we have a class called JobTracker
. The requirement is to update users via email or call based on the urgency of the job.
Let’s look at the below example to see how the DIP principle is violated in this scenario:
Now, let’s look at the correct way to implement this feature using the DIP principle:
And that’s it! If you like this and think I have done a good job here then please don’t forget to clap. Your appreciation is valuable and keeps me motivated.
Happy Coding, Cheers!!