What sucks about this code?
const success = myCache.mset([
{key: "myKey", val: obj, ttl: 10000},
{key: "myKey2", val: obj2},
]);
It's not clear at all clear if the ttl
is 10,000 milliseconds, seconds, or something else. Just glancing at this code (and knowing that JavaScript setTimeout()
uses milliseconds), you might be tempted to think it's in milliseconds. Wrong! It's in seconds!
This snippet is example code from the README of node-cache. This type of unclear code is really prevalent, so I'm not trying to pick on them in particular. Fortunately, the README does say that it's in seconds, but you have to RTFM to be sure, and who's got time for that?
Wouldn't it be nice if the ttl
property were named ttlSeconds
? Then it's instantly clear what it means to whoever is reading the code.
Or maybe there's an even better solution.
Datetimes
It's also pretty common for datetimes to be represented as an integer number of milliseconds (or seconds) since the Unix epoch ( 00:00:00 UTC on 1 January 1970). For example:
const myBirthday = 700876800000;
This sucks too. You might recognize this as very likely being a number of milliseconds since the Unix epoch, but you have no idea what date this represents.
How about this instead:
const myBirthday = new Date('1992-03-18T00:00:00.000Z');
Now whoever's reading this code knows exactly what date it represents, and code that accesses myBirthday
does too. Surrounding code doesn't need tribal knowledge about whether this number
is a number of seconds or milliseconds. It's a Date
, and has a very specific meaning.
TimeSpans
Jumping back to TTL
(time to live) again. A TTL is not a specific date and time, but a length of time (one second, one year, etc), so we can't use Date
to represent it.
Naming your TTL property ttlSeconds
for clarity is a fine solution in a lot of cases, but what if there were a datatype similar to Date
for this?
Some languages actually have such features built in. JavaScript doesn't, but we can use a package like timespan.
import timespan from 'timespan';
const ttl = timespan.fromSeconds(50);
console.log(ttl.totalMilliseconds()); // 50000
console.log(ttl.totalSeconds()); // 50
console.log(ttl.totalMinutes()); // 0.8333333333333334
You can specify your TTL in whatever units you want, and the code you pass your TTL to can read it in whatever units it wants. You don't have to agree on units at all.
If only NASA used constructs like this, they may have been able to save a few bucks.
Conclusion
Just a short one I wanted to get off my chest here. Many bugs have their roots in mix-ups about what units are being used. Fortunately we have some tools at our disposal to mitigate these sort of risks. I wish I saw them used more often!