Day 17 | #100DaysOfCode

Expressive Clean Code

Tell beautiful stories with beautiful programs

Dhananjay Trivedi
Oct 4 · 6 min read

A good storyteller has a strong command of his/her language and knows what constructs to use at which place to correctly tell any story beautifully.

Similarly, you must know the nouns and verbs (at least to start with) to be able to write clean expressive programs that tell a beautiful story to whomsoever reads them.

The nouns are the variables and classes, and verbs are the functions. Today, we will learn how to create and use them correctly.

Don’t underestimate the difficulty you’ll face for naming your variables, functions, and classes meaningfully. It’s not organic chemistry, but it’s still hard.

All right, let’s get started.


Clean Variable Names

FACT

Don’t spend too much time thinking of the right name — just write your code with different variable names in mind and see which one most closely fits with the code you have written.

A simple hard-and-fast rule you can always stick to is: The variable name should reveal three questions to the person who is reading your code.

  1. Why does this exist?
  2. What does it do?
  3. How is it used?

Here are some additional points to keep in mind:

  • Differentiating between two variables shouldn’t take much time. For example, these two variables take too much unnecessary effort to differentiate.
var XYZControllerForEfficientHandlingOfStrings 
var XYZControllerForEfficientStorageOfStrings
  • Be careful while using characters like 1 (one) and l (lower-case L) or O (upper-case O) and 0 (zero).
  • Never give names just to satisfy the compiler. When the compiler raises an error for duplicate names in the same scope, don’t just change the variable name to something like variable2 or some other random name. If your variables are different, their names should specify their different reasons to exist.
  • Use easy to pronounce names so they’re easier to pronounce when discussing your code with others.
  • Use searchable names. The IDEs are here to help us search through our code and to even give intuitive suggestions. But you can only harness this power if you’re giving names to your variable/functions. This will help you refer to them from any part of your code without having to come back to check what name you gave them.
  • Don’t use humor or puns when naming. Say what you mean, and mean what you say.

Writing Clean Functions

You’ll know when you’re working on clean code when each function turns out to be pretty much exactly what you expected.

  1. Functions should do one thing, and they should do it well.
  2. Functions should have only one reason to change. They must follow the single responsibility principle.
  3. Functions shouldn’t change when there is a new requirement. They must follow the open-closed principle.

(If you haven’t heard about the two principles mentioned above, read about them here.)

A function comprises a body and a list of parameters, both contributing equally toward writing clean functions.

Let’s take a look at some points for both:

1. The function’s body:

  • A function should either do something or return something — but not both. Either it should modify the state of the object or it should return some information about the object. Doing both will only lead to confusion in the future.
  • Functions should be small, which means they should never cross 20 lines of code (but try to keep them smaller than that).
  • The indent level of a function should not be greater than one or two as compared to the parent line. This, of course, makes the functions easier to read and understand.

Here is an example of bad code indentation:

Credit: Stack Overflow
  • The blocks within if statements, else statements, while statements, and so on should be one line long. If it’s a long conditional statement, refactor that as a function that returns either true or false.
  • A long descriptive name of the function is better than a short enigmatic name.

2. Function arguments

Ideal number: The ideal number of arguments a function should have is zero. After that, no more than one, two, or, at most, three is advisable (although the latter should be avoided). More than three arguments are only allowed for very special cases.

Why? Multiple arguments are even harder from a testing point of view. Imagine the difficulty of writing all the test cases to ensure all the various combinations of arguments work properly.

Problem: If there are no arguments, this is trivial. If there’s one argument, it’s not too hard. With two arguments, the problem gets a bit more challenging. With more than two arguments, testing every combination of the appropriate values becomes daunting. You can avoid that by writing functions with a minimal number of arguments.

Never pass flag arguments: Passing flag (true/false) as an argument is truly a terrible practice. It immediately makes your function violate SRP — as your function behaves in a certain way when the argument is true and another way when the argument is false.

What should you do? Use argument objects: Wrapping up multiple arguments inside one class may seem like cheating, but it's really not. When there are multiple arguments involved that you need to send to a function, they’re probably related to each other in some way. It’s really a good practice to encapsulate those fields into one class and give that class a meaningful name.

Many languages provide you the platform to write in-line functions. For example, you are asked to write a function that takes a report as input and appends a footer to that report.

Approach 1: Creating a function that takes the report as input and appends a footer to it. This function takes one argument. It can be improved.

public void appendFooter(StringBuffer report) {...}

Approach 2: Creating an in-line function, which takes no arguments but actually works directly with the instance of the report.

report.appendFooter()

How to Handle Errors/Exceptions?

Functions handling errors must only handle errors and shouldn’t be doing anything else.

Prefer throwing exceptions rather than returning error codes. When you return error code, you force the caller function to deal with it immediately. This means more boilerplate code.

Let’s look at an example. We’re doing some networking to update our UI with a list of food items.

Networking class:

// Inside some function
// Getting list from somewhere
val listOfFoodItems = getFoodItemsList()// If list is null, means something went wrong
if (listOfFoodItems.isNull()) {
callback(FoodOrder.Error)
}
// If all goes well, we send back list of food items
else {
callback(FoodOrder.FoodMenu(listOfFoodItems))
}

UI class:

// Getting list from somewhere
var status = getReturningStatus()
if (status == ERROR) {
// Handle errors
} else if (status == FoodItemList) {
// Do something with food list
}

If we were to use exceptions, our code would get much more compact.

Improved networking class:

val listOfFoodItems = getFoodItemsList()if (listOfFoodItems.isNull()) {
throw some custom Exception
}
else {
callback(FoodOrder.FoodMenu(listOfFoodItems))
}

Improved UI class:

try {
var listOfFoodItems = getAllFoodItems()
} catch (your exception type) {
// Act accordingly
}

Even if your number of error use cases increase, you just have to throw exceptions from the networking class — and just add more catch blocks in the UI class.

By the way, this code is also following the open-closed principle.

Tip: If you are doing multiple things in your try/catch blocks, extract out inappropriate functions to make your code look clean and readable. Don’t leave a nested, ugly-looking try-catch block.


Conclusion

Master programmers think of systems as stories to be told rather than programs to be written.

They choose the constructs of their programming language to express the story they’re writing in code. Functions are the verbs of a language, and classes are the nouns. The art of programming has been about how to use the tools that the language offers to tell the best story you can.

There is a lot more to share with you, which I will be doing in the upcoming days. Thanks for reading, and, as always, you’re awesome!

Better Programming

Advice for programmers.

Dhananjay Trivedi

Written by

Gonna leave you better than I found you. Full Stack Android Engineer @ Softway.

Better Programming

Advice for programmers.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade