論文翻譯:A PROCEDURE FOR DESIGNING ABSTRACT INTERFACES FOR DEVICE INTERFACE MODULES
個人翻譯學習記錄,如有錯漏,務必指出
更推薦英文原版
英文原版可從該網址下載 https://dl.acm.org
A Procedure For Designing abstact interfaces for device interface Modules
by Kathryn Heninger Britton, R. Alan Parker, David L. Paranas
Code 7590, Naval Research Laboratory, Washington, D.D. 20375
摘要
這篇論文描述了抽象介面原則並展示了這個原則如何應用於裝置介面模組的設計中。這個原則的目的是通過促進軟體的對可替換硬體介面的適應性而降低嵌入式實時軟體的維護成本。這個原則已被應用到Naval Research Laboratory (NRL)對A-7飛機的飛行軟體的重新設計。本論文探討基於抽象介面原則的設計方法,並展示在重新設計A-7中碰到的有趣問題的解決方案。A-7裝置介面的規格文件已給出;這個文件為本文討論的設計方法提供了一個完整的例子。
關鍵詞:軟體設計技術,模組規格,抽象介面,軟體維護成本削減,資訊隱藏模組,實時軟體,嵌入式軟體,裝置介面模組,虛擬裝置。
Ⅰ. 介紹
背景
在NRL,我們正在重新設計A-7飛機的飛行軟體,以此來評估新軟體工程技術對嵌入式軟體設計的適用性。(一個嵌入式軟體系統是巨型硬體或軟體系統的一個獨立元件。更多完整的描述見Parans關於抽象介面的論文。[5] )我們打算為包括好的結構軟體和有益的文件提供完善的例子,以此來讓其他設計者應用我們發現有用的技術。更多資訊見Heninger關於專案的論文。 [1]
多數嵌入式實時軟體的複雜度都關乎控制特定目標的硬體裝置。很多設計者通過在軟體裝置介面模組中隔離裝置特徵以降低複雜度,透過這一做法,可以讓程式在不需要了解裝置細節的情況下編寫。儘管這些裝置介面模組一般來說確實讓軟體的其他部分更簡單了,但是他們的介面通常是臨時設計的(their interfaces are usually hte result of an ad hoc design process,)並且沒法完全地封裝裝置細節。結果就是,裝置改動導致整個軟體的改動,而不是僅僅在裝置介面模組。我們基於設計A-7裝置介面模組的介面的抽象介面原則 [5] 開發了一個系統化的procedure。我們相信最終的介面可以成功的封裝裝置依賴,因此替換或修改一個裝置僅僅要求裝置介面模組的改動,而不是軟體的其餘部分。這篇論文解釋和說明了這個procedure。
內容
儘管本文描述的潛在的(underlying)原則不是新的,但設計procedure是新的,而且和當下的實踐是有巨大的偏差的。結果就是,我們希望這篇論文更能引起實踐軟體工程師的興趣,而非關注時下熱點研究人員。
第二部分討論裝置介面模組和設計者試圖使用這些模組達成的目標。儘管這個材料(material)已經不新了,但這能夠引出這篇文章的其餘部分。
第三部分定義了本文剩餘部分使用的條款(terms)。儘管這些定義不是新的,他們還並未廣為人知。對procedure的展示依賴於對這些條款(terms)的精確使用。
第四部分描述和說明了系統化的procedure。說明展示了在開發A-7裝置介面模組之一的一個抽象介面時的幾個階段。
即便是系統化的procedure也沒有辦法讓軟體設計變得更加簡單。在A-7設計中,我們經常需要在靈活性和執行時效率兩者間做出艱難的權衡。回想起來(In retrospect),我們發現了幾個反覆出現的問題。這些問題沒有逼得我們改變基礎procedure,但是他們確實讓我們在裝置介面設計上增加了額外的指導原則。第五部分描述了部分困難,和最終得出的指導原則。
Ⅱ. 目標(Objectives)
嵌入式實時軟體系統經常有複雜且限制性的外部介面。因為嵌入式軟體通常是一個大得多的系統的一個小組成部分,所以介面很少為了軟體開發者的便利而修改。A-7航空電子軟體就是一個典型:有21個裝置連線到計算機上,包括感測器,顯示器和計算機控制的裝備。那些隨意的介面特徵,比如值編碼格式和timing怪癖,都有可能在開發過程中或者在初始部署之後發生改動。缺陷(inadquacies)可能會在裝置規格中出現;supplier可能會deliver一個被認為是足夠的裝置,儘管它實際上並不滿足規格;一個裝置可能被上位替代品代替;又或者新的連線要新增到裝置之間。
嵌入式軟體總是有著普遍而不受人待見的特性——一個在裝置介面上的改動居然輻射到了整個軟體,而這正是因為程式構建於隨意的介面細節之上。如果一個介面改動,那麼依賴這個介面的程式都會變得無效。因為這些依賴關係很少被明確的記錄,介面改動經常有著令人驚訝的後果。
為了避免這些問題,通常會將軟體劃分為兩組元件:1)包含了裝置依賴程式碼的裝置介面模組;2)裝置無關的剩下的部分,包括使用者程式,這麼稱呼是因為他們使用裝置介面模組。裝置介面模組提供虛擬裝置,軟體中部分實現的類裝置能力。比如說,A-7系統中的一個虛擬高度表。虛擬高度表返回一個型別為range的值,而不是從實際感測器上讀取的bitstring。原始資料被在高度裝置介面模組中讀取,縮放,修正,再篩選。這個軟體介面在圖1中展示。
裝置介面模組的設計有如下的目標:
-
限制改動:設計裝置介面模組是資訊隱藏 [6] 的一種特殊情況;硬體介面細節應該隱藏在這些模組裡,這樣當裝置被修改或替換時才能將改動約束在這些模組中。限制改動中的問題由以下三種錯誤造成。
-
裝置介面模組允許使用者程式發掘/窺探到特定裝置的特殊特徵,這樣當裝置替換時使用者程式就必須改動了。
-
虛擬裝置缺少必要的功能,因此使用者程式必須直接訪問實際的裝置;同樣當裝置替換時使用者程式也必須改動了。
-
並不依賴裝置的程式卻被放入了裝置介面模組。結果就是,需求修改時裝置介面模組可能會改動,即使裝置根本沒有改動。並且,這樣的模組在裝置改動時更難修改。
總結,裝置介面模組理想情況下應
-
是裝置改動時,唯一需要修改的模組
-
是裝置不改動時,沒有必要改動的模組
-
是相對較小的、直接的(straightforward)以便改動
-
-
簡化軟體剩餘部分:嵌入式軟體通常難以理解因為它的正確性依賴於隨意的介面細節。如果這些細節被限制在裝置介面模組內,使用者程式就會更簡單,更輕鬆得正確的編寫,也更容易理解,相比於直接使用硬體介面的話。
-
強制規範使用資源:當所有程式訪問裝置時都遵守某個原則時,軟體reliability會增強,比如定期檢查不良事件(undersired event)[7] 和裝置共享中的標準協議 [3] 。如果這些原則在裝置介面模組內構建,他們就會系統性地強制執行(systematically enforced);開發者寫使用者程式的時候就不需要考慮這些東西了。
-
程式碼共享:當很多程式直接訪問裝置時,他們大多包含了用於最終同一方式使用裝置的相似的子程式。如果有了裝置介面模組,這些程式碼就只需要寫一次,包括儲存,debug,測試,還可能是計算機儲存。
-
裝置高效使用 相互獨立地編寫的程式通常導致裝置不必要地重複動作。中心化裝置訪問程式碼更容易避免這些無意義操作。
為了達成這些目標並避免先前提到的問題,裝置介面模組和使用者程式之間的介面應該是抽象介面,正如下一節中定義的那樣。
三. 定義
- 介面:兩個程式之間包含了一組假設,這些假設都是對其他程式所作出的,目的是為了保證自己的程式運作正常。為了方便,我們採用“程式A對程式B所作的假設”這個表述,來表示,在B的特性必須滿足的情況,A才能正常工作。這些假設不僅僅侷限於傳統上在介面文件中寫明的呼叫順序和引數格式;這些假設還包括了額外的資訊,比如說資訊交換的意義和限制(the meaning and limits of informatino exchanged),事件順序的限制,以及在意外事件發生時的期望行為。在程式和裝置之間的介面同樣存在類似的定義。
- 抽象:一個對一組物件的抽象是一個可以平等地應用於其中任何一個的描述。。每一個物件都是抽象的例項。對於一個非平凡抽象,在抽象和它所描述的物件們之間存在一個一對多的關係。Differential equations are an example of a mathematical abstraction representing systems as diverse as electrical circuits and collections of springs and weights.
對目標的合理抽象相比於實際系統更容易學習理解,因為它隱藏了對目標無關的細節。一條道路圖是對道路網路的抽象;圖表展示了方向,相對長度,以及道路路口,但是它並不顯示一條道路是由瀝青做的或者它是怎麼建造的。相比於探索實際道路,學習一個道路圖來找到一條好的路線是簡單得多的。
任何從抽象中獲取的結論,都可以應用於同一抽象表述的任何系統。廣為人知的圖論結論可以應用於道路圖來決定最短路徑;相同的方法同樣可以應用來解決其他由有向圖表示的很多問題。如果結論是從不合適的抽象,比如說,錯誤地忽視了相關細節的抽象,中得出的,那麼他們最終可能會導致錯誤。舉個例子,一個道路圖不足以找到最快的路線,因為他們沒有展示其他的更多影響行駛事件的因素,比如道路限速。
-
抽象介面:一個抽象介面是一個意味著多個介面的抽象;它由它所表述的所有介面中的假設組成。某種型別的裝置的抽象介面僅僅會暴露實際裝置的部分細節:這樣的抽象只會描述出這一型別裝置的普遍的方面,而隱藏那些可以把實際裝置從這一類裝置中辨別出來的方面。
-
裝置介面模組:一個裝置介面模組是一組用於將在抽象介面和實際硬體介面之間轉換的程式。僅當抽象介面中的所有假設對於實際裝置而言都成立時,該模組的實現才有可能。
-
祕密:裝置介面模組的祕密是使用者程式不允許做出的,關於實際裝置的假設。祕密就是相比其他相同功能的裝置而言,當前使用的裝置必須成立的假設資訊。想要軟體正確地工作,祕密必須在某處合適得考慮到;它們被封裝在一個裝置介面模組。
-
意外(Undersired)事件假設:程式A和B之間的介面包括A對B做出的假設和B對A做出的假設。系統可以設計成只有兩個之一去依賴另一個滿足它自己規格的程式。一個程式可以設計成不依賴於正確使用它的使用者程式;它可以檢查不恰當的使用並在這些時間傳送意外事件。然而,錯誤檢查和報告都需要額外的指令。在A-7軟體的開發版本中,裝置介面模組會假設意外事件可以出現;它們會包含檢查使用者程式犯錯的程式碼。在生產版本中,沒有空間給這些錯誤檢查。裝置介面模組會假設不當使用不會出現;錯誤檢測程式碼會忽略掉來讓系統更小更快。如果在生產系統的操作中出現了問題,錯誤檢查會被插入以定位原因。軟體可以像這樣子編寫,這樣組裝程式時,錯誤檢查程式碼可以方便的引入或忽略。這隻應用於程式設計錯誤;軟體需求寫明的錯誤檢查永遠不會忽略。
-
訪問函式:一個訪問函式是一個模組內的函式,可能會被其他模組呼叫。有很多種不同的訪問函式;一些返回資訊給呼叫者;另一些改變了所屬模組的狀態。
-
事件:事件用於通知使用者程式本模組內部的狀態發生了改變。他們類似於硬體中斷,因為他們的出現不可預測,且於使用者程式的控制流不同步。在A-7系統,模組會使用一個mechanism比如 eventcount [8] 來發送一個事件給等待該事件的使用者程式。
Ⅳ. 設計方法
這一部分會講述用於抽象介面設計的procedure。這個procedure是基於獲取介面的兩個部分冗餘的描述(partially reduntant descriptions)。
- 描述1:表徵(characterizing)虛擬裝置的假設列表
對於一個應用程式領域,比如說航空電子,很多裝置最終都屬於標準型別;所有該型別的裝置都有著很多相同的特徵。比如說,正如航空周和空間技術(Aciation Week and Space Technology)裡的廣告展示的一樣,飛行員看到的計算機面板都沒啥區別。對每一個硬體裝置,都要列一個表,這個表記錄著所有當該裝置被其他同類型裝置取代時不太可能改動的特徵。做到這一點必須要仔細地考慮可用的甚至開發中的裝置。這個普遍特徵表是使用者程式可以對虛擬裝置做出的假設。這些假設表徵了裝置的能力、模式、資訊要求、行為和裝置的正確使用。一個經典的假設可能是:
”裝置提供了可以決定氣壓高度的資訊“
很明確的一點是,只有滿足了這個假設的裝置可以取代當前的氣壓高度感測器。注意,這個假設並沒有提及資訊從何處獲取,而這可能各不相同。
很多假設可能看起來相當無害,但是它們必須被記錄下來。在A-7設計的覆盤中,一些看起來人畜無害的假設最終沒有成功
- 描述2:體現假設的程式設計結構(Programming Constructs)
第二個描述指定使用者可以使用的訪問函式和事件。使用者程式可以呼叫訪問函式來訪問資料或者虛擬裝置提供的設施。比如說,一個介面可能提供一個訪問函式“GET_BAROALT",這個函式會返回一個氣壓高度值。對於每個訪問函式,我們指定返回值,限制,和它能對所屬的虛擬裝置造成的影響。使用者程式還可以使用事件來監聽虛擬裝置狀態的改變。比如說,使用者程式可能需要在某個虛擬感測器不再可控後收到通知。
為什麼是兩個描述?
這兩個描述是部分冗餘的,舉例來說,程式設計結構的定義(specifications)意味著假設。比如說,對訪問函式"GET_BAROALT"的定義意味著這樣的假設——裝置是從某個能夠決定氣壓高度的地方提供的資訊。訪問函式的定義提供了額外的資訊,即裝置介面模組和使用者程式之間交換資料的形式。比如說,裝置介面模組不直接提供氣壓高度,而是提供兩個或三個可以從中計算出來的量。這樣的設計改動需要函式定義的改動,但不會改動假設列表。
介面的兩種描述有著不同的目的:1)假設列表明確地表述了假設,而這個假設是隱含在函式定義中的,這使得無效的假設更容易被察覺,以及2)程式設計結構可以在使用者程式中直接使用。這兩種描述必須一致。假設應該在程式設計結構定義中被清晰明瞭的體現,而程式設計結構定義不應該暗含任何沒有在假設列表中講述的功能。假設列表應該被開發者、使用者、硬體工程師以及其他任何有必需知識檢查有效性和一般性的人去審查。比如說,A-7的假設有被系統工程師和熟悉A-7,A-6和F-18飛機的硬體工程師審查。以散文形式寫就的假設對於非開發者來說更容易審查。程式設計結構定義應該交由熟悉相似程式的開發者來審查。這些審查者會評估抽象介面對使用者程式的支援好與壞,以及抽象介面模組是否實現高效。使用者審查 A-7 裝置介面模組的procedures和準則在裝置介面文件 [4] 中描述。
設計Procedure
得到一個抽象介面的正確且一致的雙重描述是一個互動式的過程。儘管我們嘗試著先列出假設,還是有很多必要的假設相當的微妙,而且僅在我們設計程式設計結構時才比較明顯。對假設列表的審查可以暴露程式設計結構上的錯誤。介面是數輪審查的結果,包括NRL內部的,和NWC的A-7維護團隊的。初稿由NRL A-7 團隊 非正式地審查了數次,隨後才提交給NWC進行非正式審查。在NRL團隊內部深度審查後,我們再在NWC進行一個正式審查,最終得到當前的版本。
說明(Illustration)
作為該procedure的一個例子,這一部分簡單講一下一下對飛行資料計算器(ADC)的抽象介面開發。ADC是一個用於測量氣壓高度,真實空速,和代表空速的馬赫數的感測器。
圖2至4為從成功的ADC抽象介面中摘錄的部分。每一張圖包括了一個假設列表和用於展示相關程式設計結構的表。這些表不是完整的定義;其他的表定義了系統生成引數並制定了值得範圍和求解(resolution)。在訪問函式表中,"I" 表示該輸入引數由使用者程式提供;"O" 表示該輸出引數又ADC模組返回。
Figure 2:ADC抽象介面的早期草案摘錄
假設列表
-
ADC提供對氣壓高度,馬赫數,和真實空速的測量(measure)
-
上述的測量能力基於一組通用的感測器(a common set of sensors)。因此ADC感測器中任何一個的不準確,都可能影響輸出
-
ADC會在任何其擁有的感測器無法正確工作時發出提示
-
測量基於這樣的假設——海平面壓力為29.92英寸汞柱
訪問函式表
函式名 | 引數型別 | 引數資訊 |
---|---|---|
G_ADC_ALTITUDE | p1: distance; O | 高度假設29.92英尺為海平面壓力 |
G_ADC_MACH_INDEX | p1: mach; O | 馬赫 |
G_ADC_TRUE_AIRSPEED | p1: speed; O | 真實空速 |
G_ADC_FAIL_INDICATOR | p1: logical; O | 當ADC失敗時為true |
儘管圖2展示的早期草案對我們而言顯得簡單而合理,NRL和NWC審查者在其中找到了如下錯誤。
-
當前的ADC硬體和多數可替換的裝置內含內建的測試能力,但是卻無法通過當前介面訪問的。
-
描述沒有指明ADCfailed的時候訪問函式返回的值。
-
描述沒有指明測量值的可能範圍。範圍是依賴於裝置的,但是它們仍會影響使用者程式。
-
虛擬ADC在fail時沒有傳送訊號。使用者程式必須輪詢有效性函式來檢測可靠性的變動。
-
描述沒有清晰說明模組是否對原始感測器值執行裝置依賴(device-dependent)的矯正。
Figure 3:正式NWC審查時使用的ADC抽象介面草案摘錄
假設列表
-
ADC提供對氣壓高度,真實空速,和代表了飛機飛行速度的馬赫數。任何已知的測量錯誤都會在模組內進行補償(be compensated for)高度測量基於這樣的假設——海平面的氣壓是29.92英尺汞柱。
-
所有的這些測量均基於一組通用的感測器(a common set of sensors);因此ADC感測器中任何一個的不準確,都會影響所有測量。
-
使用者程式會在ADC硬體fails的時候通過事件的形式被通知到。如果氣壓高度,真實空速,和馬赫數的訪問函式在ADCfail的時候被呼叫,會返回最近一個有效測量(舊值)
-
ADC可以通過軟體的指令來進行自檢。自檢結果會返回給軟體。
-
馬赫數和真實空速的最小可測量值是0。氣壓高度最小值會在系統生成時間之後被固定下來,所有測量值的最小值和resolution也是如此。
訪問函式表
函式名字 | 引數型別 | 引數資訊 |
---|---|---|
G_ADC_BARO_ALTITUDE | p1: distance; O | 正確的高度,基於這樣的假設——海平面壓力 = 29.92英尺汞柱 |
G_ADC_MACH_INDEX | p1: mach; O | 正確的馬赫 |
G_ADC_RELIABILITY | p1: logical; O | 如果ADC可靠,返回true |
G_ADC_TRUE_AIRSPEED | p1: speed; O | 正確的真實空速 |
TEST_ADC | p1: logical; O | 如果ADC通過自檢,返回true |
事件表
事件 | 什麼時候觸發 |
---|---|
@T(ADC unreliable) | 當“ADC reliable”從true變為false時 |
在我們糾正了這些錯誤後,圖3展示的介面又交由NWC正式的審查。指出了下列問題。
-
裝置依賴的糾正對於海平面壓力是必要。假設一個不可改動的值為海平面壓力是不太好的,因為這會迫使一個裝置依賴的糾正落到使用者程式的職責裡。以後的硬體可能可以自動做到這一糾正。
-
儘管當前的硬體有所有三個值的可靠性提示器,替代的裝置不一定有。在替換裝置中,測量可能通過單獨的感測器實現。
-
我們不能假設最小馬赫和最小真實空速的值為0;一些裝置可能沒法測量如此之低的值。
圖4說明了產品的最終版本。
Figure 4:ADC抽象介面的最終版本摘錄
假設列表
-
ADC提供對氣壓高度,真實空速,和代表飛機飛行速度的馬赫數(mach index)。任何已知的測量錯誤會在模組內補償(are compensated for)
-
使用者程式會在一個或更多輸出不可用時被以事件的形式通知到。一個使用者程式也可以查詢某單獨輸出的可靠性。如果氣壓高度,真實空速,和馬赫數的訪問函式在值不可靠時被呼叫,會返回最近的有效測量值(舊值)
-
ADC可以遵循使用者程式的指令進行自檢。該次檢查的結果會返回給使用者程式。
-
ADC所有的測量值的最小值,最大值,和resolution都會在系統生成時間後固定下來。
-
ADC會基於使用者程式提供的代表海平面壓力(SLP)的值來計算它的輸出。如果沒有提供該值,那麼SLP會預設為29.92。
訪問函式表
函式名字 | 引數型別 | 引數資訊 |
---|---|---|
G_ADC_ALTITUDE | p1: distance; O p2: logical; O |
正確的高度,基於SLP=29.92或者使用者提供的SLP 如果高度有效,返回true |
G_ADC_MACH_INDEX | p1: mach; O p2: logical; O |
正確的馬赫 如果馬赫有效,返回true |
G_ADC_TRUE_AIRSPEED | p1: speed; O p2: logical; O |
正確的真實空速 如果真實空速有效,返回true |
S_ADC_SLP | p1: pressure; I | 海平面壓力 |
TEST_ADC | p1: logic; O | 如果ADC通過自檢,返回true |
事件表
事件 | 什麼時候觸發 |
---|---|
@T(高度無效) | 當“高度有效”從true轉為false |
@T(空速無效) | 當“空速有效”從true轉為false |
@T(馬赫無效) | 當“馬赫有效”從true轉為false |
對ADC抽象介面的開發展示了procedure是如何支撐我們的設計工作的。即便是圖2中的版本也是一個合理的設計;其包含的錯誤都是經典的嵌入式軟體錯誤。我們procedure的一個結果就是,錯誤的假設被明確地以便於審查的形式寫了下來,而不是模稜兩可。而那些有可能在實際編碼前難以注意到的不明智的假設,也能在它們能被較為簡單地糾正時發現。ADC介面當前的版本不一定就完美,但肯定比它不走這個precedure的版本要好得多。讓介面擁有兩個部分冗餘的描述是非常重要的。我們檢查過我們的記錄,發現了有些錯誤是在假設列表中發現的,而另一些是在程式設計結構定義中發現。很少有同樣的錯誤同時出現在兩種描述裡
Ⅴ. 設計困難
早前提到的設計考慮是設計的準則也是用於評估結果的標準。儘管這些設計考慮帶來了很大幫助,但是 並不總是能很容易的應用它們。在以下三個設計目標之間出現了衝突:小巧的裝置介面模組,裝置依賴的使用者程式,和效率。如果說使用者程式在瞭解了並非在所有可替換裝置中均成立的假設之後,可以工作得更高效的話,又如何?如果說封裝了並不總是有效的假設最終會導致裝置介面更慢或更大的話,又如何?可接受的假設必須基於對未來改動的可能性的預估。這一部分展示了困難的權衡和我們是如何解決的,同時還要嘗試著最小化軟體整個使用週期的期望成本。
困難1:可用裝置之間的主要變化
當可替換裝置之間存在主要不同(major difference)時,想要決定裝置介面模組中應包含多少能力是非常困難的。比如說,新的內部測量集(Interial Measurement Set,IMS)生成當前的位置資料;其他的IMS裝置生成速度資料;然而當前的 A-7 IMS僅生成速度增量。為了能夠使用當前的IMS硬體模擬一個可以生成當前位置的IMS,需要往IMS裝置介面模組裡塞進很多導航網格軟體;最終讓模組變得很大。必須在這兩者做出選擇——a)在裝置介面模組裡面約束主要改動,b)保持裝置介面模組小巧,這樣次要但更有可能的改動就會更容易。在理解了剩餘的不同可以侷限在一小組使用者程式後,我們的妥協限制虛擬IMS能展現的裝置的範圍。儘管我們的虛擬IMS確實沒法提供當前的位置,但是現在能提供速度而不是速度增量了;速度增量只用於計算速度,而速度是被廣泛使用的。由此差生的虛擬IMS比硬體IMS更容易使用,雖然我們希望IMS模組能更小。
困難2:特徵獨立變動的裝置
一些裝置具有數個可以獨立變動的特徵集。比如說,投影地圖展示集(Projected Map Display Set,PMDS)包含了一組幻燈片(filmstrips)以及一個用於將幻燈片放置於顯示器上的硬體驅動。相同的驅動能配合內含不同格式的地圖的幻燈片,而同樣的幻燈片也能被不同的驅動使用。鑑於資訊隱藏的原則,兩個獨立的特徵集應該隱藏在不同的模組,以便獨立改動。然而對於使用者程式而言,沒有必要知道到這是分隔開的。我們選擇將兩個特徵集都隱藏在同一個PMSD裝置介面模組裡。模組隨後會被劃分了為兩個子模組,改動會相互隔離。因為這個分隔是PMDS裝置模組的祕密,所以這是對使用者程式隱藏的,也不會顯現在介面定義中。
困難3:大概率改動的虛擬裝置特徵
一些可以改動的裝置特徵必需暴露給使用者程式,這樣它們就能更好的開發裝置的效率。這有些例子,包括測量值的resolutions,交換的位置的數量(position on switches),以及裝置限制比如最大可顯示值。儘管我們希望使用者程式與所有的裝置改動隔離開來,但如果這樣的特徵改動了,它們也必須要有不同的表現。比如說,虛擬PMDS改為提供三種尺寸的地圖,而不是兩種,這種情況下,控制著PMDS的使用者程式也必須有不同的表現。我們通過象徵性常量(symbolic constants)標誌這一類特徵。使用者程式和裝置程式都按照象徵性常量來編寫而不是一個實際的值。在系統生成時間,程式碼可以通過基於引數值的條件性的巨集擴張來生成。
我們為輸入和輸出資料的範圍和resolution定義了系統生成引數,因為1)範圍和resolution在不同的裝置中是極有可能不同的;2)這些資訊是對使用者程式精確高效地實現算術是必需的。基於系統生成引數程式設計的使用者程式在引數值改動時不需要重寫。
一開始我們假設在系統生成時間時所有的引數都已知;比如,我們明確假設,無論何時一個新的可替換裝置加入(is introduced),會生成一個新版本的程式,再和這個裝置一起部署。這個假設在設計審查時遭到了質疑。在海軍政策中,艦隊中不能有多個版本的軟體,儘管裝備改動不能同時生效。仔細點說就是,我們不能要求在新裝置損壞然後由舊裝置暫時替代時生成一個新的系統。結果就是,一些引數必須能在執行時改變。#In theroy this is true for any of the parameters; in fact, changeover problems are movre likely for some devices than others. #執行時可變數的消耗在不同的裝置間也有所不同,取決於引數能否用控制程式碼生成以便避免執行時檢查。如果改動是不太可能發生的,我們是不樂意放棄在系統生成時繫結值的效率益處的;如果較早的繫結值不會導致顯著savings,我們是不樂意放棄靈活性的。我們獨立考慮每一個情況,使用以下的指導原則。
-
實現可變的消耗較低的引數將被視作執行時變數,無論變動的可能性大小。模組介面中會有這些變數的get,set訪問函式。困難4是這些引數引發的額外困難。
-
改動的可能性較低且實現可變成本較高的引數,會在系統生成時間繫結好。
-
對於那些改動可能性又高,實現可變成本也高的引數,有以下兩種可行的方案
a. 將他們視作執行時變數,但允許在系統生成時由給出的值提早繫結。這個選項允許我們推遲最終的決定直到我們擁有更多的資訊。
b. 我們可以找到一個適用於多個裝置的保守值,這樣我們就能在系統生成時繫結值了。
困難4:執行時改動的,裝置依賴的特徵
在某些情況下,使用者程式必須處理裝置依賴的資料。比如說,當一個IMS被另一個同類型的替代時,軟體必須做出調整,因為製造業的差異(manufacturing variations)。IMS軟體是引數化的,這樣就能做出調整來適應特定的硬體。有這麼一個需求,就是我們得能夠在不重新組裝(reassembly)的情況下改變這些引數。引數在執行時從計算機面板輸入。為了接收這些資料,IMS提供了訪問函式,這些訪問函式由使用者程式呼叫來讀入面板資料。不幸的是,一個執行時引數的存在比如漂移率會暴露IMS模組的祕密,即實際裝置的偏移是不準的。一個額外的缺陷是,一個替換裝置可能會要求不同的校準資料,這就導致介面的改動。我們限制了這些訪問函式的使用,這樣軟體就會在有限範圍內使用它們,而且也容易辨別。受限制的假設和訪問函式被稱為重配置介面,並且被加入到普通介面中。
困難5:虛擬裝置間的互聯
理想情況下,虛擬裝置之間應該相互獨立,這樣關聯的抽象介面也能獨立地設計。然而A-7系統為了硬體方便,引入了裝置相互依賴性。有些相互依賴性是基於硬體設計師對軟體的假設。比如說,Doppler和Ship Inertial Navigation Set 可能會共享同一條資料路徑,因為某人假設了這個軟體不會同時需要這兩個裝置。我們能夠隱藏相互依賴的性質(nature)但是不能隱藏相互依賴的存在;如果我們隱藏了相互聯絡,之後使用者程式的改動可能會導致對裝置的錯誤訪問。相互依賴的存在會因假設列表中對虛擬裝置的使用限制而被暴露。比如說,有個假設是兩個虛擬裝置不能同時使用。如果硬體相互依賴之後移除了,那麼對一個或兩者均有的額外用處就有可能存在和可取(desirable)了。這樣的新增一定為要求抽象介面的兩邊均發生改動:使用者程式改動以發掘新的能力以及裝置介面模組改動以移除限制。既然這沒法避免,那麼就算暴露了限制也沒有損失。
一個相似的困難也可能在一個單獨的裝置介面模組中出現,如果當前的硬體不允許虛擬裝置的兩個能力同時被使用的話。同樣,我們選擇向用戶程式暴露限制,哪怕對於未來的裝置這可能不會繼續成立。
互聯問題還會出現在當一個裝置(提供者)提供另一個裝置(接收者)需要使用的資訊時。有兩種情況需要考慮:
-
計算機能夠檢測到提供者的失敗。如果是這樣,當提供者失敗時,虛擬接收者傳送一個失敗訊號,即使實際接收者沒有檢測到失敗。接收者的裝置介面模組可以模擬對失敗的檢測,以此來隱藏互聯關係。
-
計算機不能檢測到提供者的失敗。提供者無法檢測的失敗必須也考慮到接收者的無法檢測的失敗。寫依賴於虛擬接收者的程式的開發者必須意識到無法檢測的失敗是有可能的,但他們沒必要知道互聯關係。
困難6:硬體介面的不統一
一個硬體介面可能通過並不相似的方式提供相似的功能。比如說,HUD上的標識有著三種狀態:開啟,關閉和閃爍。對於某些標識,HUD提供了一個閃爍指令,而其他的標識就必須要軟體去切換標識的開關狀態來模擬閃爍狀態。無論何時硬體介面提供某些方式來執行動作,我們都要在虛擬裝置中一致地提供該功能。虛擬HUD有著所有標識的閃爍指令。然而,當硬體介面不能提供一個方法來執行某項動作時,我們被迫暴露了介面的不一致。比如說,某些HUD標識只有兩種狀態:關閉和閃爍。
因為沒有方法去模擬開啟狀態,所以虛擬裝置也就沒有辦法提供開啟指令。如果硬體約束在未來被移除了,不一致性也能從虛擬裝置中移除。不可避免的,抽象介面的兩邊都要改動:使用者程式改動以發掘新的能力,裝置介面模組改動以實現它。
困難7:開關的命名法(nomenclatures)
很多開關僅僅是修改了計算機閱讀的位元而已。我們可以匿名地命名開關(例如,用整數來命名)和使用非助記符(non-mnemonic)名字命名設定。然而,開關命名法的改動很大概率會伴隨著需求的改動。使用非助記符工作的期望成本是更高的,也就是說更多的錯誤。正因我們試圖最小化軟體在整個生命週期中的期望成本,我們選擇了在開關名字和開關設定的助記符值中暴露命名法。這些名字可能暗示了比假設陳述更多的資訊;程式設計師不應對這些開關做出超出介面文件中明確描述的假設以外的假設。
困難8:有著硬體副作用的開關
當一個開關也會影響到其他裝置的時候,它的意義就不僅僅是一個軟體決定(software decision);#major hardware changes would be required to use it for any other prupose#。我們認為這樣的開關是它所影響的裝置的一部分,即使它不是物理上處於該裝置內。就使用者程式而言,這樣的開關不存在;開關的效果看起來就是虛擬裝置操作模式的變化。比如說,位於主控功能面板的“地形跟隨”開關影響了前視雷達(Forward Looking Radar, FLR)的狀態。不和其他主控功能開關出現在同一個介面描述中,它隱藏在FLR裝置介面模組裡。使用者程式不能閱讀開關(read the switch),但它們可以呼叫暴露了FLR操作模式的訪問函式。
困難9:報告裝置狀態的變化
使用者程式通常需要對裝置狀態的變化迅速反應。比如說,巨頂當前導航模式的使用者程式需要知道什麼時候IMS感測器的可靠性狀態發生了變化。裝置介面模組可以1)提供一個訪問函式來報告裝置的當前狀態,也可以2)傳送狀態-變化事件。mechanism的選擇取決於使用者程式是根據當前狀態做出決定的還是說在等待狀態的改變。如果我們基於使用者程式的需求進行設計,那麼其需求的改變就會導致裝置介面模組的改動,而這違反了我們“除非裝置改動,否則不應改動裝置介面模組”的設計目標。我們決定每種情況都考慮兩種mechanism,但是最終只實現真正需要的那種。因此需求改動可能會導致裝置介面的改動,但是那些改動將會預先實現。通過提前辨別可能新增的宮嗯,我們期望降低之後重新程式設計的成本。
困難10:要求從軟體獲取資訊的裝置
一些硬體裝置會要求那些不在對應裝置介面模組中計算的資訊。比如說,當前IMS裝置需要知道飛機是否在70°高度以上,儘管高度並不是在IMS模組中計算的。這時必須從兩種方法中選擇一個把資訊給到:1)裝置介面模組可以提供一個訪問函式來讓使用者程式呼叫以提供資訊;2)裝置介面模組可以呼叫其他程式來獲取資訊。我們的選擇基於,資訊的獲取對於這一類替換裝置來說是否比較普遍。如果是,裝置介面模組會提供會提供訪問函式來接收資訊。這一方案會導致對剩餘的軟體有了新的需求,並且當資訊需要改變時,提供資訊的使用者程式也必須改變。如果對資訊的需要對硬體裝置來說是比較獨有的,那麼裝置介面模組就會呼叫其他程式來獲取資料。只要需要的資訊在系統其餘部分仍然可用,那麼就算不再需要這些資訊了,除了裝置介面模組意外,也沒有程式需要改動。對於上面的IMS示例我們選擇了後一種方案,因為並不是所有的IMS裝置都需要知道飛機是否飛到70°高度以上。
困難11:不與硬體裝置對應的虛擬裝置
一開始,我們假設每個虛擬裝置都有對應的硬體裝置。我們發現基於實際裝置構造虛擬裝置的模型並不總是能收穫清晰的介面。一些相關聯的能力分散在數個硬體裝置;一些不相關的能力又因為物理上的方便而出現在同一個裝置上;又有一些是因為歷史發展的原因。比如說,A-7上武器相關的能力分散在數個裝置中。一些武器資料來自控制武器釋放的裝置,一些儲存在表裡,還有一些由飛行員通過開關給出。此外,武器釋放裝置扮演了兩個角色:既是輸入資料的源,又是在計算機控制下釋放武器的裝置。我們最終的設計是兩個虛擬裝置,一個用於武器釋放和一個用於武器資料。虛擬裝置比實際裝置更容易理解得多。不要被硬體單元的物理位置過分地影響是很重要的。
Ⅵ. 總結
我們已經基於抽象介面準則將一個系統化的procedure應用於一個重大的系統。我們發現抽象介面使得系統更容易程式設計,並且希望看到它們能讓未來的改動更加簡單。儘管我們抽象介面設計的成功與否必須等到A-7的實現和後續維護都完成之後才能判斷,我們迄今為止的經歷能讓我們自信地向其他設計者推薦這個procedure。
這篇論文是更加完善的報告 [4] 的介紹。這篇報告包含有,所有A-7裝置介面模組的完整規格,檔案組織和符號的描述,額外的設計困難的討論,對procedures的討論和主要涉及審查時使用的問卷。該檔案可從作者處獲得。