程式者的胡言亂語

pageicon 星期二 二月 26, 2008

建立自用的程式庫

當我們談及軟體開發的生產力時,其實有相當多的因素在影響著。舉凡程式員本身的素質、所使用的程式語言、應用程式框架(application framework)的選擇、有沒有好的開發工具(例如IDE、程式碼產生器)、對開發環境的熟悉程度、開發方法論、甚至到更無形的團隊士氣都會影響到軟體開發的生產力。有些因素影響生產力甚鉅,例如程式員的素質、程式語言、應用程式框架的好壞等等。好的程式員和不好的程式員,生產力相差個幾十倍也不令人意外;而像C/C++之類的程式語言,與Java這種新興程式語言相較起來,使用起來的生產力,也會有數倍的差距。至於像RoRRuby on Rails)這樣的應用程式框架,近來更是以快速開發著稱而廣為流行。

開發的生產力,絕對是軟體開發中最重要的一件事。因為生產力代表的是單位時間內可以產生多少滿足品質標準的功能單位-不一定是程式碼數量,因為高階的程式碼即使精簡,能達成的功能單位卻有可能更多。軟體開發是一件事事講究現實的工作,倘若能花更少的時間來達成相同的功能,即意謂著需要耗去的資源及成本便會降低。追求更高的生產力,絕對是軟體開發領域的聖杯。

正因為這主題是聖杯,所以圍繞在這個主題的相關研究或討論,更是汗牛充棟,族繁不及備載。在這一回的主題,不打算談論比較受人關注的議題。在這一回中,想探討的是建立自用程式庫的這個議題。

想要提高程式開發生產力,有幾個可能的途徑:(1)精要、高階的抽象表述力(2)避免犯錯或者容易找出錯誤(3)自動化規則性的動作(4)避免做重複的事(5)打字速度快。其中最違背一般人認知的,當然是打字速度快。不過,就經驗上來說,兩個專業層級相當的程式員,其生產力的差距,有很大的一部份取絕在打字的速度。打字快的程式員,單位時間內可以輸入更多的程式碼,這當然可以得到更高的開發生產力。而高生產力的程式語言、應用程式框架,之所以能為生產力帶來助益,無非是因為它們往往提供了更精要且高階的表述方式,便得程式員可以用更短的程式行來描述一件相對而言複雜的事情。同樣的,高生產力的程式語言及應用程式框架,也能夠避免程式員犯下一些隱晦難解的錯誤。程式員們往往過於在意用於撰寫程式碼的時間,卻忽略了耗費在解決錯誤的時間。但是,事實上,當你在程式中埋下了隱晦難解的錯誤時,往往需要付出數十倍於撰寫程式碼的時間,或甚至更多時間,才有辦法加以解決。對於下面的這件事也許你經驗豐富:只花了些許的時間,便完成了程式碼,但卻花了極為漫長的時間,才找到一時大意所埋下的地雷。預先的錯誤防範,或者事後的加速追蹤,都對開發生產力有極大的幫助。好比Java針對陣列存取索引值的邊界檢查,對未初始化的變數的嚴格限制等等,都是針對運用C/C++時,容易因為犯下小錯而釀成大禍的問題進行改進。而事實也證明,這的確大有幫助。而像IDE或程式碼產生工具,基本上都在協助程式員將一些瑣碎、形式相同的工作,予以自動化。程式碼產生器的優點便在於駕馭既定的規則,利用機器取代人工,因為程式碼規則固定,因此容易利用程式碼產生器快速的製造出大量的程式碼。

倘若你既選用了生產力高的程式語言及應用程式框架,也盡可能的善用程式碼產生器,那麼想要顯著的提昇生產力的重責大任,大概就會落到如何避免做重覆的事上頭。

物件導向的設計方法之所以大行其道,正是因為這個方法觀察到程式碼重複運用(code reuse)對生產力所帶來的好處。可是,大多數的程式員因為拘泥於物件導向,一想到程式碼的重複運用,往往直接聯想到透過繼承方式取得的重複運用。然而,大多數情況下,除非我們設計的是應用程式的框架,或者是某種特殊應用的類別庫,否則設計的類別之間並不會存在太多或太複雜的繼承階層關係。這自然意謂著,透過繼承而得的重用程式碼其量不致於太多,因此也不太可能透過它得到非常多生產力的提昇。

可是,當你跳脫出利用繼承得到可重複使用之程式碼的想法後,或許會發現到,重複運用許多在開發過程中會需要的公用程式,也是提高生產力的主要來源之一。

