Android Clean Code — Part 1

Mohamed Hamdan
Winfooz’s Engineering Blog
4 min readMay 7, 2019

Names are everywhere in software. We name our variables, our functions, our arguments, classes, and packages. We name our source files and the directories that contain them. We name our jar files and war files and ear files. We name and name and name

These words are from Clean Code book and as we can see, we name and name and name, so what do we need to know about Meaningful Names?

1- The names should reveal intent

Choosing good names takes time but saves more than it takes.

The name of a variable, function, or class, should answer all the big questions. It should tell you why it exists, what it does, and how it is used. If a name requires a comment, then the name does not reveal its intent.

let’s take an example

var t: Long = 0

What t means here, is it time? timestamp? or what? If we write names this way, that means after one day we will not know what t means, so let’s try to explain in code what t means

// Current timestamp
var t: Long = 0

here we add comment to explain what t means but as Uncle Bob said If a name requires a comment, then the name does not reveal intent. So let’s change the name to another clear name to reveal intent

var currentTimestamp: Long = 0

In this way if we read this variable name we will understand what it is means directly without any kind of documentations.

2- Make Meaningful Distinctions

If we can’t write same variable name twice that doesn’t mean to add number series or noise words, if the compiler tell us the names should be different that means they also should mean something different.

var date1: Date? = null
var date2: Date? = null

If we look at these variables at first glance you will think its same thing but the truth its different, the first one is for today date and the second one for yesterday date so it’s better if we change the names to

var todayDate: Date? = null
var yesterdayDate: Date? = null

Number series or noise words a1, a2 .. aN they provide no clue, Consider:

fun distanceTo(l1: Location, l2: Location): Float {
return l1.distanceTo(l2)
}

This function reads much better when source and destination are used for the argument names.

fun distanceTo(source: Location, destination: Location): Float {
return source.distanceTo(destination)
}

The noise words are meaningless distinction, imagine that you have a User class which contains another class called UserData or UserInfo, you have made the name different without making them mean anything different, What if we rename it to UserWrapper which contains User?

Info and Data are indistinct noise words like a, an, and the, There is nothing wrong with using prefix conventions like a and the so long as they make a meaningful distinction, Consider:

fun distanceBetween(): Float? {
val aSource: Location? = null
val aDestination: Location? = null

return aSource?.distanceTo(aDestination)
}

And now look at this example

fun distanceBetween(): Float? {
val source: Location? = null
val aSource: Location? = null

return source?.distanceTo(aSource)
}

In the first example i used a for all local variables but in the second example i used a because i already have variable with same name source, you can apply same things with an and the.

3- Use Pronounceable Names

If you can’t pronounce it, you can’t discuss it without sounding like an idiot. “Well, over here on the bee cee arr three cee enn tee we have a pee ess zee kyew int, see?”

This paragraph is from Clean code book, which explains that we should use pronounceable names. Consider that:

fun disBetw2Locs(l1: Location, l2: Location): Float? {
return l1.distanceTo(l2)
}

How long did it take you to understand what this method does? I’m sure you took too much time to understand or did not understand it at all but what if we renamed it to:

fun distanceBetweenTwoLocations(source: Location, destination: Location): Float? { 
return source.distanceTo(destination)
}

Now you can understand it at a glance!

4- Use Searchable Names

Instead of using single letter names or numbers you can use meaningful names with constants to fit the numbers:

fun getYears(): MutableList<Int> {
val years = mutableListOf<Int>()
for (i in 1995..2019) {
years.add(i)
}
return years
}

1995 and 2019 are not searchable so when we need to change these values we need to read all the class to find them, instead we can create two constants that contains 1995 and 2019

fun getYears(): MutableList<Int> {
val years = mutableListOf<Int>()
for (i in START_YEAR..END_YEAR) {
years.add(i)
}
return years
}

private companion object {

private const val START_YEAR = 1995
private const val END_YEAR = 2019
}

So now when we want to change these values we search for start and end years

--

--