發(fā)布于:2021-01-07 17:22:35
0
193
0
單元類型安全性或缺乏安全性可能會帶來實際后果,有時甚至是災難性后果。本文簡要演示了如何使用類型安全的單位和數(shù)量將Manifold框架的擴展和科學庫應用于一般解決方案。
直到1999年涉及NASA的火星氣候軌道器(MCO)事件為止,都沒有其他與單位相關的故障的例子。那些熟悉這個故事的人知道,航天器錯過了它的紅色大目標幾英里,幾公里或與公制相關的東西。實際上,由MCO不幸事故調查委員會領導的 調查 得出的結論是,由于以下原因,該軌道飛行器未實現(xiàn)其標記:MSOP項目軟件接口規(guī)范(SIS)要求的SM_FORCES應用程序代碼的輸出應以牛頓(Ns)的公制單位表示。相反,數(shù)據以英制單位磅-秒(lbf-s)的形式報告。
哎呀!該報告還揭示了一些本來可以防止事故發(fā)生的錯失良機。最終,溝通中的空白被視為失敗點的中心。但是必須懷疑,如果問題出現(xiàn)在軟件中,為什么沒有更多的關注呢?
為了進行哈希運算,一個系統(tǒng)為另一系統(tǒng)提供了牛頓秒(N s)的線性動量,以磅-秒(lbf s)為單位。接收系統(tǒng)的API(由數(shù)據格式組成)無法對類型進行安全地建模。相反,API接受原始數(shù)字數(shù)據。簡化圖:
/**
* 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單位。
通常,如果編譯器可以執(zhí)行否則必須記錄的內容,請支持編譯器!因此,讓我們用類型安全的抽象代替雙精度動量。
/**
* 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。在內部,維類別將數(shù)量保持為SI單位,因此所有物理計算本質上與單位無關。結果,我們現(xiàn)在可以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);
盡管它們用不同的單位定義,但兩個值都是相同的動量。大贏了!但是,我們如何 工作 有動力?使用像這樣的無單位類型的一個優(yōu)點 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的物理尺寸類提供了用于單位轉換和數(shù)據訪問的通用接口。您還可以使用字符串插值輕松格式化輸出:
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社區(qū)版一起使用。
Manifold對物理量的處理還有更多。這里的目的是指出類型安全性對于物理量的API使用的重要性,以及如何將Manifold應用于改進。當然,您可以在代碼中的任何地方使用該框架,其中類型安全的數(shù)量可以改善您的開發(fā)體驗。希望您永遠不必經歷火星氣候軌道器機芯的故障!
作者介紹