DEV Community

Cover image for Stop saving lines!
Kevin Beltrão
Kevin Beltrão

Posted on • Edited on

Stop saving lines!

Introduction

In this article, I’m gonna argue why you should write more lines of code when developing software. First of all, it might be a good idea to clarify what I’m not trying to say.

Having your project divided into modules using different files is something that you should look forward to. Having your code divided by responsibility improves clarity and makes it easier to maintain the project. That out of the way, the goal here is not to add lines just to have a longer code, but to prioritize readability instead.

Ternary

Many languages, especially JavaScript, bring many awesome features so we can have the same algorithms with less or clearer code. A good example would be the ternary operator, which many times will save us needless lines of the if/else statement.

// before
if (condition) {
  variable = 3;
} else {
  variable = 2;
}

// then
variable = condition ? 3 : 2;
Enter fullscreen mode Exit fullscreen mode

So why or when should we avoid saving lines? Following the ternary example, what if we had nested ternaries?

variable = condition ? (condition2 ? 3 : 1) : 2;
Enter fullscreen mode Exit fullscreen mode

Is it still clear? Still worth writing it in a single line? I don't think so.

// before
variable = condition ? (condition2 ? 3 : 1) : 2;

// then
if (condition) {
  variable = condition2 ? 3 : 1;
} else {
  variable = 2;
}
Enter fullscreen mode Exit fullscreen mode

Yeah, the code got way longer, but always try to be understood through your code. If you'll probably have a hard time reading it later, imagine your teammates.

Variables

As in the ternary example, sometimes it's hard to resist just adding all the expressions in the same line, but it can get a little confusing. Creating variables to describe what's happening will help other engineers at reading the code later.

// before
const getRandomInteger = (min, max) => Math.trunc(Math.random() * (max - min + 1)) + min;

// then
const getRandomInteger = (min, max) => {
  const randomDecimal = Math.random();
  const numberOfPossibilities = max - min + 1;

  const randomIntegerFromZero = Math.trunc(randomDecimal * numberOfPossibilities);
  const randomIntegerFromMin = randomIntegerFromZero + min;

  return randomIntegerFromMin;
};
Enter fullscreen mode Exit fullscreen mode

Even though our code got bigger, take a look at how much easier it got to understand what's happening to the code.
1 - We get a random decimal
2 - Calculate the number of possibilities you have
3 - Generate a random integer from 0 to the number of possibilities
4 - Use the min value as an offset so the random integer is in the right range.

If you were an engineer in this team, which code would you rather have to understand and refactor?

Functions as labels

The reason we are told that functions exist is to reuse the code instead of rewriting the whole thing. But that's not their only purpose. A smart move is using functions to name a block of code and improve its readability.

Using the same example, let's say we have a function that filters programmers in an array and randomly picks one of them to get a prize. Let's see which one is easier to read.

// before
const getRandomProgrammer = (people) => {
  const programmers = people.filter(({ job }) => job === 'programmer');

  const min = 0;
  const max = programmers.length - 1;

  const randomDecimal = Math.random();
  const numberOfPossibilities = max - min + 1;

  const randomIntegerFromZero = Math.trunc(randomDecimal * numberOfPossibilities);
  const randomIntegerFromMin = randomIntegerFromZero + min;

  const winner = programmers[randomIntegerFromMin];

  return winner;
};

// then
const getRandomInteger = (min, max) => {
  const randomDecimal = Math.random();
  const numberOfPossibilities = max - min + 1;

  const randomIntegerFromZero = Math.trunc(randomDecimal * numberOfPossibilities);
  const randomIntegerFromMin = randomIntegerFromZero + min;

  return randomIntegerFromMin;
};

const getRandomProgrammer = (people) => {
  const programmers = people.filter(({ job }) => job === 'programmer');

  const winnerIndex = getRandomInteger(0, programmers.length - 1);

  const winner = programmers[winnerIndex];

  return winner;
};
Enter fullscreen mode Exit fullscreen mode

Even though now we have more lines of code, since now we're declaring a function, notice how much cleaner and readable getRandomProgrammer got. Instead of actually having to read each step of the algorithm, now you read a descriptive label (in this case getRandomInteger) and you know exactly what it's doing. And if I want to understand getRandomInteger, I can just read it knowing its logic is restricted between those curly braces.

PS: See how that also replaces comments in a more elegant way, instead of leaving a // getting random number before that block.

Line breaks

Breaking lines also improves code readability, if done properly. Let's think of ways to help our eyes at identifying patterns. What if, in the example below, we start each method in its own line instead of leaving it single lined?

// before
const ages = people.filter(({ job }) => job === 'programmer').sort((a, b) => (a.name < b.name ? -1 : 1)).map((programmer) => programmer.age);

// then
const ages = people
  .filter(({ job }) => job === 'programmer')
  .sort((a, b) => (a.name < b.name ? -1 : 1))
  .map((programmer) => programmer.age);
Enter fullscreen mode Exit fullscreen mode

And what if we give each condition its own line?

// before
if (job === programmer && age >= 18 && index !== winnerIndex && name.length !== 0) {
  giveConsolationPrize();
}

// then
if (
  job === programmer
  && age >= 18
  && index !== winnerIndex
  && name.length !== 0
) {
  giveConsolationPrize();
}
Enter fullscreen mode Exit fullscreen mode

And as the last line break tip, add empty lines between your code to improve readability! You can divide them by any category you can think of. Let's revisit the random integer code example:

// before
const getRandomInteger = (min, max) => {
  const randomDecimal = Math.random();
  const numberOfPossibilities = max - min + 1;
  const randomIntegerFromZero = Math.trunc(randomDecimal * numberOfPossibilities);
  const randomIntegerFromMin = randomIntegerFromZero + min;
  return randomIntegerFromMin;
};

// then
const getRandomInteger = (min, max) => {
  const randomDecimal = Math.random();
  const numberOfPossibilities = max - min + 1;

  const randomIntegerFromZero = Math.trunc(randomDecimal * numberOfPossibilities);
  const randomIntegerFromMin = randomIntegerFromZero + min;

  return randomIntegerFromMin;
};
Enter fullscreen mode Exit fullscreen mode

Notice how it gets harder to lose yourself in the lines in the second example. Now it's simpler to focus on specific blocks of code each time.

Conclusion

Even though I tried coming up with a few categories and examples, the important part is the concept I'm trying to express. Develop the habit of taking a second look at your code and ask yourself if it could be more expressive. Of course, you should not be extremist, consider the tradeoffs and evaluate factors, such as code complexity.

Top comments (1)

Collapse
 
joaofelipe profile image
João Felipe

This was so useful! I always wonder if I should write less or write more understandable and it helped a lot.