about 2 years ago

今年因為轉職,特休歸零了,一年一度跟家人的國外旅遊也就暫緩,只有安排短短的宜蘭兩天一夜的小旅行,宜蘭雖然去過不少次,但這次幾個點都蠻不錯的,算是有個小小的充電,但...總覺得少了些什麼?

上一回提到在開發 framework 或 library 時,naming style 是很重要的,有一致且達意的 API 讓使用 framework 或 library 的開發者不會有意外感,容易上手。但可惜的是自動化工具能檢查格式 (縮排、空白等等),但無法幫忙判斷這個變數名稱好不好或是這個函式名稱達不達意,也許哪一天,將人工智慧用來判斷程式碼的 naming style 也許是個不錯的研究方向。

當公司的規模越來越大,開發的項目變多變大時,總是會出現在不同的專案但卻開發重複的東西,因此,公司內部的 library 或 framework 就會出現,一般來說,這些內部 library 或 framework 不會一開始就是 open-source 的形式出現在 Maven Central RepositoryJCenternpmGitHub 中。除了牽涉到公司利益的問題外,即使要開放,也會是等到內部使用一陣子後,API 有一定的穩定度後,才會釋出,例如 okhttp 原先是 Square 的內部眾多 library 的其中一個,然後回饋給 open-source 社群,類似的例子還蠻多的,像是 Cassandra 原本也是 Facebook 的內部專案。

一旦公司內開始有內部函式庫,某種程度需要一些管理,確保不會花兩倍的人力開發相似的東西,或是避免開發的東西沒人知道。之前曾聽在硬體公司的軟體部門的人聊過,公司內部的 (韌體相關) 函式庫沒有進版控系統,可能聽誰說有什麼可以用,於是找主管複製,然後在自己的專案裡一起編譯,因為沒有人維護這些函式庫,踩到雷也只在自己的專案裡東修西修,沒有任何回報機制,頂多是自己保留一份修正版本,下次要用時就用自己的版本。又或者是,不斷地複製 (分支) 然後根據專案的需要修改,到最後函式庫有眾多個不同版本,完全不知道哪個版本才是最新最完整的,最後,沒人想用這些函式庫。

沒人維護公司內部函式庫是很常見的一種情況,因為專案或產品的產出才是能賺錢的部分,函式庫只是開發過程中,附帶的產物,當初貢獻的工程師可能在忙別的專案或產品,公司也不太可能讓這工程師變成專職維護內部函式庫的工程師。所以,最起碼內部函式庫要進到版控系統,如果要修改,要在版控系統上建立分支,並留下 commit,如果哪天真的要整理函式庫,還能透過版控系統進行比較 (compare) 與合併 (merge),更進一步還能進行函式庫版本控管,如果沒有版控系統,程式碼只是各自電腦中的一個目錄,那要整理就會是一件很困難的事了。

當整個公司 share 同一個 code base 時,內部函式庫被頻繁使用的情況下,就比較不會有無人維護的情況,但要進行設計上的改版,就可能會引發公司內的政治問題,例如,一個內部函式庫 X,同時被 A 及 B 兩個專案使用,一開始可能都沒問題,但 A 專案的工程師想對 X 針對專案的需要進行設計上的調整,B 專案的工程師也想對 X 做一些針對 B 專案的調整,若兩者的設計不相違背,那是最理想的情況,但有衝突時,就需要有人出面協調,可能是原 X 函式庫的開發者或是主導整個公司技術的負責人。

不論是採用哪種方式進行改版,有使用到 X 函式庫的其他專案都可能會受到影響,所以,務必要做好函式庫的版本控管,至少讓其他專案能有使用既有版本的選擇。相較於直譯式語言,只需要做好程式碼的版本控管即可。編譯式語言或是能以 binary 形式 (像是副檔名為 libdllsoajar 的檔案) 使用函式庫的語言,函式庫的版本控管就多了一個東西要管理,也就是 binary 檔案的版本控管。雖然說,有原始碼就能夠重建這些 binary 檔案,但有些情況會盡可能避免重建這些檔案:

  • 編譯時間太長,若編譯一個 so 需要五分鐘,使用到多個 so 檔可能會花上半小時,這太花時間了
  • 編譯環境,編譯函式庫可能需要一些環境,但不見得和專案的開發環境相同,若已經有 binary 檔案,可以省去一些設定開發環境的麻煩

目前大多數的語言生態系中都有 binary 層級或是 source code 層級的函式庫版本管理系統,以 Java 來說,想在公司內管理內部函式庫,可以使用 Artifactory,透過 CI 的協助,在程式碼有變動時,可以建置、測試,然後部署新版的 binary 檔案到 Artifactory 的檔案庫 (repository) 中,就能夠在 Maven 的 pom 檔或是在 Gradle 的腳本檔中使用。

內部函式庫雖然可以幫公司省去不少開發重複東西的時間,但內部函式庫也是有一些缺點存在的。首先,一個專案中內部函式庫使用的量,會影響一個剛加入專案的新人了解專案架構的速度,使用的函式庫越多,特別是 framework 層級的函式庫,常會讓專案的程式邏輯散落在很多與 framework 有關的物件中,程式流程會較難以理解,可能會造成只知道如何撰寫特定程式加到 framework 中完成指定的功能,但整個專案的架構不熟悉,要解決要深入的問題時,就不知從何下手。

再者,是相依性問題,專案相依在許多內部函式庫時,若每個內部函式庫都很穩定,那專案應該會很容易在巨人的肩膀上專注在專案的功能上,但若有一兩個內部函式庫不是那麼穩定時,一出錯常常要找半天還不能確定是專案的問題或是某個內部函式庫的問題。

第三是部署或發佈可能會是一個問題,若公司是以產品為主,那這問題就比較好處理,但如果專案是一個接進來的外包案,內部函式庫的發佈就比較麻煩一點,直譯式語言只能將內部函式庫以原始碼的方式交給業主 (有其他方式嗎?),但即使是 binary 形式,在發佈的版本中,建置腳本需要一些特別的調整,總不能讓業主能直接連進公司內取得 binary 檔吧。

即使有上述幾個問題,但以長遠的角度來看,內部函式庫還是值得投資的公司資產,只是它需要時間、人力與管理才能做得好。若有不錯的內部函式庫其實也可以回饋給 open-source 社群,畢竟,現在開發軟體已經不太可能沒有用到任何 open-source 的東西了。回饋的形式有很多種,雖然說是將公司資產以 open-source 釋出,但換取的利益卻不見得是零,像是提升公司的聲望,在招募時能有更好的人才願意進來;獲得 open-source 社群的再貢獻,讓函式庫變得更好等等。話雖如此,但釋出時,還是要妥善選擇授權條款。

系列索引
上一篇《閒談軟體架構:API Naming Style
下一篇《閒談軟體架構:意志力不是萬能藥

← 介面本質上的進化 閒談軟體架構:意志力不是萬能藥 →