前進 2021 年 Embedded World 展覽:第 4 集
編者說明:在 2021 年 Embedded World 展覽前推出的五篇部落格文章中,第 1 篇概略介紹了 Embedded World 展覽。在第 2 篇中,Randall 重溫了一下 C 編程語言知識。第 3 篇著重說明物件導向程式設計如何降低複雜性。本文是第 4 篇,介紹優良設計的基本衡量標準,即是能夠隨著需求變化進行重新配置,而不必再實作建置組塊。最後一篇部落格文章 (第 5 篇) 則對作業系統需要不斷擴張的空間提出質疑,並談及系統分解問題。本篇寫於 Randall 在 Embedded World 2021 上發表主題演講之前。
截至目前,我介紹過軟體如何演變成今日以物件為導向的型態,也描述了物件導向與電子學的相似之處。 若以物件導向的心態來思考,則能為真實世界中的物品 (即物件) 建立代理模型。我也談到物件導向程式設計 (OOP) 的屬性,以及如何評估此類模型的品質,但我還沒論及如何建立這些模型。這涉及到如何將系統分解成有用的模組和建置組塊。1970 年代初,有人曾撰文談論相關設計方法論,如今某些教程也浮出檯面。
最普遍的系統分割方式,當然是依功能。這包括將系統中的所有功能分解成建置組塊,再指派開發人員實作這些組塊。結果證實,這不是設計系統的最佳方式。裡面有許多陷阱,導致缺乏彈性並增加開發人員的工作量。雖然利用功能分解設計的系統可行,但還有更好的方法。老實說,另一種方法更難以上手,想弄清楚也不容易。剛開始需要花費較多時間,但之後開發過程會變得更順暢,而且產生的系統能更輕易適應變更。
David L. Parnas,來源:維基百科 (https://en.wikipedia.org/wiki/David_Parnas)
卡內基美隆大學的 David Parnas 在 1971 年撰寫過幾篇關於系統設計和模組化的論文。這些論文曾幫助建構耦合和內聚的概念;我在之前的部落格中提到過這兩個概念。其中一篇是《設計方法論的資訊分配面向》(Information Distribution Aspects of Design Methodology),撰寫於 1971 年 2 月。這篇論文不長,但對何為設計方法論做了非常詳盡的說明。Parnas 表示:「針對系統結構,做出排除某些可能性的決策,是設計有所進展的象徵。」他表示,一旦排除掉可能性,就能建立後續決策的理據,並用例子佐證他的說法。這些方法論各指向一個解決方案。
他確立了三種方法:
1.取得「良好」的外部考量因素
2.縮短專案啟動和完成之間的時間間隔
3.取得一個容易變更的系統
方法 1 與「自上而下」方法有關。方法 2 會導致做出的模組化選擇,可能未完整考量到對產品最終可用性的影響,但能讓開發人員的開發速度更快。方法 3 則識別出最不可能改變的因素,結果是最普遍的資訊得到最先使用。
他認為,自上而下的方法可能會導致未來難以對系統做出變更,這純粹是因為,外部因素比起那些影響變更的因素,更傾向於成為決定標準。 他在論文的這一部分總結,表示這些方法中所作的決策,沒有一定的先後次序,因此不可能同時全部得到滿足。 他在下一篇論文中也提到這個立場,我接下來會介紹,但我想先針對這篇論文表達一些意見。
我覺得他對優秀編程人員的描述很有意思。他說:「優秀的編程人員會利用他手邊的所有資訊!」他繼續說明,優秀的編程人員很聰明,可能會使用沒有書面記錄的資訊,而這意味著,當一個組塊發生變更時,其他組塊也需要進行變更。這是我在前一篇文章中提到的共生性概念,這與方法 3 並不一致。此首篇論文的結論是,隱藏資訊是好事,這代表系統設計人員應按照 Parnas 所謂的「僅知原則」來分享設計資訊。
Parnas 接著在 1971 年 8 月撰寫下一篇論文,標題為《論將系統分解為模組時所用標準》(On the Criterion to Be Used in Decomposing Systems into Modules)。這篇論文的知名度很高,目前有稍微復興的跡象。在這篇論文中,他提出充分的理由以說明根據變更可能性來設計系統,即前一篇論文中的方法 3。
他的目標是改善系統的彈性和可理解性,同時縮短總開發時間,他還用範例來說明成功的經驗。根據資訊隱藏原則對程式碼進行模組化,就是根據變更管理將系統進行模組化。變更會被隔離至較少的模組中,這意味著當需求改變時,系統變更和重新配置會更加容易。雖然無論使用功能分解還是變更分解,系統都能運作,但如果將資訊持續隱藏並藉此確保高內聚性,系統會變得更有彈性、可理解性,且開發速度更快。
試想一下,記憶體內儲存了某個特定結構廣為人知的項目。如果對系統進行功能分解,任何或所有的模組可能會透過其運作。如果結構發生變更,所有存取該結構的模組都必須進行變更。但是,如果該結構是由負責提供存取的模組所管理,則不必變更每一個需存取該結構的模組,就能變更該結構。在此方法論中,重點是設計人員從一開始就確定可能會發生變更的內容。每個方法論都會產生相同的功能,差別在於模組性。Parnas 相信,比起功能型模組化,變更型模組化能更有效地揭露設計決定,讓系統更容易理解。
資訊隱藏型模組化並不是沒有危害。Parnas 指出以這種方式設計的系統可能效率不彰,但他認為,隨著系統成長,隱藏資訊會變得更加重要。我會在下個月的最後一篇文章中討論危害之處。
最根本的是,為了改善功能的重複使用性,該功能的介面必須盡量少揭露資訊。如愛因斯坦所說:「凡事應盡可能力求簡單,不過不能過於簡單。」就我們的情況而言,我們要把「凡事」代換成「介面」。這個任務非常適合由嵌入式工程師來執行。他們在許多技巧上受過訓練,比起不擅長的人,他們能夠處理任何層級的設計工作。如果工程師的設計將由最廣大的使用者群 (即客戶) 所使用,該設計應盡可能簡單。
來源:https://rightingsoftware.org/
如前所述,Parnas 的著作目前有稍微復興的跡象。對於任何想要深入瞭解的人,我邀請您閱讀 Parnas 的論文,以及 Juval Löwy 的著作《扶正軟體》(Righting Software)。
Löwy 對 Parnas 的方法作出讚許,也就是透過分解系統來建構系統 (考慮到潛在變更的多變性),並將這些潛在變更封裝在建置組塊中。接著會實作系統的必要行為,作為這些建置組塊間的互動。一個成功的設計是使用建置組塊的最小組合來滿足所有使用案例,但知易行難。
Löwy 表示,知道核心使用案例為何,即能確定這一組合。他還補充,這些使用案例幾乎不多,可能只有 1 至 3 個,結果產生的組成元素通常不到 12 個。12 個元素的組成和互動數量多不勝數。這讓我聯想到,樂器 12 個音符就能創作出許多不同的歌曲。音符有前後順序及時間性,所以我想他說的不錯。
他繼續說到,20 萬年前人類的使用案例,與我們現在擁有的案例並無不同之處。這個使用案例就是存活,但當時透過打獵和採集使人得以存活的架構,和讓現今軟體工程師得以維生的架構,是同一個架構 (即使用相同的組成元素)。他認為,大象和老鼠擁有相同的架構,差別在於細部的設計。此論點令人折服。
因此,優良設計的基本衡量標準是:能夠隨著需求變化進行重新配置,而不必再實作建置組塊。成功的分解能滿足所有要求:過去、未來、已知和未知。這是個很有深度的主題,值得研究。
我在前一篇文章中提過,我會描述一個我們在讓更多人使用我們開發的功能時所產生的問題,但我認為這是為了謀求更大市場所付出的代價。

Have questions or comments? Continue the conversation on TechForum, Digi-Key's online community and technical resource.
Visit TechForum