Rates
TJLMOM: Dealing with “rates”
I’ve seen a lot of code that handles “rates”[1] in such a way that if in some weird circumstance the denominator; we’ll call it “D”, here; one of 3 things happens:
- the program either just crashes outright because of a
DivideByZero
error - the math runtime catches this and the display is
NaN things/time
- the math runtime doesn’t catch it, but you get some other weird output
None of these are user friendly, and all of them are, IMO, the wrong way to handle it.
When encountering these issues, most developers will check D
to see if it’s zero and
handle that, since it’s a DivideByZero
issue, so we want to see if the thing that could
be zero is or isn’t, right? I maintain this is the wrong approach.
Normal Human Program
For this type of application, I’m talking about a run of the mill application that isn’t specifically for math or science (those are treated below). These are apps where mathematical or program purity isn’t tantamount; you just want to show something to the user that isn’t incorrect, or weird. UX is very important here.
Given that, my preferred method here is to not check D
, but rather check the numerator
(N
). Why? If you have zero “things / time unit”, it doesn’t matter what the time unit
actually is, you have zero things per that unit. So just return 0. If D
is zero but
N
is not, you still have SOME rate. You just don’t know what it is so returning 0 isn’t
quite right, and you’re masking some other issue in your program.
Either data isn’t getting to your function correctly or D
is actually zero; something’s
happened that the time (et. al.) quantum couldn’t be measured.
For UX, I’d return some sentinel value to indicate to the caller that the rate couldn’t be
calculated; have the display show “Unknown” or “N/A” or “Not Yet Ready” OR just not show
it at all! Set its CSS display: none
, for example.
Scientific/Math Program
For more rigorous mathematical apps, you can do the same thing as above, but in general
these types of apps NEVER expect D
to be zero, so something is definitely wrong with
your program. If your program reaches this “impossible” state, it’s often best to just
error and stop; you have bad data, or bad code, or both. Trying to valiantly continue on
“defensively” just leads to a crippled program, and a crippled program does WAY MORE
DAMAGE than a dead one, as a rule.
Another option would be to have the DISPLAY show that in huge red letters that THIS CALCULATION IS INVALID AND DON’T RELY ON IT.
TL;DR
Check the Numerator, not the Denominator, and handle that if it’s 0. Either use whatever logging/alerting system you have in place to let you know you have a problem so you can fix it, or error/exit if this “should never happen”.
But that’s like, just my opinion, man.
[1] Any time you have “some amount of things / some metric”. This metric is usually some sort of time quantum, so I’m talking about “bits/second”, “events/day”, type of thing. Doesn’t have to be time, but usually is.