2010年4月20日 星期二
Y20 錦囊之計 vs 設計程度
在此處暫且將時空切割為二:甲時空的軍師通常在出征前一刻根據最新軍情花一點點時間寫錦囊,將領大多時候依錦囊行事倒也正確,但是總有一兩成的機率無法應付現況,需要派人再回去稟報軍情後重新跟軍師拿一個錦囊;乙時空的軍師都會在出征前一天思考整個晚上後,在錦囊中寫下各種可能發生的情況並逐一列舉不同的應對方法,據說不符機宜的機率降低到半成以下。
在這裡說的將軍是在客戶戰場中衝鋒的專案人員,軍師則是指公司裡製作共用元件(錦囊)的支援人員。如果你是軍師,會想用多少精力寫出什麼樣的錦囊?如果你是將軍,又會希望拿到手的是什麼樣的錦囊呢?
身邊絕大多數的人都屬於將軍型,能夠快速使用資源做出客戶想要的結果,遇到不符需求的變化時也能快速地應變;只有很少數的人在面對需求時會如同軍師般思考各種可能情況再作整理設計。將軍型看軍師型會感覺在設計同樣的功能時花較多的時間且產出額外用不到的方法,軍師型看將軍型的產出卻又感覺思慮不夠周延又難以捕捉改變後的影響。更頭痛的是,有些將軍在拿到後方送來的木牛流馬時會嫌錦囊寫的文件看不懂,而且擔心萬一故障時前線不能修理將影響軍情,乾脆重新打造一套很類似卻只有自己懂的東西才會有安全感。
將軍型與軍師型的角色,在雙方的定位清楚並且相互信任的前提下,是可以發揮很大功效的。公司製作共用元件時依照標準開發流程控制品質,提供面對不同狀況下的對應參數;專案人員信任共用元件與正確性與方便性,快速地依客戶需要組裝出該有的功能。這樣不就是很有效率的開發團隊嗎?
註:某個功能在遇到例外狀況,而且從模組內修正那個例外非常麻煩時,將軍型通常會在模組外部添加某些東西,並在模組內部最前端加上判斷添加物是否存在的條件另外處理。軍師型則會堅持分析模組內的處理流程,直到找出可以明確判斷出例外狀況且不影響其他狀況的正解為止;如果找不到這樣的解答,會認為那個模組是個失敗之作。
2010年4月16日 星期五
Y19 First Practice(4)──設計階段
兩週後的某一天,主管問這次開發的工具程式能否在未來重用其中的部分?我愣了一下,由於撰寫中逐漸感覺系統有種“被綁死”的感覺,便回答說這個工具已經因為趕時間而寫壞,不可能切割出可重用的模組。以下就是我給主管的原因:
●沒有全面定義與使用介面
直接寫程式時,對物件常缺乏時間定義應有的行為。在需要對物件新增方法時,會感覺介面得多花時間去設定與調整,再加上認定系統就只會使用這種實作的物件,就順手地將方式寫在Class上。我們都很明白沒有使用Interface會讓物件間的耦合度很高……。

●取得物件的途徑不一致
上圖是工具程式的顯示畫面,最外面的MainFrame簡單地分為左右兩個Panel再各自盛裝UI元件。最外層的MainFrame設計為singleton,在設計時希望一邊Panel的UI物件可以存取到另一個Panel上的任一個UI物件來操作。例如左邊的Clear Data按鈕要能操作到右邊的Table以便做到清除的動作。但是程式寫到一半會發現並不是每個Button“都一致定義”擁有Panel物件,再加上趕時間而“懶得”調整,因此取法變為兩種(甚至更多):
1) getLeftPanel().getMainFrame().getRightPanel().getTable();
2) MainFrame.getInstance().getRightPanel().getTable();
●物件操作的方式未統一
原本定義了ModelService來負責變更Model的工作,但有時“難免忘記”應該經由ModelService來做事而直接呼叫Model的修改方法,形成跳層的使用。如此一來,層次間的關聯變得複雜,而且沒法保證要做的事都會經過ModelService。
●忽略行為的封裝
需求裡提到使用者按下Clear Data時要清除右邊的Table,所以開發時直接在它的listener內直接寫下:
getLeftPanel().getMainFrame().getRightPanel().getTable().clearData();
後來發現工具列上也有個按鈕具有Clear Data的相同功能,所以也直接在這邊的listener裡寫上這一行程式。後來使用者在測試時回饋說清空Table的同時,Delete Data應該setEnable(false),這時候就直接在兩個listener(最好是還記得有兩個地方)內多加一行而形成:
getLeftPanel().getMainFrame().getRightPanel().getTable().clearData();
getLeftPanel().getMainFrame().getRightPanel().getDeleteDataButton().setEnable(false);
在趕時間的前提下,當然沒空在Right Panel上定義clearTableData()同時封裝這兩個動作,因而繼續讓重覆的程式碼散落在各地。
基於以上的快速撰寫方式,雖然讓我的工具程式在被壓縮到不合理的時程後還能如期完成,卻同時造就出一個內部脈絡極為複雜、等於已經僵化的系統。在快速開發的同時無法“完全遵循”某些設計準則,就會付出類似的代價。
2010年3月31日 星期三
Y18 First Practice(3)──分析階段

