1

I am dealing with a clinical application that uses both base and derived units of measure.

Currently, we store them as a text field in a separate column in each table that requires units. However, I am planning to redesign the database so that we have all the units of measurement in one table and use foreign keys in the table that require UOMs.

This kind of solves the problem at the database level. However, in the Java code, we use String to store the units like so:

class Foo {
    double amount;
    String unit;
}

I imagine using String to store units could become a nightmare going forward. I need suggestions on a clean way to manage units of measure so that I can, say, compare two Foos or add two Foos by making sure they have the same units, etc.

michal
  • 67
  • 7
user330973
  • 823
  • 2
  • 9
  • 16

3 Answers3

1

I think you should have a better abstraction than a String; it's little more than a primitive.

I'd write a Units class that would parse and store those Strings from the database and allow you to compare them easily.

public class Units {
    private final String name;

    // constructors, equals, hashCode, toString and other operations here
}

It might also be useful to have categories of Units. (You can measure pressure a lot of ways.) British and international units can describe the same thing.

You might also have categories based on physical quantities (e.g. force, mass, charge, time, etc.)

duffymo
  • 305,152
  • 44
  • 369
  • 561
  • This doesn't solve how to keep the system consistent at the database level. It is also probably unnecessary abstraction. More abstraction means more complexity, and more complexity means more trouble and more bugs. Unless there is a compelling case where it is important to know if it's an American unit or a British unit or a French unit, it's likely more trouble than it's worth. – PlexQ Mar 22 '12 at 23:36
  • I disagree. Better abstraction is not an unnecessary trouble. And how is your Units enum an improvement? There aren't French and American units, as any scientist would know, but there are metric and British (e.g. kg versus lbm). Will you have pressure, time, and every other type of unit there is in your enum? That seems a worse idea to me. The OP explicitly asked about conversions. Your enum doesn't help at all. – duffymo Mar 22 '12 at 23:43
  • Sorry, but you are incorrect. An American Gallon and a British gallon are not the same. Metric units are held by a set of standard units held in Paris, so French seems an appropriate moniker as any. – PlexQ Mar 25 '12 at 05:41
  • I'm also missing where the question asked about conversion. "Better" is a relative thing, and too much abstract will always end up causing trouble. It disobeys basic good practice, which states that a codebase should only contain as much code as is in use. Providing for a situation that hasn't arisen is writing code that may never be used. Simple is better, at least in most eyes, and having a new class and therefore a new table is not more simple, it's less. – PlexQ Mar 25 '12 at 05:50
  • The question might not have explicitly talked about conversions, but if you know how these things go you'll realize that it'll be necessary at some point along the way. I agree, an abstraction that goes beyond understanding is worthless, but we aren't there with what I'm suggesting. We'll disagree here. – duffymo Mar 25 '12 at 11:33
  • You've got me with the American and British gallons. But international != French, even if they keep the standards in Paris. It used to be a meter stick, but now length is defined in terms of the wavelength of light emitted by krypton-86. That's true everywhere, even outside Paris. – duffymo Mar 25 '12 at 11:35
  • Enum is the right way to do this. The problem is that you can't extend Enums, because it would be nice to have Unit as a base and then WeightUnits, TimeUnits, etc. – Rob May 19 '13 at 22:35
0

I would recommend the JScience library which is an implementation of JSR 275.

According to this post it can do things such as:

UnitConverter toKilometers = MILE.getConverterTo(KILOMETER);
double km = toKilometers.convert(Measure.valueOf(100, MILE).doubleValue(MILE));

If you do not want to add the new library there is nothing inherently wrong with using String objects within a class. If you are never going to perform calculations on them there is even less to worry about. However, you will most likely need to use Doubles as that will be the way to get "correct" translations to and from the metric system.

Community
  • 1
  • 1
Woot4Moo
  • 23,987
  • 16
  • 94
  • 151
  • I would certainly consider JScience for conversion etc, However, I would also need to map every UOM value that I have stored in the database to JScience class. I'm wondering if its worth bringing in a new library or I can solve the problem with a home grown solution – user330973 Mar 22 '12 at 23:55
  • I've been looking at the various JSRs and unit libraries all day. None of them are great for serialization, which is really where the library is needed. I don't know what possessed the creation of all these code not using enums for the units, butt thats exactly what happened. – Brill Pappin May 09 '17 at 17:21
0

Conversion issues aside, enums are a fair way to solve this:

enum Units {
  Kilograms,Pounds,Stone
}

class Foo {
  double amount;
  Units units;
}

Most ORMs will convert the enum to a String. Your Java is type safe, and you can make the database consistent by using a simple check constraint. Pretty much all RDBMSes support them.

If you need to get more sophisticated, there are ways, but often more complicated just means more trouble not necessarily more better.

PlexQ
  • 3,154
  • 2
  • 21
  • 26
  • My first choice was enums as well, but I was concerned about integrity issues when we need to add more units in the future. – user330973 Mar 22 '12 at 23:47
  • Well, the other solution doesn't provide any improvement to integrity either. A new random unit could have been inserted into that table as much as an invalid string could have been inserted as a row in the main one. You'll still need a check constraint to ensure consistency in either case. – PlexQ Mar 25 '12 at 05:50
  • Integrity of the database is the concern of the schema designer. And no schema will prevent you from entering incorrect units. – duffymo Mar 25 '12 at 11:36