Ensure naming respresents actual object being used

This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the dumb-mistakes-and-gotchas category.

Last Updated: 2024-11-21

This sort function below ran without throwing any exceptions so I hastily assumed it was giving accurate results. (In reality I should have had unit tests - but I was under a lot of pressure to get this code out yesterday)

// Find the best match deal by timestamp
function getMatchingDeal(deals, receivedAt) {
  const leastDistanceInTime = (timestampA, timestampB) => {
    const timeDistanceA = Math.abs(timestampA - receivedAt)
    const timeDistanceB = Math.abs(timestampB - receivedAt)
    // case 1: timestampA is 2017; timestamp B is 2019; received at 2017
    // => timeDistanceA is 0.001; timeDistanceB = 2
    // => we want A to rank before B in sort => must return a negative
    // case 2: swap around A and B; thus timeDistanceA is 2 and b is
    // 0.01
    const difference = timeDistanceA - timeDistanceB
    return difference
  }
  return deals.sort(leastDistanceInTime)[0]
}

But, in fact the results were off. But when I added print logs, I saw that the variables created within the inner function (leastDistanceInTime) were all "NaN".

console.log(timeDistanceA, timeDistanceB, difference)
=> NaN, NaN, NaN

Next I logged the inputs of this inner function leastDistanceInTime:

console.log(timestampA, timestampB)
=> {dealId: 1145451421, timestamp: 1572961078419} {dealId: 372287585, timestamp: 1538483209706}

AHA - these were complex objects, not mere timestamps, as my function signature and code had assumed. My naming was wrong because I had wrongly assumed these were timestamps instead of objects with a timestamp key.

I fixed by rewriting to accept deal objects instead of timestamps:

  const leastDistanceInTime = (dealA, dealB) => {
    const timestampA = dealA.timestamp
    const timestampB = dealB.timestamp
    const timeDistanceA = Math.abs(timestampA - receivedAt)
    const timeDistanceB = Math.abs(timestampB - receivedAt)
    // case 1: timestampA is 2017; timestamp B is 2019; received at 2017
    // => timeDistanceA is 0.001; timeDistanceB = 2
    // => we want A to rank before B in sort => must return a negative
    // case 2: swap around A and B; thus timeDistanceA is 2 and b is
    // 0.01
    const difference = timeDistanceA - timeDistanceB
    if (Number.isNaN(difference)) {
      throw new Error("Cannot sort on NaN")
    }
    return difference
  }
  return deals.sort(leastDistanceInTime)[0]

Lesson learned: