顯示具有 [N] 元件作法 標籤的文章。 顯示所有文章
顯示具有 [N] 元件作法 標籤的文章。 顯示所有文章

2008年4月20日 星期日

N20 輔助的文件(5)──Component結構的所有檔案

與只擁有Interface、Controller、Model與Exception的簡潔型Component比較起來,自己所使用的Component結構實在算是個龐然大物,而且兩者間想達成的功能幾乎是一樣的。從上一篇的附圖來看,在開始設計方法前得先準備好一大堆Interface與Abstract Class,也難怪其他人根本不想改變原來的作法。

Component與Component之間在功能上是各自獨立的,但是以行為模式來說,所有Component的Implementation、Flow、Action、Model與Properties等等的特性其實是共通的。這個意思是針對Component來說,事實上也需要安置一個Abstract Component來放置所有Component裡各個零件共同的行為模式,同時還要加上管理物件生成與消滅的Interface與Method。這樣的需要就形成了這樣的Component結構:

把Component做成這麼大,如果得在佈置結構時花費過多時間,反而會降低產能,為了解決這個問題只好想辦法讓Component結構“自動產生”所有的物件。Component結構圖是既定的產出,輸入的變數可以侷限為Package Name、Component與output path,因此我在一開始就指定一個人專門製作這個工具。

如果三兩下就可以把這麼一堆的Component結構佈置進而開始設計,開發團隊的接受度與產能就可以相對提升不少。

2008年4月19日 星期六

N19 唯有先為他人著想,自己方能受惠

看別人寫的程式困難點其實在於找不到入口與看不懂處理邏輯,尤其在Component的實作只是直接從Interface後把所有的東西堆積在一個Class裡面時。

Component的設計雛型在D06時已經形成,MVC的設計方法將之修改為MF(Flow)A(Action)C並將之各自定義在專用的Interface裡。以類似SOA的觀念把Flow拉出來,對於設計者而言就變為只要挑選Action裡的方法組合為處理流程,再加上Properties改由外部傳入而不使用內部設定檔、有狀況時只拋出Exception而不在內部作任何處理,讓我的Component具有更高的reuse特性。

這樣的Component想法在2008/04時對開發團隊說明,參加的人也認同我的作法可以解決一些目前還難以解決的設計問題。我特別說明這個作法在設計時因為要把原來直接撰寫的程式拆解到不同Class的方法裡,需要直接撰寫大約五倍的設計時間,但是適當切割的作法可以讓修改除錯的時間減少一半以上,且能應付大多數的需求改變。

設計的人在定義系統時多做點,可以讓未來使用方便而且容易維護,自然可以節省未來親自處理的時間。但是習慣快速寫作的人是否能夠接受這樣的作法,尤其是多花自己時間的作法呢?如果內心的“設計”僵化到難以改變,也許人就已經定型為那個樣子了。

這張圖是我最後定型的Component內部結構。

2008年4月18日 星期五

N18 做人的方法(10)──收穫來自投入的部分

每個人一天都有24小時,扣除生活與工作必須花費的時間外,是自己可以運用的。雖然在生活中遇到的事件都會讓人學到些什麼,不過將空閒的時間投入什麼方面,在那個方面的就多少有更多的收穫,但是相對地沒有投入的部分成長會較為緩慢。

如果一個人把時間投入在讀書,與別人就沒有較多的互動,如果生活與工作上沒有辦法學習到與人相處的方式,那就有不懂做人道理的可能;把時間投入在遊戲或電影,要是內容沒有值得學習的地方,就只能得到休閒的效果而不會得到看書時能有的收獲;常與朋友一同聚會,倘使交談的內容沒有值得學習的地方,那同樣會讓學習止步。

學習的效率也是一個影響很大的因素,同樣的投入時間在不同的人身上會有不同的進度,有的人隨便看點書很快就能吸收,但是有些人投入很多的時間卻進度有限,不過只要有重覆的練習還是有很大機會學會。“一分耕耘,一分收獲”描述的是只要投入時間就會在該方面有所進步,“專家是訓練有素的狗”雖然很不好聽,卻也是描述在該領域的專家投入了更多時間反覆練習過。

