Presentation is loading. Please wait.

Presentation is loading. Please wait.

跨校推動敏捷方法 促成軟體產業升級 中央大學資工系 陳振炎.

Similar presentations


Presentation on theme: "跨校推動敏捷方法 促成軟體產業升級 中央大學資工系 陳振炎."— Presentation transcript:

1 跨校推動敏捷方法 促成軟體產業升級 中央大學資工系 陳振炎

2 緣由 台灣薪資低 名校畢業生當台勞 產業未升級 公司無力調高薪資 觀念老舊 阻礙產業升級 所以軟體業要推動新觀念: 敏捷方法 全面從教育入手 跨校推動 (初步四校參與)

3 做法 一個方法 myAgile (Extreme Programming plus) 一個專案 Grade System 成績系統 一個網站 Agile Taiwan (台灣敏捷方法苗圃) 今天先談 1) 敏捷觀念 2) myAgile方法

4 敏捷觀念

5 美國先進軟體公司 佈置圖 common white board caves

6 美國先進軟體公司 佈置圖 (Cont.) 上圖分 common 及 cave 兩區: Common 區: 兩人一組,在一台大尺寸螢幕前
工 作 (這叫 pair programming) 各組可目視、交談、溝通 Cave 區: 個人處理 , 電話,閱讀資料等 此外牆上很多白板 white board,供討論用 粗估需30坪 (約99平方公尺),台北很易設置的, 軟體業不求廠大人眾,求高素質高薪少人易溝通

7 回顧 台灣軟體公司 現場 一個小房間裏面坐著滿臉倦容、神情呆滯 (有可能公司節能,不開冷氣,頭暈腦脹)工作一整天,仍加班中的軟體工程師小林,獨自看著一大疊列印出來,自己也看不太懂的程式碼(別人當然更看不懂啦),喃喃自語: 只要再改這地方,就可消除這可惡的最後一個 BUG! 桌上有多本裝訂精美厚厚的文件,但與程式距離遙遠 三小時後,更悲慘了,BUG 仍在! 夜已深,開始自欺麻醉: 明天一早一定就可解決了! (現場寂靜、死氣沈沈) 注意: 像這樣 既沒有溝通, 又思考不清,軟體怎麼可能優質?

8 觀察、改善現場 1.冷氣電費是小錢,工程師產值是大錢,勿省小錢丟大錢 2.辦公室要便於溝通,非必要勿隔間(要搭配群育訓練)
3.要先寫test code 用工具依序test,則不會困惑 (當然要先設計切割,才能在切面上做test code, 且二人邊討論邊做,現場有點喧嘩,但生氣勃勃、 且流露 祥和自在 專注自信的氣氛) 4.要閱讀虛擬碼,勿讀瑣細難讀的程式碼 5.要用工具瀏覽 hypertext (內含 hyperlink), 勿列印(因無工具輔助搜尋、瀏覽) 6.文件常過時未與程式同步 裝訂本更易過時 7.勿加班,否則第二天很累,第三天更累… 8.勿自欺,久而久之,自豪感消失,倦怠挫折…戰將折翼!!

9 兩家軟體公司的省思 要進步,就須改變;如本國公司因工程品質差而業務外包他國,吃虧的還是本國畢業生的工作權!
因工資高,台灣自豪的工廠外移低工資國度[劉維公,風格社會,天下雜誌,2006],我叫它: 後工廠時代,留下的要升級,不要代工,埋頭拼命,處處省錢cost down;要cost up, value up,豪氣做時尚精品;要敏捷工作,心平氣和,慢活,慢食,深眠 拼命文化 要提升為 敏捷文化

10 兩家軟體公司的省思 (Cont.) Slow, but Firm - 要徐緩而確實地工作 徐緩(slow)使心沉靜,則工作平順確實(firm) 沒有失誤,沒有Bugs,沒有拼命,沒有加班, 每天快樂工作,每晚安然沉睡, 不知不覺中 精品呈現了!

11 軟體公司的省思 (Cont.) 假設有 A,B 兩家軟體公司: A 公司員工制服整齊 各人埋頭苦幹 一片寂然無聲 管理報表齊備 工作緊張 B 公司員工穿著隨意 大家不斷討論工作 隨時有哄堂大笑 沒什麼管理報表 工作從容 請問何公司有品質? 答案可能是B 但不可能是A 因A公司缺軟體公司核心要素 - 溝通

12 團隊須含駐點使用專家 有人以為這是涼缺,其實要做很多事: 1.寫使用情節 (Scenarios) 2.與開發者確認使用畫面 3.由使用情節寫驗收測試(需準備大量data) 4.當某功能完成(即其methods皆已整合),即刻執行其驗收測試(或督導工讀生去執行) 例子: 若某功能有五個使用畫面,每畫面有三狀況 則最多有 3的5次方243個驗收測試

13 (Test-driven development, TDD)
下面先解釋七個基本觀念 再以之建構 溝通週期 (Communication Cycle) 為基礎的 測 試 帶 動 法 (Test-driven development, TDD) 陳教授的 myAgile 即是測試帶動法

14 1.Pair Programming 雙人組開發
兩人配對即時溝通,有點像趣味賽兩人三腳; 加快開發及除錯速度,並激發創意 兩人肩並肩坐電腦前,同時注視螢幕,一人主導(drive),另一人從不同角度思考,即時查核(review),並可隨時交換角色 過程中隨時討論程式細節、做法,並藉由討論、爭辯,找到最佳程式寫法,隨時注意程式撰寫的小錯誤或邏輯錯誤,錯誤發生時則共同除錯, 以降低錯誤率和提高除錯效率 這樣可較快完成較佳成果(Better work in less time), 會帶來工作驕傲感 (pride-in-work)

15 1.Pair Programming (Cont.)
1)工作驕傲感,即自慢(日語,慢者傲慢也)、自傲、自豪,有助培養強烈企圖心、不服輸鬥志、樂在工作中 在此”後工廠時代”,應揚棄下面工廠思維: 兩人做一事,人力成本太高 兩人整天交頭接耳,一定在混! 此外要培養 2)公民意識(後敍),3)敏銳注意週遭, 4)自發地行動 (act spontaneously), 這四點可使團隊績效臻於顛峰 上述就是 群育,正是台灣教育的弱點之一 例子:[電視骨質藥廣告] 一老一少忙於佈置新店面,古董花瓶不小心被年青人撥倒,老人快步扶住,兩人相視一笑

16 1.Pair Programming (Cont.)
有程式師很自我 ego,不願與某人配對,應離職; 兩人互不願配對,兩人應離職 草莓族雖不耐操,但較不自私自大、反而較合群 例子:某路邊,中年人轎車亂停, 草莓族青年人機車反而都依照格子停 成員程度有高低,高高配、低低配可收切磋效果激發創意 而高低配則形同教學無切磋之效,但有管理之效 人其實不相等,二人行必有我師(三人行不精確) ,配對工作可促成團隊技術提升拉齊,每個回合(iteration)配不同人(輪調 rotation),大一計概開始做! 例子:某研究生團隊四人藉 pairing 由不懂到完成軟體! 大道至簡,溝通而已矣!

17 1.Pair Programming (Cont.)
如何深耕 pair programming? 陳教授認為要改變工作習慣 試想:遊玩時要有”玩伴”才愉快盡興,那麼學習時也要有”學伴”,兩人一齊在螢幕前複習教學投影片,才愉快有效 陳教授希望藉教學時推廣”學伴”,來厚植 pair programming 習慣

18 1. Pair programming (Cont.) 面對面溝通 效果最佳!
1. 小張、老李 pair programs.(效果最佳) 2. 兩人用不同電腦,但肩併肩 (效果很好) 3. 兩人各據一角,背對背 4. 兩人在相鄰辦公室,有牆隔開 5. 兩人在不同樓層或相鄰大樓 6. 兩人在不同時區的城市 (效果差,有人加裝視訊設備, 叫 distributed pair programming, 效果並不好)

19 Pair Programming 好處 一個人的邏輯思考上常常會出現漏洞,兩個人的邏輯思考卻可以降低這樣的漏洞發生。Pair programming不僅可以提昇工作上的品質,更可以營造出融洽的工作氣氛,以往的programmer都是一個人撰寫一支程式,遇到問題才與同事間 相互討論的方式來解決,或是自己悶著頭上網找資料或想法;若是採用pair programming 的方式,兩個人可以在討論問題之餘穿插個閒話家常,這樣看似是在浪費時間,但是實際上是可以降低彼此腦部思考的壓力,因為一直想同一件事是容易想不通透的,那何不放下心情來降低腦中的壓力後再來思考,這樣對於事情的進展反而是更有幫助的。 [中央大學碩士 蘇友信 (Silver)]

20 Collective Code Ownership
經過上述 Pair Programming 及 rotation 久而久之,團隊成員可大致了解他人寫的程式,甚至可維修他人程式-不畏員工流動了! 成員間信任感很高,重用(reuse)閱讀他人程式時,可快速主動改善之,而不必知會原作者或上級,使軟體在不知不覺中,不斷提升品質,再搭配測試碼把關,可確保品質 這形成程式碼不屬於原作者的共有制度 叫程式共有 collective code ownership

21 2. Re-factoring 重整 程式在保持原功能下 需不斷小幅改寫 以提升可讀性 (small behavior-preserving transformations), 叫重整 需: 1.各人願意去改別人寫的程式;相對的, 高興自己程式被別人改進 (群育訓練) 2.程式人人易懂(設計草圖及虛擬碼解決此事) 3.程式修改後,要週密地重做測試 (test code,JUnit 解決此事) 重整後得新版本,存於版本控制系統 好處:interface不變時,因有測試碼保護,開發者勇於修改 舊程式(重整),使軟體常新; 若interface改了,則要重做測試碼

22 Reuse 重用 vs. Refactor 重整 架構設計決定後,應盡量Reuse(重用)既有程式(不管是本公司別人寫的或未謀面的人寫的open source)以提高品質,且少耗力氣 另一更重要的是:程式要勇於 Refactor(重整),使程式脫胎換骨,品質爆增,有如地上醜醜人見人厭的蛹勇於蛻變,成了美麗飛翔人人欣羨的蝴蝶

23 3. Continuous Integration 持續整合
每個public method 寫完,用unit test code (後敘) 測完後,數小時內即整合進系統,不拖過夜 (隔夜就忘大半了) ,各個 method 是這樣持續地整合進去, 若某功能的 methods 都齊了,駐點使用專家就手動測其驗收測試 這好處是: 以往痛苦的integration phase 不見了;現在,腦筋還記得當天寫該method 的細節,所以很容易整合

24 3. Continuous Integration (Cont.)
Method 有其呼叫使用順序: 被呼叫者為下層 method 呼叫者為上層 method 最好先整合下層 method 進入系統 若先整合上層 method 則因其呼叫尚未在系統內的下層 method 會造成錯誤 這時應在系統內暫補 空的下層 method (它叫test stub)

25 3. Continuous Integration (Cont.)
傳統軟工的整合測試已在此巧妙完成了: 當各個 unit (method) 由下而上(bottom-up) 持續整合進系統時 (continuous integration), unit testing (單元測試) 也就成為 整合測試 (integration testing)了

26 4. Simple Design 簡約設計 簡約是任何設計的精髓* 透過CRC會議(後敘)的溝通,想出軟體系統中各class
及其之間的關係: 1) 各class 須呈現簡潔外觀 (interface),與一致的格式 2) classes 之間的關係須: 簡潔(關係不可太多) 平衡(不可呈星狀結構) *設計簡約,質感出眾 [IKEA 桃園店標語] 反映北歐極簡、內斂風格 質感 > 品質 > > 質量

27 5. 交貨規劃(Release Planning)
由駐點使用專家(後敘)主導的會議 (開發者必參加) 會中決定目前系統功能 (user stories) 要分幾次交貨(releases) 客戶需求不斷變動,故只第一個release (平均為兩個月)確定,往後releases,日後再修訂,這叫演化(evolve);軟體不斷演化,不再有開發、維修之分,且演化使文件瞬間過時,故本法倡虛擬碼,隨時閱讀了解修改軟體

