2007年10月31日 星期三

F23 測試結果與對應文件裝訂在一起

需求被定義為功能,功能經由設計而實現,實現的程式藉著測試來保證運作的正常。不止是測試的結果,這一系列的相關文件具有演進的垂直關係,理應放置在一起以便查詢。

不過物件的位置與關係至少會是二維的,處於同一層次的物件彼此間會有相互使用的水平關係。像最開始會在功能裡使用其他功能,接著就影響到其下的設計與測試,都必須等待自己使用的功能完成後才能開始。這樣的關係也是必須在文件裡註明的。

另外也要記得同種類物件的清單必須產生,這是各個層次物件的快速索引表。如果有能力的話,水平追溯表與垂直追溯表還是做出來會比較方便查出所有的關聯;但是如何與真實物件間的關係作同步的修改,將會是日後需要多花資源的地方。

總之,讓同一個功能之下所有項目的資料都放在一起,這是符合聚合並封裝概念的作法。

2007年10月30日 星期二

F22 追溯關係(4)──Use Case vs. Test Case

Use Case應該與Test Case作好關聯的追溯。我們可以藉由測試過哪些Test Case來達到保證某特定Use Case可以正確執行的結論。

不管是因為什麼原因更動了程式碼,最基本的就是那個Class必須重作Unit Test;其次再依序往上,一層層地對使用到這個Class的Class作Unit Test,並依此原則遞迴測試所有最終會用到該Class的所有程式。

接著需要分析的是剛才所有重新作過Unit Test的Class,各自被包含到哪些Use Case的範圍內;有包含那些Class的Use Case對應的Test Case都必須重新進行測試。如果更動的是很多Use Case所使用的核心Class,那麼重新測試耗費的資源會是很可觀的。

要能根除“改過這裡之後要測試哪些東西才能再度保證系統是可以正常運作的?”這樣的問題,唯有作好對應功能、設計與相關測試的追溯關係方有終點。

2007年10月29日 星期一

F21 測試錯誤的處理(3)──迴歸測試(Regression Test)

如果問題單提出的內容的確是系統的錯誤,那麼系統理應針對這個問題作修正。程式的任何變動都會造成程式所在方法的改變,進而影響到呼叫該方法的所有地方。為了保證一段程式被修正後,其他使用它的方法同樣運作正常,我們必須再重新測試過這些方法所對應的測試項目(即使修改前已經全部測試通過)。

由此可見,程式的變動是需要審慎從事的。在國外的專案裡,每一行程式的變動,客戶都會詢問是為什麼而改,同時會影響哪些範圍,因為錯誤的解決方法會讓系統如同骨牌傾倒般到處出現連帶的問題。有時邏輯上的問題造成兩個地方糾纏不清,A改好B就有問題,去改了B時A又壞掉,這樣的Side Effect是任何人都沒法忍受的。

前面提到程式的追溯最好是到方法層級,這是因為方法內部的改變只要往上追溯使用該方法的地方;如果追溯的程度使用的是類別,那會使得追溯出來的範圍過大且不正確。涵蓋了一堆沒有使用關係的方法,會測試到一堆本來就正確的地方(因為沒用到改變的地方),比起在設計時去追溯方法的關係,將會浪費更多的測試資源。

2007年10月28日 星期日

F20 測試錯誤的處理(2)──用Defect System記錄

問題單應該統一開立在一個地方,至少可以使用一個Excel存放;但是最理想的方式還是使用Defect System。後者的好處是可以集中存放,多人同時使用與編輯,而且在與自己有關的問題單改變時,會主動發出郵件通知(Event)而不用時常進入系統查看。

把開立的問題單視為資料庫,我們可以在特定時間點統計開立問題單的數量、退回數量、解決數量、未解決數量、重開問題數量……等等的統計與百分比,這些數據的統計範圍除了整個系統之外,也可以針對各個定義的範圍(模組或功能)統計出各個部件的問題單狀況。

另一個好處是,任何時候遇到系統上的問題都可以先到Defect System上查詢以前是否發生過同樣的狀況,如果有的話先參考之前是如何解決或是如何正確使用的,如果沒有就能放心地開立新的問題單而不用擔心會有重覆的狀況。

