Java的类型安全的单位表达式

发布于:2021-01-07 17:22:35

0

180

0

Java 单元类型 安全性 单位表达式

单元类型安全性或缺乏安全性可能会带来实际后果,有时甚至是灾难性后果。本文简要演示了如何使用类型安全的单位和数量将Manifold框架的扩展和科学库应用于一般解决方案。

直到1999年涉及NASA的火星气候轨道器(MCO)事件为止,都没有其他与单位相关的故障的例子。那些熟悉这个故事的人知道,航天器错过了它的红色大目标几英里,几公里或与公制相关的东西。实际上,由MCO不幸事故调查委员会领导的 调查 得出的结论是,由于以下原因,该轨道飞行器未实现其标记:MSOP项目软件接口规范(SIS)要求的SM_FORCES应用程序代码的输出应以牛顿(Ns)的公制单位表示。相反,数据以英制单位磅-秒(lbf-s)的形式报告。

哎呀!该报告还揭示了一些本来可以防止事故发生的错失良机。最终,沟通中的空白被视为失败点的中心。但是必须怀疑,如果问题出现在软件中,为什么没有更多的关注呢?

为了进行哈希运算,一个系统为另一系统提供了牛顿秒(N s)的线性动量,以磅-秒(lbf s)为单位。接收系统的API(由数据格式组成)无法对类型进行安全地建模。相反,API接受原始数字数据。简化图:

/**

* Position the orbiter for optimal trajectory. Don't mess this up!

*

* @param momentum Amount of thrust to apply. And uh, one more thing, use SI units here.

*/

public void performManeuver(double momentum) {

// fire thrusters and stuff

}

也许这是真正的悲剧?当然,文档指定了SI单位,但是文档没有编译代码。Javac可以确保调用者通过两次加倍,但是除非知道,否则它不知道线性动量或SI单位。

通常,如果编译器可以执行否则必须记录的内容,请支持编译器!因此,让我们用类型安全的抽象代替双精度动量。

/**

* Position the orbiter for optimal trajectory. You *can't* mess this up!

*

* @param momentum Amount of thrust to use.

*/

public void performManeuver(Momentum momentum) {

// fire thrusters and stuff

}

该 Momentum 类型取自Manifold框架的 Science库,该库将物理尺寸建模为类型安全的单位和数量的类库。的数量以 Momentum 表示 MomentumUnit。在内部,维类别将数量保持为SI单位,因此所有物理计算本质上与单位无关。结果,我们现在可以performManeuver() 使用我们选择的单位进行调用 :

Momentum momentum = new Momentum(50, MomentumUnit.POUND_SECONDS);

orbiter.performManeuver(momentum);

// or

Momentum momentum = new Momentum(222.41108075988, MomentumUnit.NEWTON_SECONDS);

orbiter.performManeuver(momentum);

尽管它们用不同的单位定义,但两个值都是相同的动量。大赢了!但是,我们如何 工作 有动力?使用像这样的无单位类型的一个优点 double 是简单。流形使用类型安全的单位表达式维护和扩展了这种便利 性,这使我们可以像上面这样重写代码:

Momentum momentum = 50 lbf s;

orbiter.performManeuver(momentum);

// or

Momentum momentum = 222.41108075988 N s;

orbiter.performManeuver(momentum);

此外,借助Manifold提供的 运算符重载, 我们可以在整个物理量范围内使用类型安全算术。例如,科学图书馆将的乘积Force 和 定义 Time 为 Momentum。

Momentum momentum = 5 lbf * 10 s;

// or

Momentum momentum = 22.241108075988 N * 10 s;

平等和关系表达也非常简洁:

out.println(50 lbf s > 222 N s); // true

最终,物理计算导致与外界的交流。无论是在屏幕上显示结果还是与航天器进行交互,该软件都可以提供特定的值。Manifold的物理尺寸类提供了用于单位转换和数据访问的通用接口。您还可以使用字符串插值轻松格式化输出:

Momentum momentum = 222.41108075988 N s;

Time duration = 10 s;

Force force = momentum / duration;

out.println("$duration burn at $force");

out.println("$duration burn at ${force.to(lbf)}");

注意,用于IntelliJ IDEA的 Manifold插件为 框架的所有功能提供了全面的支持。它可以免费与IDEA社区版一起使用。

Manifold对物理量的处理还有更多。这里的目的是指出类型安全性对于物理量的API使用的重要性,以及如何将Manifold应用于改进。当然,您可以在代码中的任何地方使用该框架,其中类型安全的数量可以改善您的开发体验。希望您永远不必经历火星气候轨道器机芯的故障!