如果希望自己學到什麼(目的),就要決定達成學習目的的過程(步驟),然後按部就班地投入資源,努力學習以期產生效果(影響)。我們應該依現有的資源來計畫好自己的人生可以有什麼樣的成果,依此決定更多有機會達成的學習目的,藉此慢慢構築出個人的生涯規劃並努力去實踐。

2008年4月17日 星期四

N17 API字典與一般字典的異同

所有開放的API都應該撰寫詳細的Java Doc給使用者參考,包括Package、Class、Method、Data,只要是使用者看得到、用得到的東西都應該要有說明。文件的製作就以Java Doc直接產生並加以收集保存,我會稱之為API字典。

不管是哪一種字典,目的都是收納該領域應該有的項目,使用者想了解某個項目的使用說明時,可以根據字典的分類原則從上到下找出需要的項目。不過若是想要表達某個意義,一般的字典卻無法讓使用者條列出符合該意義的所有項目供使用者挑選,使用者只能依印象或請教別人來找出達到某個特定目的的項目,再瀏覽解說看是否符合需要。

API字典的目的,一方面可以讓使用者明白某個Class的功能與有什麼樣的常數與方法,另一方面是明白指出系統內開放使用的API範圍。雖然安排的原則與一般字典相同,但是我們可以搜尋API資料夾的內容來找出擁有搜尋關鍵字的所有檔案,藉此縮小尋找的範圍以希望精確地找出需要的項目。

看到一個API後找出它的使用說明,因為某個目的找出所有可能的API作篩選,這是API字典應該提供給使用者的功能。

2008年4月16日 星期三

N16 設計的製程(10)──API的定義與分類

執行方法後立即傳回結果,而且在執行前後不需要額外的設定且不留下執行狀態者,我都會將之歸類為API。在這樣的定義下雖然可以把方法宣告為static但是我仍建議使用Singleton的設計,以確保將來出現變化時還擁有改變的彈性。

API可說是對於資料的常用動作,像對於String、Array、File、Collection甚至是XML Dom我都定義了Class來放置對應的API方法。雖然許多JDK的物件都已經提供基本的操作,但是還是有一些數個操作組合形成的動作,或是加強原先操作的功能與應用性等等的需要,這些製作的產出都要對應操作的物件類型放到各自的API Class。

除此之外,對於自己定義的Data Model也可以應用這樣的設計:Data Model本身只提供最基本的getter與setter,有組合性的需要時再於Data Model的上一層放置一個Data Model API來操作。把對資料的動作分成基本與組合兩層放置,這個觀念與Controller裡的Flow與Action是一致的。

2008年4月15日 星期二

N15 如何學好地理與歷史

地理與歷史雖然被分為兩門功課,但是兩者之間的關聯是非常密切的。地理描述了地殼的特質,包括了地形、礦產、種植、畜牧、城市等等;歷史描述的是人類在地球上生活時發生的重大事件,包括產生的原因、事件的內容與日後的影響。

從系統的角度來看,地形、氣候與礦產是位於最下方的靜態層次,城市、畜牧與種植是人類決定在此處生活後才有的中間層產出,最上層則是種族與戰爭、遷徙等歷史事件的發生。人類受地形影響決定在哪裡建造城市、在哪裡種植與畜牧,但人類的歷史同時也改變這些;人類可以改變小部分的地形,地形變化在人類歷史中雖很少發生,卻會改變該地大部分的人類(例如龐貝城)。

這兩門功課在求學階段裡都是硬背硬記度過的,主要是因為課目被切分為本國地理、世界地理、本國歷史與世界歷史,每位老師都很認真地教他們負責的科目而忽略了說明彼此間的影響,連帶地讓我沒法去融會貫通世界的平衡。

前陣子在觀看介紹圓明園的DVD時,裡面帶到建造圓明園時與乾隆死後的幾十年間,歐洲各國發生了什麼樣的事情(工業革命、法國大革命等),相較之下才更明白在某段時間裡各國的演變與之後發生事件的關聯。相信唯有明白在每塊地形上的人類在同一個時間點時各發生了些什麼事,才能對接下來的世界局勢走向有更清楚的掌控。