28 6. 回合規劃(Iteration Planning)
由開發者主導的會議 (駐點使用專家必參加)會中決定”派工及時程”(工序四) 每個回合工作量不同,故其週數不固定,平均為三週*,這就是敏捷方法專案管理**。三週不長,故時程可嚴格控制,因而取信(甚至感動)客戶 * 石頭閒語網站認為:Ruby/PHP 生產力比Java 快5倍,可2-3天就推出release ** 傳統軟工專案管理常規劃一季(三個月)時程,軟體業一季中變動太大,專案經理通常無力控制時程

29 6. 回合規劃 (Cont.) 要在白板上精準寫出: 每個method 每個class 預定之工作天數 每天追蹤進度 才能依規劃完成該回合 之前交貨規劃時 會預估每個功能(user story)之工作週數 向客戶粗估時程 這與上述精準控管不同

30 7. 站著開日會* (daily stand-up meeting)
每個工作天,全體開發團隊成員要 站著、圍成一圈,舉行每日會議 要站著,才可長話短說,使會議簡短 要全員,才使資訊直接傳達至每一人 要每日,才使溝通週期縮為一天 (昨日談的事,今日即可當面問) * 有專家認為:既然團隊整天在一起,溝通已足夠,就不需此會議,各公司自行斟酌吧

31 Communication Cycle 溝通週期
不斷溝通、回饋、檢查、除錯、修改; 幫助人人成長、技術精進 回合規劃 站著 開日會 簡約設計 Pair Programming with On-site Customer 1..N Bugs CYCLE TIME 5 seconds 持續整合 重構 1..N Iterations 3 weeks 交貨規劃 1..N Increments 2 months 增量 增量加 上次交貨 測試碼保護中 1..N Methods 0.5day CYCLE TIME 1 day 喜好度調查 1..N Questions CYCLE TIME 5 seconds (Not in XP)

32 測試帶動的開發方法 (Test-driven development, TDD)
上面的溝通週期圖中,每個溝通圈走一圈(溝通要快而準),就是一次測試,在週而復始的不斷測試中,優質軟體緩緩開發出來了! 例子: Pair Programming中,小張將 N-1寫成 N, 同伴老李馬上指正,這就是測試 例子: Pair Programming中, 駐點客戶 (on-site customer) 小王要求畫面字體加大,這也是測試 例子: 喜好度調查中,使用者小林回答對某功能喜好度(1至5,5表最愛)為: 1 (極不喜愛),這也是測試

33 測試帶動的開發方法 (Cont.) Test-driven development (TDD) 原本是指 test case, test code, test tool 在本法中 TDD 擴充其範圍,包含: 口頭確認 (check) 人工審查 (review) 等 廣義的 Test

34 myAgile 方法

35 myAgile 敏捷方法 (11道工序) * 0.探索需求 (Exploring requirements)
1.使用情節 (Scenario) 2. 驗收測試案例(Acceptance test case) 3.架構設計會議 (CRC session) 4.派工及時程 (Dispatching and Scheduling) 5. 單元測試碼 (Unit test code) * 6.資料結構設計 (Data Structure Design) * 7. 演算法設計 (Algorithm Design) 含設計草圖及虛擬碼 8. 補上程式碼 (Coding) 9.單元及驗收測試 (Unit & Acceptance testing) * 10.逆向工程工具 (Reverse Engineering Tool) (* 4道工序 即陳教授補充, No.6,7未落實可能造成O-O失敗) (另外7道工序 即原始 Extreme Programming)

36 1.使用情節 (Scenario) 駐點使用專家(on-site usage expert)(前工序兩人之一)逐步用文字寫軟體某功能 ( feature) 的使用情節(scenario),用A4紙以鉛筆記錄之,字跡工整可讀,不可鬼畫符;阿拉伯數字要慢寫清晰 探索找尋各種使用情節 - 由簡單而繁雜,由正常(normal)而異常(exceptional) 同類 scenarios 存放同file ,可用editor快速修改 例子: 遊戲軟體最簡單的 ”情節一”: 1.看到welcomeScreen (圖一)* ,輸入password 2. 看到 mainScreen (圖二)*,離開系統 * 在白板畫出各圖

37 1.使用情節 (Cont.) 傳統常做 流程圖 (Flow Chart) 它與虛擬碼 (pseudo code) 的抽象層次相同 只是表示法不同 而本法採用虛擬碼 一個虛擬碼會對應多個使用情節(雖抽象層次高很多) 例如虛擬碼中 if then else 對應兩個使用情節(分別執行then及else)

38 2.驗收測試案例 (Acceptance test case)
上述每個使用情節, 加上輸入資料及預期輸出資料後,即做為測試該功能可否驗收之依據, 叫一個驗收測試案例 也就是, 依每個案例跑程式; 如順利跑完,則該驗收測試案例 (acceptance test case) 通過 例子: 遊戲軟體最簡單的”驗收測試一”: 看到 welcomeScreen,輸入password JFK2008*後, 看到 mainScreen,點選 Exit,離開系統 *JFK2008 是 exact data,”情節一”無此 data , 又, 此data常是龐大的data file.

39 User Manual 驗收測試案例稍加修改簡化 可輕易得到 User Manual 記得文件是動態的 驗收測試案例隨時變動 所以 User Manual 也是隨時變動的

40 3.架構設計會議 (CRC Session) 架構設計會議常使用CRC(Class,Responsibility, Collaborator)會議:五人以內圍坐(二人亦可,國內單人專案多無切割,兩人先溝通切割系統吧) ,執行驗收測試案例,推敲切割(partition)之, 找出物件(object)及物件互動(object interaction,即method),須含下層隱藏物件(hidden objects),用小卡片(CRC card,可用A4紙)記錄: 1.Class name (C), 2.要做何事 Responsibility (R),(將轉為 method) 3.要誰合作(即需呼叫誰的 responsibility) 叫 Collaborator (C) 會議後所有 CRC cards 即系統架構(class interfaces),(1)(2) 找class encapsulation, (3) 找 class use relationship 此會議是群體智慧- 腦力激盪,快速溝通 真相: 大型軟體從未在架構師腦袋,而是多個程式師共同擁有

41 3.架構設計會議 (Cont.) 1. 對每個 accep. test case 由第一步驟出發,大家討論:
要有那個 object 執行那個 method,接著 又有那個 object 執行那個 method … 直到最後步驟做完 2. 討論中,用一張A4紙記錄一個class及其methods, 並指定專人扮演這class (即CRC) 3. 會後,檢視所有A4紙,並調整之(如某些classes 可合併) 即得 class interfaces (軟體架構) 4. 架構定案後,各 method 要寫好 header (method description, parameters, return value, exceptions) 1.parameters 不超過 5 個 (magic 7 minus 2) 2.return value 是一個 object, 但寫出的是其 class 3.原則上禁用 global variables

42 3.架構設計會議 (Cont.) CRC集思廣益來切割(partition)驗收測試案例,並找出user看不到的下層隱藏物件(hidden objects) 紅色表示 例如: 張三是位官兵 李四是個土匪 某日二人狹路相逢* 張三要用繩子捉拿李四** 李四問王五綁何處 (王五是位醫生) 張三想起兩人恩怨情仇 不禁流下熱淚 *一般英文書用John, Mary為物件名, 國人感受不深, 故用張三等 * Scenario中細字表示未實作部分 底線表class,object 粗體表method 斜體表parameter **直覺的說: 張三用繩子捉拿李四 但 O-O程式不是這樣執行的 method捉拿屬於土匪

43 3.架構設計會議(Cont.) class官兵{..} 官兵 張三 class土匪{.捉拿(工具,被捉者)}土匪 李四
由上述 可得下列設計: class官兵{..} 官兵 張三 class土匪{.捉拿(工具,被捉者)}土匪 李四 class醫生{..綁何處 ( )} 醫生 王五 ..... 李四.捉拿(繩子, 李四); …… 王五.綁何處 ( );

44 3.架構設計會議(Cont.) 複習一下本例基本觀念: User Story (功能)是:張三捉人 Scenario 是:張三要用繩子捉拿李四 Use Case 是: (這文件併入架構設計文件) 張三要李四用繩子捉拿他自己 李四問王五綁何處

45 張三捉李四的真相 的確是張三下令要捉李四,但張三沒動手
張三把繩子給了李四,並指示李四:被捉者正是李四自己* 然後李四毫不猶豫執行捉拿動作** 而張三不知道動作細節(綁手或腳),執行後系統會回報結果給張三*** * The method gets two input arguments. ** then, it executes the method, *** finally, it sends return value.

46 架構設計的重要性 專案如沒做好架構設計,將導至: 物件不吻合客戶觀念,即 O-O 失敗! 同時,因無良好切割,常有太大模組,
無法找到完整單元測試狀況,使品質差。 而且,重擔集中在寫大模組那一人, 無法真正分工,也就無法做到teamwork 架構設計切割出的class, public method 要寫class interface,再補充成標頭(header)

47 Class Interface 的好處 1. 藉精準命名 class names, method names
捕捉客戶觀念,以落實物件導向(O-O)開發;如客戶不懂這些 names,此時尚未開始寫程式,即已確定 O-O失敗! 2. 可依之分工,多人併行開發各 class, 以加速軟體交貨;高速度交貨很重要 Class interface 補充後成為 class header 內有 method headers

48 Class Interface 例子 Selection Sort 的class interface 如下:
public class mySort { /*稍後 data structure 在此 (目前不含)*/ public mySort (int inputArray[]){ } public int [] sort ( ) { } } // end of mySort method interface

49 確認 物件 駐點使用專家要確認: 物件是否吻合客戶觀念:
確認 物件 駐點使用專家要確認: 物件是否吻合客戶觀念: 1. 將class names, public method names (英文)列一清單, 刪除底層電腦相關 names,如資料庫class 2.不加任何書面或口頭解釋,將清單給多位領域專家 3. 專家們逐一確認上述 names : 如了解,則打勾;如不清楚,則打X 4. 統計打勾比例,如100 個 names 平均有 80 個打勾, 則 O-O 80% 成功!

50 為何要確認 物件? 軟體必須精準反映領域知識(domain knowledge) 才易不斷維修 軟體才活著 而領域知識就是領域專家們的知識
所以要確認軟體用詞吻合 領域專家們(domain experts)的用詞 例子: 會計軟體用 class Names 如BalanceSheets, Accounts 等; Object Name 如 sep09Account; method Names 如 debit 借, credit 貸

51 Interface and Header (標頭)
Class interface and method interface 之前都需要文字說明, 以便維修者閱讀了解之 這文字說明就叫 Header (標頭)

52 標頭(header)的重要性 搜尋、閱讀 open source 的標頭,才能重用程式(reuse code);與開發程式(developed code) 相較,它較優質,應優先採用:1)因大眾測試過(可信任), 2)並有效能評估(Big O time estimate) 大量重用程式,小團隊(small project size, team size)能快速完成優質大軟體(big problem size) 開發程式行數(Line of code)無甚意義了

53 標頭的重要性 (Cont.) 標頭有點像程式碼的使用手冊,常見一般人使用電氣用品不讀使用手冊(有時因使用手冊艱澀難讀),易把東西用壞,修幾次後就不能修了,只好丟棄,很不環保 標頭也像報紙標題,要能助讀者輕鬆讀報 標頭要寫好,程式碼才能易讀易修, 活得長長久久

54 Interface 的重要性 有次安裝冷氣機後,工人開冷氣開關,機器不動,於是拆開冷氣機檢查,後來才發現是: 電氣總開關中,冷氣開關標示位置錯誤 對應到軟工領域:有次開發軟體時,軟體不動,於是工程師 debug source code,後來才發現是: API (application program interface) 的 header 寫錯了

55 Header(標頭)設計原則 Header要醒目易溝通[寫給大家的平面設計書,R. Williams原著,三言社,2006] 舉數原則: (後面有例子) 1.利用空白將相似項目放一起 形成視覺單元 2.每頁不超過五個單元 3.各單元要對齊 形成視覺聯貫性 4.要重複重點(如粗體字) 營造一致性風格 5.要強烈對比(如粗體字與標準字) 營造視覺焦點

