发布于:2021-01-07 17:22:35
0
183
0
单元类型安全性或缺乏安全性可能会带来实际后果,有时甚至是灾难性后果。本文简要演示了如何使用类型安全的单位和数量将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应用于改进。当然,您可以在代码中的任何地方使用该框架,其中类型安全的数量可以改善您的开发体验。希望您永远不必经历火星气候轨道器机芯的故障!
作者介绍