註:高中時選讀的是自然組,國中與高一的地理、歷史都是在課本上硬畫重點強記而及格的,因此以上僅純屬個人推測的結論。如有人看後嘗試不同的讀法而導致死當的話,本人概不負責!

2008年4月14日 星期一

N14 設計的製程(9)──Component的說明文件

對要使用的人來說,只需要說明詳盡的Component Interface註解就足以知道它是否適用;真正要使用時需要的是Component Interface Method的Java Doc加上簡單的使用範例。所以讓使用者明白Component的功能與用法是撰寫文件的方向。

功能與用途寫在Class的註解,常數與用法則寫在public Data與Method前,所有說明都用Java Doc的寫法以便產生給使用者觀看的文件。除了單一Component的內容之外,還要準備所有Component的分類清單,讓使用者快速依功能需要找出所有可以被應用的Component再從中挑選最適合的。

給維護人員看的是設計的想法,依之前提到的原則與順序,提供描繪Class與Interface的Package Diagram,同時在裡面標示所有Data Model、Action、Properties、Exception等靜態的方法,再以實作Component Interface Method的Controller說明來串連,就可以快速明白所有的方法合作的概念。

Component文件主要在於使用上的描述,讓使用者只要看文件就會運用的話,可以省掉教學的時間。由於理論上Component會在許多系統內使用,通常在初期時就會經過需求確認與較多測試,維護方面的要求相對的就會比較低一些。

2008年4月13日 星期日

N13 佈置容易看懂的軟體結構減少文件製作

似乎除了設計者之外的所有人都贊同文件的重要性,認為留下適當的文件是該做的事。但是真正在做事的人一邊寫程式還得一邊更新文件,這樣子相當於處理兩倍的工作量,每一個地方都這麼做的話肯定會累死的;但是要是只更新一邊就會造成內容不同步:正確的是程式,錯誤的文件就沒人要看,等於白做。

厲害的程式設計者通常不寫文件,就是因為他們覺得文件寫了很久卻沒有參考價值,反而拖累他們的開發進度。可是問題是他們寫的東西雖然功能正常,想要瞭解裡面做的事時,除了在沒有文字描述的輔佐下難以看懂之外,還得面臨詢問時得到“我忘記了”的回答。

大陸某大公司說他們採用敏捷開發,其大意是先定義好系統的模組,並且完整定義出每個模組的介面,結構經過討論確定後,每個模組的內容再由負責的人直接在裡面寫程式實作。發現這與我使用的開發方法很接近,只是我連模組裡的軟體結構都有佈置的準則。

每個獨立區域(包括System、Package、Module、Component)都應該要至少有一張靜態結構的Class Diagram,還要有完整的Interface與Interface Method清單來描述這個區域“應該”具有的功能;另外“如何”履行這些應該具有的功能,就努力將之收集在Controller的方法裡,以標明原因與目的的詳細註解加以描述,同時還是要記錄流程內使用同一Package內的動作Method。

動態的流程使用註解說明每一步驟的使用,靜態的動作記錄詳細的操作方式與使用效果,如此一來可以省卻變動性質最大的流程描述文件,同時保持記錄全部動作的必要資訊。

2008年4月12日 星期六

N12 備齊資料的記錄才能應付各類的分析

相信有許多人都喜歡看棒球,不懂門道的人大多只看球星上場或者自己支持的球隊表現如何;真正研究棒球的人會去收集許許多多的數據來統計每一場比賽裡的每一種事件,比較看看哪些人、哪些球隊、哪個球季有什麼樣的統計數據。

棒球比賽裡最基本的事件是投手的投球,投手投出一個球的時間很短,但是每一個球記錄下來的資訊卻是大量的。先看時間點,投手投某個球是這場比賽的第幾球、是哪一局的第幾球、是這名打者的第幾球?投出的球球種是什麼、時速多少、投到哪個位置、是好球還是壞球?對應投過來的球有打者的反應,打者的每一球有沒有出棒、被判好球或壞球、揮棒擊出後球飛往哪裡、是飛球還是滾地球、結果造成了幾個壘打數或是造成幾個人出局、怎麼出局?

