A simple abstraction to keep code clean

Manoj Mohanty
ProAndroidDev
Published in
3 min readMar 24, 2022

--

Photo by Gallery DS on Unsplash

While we all talk about different architectures, there are other important and simple things that can be done to keep code clean and manageable in the long run. In this article, I will share how adding abstraction for using external libraries can benefit in the long run and make your code more resilient to changes when decisions to remove or replace external libraries are taken.

We don’t use libraries because of the features they provide we use libraries because we need certain features to be fulfilled.

So there are things which as a product/developer you want to have control on it can be enabling and disabling features on the fly, enabling for certain cities, user segment, showing different messages for different users, changing messages, etc. so there are multiple ways of doing it and Firebase Remote Config does that for you. One can check how to set up Firebase remote config and other use-cases here.

As a developer, we need something which helps us auto-sync our changes on the fly, and data can be primitive or of a specific type while auto-sync is something that the library provides and maintains for us we are focused only consuming.
Once you decide you want to use any particular library you can go ahead add it to your project and start using it but it is always better to think how easy it will be for me/someone on the project to change/replace the library without impacting the code. In the case of Firebase Remote Config, it is as easy as below

remoteConfig.getBoolean(key)
remoteConfig.getString(key)
.
. other available options

The above might look tempting but slowly you will see Firebase Remote Config getting into your code everywhere which is not good in the long run.

So we create simple rules for consumption that guard our code for the future.

Here Gson is used and other such or your own impl can be used for converting to specific types

Adding Implementation for this abstraction:

Config Provider which wraps the required options and usages for its consumer.

Start using it now with simple data providers one can create different data providers based on different feature modules and use them. The consumers of this implementation are least concerned about the underlying implementation of the library itself and we won’t even need to add Firebase Remote Config dependencies in Gradle for other modules.

Simple usage without even knowing what is being used for this feature

In the same way, other modules can create a config data source and use the feature which will lead to further separation.

Benefits of such implementation:

  • Library-related code is not scattered in the code.
  • The library becomes plug and play
  • Developers can move out of Firebase Remote Config and add new implementation and it will not require code changes given we adhere to rules.
  • We hide features that we don’t want of the library as the user can only use the available options.

We can write simple wrapper around the remote config provider as well and use instead of this implementation

Another use case where such abstraction can be implemented is image libraries. As these features deal with specific functionality with image libraries we want to load the image in a specific view and have some caching mechanism and it should be able to load images from drawable, network, files, etc so creating simple abstraction with this thought process can help in the long run and we can keep changing libraries without impacting our code e.g. initially we think Picasso is good and later Glide, Coil or any other library works better in some scenarios so changing it will be way easier.

That’s it for now :) If this helped you please share it with others as well and do give some claps. Also, do share your feedback and lets connect on Linkedin and Twitter.

--

--

Android Engineer @PayPay | Ex Rapido, Medibuddy, Carnot Technologies, Deloitte