類似的系統在系統出版本後,可以應用在FAQ(答客問)的方面,使用者遇到問題或是不會使用的狀況,都能找到一個集中管理類似問題的資料庫搜尋想要的資訊或提問讓系統維護人員回答。

2007年10月26日 星期五

F18 Unit Test(4)──測試Component Interface

表面上Component Interface要測試Interface,但是事實上同樣是要測試實作Interface的所有Class。

測試時每個實作Class生成一個測試類別,每個Component Interface方法都對應一個測試方法,這與Interface的測試策略相同。從Class到Interface到Component Interface逐步的測試,代表的是由組成單位往上組裝成元件的測試,經由一層一層的設計與測試確認,我們得到的將會是穩定度很高的元件。

元件是用來組成系統的最大單位,在元件之上就是系統使用它們的控制流程;測試控制流程的部分就進入到Use Case相關的功能測試與整合測試。參考系統架構設計的圖,單元測試主要是保證的是右下角元件的正常運作,整合測試、功能測試與使用者測試則是針對其他與專案相關的層次加以測試。

註:專案層級裡所有程式同樣也需要通過單元測試,先保證每個Class的方法都正確後才可以進行更上層的測試。

2007年10月25日 星期四

F17 Unit Test(3)──測試Interface

在元件內部的設計層次我們的架構留了幾個介面的存在,介面之下的實作少則一個Class,多的話也有可能超過十個。無論如何,Class測試通過後就要往再上一層的元件內部介面進行測試。

每一個元件內的介面,其往下的實作Class會生成一個測試類別,每一個介面裡定義的方法都生成測試方法加以測試。測試的原則同樣以在時程允許下寫出最多的測試內容為理想作法。這裡進行的已經是小規模的Class整合,有時明明每個Class都測試通過,但是放在一起就是沒法全部測過。就像有時社會裡明明每個人都守分地只做自己應做的事,但是整個社會還是會莫名其妙地產出問題。

Interface層級的測試,是把它之下從實作的Class起的使用關係都視為封裝的組件,測試通過保證這一部分的程式都沒有問題後,才允許再往上一層的元件使用這些層級來組合達成元件預期提供的功能。

註:Class與Interface的測試都要依據使用關係,從沒有使用其他Class或Interface的開始測試起,依序照著使用關係往上測試。

2007年10月24日 星期三

F16 Unit Test(2)──測試Class

Class是系統組成的最小單位,因而同樣也是單元測試的最小單位。設計時讓每個Class都各如其分地負責自己的工作,測試時則確保每個Class都能正常運作,這麼一來採用這個Class組成的大小組件就不會出現基本層面的問題。

一個Class會有一個對應的測試類別,生成的同時應針對public、package與protected的方法產生對應的測試方法,每個測試方法裡依設計規格產生輸入用的資料後,呼叫該方法並驗證傳回值是否正常或是否如預期般拋出例外。public的方法是必測的,package與protected的方法如果可以測試會更理想,然而因為後兩者在包裝層次與元件時可由外部測試來涵蓋相當大的部分,要是時間不夠的時候略過也無妨。

能夠針對規格裡提到的所有狀況都寫出一段測試程式是最理想的,因為測試涵蓋度越大就越不容易有問題,不過測試時大多都只會挑選一些重要的規格,省略測試功能的結果就是有可能讓小問題在未來因為相互影響而成為更大的問題。

註:測試Class的範圍包含static APIs但不包含Abstract Class。

2007年10月23日 星期二

F15 Unit Test(1)──基礎的單元測試

程式的實作都在Class裡完成,元件與系統都是由Class所組成。確保Class提供給外部使用方法運作的正確,就是單元測試所要提供的保證。

程式實作的過程會根據Coding Standard來review所有的程式碼,寫作的風格也有檢查的工具,只要依希望的程式風格設定參數檔後,工具就會依設定檢查程式並條列出不合規定的所有地方。由於改變程式就會有影響,所以在測試之前應先進行review與調整到符合規定的穩定程度再進行單元測試。

Unit Test有測試工具可以使用,對於Class來說會有一個測試用的Class裡面有每個方法對應的測試方法,我們在初始化方法定義每個測試方法之前的動作後,即可在測試方法裡寫下所有的測試動作。工具允許把Class依所屬關係集合起來一次執行,並在結果上註明有哪些測試的動作沒有得到預期的傳回值。