56 Header(標頭) 兩例 /* method subString * A String object呼叫此 method,傳回介於兩個指定的 indexes 的子字串 * beginIndex 子字串起始的 index (含此 index) endIndex 子字串最後的 index (不含此 index) 由 beginIndex 到 “endIndex 的前一個位置” 的子字串 IndexOutOfBoundsException – * if beginIndex 是負數 or * beginIndex 大於 endIndex or * endIndex 大於 length() * Time estimate : 演算法設計後,才獲此資訊,如 O (n) * Example: “helloworld”.subString(3,6) ; 傳回結果為 “low” */ public String subString (int beginIndex, int endIndex)

57 *------------------------------------*/
/* class EventDetectionThread * * 本 thread 產生 detector,它start後,每0.5秒(500 ms)到預設的./buffer資料夾抓取(fetch)一個event information(.xml)的path * 並通知observer (叫 event parser) 此path. * 如資料夾是空的, 則回傳null. * Example: * ./buffer資料夾有存進來的三個event information: * xml (最早存進來) y09 m11 d23 ms0 * xml y09 m11 d23 time1530 ms40500 * xml (最晚存進來) * detector 依序抓取 xml 等等 * */ 註:如寫detector=new EventDetectionThred();則不夠abstract

58 工序一至三片段例子 工序是前後聯貫的 例如: 1.Scenario: show finish message (msg) 2.Acceptance test case: show finish message (msg) “結束了” 3.Architecture design: /* show finish message “結束了” */ public void showFinishMsg()

59 傳統軟工設計(Cont.) 例子: 兩個軟體工程師風格迥異: 小王: 某程式寫二百行很快寫完 小林: 上網查API直接reuse 一行也沒寫 誰應加薪? 真相: 小林應加薪 因reused code不需測試 且日後永不需維修

60 傳統軟工設計(Cont.) 例子: 兩個軟體工程師風格迥異: 小王: 很快開發完20K的class 小林: 仔細推敲不同切割方式 最後完成 多個 2K 的小classes 誰應加薪? 真相: 小林應加薪 他完成 well-crafted software 而小王只完成working software

61 4.派工及時程 依上述軟體架構 (class interfaces), 各個 class 由團隊成員”認領” 即為派工(真義是: 領工)
由認領本人依本身狀況,估計工作天數,乘公司經驗值寬放係數後,即為時程 本回合內每天嚴守時程,即可精準交貨,以執行力達成承諾 才能取信、感動客戶* *國興電視”全能住宅改造王”注重生態文化,工匠極致矣 下圖白板上顯示 Mary Ann 回合 的派工資訊

62 Cockburn, Agile Software Development, p.86, Addison-Wesley, 2002.

63 4.派工及時程 (Cont.) Release 交貨 vs.Iteration 回合
只對目前回合(二至四週,平均三週*) 做派工及時程規劃,回合可打出進攻節奏(pace)使團隊威猛快速 (strong heart-beat) 每回合後微調方法(methodology tune-up) 每一至四個月(平均二個月)交貨給客戶** *用Ruby/PHP(而非Java)可縮短時間;用組合語言,則增長 ** 不斷交貨(即演化 evolve),已無開發、維修之分

64 Release 交貨 Increment 增量 Iteration 回合
約二個月 虛線表示:不確定、可變動 增量 1 增量 2 交貨 1 交貨1 +增量2 =交貨2 約三週 回合 (派工及時程)

65 5.單元測試碼 (Unit test code) 對某 class 的每個 public method (叫單元 unit)先想出多種測試狀況 (test cases)由簡而繁(最簡如 null input)由正常而異常 (異常exceptions 若 handle 不好,軟體將不好用) 每一狀況寫出輸入 (input) 及預期輸出 (expected output) 叫一個單元測試 (unit test case);再改寫成測試碼 (test code) 相對於他國,國人工作文化較急燥,所以更需要做好單元測試碼 做為程式護身符 程式一有維修,即全面重跑測試碼,可確保品質

66 Test Code Example //Test Case 1:input {3,1,4,2} expected output:{1,2,3,4} public void testSort1() {  /* input為待排序數列,expected為預期結果, result為實際結果*/  int input[] = {3,1,4,2},expected[] = {1,2,3,4}; int result[]; /* new 一個 mySort的物件,傳入參數input */ mySort obj = new mySort(input); /*呼叫sort來排序*/ result = obj.sort(); /* assert實際結果與預期結果是否 equal */ assertEquals (toString(result), toString(expected)); }

67 Test Cases As Test Code Header
//Test Case 1: input {3,1,4,2} expected output:{1,2,3,4} //Test Case 2: input {1,1,1,1} expected output:{1,1,1,1} //Test Case 3: input {3,2,4,2} expected output:{2,2,3,4} public void testSort1() { /* input為待排序數列,expected為預期結果, result為實際結果*/ int input[] = {3,1,4,2},expected[] = {1,2,3,4}; int result[]; …….. public void testSort2() { …… public void testSort3() { ………

68 More on Test Cases (Cont.)
舉極簡例: 先開發 method interface: /*加 a,b,回傳其和*/public int add (int a,b) {} 1.a,b 各有正,零,負三狀況,共有九狀況: Case 1: a is 1, b is 2 (正,正) Case 2: a is 1, b is 0 (正,零) …… 2.將 9 test cases 寫成 test code 3.再開發 source code 即 { return a+b;} 4.最後用Junit跑test code測source code

69 6.資料結構設計 (Data Structure Design)
對每個 class,要設計這 class 所含的 public methods 共同要用的 data 儘可能設計出 high-level data structure 如tree 而非 low-level data structure 如array 這樣可簡化 演算法設計 使之易於思考

70 6.資料結構設計 (Cont.) 建議使用Java Collections Framework (JCF) *
含下列三種離散數學觀念及其 classes: 1.List如<1,2,3>: ArrayList, LinkedList 2.Set 如{3,1,2}: TreeSet, HashSet 3.Map 如{1->a,2->b,3->a}: TreeMap, HashMap 另有 Heap, PriorityQueue (以後可能有 Network) JCF method 有 Big O,使開發的 method 也有 Big O 例子: for each i 從1 到 N call TreeSet method with O(logN) end for 即得 O (N logN) * Collins,Data Structures and the Java Collections Framework, McGraw-Hill, 2005.

