From: Noah Roberts (roberts.noah_at_[hidden])
Date: 2007-01-22 16:42:55
Michael Fawcett wrote:
> On 1/22/07, Noah Roberts <roberts.noah_at_[hidden]> wrote:
>> Yes, it does sound familiar but it is just a common way of writing bad
>> code. In any given project your base unit should be the same for any
>> given function. Anything that accepts a length should accept either
>> feet or meters, and a mix of both in your project is a Really Bad Thing.
> And how can you enforce this? Take for instance a database that holds
> radar characteristics. The units that pilots use are always feet (for
> altitude) and nautical miles (for distances). Ground elevation data
> is stored as DTED files which are in meters, where the distance
> between elevation postings is in latitude/longitude. Now convert an
> AGL (Above Ground Level) altitude to an MSL (Mean Sea Level) altitude.
> Wait...that requires adding feet (the altitude of the aircraft is
> always given in feet) to the ground elevation at that particular
> latitude/longitude (but wait, pilots measure distance in nautical
> miles, plus the ground elevation is given in meters!). These are all
> just errors waiting to happen that a good units library will catch at
Well, I guess now that you're more interested in getting defensive than
talking about this so this is likely to become non-productive.
What you are talking about above is exactly what I mean. Those are
*interface* issues. Doing all the conversions through casts, which will
be converting between these units in-place, is less efficient. A good
units library would convert all of the above to a base, meters usually,
instantly and provide only that value to the underlying equations while
reporting values using the units logical for the user for that use.
There is no reason why the different calculations you speak of should
actually do their calculations in different "systems".
To make this clearer lets look at your above equation: MSLm = AGLft +
GLm. Lets also assume you're doing this about a 1,000,000 times in some
internal calculation that will result in a value reported in miles.
You're answer seems to be something that resolves to:
MSLAm = (AGL ft * ft/meter) + GLm
Sure, the ft/meter conversion factor is statically calculated/provided
and the developer doesn't see the equation like that but you still have
an unnecessary conversion worked in. This isn't 0 runtime overhead. I
do like the fact that you have a cast required to advertise this fact.
The alternative approach would be more like:
MSLAm = AGLm + GLm.
The problem here is that AGL makes less sense in meters for the user.
Let's further say that AGL might be measured in any given unit for some
user (This is _very_ common in the field I'm working in). Now we need
some way of getting an AGL value from the user in an arbitrary unit but
making sure calculations don't keep converting it and adding overhead we
don't want or need. The best way to do this is to have the AGL value
convert when the user enters it or when the calculation performed to
find it is assigned to the value...and only at those times. Then your
whole underlying functions would all use a particular "system" that
these runtime united values convert to.
Your unit setup could be used in the underlying computations to enforce
a given set of unit->dimension pairs but there is still most definitely
a need to provide an easy to use runtime equivalent. Without such the
unit library is not as useful as it could be and doesn't answer what
seems to me as the more general and practical use. I also think it
should be easy for the developer to write the equations in one set of
units but have the code calculate in the base units without adding
conversion overhead. Hence my question about qty<length> qt = 9.3 * psi
and I have to say I really like that syntax that you've used.
I'm not saying this library is no good or not useful. You've done good
work and I think you have a better solution than Little's attempt. What
I'm saying is that in order to answer the general case it needs to
answer runtime units either directly or by thoroughly documenting how it
could be done.