發(fā)布于:2021-01-07 17:22:35
0
193
0
單元類型安全性或缺乏安全性可能會帶來實(shí)際后果,有時甚至是災(zāi)難性后果。本文簡要演示了如何使用類型安全的單位和數(shù)量將Manifold框架的擴(kuò)展和科學(xué)庫應(yīng)用于一般解決方案。
直到1999年涉及NASA的火星氣候軌道器(MCO)事件為止,都沒有其他與單位相關(guān)的故障的例子。那些熟悉這個故事的人知道,航天器錯過了它的紅色大目標(biāo)幾英里,幾公里或與公制相關(guān)的東西。實(shí)際上,由MCO不幸事故調(diào)查委員會領(lǐng)導(dǎo)的 調(diào)查 得出的結(jié)論是,由于以下原因,該軌道飛行器未實(shí)現(xiàn)其標(biāo)記:MSOP項(xiàng)目軟件接口規(guī)范(SIS)要求的SM_FORCES應(yīng)用程序代碼的輸出應(yīng)以牛頓(Ns)的公制單位表示。相反,數(shù)據(jù)以英制單位磅-秒(lbf-s)的形式報(bào)告。
哎呀!該報(bào)告還揭示了一些本來可以防止事故發(fā)生的錯失良機(jī)。最終,溝通中的空白被視為失敗點(diǎn)的中心。但是必須懷疑,如果問題出現(xiàn)在軟件中,為什么沒有更多的關(guān)注呢?
為了進(jìn)行哈希運(yùn)算,一個系統(tǒng)為另一系統(tǒng)提供了牛頓秒(N s)的線性動量,以磅-秒(lbf s)為單位。接收系統(tǒng)的API(由數(shù)據(jù)格式組成)無法對類型進(jìn)行安全地建模。相反,API接受原始數(shù)字?jǐn)?shù)據(jù)。簡化圖:
/**
* 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
}
也許這是真正的悲???當(dāng)然,文檔指定了SI單位,但是文檔沒有編譯代碼。Javac可以確保調(diào)用者通過兩次加倍,但是除非知道,否則它不知道線性動量或SI單位。
通常,如果編譯器可以執(zhí)行否則必須記錄的內(nèi)容,請支持編譯器!因此,讓我們用類型安全的抽象代替雙精度動量。
/**
* 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庫,該庫將物理尺寸建模為類型安全的單位和數(shù)量的類庫。的數(shù)量以 Momentum 表示 MomentumUnit。在內(nèi)部,維類別將數(shù)量保持為SI單位,因此所有物理計(jì)算本質(zhì)上與單位無關(guān)。結(jié)果,我們現(xiàn)在可以performManeuver() 使用我們選擇的單位進(jìn)行調(diào)用 :
Momentum momentum =
new
Momentum(
50
, MomentumUnit.POUND_SECONDS);
orbiter.performManeuver(momentum);
// or
Momentum momentum =
new
Momentum(
222.41108075988
, MomentumUnit.NEWTON_SECONDS);
orbiter.performManeuver(momentum);
盡管它們用不同的單位定義,但兩個值都是相同的動量。大贏了!但是,我們?nèi)绾?工作 有動力?使用像這樣的無單位類型的一個優(yōu)點(diǎn) double 是簡單。流形使用類型安全的單位表達(dá)式維護(hù)和擴(kuò)展了這種便利 性,這使我們可以像上面這樣重寫代碼:
Momentum momentum =
50
lbf s;
orbiter.performManeuver(momentum);
// or
Momentum momentum =
222.41108075988
N s;
orbiter.performManeuver(momentum);
此外,借助Manifold提供的 運(yùn)算符重載, 我們可以在整個物理量范圍內(nèi)使用類型安全算術(shù)。例如,科學(xué)圖書館將的乘積Force 和 定義 Time 為 Momentum。
Momentum momentum =
5
lbf *
10
s;
// or
Momentum momentum =
22.241108075988
N *
10
s;
平等和關(guān)系表達(dá)也非常簡潔:
out.println(
50
lbf s >
222
N s);
// true
最終,物理計(jì)算導(dǎo)致與外界的交流。無論是在屏幕上顯示結(jié)果還是與航天器進(jìn)行交互,該軟件都可以提供特定的值。Manifold的物理尺寸類提供了用于單位轉(zhuǎn)換和數(shù)據(jù)訪問的通用接口。您還可以使用字符串插值輕松格式化輸出:
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插件為 框架的所有功能提供了全面的支持。它可以免費(fèi)與IDEA社區(qū)版一起使用。
Manifold對物理量的處理還有更多。這里的目的是指出類型安全性對于物理量的API使用的重要性,以及如何將Manifold應(yīng)用于改進(jìn)。當(dāng)然,您可以在代碼中的任何地方使用該框架,其中類型安全的數(shù)量可以改善您的開發(fā)體驗(yàn)。希望您永遠(yuǎn)不必經(jīng)歷火星氣候軌道器機(jī)芯的故障!
作者介紹