再往上推還有今天投手與打者的統計數據、投手與打者的對決統計數據、防守者與跑壘者的攻守統計數據、如果這場比賽有誰有特殊的表現也會另外記錄……我雖然不是棒球專家,但是球賽看久了也知道有哪些數據常被提起,也可以發現專業的棒球可以說是想要知道什麼樣的資訊幾乎都有這樣的記錄。

在這裡我想要表達的是,在一場比賽裡每一次的投球所需要記錄的資訊是如此之多,再衍伸出來可以查詢的數據還有更多。倘使我們將系統(或元件)的開發視為整個球季,把每一個方法的設計視為每一次的投球,這樣是否可以感受到Method設計資訊在系統(或元件)裡的重要意義呢?

2008年4月11日 星期五

N11 令人感到麻煩的設計(15)──避免將參數放在設定檔

決定不用程式碼寫死使用關係的同時,表示我們必須在某個地方記錄對應的關係並在執行時取得。通常的最快作法是將參數放在properties檔案,再使用ResourceBundle方式讀入為Properties取用;不過使用時再多往幾個方向思考一下,或許會有不同的決定。

檔案位置的固定。很多時候為了方便設計與管理,Component的參數檔案會被指定放在一個固定的地方,而且通常是使用它的Package裡。這樣的放置會造成設定檔被“綁死”在那個地方,無法應付系統要求要集中所有的設定檔方便管理的需求。

檔案類型的固定。在設計上採用傳入檔案所在的URL後再於內部讀取內容,這樣的設計可以讓設定檔在任何存取得到的地方。不過取得的來源就只限於properties檔案,要是客戶另外有xml或是資料庫來存放設定的話,就沒法動態由不同的來源產生。

雙向讀寫的要求。即使設定檔由外部組成Properties物件再傳入Component的作法可以滿足以上的想法,但是Properties的特性是只能讀取的。設定一般來說是允許客戶修改的,直接修改檔案內容雖然快卻有修改內容發生錯誤的狀況,此時可能需要選用別的物件。

靈活替換的判斷資訊有很多存在於設定檔,針對以上各方面的考量,在設計上我會定義自己的設定檔物件,由客戶決定怎麼生成Component需要的設定來滿足以上的想法;當然,這個設定檔物件是存放在元件庫裡的。

2008年4月10日 星期四

N10 置換整個Class與用參數涵蓋可能變化的比較

在軟體工廠的概念裡,所有的元件都像是積木有自己的規格,系統的開發在大部分的地方都是只選擇適合的積木堆成我們想要的模樣。在需求變更的情況下若有元件變得不適用,可以將之拔除再另外放一個更適合的進去。

以取出積木再另外放一個進去的想法,有可能會使得功能幾乎相同的元件有許多分身存在,這是因為製作元件的人不想分析比較彼此之間的差異,而直接把變化寫死在一個特定元件裡。如此一來每次的小變化都形成一個元件,時日一久自然就可以擁有“看起來很多元件”的元件庫。

玩過積木的人應該注意到,同樣有那種具有可動部分的積木,像是螺旋漿、門窗、旋轉軸之類的。這種積木只要撥動一下可動部分,就可以讓積木以不同的的方式呈現。如果今天的積木在開門、關門與半開關之間都要求使用者“置換”該積木的話,玩的人會不會覺得頭很痛呢?

直接把變化對應到不同的元件是最直覺的,開發者幾乎連想都不用想就可以由copy-paste或是繼承快速地做出一個新元件;去分析改變與影響並在同一個元件內去涵蓋相對地就得花上比較多的時間處理,但是對使用者而言卻有能應付多樣變化的單一元件。如果你是開發者,會決定怎麼做呢?

2008年4月9日 星期三

N09 令人感到麻煩的設計(14)──Component間的避震器

Component更應該要堅守使用專用Data Model的原則,因為Component之上是各式各樣不同的其他元件以及系統。只要兩個以上的Component使用了同一種Data Model,即使二者之間並沒有直接呼叫對方的Method,兩者還是產生了間接的使用關聯。