71 An Example 例: 從小明家有單行道十公里到小英家 本頁是問題描述 下頁才是設計草圖

72 adjacencyMap 100 17 29 57 85 95 null hash key value next 68899 小華 小莉
29 57 85 95 null hash key value next 68899 小華 小莉 小明 小英 阿偉 15.0 8.3 20.0 14.2 10.0 7.4 to distance next

73 設計草圖轉成 Java data structure code
protected HashMap <Houses, LinkedList <NeighborDistances>> adjacencyMap; protected Houses 小明; protected NeighborDistances 小明小莉14.2;

74 6.資料結構設計 (Cont.) 資料結構設計與演算法設計互有關連,前者高階 則後者精簡、品質高
目前很多人寫程式,不落實資料結構設計,直接進入演算法設計,甚至直接進入程式設計,其資料結構只用很多基本的陣列 (array)這使得演算法繁複,導致程式冗長,不易閱讀維修

75 6.資料結構設計 (Cont.) 有學生問: 如要存放一些資料到 array 那麼資料結構就用array就好了 何必用高階資料結構呢? 答: 用高階資料結構 Java 的 ArrayList 可 auto resizing 當長時間使用後 array資料滿了 它可自動擴充size 使系統不當機 這當然比用低階的 array 好多了

76 7.演算法設計 (Algorithm Design)
先依資料結構及單元測試,畫出設計草圖 (design sketch)並寫下當時的解題想法,再用英詞中句的虛擬碼 (pseudo code)寫出該想法,此即演算法設計 要依不同抽象層次 (abstraction levels) 由上而下逐層寫出虛擬碼 每層都要 trace test case來debug,即演算法設計 除錯 最下層虛擬碼即演算法,要做時間估算 (time estimate), 若時間太長,如O(n3),則重做資料結構設計 若演算法超過一個畫面,則分割出下層 private method, 這可使演算法清晰呈現 (若只有程式碼,無法呈現演算法) 演算法可投影牆上,做 團隊審查 (group review)

77 設計草圖

78 虛擬碼設計一 public Tokens[] getTheTokens ( )
//see youTube “compiler lab1 scanner” Tokens aToken // next token in the line String line //the current line being scanned private skipBlanks () if (endOfLine) then do nothing else while (tokenBeginning points to a blank) increment both tokenBeginning & forward end while end if end skipBlanks()

79 1 open sourceFile 2. read first line into “line” 3. forward,tokenBeginning ← 0 4. while (not endOfFile) 1. call skipBlanks( ) 2. if (endOfLine) then 1.read next line into “line” 2.if (not endOfFile) then forward,tokenBeginning ← 0 end if else 1. call getNextToken( ) to get aToken (“tokenBeginning” to “forward-1”) 2. store aToken into theTokens 3. tokenBeginning ← forward; end while 5. return theTokens end getTheTokens()

80 改善虛擬碼 虛擬碼設計一的缺點: 1: skipBlank() 內不只跳過空白字 還要檢查是否 end of line 太複雜
2. 若把上述end of line 檢查移到calling program (getTheTokens) 發現end of line 檢查重複兩次 須化簡 改善後 得到虛擬碼設計二

81 虛擬碼設計二 public Tokens[] getTheTokens ( )
//see youTube “compiler lab1 scanner” Tokens aToken // next token in the line String line //the current line being scanned private skipBlanks () while (tokenBeginning points to a blank) increment both tokenBeginning & forward end while end skipBlank ()

82 1 open sourceFile 2. read first line into “line” 3. forward,tokenBeginning ← 0 4. while (not endOfFile) if (endOfLine) then 1.read next line into “line” 2.if (not endOfFile) then forward,tokenBeginning ← 0 end if else 1. call skipBlanks( ) 2. call getNextToken( ) to get aToken (“tokenBeginning” to “forward-1”) 3. store aToken into theTokens 4. tokenBeginning ← forward; end while 5. return theTokens end getTheTokens()

83 Why 增加兩種文件? XP 常被批評文件不足,又斟酌台灣國情, 故增加兩種文件: 1. 設計草圖 (design sketch)
寫在白板或白紙,短暫儲存 重要草圖可貼入文字檔長久儲存 2. 虛擬碼 (pseudo code) 寫在文字檔(如Java file)可與程式融合, 長久儲存 它與流程圖(flow chart)語意相同

84 Why 增加兩種文件? (Cont.) 有研究生問: 網站看到美國程式 並無設計草圖虛擬碼 何以需要? 答: 在美國鄉間小路 中間沒劃分隔黃線 但開車者心中有把尺 把路分兩半 車子開在右半 左半留於對向來車 這就不撞車了 在台灣 就需要有分隔黃線 才免於撞車 因為人的心中無法度 文化不夠 只好增加工序 另一正面思考是 這可使台灣軟體品質超過美國軟體

85 Design Sketch 設計草圖 利用紙、鉛筆、橡皮擦、尺描繪出design sketch
首先從數列中 select 出 min(即 數值 1),並放到數列的第一個位置(即 索引 0)。 索引 數值 .. n-2 n-1 3 1 4 2 1 ( i ) .. .. n-2 n-1 1 3 4 2 固定此數不再變動。 再從剩餘數列中 select 出 min(即 數值 2),並放到剩餘數列(即 索引 i ~ n-1)的 第一個位置 (即 索引 1)。 1 ( i ) .. .. n-2 n-1 1 3 4 2 .. n-2 ( i ) n-1 1 2 4 3 固定此數不再變動。 依此方式直到走訪完, 走訪至數列倒數第二個數(即 索引 n-2)。 .. n-2 n-1 1 2 3 4 即完成數列小到大sort (詳見範例)

86 Design Sketch (Cont.) 畫design sketch 後 - 看圖說故事:
故事即 pseudo code 細部設計(上頁右側) Sketch 很人性化,開發者心神負擔 (cognitive load) 小,不易出錯,品質較高 兩人在白板前進行 design sketch, 可充份討論,品質較佳