Class本身的方法、元件層次Interface的定義、封裝元件的Interface、系統層次的Interface,由下往上組合而成的各個組件,每一層在測試時都會被視為獨立的黑箱,由Unit Test工具進行所有方法的結果檢查。

2007年10月22日 星期一

F14 Use Case測試(3)──系統整合測試(System Integration Test)

在主要功能(由客戶指定哪些是重要的)的各個層次做好且通過單元測試後,我們必須把這些層次的程式放置在系統架構上,以驗證這些程式放在一起時能否正常運作。

像Client與Server間收送的模組、Context、Flow Engine等與系統架構有關的必定屬於最重要的功能,這絕對是需要優先整合完成的;系統架構沒有問題後,才能把重要功能的程式放上去進行它們的功能測試。整合測試與功能測試要檢查的都是系統執行的正確性,但整合測試時主要是強調系統架構是否可以讓功能的執行順暢且無誤,而不在於功能的內容是否全部正確。

因此整合測試的內容通常會先列出系統架構上的測試項目,接著會基於幾個重要功能裡足以驗證可以被正常執行的項目。不過我們通常會要求重要功能裡的所有測試項目都要通過,因為幾個重要功能可以在架構上完全正常執行,大多代表著其他功能不會因架構問題而產生錯誤。

2007年10月21日 星期日

F13 Use Case測試(2)──功能測試(Functional Test)

正常執行所有的功能是系統最低的要求,也因此通過所有的功能測試是最低的要求。雖然測試功能是非常重要的,但是不要誤以為客戶只注重這個測試而跳過其他底層的測試,因為底層幾個交錯的小小錯誤,很可能讓問題在功能之間相互影響而難以根除──除非重新設計。

功能測試我會分為兩個層次來進行:第一次由測試人員依使用者測試的步驟操作,一方面準備執行的資料,一方面可以藉此先找出操作介面上的基本問題。在輸入好全部的資料執行功能的一開始,用一個暫放的小程式把Context的內容儲存下來,往後測試人員在進行這個功能的測試時,可以使用Hot Key叫出以前的測試值直接重現,可以省卻許多重覆輸入的時間。當然這樣的小工具在功能測試結束時一定要移除。

一邊輸入資料,一邊觀察系統反應,執行功能後再確認執行結果的所有內容都是符合測試項目所描述的。所有的功能都測試成功,就至少符合系統的基本需求。

2007年10月20日 星期六

F12 Use Case測試(1)──使用者測試(User Acceptable Test)

Use Case基於系統架構作完設計後,應該把該功能從頭到尾的使用者操作動作記為測試的內容,並與預期的系統反應比較是否正確。

測試的內容以如何進入這個功能為起點,接著開始一步一步地註明要如何操作系統輸入,有時夾雜一些錯誤的操作以證明系統能夠有正確的反應。藉由逐步操作準備好輸入的資料後便執行功能(功能測試要先完成),同時觀察系統的輸出是否與規格書相同;如果需要再進一步的操作則同樣記錄並加以測試。

每個功能的每個步驟都應該測試正確,在提供給使用者作真正的User Test之前,專案人員當然必須先行測試過讓排除掉顯而易見的問題;沒有使用者會希望給自己測試的系統連立即可見的錯
誤都還有一大堆的。幸好這在功能測試時大多都會被發現。

對於可以正常執行功能的各個步驟與系統反應要稍加註記,因為使用手冊裡的操作步驟會由這些內容依序匯集而成。另外在使用者測試進行到一定程度,確定系統架構足夠穩定、功能可以順利執行且操作介面沒有大礙之後,可以增加同時進行測試的人員數量,藉此開始測試系統在多個使用者操作時的穩定性。

2007年10月19日 星期五

F11 系統整體測試(3)──組態設定測試(Configuration Test)

在設計各個元件與功能時,會有許多設定拉出到允許使用者設定的層級,這些設定的內容都需要加以逐一驗證與測試。

通常的測試都會一一將各個設定檔內容加以調整再進行測試,逐一驗證系統的行為模式。我覺得可以使用兩段式的測試方法:首先先測試設定檔是否可以正常被讀取為Properties;再來就只要寫測試程式去改變系統內部的Properties內容並呼叫對應的測試方法去測試特定的功能即可。這樣一來就可以讓系統一次測試所有的設定檔內容以比對結果。