●UI+Listener
負責畫面的呈現與畫面操作事件的處理。Listener部分會將View與Model都放在Action裡,同時指向Controller做統一的處理。
●ActionService
生成Action並執行的機制,編輯工具需要的Undo/Redo功能也在這裡管理。
●Action
實作處理邏輯的地方。同時握有View與Model,可以讓處理流程完整地取得需要的資訊,同時任意控制每個地方應該發生的變化。
●ModelService
原本為了同時存取多個Model而包裝的服務,後來加上所有儲存Model內容的行為。一方面包裝複雜的Model行為,另一方面提供統一的Model修改處而不致散落在各個Model。
●Model
資料物件。除了ModelService之外只允許讀取內容。
●Environment
環境相關的靜態變數與使用者設定的各種參數。
整個系統內區分為三種層級的操作:Project、Transaction與Field,也就是說每個Package內都對應著這三個層級有不同的入口,在結構上就需要控制 6 * 3 = 18 個群組。根據這樣的佈置就可以開始對每一個UI元件的操作繪製對應的Sequence Diagram。
聽起來似乎蠻不錯的,但是很快產生了變化:原本還有六週的開發被壓縮到兩週,眼看要做的功能實在太多了,所以硬是多要一週變成三週的開發加測試,不過這也足以造成每天加班到半夜的事實。所以跳過了分析階段,直接進入了設計與實作。
2010年3月25日 星期四
Y17 First Practice(2)──需求階段
需求訪談並繪製成UML用了兩週,但也足夠讓自己發現以往的經驗值有許多與理論不合之處:
●從使用者角度看Use Case
記錄使用者需求時,一開始我記錄的是系統要做出的功能:像是新增交易檔案、編輯交易說明之類的,很快地就累積了上百個Use Case。E主管review時強調Use Case是描述客戶完成一件有意義的工作,並不是對應完成工作的分解動作(雖然對系統來說是完整的工作,但應放在Activity);重新定義之後的Use Case剩下六個。

●幫Use Case說故事
Use Case的Activity Diagram要從使用者的角度來陳述做一件事的經過,強調的是使用者做了什麼以及與系統的互動。對系統的操作只需說明(對使用者來說)要做什麼事而不用描述操作的更細節部分。用swimlane分隔使用者與系統更能清楚表達二者的互動關係。

