2008年12月25日 星期四

S25 理想元件結構的自動化產出

我最終的理想是將所有產出的程式碼視為一種Model,用方法論約束以形成為固定類型的結構,再撰寫(或找到適合的)應用工具導出到各種方向的結果。這裡記錄的是自己現在認為“應該且可以”具有與可以實現的同步轉出功能。

分析的最小單位應該是Method。每個Method在以規定的方法撰寫並註記合格的註解時,就可以將所有Method視為能用同樣方式存取的Model,依其特性與原則必定可以設計出工具程式自動取得以下的資訊:

◎所有的傳入參數
◎所有的傳回可能值
◎所有的使用資料、參數(常數)與例外
◎所有的方法呼叫(包括同一個Class與其他的)
◎所有使用常數與呼叫方法所屬的Class(使用關聯)
◎使用XML定義流程處理、依設定檔deploy出攤平的程式碼(執行速度變慢才會做)
◎程式的完整流程(搭配輸出工具可以產出流程圖)
◎所有判斷指令內依賴的條件清單(每個條件都附上所有可能的傳回值)
◎所有的變更歷史清單(包含日期)與改變的程式
◎Commit時產生所有需要填寫的變更註解


Method是最基本的單位,往上推展依序是Class、Component Package、Package……到最後就會達到Use Case Package。從最底層精確地產出每一個單位的完整記錄,往上產出時就能拿到百分之百正確的資訊,到最後產生一個關聯與影響的龐大結構,我們可以選取任一個方法作為起點,就可以拿到自己使用到哪些方法(與所屬Class)與哪些方法使用自己完整追溯結果。其實還不只如此,我們甚至可以在任何一個指定層次取得之下的所有資訊匯整出文件。

一直以來額外花時間製作程式文件與修改後同步文件的工作都是程式開發者頭痛的問題,多花一倍時間把原來設計程式時的想法再寫一次,文件或程式修改後還得要同步另一份的資訊。文件與程式相互依賴的關係是如此之多,只要有任何一個沒有更新為對的資訊就會造成兩者各做各的,完全失去原有的意義。

“完整規定程式設計產出的結構、要求在該寫註解的地方填上必要資料“,這是我想做出來的程式設計方法論!

2008年12月24日 星期三

S24 沒人想做的事裡有值得學習的道理

進社會找到了第一份工作,當時使用的作業系統與程式語言是全國唯一使用的,基於自身經驗不足想說有個穩定的工作再說。公司接著陸續應徵了許多人要做與我相同的工作,但是大部份的人在發現使用的是這種冷門技術後都很快消失,很快地除了主管之外就屬我最資深。

公司是製作電話語音系統的,在第一年裡我慢慢摸索後建立了一些好用的函式庫,第二年主管將我調到連線的部門去學習撰寫Gateway的技術。工作了兩年多後因故離開那間公司,在新公司裡綜合了前面兩年的經驗,以不同的作業系統與程式語言用相同的概念製作了另一個語音傳真系統。

2006年主管推派我當公司的福委,在幹部選舉的會議裡被拱為主委,起初對這種吃力不討好的職務頗為反感,不過從另一個角度發現有人出錢讓自己模擬公司的運作也是不錯的事。經歷幾個事件後倒也瞭解了行事曆、事件流程與資源規畫的道理,反而在OO的分析方面有了不同的體認。

同年公司製作的自有平台產品後續需要有人維護,在所有能夠接手的人選裡由於我之前沒有在專案裡奮鬥,因此選擇了我。接到問題後想辦法重現、確認問題發生處、無法解決的、詢問原作者、修改後程式比對、確認並撰寫影響報告、另外加上補齊一些需要的文件,這些事情其實都是工程師們很不願意做的事情。

這段時間其實做得很痛苦,因為要在說明極少的情況下去看懂沒有任何一行是自己所寫的系統,任誰都沒法輕鬆愉快的,但是我卻在不知不覺中累積下不同的經驗。做一個動作時去明白為什麼要做、做的時候缺乏什麼資訊、那些資訊可以在什麼時候由什麼人產出、動作做完之後可能產生什麼影響、影響的範圍在哪裡,腦中累積很多很多之後就開始思索要怎麼做才能改善現有的狀況,有了初步想法之後就開始在這個部落格裡記錄。

2008年12月23日 星期二

S23 專案問題產生原因之可能破解

專案時程給得過於緊迫會有這幾個後遺症:功能急著想完成忽略所有可能的例外、SA與SD收集分解動作的不完全、動作難以抽取或分派形成過多的重覆程式碼,最終造成難以調整的複雜結構。根據以上問題我採用的應對方式是從後面開始解決起。

首先是適合調整的軟體架構,依之前提到的軟體結構設計出放置程式的Class,確保每一個分解動作的程式都是分離且容易移動的。其次是找出適合SA與SD使用的工具軟體,在分析設計每一個Use Case的同時還能以整個系統的角度來思考與放置。最後則是具有大量元件的函式庫,分析設計出來的分解動作在以前若已經依理想的方式包裝成元件,那麼應該有理想的解法同時包覆著許多例外狀況的處理而能夠直接引用,考慮的重心就可以移到多個Use Case共用時產生的各種條件變化。

公司在數個專案間有共用的Jar File,在其中一個專案上線後根據其他專案遇到的問題陸續修改了其中一個。後來在上線專案那邊找到同一個Jar File的重大改變,但是我只敢改在原來的檔案裡而無法直接更新為最新的版本,因為我無法保證沒有side effect。主管說多測試後就可以用,我回答說就算投入一百個人測試,只要沒測到全部的流程就有可能出事,全部的流程卻又是眼前無法提供出來的。

就像以前提到的紅豆與綠豆的例子,在不分類的狀況下全丟在一起是很快完成的,但是未來遇到想分開的情況時會花更多時間。剛開始只求功能的完成,只要豆子的總數對怎麼放都無謂,但是在專案到尾聲時任何一個變動都可能牽一髮而動全身;如何拿出可以掌握任何改變的關聯與影響的追溯結果,正是維持品質的關鍵因素。

2008年12月22日 星期一

S22 專案的痛苦在投入時間的不足

常聽人說專案給的時間都很緊迫所以沒法把設計作好,有次我就反問同事說如果現在有個專案給的時間非常充足,那會怎麼做來作好設計呢?他想了一下暫時沒有答案,不過我倒開始思考壓迫時程之後會造成設計上的什麼問題。

兩點之間最短的距離是一直線,完成功能最快的方式就是只直接寫出達成所需的全部動作,其他狀況就依經驗想得到的就做,所以此時完成的程式根本只夠做出達到目標的動作,沒空細想可能的變化。這樣先天不足的設計,若加上寫的人想偷懶只先寫一部分其他等測到再寫的後天不良,在動作層次不分、判斷條件不足的情況下如果測得出來問題就算幸運,沒測出來等客戶測到或是上線才爆發,那可只有一個慘字能形容。

客戶需求變更的管理是讓系統穩定的因素,但是時程過趕的狀況下,SA與SD沒有完全收集到Use Case應做的全部動作,未來發現缺少動作時就得再補上。一般無關緊要的動作直接補就沒事還沒話說,就怕缺少有關鍵性影響的動作與根據之前資訊所作的設計有所衝突,此時每加上一個就像一次重大的需求變更(或是需要抽取與分派的狀況卻無法重構而硬塞許多重覆的程式碼)。在這種狀況下作出來的設計怎麼可能有穩定的品質呢?

有次與總經理談話的時候他說:管理階層解決問題才是眼前重要的事。但是眼前的問題卻是之前專案模式所殘留下來的後遺症,再加上人設計程式時被測試抓到一項才承認一項的惰性,因而形成令人詬病的品質問題,到頭來需要投入更多額外的人力去找出問題。麻煩的是找到問題後即使知道怎麼改也會擔心影響其他大部分已經正常的功能而無法從根本改起,進而造就疊床架屋式的結構。

2008年12月21日 星期日

S21 做人的方法(15)──有關聯必有影響

物與物之間都是單獨的個體,初始時相互之間是沒有關聯的;物之間的關聯可以想作為有事發生才讓彼此產生關聯、互有影響。兩個物之間可以建立的關聯種類要看兩者之間能夠發生哪些事件來決定。人與人之間會有下面幾個事件與關聯的發生:生育(父子)、交往(情侶)、結婚(配偶)、看不順眼(仇家)、認同(朋友)……等等。

清楚與其他人與物之間的關聯、用對的態度面對接觸到的所有人與物是保持和諧的基礎。用錯誤的態度強欲建立起不自然的關係、在不應該做的時候依舊做了某件事、在該做某件事的時候沒做或未做好,就會使得事物之間的關聯失序而形成混亂。像是偷摘公園裡的花朵、將垃圾隨意丟棄、遇到親友視而不見……。