如果設定檔改變的是顯示時的外觀,必須另外分開使用人力來測試,因為外觀的改變必須要由人來判斷正確與否。如果影響的操作的動作,我們像前面那樣完全由人來測試、錄下使用者的操作或是使用Robot程式來模擬使用者的操作行為,並在關鍵時暫停由人來判斷結果。

組態設定的檔案、內容、測試使用的值與對應的結果正常與否都要詳加記錄的。通常這會在系統測試的最後階段進行。

2007年10月18日 星期四

F10 系統整體測試(2)──壓力測試(Stress Test)

為了保證系統在多個使用者時可以穩定執行,客戶應該都會要求Server必須在多少不同的使用者同時執行任意功能多久時間之下,不能有任何的系統錯誤。

假使系統的要求是一百位不同使用者同時執行功能,通常我們會選用十台電腦,每一台都用不同的Thread執行十個系統同時執行指定的功能,藉此來模擬一百個使用者同時上線的狀況。雖然與真正的情況有點小差距,但是要同時找上百台電腦可是件困難的事情,所以這是個可以通融的測試方式。

壓力測試有時會與效能測試的規格一同定義,比如說單機執行功能時要在三秒內完成,在一百位使用者同時使用的情況下,每位使用者都要在十秒內完成功能之類的要求。效能測試與壓力測試有時會因為瞬間的因素而不準確,因而會多測幾次,剔除絕對不合理的數值後再求得平均值。

或許我們可以像奧運裁判那樣測試七次,忽略最好與最壞的一個只取中間的五次來計算平均值。

2007年10月17日 星期三

F09 系統整體測試(1)──效能測試(Performance Test)

需求收集並加以分析之後,首先要決定的是系統的架構。在設計系統的同時,我們會參考客戶偏好的方式並顧及到非功能需求裡要求的項目。通常可以看到的是客戶會指定一些重要的功能,要求執行時間必須在某個限制之內;還有就是要求處理功能時電腦之間傳送的資料,必須在多少頻寬之內。

要如何加快執行時間與降低系統頻寬是設計時要注重的內容。對於測試來說,速度的測試會在功能執行的開始用Log記錄開始的時間,並在結束時記錄結束的時間,再用個函數求得執行的時間;這樣的測試若能使用程式準備好測試資料執行,同時收集每次執行的結果是最理想的。

在上面的測試裡,於發動傳送的程式點記錄下傳送出去的資料量與接收回來的資料量,會有助於知道頻寬的使用量。雖然網路傳送時會加上封包的大小,但大致上可以求得差距不多的大小,因為我認為這方面做到可以自動測試會比要求完全的準確重要那麼一點點。

2007年10月16日 星期二

F08 最好可以快速地重覆測試

一個系統動不動就上百個功能、近千個類別且上萬個方法,即使已經有所取捨,但是撰寫測試內容所花費的資源還是很多;當然實際測試時投入的資源一樣不少,也因此在求快型的專案中決策的人有很多決定只粗略地進行測試工作。

首先要注意的是要建立起系統項目與測試項目的關連,先建立起明確的關係才能在需要測試時立即知道進行哪些項目就能保證那些產出運作正常。在第一次測試時測出的問題會經過修正,修正時會進行影響評估得知另外改變了哪些模組,所有改變模組的測試項目都應該要重新進行測試。

沒有建立起關係追溯的系統就會在這個時候開始失衡,因為沒有辦法判斷出改變設計時的影響,也沒有辦法得知改變影響後相關的測試項目,甚至連對應的測試項目都不存在。這樣多改個幾次之後,整個系統就開始混亂。

為了避免重覆測試時投入過多的資源,最好是選擇可以自動重覆測試的工具與方法以節省測試時投入的資源。在具有自動測試比對的工具裡,需要重新測試模組的時候只要點個開始,就可以等著得到該模組甚至整個系統的最新測試結果報表。這應該是最理想的結果了。

2007年10月15日 星期一

F07 測試計畫、項目、步驟與結果都要留下記錄

測試相關的內容是基於功能與設計的結果而決定的,範圍的取捨與項目的決定會被列成清單來表示,最好在清單裡記錄著所有應測試的項目再註記哪些項目因為什麼樣的原因而在此不作測試。