87 Design Sketch (Cont.) 各種設計皆始於草圖(sketch), 草圖要”草”(不精確描述 未確定部份),
再逐步思考、決定,趨於精確描述, 可用 //TODO 或 //?? 表示未確定部分的圖 這樣避免率爾決定,才有深而密的思考 程式師常過早使用精確符號(如程式語言) 過早決定細節, 這就破壞了設計品質

88 Pseudo code 內文 Pseudo code 內文以英詞中句書寫 英詞 (English Term) 就是詞直接以英文表達
(如 class name、method name、variable name等),要精準,須與程式內命名相同 至於「詞」組合成「句」,因國人英文造句能力較弱,故用中文句子(叫中句),便於快速了解以維修之 例如下面中句含二英詞: 從array [i..N-1] 中找 min , 並換到它的第一個位置

89 英詞 (English Term) 如果開發者以中文思考 且皆閱讀中文資料則其腦海不易訂出精準英詞 可是程式要以精準英文表達的
此時要找英文較好者 review 英詞

90 英詞 命名 Class, object, variable 以名詞命名 class 用大寫開頭 最好複數 (如Desks)
object 用單數 最好有冠詞 (如myDesk) 只有一個 object,不致混淆,則省冠詞 如 symbolTable 而非 aSymbolTable Method 以動詞命名,並以參數區別之,如: buy (Desks myDesk) buy (Tables hisTable) 為不同 methods

91 英詞 命名 (Cont.) 英詞 要易了解,才記得住 (sticky 黏得緊不脫落 意即不忘記) 請用十秒鐘 默記下面英詞 再寫出:
測驗一: WT Oleogg Crosmioft 測驗二: TW Google Microsoft

92 英詞 命名 (Cont.) 上面的英詞 WT0820 TW2008 雖擁有相同字母 但因排列不同 其易記性 (stickiness) 品質差異甚大 TW2008 使讀者聯想到: 1. TAIWAN (TW) 2. 西元2008年 這兩個印象深刻的詞 易了解 因而易記 WT0820 則無此機制 讀者需死背字母順序 所以易忘 不易記得

93 Pseudo code 結構 1. Sequence 如: 2. Selection 如: 3. Iteration 如:
1.從 array[i..N-1] 中select出 min,且換到它的第一個位置 2.固定此數不再更動 只有1.無2. 時,不構成sequence,故不寫1. 2. Selection 如: if 第 j 個數比 min 所指的數小 then 叫它min else null end if 又如 case .. end case 3. Iteration 如: for j from i+1 upto N-1 if 第 j 個數比 min 所指的數小 then叫它min end if end for 又如 while .. end while

94 Pseudo Code 關鍵詞 關鍵詞以外的英詞,必須是 data (或method) names 1. 2. ….
if then else end if case end case while end while for each end for from upto downto by call null ← ( a←1 means “set a to 1”) //?? 存疑部分 //TODO 待補充部分 (有?或TODO時 不可coding) 關鍵詞以外的英詞,必須是 data (或method) names

95 Pseudo Code (Cont.) Pseudo Code 依據下面抽象層次 (abstraction levels) 逐層開發:
1. 抽象層次最高,接近人類思考敘述方式。 2. 抽象層次中等,一半程式一半人類方式。 3. 抽象層次最低,接近程式層次。 且逐層用 test case 手工 trace, 這就是 演算法設計 除錯

96 Trace to Debug (演算法設計 除錯)
Trace pseudo code 要精準 如無法trace 則表示pseudo code 有思考不週之處, 絕不可貿然進行 coding, 否則, source code 絕不會 work Trace 要心平氣和,從容自信,要優雅, 不慌亂粗糙,才能精準除錯 (Trace to Debug) source code 將無任何 BUG!

97 Trace to Debug (Cont.) 認知心理學家指出: 要放鬆(relax)、專注沉靜,不能焦慮不安,才能心智暢通,創意湧現(神經緊繃時,做不到這個的) 不妨泡杯好茶,戴耳機(不妨礙同事)聽音樂 在此 專注 情境下,才能查出: 軟體思考漏洞 (BUG!) 例子:某生 確實 trace Compiler Project 虛擬碼, 使 整個 project 程式無 BUG!

98 Trace to Debug (Cont.) 請回想: 上次找不到鑰匙的情形 愈著急、愈找不到,氣了一整天 ……
晚餐時,氣消了、認了、算了、放鬆了 突然間 - 想到了!鑰匙就放在 …… 放鬆而專注 (絕不是鬆懈) - 才能 創意湧現 (Flow)

99 Trace to Debug (Cont.) Trace不下去時,表示在那特定點思考不清,可即刻尋求他人協助那點
只要問題點明確,他人可快速解答之, 這種溝通甚為 簡短有效 若無 pseudo code,他人縱然有心協助, 也將陷入 source code 泥淖中, 這種溝通 耗時耗力、而無成效

100 7.演算法設計 (Cont.) 寫出完整虛擬碼,然後耐心地 trace to debug,這工作似易實難
因為:長年來工作習慣根深蒂固,要寫程式才能思考(趕工不放心時更是如此);寫虛擬碼只是應付上級要求,不習慣在該階層思考。也不會封裝低階data 為高階class,以進行高階思考,當然無法有效做此事 一定要深信本方法威力,才能心平氣和、心思澄靜, 不只無錯,而且有創意、美感

101 7.演算法設計 (Cont.) 有人指出: 不需寫出虛擬碼 因為Java code 是高階語言 本身即具可讀性 但是 依陳教授經驗:
虛擬碼可提供更簡潔 更高階的了解 可讀性更提升 更有助日後維修

102 例子 單元: public Entry findMin (root) 資料結構: binary search tree
單元測試: input 5; expected output 2 設計草圖: 5 3 6 2 4 虛擬碼 (演算法): 1.從 root 沿左邊走到底 2.return 該 entry的 element

103 例子 (Cont.) 三個方法開發findMin(): 找a,b,c等10000個 data elements 的最小值 1.資料結構如用array 則 findMin 演算法為: 令min為array第一個元素 for each array元素 if 它比min小 then 令min為它 end for 2.資料結構如用 heap 則 findMin 演算法更簡單: 3.如無資料結構,則無演算法: 令min為a if b比min小 then 令min為b if c比min小 then 令min為c 這要寫( )行程式 不可思議!