單純的事件失序時不見得會出問題,在很多時候問題都在於環環相扣的事件影響,像滾雪球般地造成連瑣效應而無可挽回。社會新聞裡偶而會看見原本兩個人在路上擦肩而過,因互看不順眼互罵進而互毆,甚至打電話邀集人馬示威,最後由於支援的朋友裡有人不慎擦槍走火而致人於死。觀看這類事件時人們難免會想:如果一開始擦撞時能夠忍一口氣的話就不會有這種後果。

任何的果都有因,從眼前的果探究形成的原因比較容易,但是在因一呈現時就能分析其利弊與影響而找出最理想作法的話,很多後來的事都可以消弭於無形。人生的經驗就在於收集世界上人事物的因果關係資訊,當某個人事物出現在眼前時,快速地分析不同的處理場景會造成哪些不同的結果影響,再從中抉擇出最有利於自己(有能力的話要同時有利於別人)的作法。

平時大量地收集資訊、條理化儲存資訊建立腦中的資料庫,遇到事件時快速分析並列舉出關聯資訊,最後判斷出一個結果最優化的決策。無論在什麼樣的場景,這個簡單的道理卻適用在整個人生。

2008年12月20日 星期六

S20 只要……就好了?!

這句話如果成立那真的很好,但是說這句話的時候到底是否評估過真正的關聯與影響?或者評估的內容有誤差?抑或僅是安慰可能受傷害的一方?就真的得審慎判斷了。

學生時代時若有同學請你抽煙同時還說:擔心什麼,只要不被教官看到就好了。半夜搭計程車闖了紅燈,司機說:半夜沒有人車,只要沒有警察就沒關係。若以會不會抓到角度看待自己所做的事情,社會秩序就會永遠這麼混亂,個人的生活同樣也會雜亂無章。

公司在其他客戶那邊有前一代的產品,客戶一直希望可以升級到現在的產品,但是由於在設計上的變更而無法直接相容升級。為了符合客戶的期待,有人提出一個簡單的方式:比對兩種產品,把相同的抽取出來放在一起,不相同的整理出相容的界面提出,然後不同的實作各自放在不同的地方,只要依此原則弄成三個專案就可以符合客戶需要。

主管問我的意見時我說:要滿足客戶的需求這樣最快沒錯,但是未來程式有變動時就很慘。一個改變要先研究出應該放在哪裡、程式改好後放回去可能得測試三遍、版本變更清單也要分三處處理,如果提出這種作法的人願意來做維護我就沒話說,我是絕對不接手這種東西的。主管說會再考慮看看,不過後來客戶也沒接受這種作法;一旦設計沒法相容在一起,幾乎是沒可能再合併的。

這個句型在顧前不顧後的案例發生時,至少還可以滿足眼前的需要;有時一聽就感覺有漏洞存在時才更令人無力,那時都會直接反問要是狀況之外的例外發生時該怎麼辦?想要能夠提出“只要……就好了”的說法,務必要對問題的所有發生條件與關聯影響都胸有成竹後再講出來,如此方能應付所有提問的可能狀況不致漏洞百出。

2008年12月19日 星期五

S19 讓流程中蘊藏彈性的思考

即使在軟體架構上使用了最靈活的設計,但是由於架構僅是靜態佈置的框架,實作的功能劇本仍然靠流程設計來達成;功能流程的設計的正確性與成熟度就得看是誰來設計的。如果動態的流程設計僵化而難以變動,不管放到多麼有彈性的軟體結構裡都完全不會有絲毫改善。

在流程設計過程中面對所有的動作時,可以思考是否符合這幾個原則:

整合與拆解:做一件事所需的動作拆解的步驟單位大小。切得太大步驟難以再細分、切得太小控制會太瑣碎,最理想的還是依現有層級的最適大小。分解步驟的恰當將會使得流程更容易設計,較不容易有盲點,也容易作不同方式的組合。

抽取與分派:某些不適合自己處理的步驟交由其他負責單位進行,將工作分派出去會讓自身的工作內容單純易管理;不過遇到別人的工作內容與自身的類似時就要考慮將工作抽取到同一個地方進行,以免造成多頭馬車的現象。

單一與重覆:一件事即使可以處理妥當,有時會需要處理集合內的多數相同事情;相對地也有可能將循環處理的事切分出可以單獨來做的。設計時若遇到有迴圈的地方,都盡可能把迴圈中的動作拉出為可以獨立呼叫的方法。