如果在設計上它們不應該產生使用同一種Data Model的關係,那麼應該先讓兩個Component使用各自的Data Model,並另寫一個資料轉換的函式負責在兩種不同的Data Model間搬移內部的資料,或者是在系統裡準備一個共用的系統資料區,在全部需要準備Component Data Model的情況下都與系統資料區作資料的交換。在開發系統時我比較偏好後者,縱使需要為每個Component撰寫一個資料轉換程式,卻可以保證在同一系統下是同一種作法。

在動作方面,可能某一個系統的動作需要同時使用數個Component的方法,直接依序把Component Method放到系統動作方法裡是直覺的設計。但是在分析階段時,必須要檢視是否有一個系統動作需要同時執行數個Component Method的狀況,如果有的話還是另外抽取一個系統方法存放為佳。

無論是Method或是Data,在有差異存在時務必要安排一個物件(而且只有一個)來負責填補其間的差異,以期在使用時能夠直接呼叫而感覺不出有差異。

2008年4月8日 星期二

N08 開發系統與設計Component的差別

設計一個功能,是要解析出達成功能的所有動作,並將之以正確的順序串連起來。在時間急迫的專案裡必須以完成功能為優先,這時可以簡單地先寫出正確順序的所有動作而先不寫上完整的錯誤控制,等到測試階段再根據測試出來的錯誤補寫上錯誤控制。這是很好用的快速作法。

可以這樣做的原因在於專案的功能佈置最上層,除了少數幾個功能可能使用之外沒有任何程式使用,因此無論作什麼樣的改變都幾乎沒有影響。但是Component的設計卻絕對不能用這種走捷徑的方式,因為有非常多的程式使用Component,只要內部的設計有不正確的結果或是因為修正錯誤而改變,都會有多到難以估計的程式受到影響,根據理論所有被影響的地方都必須要重新測試過以保證正確。

有時使用其他元件時會遇到邏輯控制不理想的狀況,那時只能在自己程式的流程裡記錄現在動作的狀態,在後面的流程再判斷動作狀態的內容作對應的處理。這樣的繞路處理很像是在沒有設計好的主機板跳線來達成功能,是很不理想的設計結果。在之前使用swing與swt兩種UI元件時都曾經遇到許多這樣的現象。

設計Component的態度應該時時戒慎恐懼,一方面要努力思索提供足夠的Method應付全面的需求,另一方面要維持設計的品質與定義吻合且沒有錯誤,因為設計不良時微小的改變都會造成其他系統的大量變動。

2008年4月7日 星期一

N07 設計的製程(8)──提供不同範圍的流程Method

雖說Component只提供動作方法,讓系統定義各自使用Component的流程方法是最有彈性的作法,但是使用Component的流程也無可避免地會因為大多系統的使用方法都相同而必須抽取到元件庫的狀況。

系統對於列印的要求定義了一個方法printData(),內部的分解動作是進紙closeInserter()、列印print()、退紙closeInserter(),這三個動作是Component提供的基本方法。後來發現printData()是所有系統對印表機的共同功能需求,因此將集合數個列印動作的printData()放置到Component。請注意此時Component已經帶有了流程方法。

再更進一步在分析系統時又發現:即使列印是把三個動作集合在一起,但是如果接下來還要在同一張紙上接著印其他資料時是不需要退紙的,因此在原有的printData()加上列印後要不要退紙的參數。我們可以發現,Component帶有流程方法後就增加了設計的複雜度。

在流程方法裡的每個動作,使用者都有可能決定要不要做?該怎麼做?所以設計時也必須要同時考量是否要提出參數供使用者決定;但是如果呼叫時每次都設定一大堆參數又相對地比較難使用,所以同時要提供參數較少的預設的使用方法。有時的需求又會要把數個較小的流程方法集中在一個較大範圍的流程方法裡使用。

Component加上流程Method時將會增加許多設計的複雜度,切記要完全遵守OCP設計原則來設計。

2008年4月6日 星期日

N06 設計的製程(7)──備齊Component應有的Method

Component的初期只是系統裡的一個Package,Method的設計都是根據Activity的定義而來。當我們覺得這個Package適合抽取為Compoent時,或許在現在的系統而言只要直接將之劃歸元件庫就可以繼續開發,但是對於一個必須應付多方面需求的Component而言卻應該把所有該有的Method都定義清楚。

