2015-05-18

[心得文] 自動測試與TDD實務開發 Day1

[前情提要]
其實半年前我就想報名這堂課,不過可惜最後因為幾個負面思考而打消了念頭,當時在心中埋下了一顆悔恨的種子,告訴自己說,下次再有這個機會請不要錯過。
終於,今年盼到了第三梯的課程,雖然價格提高了4 =.= ,不過還是自己能夠負擔的範圍啦,當然就報囉。
剛好今年也給了自己一些明確的目標:
1.     2015Q4 要在公司教授Unit Testing的課程:
為了要教別人,所以先來觀摩大神91哥是怎麼教學員的XD
果然Lab中的幾個例子都很務實,也給了我一些方向。
2.     Team導入完整的Continuous Delivery Solution
為了使CD更完整,Unit Testing就不能缺席,我一定會建置出一個方便的Solution讓同事們能夠無痛升級。

於是呢,獲得老婆的諒解之後,踏上了學習之路!


[我們的痛?]
91在課程的一開始,先分組讓大家自我介紹,請大家分享一下為什麼要來上這堂課。我覺得這是個很好的開始,要解決任何問題之前,請先停下來思考:問題是什麼?釐清問題之後,大家的學習會更努力更有效率。
歸納當天學員們的問題,不外乎就是:
1.     想了解Unit Testing & TDD
2.     實務上怎麼導入?

以我自己為例,我為什麼想要學這堂課的原因是:
1.     我要導入Unit Testing至我們Team,希望能學到實務的例子,提供簡單的架構,降低同事們的學習門檻。
2.     我要教這堂Unit Testing,所以來學習91是如何教學員。

實務上開發常見的問題有那些呢?我想身為一個Developer,應該對這些問題都耳熟能詳,但是卻無法有效解決:

  • 測試環境無法準備
  • 不曉得Developer交付的code是否正確?
  • Side Effects
  • 跟其他Team一起平行開發中,過程中必須相互等待。

其實我們就能透過Unit Test解決上述問題。
1.     測試環境無法準備????
有些系統是屬於外部系統,他們的整合日期可能不是我們這個Team這個層級就能決定的,但是開發不能等他們好再來測,此時我們可以使用Mock Framework來協助我們克服這個問題。

2.     不曉得Developer交付的code是否正確?
交付code即附上Unit Test。結果清楚明瞭。未來若整合進CD,我們可以在建置後就能知道code是否正確,比起問題要到QA才發現還早多了。Bug是需要提早發現及早治療的。

3.     Side Effects
儘管有Code Review。大部分最難防的還是Side Effects吧!而完整的Unit Test就能幫大家補上這一塊,改完code隨時執行Unit Test。有沒有改東壞西馬上就知道結果。
遙想當初我想要Refactor某個Feature,卻因為沒有Unit Test,也沒有QA可以驗證而放棄。如果有Unit Test就會增加我們Developercode的自信心吧!

4.     跟其他Team一起平行開發中,過程中必須相互等待。
其實這問題跟第一點很像,但是更有可能以design的方式就能解決。體會到Unit Test的魅力之後,自然而然會想寫出可以測試的程式(Testability),在寫code時自然就會考量到Isolated關注點的問題,盡量將Dependency隔離開。最後的實務上就能以Mock Framework輕鬆隔離相依性,只測該測的地方,讓Unit Test變得簡單,簡單才會有人想用。

這條路上一定會被問到:
如果寫Unit Test,在開發上會增加多少時間?
這讓我想到之前讀”The Art of Unit Testing with Examples in .NET”這本書時,作者以他本身在大型企業的案例作為例子:





Developer開發的時間雖然變成2倍,但是整體的時間是下降的,更重要的是,Bug的數量很顯著的下降。這就是Unit Test的威力。

還有一句話讓我很有感:
面對未知的問題,不要用猜的,用測的最準!!!


[基礎概念]
什麼是Unit Test
幾點定義:
1.     最小的測試單位
2.     外部相依性為零
3.     沒有商業邏輯
4.     Test Case彼此的相依性為零
5.     一個Test Case一次只測一件事

其中最重要的兩點就是 2 & 5
只要把握這些特性,就能寫出有效的Unit Test
如果Test Case測了兩件事,代表測試失敗時會有兩種可能!

3A原則 Arrange, Act, and Assert
這裡學到幾個tips
1.     面對Unit Testing的初學者,我們在導入時可以將Arrange, Act, and Assert的結構用註解隔開。
2.     Naming時也請習慣使用target, expected, and actual
3.     Assert的位置是(expected, actual) 不要搞錯位置囉!
以上作法能夠幫助Developer清楚原則與用法。