在功能的測試方面,有測試工具可以管理所有的測試項目。每個測試項目對應到一個測試劇本,劇本裡可以編輯測試步驟的內容與順序,另外在需要檢查的步驟之下可以插入一個結果描述,測試的時候操作完該步驟後就核對是否與結果描述相同並加以記錄。經由測試工具管理的測試結果,可以依不同的需求產生出測試報表。

在程式的測試方面,有單元測試工具來管理所有類別方法的測試項目。定義好要測試的類別與其方法,在測試的方法裡用不同的參數內容呼叫要測試的方法並核對結果,依此作為測試是否正確的依據。在單元測試工具裡,可以一次測試所有的測試內容來判斷現在版本的系統是否運作正常。

把所有的測試作記錄,我們才能明白每個功能各有哪些測試、測試了什麼項目、用什麼方式測試與所有測試的結果。由於測試與各層次的產出都有關聯,這也是需要另外再記錄下來的關係。

2007年10月14日 星期日

F06 測試計畫的內容與涵蓋度(Model)

每個測試的功能或組件,必定都有其對應的規格書。根據規格書作出的設計一方面交給開發人員實作,在擬定它的測試計畫之後還要再進一步擬定要測試的項目,還要決定測試時的流程與每一個測試的步驟。

將每一個測試項目裡的每一種可能都至少測上一遍可以說是完美的測試,但是別忘了想出所有測試可能並對應每一個可能編寫一個測試劇本,必定是個勞民傷財的動作。因而一般來說,只會選擇一些非測成功不可的內容來決定劇本;但是在這樣的取捨之下,雖然保證主要的功能可以如預期般執行,但是必然會有些很少見的現象將導致系統有些小小的問題。

每個功能或方法都有它的目標與期望的結果,還有一些必須處理的錯誤狀況,這幾項應標註為必須測試的內容。由於分析與設計的人是最明瞭規格者,所以理論上應由他們決定測試的項目範圍,並參與測試流桯與步驟的制訂討論。

測試階段相關內容模型:

2007年10月13日 星期六

F05 擬定系統的測試計畫

當決定系統的架構並確定功能清單之後,首先要擬定並執行的是設計與實作的計畫;測試雖然是在實作開始之後才有可能施行,但是由於有些測試的資料來源在功能描述裡就有,所以此時也適合開始計畫測試的時程。

可以根據F03圖裡區分的開發階段,先決定在各個階段的產出要進行哪些種類的測試,並概估每個階段裡的所有產出大約需要進行多少時間,並將之排在實作階段的中後期開始陸續進行。以系統層級來看,能夠先行處理的階段是硬體架構與系統功能的部分。

接下來進行的階段,每個層次與每個元件的負責人員也必須依照原則來擬定測試該層次或元件的時程。務必記得測試的計畫根隨著功能的切割,每一塊組件都應該要有搭配要進行的測試計畫。測試計畫必須在該組件設計完後進行,測試內容則必須在實作完成之前全部擬定,因為實作完成後應該隨時可以進行測試,而且要由最底層開始往系統上層進行測試。

2007年10月12日 星期五

F04 測試的項目與內容都來自功能

設計的目的是要做出一個與預期目標相同的產出,經由該產出我們可以得到與描述相同的結果;而測試就是以設計時指定的方法去驗證該產出真的可以得到那個結果。

在系統架構、系統功能、架構設計、細部設計與程式實作時,我們對於每一個需求項目,都會設計出一個對應的功能。每個功能都會記錄它的目的,並敍述經由什麼樣的設定、輸入與操作,將會獲得什麼樣的產出與結果;測試時所要做的就是準備好符合輸入時的設定與資料來執行該功能,並經由驗證結果是否為預期中的結果來決定它是否正確。

一個功能的執行有正確與錯誤的結果,除了要驗證正確的結果之外,也必須準備預期會產生各種錯誤的資料來驗證功能是否能夠處理。因此,功能描述裡提到的正確結果與錯誤結果的總和將會決定測試項目的數量,有時同一種結果會經由不同的輸入達成,此時根據輸入而也會有不同的測試內容。