●Activity與Domain Object無關
這個工具輸入與輸出的詳細內容已經確定,所以我很早就開始繪製Data Model並將之連接到會操作到的Activity。後來發現這是提早設計的混淆,因為在分析階段時才會運用Boundry-Control-Entity的方式定義Domain Model、接著在設計時再定義為Data Model;在需求階段應該只先收集系統詞彙作CRC分析。
●UI的Prototype
在需求階段的末期應該與使用者討論資料的呈現內容與功能的操作方式,雖然Eclipse上有Visual Editor可以快速繪製UI,但是使用與調整還是需要不少時間。同事推薦一個網頁版的UI Prototype工具,能夠在極短的時間裡儘可能地表達出畫面的模樣;雖然與實際畫面有點落差,不過使用者接受度倒是挺高的。
Balsamiq Mockups:http://www.balsamiq.com/products/mockups
2010年2月6日 星期六
Y15 功能強大的音樂軟體──Max 5
Max 5這套軟體看起來真的對音樂製作有很有的幫助,而且是完全免費的。不用懷疑,軟體真的是完全免費的,因為要收費的是可以連接實際音樂設備的元件,使用外接型的元件能夠驅動真實的設備使之按照設計流程發出定義的音樂(這是同事說的)。同事說他還付費報名了外面的Max 5課程來學習。
看過之後我們有了短暫的討論,好奇於為什麼能將某個領域的軟體做成這樣,反而自己沒有這樣功能強大的編輯工具可以使用?(討論時也提到範圍較小的LEGO Mindstorm作比較)初步有了以下的共識,但也發現這些因素會讓寫程式的行為變得複雜:
●必須完全清楚該領域要做的事,才有辦法定義出被使用者選用元件的完整集合。
如果做功能時只是找出一條可以執行的路,肯定沒法收集到完整的集合。然而,程式碼裡會做的事太多了,如何收集得齊全?
●每個元件都要定義可以傳入的參數,以及傳回的值。
在寫API時常感覺參數總是少一個(傳物件的話需要使用較複雜的編輯器操作),傳回的除了值還有可能是各種Exception,在流程控制上有很大的變化。
●每一個元件幾乎都獨立到與前一個元件無關
音樂要動聽雖然有些規則,但是每一個音符的發生都是獨立事件;LEGO的行為也類似(譬如起重機的繩子一定要先放下才能升起,但是怎麼放下去的並不會影響升起的動作)。寫程式很麻煩的是還要讓後面的元件使用前面處理後留下的資料。
2010年1月23日 星期六
Y14 設計想法彙總(4)──事時物者為俊傑
程式的執行的最終結果是為了操作資料,部分的人會將設計重心放在資料的存取,而我認同是事的處理過程才去影響到物,所以將設計的重心放在如何以人性的思考來鋪陳事的經過以及事如何去操作物,還有如何將事掛到對應的觸發時間點上。我們時常聽到“堅持做對的事”,這句話其實很適合運用在設計事的處理過程,再加上“所有的物只被事所影響”的限制,“堅持做對的事,同時讓影響的物合乎規範”就形成我最根本的設計理念。再多思考一下會發現,事隱含有處理流程(Flow)與分解動作(Action)二種元素,Action是真正做事的行為,Flow則是組合Action達成目標的完整經過,將兩者明確地分離對於動態置換有相當大的助益。
在程式設計領域裡有很多人提供非常有用的想法與工具(譬如最近亂翻過的新書──編程創藝:編寫出卓越的程式碼就寫得相當好),但是實在不希望程式設計永遠是那種不同人寫的不同、同一個人不同時間寫的也不同的那種混亂。我的目標是想擺脫“趕快用程式碼堆砌出功能就對了”這種思維的產出,而從順應事物運行的自然流動作為出發點來設計。事(Flow、Action)與物(Model)是元件結構裡的三個重要部分,希望只需要簡短的說明就能讓大部分的人寫出相同規格的程式碼。
要去布置妥程式碼會花較多時間,絕對沒有人會接受多花時間只能得到相同運行結果的,現今有些作法有令人頭痛的關聯追溯與文件問題,推論起來有機會在我的理念中全部自動產生;目前唯有讓自動產生內容節省的時間大於(大很多)布置程式碼時多用的時間才會有誘因。
科學的字義是:以一定對象為研究範圍,依據實驗與邏輯推理,求得統一、確實的客觀規律和真理。精確地100%維持每一個程式指令全部在對的位置做著對的事是極其困難的,需要團隊中每一位成員的堅持。暫且放下類似“人性不可能做到100%”的負面想法,試著思考“怎麼調整可以達成那個理想?”、“做到後是否真的帶來那些好處?”,積極地相信未來的願景才有可能在現下勉勵自己達成各項要求一步步的前進……。
註:努力的方向([Q09]、[Q10]、[Q11]、[Q12]、[Q13]、[Q14]、[Q15]、[Q16]、[Q17]與[Q18])記錄的是我想做的。
2010年1月22日 星期五
Y13 設計想法彙總(3)──唯一的資料物件
在執行的過程中模組與元件都各自操作自己的資料物件,在設計時會根據不同的需要定義存取方法,不過我想做的是在各自的資料物件包裝內全部使用一種實作──基本Data Model。
基本Data Model向下可以使用不同的Parser對應各多種儲存檔案:目前實作過XML、properties、text、CSV、excel,計畫再對應html、ResultSet、Model(使用XML字串描述而生成定義的物件種類)以符合更多樣化的運用;Parser應該提供這幾個基本功能:讀檔、存檔、傳入字串與傳出字串。再者就是能夠以對應基本Data Model的單一編輯器達到通用的目的。
向上則可以被繼承後依照個別的需要定義存取方法,宣告為元件結構裡的Model、Properties與Exception。另外,為了區分每種資訊被存取的差別,會要求必須擁有獨自的getter與setter,不得使用通用型的方法。
在執行期間只要更換Properties的內容(或是重新設置),就能夠改變元件內部的行為;不同模組或元件之間的資料傳遞也只需要取得基本Data Model字串再直接傳到另一處而變得簡單。如果需要當時資料物件的全部內容,經由Parser可以轉換為各種不同格式的字串寫在log裡,事後可輕易地回復為該時間點的執行資料進行測試。
在公司曾實作過一版最早版本,幾位用過的同事都覺得方便且容易操作,自己也滿意這樣的設計結果。雖然基本型態的欄位資料都必須使用String型態存放,但是在不甚計較容量與速度的執行環境下卻也沒有什麼缺陷。
與基本Data Model想法有關的文章是:[C22]、[E06]、[E07]、[E08]、[E09]、[E10]、[E11]與[E12]。
2010年1月21日 星期四
Y12 設計想法彙總(2)──遞迴的一致結構
根據這個目標,我認為需要的就是一致的元件結構與元件間的遞迴式呼叫。
元件結構的一致性,在[D06]、[D07]、[D08]、[D09]與[D11]有詳細提到切割的六個部分:
●Implementation
管理元件內部的小型工廠與使用窗口。元件生成後,內部Flow與Action的生成與置換都由它處理;另外每一個介面方法必定要通過這裡的管理。(整個元件的生成應由元件生產工廠模組來統一管理)
●Flow
元件內部處理流程統一放置的類別。應依照SOP的想法定義每一個方法的實作流程,在不同應用的需求下允許使用者動態改變流程類別。
●Aciton
操作流程分解動作統一放置的類別。流程依照SOP的想法定義,流程中的每一個步驟都定義在這裡,在不同應用的需求下允許使用者動態改變動作類別。
●Model
定義元件專用的資料類別。每一個屬性都要同時提供getter與setter。
●Properties
定義預設生成的Flow與Action,以及其他執行期間需要調整的參數。由Implementation讀入並保留使用。
●Exception
每個元件要有自己的例外。介面方法內部發生無法預期或難以處理的情況時,拋出內含相關資訊的例外物件。

