Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[science-iwg] Units of Measurement with stronger type-safety

Dear All,

Thanks everyone who was interested to learn about JSR 363 in my presentations at the Science F2F in Ludwigsburg today.

I'll upload the slides to Slideshare and provide the link once it's uploaded. For STEM I want to confirm, if e.g. Kun at IBM has the PDF somewhere or it already can be found in the Wiki and tell you about it.

As for the question about an even stronger (compile-time) unit type-safety.
There are at least two approaches to that. Both require constraints to the "universe" one deals with, e.g. new or unknown units and quantities may be hard to deal with or impossible. Which is why the RI of JSR 363 and most prior implementations of similar APIs made compromises between type-safety and extensible.

Let's not forget, e.g. the OSGi Measurement is restricted to a certain number of SI units and only works at runtime. As do many similar solutions for Java e.g. UCAR Units derived from the first approach in the JCP JSR 108.

An approach to this can be found in the JSR 363 API JUnit tests for quantities:
https://github.com/unitsofmeasurement/unit-api/tree/master/src/test/java/javax/measure/test/quantity
Kindly contributed by Paul Morrison who also retired from IBM (a bit earlier than Don Eigler, Paul invented the concept of Flow-Based Programming in the mid 70s, when Oracle, Apple or Microsoft had just been founded or were about to;-D https://en.wikipedia.org/wiki/Flow-based_programming#History

The test classes are only a small set, but e.g. 
public AreaQuantity multiply(DistanceQuantity d1) {
or
public VolumeQuantity multiply(AreaQuantity a1) {
show how a strict enforcement of multiply or divide methods could work.

The other default methods like multiply(Quantity) 
are ignored there btw, so don't take it as a fully blown example.

SI Units (the si-quantity module only defines sub-types of Quantity) also has similar types here, but without the specialized methods:
https://github.com/unitsofmeasurement/si-units/tree/master/units/src/main/java/si/uom/impl/quantity

Either for a known set of quantities, e.g. certain SI types or a special field (Science, IoT,...) such special implementation module could help increase type-safety.
Beyond that, we hope maybe Java 10 or 11 (with efforts like Project Valhalla, etc. driven by Brian Goetz) could help improve some of that. I had a conversation with Microsoft F# Unit Mastermind Andrew Kennedy (based in Cambridge) about it when JSR 275 was stopped. And he said, a few aspects like reified types (see http://stackoverflow.com/questions/1927789/why-should-i-care-that-java-doesnt-have-reified-generics) were not available in Java while e.g. C# or F# offers that. Some of these language features discussed by the Java architects may help projects like Units of Measurement, but that would be up to a new JSR in the future.

A vague glimpse was offered by JSR 308, Java Type Annotations.
Unfortunately even Brian Goetz said, Oracle does not use it in Java SE 8. Nor do other projects like NetBeans. And JSR 305 standard Annotations were not adjusted to use it either, so it remains a helper feature for documentation purposes or support by certain IDEs like Eclipse or IntelliJ, not a strict compiler enforcement with @NonNull or @Nullable, etc.

The Checkers Framework:
http://types.cs.washington.edu/checker-framework/current/checker-framework-manual.pdf
offers annotations for many cases, but to enable a particular one you so far need to run Javac in ways like

javac -processor org.checkerframework.checker.units.UnitsChecker \

    -Aunits=myproject.qual.MyUnit,myproject.qual.MyOtherUnit MyFile.java  

So many "fancy" build scripts seem necessary at this point, if you wanted to enforce a new checker or introduce say units for a new domain or system.
When you defined and called all those checkers correctly, it'll something like: 
static final @m int m = new @m Integer(1);
static final @s int s = new @s Integer(1);

void demo() {
 @m int len = 5 * m;
 @s double time = 1 * s;

 @mPERs double mps = len / time;
 // Fails
 // @kmPERh double kph = len / time;
}

Similar to F# JSR 308 only provides compile-time type-safety, so at run-time there is currently no way to introspect or otherwise use that information. 

Combining these kinds of annotations with run-time equivalents like Bean Validation in its 2.0 version is an idea to get the best of both worlds. We might do something similar with JSR 363 but the Checkers Framework is still pretty academic and experimental. No proper vendor or tool support at this point, which is why it's only for special cases right now I'm afraid, but we're open to explore it either at Eclipse UOMo or elsewhere, if there was enough interest.

Enjoy the main ECE,

Werner 


Back to the top