測試的準備工作是繁複的,我只能說準備得越多就有機會讓系統執行更加正確,而且日後有人詢問說這個功能作過哪些測試的時候,只要拿出測試項目、內容與測試結果就能夠完備地回答這個問題。

2007年10月11日 星期四

F03 測試的層次對應到設計的層次

在系統目標的那張圖上,闡述了系統從使用者的想法慢慢變為需求、功能與程式的各個階段。每個階段除了記錄性的文字之外,所有基於設計而實作出來的所有程式與設定檔都必須經過詳細的測試,來保證每一個產出都是能正常運作的。

從最小的程式開始,往上的程式介面、元件介面、架構介面每一層都應該有自己的測試內容;嵌入到系統架構之後,還有設定檔正確性、執行速度與同時可執行數量的測試。系統測試的種類與項目在不同的事件發生時,還會有不同的定義,比如說系統正式上線後才修改後的回歸測試。

這裡列出的是我認為系統內所需要最小數量的測試,分別對應到開發系統的不同階段。如下圖所示:

2007年10月10日 星期三

F02 應該保證每段程式都可以正常執行

只要人做的事就有可能會出錯,不管是忘記記錯或者是疏忽,在處理系統的各個階段與部分都有可能會有錯誤。使用者總是希望拿到趨近零錯誤的系統,因此找出系統現在存在著的問題,就是測試所負責的任務。

在求快的專案型態裡,測試的目的通常只是要求到使用者看得到的部分,也就是以系統的功能與效能
合乎規定為主;只是功能的正常並不表示內部所有的部件都各司其職,有時幾個地方都有小小的錯誤,反而使用最後的結果負負得正而沒錯。完整的測試應對於設計出的所有產物都有各自所屬的測試計畫、測試項目與測試內容。

測試的項目與內容涵蓋的範圍越趨近於設計的規格,就能夠保證在測試時驗證過的狀況在未來都不會再有錯誤(除非因需求變更而修改過內容),就能使得測試過的部件有越高的正確性。如果想要快速測試而花較少的時間準備測試個案,可以想見沒有被測試個案涵蓋的部分都還是可能有錯誤存在。

如此由下而上,從保證底層物件的正確性開始,一層層地往上測試各個部件並加以整合,到最後完成時我們就可以獲得一個穩定性極高的系統。

2007年10月9日 星期二

F01 系統是為了哪些人而存在的?

一開始,客戶會有對於未來系統的“想法”,雖然有些想法會過於理想,但是訪談的系統分析師要依據可行性記錄想法並分析使之成為具有完整描述的“功能”。功能可以說是系統的組成單位,因為從這裡開始會有不同的展開。

依據功能規格,程式設計師會以“設計”使原先使用者天馬行空的想法成為可能實現的藍圖,接著程式寫作員會將設計的功能實作為可執行的程式碼。在功能可以執行的時候,為了要保證日後交給客戶的系統是趨近沒有錯誤的,就需要經過“測試”的階段來除錯並修正。

功能在被設計並實作時,對日後使用系統的人來說除了系統執行看得到的部分外都是不可知的黑箱,因此還需要文件來“說明” 讓使用者如何操作各個功能。如果想要系統順利完成並驗收,這幾個項目都是必須做好的。

2007年10月8日 星期一

E30 萬物生息皆有其道,設計系統亦同

在早期的工作歲月裡,曾經我也認為達成系統要求的目標即可,但逐漸累積經驗後我慢慢感覺設計的東西要能彈性地應付需求的改變,才能夠正確實用在多種不同的地方。但是缺乏實際的方向時所能改進的地方其實是很有限的。

2004/07公司裡有講師講授OO-226 (B)的課程,那時第一次聽到這類的設計方式感覺似乎不錯,但是那時還無法理解。2005/10公司派我到恆逸上OO-226 (C)的課程,這次的課本編排得很好,所以聽起來也格外用心;只是聽完後依主管要求在公司講解一遍時,只能食古不化地依內容照念。

2006/01起公司開始研發自有產品,這時我大膽地與同組人員決定使用OOAD來做,不過當時原擬定四週的設計,光是Data Model就做了兩週半才定稿,與其他直接寫程式的組相比落後許多,但是在03/26那天初次感覺到OOAD的融會貫通。

