Refactoring utility classes with Kotlin : Shared Preferences

If you were developing Android apps in Java until now and haven’t started using Kotlin in production yet, you may have some sort of utility classes for many things like File I/O, Connectivity, Cache, Shared Preferences etc. Today, I am going to write only about Shared Prefs and how we can use Kotlin to refactor our old Java utility classes. This post is intended for anyone including beginners who want to play around Kotlin.

Maybe you have a good solution for shared prefs but I have it copied from here:

It looks ugly. To edit preferences, I have to write same things repetitively. Also, to access and manipulate, there are separate getters and setters for each type. In below steps, we will first try to refactor our Java class and then convert it to Kotlin.

Refactoring Step 1: Higher-order functions

The first step we can do is to identify a repetitive task that has been performing. In our case, every time we put something in preferences, we open an editor, put value and commit that transaction. Instead, we can compose a higher-order function that would accept a function to be performed by the editor. I am not going to discuss how you can use lambda expressions on Android. You can either enable Jack or use retrolambda.

Here, the Performer is a functional interface and edit method takes an anonymous function as an argument:

Refactoring Step 2: Using generics

Even after using lambdas, we have methods for each data type, which is not so good. We can use generics to have conditional checks for the type at run time. Either using instanceOf or using parametrizable class(class<?>), we can avoid writing a separate method for each type:

Finally, we can manipulate preferences with just two methods :getValue()and setValue(). Now code looks less ugly and concise than previous.

However, this if…else still looks bad. Many things like checking for nulls etc. are omitted. There are three to four parameters to pass in every single method. That interface for the higher-order function is unnecessary. We can not refactor those things because of limitations of the language.

Converting to Kotlin

Refactoring Step 3: Using extension functions

In the Java version of our class, we were using all static methods. We can now convert them to powerful extension functions. So, in our case, we will first convert our edit() function as an extension for SharedPreferences:

As we can pass function directly as an argument in Kotlin, we can get rid of that Performer interface. Here I used inline keyword to avoid the cost of higher-order functions. You can read more about it here.

Refactoring Step 4: Using when expressions and reified types

Using when expressions, we can eliminate all those if…else hell and make our setter look like below:

Well, but what about getValue()? In the Java version, we were using parameterizable class (class<T>). In Kotlin, we can do the same thing but with more elegantly using reified type parameters. To put simply, it will allow us to use type passed as a parameter. You can read more about it here.

Look at the following part:

getInt(key, defaultValue as? Int ?: -1)

Here, as? is a safe cast operator and so it returns null if typecast is failed. ?: is an elvis operator. It simply says: ‘take this value if the original value is null’. In our function parameter, defaultValue is the optional parameter. As a result, even if we don’t pass the default value, it will take from the right-hand side of the elvis operator.

Refactoring step 5: operator functions

So, our implementation now looks like below. Notice that I have added methods for accessing default as well as custom preferences and used object declaration to make it work as a singleton.

Wouldn’t it be great if just rename our setter and getter to just set() and get(). Kotlin supports operator overloading and so we can convert function to look like an operator:

Now we can use square brackets for setting and getting values. Just two lines of code for manipulating shared preferences.

It looks neat and elegant. Thanks to Kotlin!

Advertisements

Random thoughts on modern programming languages and Go

When I started my career as a developer, it was about last year of my graduation. At that time, I was like a Java fanboy. I fell in love with Java while studying it. Honestly, It felt very natural as a programming language. (and don’t get me wrong – I still really like Java) When I started working on real projects in my early days of the career, I realised that there is much to learn about programming languages & their semantics. I worked with many smart people and introduced to a whole bunch of new techniques, patterns, libraries and tools to build software in the fast and efficient way. It was a good and overall very enjoyable learning experience but I also passed through some of the issues about the current state of programming.

The Problem with Black box Abstraction

When I started building apps, I was introduced to some popular libraries that are recommended to use for general stuff like networking, databases and image decoding etc. I am very curious and so I always tried to find out how some big libraries works under the hood. I tried to look at their GitHub repositories and navigate to some code and tried to understand how it does some XYZ things. It was very beginning of my career and I always failed to fully understand how they do. So, I asked to some of my colleagues and some of them replied:

Who cares how it does something? It always works”

“You just need to learn about how to to use them. Don’t worry about inner details”

The library is just someone other’s code that provides an abstraction on certain things to make our life easy. But the point is why it is harder to read code than to write it? Why sometimes it becomes difficult for a beginner to look at someone other’s code and reason about it? Is it because the code is written as that one may get confused. or is it because one may not know certain design patterns used in that library? or is it because the programming language itself can do many things in many ways that one doesn’t know about them?

Almost every beginner and most end programmers tend to use libraries and frameworks without understanding how it does something under the hood. They see them as a black box. The black box that does certain things for them and make their life easier.

This is a big problem. Most of the times, it takes more time to understand someone’s code than writing it by yourself. This is why code reviews are taken more around code quality rather than software architecture or performance. Readability is the only most important thing considered while taking code reviews.

I don’t think that libraries and frameworks should provide the abstraction in such way that hides the details of the underlying system. Rather, they should provide the abstraction in a way that people can actually understand the underlying system. Too much abstraction becomes a barrier for most people, especially beginners to actually understand what the system does. It makes them think more about doing things rather than going deep and understanding things. That’s not a good thing. We want people to actually understand the details of stuff under the hood, not to learn the ways of using things. Anyway, this is my opinion and not everyone would agree on it.

The main reason behind all of the things I think is the current state of programming languages. When you look at some of the old programming languages like C++, JavaScript or Java and newer programming languages like Swift or Kotlin, you will realise that they are adding more and more features from one another and thus gives more ways of doing the same thing. This leads to writing program easily and faster but makes programs more complex and harder to reason about. Some people says that it makes programmers more productive. Adding more features to the language is not the only thing that makes programmers productive. When the codebase becomes large, sooner or later people realises that it could be made simpler if it had to deal with fewer ways of doing same things.

Learning Go

For the last couple of months, I have tried many new programming languages. I tried Dart and Kotlin. I looked at Rust and Swift. I like them. They all are feature rich. But they all forces you to think the same and believes that it is the standard paradigm for building good software.

Then, I tried Go. It took me less than two hours to learn the basics of Go. The language is simple and syntax is very much concise. The most important thing I liked about Go is that it has a minimal set of what called ‘features’. For an example, Look at the way of handling errors. At first, it looks very different from a Java background. But when you try it, you will realise that this is the way I should handle the errors. Go is a perfect blend of notions that makes the language very easy for learning and programs more readable for any level of programmer. The way interfaces are used feels very natural. There are no classes and so there is no type hierarchy – the hierarchy that can be broken by subtle changes after decisions. There are no generics. Sometimes I miss them. But when I think as a beginner, I think it is nice not to have them.

The most important thing in Go is that it solves above stated problem. Any beginner can easily read through the libraries and know how it works under the hood. It is very easy to read other people’s Go code and it always takes less amount of time than other languages.

With the current state of IDEs and tools, I feel very productive in Java. But as the second language of choice, I will surely go with Go. :=)