顯示具有 Software Engineering 標籤的文章。 顯示所有文章
顯示具有 Software Engineering 標籤的文章。 顯示所有文章

2016年5月29日 星期日

從定義看重構

2016/5/29 14:06~14:45


圖片取自 <泰迪軟體-軟體重構入門實作班>投影片

重構就是『在不改變程式外在行為的前提之下改變城市內部結構以提升設計品質』

Teddy從定義切入引伸出了六個議題:

1. 如何確認程式外在行為沒有被改變?


在正常的軟體開發過程中,通常會先規劃好設計規格(或類別),才開始動手寫程式,然後經過手動或自動化測試驗證功能是否符合規格。
程式會依時間或需求而變得越來越大坨,測試項目也會跟著越來越多,假設目前的程式已開發了100個功能,當你重構一小塊功能,通常要重新測試這100個功能,以確保自己修改的程式沒有問題。這時候如果沒有自動化測試的話通常開發人員也會開始不敢改程式,更別說整理程式碼了。

2. 如何定義哪些是外在行為?


一個使用者使用計算機類別的類別的public "add" 方法,對使用者來說,add的行為就是外在行為,計算機使用者來說是一個黑箱,我不知道它怎麼做,但我知道它會說。

3. 為什麼要以不改變程式外在行為當作前提?


這個問題很有趣,為什麼不能再新增功能的同時順便重構?
不知道你有沒有這樣的體驗,在新增功能的過程中,發現某一塊的程式碼寫了100行達成一個功能,但你發現其實寫10行就可以達到一樣的功能,所以你修改這一塊程式碼,改完之後才繼續做原本要新增的功能,好不容易把功能新增完,很興奮地按下"執行",再來你的情緒就跟著程式一起崩潰了,是剛剛重構錯誤,還是新增的功能錯誤?

4. 怎麼改變程式內部結構以提升品質?


藉由重構裡面所定義的壞味道與技巧,加上自己的反覆練行。想知道怎麼改可以讀Martin Flower的重構或者上泰迪軟體-軟體重構入門實作班。

5. 那些內部結構可以改?


以Java來說,程式碼的結構從小到依序為
變數(Variable) → 條件式(Statement) → 方法(Method) → 類別(Class) → 包裹 (Package)
重構裡面所談的重構技巧也是有結構上的差別,例如調整類別的繼承關係、改變方法的介面、將1個100行的方法切成5個20行的方法等等。

6. 品質提升的目的為何?


讓軟體變軟


Teddy總是能把死的定義講得很活真的有很猛

2015年7月12日 星期日

Martin Fowler整理的重構名錄

2015/7/2 20:34-21:20

前幾天終於把<重構>這本書讀完一次了,這本書有一半算是工具書,介紹非常多的重構手法,每個重構手法都以一個例子介紹,每個重構手法通常都可以找到它的情侶XD,原本正方形的東西不好看,所以凹成的長方形,凹長方形之後看起來有覺得怪怪的,於是又凹回了正方形。

在寫程式的時候,重構通常是為了讓程式碼更乾淨,但有時候還是會被"設計"綁住,對於還沒碰到的問題,有了過多的設計,也許在這個當下,你認為將來系統會遇到某些的擴充,所以你為了預防這個很久很久才會到來新需求或是非常偶爾才會出現的Special Case,開始重構程式,把原本功能簡單的程式碼切成很多Class去實作,以便以後可以應付這種Special Case。過了一段期間,才發現之前太杞人憂天了,很多預想的狀況根本都沒有發生,於是開始反重構,把很多冗員類別刪除。

這本書厲害的地方就在於每一個重構手法都以很小的步驟慢慢前進,在實際的工作中,可以先培養聞壞味道的能力,然後遇到某種壞味道的時候,在把這本書拿出來翻到最後一頁,參考下面的兩張表格,找出能解決這個壞味道的重構手法。


擷自<重構>最後一頁


擷自<重構>最後一頁

---



最近感冒,一直覺得頭好暈阿,差點兒沒發網誌。

讀完中文版的第一次,再去借了一本英文版,即使看過一次中文版的,英文版的讀起來還是頗硬阿!

先把一本原文書重頭到尾讀三次→Teddy Chen教我的那些事

2015年7月4日 星期六

程式碼的壞味道(3)

2015/7/3 21:58-22:44


上兩篇節錄了16個在重構中所提到的壞味道,
<程式碼的壞味道(1)>
<程式碼的壞味道(2)>

剩下6個壞味道,今天終於要把它們全部抄完節錄了


---

17. Inappropriate Intimacy (狎暱關係)

有時你會看到兩個classes過於親密,花費太多時間去探究彼此的private成分。如果這發生在兩個「人」之間,我們不必作衛道之士;但對於classes,我們希望他們嚴守清規。


18. Alternative Classes with Different Interfaces (異曲同工的類別)

兩個函式做同一件事,卻有著不同的署名式(signature)。


19.Incomplete Library Class (不完美的程式庫類別)