完美地保持只呼叫下一層的遞迴型態,代表著需要嚴謹地定義每個套件的使用關聯,並補齊每一個層次原本沒有定義的元件空隙;只要有一個例外,就會造成處理程式的邏輯判斷錯誤。當然,也必須讓處理程式知道每個層次的定義與存取位置。自動產生設計文件的記錄在[P06]、[P07]、[P08]、[P09]與[P13]。
當元件結構的一致性與從上而下的遞迴規則定義好之後,可將足以得到很多現在難以自動產生分析、統計、追溯……以及各種想像得到的程式內容應用。
2010年1月20日 星期三
Y11 設計想法彙總(1)──層次與使用定義
首先是關於層次的設定,像下圖中這樣Business Module、Module、Component、Utility從上到下佈置下來的方式,雖然安排的層次上或多或少有所不同,但是由上到下的使用關係都是大家所習慣的作法。這裡我想要討論的是:需要開發電子日誌商業模組時決定要使用外面開發的DB存取元件,應該直接從電子日誌模組使用?或是定義一個自有的DB存取元件使用,電子日誌模組只呼叫它呢?(如果只看功能,程式怎麼布置都可以達成)

最快的方式是在電子日誌模組裡直接使用外部的DB存取元件,這意味著模組與外部元件有不可分的相依性,所幸這個問題在遇到第二種資料庫時就會因為想要抽換實作層而自己布置一個Component來負責。再接著會遇到一些通用機制需要設計(像是roll back、SQL command管理等),那些是所有使用DB的商業模組必須應用的,但是若想放在功能性強的Component又會感覺綁手綁腳的。