Unit Test的特性:FIRST
Fast, Independent, Repeatable, Self-Validating and Timely

(心得) Repeatable Idempotent來解釋會更有說服力
Idempotent : 無論執行幾次,結果都是相同的。

[AreEqual v.s. AreSame]
原則:(MsTest, 但我想NUnit應該也差不多)
1.     比較value type的值用AreEqual()
2.     比較reference typememory位置是否相同用AreSame()
3.     比較 Collection 可用CollectionAssert
4.     想測是否會有Exception請用[ExpectedException],切記不要自己寫try catch
Exception一定要測如果是Scenario1就預期有ExceptionCase
5.     .Net String Object的特性:String雖是Reference Type,但是有實作StringPool的緣故,所以如果是同一個值將會指到同一塊Memory,所以也擁有value type的特性。

[如何解決相依性]
接下來就進入實務上最常碰到的問題了,也開始進入導入上所面臨的困難。
Solution :

  • 單一職責
  • 依賴Interface
  • 依賴注入
  • 利用Mock Framework

1.     單一職責
Design上就盡量讓一個Class,一個Method負責單一的職責。從這裡盡量降低一些Dependency

2.     依賴Interface
我們要從使用端的角度去定義Interface,從相依的Class中抽取出能共同使用的Interface

3.     依賴注入
這邊要想個法子讓測試程式可以替換掉有相依性的production code instance
91介紹了 (1) Constructor Injection & (2) Parameter Injection
我記得之前書上還有提到(3) Factory Method 以及(4)Extract and Override
下次再補上

4.     利用Mock Framework
自己去寫上述測試程式是很累人的,也會降低Developer想寫Unit Test的意願,此時Mock Framework就能幫助大家很簡單地寫出可避開相依性的測試程式。
這次使用的NSubstitute真的很好用,也不像Rhino違反了3A原則。我們可以透過Substitute.For<T>產生stub, 再透過xxx.TestMethod1.Return(R) 取得stub預期會回傳的R (Stub 關心的是回傳值)
若是想要測Mock (與外部的互動) 也能使用xxx.Received().ExpectedMethod() 知道預期是否有呼叫ExpectedMethod() 或是 DidNotReceived()驗證不被呼叫的情況。(切記,一次只測一件事,如果要測Mock,只要驗證是否有被呼叫即可。)

91的經驗:大部分都是測Stub, Mock的比例大約10%

[PublicMethod該不該測]

不用針對它特別測!!!
但是得透過Public Method測到它

不要為了測試而測試,想想需求吧。非PublicMethod一定是在哪裡被PublicMethod使用到。
Code Coverage的建議
1.     檢視Test Case是否包含最主要的情境
2.     檢視Test Case是否包含曾經出錯的情境
3.     檢視是否有不必要的code或是缺少對應的Test Case
4.     相對比例盡量只能往上,不要往下

[Internal該如何測試]
在實務上我們有些Class是設定成Internal的,測試程式可能無法取得。
Solution :
1.     AssemblyInfo.cs 加上 [assembly:InternalsVisibleTo(“XXX.Test”)]
2.     AssemblyInfo.cs 加上 [assembly:InternalsVisibleTo(“DynamicProxyGenAssembly2”)]
要給DynamicProxyGenAssembly2看得見才能動態建立stub/mock

[其他心得]
1. TDD導入與推廣的原則
(i) 如何讓Member不要太過麻煩就能做
(ii)如何盡量不影響現有production code

2. 不要為了測試而去切Interface
要反過來問需求,我們是為了彈性才去切Interface

3. .NET Framework的Object不建議用Interface去抽換