2006/08接手了沒有一行程式是自己所寫的那個產品,除了首次以正式的方法進行錯誤的修正與需求的變更之外,也漸漸明白沒有分割好設計層次所得到的程式有哪些問題。2007年在公司又陸續講了兩場OOAD,加上聽過一場軟體工程的講座便興起了將自己OOAD的想法記錄下來的念頭。

2007/05/30開始在Blog上以每日一小篇的方式記錄,原先的計畫是以百篇上下的內容描述整個系統的開發與維護內容,但是一邊撰寫又一邊領悟到新的想法,現在到這裡已經成長到超過130篇,看來整個系統寫完應是200篇左右。

思索與領悟的過程裡,感覺在實作與設計之上還有一個“道”的存在,所謂的架構設計、細部設計等等都是依循那個常理所必然生出的產物,而且唯有領悟到那個道才能設計出理想的系統。現在的我也只不過是初次感受“道”的存在的新手而已……。

2007年10月7日 星期日

E29 設計的終點(6)──穩定、容易改變、又能快速開發

綜合以上所有的想法,開發一個系統時,我會先著重在MVC的分層設計,每一層再分為Implementation-Controll-Action三個小層次;不管大的層次或小的層次,其中的設計都使用Interface來規範裡頭打算要做的事情,Interface的實作程式會依需要去使用已經開發完成的元件並加以控制

每一層往上會去思考套用Design Pattern的可能性,再適當地改寫為適合作流程控制的寫法,甚至更進一步地做成基本框架的類型。把每一個功能與層次的內容與作法都定義出來,再統合審視可能性與適用性並修正,等專案人員都同意之後就定義出工作項目並發配下去進行。

系統經過精密切割後分層開發,每一層都檢視看哪些可以利用reuse的元件,在寫作的同時讓別人明白裡面在做什麼,並在與其他各層銜接的地方加上吸收改變的避震器類別。每一層都可以方便使用實作,又可以輕易改變內容,如此一來專案的品質將更穩定,開發速度也會比之前更快。

第一次的實作會是辛苦的,因為要比直接做一個專案花費更多的時間。決策上如果確定未來有類似的專案需要開發,那持續往這個方向改進會是最有利的。

這張圖要表示的是所有實作元件與檔案之間的關係:

2007年10月6日 星期六

E28 設計的終點(5)──以做成基本框架(Framework)為目標

把原先用程式表達出來的動作與邏輯,使用文字描述的方式來表達並依序實作,這是撰寫程式之上的另一個層次。

把文字設定讀入依設定生成程式來動作,概念與Web Service裡把XML再生成Data Model差不多,但是需要處理動作與順序,複雜度倒是有過之而無不及。雖然開發這類基本框架的處理需要能力更好的人才做得出來,然而一旦規格開得理想又能完成的話,應付未來的需求改變時,投入人力的數字與門檻就可以降低很多。

Data Model與Controller的基本框架是可以實現的,View當然也可以。同樣應用一組XML的設計內容,我們可以在不同的需要上將之轉變為不同的外觀,無論是哪一種程式語言所使用的UI,甚至是瀏覽器使用的html都可以分別以產生程式來產生。如此一來,整個系統都能夠大量地以設定的方式來生成。

2007年10月5日 星期五

E27 專案分析工具(4)──讓編輯工具能自由決定設定內容

對單一專案而言,製作出分析設定編輯工具之後已經可以算大功告成,但是更理想的狀況是針對用途不同的系統也可以reuse這樣的分析設定產生工具。

不同用途的系統有不同的思考方式,首先就會有不同的設定檔,有不同編輯外觀,也有不同的對應方式,當然匯出到系統的處理方式也有所不同。設定檔可以使用元件對應到Project Data Model,編輯外觀可應用通用編輯器再加工使用,儲存的對應方式與匯出的處理動作能夠使用Flow Engine的架構讓使用者撰寫對應的程式;如此一來在Model-View-Controller三個部分都可以有快速完成的方式。

撰寫客製化的程式已經具有相當的便利性,但是需要一定的程式功力與經驗才能寫得好,資深的設計與寫作人員在專案裡已經不多,有時候會難以再抽出適當人力做出這樣的工具。如果專案需要的工具設計變得容易製作而且沒有問題,是不是大家都渴望的呢?

2007年10月4日 星期四

