I'm currently working on a project that requires managing metric units correctly. The language used is Java. Also, I have developed an external, open source library, that provides the essential API for managing metric units. It's a very young project so it supports a very small range of metric units (only those needed by the bigger project) but it is sufficient to demonstrate the basic design principles for managing metric units.
You can find the library here.
Let's examine it's usage in a few examples. Let's say we want to keep track of velocity.
Actually, this is already provided in the library.
public final class VelocityUnit {
public final DistanceUnit DISTANCE_UNIT; public final TimeUnit TIME_UNIT; public final double DISTANCE_VALUE; public VelocityUnit(DistanceUnit distance_unit, TimeUnit time_unit, double distance_value) { DISTANCE_UNIT = distance_unit; TIME_UNIT = time_unit; DISTANCE_VALUE = distance_value; } public VelocityUnit convert(DistanceUnit distance_unit, TimeUnit time_unit) { if (distance_unit == DISTANCE_UNIT && TIME_UNIT == time_unit) return this; double newTimeUnitWorthOfCurrentTimeUnit = 1/time_unit.convert(1, TIME_UNIT); double newTotalDistance = DISTANCE_VALUE*newTimeUnitWorthOfCurrentTimeUnit; double newDistanceValue = distance_unit.convert(DISTANCE_UNIT, newTotalDistance); return new VelocityUnit(distance_unit, time_unit, newDistanceValue); } public String getMetricSignature() { return DISTANCE_UNIT.signature + "/" + TIME_UNIT.signature; } public String toString() { return String.format("%.2f%s",DISTANCE_VALUE, getMetricSignature()); } } In the constructor, the programmer passes the metric unit of the distance and the time.
This implementation is quite simple, so it gets the difference in distance as a third parameter
and it assumes the value of time is a single unit of whatever metric is passed.
You can then convert it to use different distance units or time units accordingly.
But that doesn't tell much about differences between two people, what about hiding the
information from the third party developer? Let's see another example now of how the
developers will get what they expect by interacting with a black box class. In the example below,
the developer can put values in whatever metric unit they like and get it back in whatever
format they like. The magic is by telling the class to explicitly work with only one metric unit.The ExampleDistanceCalculation will work with meters while the third party developers can
package com.vaslabs.units.examples; import com.vaslabs.units.DistanceUnit; public class ExampleDistanceCalculation { private final DistanceUnit PREF_DISTANCE_UNIT = DistanceUnit.METERS; private double pointA; private double pointB; public ExampleDistanceCalculation() { } public void setPointA(double value, DistanceUnit distanceUnit) { pointA = DistanceUnit.PREF_DISTANCE_UNIT.convert(distanceUnit, value); } public void setPointB(double value, DistanceUnit distanceUnit) { pointB = DistanceUnit.PREF_DISTANCE_UNIT.convert(distanceUnit, value); } public double getDistance(DistanceUnit distanceUnit) { return distanceUnit.convert(DistanceUnit.PREF_DISTANCE_UNIT, (pointB - pointA)); } }
choose their own metric system. For instance, you can have a sensor and some software that
give you values in centimeters. You can have a class like the above as a middleware
(with CM instead of METERS) and allow all the other developers to work on the metric unit of
their preference. It is also useful when delivering to the userland, as users may have different
preferences on metric units.