復用(reuse)常被視為物件的終極目的。我們認為這實在是過度估計了(我們只是使用而已)。但無可否認,許多編程技術都建立在library classes的基礎之上,沒人敢說是不是我們都把排序演算法忘得一乾二淨了。Library classes構築者沒有未卜先知的能力,我們不能因此責怪他們。畢竟我們自己也幾乎總是在系統快要構築完成的時候才能弄清楚它的設計所以library構築者的任務真的很艱鉅。麻煩的是library的形式(form)往往不夠好,往往不可能讓我們修改其中的classes使它完成我們希望完成的工作。


20. Data Class (純稚的資料類別)

所謂Data Class是指:它們擁有一些欄位(fields),以及用於存取(讀寫)這些欄位的函式,除此之外一無長處。這樣的classes只是一種「不會說話的資料容器」,它們幾乎一定被其他classes過分細瑣地操控著。


21.Refused Bequest (被拒絕的遺贈)

subclasses應該繼承superclass的函式和資料。但如果它們不想或不需要繼承,又該怎麼辦呢?它們得到所有的禮物,卻只從中挑選幾樣來玩!


22.Comments (過多的註釋)

從嗅覺上來說,Comments不是一種壞味道:事實上它們還是一種香味呢。我們之所以要在這裡提到Comments,因為人們常把它們當作除臭劑來使用。常常會有這樣的情況:你看到一段程式碼有著常常的註釋,然後發現,這些註釋之所以存在是因為程式碼很糟糕。這種情況的發生次數之多,實在令人吃驚。
Comments可以帶我們找到本章先前提到的各種壞味道。找到壞味道之後,我們首先應該以各種重構手法把壞味道去除。完成之後我們常常會發現:註釋已經變得多餘了,因為程式碼已經清楚說明了一切。

『當你感覺需要撰寫註釋,請先嘗試重構,試著讓所有註釋都變得多餘。』


如果你不知道該做什麼,這才是註釋的良好運用時機。除了用來記述將來的打算之外,註釋還可以用來你並無十足把握的區域。你可以在註釋裡寫下自己「為什麼做某某事」。這類資訊可以幫助將來的修改者,尤其是那些健忘的傢伙。


---

書中的這個章節,我覺得是全書最精華的地方,之前翻了一點<深入淺出程式設計>,雖然有認識到一些Pattern,但是一直無法找到應用某個Pattern的時機。

就在今天利用Extract Super Class重構的時候,突然發現重構完的地方可以套用Command Pattern,突然有一種串起來的感覺,頗有成就感XD。



每個軟體工程師都應該來讀一下重構這本書。

2015年6月27日 星期六

程式碼的壞味道(2)

2015/06/27 22:29-23:37

今天延續上一篇的壞味道繼續節錄XD


9. Primitive Obsession (基本型別偏執)


大多數的編程環境都有兩種資料:結構型別(record types)允許你將資料組織成有意義的形式;基本型態(primitive types)則是構成結構型別的積木塊。結構總是會帶來一定的額外開銷。一般程式語言中物件技術的新手通常不願意在小任務上運用小物件。


10. Switch Statements (switch驚悚現身)

物件導向程式的一個最明顯特徵就是:少用switch(或case)述句。從本質上說,switch述句的問題在於重複(duplication)。你常會發現同樣的switch述句散佈於不同地點。如果要為它添加一個新的case子句,你必須找到所有switch述句並修改它們。


11. Parallel Inheritance Hierarchies (平行繼承體系)

在這種情況下,每當你為一個class新增一個subclass,必須也為另一個class相應增加一個subclass。如果你發現某個繼承體系的class名稱字首和另一個繼承體系的class名稱字首完全相同,便是聞到了這種壞味道。


12. Lazy Class (冗員類別)

你所創建的每一個class,都得有人去理解它、維護它,這些工作都要花錢的。如果一個class的所得不值其身價,它就應該消失。


13. Speculative Generality (夸夸其談未來性)

當有人說『噢,我想我們總有一天需要做這種事』並因而企圖以各式各樣的掛勾(hooks)和特殊情況來處理一些非必要的事情,這種壞味道就出現了。那麼做的結果往往造成系統更難理解和維護。如果所有裝置都會被用到,那就值得這麼做;如果用不到,就不值得。用不上的裝置只會擋你的路,所以,把它移開吧。


14. Temporary Field (令人迷惑的暫存欄位)

有時你會看到這樣的物件:其內某個instance變數僅為某種特定情勢而定。這樣的程式碼讓人不易理解,因為你通常認為物件在所有時候都需要它的所有變數。在變數未被使用的情況下猜測當初其設置的目的,會讓你發瘋。


15. Message Chains (過度耦合的訊息鏈)

如果你看到用戶向一個物件索求(request)另一個物件,然後再向後者索求另一個物件,然後再索求另一個物件…這就是Message Chain。程式碼中你看到的可能是一長串的getThis()或一長串暫存變數。採取這種方式,意味客戶將與搜尋過程中的航行結構(structure of navigation)緊密耦合。一旦物件間的關係發生變化,客戶端就不得不作出相應修改。


16. Middle Man (中間轉手人)


物件的基本特徵之一就是封裝(encapsulation)-對外部世界隱藏其內部細節。封裝往往伴隨著委託(delegation)。比如說你問主管是否有時間參加一個會議,他就把這個訊息委託給他的記事簿,然後才回答你。很好,你沒必要知道這位主管到底使用傳統記事簿抑或秘書來記錄自己的約會。但是人們可能過度運用delegation。你也許會看到某個class介面有一半的函式都委託給其他class,這樣就是過度運用。這時應該直接和實責物件打交道。


原來switch這麼驚悚,我卻不知不覺跟它相處了這麼多年...

2015年6月20日 星期六

程式碼的壞味道(1)

2015/06/20 21:07-22:38

今天來節錄<<重構-改善既有程式的設計>>書中提到的程式碼壞味道。


  1. Duplicated Code (重複的程式碼)
  2. Long Method (過長函式)
  3. Large Class (過大類別)
  4. Long Parameters List (過長參數列)
  5. Divergent Change (發散式變化)
  6. Shotgun Surgery (霰彈式修改)
  7. Feature Envy (依戀情節)
  8. Data Clumps (資料泥團)
  9. Primitive Obsession (基本型別偏執)
  10. Switch Statements (switch驚悚現身)
  11. Parallel Inheritance Hierarchies (平行繼承體系)
  12. Lazy Class (冗員類別)
  13. Speculative Generality (夸夸其談未來性)
  14. Temporary Field (令人迷惑的暫存欄位)
  15. Message Chains (過度耦合的訊息鏈)
  16. Middle Man (中間轉手人)
  17. Inappropriate Intimacy (狎暱關係)
  18. Alternative Classes with Different Interfaces (異曲同工的類別)
  19. Incomplete Library Class (不完美的程式庫類別)
  20. Data Class (純稚的資料類別)
  21. Refused Bequest (被拒絕的遺贈)
  22. Comments (過多的註釋)

首先簡單節錄前八個壞味道:

1.     Duplicated Code (重複的程式碼)
最單純的情況就是同一個類別(Class)內的兩個函式函有相同的實作內容

2.     Long Method (過長函式)
不熟悉物件導向的人,常常覺得物件程式中只有無窮無盡的委託(delegation),根本沒有進行任何計算。和此類程式共同生活數年之後,你才會發現這些小小函式有多大的價值。解釋能力、共享能力、選擇能力都是由小型函式支援的。

3.     Large Class (過大類別)
想利用單一類別(Class)做太多事情,其內往往就會出現太多instance變數。一旦如此,Duplicated Code也就解踵而至了。

4.     Long Parameters List (過長參數列)
以前學C語言,老師教我們:把函式所需的所有東西都以參數傳遞進去。這可以理解,因為除此之外就只能選擇全域資料,而全域資料是邪惡的東西。有了物件,你只需傳給它足夠的東西,讓函式從中獲得自己所需要的所有東西就行了。

5.     Divergent Change (發散式變化)
一旦需要修改,我們希望能夠跳到系統的某一點,只在該處作修改。如果不能做到這點,你就嗅出兩種緊密相關的刺鼻味道中的一種了。
如果某個class經常因為不同的原因在不同的方向上發生變化,Divergent Change這個壞味道就出現了。例如:當你看著一個class說:『呃,如果加入一個資料庫,我必須修改這三個函式;如果新出現一種金融工具,我必須修改這四個函式』。

6.     Shotgun Surgery (霰彈式修改)
類似Divergent Chane,但恰恰相反。Divergent Change是指「一個class受多種變化的影響」,Shotgun Surgery則是指「一種變化引發多個classes相應修改」。

7.     Feature Envy (依戀情節)
我們看到某個函式為了計算某個值,從另一個物件那兒呼叫幾呼半打的取值函式(getting method)。

8.     Data Clumps (資料泥團)

兩個classes內的相同欄位(field)、許多函式署名式(signature)中的相同參數。


---


本來要去圖書館拿有關UML的書,看到這本書在書架上發光就索性帶回家。
借回來五天,利用交通和空閒時間看,已經讀了140頁。

如果已經碰過程式有幾年經驗,這本書應該能講到你的心坎裡。但是如果你是學程式初學者應該會看得"霧颯颯"。


先聞出壞味道會比較清楚重構的時機

2015年6月13日 星期六

Scrum的意義

2015/06/13 19:16-19:57



圖片來源在此


Scrum是軟體敏捷開發法中的其中一個方法,這個字在橄欖球之中,是爭球的意思,翻成中文有個更貼切的名詞「鬥牛」。

在美式足球的活動裡,同一個隊伍裡面的人目標都必須一致 ---「爭球」,橄欖球彈跳的方向通常很難預測,隱喻在軟體開發的活動中,顧客的需求通常也很難在專案初期就規畫得很完整,需求改變就如同橄欖球的彈跳班難以預測。

在Scrum裡的所有活動,都有規範一個固定長短的時間,時間到活動就應該立即結束,猶如橄欖球比賽,假設比賽結束的那一瞬間,隊伍A 53分,隊伍B 55分,那就是隊伍B獲勝,

隊伍A總不可能說:「再給我五分鐘我就可以把球放進得分區!」←開發軟體的時候,每當死線逼近,我好像都會這樣說XDD

這星期的軟體生命週期,Teddy把Scrum重新拿起來介紹了一番,