104

105 Design Sketch root subTree1 subTree2
The successor of Root is the smallest of sub-tree 2 (go left to the end) Root is the successor of the largest of sub-tree 1 (go right to the end)

106 Pseudo code protected Entry<E> successor (Entry<E> e)
1. if (e == null) return null; else if e 有 right child, 像 50 右下走一步 再往左下方走到底 else e 沒有 right child, 像 36 往左上方走到底 再右上走一步 2. return 找到的 entry end successor()

107 7. 演算法設計 (Cont.) 先上網找現成演算法,常可找到,可省下不少演算法設計時間
若從open source找到程式碼,那省下更多時間,如自行開發程式碼,因演算法常較差執行速度慢,且程式行數較多開發速度慢 因open source 通常他人用過,有bug會有人報告或訂正,通常不用做單元測試;但必要時,可把reused open source當unit,做 test code 英文要OK,才能讀清楚open source的標頭(當然有些寫不好),正確呼叫使用,並與全球同好討論

108 7. 演算法設計 (Cont.) 一般人從大一起就直接寫程式 跳過演算法設計 這已是根深蒂固的惡習 要改正 注意:
並非整個系統的演算法都設計好了 才寫程式 否則又陷入傳統 waterfall 模式了

109 Class Interface & Data Strucure
class Adjacency protected HashMap <Houses, LinkedList<NeighborDistances>> adjacencyMap; void showAllAdjacencies (Houses theHouse) void showNames (HouseList houseList) end Adjacency

110 演算法設計例子 public void showAllAdjacencies (Houses theHouse)
/* * showAllAdjacencies 顯示所有與 theHouse相鄰 (不見得有路) 的人名 * theHouse 某個人住的 house * Time estimate: O(n2) * 例: 若theHouse為小莉,相鄰的是 小華 阿偉(有路) 小明(沒有路) */ public void showAllAdjacencies (Houses theHouse) 1. 找從 theHouse 可到的 toHousesList 如小華 阿偉 O(n) 2.顯示 toHousesList showNames(toHousesList) 3. 找可到 theHouse 的 fromHousesList 例 小明 O(n2) 4. 顯示 fromHousesList showNames(fromHousesList) 110

111 演算法設計例子(Cont.) private void showNames (HouseList houseList)
/* * showNames 顯示 houseList 各人名 * houseList 例 小華 阿偉 * Time estimate: O(n) */ private void showNames (HouseList houseList) for i from 0 upto houseList的元素個數-1 顯示 houseList 第 i 個元素所含的人名 end for 111

112 8.補上程式碼 (Coding) 將虛擬碼改成註解 (加/* 及 */) 虛擬碼逐行補上對應之程式碼 儘量使程式碼隱蔽,不干擾虛擬碼之閱讀
(常見舊程式難讀、難維修,只好重寫) 本步驟虛擬碼針對 Java, C#,C 程式, 若用Ruby/PHP 程式本身即已易讀, 虛擬碼須寫得更高階

113 補上程式碼 例子 注意:要凸顯虛擬碼 隱藏程式碼 以利閱讀 虛擬碼程式碼分開亦可 清晰為先
/* * showNames 顯示 houseList 各人名 * houseList 例 小華 阿偉 * Time estimate: O(n) */ private void showNames (HouseList houseList) /*for i from 0 upto houseList 的元素個數 -1 */ for(i=0, i<=length(houseList-1), i++); /*顯示 houseList 第 i 個元素所含的人名*/println houseList(i).name); /*end for */ 注意:要凸顯虛擬碼 隱藏程式碼 以利閱讀 虛擬碼程式碼分開亦可 清晰為先

114 9.單元測試 (Unit testing) 待單元程式(unit, 如一個 Java public
method source code) 完成後, 用工具(如JUnit),自動執行 test code 測試該單元 (unit) 叫單元測試

115 單元測試 例子

116 10. 逆向工程 工具 利用逆向工程 工具 如 eUML,AgileJ
10. 逆向工程 工具 利用逆向工程 工具 如 eUML,AgileJ 需要時,可由程式碼(source file;不含 reused code) 動態產生 class diagram, sequence diagram 等設計圖文件,供了解軟體全貌、決定維修那個class 及 檢查相關classes (為了解軟體全貌,main program 之前也要有標頭:系統描述、重大決策) 這有可能敏捷達成 CMMI 一些 process areas 的 goals 從CRC工序後 即可隨時使用此工具產生設計圖

117 10. 逆向工程 工具 (Cont.) 一般人常直接 coding source code 這種 source code 輸入逆向工具後 產生的 class diagram 亂七八糟 慘不忍睹 反映出 軟體設計品質低落 的 真相 雖另有工整的 工具畫的 class diagram 但那與 source code 不符 造假的!

118 Class diagrams generated by tool

119 Sequence diagram generated by tool

120 myAgile 經驗談 陳教授研一學生試用myAgile 做小軟體, 覺得 CRC, test code, pseudo code 很費時,不甚敏捷。反之傳统直接coding 快多了 重點: 1) CRC 使test code可行,確保了品質 2) pseudo code 使變動的需求帶來的重構(refactor) 得以敏捷地做;而在變動需求下,CMMI 大量文件瞬間過時無用 3) 民主溝通費時但品質高;獨裁快速但危險

121 myAgile 經驗談 (Cont.) 有一雙人組 (pair) 在一齊維修時 先讀 header 再讀 pseudo code
了解後再修改 Java code 這樣只花 15 分 若直接修改 Java code 時間拉長不少

122 myAgile 經驗談 (Cont) 讀者投書: 一般行業精密分工,使員工專業,引進流程,重視紀律,以掌握品質,平行作業,以壓縮時程,何以為敏捷而反其道而行? 要員工會寫程式,會設計,會測試,要改他人程式,大家同室,同桌,同電腦 陳教授回覆: 上述行業是一般工廠式行業 流程固定,變化少,創意少 但是,軟體業不是工廠,所以是不同的

123 最後 簡單瀏覽 Grade System Project
謝謝大家!


Download ppt "跨校推動敏捷方法 促成軟體產業升級 中央大學資工系 陳振炎."

Similar presentations


Ads by Google