有一派的程式設計者,在收到工作的需求(通常是設計好的介面)之後,他們會認真思索如何進行實作,考量效能、彈性、擴充性、可維護性、等等在設計時會考慮到的諸項要素,力求一次到位,一次就寫出效能好、彈性高、擴充性好、容易維護的程式碼。

不過,也有另一派程式設計者,並不習慣採這種一次到位的寫法,而是先試著做出一個很基礎的版本,不求效能最快、程式寫法可能沒什麼彈性、也不好擴充,也沒有考慮日後容易維護,甚至功能還不完備,就是初步的能動。

當然,並不是這樣就把工作打發掉,先求能動是只個開始,程式基本上能動有幾個重大的意義,首先,程式能編譯而且執行了!這看來簡單,但是,如果你打算一次到位,那麼,你的程式就不見得時時刻刻處於能執行,甚至可以成功編譯的狀態。因為「一次到位」的寫法通常比「先求能動」來得複雜許多,需要花上更多的時間、更長的程式碼,才有可能將實作處理完備。

一次到位與先求能動的比較
或許,複雜的寫法,總是可以持續保持在可編譯的狀態,但是,不見得可以保持在讓主要功能可執行的狀態。

因為,實作的方式複雜許多,所以,在實作完成前,時常都是處於不能正常執行的狀態。相反的,在「先求會動」的哲學底下,可以很快的有一版出來,即使這時候還有很多的限制,但起碼,主要的功能都可以執行了。

程式的主要功能能動了,代表相依此模組的其他模組,也都可以實際進行整合了。雖然,這些模組想要提前整合還有一些其他的方法,像是利用Dummy物件來提供同樣介面、卻是寫死或簡單的實作。但是,相較於真實的實作,這終究不是真正的整合。

許多整合的問題,還是要等到實際的實作出爐並整合後,才能發現。因此,可以開始實際的整合,也是一件意義重大的事。

很多時候,主要功能的實作,倚賴一些關鍵的技術,或是想法。

先試著將這些技術套用、或是具體的落實這些想法,可以驗證技術或想法是否可行。當然,有些人會在開發之前先做POC(Proof of Concept),確定關鍵技術或是想法是否可行,但若少掉了POC的程序,這種「先求能動」的實作哲學,就可以在初階段的實作中,融入POC的作用。

先求能動的做法,可讓問題提早出現

不論是提前開始整合,或是驗證關鍵技術及想法,都能對開發時的風險評估帶來好處。

當你還沒有開始真的整合之後,所有的事情都只是在想像中發生。以前有人用「過山洞的火車」來形容這種感覺。

還沒整合之前,就像進了山洞的火車,因為洞裡沒有光線,所以,你無法預測究竟何時才能離開山洞。當你開始真的整合之後,即使有問題,起碼你也知道有什麼問題。因為問題曝露了,所以你會知道究竟還需要解決那些問題。

關鍵技術或實作想法的落實也和提前整合一樣,都能夠提前讓問題浮現。對於可能發生但卻不見得發生的事件,只要有可能影響到開發專案進程的,都是風險。愈早知道整合時會發生的問題,或愈早知道實作的想法是否的確可行,都可以讓評估風險的時間點提前。這意謂著你能更早開始運用資源調度來面對的風險發生,並且加以處理。當你在專案的愈後期,才偵測到這樣的問題,那麼一旦專案的資源──尤其是當時程已無餘裕時,就無法妥善地處理。

先有一個能動的東西,這意謂很多事情都可以在一個穩固的基礎上進行討論,因為大家看到了一個具體能運行的產物。即使它有問題,我們也更容易估計解決這些問題需要再花費多少時間,而不再像是在談論一個空中樓閣。

減少做白工的機會
除此之外,這種方式還可以避免掉一些「過度工程化(Over Engineering)」的可能性。

有時候,想「一次到位」的想法,會引導設計者多做了許多額外的實作。例如,設計者可能希望提供最佳的效能,所以處心積慮的在各個環節做效能的調校。以及最佳化。但有時候,在初實作時,不見得能、甚至很難預測系統真實運作時的動態行為。在這種階段所做的效能最佳化動作,有時反而是瞄向了錯誤的方向。但是,整合到真實的系統之後,起碼可以捕捉到系統真實的動態,對於究竟需不需要在特定的環境上做效能的調整,也就有了基礎的答案。

我們可以用最簡單的方式來做,「先求能動」之後,一個能動的產物,就能讓系統真實地運作起來,而真實能運作的系統,可以回答你很多事情。

一個很簡單的實作方式,對你而言,可能知道它有什麼潛在的缺陷,但也可能不確定。對於你不確定是否會有問題的方式,在整合到系統後,就會由系統來告訴你它究竟有什麼問題。如此一來,往往會發現,在實作前的對需求的許多想像,其實都不存在。

你可能會想像,它應該需要有多快、多有彈性,但當你真的有了一個能運作系統後,你或許會發現,這些需求其實根本就不存在,是自己想太多了。

當然,需求也有可能真的的確存在,但沒關係,當需求證明它自身的確存在時,再來進化你的程式碼,常常也仍為時未晚。這就能避免「過度工程化」的情況。

讓整合先發生

而對於一個你已經明知它有什麼缺陷(例如效能一定不夠、或是能處理的資料量有限)的實作方式,你可以讓整合先發生,之後在保持介面不動的原則下,持續的進化內部的實作方式。外界的程式碼不受影響,而已知的缺陷,卻可以因此獲得改進。

這並不是說「一次到位」的設計方式不可行或較劣,相較於「先求能動」之後再持續演化,「一次到位」若能精準到位,其實是最節省成本的。

因為演化乍聽之下很理想,能持續的依據最即時的需求來將程式碼調整成對應的形式,但是,演化路線中的曲曲折折,就是需要付出的代價。

二點間最短的距離是直線,有了曲折就代表要付出額外的成本。但是「一次到位」的難處在於,我們都不見得有足夠的能力和智慧,在第一次就預見了終點的位置。不過,對於有些應用而言,需求明確、對於風險也都有很高程度的掌握,與其日後花費額外的時間和力氣反覆在演化工作上,不如一次直達終點,反而更節省時間及力氣。

因此,不同的情境下,是應該採取不同的策略。

「先求能動」之後再持續演化,在曲曲折折處額外付出的成本就像是在買保險,我們付了一些保險費,就是希望我們犯錯時還有機會彌補,不致於孤注一擲。

不過,好的設計、實作技巧,可以讓我們少付一些保險費。為了因應持續的改變或演化,有一些設計、實作的技巧,可以降低演化時所付出的代價。

這意思是說,我們可以用更少的錢買到同樣保障的保險。當你選擇了「先求能動」再持續演化的設計方向時,你愈熟悉這些技巧,就愈可以省下更多的保險費。也有些情況,你知道風險夠低,選擇「一次到位」反而更為划算。

 

作者簡介


Advertisement

更多 iThome相關內容