寫程式庫?開發者應該不陌生,然而,多半是為了應付公司或客戶使用,而去寫程式庫的情況比較多。

談到寫個自己的程式庫,過去我也常常自問:「要寫哪種程式庫?」主流語言的程式庫多到爆了,完全提不起動力來寫啊!如果這也是你的困惑,不妨來試試我的笨方法!

一百多個作品的想法與記錄

想寫得出像樣的程式庫,應該是要對某個語言或生態圈很熟悉吧!基本上是這樣沒錯,不過,機能或生態過於豐富的語言技術,開發者越是熟悉,往往越覺得沒有必要重新打造輪子了,然而,熟悉的意義是指「找出自己真正的需求」,而不是知道有哪些程式庫「可以用來滿足需求」,程式庫說是能滿足需求,實際上往往是用來削減、規範需求,讓程式有一致性,然而久了,就會誤以為被削減的需求,就是自己的需求,也自然就不會有動機想寫自己的程式庫了。

曾經有人為了要學習程式設計,決定要在180天內建立180個網站(https://jenniferdewalt.com/),而我在過去一年多以來,基於個人興趣,也為了訓練多做些數學方面的思考,幾乎每個星期都會發表程式3D建模作品,半年左右隨著作品的增加,就萌生了建立程式庫的想法,既然如此,那就持續做滿一百個作品的話,會是如何呢?

從有想法開始,之後也曾經嘗試將作品中重複的程式碼抽取為模組,基本上就單純只是抽取重複居多,新作品若有需要類似的概念,會試著使用這些模組,然而隨著作品越來越多,這種隨意抽取出來的鬆散模組,就陸續出現問題,模組往往需要修改,類似模組有多個版本,命名與變數範圍會有一些衝突,模組相依性也開始複雜起來,在累積一百多個作品的同時,也累積著對程式庫的種種考量。

為了記錄這些想法,我開始為設計時的考量寫文件,也同時思考著,既有作品在數學、演算,以及程式面的組織上,還有哪些可以改進的地方,過程中使用的範例,也開始試著做些泛化,並在後續的文件中,使用先前文件中試作的成果。

哪些才是基礎元素?

一個程式庫中,最基礎的元素是什麼呢?當我決定認真地打造dotSCAD程式庫(https://goo.gl/Yb2IOR)時,決定的第一個基礎元素是「文件」,這是我在一百多個作品中使用那些鬆散模組,以及現有的OpenSCAD程式庫時的切身之痛。沒有文件,這程式庫最後連自己都不會想用。

那麼,文件該怎麼寫?參考官方的文件來組織內容,會是個不錯的方式,類似的考量也在模組與函式的介面設計上,如果自訂的模組是基於內建模組而擴充,那麼在參數與行為上,就會優先考量銜接內建模組,例如,建立圓弧線用的模組,在邊線的表現上,就會考量與內建的circle模組一致,圓角矩形多了控制圓角的參數之外,與內建的square模組也有著同樣的參數安排。

名稱空間是個大問題,OpenSCAD本身沒有名稱空間管理機制,為了突破語言的限制,我才終於認真地去研究一些特別變數範疇,以及模組的引用(use)與含括(include),決定一個公開模組或函式就使用一個原始碼檔案的方式,並藉此解決相依性問題,這是基於一個簡單的想法。如果沒辦法完全解決名稱空間或相依問題,那就在問題發生時,可以很快地找到根源。例如,程式運行時缺少line3d模組?那就include <line3d.scad>就對了!

在這之後,才是慢慢去思考,哪些模組或函式可以加入程式庫。也許有許多開發者會認為,模組或函式才是程式庫的主體,然而,如果沒有先去考量如何處理文件、一致性、名稱空間、相依性等,程式庫最後會什麼都不是!

那麼,有哪些模組或函式可以加入程式庫呢?

這就要去觀察過去的一百多件作品了,實際上,決定什麼不加入會比較難,然而,拒絕加入某個模組或函式的理由,如果夠充分,往往才能看到其中真正的基礎元素。

舉例來說,加入一個可以繞圓的文字模組如何?不!它不該加入,因為想繞著圓的不一定是文字,實際上,圓只是個路徑罷了,該加入的是一個可產生路徑上所有點座標的函式,這樣就可以在點座標處放上任何東西了。

這樣夠了嗎?

正如設計一百多個作品之後的記錄,總是在思考著還有哪些可以改進的地方,當模組與函式陸續加入至程式庫之後,有時需要停下來想一下,還有哪些可以改進的地方,修臭蟲是必然的,每當思考「這樣就夠了嗎?」之時,效能就會是一個重點。

繪圖往往需要比較多的資源,簡單的做法往往耗費更多資源,像是繪製3D線段,常見的做法是放兩個球體,然後找出凸包(hull)將它們涵蓋,不過,在線段非常多或球的面數多時,繪製速度就會急劇下降,自行計算出線段上必要座點的方式比較麻煩,然而效能改善顯著。曾經幫人解決函數圖形繪製的效能問題,單只是改用我的線段模組,而且,光預覽花費的時間,兩個版本就有兩分多鐘與一秒的差距。

另一個總是想著能否改進的地方是精確度。既然使用程式建模了,讓模型精確地定位,減少不必要的面,除了計算更為快速之外,還有著模型檔小、有利於3D列印時切片操作等優點。

因為是基礎程式庫,精確度考量高一點的話,在與其他模型接合時,也能解決誤差問題。例如,10x10x10圓角立方體的製作,隨意地擺上具有多個面數的八顆球,並使用凸包,可以解決問題;然後,如果因為某個需求得將球的面數減少,那麼,這立方體就不會是10x10x10了,然而只要做些計算,這是個可解決的問題。

雖然OpenSCAD的程式庫相對來說比較少,但不是沒有,但我多半對它們不感興趣,在設計程式庫時,我反而又去看看這些程式庫。

除了看看有哪些元素是可能納入之外,最主要的是從中思考:它們讓我不感興趣的理由是什麼?看得出來,有些程式庫應該不是專職程式設計的人寫的,因為可讀性差、組織鬆散、變數範圍亂七八糟,更別說有文件了,這也是為何我一開始思考基礎元素時,會優先考量文件、一致性等的原因。

畢竟這是自己會用的程式庫,總不能之後自己「裱」自己啊!昨天晚上我想出如何點間等距計算出黃金螺線的方式,並予以實現,今天早上就想著「這樣夠了嗎?」當用到的費式數多時,速度就慢下來了,試著使用數式的公式計算費式數,也沒改進多少,這才有動機研究一下快速費式數演算。

有基礎才能激發更多想法

點間等距計算出黃金螺線的方式,其實也不是憑空想像出來的,因為曾經在程式庫中加入過圓路徑計算,以及轉動座標點的基礎函式,昨晚我想到黃金螺線本身,其實就是一連串四分之一圓依規則轉動而構成,而圓實際上就是正多邊型,這不就是等距嗎?因此,需要的基礎函式都有了,只要試著結合起來,就可以建立黃金螺線的路徑了。

也許有點諷刺,Java是我最熟悉的語言,這中間也接觸過Python、JavaScript等語言,不過,第一個認真的程式庫卻是OpenSCAD,我常自嘲地說:「反正OpenSCAD沒幾個像樣的程式庫,一個隨便寫都可以隨便唬的概念」,實際上,寫一百多個作品再來做程式庫,這方法也太笨拙了。

然而笨歸笨,就算想在主流語言技術中套用,應該也是適用的吧!也許寫出來的成果,不見得能比上其他更優秀的程式庫,然而,一百多個作品的想法、難題、靈感、實現,重複地迭代,是個滿值得經歷的過程,有了這樣的基礎,將來或許才真的能激發更加優秀的程式庫吧!

專欄作者

熱門新聞

Advertisement