想像一下ATM對於晶片金融卡的動作,我們需要的是讀取卡片帳號、比對密碼、變更密碼、顯示約定轉帳帳號等動作,所以在ATM的設計裡定義了這些動作。後來覺得處理晶片金融卡的動作適合抽取為Component,但是原有的動作Method是足夠的嗎?當開發網路ATM系統時,我們會發現還需要加上寫入約定轉帳帳號的動作。

當然有人會質疑在第一個系統時並不知道未來需要什麼,但是我們可以根據簡單的原則來檢視定義的Method。首先是生成與消滅,用來確認如何取得Component物件來使用與不用時消滅它的方法;再來是資料的CRUD原則,Component裡的所有資料都應提供Create、Retrive、Update與Delete四種方法才算是完全的使用(有保護性質的資料就需要隱蔽其中幾種)。

這兩個原則用來檢視存取資料的靜態方法,如果Component裡提供了流程控制的方法,就應該有更進一步的考量。

2008年4月5日 星期六

N05 Component設計要恪守OCP設計原則

Component是基於抽取共用原則所抽取的Package層級物件,一旦標記為共用則表示每個Component Method都會在未知數量的系統被未知數量的程式所呼叫,我們可以想像如果Component Interface Method的定義改變時(例如原來沒有傳回值現在改為傳回boolean),跟著而來的會是大量修改與測試的動作。

處理所有共用部分的最高指導原則就遵守OCP設計原則:Open for Extension, Close for Change。對於原有的方法要努力讓它保持不變,如果內部的作法有所改變就試著在內部程式消化掉,永遠讓方法的使用維持著原來的定義;如果改變無法在內部程式消化而勢必影響到外部的使用,那就就另外定義一個新的Component Interface Method提供給新的需求使用。

單純目標的動作改變的機會不多,大部分的改變發生在流程裡,尤其是改變動作順序或增減動作之類的。也因為動作內部隱含的邏輯極少變化,所以它們是比較適合開放為reuse的部分,這也是一般Component Interface Method定義的方向。流程控制著動作方法使用的順序與方式,因為每個系統操作Component的需要都不一樣,所以會在Use Case實作方法的邏輯裡處理;不過還是建議針對一個Component的操作邏輯另行在系統裡拉出一個對應的地方放置。

使用Third Party Component時若擔心其他公司改版造成的影響,可以幫它加一個Wrapper Class把Component封裝在裡面,讓改變只影響Wrapper的內部作法而不致於擾亂系統的使用。如此將可以更放心地使用其他已經經過測試的好用Component。

2008年4月4日 星期五

N04 設計的製程(6)──設計Component Method

Component Interface Method所定義的,一般都以功能流程裡的一個動作來看待的;流程的分析裡有對某個動作的需求,因而要找出元件裡有支援該動作方法的來使用。

Component的抽取大多是以Package為單位,即使有單純以一組Class為單位的,但是整體來說都是基於Interface Method的定義適合獨立作業。M02裡拉出的特定用途Method時一方面需要檢視元件庫裡是否已經有同樣功能的元件存在,如果沒有的話還要檢視這個Method是否適合作為Component。決定是的話還要再決定它應存在的reuse層級(通用, 行業別, 系統別, 專案專用)

Component的本質是Package,我們可以將之視作更小型的System,裡頭應該只有使用到的其他Component或內部Method。首先我們要用Class Diagram描述Component的內部結構,接著每個Component Interface Method都要至少用一張Sequence Diagram描述執行的過程,作法就像處理System Interface Method一樣。

Component Interface Method進入點同樣會先進到流程Method,設計時要記錄流程裡使用到的每個動作Method;對於每個流程與動作Method也要記錄所使用到的內部變數與其他Component。以Method為主軸記錄使用到的Data與Component就可以追溯出Component的所有使用關聯。

2008年4月3日 星期四

N03 Compoent與API的判斷與佈置