Teddy:「Scrum有哪些地方還沒講過的?」

班上同學們:「這學期到現在還沒有介紹過Scrum是什麼,只有看過一個15分鐘的短片」

Teddy:「蝦米!?這學期都沒有講過Scrum。所以你們也不知道整個學期在做什麼,這就代表不用懂Scrum也可以玩得很好。」

Scrum有股神奇的魔力,只要按照它的遊戲規則走,就能暴露出問題所在,所以它又有「照妖鏡」的美名。


情境模擬:

你是Scrum Master,正在一家公司導入Scrum,團隊的開發人員們每天都加班到半夜12點,他們開始抱怨Scrum害他們加班,因此認為Scrum是個爛東西,你是Scrum Master,遇到這種情況,你會怎麼辦?

霸氣回應:「你們加班,就是在隱藏問題!!!」

謎之聲:「其實加班.....是為了解決問題」




Scrum讓我知道原來還有這麼多的問題在等著我要去解決。只有更好,沒有最好

2015年5月16日 星期六

軟體工程中的MVP



2015/5/16 21:18-21:54

又到了一週一度的發網誌時間,沒想到最近流行的感冒毫無預警地降臨在我身上,乖乖的把醫生的藥都吃完了身體還是不給面子,其實想繼續睡連網誌打懶得打了XD

在北科大的軟體生命週期期中考,考了一題"什麼是Minimum Viable Product?",在考前我是有上Wiki隨便看了下它的定義,看完之後印象也沒有很深,就字面上的意思"最小可行性產品"解釋,就是----UI做得不用做得太漂亮,東西能動比較重要。然後再衍伸一下,就變成以最小成本驗證產品所帶來的價值。

但是這題我只對了一半XD。

MVP大師云:「通常在開始做一個產品之前,都會有一個願景,假設這個產品會帶來某種很大很大的價值,在真正製作軟體的過程中,隨著每次的產出,驗證它是不是真的和之前的假設一樣帶來很大很大的價值,就像做實驗一樣,一直循環著學習→產出→驗證。」


要一直循環到什麼時候呢?我想到兩個答案:

1. 把公司錢燒光的時候

2. 驗證價值的結果差到不能在差 (這時候就該轉換跑道了,再ㄍㄧㄥ下去傷錢又傷肝)



突然發現以後用Google查觀念時,用圖片查詢的結果比較容易消化

2015年5月2日 星期六

Scrum初體驗(6) - 守住最後防線

2015/5/1 8:44-9:01
在上一集中,提到我們在Sprint中修改Story,我一直覺得怪怪的。
因為在Scrum中,不建議我們在Sprint中插入緊急的工作,所以我像得了強迫症似的強力反對團隊這樣做。
忍了一個星期之後,終於有機會見道到Scrum大師解惑。
我: 「Scrum大師,我的團隊有罪。我團隊擅自在Sprint中修改Story。我知道Scrum中建議我們不要這麼做,團隊都還沒完全了解Scrum就擅自靈活地變化。是不是應該要求團隊先全面了解Scrum之後,再開始靈活變化會比較好呢?」
Scrum大師 : 「你覺得團隊什麼時候才能完全了解Scrum?」
我 : 「不知道...」
Scrum大師 : 「在Sprint中,當然可以修改Story,這樣的情況發生少數幾次是正常的,但是如果每個Sprint都有這種情況出現,那就要看看是哪裡出了問題。」
原來走我火入魔的是我

2015年4月25日 星期六

Scrum初體驗(5) - 在Sprint進行中重新安排Story

2015/4/18 16:04-16:24

我們團隊進行Sprint Planning Meeting時,挑選的Story已經經過優先權排序,挑選團隊所認為最重要的Story先做。

你猜猜,我們第一個完成的Story是什麼?

沒錯,就是大家開始使用大部分個人化App都會有的功能『登入』

Story會依對客戶的價值,經過排序後擺進Product Backlog,再經由Sprint Planning Meeting這個活動,挑選這個Sprint中所要完成的Story,所以我們團隊認為對客戶最重要的價值是『登入』!?

團隊在一開始已大致了解Scrum的進行方式,但是一個不小心,又掉入流程價值的陷阱,團隊是這樣想的「沒有登入,要怎麼繼續後面的功能?」

流程價值的意思大概是這樣:
在專案還未進行之前,團隊會大致決定App服務的流程,一般都會依流程畫面的先後順序,決定要施工的項目,先出現的流程,就須先實作。

到今天Sprint已經過了四分之三,Scrum大師突襲檢查,反問了我們:「難到系統不登入,就沒辦法體驗你們的App嗎?」

於是團隊驚覺之前的Story排序有錯,這個Sprint的Story應該要重新排序,所以我們利用Daily Scrum的時間重新排序了Story的優先順序,將不重要的Story從Sprint Backlog丟回Product Backlog,新選進來的Story,依照Sprint Planning Meeting的流程一樣,切Task然後估點。

雖然在真的這樣做之前我反對團隊這麼做,但我無法說服團隊不這麼做,其實我也不知道哪裡不好,還沒守住Scrum就先擅自靈活用運Scrum,總覺得怪怪的。

