top tip:
Level up your console.log game

Jul 27, 2020

TLDR: Assign everything to a variable. Use console.log({x})

Recently I've been working on rewriting a maths engine. This is a very large set of javascript classes and functions that performs a lot of complex financial calculations. I did not build it originally.

It is being rewritten to provide new features,and to get the benefits of using typescript, but a lot of my work has been converting existing classes methods. I'm trying to make the code more readable at the same time as simplifying it.

When it was first written, there was a need to completely emulate Excel's calculation functions(!) Luckily, this is no longer a requirement, and it's been satisfying stripping that code out.

I'm finding that my workflow goes like this:

  • Convert the test for a method
  • Cut and paste the existing code, which won't work because we've changed quite a lot about the way it is run
  • Come up with a neat, more efficient implementation, with leveraging the best of typescript and ES2019
  • Panic when it doesn't pass the test, on one memorable occasion, being out by Number.POSITIVE_INFINITY dollars

and that's when I need to start debugging.

The rest of this post will probably apply to any language that has some sort of print statement. My number one console.log tip though, depends on ES2015 javascript, because it uses object shorthand property names.

Here it is:

Instead of using console.log(variable) use console.log({variable})

{variable} is a shorthand for {variable: variable} and it means that, with the addition of two curly brackets, our console output becomes much more useful.

Instead of 50 we get {iterations: 50} printed, which lets you know what you are printing. It probably doesn't matter if you're only checking one variable but in any other situation, it is well worth it.

There are other ways you could do this

console.log('iterations', iterations);
console.log(`iterations: ${iterations}`);

but they all require typing the variable name out twice.

Now, Firefox and Chrome devtools are great, but sometimes I just find console.log to be conceptually easier. However, when I'm trying to replicate a method like this:

getSomeFinancialAmount {
return Math.min(0, this.otherMethod(
this.otherFinancialAmount / dateLibrary.MONTHS_IN_YEAR
));
}

then it's not as easy.

The first problem is that I can't console.log the return value easily. So I would probably rewrite this as:

getSomeFinancialAmount {
const output = Math.min(0, this.otherMethod(
this.otherFinancialAmount / dateLibrary.MONTHS_IN_YEAR
));
console.log({output});
return output;
}

But what about the otherMethod call? You can't do console.log({this.otherFinancialAmount}) because the object property shorthand only works with variables. Well, I've taken to following this rule

Assign everything to a variable

when I'm writing tricky code. Like any rule, there's times to bend or break it, but in the example we're using, I would probably write:

getSomeFinancialAmount {
const { otherFinancialAmount } = this;
const { MONTHS_IN_YEAR } = dateLibrary;

/* as an aside, I feel like you can replace MONTHS_IN_YEAR
with 12 if you have sensible variable names elsewhere */


const otherFinancialAmountPerMonth = otherFinancialAmount / MONTHS_IN_YEAR;

const resultOfOtherMethod = this.otherMethod(otherFinancialAmountPerMonth);

/* Ideally, otherMethod would have a better name, and so would
this variable :) */


const output = Math.min(0, resultOfOtherMethod);

console.log({
otherFinancialAmount,
MONTHS_IN_YEAR,
otherFinancialAmountPerMonth,
resultOfOtherMethod,
output
);

return output;
}

It's much longer. But we get, in one single console.log all the relevant information printed.

The console.log statement would be removed once the debugging is finished. But I would leave the code like this, otherwise. It makes me write code that is easier to understand next time I need to change something. This is almost always more important than writing fewer lines of code.

As a final tip, if you're debugging more than one method or class, it can be useful to do

console.log('Class.method1', { variable1 });
// ...
console.log('Class.method2', { variable2 });

to make it clear where the console output has come from.