從上方往下看是這張圖中像洋蔥的結構,Use Case劇本呼叫的是Business Module的方法,再一層層地向內使用,外部元件全部由Component包在其內部使用,在其他任何層次都不會接觸到。在這種結構下,與外部的接觸點只限於Component層(Utility也可能會使用到外部Class),可以避免在任何模組或元件都能使用外部元件。
一致的層次設定與使用規則,是最開始就需要定義好的布置框架。
2009年12月29日 星期二
Y10 用物來描述事,用事來成就物
當事情可以用人或電腦來處理時,不同人、不同時間的同樣操作都有較高的錯誤與不一致機率,這些問題在利用電腦處理時可以大幅降低,只需要花一次時間精確地定義出處理的詳細規則;觀察許多工具其原始目的大致如此。Ant對於單一事件(通常是build版本)定義出詳細的處理過程,而Maven更進一步地定義出專案管理中的幾個階段,再整合其他工具、加上與程式碼相關的物件(library、testing、reporting……等),建構起一個能夠調校的自動管理系統。
收集軟體專案開發必須要做的事,定義出每個軟體專案能通用的開發流程、階段與當時可以做的事,同時允許使用者設定使用一般常用的方便工具,得到適用的客製化結果。當工具符合專案大部分的自動化需求時,即使需要額外投入學習的時間還是會加以運用。
回到自己部落格的內容,現在記錄的資料只是根據過去的零碎的經驗值推想一些改進的方法,沒有全面的整理與比較根本說不出這麼做的最終目的。此時的思緒已經逐漸清楚,明白自己是想定義用程式碼製作出來的全部事與物都有完全一致的型式與規則。如果像專案開發階段這樣令人感覺抽象且發散的事都能夠依賴設定之物來運作,試圖將程式碼轉化為某種特別的設定來驅動更豐富的自動化解析也應該是可以達成的。
這,正是我想逐步實現的理想。
2009年11月19日 星期四
Y09 關於共用核心元件(Core Component Library)
UN/CCL主要的目的在於各國、各系統間的資料交換,翻閱過08A的中譯資料發現已經定義了許多曾經使用過的資料。席間有人發問說資訊物件內的欄位並沒有定義長度,學者回答資料若定義長度在語系轉換時會發生長度計算的問題,不過我認為資料在使用的意義上並沒有長度的規範,而是系統設計時因應儲存限制才加以規定的。
然而UN/CCL只是該組織計畫一部分,資料的定義用ebXML來描述,Business Process與Information Model會有UMM方法論,相對地這也是範圍更大、更難定義的部分。根據簡報的陳述,倘使各國的菁英最後能夠定義出絕大部分的商業流程與其對應使用的商業資訊物件,未來的電子商務相關系統開發模式很可能是:
●定義使用系統的所有Actor
●定義每個Actor所使用的Business Use Case(從清單中勾選)
●定義每個Business Use Case裡所需要的Business Process(從清單中勾選)
●定義Business Use Case裡的Business Process執行順序
●定義Business Process對應的CCL資料物件中的使用資料欄位(從清單中勾選)
●底層的架構會根據勾選的資料物件欄位產出ebXML傳送到另一端的系統
這個組織已經運作好幾年,但是以“Core Component Library”搜尋中文網頁時所得的資訊並不多。從另一個方面來看,自己定義的“人-事-物”關係能夠接近許多專家定義的“Actor-Business Process-Core Bomponent Library”精神時,總是對自我更多了幾分認同。
官方公佈UN/CCL版本的網址是 http://www.unece.org/cefact/codesfortrade/unccl/CCL_index.htm。
2009年10月18日 星期日
Y08 不要只用技術的角度想事情(3)
不管是SOA或是服務體驗,初接觸客戶服務時我都直覺地認為不過是“從客戶的角度來想事情”,然而在很多的時候我們只是“把自己視為客戶”來討論;即使直接對客戶訪談或作問卷調查,取得的資訊通常只是片面的資訊,因為得到的答案是經過思考(可能帶有修正)才輸出的。
德國的服務工程與美國顧客體驗洞察技術提倡的是使用科學化、系統化的方法,將客戶的真實行為模組化為數種Model再進行服務設計。剛開始時實在不以為然,甚至萌生不知道為什麼要學習這種東西的負面想法;隨著漸漸瞭解服務的本意,才慢慢明白要用什麼樣的立場與方式去思考客戶的事。現在與技術人員開會(我當然還算是技術人員啦)時,時常會感覺他們看事情的立場有很大的差異,才猛然省悟原來自己以前也是這樣!
從完全不懂到能初窺其奧妙經過至少四個月,心態上也從抗拒轉變接受並嘗試;回首歷程,能不能聽懂是第一個關卡,想不想接受是第二個關卡,會不會去做是第三個關卡。倘使不去嘗試、不去吸收、不去思考、不去改變,是永遠不可能走出現有模式的。
事情常有一體兩面,以往自己獲知一件事時最先想到的都是找出其問題點並提出難以施行的障礙,現在則會先考慮可以順利執行的狀況然後想出困難點再思考克服的方式。從負面指出哪裡有問題的確是技術人員(與政治人物)會最先想到的,我覺得這才是想事情角度不對的最大癥結吧?
2009年10月16日 星期五
Y07 不要只用技術的角度想事情(2)