到底哪裡怪?還須請Scrum Master大師指點

Scrum只是一種流程框架,可依團隊狀況自行調整,調整不好就容易走火入魔


2015年4月18日 星期六

Scrum初體驗(4) - Scrum Master 存在的地目

2015/4/18 15:18-15:36


我:「身為Scrum Master,初到一個公司導入敏捷開發的時候,一定會遇到有一種團隊,不知道自動化測試、持續整合、單元測試、版控系統等等等等等,從一個千錘百鍊的Scrum Master眼中,一定會覺得這種開發團隊似乎沒救了,但是又不可能一次把這些知識全部塞給開發團隊,那Scrum Master到底要怎麼抓對時機給開發團隊需要的知識呢?」

Scrum大師:「就像老師帶幼稚園小朋友一樣,幼稚園小朋友不會數學、不會英文、不會國文,你也不可能請數學家教、英文家教幫小朋友惡補,如果真的這樣做了,小朋友一定會被壓垮,當Scrum Master最難的地方,就在於要有耐心,你的主觀上,雖然一下就能看出開發團隊不足的地方,但又不能一次性修正所有的不足,在適當的時候提出一點點的不足,Scrum Master雖是一個觀察者,看似什麼事情都不用做,其實在內心卻要擺番地掙扎,選擇適當的時機一點一點地透過團隊自己發覺這些不足,且引導他們能一點一點地自動克服這些不足。對團隊來說,他們的產品是客戶;對Scrum Master來說,他們的產品是團隊,直到團隊成員能達到自我管理,那Scrum Master有能功臣身退了。有一句話說得很棒:『Scrum Master存在的目的,就是為了消滅自身的存在』」

我:「我懂了,謝謝Scrum大師」

---

雖然我還是不知道什麼時機該向團隊提出缺點,但在Scrum大師的回答中,提醒了自己要有耐心、有耐心、有耐心,因為很重要所以打三遍。


Scrum Master存在的目的,就是為了消滅自身的存在

2015年4月11日 星期六

Scrum初體驗(3) - Scrum Master 出現的時機

2015/04/11 21:31-20:03

最近打網誌的習慣快要蒸發了,非得要拖到星期六快結束才開始打網誌,當初開始發網誌的時候給了自己小小的目標「每個星期六要發一篇網誌」,持續到現在也有23週。

剛開始寫網誌時,想要試著分享自己在身活中所遇到的趣事,每個星期還沒到星期六前就能產出一篇網誌,那時候的心態是「為了分享而寫網誌」,可是現在好像是「為了寫網誌而寫網誌」。現在這個Form好像不太Fitness,該來找找Force後,換個Form再來!!發牢騷到這邊,以下開始進入正題...

在我們修課而組成的Scrum中,Scrum Master很幸運地由我來擔任,但很不幸地我也是開發人員,一不小心就會身分錯亂,平常也可能是當開發者當習慣了,也不知道Scrum Master會有什麼不一樣,目前跟著課程進度,開始了我們的第一個Sprint,這個Sprint開始到今天已經過了8天,我這個不專業Scrum Master的角色觀察到一些現象。

1. Daily Scrum雖然已經訂下時間,但是開發人員(包括我),常常因為突發的重要事情,必須取消當次的Daily Scrum或頻頻改時間。

2. 因平常沒有相約一起專案的時間,雖然在Sprint Planning Meeting的時候,假設每個人每天會花1小時的時間在Sprint上,但我自己好像就沒有做到這點(忘了我也是開發人員Orz)。

3. 平常身在不同實驗室,因大家工作時間都不一樣,有時候開發遇到問題,就稍微怠惰,放著不管等著有緣份的下一次見面

4. 在Scrum的框架中,最後有一個回顧會議(Retrospective),主要是用來讓團隊成員們提出這個Sprint中好的部分和可以更好的部分,但從Sprint開始到現在,就有好多部分想要修正,能不能等到Sprint還沒結束就提出來呢? (我是真的不知道XD)

之前基於對Scrum的好奇,有稍稍和某Scrum專業人士討論,他說:「通常在團隊剛開始使用Scrum的時候,都會發現產能反而比採用之前的方式還要低,所以大家在跑完第一個Sprint之後就被打回原形」。

我自己對於Scrum Master角色定位,覺得他是個默默的觀察者,這個觀察者盡量不要輕易地干涉開發人員現在做事的方式,等觀察一段時間後,再出現提醒或糾正。可是哩,我這個不專業觀察者一不小心就會把自己的主觀感受帶入。可能是因為完全不知道Scrum Master到底要幹嘛。

如果團隊已經遵守Scrum框架,那要Scrum Master來做什麼?


2015年4月4日 星期六

Scrum初體驗(2) - 這個Sprint要選幾個Story

2015/4/4 16:43-17:04

相信各位有試過Scrum的鄉民們,在開始人生中第一次的Sprint Planning Meeting時,一定都會有一個很大很大的問號:「Story點數都估完了,我怎麼知道這個Sprint要選幾個Story?」

這週四在軟體生命週期的課堂上,終於把這個積了一星期之久的問號丟給Teddy



Brian:「我怎麼知道這個Sprint要選幾個Story?」