對這堂課有興趣的朋友們
可以關注一下SkillTree什麼時候要推出第四梯的課程喔
自動測試與 TDD 實務開發(使用C#) 第三梯

系列文章
[心得文] 自動測試與TDD實務開發 Day2

2015-05-13

[讀書筆記] [Continuous Delivery] Build and Deployment Scripting

Build and Deployment Scripting

Introduction
簡單的專案可以用簡單的方法進行建置與部署

只要專案規模稍微複雜點 建置與部署就會出現以下問題 :

  • 步驟會越來越繁複
  • 所需時間也會越長
  • 人工容易出錯


強烈建議使用Script來達成建置與部署的自動化

An Overview of Build Tools

  • Make & SCons
  • Ant
  • NAnt and MSBuild
  • Maven
  • Rake
  • Buildr
  • Psake


各個建置工具的不同點在於
任務導向
    e.g. Ant, NAnt and MSBuild
    根據一系列的任務來描述建置相依性
    不保存狀態(完全不適合C++)
    但對C# 沒有問題
    for example :
          要完成Init 或 Setup test data 的task之後 進行 compile source and test
          儘管很多task都必須依賴Init , 但執行過一次之後就不會再執行
 
產品導向
    e.g. Make
    跟據一系列的檔案來描述建置相依性
    增量式建置(C/C++)
    for example :
           確保compile source 跟 compile test之後的產出出來之後
           利用時間戳記來確是否進行Run Test
         


(1) Make & SCons
      http://zh.wikipedia.org/wiki/Make

      優點 :
                  (i) 能在單次建置中追蹤相依關係 只建置受本次修改影響的元件
                  (ii) 使用簡單
      缺點 :
                  (i) 相依複雜度增加時會難以除錯
                  (ii) 現代語言的IDE已經幫忙處理這塊
                  (iii) 依存在Shell上 (UNIX)

     “This is one of those days when I am not happy with software. It sometimes surprises me how many of those days involve Make.”
—Mark Dominus, “Suffering from ‘make install’”

      現在許多C/C++ Project的Developer都推薦使用SCons
       Why ?
                 1. Python 寫的
                 2. 支援Windows和並行建置

(2) Ant
      參考文件
      http://zh.wikipedia.org/wiki/Apache_Ant

      【認識 Gradle】(1)講古的時間 Apache Ant     
   
     優點 :
                (i) Jave寫的, 強大跨平台的能力
                (ii) Script用XML寫的
               
     缺點 :
                 (i)  XML不簡潔
                 (ii) 領域模型非常貧乏, 要耗費大量時間來編譯,產生jar,執行測試以及編寫樣板檔
                 (iii) 宣告式語言
                 (iv) 無法回答 執行了多少測試? 需要多久?
                 (v) Ant檔非常冗長 也難以重構

     若要使用Ant 推薦Julian Simpson寫的文章:
     “Refactoring Ant Build Files,” in The ThoughtWorks Anthology.      

(3) NAnt and MSBuild
     https://msdn.microsoft.com/zh-tw/library/0k6kkbsd.aspx

     Microsoft當初在導入.NET Framework時 很多Java的Developer將他們喜愛的工具移植到.NET上
   
     Ant  -> NAnt
     NAnt 變體 -> MSBuild

     MSBuild
     優點 :
                 (i) 與Visual Studio 緊密結合, 管理相依性較容易                
     缺點 :
                 (ii) 與Ant相同

(4) Maven
     http://zh.wikipedia.org/wiki/Apache_Maven
     【認識 Gradle】(2)講古的時間 Apache Maven

     Convention over configuration

     Maven被創造出來的動機如下 :
     (i) JAVA專案的標準化 -> 消除Ant大量樣板的問題
     (ii) JAVA專案函式庫管理的問題

     缺點 :
                (i) 缺乏彈性 : Project必須按照Maven規定的結構與生命週期
                (ii) XML
                (iii) 在預設與設置中, 總是自動更新自己 => 可能會導致不可預期的失敗

(5) Rake
      
     產品導向
     要安裝Ruby執行環境
     要用RubyGem建置

(6) Buildr
     
      Buildr 建立在Rake之上, 能做到Rake能做到的事
      作者推薦 如果想找Ant 或 Maven的替代品 強烈推薦 Buildr
      如果喜歡Groovy 就用 Gradle
    
(7) Psake
      
      支援Windows
      用PowerShell寫的內部DSL

Principles and Practices of Build and Deployment Scripting
以下將會提到幾點原則與實踐:


  1. Create a script for each stage in your deployment pipeline
  2. Use an appropriate technology to deploy your application
  3. Use the same scripts to deploy to every environment
  4. Use OS's packaging tools
  5. Ensure the Deployment Process is Idempotent
  6. Evolve your deployment system incrementally
(1) Create a script for each stage in your deployment pipeline
當Project開始時 或許可將script都寫在同一個檔案中
但是 一旦script變得太長 就要將它分成獨立的腳本

要確保所有的script都放在version control repository

(2) Use an appropriate technology to deploy your application
當我們在做自動化部署時 要使用合適的工具 而非general-purpose scripting language

Q : 何謂合適的工具?

When and Who?
在Project一開始就要進行時, Developers, testers, and operations staff都要一起來做部署
要一起決定部署的工具

CASE : One Telecoms Company

(3) Use the same scripts to deploy to every environment

使用相同的預設script部署到所有的環境
環境設置資訊必須分開管理

(4) Use OS's packaging tools
Problems : "將一堆檔案分別部署到檔案系統的不同位置" 效率又低且維護麻煩

要考慮到 upgrades, rollbacks, and uninstalls

Solution : 強烈建議使用 OS's Packaging Technology
For example :

  • Debian and Ubuntu : Debian Package System
  • RedHat and SuSE : RedHat Package System
  • Windows : Microsoft Installer System


也可以考慮使用platform-specific packaging system :
For example :

  • Ruby Gems
  • Python Eggs
  • Perl's CPAN


但如果可以 仍是推薦使用OS's Packaging Technology

(5) Ensure the Deployment Process is Idempotent
Idempotent : 無論做幾次 結果都要一樣

無論target environment現在處於什麼情況 當部署完畢之後target environment 上的狀態都要一樣

How to do?
1. 以已知狀態良好的環境當作起點
2. 驗證環境所需假設

每次部署時都應該根據version control 的某個單一修正版本產生的Binary從頭開始
當部署某元件時 就應該將相關的原件都重新部署一次 (Rebuild)

3個例外

  • (i) Clustered System (Chapter 10)
  • (ii) 應用程式是由多元件(不同version control repositories) => 要通過測試相關的所有元件組合 才可以只部署變更的元件
  • (iii) 使用可以讓效果Idempotent的Tool

(6) Evolve your deployment system incrementally
從簡單的小事開始做起
循序漸進

Deployment Scripting

核心原則 : 完全自動化

不要再遠端登入到環境上執行部署動作!!!

三種scripted deployments的方式 :
(1) 寫一支script 執行所有工作 (For  一台機器)
(2) 遠端部署 (For 多台機器)
(3) Script your own deployments (如果上述方法都不適用)

(1) 寫一支script 執行所有工作 (For  一台機器)
     因為只有一台機器 所以可以用一個script在local端執行所有工作

(2) 遠端部署 (For 多台機器)
      A set of deployment scripts
     (2.1) 寫script並登錄到遠端每台機器上執行
     (2.2) 在Local端寫script 利用agent在遠端每台機器上執行
     (2.3) 利用合適的OS's packaging technology
              第三種作法是最powerful
               why ?
               2.3.1 Idempotent
               2.3.2 管理部署及基礎建設可在同一套Tool上 不同團隊較容易溝通

    如果2.3找不到或無法使用這套方法
    找找看是否有包含Agent model的CI Server

(3) Script your own deployments (如果上述方法都不適用)

Deploying and Testing Layers

原則 :
總是把根基紮在已知狀態良好的基礎上


只有環境都設置完成 才能開始部屬軟體

Testing Your Environment’s Configuration

任何層次部屬出錯 都有可能造成應用程式無法正常執行
所以每個層次都需要進行測試

如果Fail 就讓環境設置流程快速失敗

For example :

  • Confirm that we can retrieve a record from our database.
  • Confirm that we can contact the website.
  • Assert that our message broker has the correct set of messages registeredin it.
  • Send several “pings” through our firewall to prove that it allows our traffic and provides a round-robin load distribution between our servers.


Tips and Tricks

  • Always Use Relative Paths
  • Eliminate Manual Steps
  • Build In Traceability from Binaries to Version Control
  • Don’t Check Binaries into Version Control as Part of Your Build
  • Test Targets Should Not Fail the Build
  • Constrain Your Application with Integrated Smoke Tests
  • .NET Tips and Tricks



(1) Always Use Relative Paths
建置中最常見的錯誤就是預設使用絕對路徑 (相依性)

所有位置都必須是相對路徑
能確保每個建置都是完整獨立的

如果不得不使用絕對路徑 請確保
1. 這是特例
2. 必須與建置系統相互獨立

盡量減少安裝於非標準位置的路徑

(2) Eliminate Manual Steps
"A bad system will beat a good person every time" 
by W. Edwards Deming

只要是手動 一定容易出錯

何時要考慮自動化呢?
當你不得不做第2次時

(3) Build In Traceability from Binaries to Version Control

確定某個Binary是由版本控管哪個版本產生
版本化的metadata

(4) Don’t Check Binaries into Version Control as Part of Your Build
不要把Binary當作建置的一部分check in進Version Control

因為我們總是能從重新建置一份

將Binary或是Report存到File System就好

經驗法則 :
不要將建置, 測試和部署期間產生的任何產出check in 進 Version Control
而是要將他們當作Metadata

(5) Test Targets Should Not Fail the Build
本書覺得不好的作法是 任何一個Fail都導致建置失敗

原因是 :
若是某個Unit Test Fail就導致Build Fail , 我們不曉得之後是否有更多測試沒過
要等下次建置才會測到未測到的部分, 一來一往之間更浪費時間

Solution :
1. 紀錄當下的錯誤 並註記1個 Flag
2. 經過完整的測試之後 根據Flag決定是否讓Build Fail

(6) Constrain Your Application with Integrated Smoke Tests

在部署之前另部署script檢查一下環境是否正確

(7) .NET Tips and Tricks
Problem 1
.NET .sln and .csproj 會記錄實際建置專案時所引用的reference, 但很有可能某個file已經不被引用了 但仍存在 file system中
Solution
在全部的sln中打開顯示隱藏檔案的屬性 , 刪除沒用到的File

Summary
script 可以輔助我們進行建置,測試,部署和發佈應用程式
請找出最痛苦的步驟, 開始嘗試自動化, 逐步完善自動化建置與部署的能力
Build and Deployment Scripting必須貫穿整個開發流程

2015-04-28

需求怎麼估? - Animal Point Workshop Part II - 實際動手玩

需求怎麼估? - Animal Point Workshop

前情提要

需求怎麼估?  - Animal Point Workshop Part I - 估需求前必須知道的事


Previously 我們討論了估需求前必須知道的事
提到了
三個基本原則 : 
  • 相對比較 絕對評估 簡單
  • 小任務 大任務 容易掌握
  • 使用 Planning Poker 來估

點注意事項:
  • Who : 做事的人一起
  • When : 被分派任務就估
  • What : 評估時請考慮複雜度重複性風險

現在就要帶大家來體驗一下Animal Point Workshop
















遊戲故事的假設是這樣的:
今天你們是個動物園管理團隊,要評估幫動物們洗澡的複雜度。
團隊裡角色只有兩種
1.     Product Owner
Product Owner(PO)要解釋有關動物洗澡的任何需求,所以當團隊翻出新的動物牌卡時,PO要天馬行空地描述需求,假若Team Member對於需求有任何的疑問,PO要解答團隊的疑惑。(但要注意的是,PO不要主動地引導,for example:我覺得不是這樣)
2.     Team Members
Team Members 則是實際要幫動物們洗澡的員工,他們必須一起評估每個動物洗澡的需求複雜度。過程中若是對需求不清楚則是要趕快找PO確認細節。

圖為PO解釋需求中





















Step 1 : 比較大小
注意事項:團隊成員輪流出動物牌卡,一次只能移動一張卡 (翻新圖卡或挪動現有圖卡)
步驟:
          (1) Member A隨機抽一張新牌卡,PO解釋新牌卡的需求。
          (2) Member B隨機抽一張新牌卡,PO解釋新牌卡的需求。Member B要比較現有牌卡的複雜度,小的擺左邊,大的擺右邊。挪動時請向Team說明理由。
          (3) Member C 可以選擇以下兩種方式
                   i. 抽新卡如同步驟(2)
                   ii. 挪動現有牌卡。挪動時請向Team說明理由。

          (4) 重複步驟(2)或是步驟(3)直到全部的牌卡都抽出以及大家都同意現在的排序。

結束這個步驟之後,會得到一串經過排序的牌卡






Step 2:校正基準
兩套校正的方法

(1) 歷史基準
由於SCRUM裡評估的Story Point都是相對的,所以每個Sprint 或是每個Release估出來的數值無法拿來比較。這邊採用歷史基準的原因就是想要讓每一次的評估都可以校正為統一的標準。
所以校正的方式是拿出過去評估的需求,首先要評估這個需求可以插在剛剛排序完卡列中的哪個位置?
For example:
假設小黑熊在過去評估的複雜度為8點,將他放置在現有排序中,則小黑熊8點就是這次的基準參考點。







(2) 定義最小
若是不想採用歷史基準或是沒有歷史資料,那就就這次的需求來估算吧。上一集有提到原則二:小任務估算比較有信心、比較精準。所以我們可以拿目前最小的需求來估算點數。
For example:
假設這次團隊所排序最小的需求是幫天竺鼠洗澡,經過Planning Poker的過程估出複雜度為3點,那麼這次的需求複雜度就是由3點起跳。









Step 3 : 評估程度
注意事項:
團隊成員輪流出點數,一次只能更動一個點數
若相鄰多張圖卡皆評估為相同點數,請將該點數放置在最左邊的圖卡
步驟:
          (1) Member A檢視桌上的排序,依照基準比例,挑選合適的一張點數放置在任何一張牌卡上。
          (2) Member B可以選擇以下兩種方式
                     i. 放上新點數如同步驟(1)
                     ii.挪動現有點數
          (3) 重複步驟(1)或是步驟(2)直到大家都同意現在的估算。


結束這個步驟之後,會得到評估後的結果






Recap一下Animal Point Workshop的執行步驟:

  • Step 1:比較大小
  • Step 2:校正基準
  • Step 3:評估程度

心得

在玩Workshop的過程中,有的團隊有面臨到意見不合的衝突,但是經由充分的討論以及一再地向PO確認需求,最後總是能達成共識。也有PO根本不知道這張卡的需求為何?所以團隊很有共識地給予那張卡一張問號,代表PO要先回去搞清楚,是不是很符合現況呢XD












結論

導入SCRUM 或是Planning Poker的方法進入團隊是道門檻,而今天筆者介紹的Animal Point Workshop有個好處:簡單。越簡單的東西才越容易導入到團隊裡。相信經過這個Workshop的練習能夠讓團員們體會相對估算的精神;幫助他們熟習一起估算的方式;在討論中達成共識。大家一起估就能消除個人主觀的因素。整個團隊估出來的東西才會比較客觀。

另一方面,這種簡單的相對估算,可以幫助團隊快速地區分需求複雜度,團員們不用再苦惱到底怎麼估才能估出一個精準的工時,對公司跟團隊都是一種”win-win situation”喔。

參考資料
估算需求複雜度(2)Dog Point Game
A Fast Story Point Estimation Process

需求怎麼估? - Animal Point Workshop Part I - 估需求前必須知道的事

需求怎麼估? - Animal Point Workshop



2015.04.24 星期五
我很榮幸在Agile Meetup新竹場分享這個Topic


























其實這場Topic的靈感是來自於91學長上次的Dog Point Workshop
http://www.codedata.com.tw/social-coding/estimation-with-dog-point-game/
只是我這次有調整了一下講課內容以及workshop的流程

這邊就先整理一下今天的內容吧

今天這場sharing 主要分兩個部分
上半場主講估需求前必須知道的事
下半場就讓大家來玩Animal Point Workshop

來先談談估需求前必須知道的事吧

在任何的軟體開發流程中,需求估算永遠不會消失。
或許很多朋友認為估需求是相當困難且痛苦的一件事,或許很多朋友把大量時間花在冗長的估算上但始終也估不準。
今天這堂課將則是引導出需求估算的另一種方向 - 相對估算
課程將會以Workshop的方式進行,用一個有趣的案例,讓學員們實際操作,體會相對估算的精神。

首先 我請大家先思考一下
目前自己的團隊中對於估需求這件事是否遇到什麼問題?















主要的想法是要解決問題前
至少要知道問題是什麼吧

於是我就請學員們分組討論
5分鐘後請每組挑出三個最重要的問題來分享
以下是學員們的分享:

  • 估不準
  • 照著被訂好的deadline估
  • 每個Sprint的工作量不一
  • 總是被分派到類似的任務
  • 需求不明確
  • 需求超出能力
  • 團隊對工時有落差
  • 範圍太廣很難估

或許今天的內容無法解決他們的問題
但是釐清問題就是解決問題的一大步了

接下來就進入主題了

I. 估需求前必須知道的基本原則

  • 相對比較 比 絕對評估 簡單
  • 小任務 比 大任務 容易掌握
  • 使用 Planning Poker 來估

原則一 : 相對比較絕對評估 簡單
我請大家進入一個情境 : 假設今天你要爬樓梯
請問大家這24層樓的大樓以及101登高賽分別要爬多久?




要很快地回答要爬多久其實有點困難
但是要比較兩者之間的難易度就簡單多了

我們不知道每一棟高樓實際要爬多久
但是知道彼此的相對關係

所以估相對關係真的比較簡單


原則二 :  使用 Planning Poker 來估
我一樣請大家進入一個情境 : 假設今天你要評估肌肉痠痛的程度
一樣是爬樓梯
面對1層樓、3層樓或5層樓甚至是40層樓應該是不一樣的痠痛程度吧!
那我們如何很快地評估肌肉的痠痛程度?
其實可以參考費氏數列 (Successione di Fibonacci in wiki)
















費氏數列的特性是越後面的數字,差距越大。
當數字小的時候,你感覺得到差距


















可是當數字大的時候,你卻分不出誰大誰小,反正都很痛苦就是



















所以費氏數列很完美地詮釋了需求越大,不確定性越大的特性。
我們可以利用這個特性來對需求快速的分類
這邊呼應了原則一,我們對於評估實際的數值感到困難,但評估彼此的相對比例會簡單很多。
當數字小時,即使保守點取較大數,也不會造成太大的影響
當數字大時,不用糾結於40或是41的差別

而Planning Poker正是使用類似費氏數列的數字牌卡
所以這邊推薦大家使用Planning Poker














II. 評估時的注意事項

Who - 誰來估?

























你累了嗎?來聽個故事好嗎?
照片裡的主人翁是個小力士,這個祕密被邪惡老爸發現了之後,規定他一分鐘之內要搬10包尿布!但是實際上小力士只能搬2包。
請問各位如果你是小力士,作何感想?
小力士:實際搬的人又不是你! 真是OOXX
這種情境總是一再上演阿!所以誰要來估?當然是有做事的人才來估。而且要大家一起評估,估出來的結果才會客觀;大家也會達成共識;團隊也有參與感。

所以誰來估?
由做事的人一起評估

When – 何時估?
還沒分派任務前估


原因是將個人因素降低,估出來的結果才會比較客觀。

What – 評估因素
我們在評估這個需求時,可以就這三個角度來思考 :

  • 複雜度
  • 重複性
  • 風險

這邊是參考之前讀的一本書:
Scrum Shortcuts Without Cutting Corners: Agile Tactics, Tools, & Tips

小結
為何推薦大家採用這套相對估算方法?

  • 簡單
  • 客觀評估
  • 達成共識
  • 自我承諾


簡單
越簡單的東西才越容易導入到團隊裡。尤其要改變大家平常的工作習慣,必須想辦法簡單到無縫接軌,或是讓團員們有感覺到好處。才容易導入成功。

客觀評估
大家一起估,就能消除個人主觀的因素。整個團隊估出來的東西才會比較客觀。或許你會問,那估錯怎麼辦?那就下次改進囉!我們也可以利用每次的Retrospective Meeting修正一下估錯的因素。

達成共識
大家一起估的東西,才會達成共識。

自我承諾
我一直都認為自己開出去的支票,比起被別人assign,總是會更想努力地兌現。而這套方法是Member大家一起估的東西,等於是自己承諾的份量,他們肯定會想辦法完成的。

下一篇就來談談Animal Point Workshop怎麼玩喔
需求怎麼估? - Animal Point Workshop Part II - 實際動手玩

參考資料:
估算需求複雜度(1)Story Point 與 Planning Poker

2015-04-14

[瀑布底下玩SCRUM] CM的Retrospective Meeting經驗談


最近趁著 I6Sprint結束,打鐵趁熱地在部門內辦一場 Retrospective meeting。算算日子轉到 CM Team也已經 9個多月了,從 6.0 SP3 I2開始推動 Retrospective meeting,至今也已經舉辦過4場。但過去的方式都是傳統式的ㄧ個ㄧ個地表達意見,雖然還算open-minded,但是有時候仍會被前面講過的idea影響,有些同仁則是反映都是那幾個人在發表。

所以這一次我特意換成外界SCRUM愛玩的那一套便利貼Feedback法,事前先請同仁就I6這個Sprint先想一下以下三個主題:
1. Good
2. Should be improved 
3. New

當天會議的流程如下:
1. 回顧上個Retrospective Meeting Result
2. 報告這個Sprint的相關統計資訊
3. Brainstorming for good (5 minutes)
4. 大家輪流上台貼便利貼及說明
5. Brainstorming for improved(10 minutes)
6. 大家輪流上台貼便利貼及說明
7. Brainstorming for new (5 minutes)
8. 大家輪流上台貼便利貼及說明
9. 分類 improved & new的便利貼
10. improved & new中選出3項下個sprintaction item
11. 討論解決方案

這次我特別將good, improved, new 分成三個部分來分開討論
用意是希望同仁們可以更focus on目前的topic

或許是這套方法引發大家源源不絕的想法吧?
或許是大家對團隊很多期待吧?

還滿開心看見當天同仁們滔滔不絕地發表看法,不過也讓會議時間到了2小時仍是無法結束,所以很可惜最後並沒有跑到投票與討論solution的流程。
會議結束後我把黑板上的便利貼拍下來,後續會整理成文件以便下次使用。(Post-Mortem Meeting還能拿來用)

幾點心得分享
1.     時間還是必須要控制,實在run太久了。
2.     這次的方式的確激發出大量意見,大家也都在台上侃侃而談,我覺得效果不錯。
3.     最後還是沒能跟QA一起舉行是有點可惜。
4.     聽到同事們支持與稱讚這次Sprint推行的方法其實還蠻有成就感的,原本還擔心會造成大家的負擔,不過就結果論來看,從”win-win”的角度切入真的比較容易推行喔。

2014-12-21

[反省] 學習是要正面主動積極的

昨天看到學長開的課終於結束了 心中好是後悔

其實我在課程一開始就跟公司申請要去上這門課

結果卻被拒絕了

原本我有打算就算沒經費 也要自費去上課

不過卻被幾個負面思考打斷了這個念頭

1. 現在用不到
    說實話 真的用不到 這套作法要導入我們部門 確實有點窒礙難行
    不過 話說回來 即使目前環境用不到 但對我自己來說 一定也是有幫助的

2. 老婆會抗議
    因為上課會花掉三個星期六全天的時間 我很感謝平日老婆的辛苦
    周末就盡量花時間陪伴家人
    所以當初這也是個考量因素之一

3. 經濟問題
    雖然課程費用不貴 但對最近的我 自掏腰包額外掏出這些費用也是有點痛的
    
其實念頭就在一念之間
從想報名上課到索性就不報了的念頭也不過幾天

但結果卻是相當後悔的

希望下一次 我能好好想想 學習是個人的 應該要更主動一點


2014-12-18

[讀書筆記] Design and Testability

Design and Testability

1. Why should I care about testability in my design?

In a testable design, each logical piece of code (loops, ifs, switches, and so on) should be easy and quick to write a unit test against, one that demonstrates these properties:

FICC

  • Fast
    • Runs fast
  • Isolated
    • Is isolated, meaning it can run independently or as part of a group of tests, and can run before or after any other test
  • Configuration-free
    • Requires no external configuration
  • Consistent
    • Provides a consistent pass/fail result
If you were doing test-driven development, you’d have no choice but to write a testable system.

2. Design goals for testability

2.1 Make methods virtual by default

Java makes methods virtual by default, but in .NET, you need to explicitly set it as virtual so you can override it in a default class.

An alternative is to have the class invoke a custom delegate.

Using virtual methods is handy, but interface-based designs are also a good choice.

2.2 Use interface-based designs

Refer to chapter 3~5

2.3 Make classes nonsealed by default

If you can’t inherit from a class, you can’t override any virtual methods in it.

2.4 Avoid instantiating concrete classes inside methods with logic

Tests might need to control what instance is used in the class under test.

Solution:
(1) Use the external tools such as Mock tool
(2) Ways in the 3rd chapter such as Factory Method.

2.5 Avoid direct calls to static methods

Try to abstract any direct dependencies that would be hard to replace at runtime.

Solution:
(1) Ways in the 3rd chapter      
      Abstract a static method away using the Extract and Override refactoring.(2) Avoid using any static methods whatsoever
(3) Trying to minimize the number of singletons or static methods

2.6 Avoid constructors and static constructors that do logic

Things like configuration-based classes are often made static classes or singletons because so many parts of the application use them.

在Constructor建立多個邏輯或是static constructor 會因為很多地方有使用到導致難以替換

Solution:
(1) IoC Container

2.7 Separate singletons and singleton holders


SRP: Single Responsibility Principle

原則上就是將該做事的Class跟產生Singleton的Class權責分開
好處是 :
(1) SRP
(2) 可以替換

Sample:

原本的設計 Singleton

Singleton Holders抽出


3. Pros and cons of designing for testability


  • Amount of work
    • Let’s just say that more code, and work, is required when testability is involved, but that designing for testability makes you think about the user of your API more, which is a good thing.
    • 工作量增加是一定的 但是能多用User的角度來設計 這是好事
  • Complexity
    • Over design
    • 能用Tool來克服 (e.g. ReSharper)
  • Exposing sensitive IP
    • IP: Intellectual Property
    • Workaround : 
      • keeping things internal and using the [InternalsVisibleTo] attribute
    • Compromise
  • Sometimes you can’t
    • Political or other reasons


4. Alternatives to designing for testability

If a tool comes along that solves the testability problem for you, there will be no need to design specifically for testability.

5. Summary


Testable designs are what SOLID design principles have stood for. 
The end goal should not be testability, but good design instead.