與不同的同事們聊天時,才發現每個人的設計想法差異很大,最常見的設計想法是將執行交易種類次數報表與記錄模組全部都綁在一個模組裡,然後套用“只作出客戶需要的東西”這個說法。如此一來,這個模組的存在最差的情況下只符合這一個報表,而且記錄的資料元素很可能因沒妥善思考而不足,根本沒法應付未來的各種可能。
不去想其他可能而只注重單一功能,進行速度當然可以很快。但是在未來有需要修改記錄的資料元素才能產生的報表時,就需要改動最底層的模組,連帶地影響其他原本可以正常運作的報表;為了隔絕對舊有系統的影響,唯有copy-paste出另外一套來修改。這樣就產生了號稱絕不疊床架屋的設計──只是同樣的東西有很多套而已。
交易記錄模組是需要良好的設計來提供最大範圍的支援,報表部份則從底層模組取得資料只作客戶所需要的就好。底層的模組用最大化的可能設計來應付未來需求的改變,實際的呈現則只實作客戶提出的部分即可;雖然客戶想要的可能會增加,但是多送他不需要的東西也絕對不會收的。
觀察主管的感覺,發現他們通常會先定出做事目標,然後會陳述做事的順序與原則,但是對於每個步驟所需要用到的資源與可能的困難點幾乎都不涉獵,通常變成很理想化的想法。實際做事的人需要顧及每個步驟的可行性、風險與替代方案,這些都不是只談原則就能夠順利推動,而是需要精確地衡量與思考才有可能做好的。
在主管的想法與實際施行有衝突時,實在有股衝動想跑去主管面前大聲疾呼:可不可以拜託你們從技術的角度來想事情!
2009年10月14日 星期三
Y06 不要只用技術的角度想事情(1)
在開會時思考系統可以加強的地方時,我想到之前很需要但是沒辦法產生的一份報表(註:不能描述太詳細,就暫時以執行交易種類的次數報表稱之),連帶地想到產生該報表時需要配合記錄Log的各個時間點,並想這個想法整合為一個Log記錄模組的概念。後來將這個概念私下陳述給E主管聽時,他回答說:不要只用技術的角度想事情,不要習慣從bottom-up思考而應該是top-down。意思是說概念要思考能符合客戶的需求且賣得出去才算是成熟的概念。
當時我的腦中忽然發出像是什麼斷掉的聲音,立即有了否定的回答。
現在我需要一份現有系統無法產生的報表,便開始思考要怎麼做才可以滿足自己的需求;發現報表所需要的資料可以從增加特定時間點的Log來取得後,就認為應該有一個專門負責記錄Log的模組來收集各種資料。這個模組概念的產生是由我自己(客戶)需要的報表(需求)所引導出來的,完全符合由上到下、根據使用者需求而出現的想法。
目前其他客戶想要什麼樣的報表我們都不可能知道,即使今天訪談了十個客戶所收集到的報表種類,在找到第十一個客戶時還是有可能要之前沒提過的報表;就算我們想從客戶的角度來思考,也不能肯定思考出來的範圍是不是百分之百。在無法肯定未來變化的現在,我只能以現有模組的角度來定義其中的資料元素(譬如人、事、時、地、物),期望在設計的同時可以有最大範圍的排列組合,而未來客戶想要的報表儘可能地落在設計的範圍裡。

用最小的額外花費涵蓋最大範圍的可能需求,不就是設計的目的嗎?我這麼反問E主管,他沒有反駁。
2009年10月10日 星期六
Y05 都只是為了完成功能……

