從Unix開源開發學習應對大型復雜項目開發

 2023-12-06 阅读 28 评论 0

摘要:封裝與抽象 在 Unix、Linux 系統中,有一句經典的話,“Everything is a file”,翻譯成中文就是“一切皆文件”。這句話的意思就是,在 Unix、Linux 系統中,很多東西都被抽象成“文件”這樣一個概念,比如 Socket、驅動、硬盤、系統信息

封裝與抽象

在 Unix、Linux 系統中,有一句經典的話,“Everything is a file”,翻譯成中文就是“一切皆文件”。這句話的意思就是,在 Unix、Linux 系統中,很多東西都被抽象成“文件”這樣一個概念,比如 Socket、驅動、硬盤、系統信息等。它們使用文件系統的路徑作為統一的命名空間(namespace),使用統一的 read、write 標準函數來訪問。

比如,我們要查看 CPU 的信息,在 Linux 系統中,我們只需要使用 Vim、Gedit 等編輯器或者 cat 命令,像打開其他文件一樣,打開 /proc/cpuinfo,就能查看到相應的信息。除此之外,我們還可以通過查看 /proc/uptime文件,了解系統運行了多久,查看 /proc/version 了解系統的內核版本等。

實際上,“一切皆文件”就體現了封裝和抽象的設計思想。

封裝了不同類型設備的訪問細節,抽象為統一的文件訪問方式,更高層的代碼就能基于統一的訪問方式,來訪問底層不同類型的設備。這樣做的好處是,隔離底層設備訪問的復雜性。統一的訪問方式能夠簡化上層代碼的編寫,并且代碼更容易復用。

除此之外,抽象和封裝還能有效控制代碼復雜性的蔓延,將復雜性封裝在局部代碼中,隔離實現的易變性,提供簡單、統一的訪問接口,讓其他模塊來使用,其他模塊基于抽象的接口而非具體的實現編程,代碼會更加穩定。

分層與模塊化

前面我們也提到,模塊化是構建復雜系統的常用手段。對于像 Unix 這樣的復雜系統,沒有人能掌控所有的細節。之所以我們能開發出如此復雜的系統,并且能維護得了,最主要的原因就是將系統劃分成各個獨立的模塊,比如進程調度、進程通信、內存管理、虛擬文件系統、網絡接口等模塊。不同的模塊之間通過接口來進行通信,模塊之間耦合很小,每個小的團隊聚焦于一個獨立的高內聚模塊來開發,最終像搭積木一樣,將各個模塊組裝起來,構建成一個超級復雜的系統。

除此之外,Unix、Linux 等大型系統之所以能做到幾百、上千人有條不紊地協作開發,也歸功于模塊化做得好。不同的團隊負責不同的模塊開發,這樣即便在不了解全部細節的情況下,管理者也能協調各個模塊,讓整個系統有效運轉。

實際上,除了模塊化之外,分層也是我們常用來架構復雜系統的方法

我們常說,計算機領域的任何問題都可以通過增加一個間接的中間層來解決,這本身就體現了分層的重要性。比如,Unix 系統也是基于分層開發的,它可以大致上分為三層,分別是內核、系統調用、應用層。每一層都對上層封裝實現細節,暴露抽象的接口來調用。而且,任意一層都可以被重新實現,不會影響到其他層的代碼。

面對復雜系統的開發,我們要善于應用分層技術,把容易復用、跟具體業務關系不大的代碼,盡量下沉到下層,把容易變動、跟具體業務強相關的代碼,盡量上移到上層

基于接口通信

剛剛我們講了分層、模塊化,那不同的層之間、不同的模塊之間,是如何通信的呢?一般來講都是通過接口調用。在設計模塊(module)或者層(layer)要暴露的接口的時候,我們要學會隱藏實現,接口從命名到定義都要抽象一些,盡量少涉及具體的實現細節。

比如,Unix 系統提供的 open() 文件操作函數,底層實現非常復雜,涉及權限控制、并發控制、物理存儲,但我們用起來卻非常簡單。除此之外,因為 open() 函數基于抽象而非具體的實現來定義,所以我們在改動 open() 函數的底層實現的時候,并不需要改動依賴它的上層代碼

高內聚、松耦合

高內聚、松耦合是一個比較通用的設計思想,內聚性好、耦合少的代碼,能讓我們在修改或者閱讀代碼的時候,聚集到在一個小范圍的模塊或者類中,不需要了解太多其他模塊或類的代碼,讓我們的焦點不至于太發散,也就降低了閱讀和修改代碼的難度。而且,因為依賴關系簡單,耦合小,修改代碼不會牽一發而動全身,代碼改動比較集中,引入 bug 的風險也就減少了很多。

實際上,剛剛講到的很多方法,比如封裝、抽象、分層、模塊化、基于接口通信,都能有效地實現代碼的高內聚、松耦合。反過來,代碼的高內聚、松耦合,也就意味著,抽象、封裝做到比較到位、代碼結構清晰、分層和模塊化合理、依賴關系簡單,那代碼整體的質量就不會太差。即便某個具體的類或者模塊設計得不怎么合理,代碼質量不怎么高,影響的范圍也是非常有限的。我們可以聚焦于這個模塊或者類做相應的小型重構。而相對于代碼結構的調整,這種改動范圍比較集中的小型重構的難度就小多了。

為擴展而設計

越是復雜項目,越要在前期設計上多花點時間。提前思考項目中未來可能會有哪些功能需要擴展,提前預留好擴展點,以便在未來需求變更的時候,在不改動代碼整體結構的情況下,輕松地添加新功能。

做到代碼可擴展,需要代碼滿足開閉原則。特別是像 Unix 這樣的開源項目,有 n 多人參與開發,任何人都可以提交代碼到代碼庫中。代碼滿足開閉原則,基于擴展而非修改來添加新功能,最小化、集中化代碼改動,避免新代碼影響到老代碼,降低引入 bug 的風險。

最小驚奇原則

《Unix 編程藝術》一書中提到一個 Unix 的經典設計原則,叫“最小驚奇原則”,英文是“The Least Surprise Principle”。實際上,這個原則等同于“遵守開發規范”,意思是,在做設計或者編碼的時候要遵守統一的開發規范,避免反直覺的設計。實際上,關于這一點,我們在前面的編碼規范部分也講到過。

遵從統一的編碼規范,所有的代碼都像一個人寫出來的,能有效地減少閱讀干擾。在大型軟件開發中,參與開發的人員很多,如果每個人都按照自己的編碼習慣來寫代碼,那整個項目的代碼風格就會千奇百怪,這個類是這種編碼風格,另一個類又是另外一種風格。在閱讀的時候,我們要不停地切換去適應不同的編碼風格,可讀性就變差了。所以,對于大型項目的開發來說,我們要特別重視遵守統一的開發規范。

總結

封裝與抽象
分層與模塊化
基于接口通信
高內聚、松耦合
為擴展而設計
最小驚奇原則

參考

78 | 開源實戰二(上):從Unix開源開發學習應對大型復雜項目開發

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/3/189294.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息