Verbose code is bad

by Dennis — 9 minutes

Us Divotees are well known for our good and strong discussions. It's not uncommon that we talk longer about a front-end related topic than we initially planned. This is why our knowledge sessions by default have significant overflow, this time is always utilised by passionate discussions. The same thing happened when Gosse, our marketeer, asked us a question in the office: What is verbose code, and what does it mean for you? The first thought that popped into my head was: Verbose code must be something to avoid. The translation for verbose is ‘too many words’. My first thought was: that certainly can’t be good as more words can lead to a big unmaintainable codebase. The question that remains: how do we define “too many”?

The stigmatic idea of software developers writing “the new Facebook app” on their computer in the attic, without seeing much daylight, is disappearing. Yes, we still write code in the attic, but coding is all about communication. Hence, I describe myself as a social nerd. If I write code I need to make sure everyone understands what I’m doing.

Software developers communicate in the language they know. Most of the time it's English, but more often it's through a programming language. Developers translate the language of the business needs into a technical language that results in something the user actually needs. This translation happens automatically for us. But talking the same language doesn’t automatically mean we understand each other. You might have encountered this problem, for example when talking to your partner about what you are going to eat tonight.

Communication is key

Communication indifference has a bigger impact on our lives than we might think. We can apply the DISC-model for our communication. The DISC-model tells us we tend to communicate better with people who are more alike. Some people tent to be very direct, others can be a bit more subtle with their communication. For example, direct people like to have strong and direct conversations. When asked what to have for dinner they will probably respond with a suggestion they see fit. When the other person also has a more direct approach, they will probably reach a conclusion really quickly, and thus arrive at something to eat.

Drawing a conclusion the previous example one might say that the direct approach is the most effective way of communicating. For this reason verbose code - the topic on which I started this article - is something we should avoid. But a direct approach also has its disadvantages. More direct and shorter code doesn’t necessarily mean better quality. Besides speaking the same language we still need to learn “each other's language”. Our own language is the way we like to communicate, and this can be different for all of us. The best possible way to communicate with each other is to communicate on how to communicate.

Defining communication intent through code

We can apply the same rules to software development. For example, your team has already defined the programming language you write the application in. You've probably also defined other sets of rules when it comes to code quality. Code can be really straightforward and direct, this is also encouraged by functional programming. Let’s clearly define our communication intent through a JavaScript example.

For this example we have been given a cart. We now want to calculate the total sum of the items.

Our data:

const cart = [
  {
    lineItem: 9.15,
    name: "Some item",
    // moreData
  },
  {
    lineItem: 5.65,
    name: "Some other item",
    // moreData
  },
  ...moreCartItems,
];

We can redefine the question to give more direction for our intended solution. With the given cart array I want to sum the lineItem property of each item.

This gives us two action points

  1. We want a new array of lineItems
  2. We want the sum of this new array

So let’s create two helper functions for this.

function mapCartLineItems(cart) {
  return cart.map((cartItem) => cartItem.lineItem);
}

function sum(numbers) {
  return numbers.reduce((a, b) => a + b, 0);
}

const cartLineItems = cart.map(mapCartLineItems);
const sumOfCartLineItems = sum(cartLineItems);

With this example we clearly defined our way of communication. We took each action as a function and defined how we want to process each part.

But this isn’t something we do in real life either. We won’t start a conversation and firstly set aside all ways on how we want to process each word or given sentence. So maybe this example is what we call a bit too verbose. We over-communicated about our way of working, and even though this example is a short one, this can grow to a big unmaintainable codebase. We need to find a way to describe our way of communicating without defining all parts separately. This way we can process data a lot faster and our codebase gets more maintainable.

Context is key?

As humans we are really good at interpreting and converting bits of information. When having a conversation we can automatically detect context. By context I mean every bit of information you can gather, for example non-verbal communication and the environment. Everyone can interpret this same context differently.

Context helps us understand each other, creating a relationship between the sender and the receiver, giving a deeper understanding of the intent and direction of the conversation. When this intent or direction isn’t automatically communicated through context, a conversation can get stuck. For example: When in the supermarket the cashier asks if you want to pay by card or cash, you answer “by card”. The cashier will understand the response “by card” as it's related to the question and the environment. It's a common practice to use context like this. It allows us for the creation of multi-turn dialogs. Without it, every dialog turn would result in a new fully blown conversation.

When in a multi-turn dialog, a conversation can happen without any effort. It will get a bit more complicated when you switch context during a conversation. Let’s say the same cashier compliments you on your shoes. We can detect this context switching as the intent and direction of this new conversation is being stated clearly. Switching context without this intent can be confusing otherwise.

Applying context to code

We use multi-turn dialogs and context switching all the time as part of our (ordinary) life. The same applies for our code. For example when declaring a variable named Title we need some extra context. Where is this title being used? We can give this context in different ways.

  • We can rename this variable to something that clearly states the context of the title, DocumentTitle for example.
  • Another way of achieving this result is by placing this variable into an environmental context by our project structure.

The rules for context are the same for programming languages. Environmental context can come from a project structure, or you can rename a variable stating your intent of the code. Verbose code, in my opinion, is a piece of code that expresses too much context.

Reducing verbose code

As mentioned above we can reduce our verbose code by relying on existing context. If you get familiar with your codebase the context of your code will also be clearer. But beware of relying on context that only you can understand. Context in software development should be written down. Take a step back from your code sometimes and try to see if you have provided enough context for your code, or maybe even too much.

An important thing to take into account when reducing code, and relying on already existing context, is being too direct with your code. This term is a little bit vague so let me demonstrate with a JavaScript example taken from the HTTP 203 series on YouTube.

images.reduce((merged, image) => {
  if (image.thumbnail) {
    merged.push(image.thumbnail);
  }

  return merged;
}, []);

In this example we take an array with an image object and return all images with thumbnails in it. A simple code snippet that uses functional programming through a reduce function.

This example provides enough context to read, we have an array with image objects, and we create a new array with image thumbnails. But the function is harder to read due to the cognitive load of the function. Even though we provided enough context for the reduce function, the context is separated.

To understand the inner working of the reduce function we first have to loop at the initial value, in this example an empty array. This is the most crucial bit of context we need for the reduce function, unfortunately it's located at the end of the function.

We can create the same context but in my opinion a bit clearer.

images.map((image) => image.thumbnail).filter(Boolean);

// or
images.filter((image) => image.thumbnail).map((image) => image.thumbnail);

Given the same image we now take two functions instead of one. We now first map the image array to a new array containing the thumbnail, or undefined in this case. Now we remove all undefined values from the array with a filter function.

Both these examples gave context to the function but they can be interpreted differently. Personally I like to be explicit in my intentions, and for this reason I rather use the second example.

Conclusion

If I write code I want to make sure everyone understands what I’m doing. That is why I describe myself as a social nerd. In software development we do this by communicating through code. In our day-to-day lives we rely on context to provide a deeper understanding of the intent and direction of a conversation. We should use the same skills in our code style. By clearly stating the intent of your code. But we have to be aware of over-communicating through code and rely on existing context. If not, it can result in verbose code and maybe an unmaintainable codebase. For me the term “too many”, and thus verbose code, is an over-communication in context.

Resources

meerdivotion

Cases

Blogs

Event