E26 設計的終點(4)──用程式封裝商業邏輯與設計邏輯

應用Baisc Data Model的觀念,專案的分析與設定記錄就像是外部的檔案,為了更方便地編輯檔案的內容,我們可以使用通用編輯器來擴充為專案用編輯器讓使用者直接編輯並存檔。

在編輯器上編輯的欄位可利用提示文字與輔助說明描述欄位值要如何設定與會有什麼影響,使用者只需要參考詳細的說明來設定,就可以得到正確改變系統內容或運作的結果。這裡引用的技巧在於使用者按照說明設定的值,在匯出動作的同時被一組負責處理匯出的程式依設定在程式裡轉換出系統對應的輸出。

用程式封裝邏輯就是編輯器與轉換器最大的任務,無論是系統的分析與設計還是系統執行時的設定檔,利用編輯器明白地告知使用者所有設定即將造成的影響,再使用轉換器讀入設定值並反應出應該要有的動作。

減少懂得設定之前學習曲線與設定時的花費時間,將有助於所有人員對於系統的了解、使用與操作,這也會是節省專案開發時耗費資源的最大捷徑。

2007年10月3日 星期三

E25 專案分析工具(3)──將分析與設計的記錄匯成產出

再進一步想,以文字檔形式讀入的其他專案內容有Flow Engine定義檔、訊息內容檔案、元件設定檔案……等等,凡是在執行時期以文字檔案生成或設定系統的一部分者,都可以使用程式將記錄加以轉換產生。

由於實際系統的產出分散在許多地方,在取得清單與比較內容這樣的組合動作上都比較不易處理。倘使用集中處理再匯出的方式,同時加上把系統實際產出內容抓取到集中處理的設定檔,這樣就可以擴充到取得系統的目前狀態並加以修改再匯回系統的處理模式。

雖然集中處理檔案設定的內容,已經可以加快設定與產出系統檔案的速度,但是要去產生或編修相關的內容卻還是需要對系統內部有相當程度的了解。為了讓並未完全清楚系統運作的人員(甚至是幾乎不懂系統內部的使用者)能夠順利地正確設定,勢必還需要有輔助的設計才行。

2007年10月2日 星期二

E24 專案分析工具(2)──需求分析與設計的記錄

在需求分析與設計時,我們需要對收集到的資訊加以分類並整理,要能明白每個功能是由哪些動作所組成,而那些動作允許有哪些檔案與內容的存在。分析出來的需求規格書會以文字描述為主,接著對應到設計的設計規格書就會將文字描述轉換為應有的系統產出。

專案的整體設定、各個功能的需求規格書與設計規格書,在實作的觀點來說全部都是在描述系統即將會有的產出。通常程式員會依照規格的內容,逐一做出專案裡對應的所有產出,這一向都是最花費人力資源的工作。

試想,以上的文件與產出其實都有關係存在,如果我們把所有的內容與關係都定義在表格裡的話,系統分析人員就只需要把想法填入表格就可以期望未來有對應的產出。這個概念,就像是設計時把想法直接放到Design Model,再經由其他的工具轉換出我們期望的文件(產出),將會節省許多開發人力。

2007年10月1日 星期一

E23 專案分析工具(1)──執行設定檔的編輯器

我一直強調在設計時,一定要讓影響程式運行的參數定義在外部的文字檔(或資料庫),最大的理由就是讓改變設定不要發生在程式內部,因為設定會由人來決定要設定什麼。如果封裝到程式裡面的話,只要一改變就會需要作改變的追溯。

在設計時依據架構設計的原則,產出層次整齊且方式一致的設定檔案,會比較容易讓使用的人找到想要的設定內容。在提供給使用者修改的大多情況下,由於必須防止程度較差的人作出錯誤修改而導致系統停擺,所以都會準備編輯器;透過編輯器可以只顯示出使用者可以修改的地方與現在的值,使用者只能輸入經過檢核的值而且保證以正確的格式放在正確的位置。

利用通用編輯器可以對應編輯一個檔案,我們可以收集專案所有設定檔清單加以分門別類,做出一個符合專案範圍的設定檔編輯工具。這時對於使用者而言,只要打開編輯器就可以保證看到的是他全部所能調整的設定,同時也不用擔心輸入錯誤的問題,因為這些都已經被編輯器加以管理。