What ever happened to numeric classes?

Java Textbooks Keep Undermining Objects

Conrad Weisert
May 5, 2012

NOTE: This article may be reproduced and circulated freely, as long as the copyright credit is included.

Another typical example

I was reading another intermediate-level text book1 about programming in Java, and I came upon this example:

 public static celsiusToFahrenheit(double x)
  {final double MINIMUM_CELSIUS = -273.15;

   if (x < MINIMUM_CELSIUS)
     throw new IllegalArgumentException
               ("Argument " + x + " is too small.");
   return x * (9.0/5.0) + 32;
  }

Questions and answers

Q:   What's wrong with that?
A:   Practically everything!

Q:   Will it work?
A:   Yes.

Q:   Would a typical Java programmer write that?
A:   Probably.

Q:   Would a highly competent C++ programmer write the C++ equivalent?
A:   Certainly not!

Q:   Why?

Obvious flaws

  1. Misplaced constant(s)

    Is this the only place in an application that needs the value of absolute zero? What about a Farentheit to Celsius conversion function? What about Kelvin to either one? What about computations involving temperature? What about input routines that obtain temperature values from an external source?

    It may be unthinkable that physicists will ever know this value more accurately, but it's still bad practice to repeat a shared fundamental constant in multiple functions.

    We don't object to the other constants2, 9.0, 5.0, and 32, because they're derived from the very definitions of the Celsius and Fahrenheit scales and could never change or be known more accurately.

  2. Misplaced error check

    If an application program passes to this function a temperature value less than absolute zero, something has gone terribly wrong before the program ever got to this point. The user program obviously needed to check for illegal values when they were computed or read in. The conversion function is concerned with displaying a value, not with the correctness of data that was produced earlier in an unrelated part of the program.

    Note that the error will be fatal, terminating execution, if a higher-level function doesn't catch it.

  3. Missed opportunity to standardize

    Should we assume that the application using this function represents temperatures internally in degrees Celsius but may want to display them in a report or on the user's screen in degrees Fahrenheit? Perhaps, but wouldn't a program that does physical calculations prefer degrees Kelvin? Shouldn't all the program deisigners and data administrators in an organization agree on one common internal representation?

  4. Amateurish error message

    We've already noted that the actual problem occured earlier in the program. Even so, "too small" and "argument" are awfully vague for some contexts. In a hospital patient monitoring system, 25C would be too small. In a program that computes flow of water through a pipeline, -10C would be too small. "Absolute zero" is much more informative.

    Furthermore the user to whom the message is directed may have no idea where the message originated. The user sees "argument" but isn't told what function the illegal value was discovered in. We may hope that a higher-level function will catch the exception and issue a more specific message, but all error messages should identify the program component issuing them.

Obvious solution

Every one of the above flaws goes away as soon as the program designer recognizes something that ought to be the first thing that an experienced object-oriented programmer would think of:

We need a Temperature class from which our programs can instantiate Temperature objects.

Then:

Isn't that what the object paradigm was supposed to do for us when it was introduced? Doesn't Java claim to support the object paradigm?

Further discussion

Other web articles

Book


1—I don't need to identify the 2012 Data Structures book, since the issues are common to many books on Java programming by many authors.
2—We assume a smart compiler knows to obtain the conversion constant 1.8 at compile time and not perform division during execution.
3—Many programs won't need to. They can rely on the toString() method (Java) or the output stream insertion operator (C++) to display the value in an understandable form, possibly including the units name.

Last modified May 6, 2012

Return to IDI home page
Technical articles