TPP Topic 38: Programming by Coincidence

steadbytes profile image Ben Steadman ・3 min read

This post originally appeared on steadbytes.com

See the first post in The Pragmatic Programmer 20th Anniversary Edition series for an introduction.

Exercise 25

A data feed from a vendor gives you an array of tuples representing key-value pairs. The key of DepositAccount will hold a string of the account number in the corresponding value:

 {:DepositAccount, "564-904-143-00"}

It worked perfectly in test on the 4-core developer laptops and on the 12-core build machine, but on the production servers running in containers, you keep getting the wrong account numbers. What’s going on?

Assuming that the key-value pairs are read into a hash map (or similar) data structure, for example in Clojure:

user=> (into {} [[:DepositAccount "564-904-143-00"] [:OtherKey "Other Value"]])
{:DepositAccount "564-904-143-00", :OtherKey "Other Value"}

Then it is possible that the :DepositAccount is being overwritten due to multiple occurrences of a :DepositAccount tuple in the input array. An array of tuples will not enforce uniqueness of the keys, whereas a hash map does. Most hash map implementations will update the value of an existing key when a duplicate insert is performed:

user=> (into {:DepositAccount "111-111-111-11"} [[:DepositAccount "564-904-143-00"]])
{:DepositAccount "564-904-143-00"}

The fact that it worked on laptops and the build machine is a coincidence that (I think) the authors included to lure the reader into a trap!

Exercise 26

You’re coding an autodialer for voice alerts, and have to manage a database of contact information. The ITU specifies that phone numbers should be no longer than 15 digits, so you store the contact’s phone number in a numeric field guaranteed to hold at least 15 digits. You’ve tested in thoroughly throughout North America and everything seems fine, but suddenly you’re getting a rash of complaints from other parts of the world. Why?

Again, the authors are throwing in additional information to demonstrate the trap of coincidence. The ITU's 15 digit length limit is not the cause of the problem, it is the use of a numeric field to store phone numbers in the database. The ITU E.164 standard specifies that the international call format start with a + sign. Characters such as * or leading zeros are also used in some areas. None of these can be stored in a numeric field.

Exercise 27

You have written an app that scales up common recipes for a cruise ship dining room that seats 5,000. But you’re getting complaints that the conversions aren’t precise. You check, and the code uses the conversion formula of 16 cups to a gallon. That’s right, isn’t it?

The "cup" measurement has a surprising number of interpretations therefore the conversion stated in the exercise is dependent on both location and custom. From Wikipedia:

  • United States

    • Legal cup = 240 ml
    • Customary cup = 1/2 of a liquid pint ~= 237 ml
  • Commonwealth of Nations

    • Metric cup = 250 ml
    • Canadian cup = 8 imperial fluid ounces ~= 227 ml
    • United Kingdom = 10 imperial fluid ounces ~= 284 ml
  • International

    • Latin American cup = 200 ml or 250 ml or either US cups
    • Japanese cup = 200 ml (legally) or ~180mL (traditionally)

In this case, the programmer made the assumption that the app will only be used within the United States, converting between customary cups and liquid gallons.


Editor guide