就像作文一樣,看到題目之後心裡就要先有文章的架構鋪陳;功能明確之後同樣會有執行的順序。如同作文時的擬定大綱,設計程式也需要概略描述達成功能的過程。作文的大綱完成後要開始逐段、逐句、逐字寫出文章,程式碼的產出也是如此;其中的差別在於作文強調的是從頭到尾、一氣呵成的感覺,寫程式除了這個感覺之後還有逐步的例外處理。
寫出程式後需要經過測試來精確地保證功能可被達成,測出錯誤會使得程式碼有再次的修改,每次修改都會有版本的記錄;每個版本各修改了哪些地方,造成什麼影響都必須要能迅速查詢到。怎麼佈置、怎麼撰寫、如何保證與如何管理,是因為有程式碼的存在所連帶產生的四件事情,標準化的做事會有方法與準則,這意味著還要定義出至少四組的做事方法與做事準則。倘使做這些事的過程裡需要有其他的物(工具)協助時,還會再衍生更多的事……。
只是為了達成一個功能,在產生程式碼的過程需要考慮很多其他的事,可以想見如果沒有全面性地看待而只注重在如何完成功能,就會造成除了執行正確之外的全部都有潛在的問題。雖說完成功能是最終目標,然而考慮程式時常被修改的特性後應同時注重其他方面的要求。
2009年9月30日 星期三
Y04 POC的產出不適合直接使用
這當然是從“可以驗收”的角度來看待POC的產出,但是深入一層去想,POC這個名稱已經很清楚地說是“概念的雛型”,目的在於驗證想法是否可被實現。在架構已經選定的前提下,自己在製作POC時思考的是:
●什麼時間點需要執行這個功能(入口)
●執行這個功能時需要哪些步驟(流程)
●每一個步驟各需要什麼元件來支援(動作)
決定執行的時間點後可以導向入口,在專案裡掛上功能的入口很簡單,但是需要調整傳入與傳出的資料。流程是功能進行的順序,在POC時幾乎都只製作正常的流程與幾個需要呈現的錯誤,要在專案實用就得加上所有的錯誤控制。動作方面大多會使用到其他元件提供的功能來組成自己的分解動作,倘若是第三方提供的元件使用的方式會比較固定,但要是使用元件預定是在專案內才設計的就會有被變動影響的風險。
達成目標經過的每一步以及收送的資料內容都需要經過設計,這些並不是在製作為了測試概念能否執行的POC時會考慮到的,僅求一時之快將POC的內容直接引用,未來勢必會出現設計想法不同的落差。能夠只作些小修改就融入專案設計算是最好的,但是大多數的情況還是需要打掉重做才能符合專案需要。
曾經在專案後期被POC改寫的元件卡著上下不得:想作些專案需要的修改時覺得綁手綁腳,想重做又會浪費重新測試的資源。捨棄POC所寫的功能而僅參考執行概念再重新設計出新的元件,是我決定的作法。
2009年9月14日 星期一
Y03 與理論型同事對設計作法的討論
他的想法主要是參考大師們的說法,因為那些都是根據有經驗者的智慧結晶而定義出來的;不管是分析設計時應該做的步驟、使用的工具與應有的產出等等,都鉅細靡遺地遵循書上的方式。我則根據部落格上的心得,先把使用UML工具會作出的產出定義為程式碼,再逐一將分析與設計的想法衍伸在程式碼裡。
我們的分歧點在於“不應該用程式碼作設計”。E主管的感覺是直接產出程式碼而不先模組化就會回到以前設計不良的窠臼,同時也提到以前在學校若先寫出程式碼會被教授責備根本不作設計的事,當然也聽不進去我希望解決之前使用UML工具進度緩慢、達到分析與設計模組追溯的目標,因為他暫時落入“馬上有程式碼絕對作不出好設計”的想法中。
爭辯了一陣子雙方僵持不下,最後我只好換一種方式說明。先解釋說,現在有一個功能與Rose完全一樣的UML工具,採用的OOAD作法也與RUP完全一樣,然而那個工具的存檔格式剛好與Java程式碼一模一樣。今天我們的OOAD作法每一步應該做什麼就同樣地在“程式碼”會有什麼,這樣一來無論分析或是設計都能夠採用我計畫的工具作出全部的管理與追溯;分析的“程式碼”則在build產出時不處理而僅作為模組化的分途。
E主管認同了我的說法,但有個前提是:要先明確定義好OOAD的詳細步驟後,才能逐一定義與我想法之間的對應。前面的討論對於modeling來說都只是產出的物,先要有應做之事與其順序後再去談應有之物;這也正是做事的基本前提。
2009年9月9日 星期三
Y02 如何寫出難改又難懂的程式碼?
一直都在談如何作好分析與設計,這回就來個逆向思考的建議。
●目標:如何寫出難改又難懂的程式碼?
想像公司早上第一個到的人所要做的事如下:開鐵捲門、用識別證開門、開一號盤的15個電燈開關(1-15)與二號盤的15個電燈開關(16-30)。現要設計一個功能來實現這些行為,建議使用以下推薦的方式來撰寫程式,保證可以達到難改又難懂的特殊效果同時不會影響功能的正常執行。(此等技術暫時命名為程式碼的人工混淆化)
●Class、Method與Field的隨興命名
效果:讓人即使看到名稱也不見得知道這就是他要找的程式。
●Class隨便放到某個Package裡
效果:與上一招同時施展,可以讓人感覺Class在某個雲深不知處的地方。
●Class、Method與Field內外完全不寫任何註解
效果:讓別人從眾多的程式碼反推你原本想要做什麼。如有人能完全識破此機關的話一定要選為衣缽繼承人,因為那是萬中無一的奇人。
●執行的大大小小步驟都寫在同一個Method
效果一:搭配前一招時可以讓邏輯處理的焦點忽大忽小,明明在講進門要做的事卻一下子跳到拿出識別證的動作,完全不知道在幹嘛。
效果二:可以保護自己想出來的程式解法,例如自己發明一個很帥的識別證拿法就可以直接寫在Method裡,其他人想要用就只能copy(因為要抽方法就得幫你改寫程式,以我所知沒幾個人有這閒工夫);有天你發現姿勢可以更帥時可以保證只有你知道,因為別人抄到的是你前一次的姿勢,跟你肯定沒得比。
●不要花時間去想執行發生錯誤時該怎麼辦
效果一:程式碼裡一定存在著錯誤,這樣一來可以用更多的錯來證明這句話是極為正確的。
效果二:搭配前前招使用,可以讓別人在不知道處理邏輯之餘更不知道發生錯誤要怎麼辦?同時讓老板知道只有你能搞定這樣的錯誤處理問題。(註:平時常逛逛求職網站是有助益的,因為總有一天會發生連自己都搞不定的重大問題……)
採用以上方式撰寫程式碼,將會產生下列各方面的效益:
●個人方面:
加速個人的效率與產能(不用抽Class與Method可減少思考與重構時間)
提升個人在開發團隊中的重要性(沒人有把握修改別人的程式)
●公司方面:
加強與其他公司合作的意願(即使程式碼外流也毌用擔心技術被學走)
減少額外控管程式碼的成本(只要從jar file反組譯回來就是完整程式碼)
●產業方面:
創造更多的營業額(因應提高開發與維護的成本會增加系統的售價)
提升開發人員的素質(無法看懂別人程式碼者會被淘汰,只留下適任者)
註:最近一個多月狂寫公司某份計劃書,因而導致這篇文章的風格被影響。
2009年9月4日 星期五
Y01 程式設計是藝術創作?
我提出的切入點是人像的雕塑,這很明顯是屬於藝術的範疇,每一位作者都可以任憑喜好去製作各式各樣的人像。接著提出同樣屬於人像創作的秦朝兵馬俑,我們都曉得兵馬俑的數量很多,雖然姿勢、表情與裝扮都有不同,但是服裝與身材卻是大致上相同的。再極端一點可以想像有一國的統治者想在全國各地放置出他的雕像,於是他穿上最喜愛的服裝並擺出某種姿勢,要求全國所有工匠全部都得做出一模一樣的人像。(以上的前提建立在工廠出現之前,所有的人像都必須經由手工製作)
從上面的說法,我們可以發現隨著要求的規格越來越多,每個藝術家的創作也可以從依各人隨興而作演變為具有統一規格的產出。同樣的道理也適用在程式設計之上:在沒有規範時每個人寫出程式碼的想法與風格會是相異的,隨著種種規範與規格的建立將會調整每個人的想法與寫法,漸漸演進為所有人產出的程式碼每個人一看就明白。
K主管認同了我的看法,想法調整為:遵循規範與規則的部分像是工程,其他的部分則屬於藝術的創作。然而隨著規範與規則訂定地更加完整,藝術創作的範圍勢必越來越小;等到某一天程式設計的一切都有人定義出良好的規範與規則時,programmer是不是真的就會像作業員一樣,每個行為都只能根據該生產線的SOP找出適合的零件來組裝產品呢?