拆解與變動基本有三種不同的方向,但是其根本的原則還是在於把過程分解為一個個獨立無依賴關係的分解動作,再將各個動作放置到它應該存在的結構位置。只是憑個人去設計所有流程動作總會存在死角,藉由其他人的review與回饋才更能補齊各種可能的思緒。

2008年12月18日 星期四

S18 Review──問題來自過於相信自己

之前支援的專案在十一月下旬出了嚴重問題:執行交易後會保持交易執行中的狀態,無法恢復為等待執行。一開始沒有頭緒,花了很多時間後確認是UI被卡住,又再花了很多時間才知道是自己之前寫的一個API裡發生了無法離開的while迴圈。

那個API原來的用途是找出輸入元件前或後的下一個可輸入元件,尋找的流程是遇到下一個可輸入元件就傳回。設計之初認為再怎麼樣循環找回到自己一定會有結束,經過幾個月來的使用也沒有問題,卻沒想到在特別的操作狀況下會有欄位全部變成不能輸入的狀況,因此造成跑不出來的無窮迴圈,加上在AWT Event執行緒呼叫而使得其後排隊的UI動作全部不會運作。

檢討的最後客戶詢問我們:系統陸續出現這麼多問題的根本原因是什麼?我依據這次問題的經驗回答道:是因為對自己設計的執行流程過於自信。根據提出需求規格的人撰寫對應的方法時,依分解動作堆疊的同時心裡在意的是完成功能,相對於例外的處理則以自己的思維加以管控;然而例外的形成組合種類卻不是一時間可以完整條列的,因而寫出的程式邏輯間就形成潛在的漏洞。

程式能不能完成功能只是找出一條可以走到目的地的路,但是如何在動作的順序間條列出所有可能造成例外的情況,卻得一步一步審慎思考才有機會列舉更多。一個人思考或許列出95%以上,但是只要出現沒想到的狀況,整個系統就可能爆發出嚴重的問題,因此至少需要再有其他人的Review來儘可能協助補齊邏輯上的漏洞。其重要性比起找出程式更理想的寫法真的是大多了。

為人處世時亦是如此,光憑自己的直覺反應可能會太過衝動、粗心或鑽牛角尖,縱使三思過後也可能因為個人特性依然存在著盲點。在重大決定前與親朋好友稍作討論,取聽其他人的不同意見加以綜合應能找出一條更好的路。這幾年在想不透的人生問題上有這樣的朋友可以聽取我的疑問,提供我適切的回答,雖然說最後還是要自己想通才會有改變,但是有其他人幫忙檢視總是提供了更全面的資訊。

2008年12月17日 星期三

S17 做事的方法(15)──適當時機下的適當反應

人與人之間的關係是一種關聯,在發生某些事件的時候我們會與他人產生互動。一個事件的發生是由於人想達成什麼目的或是周遭發生了什麼事,每個關係人再根據事件產生時的連帶資訊,經由本身的判斷流程決定應怎麼回應。掌握好互動時機的發生、互動對象的確認與互動內容的選擇將會影響結果。

小朋友有時會問為什麼遇到親戚或鄰居時一定要打招呼?我說與他們見面是一種特殊的事件,在那個時機的最佳反應就是與對方打招呼。當然我們可以不打招呼,不過要去承擔應打招呼而不打時對方對自己可能產生的不好想法。在聽到內容不確定的消息時不要像傳聲筒般直接傳開,務必要根據現有資訊來研判其真偽,在確定內容真實之前試著完全封鎖消息不要再對任何人提起,這正是“謠言止於智者”所要告誡的。

公司有位主管在系統出問題時就會開始聯絡可能可以解決問題的人,這樣的反應動作是正確的。但是他在聯絡的同時不管正在處理的人已經看出問題都要求再跟原作者溝通,而且在工程師們正在討論時常會來問“問題在哪裡?要怎麼去改?”,感覺上我們付出了時間來處理額外的溝通與溝通時額外的資訊往來。

在不適當的時機作了多餘的溝通可能令人感覺麻煩,在應做事的時機沒有反應也可能造成困擾;即使在適當的時機作了反應,反應的內容太少可能不足以作出正確的判斷,反應的內容太多也可能形成資訊混淆而無法在第一時間找到重點。面對事件時的反應時機與資訊與接下來的處理動作有關聯,接下來的處理動作又與互動的對象有影響;在“牽一髮動全身”的關聯影響下,每一個細節都應該三思而行以避免決策的錯誤。