在我而言,判斷的準則其實很單純:就看程式模組處理後是否在物件內保存著狀態。單純地處理傳入的資料並傳回者為函式,除了處理之外還將會影響本身內部狀態者為元件。例如:把檔案讀出為字串應是API、讀取檔案後放置資料的物件就屬於元件。判斷類型後再根據其應用範圍決定它的reuse層次,接著再依照功能放到所屬的區域裡。

在架構上來說,元件與函式都與專案無關。專案之下先是元件,再往下是API,最下面是Java API或是Third Party API,使用的方式是上層的可以使用下層且可以使用同一層內的物件(不可造成循環使用)。Third Party API有時也會被列入到自己的元件庫管理。

在元件的使用上,雖然可以直接呼叫元件提供的方法,但是在系統裡對於元件的使用結果通常會有自己的邏輯處理,這些元件專用的邏輯處理為了避免散落各處,最好是規定一個地方來放置。也因此,我建議對於元件的使用要用以下的佈置。

一個典型的範例在於要處理印表機的低階控制碼:元件動作管理控制碼的輸入、元件動作控制負責印表機對於每個控制碼的反應,這兩者都屬於元件層;專案對於列印的要求是組成固定的格式並控制進退紙與列印,這些複合元件動作就交由元件動作結果控制與元件資料轉換來處理。

2008年4月2日 星期三

N02 資料變化的設計與做事方法的設計

程式設計的目的是要存取資料,這是毋庸置疑的道理。基於這個想法所衍生出來的方法論,簡單地說是先分析出功能裡資料存取的順序與使用方式,再放置處理用的程式;因此我們可以得到資料流動的流程圖,與每個資料流動時的程式處理模組。

這樣的設計可以滿足系統的開發,因為系統最終的目的就是要改變資料;在這個情況下,資料結構與處理程式的定義與追溯關係就顯得十分重要。無論哪一種設計方式,其實都會要求資料結構與業務邏輯的對應關係,E-R Model與資料庫的正規化都可以讓我們設計出最佳化的資料結構。

OOAD的介紹裡常說它是貼近自然界的設計方式,一部分的原因是其設計的重點在於物件的封裝,將系統裡的資料依據特性分別包裝在對應的物件,同時也將處理資料的程式封裝在一起。功能依Use Case Driven的方式設計,強調功能裡應該具有的每一個動作這比起依資料變化所做的設計,更要求了做事方法的設計。

現在的設計方向走到了服務導向,希望連Use Case都可以做到reuse。設計從資料層次,往上推展到處理流程,再往上擴充到整個功能,開發時越來越便利的使用,表示設計時要容納更多的考量。隨著封裝更多的邏輯,除了要保證功能一切要正常之外還要顧慮到使用上的變化。每個功能越來越複雜,也越來越難實作……。

2008年4月1日 星期二

N01 元件庫與函式庫的重要性

在開發系統的過程中,有時候我們會發現某個Interface或某個Method,除了可以滿足現在的系統需求之外,還能夠應付未來的使用。這樣的特色,即使Interface或Method內需要作小部分的調整或是將一些邏輯變數拉成參數,但是還是適合投入一些努力使之成為可以reuse的元件或函式。

擁有元件庫與函式庫的好處在於各個不同的專案裡,為了相同目的所設計的動作,可以找到一個已經開發並且測試好的元件或函式直接使用。抽取元件與函式時,應該也要規畫元件庫與函式庫裡的結構,規定基本共用層、行業共用層、系統共用層等放置的地方(參考L07的層次,元件與函式都各要準備自己的結構),再依照其特性放置到該放的組織層次裡。

除了放置到應用上的結構外,還要依據其應用功能加以分類。我們可以想像元件庫與函式庫就像百科全書一般,想要特定方面的功能時可以先找出符合的元件與函式,再參考reuse層次從中選擇最適合自己需要的。對於一個特定的元件或函式,同樣也可以取得使用時的所有資訊。(也可以考慮將Third Party API加以整理歸類)

函式與元件應該是經過良好設計與完整測試的,在取用時儘可宜接應用而毌須浪費專案的資源再去了解設計、實作與測試。在系統需要與元件功能能夠吻合時,對系統的開發是有絕對好處的。