我有留意到一個現象:現在的程式員多半都會利用現成的程式庫來協助自己快加開發的腳步,但程式員們鮮少建立自己的程式庫。這是一個很奇特的現象,因為其實在日積月累、諸多專案的開發經驗中,總會查覺到,有一些程式碼片段總是會一而再、再而三的重複發生。

你的系統中所會運用到的程式碼,依據其來源大致上可以區分為三類:(1)應用程式所專用,必須重新開發(2)現成的程式庫(3)並非前二者,但卻又很頻繁的在各專案中出現。倘若,針對那種很頻繁在你的各專案中出現、但卻又不存在於現成程式庫中的程式碼,未加以捕捉、整理,那麼對你來說,等於是在每個專案中,都要重新的將這些程式碼一一寫過。

以我的經驗來說吧,我時常要在表示日期的字串以及表示日期的物件(例如Java中的java.util.Date)之間進行轉換。雖然像Java的標準程式庫中的java.text.SimpleDateFormat已經提供了大部份我所需的功能,但因為實際上的需求卻又多過於它所能提供的。例如,我希望可以自動猜測要轉換成Data物件的格式,究竟是yyyy-MM-ddyyyy/MM/ddyyyyMMdd,甚至要能允許可選擇性的提供時間部份(HH:mm:ss)或是不提供時間部份。雖然,這只是一個很小的功能,但是倘若沒有捕捉到這段程式碼重覆發生的特性,因而未加以整理,那麼我就會反覆的在接下來的每個專案中,重新的予以撰寫過。又好比,在利用Java開發基於SWING的應用程式,我們時常會有一個需求是要將視窗、對話窗之類的元件置於畫面的正中央。這也許只需要十行左右的程式碼就能完成,但是同樣的,如果沒有留意到它的重覆性並加以整理,仍然得在大大小小的專案裡重新加以實作。又好比,我們時常要把一個整數值,表示成中文的數字寫法(零、一、二、)、把一個浮點數表示成百分比的字串呈現(例如:把0.75表示成75%)、將HTML中的所有tag都去除,只留下文字部份、等等。這些程式碼因為功能小,所以大多沒有被現成的程式庫所涵蓋,因為現成的程式庫多半著墨在較完整的主題,例如像log4j乃是針對日誌記錄的主題而設計的程式庫。對於零零散散的重複需求,很少能夠找到現成的程式庫。

雖然重新實作的程式碼看似不多,但是因為它們都是需求重複性高的程式碼,因此重覆實作的次數就多,對生產力造成的傷害當然就大。而且,對生產力造成的傷害卻不僅於此,因為每次程式員都得重覆寫下類似的程式碼,這些重新寫過的程式碼同樣可能出錯,同樣都需要被測試甚至耗費除錯的時間。兩項時間加總起來,許多寶貴的開發時間便因此而暗自的流失。我不知道有沒有人統計過,因為缺乏這樣的程式庫累積開發過程中需要的每個小功能,究竟對生產力的影響有多大,但就個人的經驗來說,許多小片段時常都會出現,倘若每次都重新來過,很直覺的,對開發的速度肯定大有影響。它們都是小東西,但如果每次都得反反覆覆的重刻,也會造成很大的傷害。

因此,我想給許多程式員一個建議:開始累積自己的公用程式庫(utility library)。你不用追求一次到位式的立即整理出一個好用的公用程式庫,你只需要在開發的過程中,逐步的觀察是否發生了重複性的程式碼片段,倘若有,便利用「重構(refactoring)」中提煉函式或提煉類別的技巧,將它們從應用程式的程式碼中提煉出來,萃取到你自己的公用程式庫中。如果是在一個開發團隊中,這個公用的程式庫應該是採取團隊共用的模式,相關的議題就會更多,包括:你們應該要制定一個維護公用程式庫的簡單流程,例如應該通知那一位協調者,應該如何撰寫說明文件、如何對你加入程式庫的公用程式進行測試以維護品質、如何確保不會對公用程式庫的其他程式產生副作用、如何管控公用程式庫的版本,以及和已開發、開發中的應用系統之間的組態管理等等。

善用公用程式庫是一門積小成大、積少成多的學問。許多專案累積、沉澱後的公用程式碼,它們並不是程式員單憑想像寫下「疑似」會被重複使用的程式碼,而是真正通過實戰考慮的可重用程式碼。打造自己專屬的利器,使用起來也更順手,不是嗎?

Blogged with Flock

迴響:

發表迴響:
  • HTML 語法: 關閉
把對母乳媽媽的感謝與支持傳出去

« 八月 2014
星期日星期一星期二星期三星期四星期五星期六
     
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
      
今日

Search this blog

Links

Weblog menu

Today's referrers

Feeds