Teddy反問:「為什麼要估算?」

同學A:「(%$(&^@($%)#@$&!#$^!@#%!@#$」

同學B:「根據上一次的Sprint經驗,決定這次要選幾個Stroy」

同學C:「藉由估算,可以看出每個團隊成員是否都了解這個Stroy的需求」

聽到同學C的答案,才回憶起上一次上課的時候我明明才在筆記本抄了幾個字
<估牌是為了讓PO知道團隊成員是不是對這個Story的認知一致>,可能是因為寫的字太小,讓我完全忘記它的存在,瞬間有一種被打醒的感覺。

Teddy在後面補上比較有漂亮的講法:「估算,是為了讓團隊成員了解這個Stroy的Boundry。」


接著再加碼介紹兩個選Story到這個Sprint方法:


1. Velocity base
依據團隊的產能挑選Stroy的數量。

2. Commitent based
一次挑一個Stroy,直到團隊認為無法再挑更多的Stroy加入這次Sprint。




在估算中學習,而不是學習該怎麼估算

2015年3月28日 星期六

Scrum初體驗(1) - Sprint Planing Meeting

2015/3/28 20:08-20:28

我們的Scrum Team共有六個人,
一個Product Owner、一個不懂Scrum的Scrum Master兼Developer、其餘4位都是Developer,在Spint Planning Meeting中有遇到2個問題:

1. Story在估點數的時候,如果每個人點數差異性一直過大,該怎麼辦?

2. PO怎麼知道這個Sprint要拿幾個Story


目前使用的估點數方法:

我們最後所採用的方法,首先看大家所估的點數是不是差不多,只要有一個人出的點數過大,會請他說明原因,再由PO或點數出很低的人解釋Story達成的複雜度,通常解釋完之後,第二回合點數的差異性會變低,但是我們最後估出來的點數是採用多數所出的點數,而不是全部點數加起來平均,剛開始還不覺得奇怪,但估到後面發現大家點數不一定會一樣,多少都會有差異,但目前還是遵照一開始的方法將Story估完,待下一個Sprint再改進。


目前估算這個Sprint要做幾個Story的方法:

第二個問題,點數估完了,開發人員將Story切成若干個Task,將每個Task估算時間。
我們團隊共有五位開發人員,這個Sprint共有三週,假設每個人每天工作一小時,所以一個Sprint,共有
5(人) * 1(小時) * 5(天) * 3(週) = 75 小時

這個Sprint就選入75小時的Story量。


整個Meeting耗時3小時,中間休息十分鐘,以Team的角度來看,發現要完成每個功能很簡單,跟著一群神一般的隊友。


結果會如何呢?讓我們繼續看下去

2015年1月31日 星期六

程式的強健度等級

2015/1/31 20:23-21:22

今天來講一下程式的強健度等級,強健等級分為四級,分別為等級零、等級一、等級二、等級三,共四個等級。





等級零 (G0):
沒有任何例外處理,一般工程師在時間緊迫的情況下,只會實作正常流程,毫無考慮及處理異常流程,當異常流程發生時運氣好則程式崩潰,工程師可直接複製情境解決問題,運氣不好不知道怎麼複製情境,也就只能燒香拜拜,祈禱它下次不要再出現。

等級一 (G1):
異常發生就須通報使用者且終止程式。問題發現的越快也就能修正的越快。

等級二 (G2):
假設現在有個函式無法達成所規範的規格,就必須把狀態回復到還沒執行這個函式的正常狀態。

等級三 (G3):
是個使命必達的FU。達成目的的方法有很多路徑,執行一個路徑失敗,就換成另一種路徑試試看;或者一直重試,試到規範的次數,如果還是失敗才不得放棄。



強健度等級是個逐步升級的過程,如果升級不成,就只能降級處理啦!原本強健度等級3的如果無法使命必達,只好採取等級2的策略,將狀態恢復到還沒執行函式的正常狀態,降等級2不成就只好繼續往等級1降,將異常回報給使用者且終止程式。


以上圖片擷取自



更精采的內容請參考Teddy的博士論文<<Exception Handling Refactorings: Directed by Goals and Driven by Bug Fixing>>,如果不想看英文版也沒關係,還有特別整理過的中文版<<例外處理設計的逆襲>>


原來例外處理還有這麼深的學問啊!

2015年1月17日 星期六

練習程式的道場-Coding Dojo

2015/1/17
15:31-15:39, 8 minutes
18:51-19:13, 22 minutes
19:15-19:22, 7 minutes
20:13-20:47, 34 minutes

Dojo從日文翻譯而來,是道場的意思,Coding Dojo的活動,由Dave Thomas最先提出。

Dave Thomas 說:「In software we do our practicing on the job, and that's why we make mistakes on the job. We need to find ways of splitting the practice from the profession. We need practice sessions.」

中文意思:「我們都在工作的時候練習軟體,這就是我們為什麼在工作犯錯的原因,我們需要找到把練習環境和工作環境切開的方法,我們需要一個練習軟體的會議。」

Coding Dojo有一個wiki網站在這裡,裡面有介紹舉辦Coding Dojo須注意的事項,在Coding Dojo之中依活動的流程分成兩種Kata(Kata也是日文,是『形』或『套路』的意思,就像練習功夫的人,有詠春拳或螳螂拳,每一種拳法,都可以算是一種Kata):

***

1. Prepared Kata

準備式套路,指說一個人已經準備好問題和答案,在活動進行中,要讓在場的觀眾體驗解決問題的過程,報告者解題的每個步驟要非常小(Baby Steps),如果觀眾對於正在進行的步驟有疑問,可以馬上中斷台上的報告者,報告者講解清楚後,才能繼續下一個解題步驟。

要注意的是,在活動進行時,觀眾所提出的問題,不能與報告者所進行的步驟無關,舉例來說,觀眾不得要求重構某項功能,這些與功能性無關的要求只有在報告者帶完整個活動後,才可以提出。

2. Rendori Kata

亂鬥式套路,不用做任何的事前準備,只須將所要練習的問題帶來,活動開始的時候,會有一個主駕駛和副駕駛,一次只有兩個人在寫程式(Pair-Programming),每一組限制一段時間(Time-boxing),當限制時間到了,主駕駛回觀眾席,一個觀眾變成副駕駛,台上的副駕駛變成主駕駛,開始計時,時間到了之後,繼續換位,現場全部的觀眾的輪過一次駕駛和副駕駛時,活動才算結束,台上的人也要遵循Babay Steps,把自己的每一步,盡量表達給台下的觀眾知道。
活動過程中,觀眾只有在台上寫程式的人達綠條(Green bar)的時候才能提出問題或提供更好的建議,如果台上寫程式者遇到紅條(Red bar),觀眾就不能提問,因為台上的人必須要專注排除問題。
但因為大家都是臨時Coding,多少都會產生一種競爭的心態,想要在自己寫程式的回合中產生出最多且功能正確的程式碼,或者是時間到了還賴著不走,這時候叫就靠帶活動的人維持秩序啦!

***

其實在帶Coding Dojo活動的時候,大部分的人都容易犯一個錯誤,就是帶活動的人想要讓活動都在預期的時間結束,而在這預期的時間之中,會先事先做好一些準備,在活動開始的時候,希望把所準備的東西全部表達出來,但往往會無法預測台下會提出怎樣的問題。
要切記,Dojo活動志不在呈現結果或完成任務,活動的初衷是希望創造一個練習Coding的環境,大家可以在活動過程中彼此學習到Coding的技巧,寧願活動前進步驟緩慢,也不要因為想把活動帶完而跳步驟,即使當次活動沒有完成任務也沒有關係。

目前在網路上,可以找到許多的Kata題目,只要照著他們的步驟完成程式,就能學到不少東西哦!

這是一個保齡球遊戲,網站有PPT供下載,遊戲很簡單,只須按照PPT描述的步驟就能完成任務,大家可以來玩玩看。



與你分享的快樂勝過獨自擁有→愛唱歌的人都知道的那些事

2015年1月10日 星期六

Java中的Checked Exception與Unchecked Exception

2015/1/10 13:31-15:19

在這個星期,終於完完整整地將Teddy的<例外處理設計的逆襲>讀完一遍,在最後面有一個附錄叫做視力測驗,這個章節是測試自己對於書中介紹的還記得多少,全部共20題,答對其中14題以上才算及格,如果低於14題,Teddy建議讀者要再閱讀幾遍,作答過程中自己都很有把握,最後竟然才剛好對14題,差一點點就要不及格,突然回想到自己國中國小考選擇題的時候,常常把題目『下列何者錯誤』的題型看成『下列何整正確』,不是不會只是題目不小心看錯啦XD(給自己的小小藉口)。

這次稍微介紹一下Unchecked Exception和Checked Exception

在Java程式語言的例外處理中,依編譯器檢查程式碼的的觀點,分為兩類
1. 受檢例外 (Checked Exception)
2. 非受檢例外 (Unchecked Exception)


Checked Exception代表在程式編譯的期間,編譯器如果發現開發者沒有處理Checked Exception的話,它會把這個情況視為錯誤,強制開發者修正後,才能成功編譯程式。

相反地,如果例外是屬於Unchecked Excpetion,使用者不須多加處理,程式就可以通過編譯器的檢查。

在Java程式語言中,所有的例外都繼承自Throwable類別,繼承關係如下圖:




在上圖中,Throwable、Exception、IOException和SQLException屬於Checked Exception;
Error、RuntimeException、IndexOutOfException和NullPointerException屬於Unchecked Exception。



現在舉例讓各位體驗一下在撰寫Java時,遇到Unchecked Exception和Checked Exception的情況,我使用的IDE為Eclipse。

圖1 編譯器提示錯誤

圖1中,我在主程式main中呼叫了testCheckedException,它會丟出IOException,IOException屬於Checked Exception,編譯器在第11行出現一個錯誤,提示我必須在main的介面上宣告或捕捉IOException,才能通過編譯器的檢查。

圖2 將例外宣告至函數介面上

圖2將IOException宣告在介面上的程式碼,此程式通過編譯器的檢查,這個例外最後會由捕捉它的人處理,也就是呼叫main的函數處理,或者呼叫main的函數可以繼續往外丟。在這個例子裡,誰會呼叫main呢?答案就是處理Java Process的Java Virtual Machine(JVM),JVM捕捉到例外之後,會將例外印在Console視窗接著把程式中止。

執行程式的結果如圖3


圖3 JVM收到例外


現在將圖1的程式,改為捕捉IOException,使用Eclipse自動修正後程式碼如圖4。


圖4 捕捉IOException且印出該例外的詳細資訊


圖4中的第14行程式碼會印出例外的詳細訊息,結果如圖5。


圖5 執行e.printStackTrace()在Console會印出例外的詳細訊息



以前剛寫Java的時候,以為程式只要發生例外,就算有捕捉(catch),程式跑完catch區塊的程式碼還是會中止,但事實不是這樣的,執行完catch區塊的程式碼後,程式還是會繼續執行下去,看以下的例子。

把圖4中的程式碼稍作修改,執行並觀察其輸出狀況如圖7。

圖6

圖7


由圖7的輸出結果可以觀察出程式執行的狀況,當程式執行到第13行時,發生IOException,程式碼直接跳到第16行執行catch區塊的程式碼,接著繼續往下執行到程式碼第20行。



接著我們繼續測試Unchecked Excpetion。


圖8

在圖8中,main呼叫了testUncheckedException(),此函數會丟出RuntimeException,它屬於Unchecked Exception,此程式直接通過編譯器的檢查。

當程式執行到第9行,main丟出例外給JVM,JVM會將例外資訊印出且中止程式。執行結果如下圖9。



圖9



以上就是今天的介紹,下回見。


我的例外處理層次好像多了一層


2014年12月27日 星期六

踏入Design Pattern的大門 〈2〉- 獨一無二的物件

2014/12/27 16:49-18:26

在經過C語言的長年洗禮後,前兩年因為開發Android的關係轉戰Java,剛開始寫Java時,自己還是用C語言的觀念去設計程式,在設計的時候常常會碰到一個麻煩的疑問:我的全域變數到底要放在哪裡?最後就創一個類別名叫Global,然後宣告成static method或static variable,透過呼叫靜態函式去使用全域變數,後來才明白,在物件導向的程式語言中,是沒有所謂的全域變數的,程式設計師必須先找到類別,再往下找該類別是否提供所需要的功能。


而在C語言的全域變數得概念,可以映射到一個設計模式(Design Pattern)中的獨體模式(Singleton Pattern),獨體模式顧名思義就是確保一個類別只有一個實體,而大家可以透過獨體類別的方法(Method)取得該類別的實體,使用此類別的人,無法使用new的方式自己產生實體。

先來看看獨體模式的類別圖:

圖1 取自 <<深入淺出設計模式>>


再來把類別圖實作一下:

圖2

其中第5~7行,是為了讓使用Singleton類別的人,不能用new的方式取得實例,如果要使用Singleton類別,須透過getInstance去取得實例。

第10行做了uniqueInstance的判斷,如果已經產生過實例,就把之前產生的實例直接回傳出去。


使用Singleton的程式碼如下:

圖3


這樣的設計在書中還討論到一個問題,在多線程的環境下,多個線程競爭,有兩個以上的線程同時執行圖2中的11行,使得有Singleton產生兩個實例,而線程中的操作其實是反映在不同的實例上。

在書中有提出三個解決方法:

1. 將getInstance()加上同步鎖(synchronized)

這樣做有個缺點,當getInstance被很多線程使用時,線程必須彼此等待,拖慢各自線程的執行速度。


2. 率先建立實體

在宣告uniqueInstance的同時,直接new出一個實例,但是這種方法在編譯時期就會產生實例,如果整個執行期沒有使用到此類別,就會造成不必要的記憶體浪費。

3. 利用『雙重檢查上鎖』

將getInstance中的程式碼稍作修改:



只有第一次執行的時候,才會因為同步鎖而拖慢速度,當uniqueInstance已經被建立實例後,就不會執行12-16行的程式碼。
在程式碼第4行的地方,出現volatile,我個人認為不寫volatile也可以達到一樣的效果。

書中有提到方法3只適用於Java 1.5以上的版本(含Java 1.5)。


獨體模式與一般直接使用static method的設計方法,好處在於獨體模式只有在用到的時候,才會產生實例,如果當我們的程式從頭到尾完全沒有使用到該獨體類別,就不會產生記憶體,這種特性稱為推延實體化,也就是當第一次使用的時候,才會產生實例占用記憶體空間,而static method的作法,是在編譯期就產生的實例,一執行程式就會占用記憶體。

其實在學Design Pattern之前,已經知道有這種撰寫法,學了之後才知道原來這種方法有個獨體模式的名稱。

在設計軟體的時候,難的不是叫人把功能做出來,有時候想要請分工的開發人員按照某種設計方法去撰寫程式,卻不知道要怎麼把想法表達給對方懂,或是已經照著自己的方法盡力詮釋之後,對方還是完全聽不懂,學了Design Pattern,讓程式設計師彼此有共通詞彙,在表達上可以更快速抓到對方所要的設計方式。


學過不代表已經了解,多看幾次有益無害→之前就知道Singleton的我學到的那些事