2015/06/29

Scrum vs Kanban

Kanban vs Scrum 簡要說明並比較 scrum 以及 kanban,雖然兩者都屬於 agile managment 的方法,但在自由度的精神上,還是有些差異。一個 agile 團隊不會照單全收某個方法的所有工作指引,而是在透過討論與實際的驗證,決定該怎麼進行團隊管理,本文的作者認為可以整合 kanban 與 scrum 方法,調整為自己的團隊專屬的專案管理方法。

中文版 比較Kanban和Scrum

scrum

  1. 將所有成員分為數個 small, cross-functional, self-organizing teams
  2. 將整個專案切割為數個 small, concrete deliverables,並以 priority 以及預估的 effort 排序
  3. 將時間切割為 short fixed-length iterations (通常是 1~4 週),每一次 iteration 都能產出可 demo 可釋出的 code
  4. 持續跟客戶review release plan 並更新工作的優先順序,基本是以每一次 iteration 結束 release 的產出目標為基準。
  5. 每一次 iteration 之後,都要再 optimize process

kanban

  1. 將 workflow 以圖表視覺化
    切割工作項目,寫在卡片並貼在牆上
    在 workflow 中為每個工作 columns 命名工作階段
  2. 限制 WIP(work in progress),明確地限制每一個 workflow state 的 WIP 上限
  3. 估算 lead time(完成一個 item 需要的平均時間,也稱為 cycle time),持續改善 process 直到可以正確地估算 lead time

Agile 自由度

以下的圖表,將幾個管理方法放在 agile 自由度的光譜上度量,流程越複雜,細節越繁瑣的管理方法在左邊,輕量化,以軟體產出為主要目標,讓團隊更專注在專案開發上,減少專案管理 effort 的管理方法在右邊。

換句話說,Agile 就是讓團隊成員越自由,老闆不需要管什麼,就能自動把專案跟事情做好,但這應該只是理想,人與人之間還是需要一些溝通與資訊交換,才能確保軟體功能實作時,內部的資料邏輯與精神是一致的。

focus vs interrupts, repeatable vs exploratory innovation

Scrum 與 Kanban應用環境 文章中提到Scrum or Kanban? YES! 提出的一個比較的圖表。

二維的圖表可區分為五個區塊

  1. focus - innovation
    scrum
    同時需要專注在創新以及專案開發,並維持持續交付 deliverables
  2. focus - repeatable
    production line kanban
    例如生產線作業員、產品量產階段
  3. interrupts - innovation
    混合使用 scrum 與 kanban
  4. interrupts - repeatable
    support kanban
    例如客服中心、公司內部的 MIS,需要團隊持續維護,並作些微的調整與修改
  5. 中間
    kanban

類似的地方

  1. 都是符合 lean and agile 精神的管理方法
  2. 都使用 pull scheduling
  3. 都有限制 WIP (work in progress)
  4. 都利用 transparency 透明化來改善工作流程
  5. 都著重於儘早及經常交付可出貨的軟體
  6. 都是給 self-organizing team 使用
  7. 都要求把工作拆解成更小的工作細項
  8. 發佈計畫是根據資料(速度/前置時間)來持續優化

不同的地方

Scrum Kanban
timeboxed iterations prescribed (預先定義 itertation 的時間) timebox iterations optional (可區分 planning, release, process improvement 階段,且可以 event-driven 取代 timeboxed)
團隊 commits 每個 iteration 交付的工作量 commitment optional
以 velocity 生產率 作為流程改善與計畫的 metric 以 Lead Time 生產週期 作為流程改善與計畫的 metric
cross-functional teams cross-functional teams optional 允許有 specialist teams
工作必須 break down 至 1 sprint 可完成的份量 沒有特定的 item size
burndown chart prescribed 沒有特定的 diagram
間接限制每個 sprint 的 WIP 直接限制每個 workflow state 的 WIP
estimation prescribed estimation optional
不能在進行中的 iteration 增加 item 只要團隊容量允許,就可以增加 item
由一個特定團隊維護 sprint backlog 數個團隊或多人共享一個 kanban board
有三個角色 PO/SM/Team 沒有預定的角色
sprint 結束後就重設 scrum board kanban board 是永久長存的 
預先定義 prioritized product backlog prioritization is optional

Reference

Scrum vs. Kanban:軟件開發新方法大比拚

Scrum 和 Kanban 的比較

從 Scrum 到 Kanban: 為什麼 Scrum 不適合 Lean Startup

硝煙中的Scrum和XP

看板管理

Kanban, Flow and Cadence

看板和Scrum——相得益彰

Kanban vs Scrum

Intro to Kanban in Under 5 Minutes (What is Kanban, Learn Kanban)

Scrum和Kanban比較的結論

2015/06/22

Introduction to Play Framework

Introduction to Play Framework for Scala developers 這個影片,由建立 Play Framework 專案開始,解釋初始專案的內容,在 trace 的過程中,連帶將如何使用 Play Framework 的概念一併提供給讀者。

啟動 play framework web server

在「命令提示字元」裡,切換到 scala-play 的目錄,然後鍵入指令 activator run ,就能啟動 play framework web server。瀏覽器瀏覽網頁 http://localhost:9000/ 就可以看到 play framework 的測試網頁。

網站首頁

  1. 首先我們先看 conf/routes 這個設定檔,這裡面針對 / 這個 URI,設定是由 controllers.Application 這個類別的 index 這個 method 負責處理。

    設定檔 /conf/routes

     ## Home page
     GET     /                           controllers.Application.index
    

    在 app/controllers/Application.scala 這個 controller 中,會看到處理 index 的 Action

     package controllers
    
     import play.api._
     import play.api.mvc._
    
     class Application extends Controller {
    
       def index = Action {
         Ok(views.html.index("Your new application is ready."))
       }
    
     }
    

    瀏覽器首頁最上面的 "Your new application is ready." 文字,就是從這裡列印到網頁中的,但實際上,Ok 裡面還是呼叫了 view template 的程式,後面的部份是傳送給 view template 的文字參數。

    在 play framework web server 啟動的狀態下,如果我們修改了 app/controllers/Application.scala 的內容,網頁會自動重新編譯,並輸出到瀏覽器上。同樣地,當原始程式編譯產生錯誤時,網頁也會自動顯示錯誤點,而且未來在實際上線時,可以將顯示錯誤點網頁的功能關閉。

  2. view template
    app/views/index.scala.html 最前面的 message 是收到的參數內容,也就是上一個步驟傳送進來的 "Your new application is ready.",接下來的 template 引用了兩個參數,並傳送至 app/views/main.scala.html。

    play20.welcome 是一個內建在 play framework 的 template ,裡面是 play framework 的 document 網頁。

     @(message: String)
    
     @main("Welcome to Play") {
    
         @play20.welcome(message)
    
     }
    

    app/views/main.scala.html 的一開始,定義了兩個參數,分別是 title 以及content html。

     @(title: String)(content: Html)
    
     <!DOCTYPE html>
    
     <html lang="en">
         <head>
             <title>@title</title>
             <link rel="stylesheet" media="screen" href="@routes.Assets.versioned("stylesheets/main.css")">
             <link rel="shortcut icon" type="image/png" href="@routes.Assets.versioned("images/favicon.png")">
             <script src="@routes.Assets.versioned("javascripts/hello.js")" type="text/javascript"></script>
         </head>
         <body>
             @content
         </body>
     </html>
    

    將 app/views/index.scala.html 裡面的 @play20.welcome(message) 改為 @message,瀏覽器上就只會剩下 "Your new application is ready." 的文字列印在畫面上。

     @(message: String)
    
     @main("Welcome to Play") {
         <!-- @play20.welcome(message) -->
         @message
     }
    

如何測試 play framework

test/ApplicationSpec.scala 是直接發送 http request,然後以 http response code 確認是否正常。

    import org.specs2.mutable._
    import org.specs2.runner._
    import org.junit.runner._

    import play.api.test._
    import play.api.test.Helpers._

    /**
     * Add your spec here.
     * You can mock out a whole application including requests, plugins etc.
     * For more information, consult the wiki.
     */
    @RunWith(classOf[JUnitRunner])
    class ApplicationSpec extends Specification {

      "Application" should {

        "send 404 on a bad request" in new WithApplication{
          route(FakeRequest(GET, "/boum")) must beSome.which (status(_) == NOT_FOUND)
        }

        "render the index page" in new WithApplication{
          val home = route(FakeRequest(GET, "/")).get

          status(home) must equalTo(OK)
          contentType(home) must beSome.which(_ == "text/html")
          contentAsString(home) must contain ("Your new application is ready.")
        }
      }
    }

利用 browser 測試網站

    import org.specs2.mutable._
    import org.specs2.runner._
    import org.junit.runner._

    import play.api.test._
    import play.api.test.Helpers._

    /**
     * add your integration spec here.
     * An integration test will fire up a whole play application in a real (or headless) browser
     */
    @RunWith(classOf[JUnitRunner])
    class IntegrationSpec extends Specification {

      "Application" should {

        "work from within a browser" in new WithBrowser {

          browser.goTo("http://localhost:" + port)

          browser.pageSource must contain("Your new application is ready.")
        }
      }
    }

打開一個新的 「命令提示字元」,切換到 project 目錄,輸入 activator test

> activator test
[info] Loading global plugins from C:\Users\yaocl\.sbt\0.13\plugins
[info] Loading project definition from D:\projectcase\trunk3\play-scala-intro\project
[info] Set current project to play-scala-intro (in build file:/D:/projectcase/trunk3/play-scala-intro/)
[info] Compiling 2 Scala sources to D:\projectcase\trunk3\play-scala-intro\targe
t\scala-2.11\test-classes...
[info]
[info] IntegrationSpec
[info]
[info] Application should
[info] - play.api.libs.concurrent.ActorSystemProvider - Starting application default Akka system: application
[info] - play.api.libs.concurrent.ActorSystemProvider - Shutdown application default Akka system: application
[info]   + work from within a browser
[info]
[info] Total for specification IntegrationSpec
[info] Finished in 14 seconds, 734 ms
[info] 1 example, 0 failure, 0 error
[info]
[info] ApplicationSpec
[info]
[info] Application should
[info] - play.api.libs.concurrent.ActorSystemProvider - Starting application default Akka system: application
[info] - play.api.libs.concurrent.ActorSystemProvider - Shutdown application default Akka system: application
[info]   + send 404 on a bad request
[info] - play.api.libs.concurrent.ActorSystemProvider - Starting application default Akka system: application
[info] - play.api.libs.concurrent.ActorSystemProvider - Shutdown application default Akka system: application
[info]   + render the index page
[info]
[info] Total for specification ApplicationSpec
[info] Finished in 447 ms
[info] 2 examples, 0 failure, 0 error
[info]
[error] Failed: Total 3, Failed 0, Errors 0, Passed 3
[error] (test:test) sbt.TestsFailedException: Tests unsuccessful
[error] Total time: 90 s, completed 2015/6/11 下午 01:53:07

如果測試時發生錯誤,修正程式後,可直接執行 "activator test-quick" 快速重新測試 failed tests

Data Persistence

在測試影片中說明的 sorm : scala 使用的 ORM framework,一直發生一些問題,在 play framework issue #4342中提到,sorm 原本是以 scala 2.10 編譯的,可能因此沒能正常地支援 2.11,最後建議嘗試使用 Anorm 或是 Slick。

根據上述文章的建議,我們就測試了 Anorm 的方案。

activator computer-database-scala 的 project template 設定過程如下:

  1. activate new play-scala-db computer-database-scala
    以 computer-database-scala 這個 template 建立一個新專案 play-scala-db

  2. cd play-scala-db
    切換到 play-scala-db 目錄

  3. activator eclipse
    建立 eclipse project settings

  4. activator run
    啟動 play-scala-db project

  5. 瀏覽器連結到 http://localhost:9000/ 可看到以下的畫面

這個 project template 是個傳統的 CRUD 頁面,Model 利用 Anorm 存取 DB,有使用 twitter bootsctrap 產出頁面以及分頁功能。project 設定檔 conf/application.conf 裡面預設是使用 h2 memory database。

2015/06/15

如何建置 scala, play framework 的開發環境

傳統的 Java Web Project 也就是 Java EE (Enterprise Environment) ,其中包含了 JSP/Servlet以及 EJB,後來在肥大的 EJB 失敗後,網頁專案開始 POJO (Plain Old Java Object) 化,就是盡可能地不做太多的物件封裝,這個階段,產生了很多的網頁 MVC framework,而 play framework 是以 scala 與 java 撰寫的 web application framework,他的本質也是提供一種 MVC 的框架,但實質上,他還承襲了 scala 非同步的特性,提高了網頁服務的可用性,他也更進一步地完全跳脫了 Java EE 的網頁標準,我們要做的不再是 JSP 以及 Servlet。

構建可伸縮系統 Scala vs Java 這篇文章,以 Java/Tomcat 與 Scala/Play 這兩種 web framework,建立了簡單的購物 web project,並以 JMeter 進行效能的量測,從該文章的結論中我們得知,當系統在穩定運作的過程中,兩個 framework 的效能表現並沒有什麼差異,而當預先定義的 search 後端服務發生問題時,尤其是使用 proxy 連接到 seach service 時,網站的其他功能例如 Payment、瀏覽目錄的網頁也同時受到影響。但是用 Scala 建置的 service 可在 search 發生問題時,不影響到其他的服務項目。原因是因為 Scala 天生的非同步特性,讓 Programmer 能很自然地寫出非同步 IO 處理的程式碼,如果要使用 Java 達到同樣的功能,也能夠做到,但是我們會發現很多不自然的 callback 程式碼,programmer 需要耗費大量心力,去維護非同步的程式碼。

在 play framework wiki 中,提到了一些使用 Play framework 的 reference sides,例如比較有名氣的 Linkedin、Coursera。

要建置 play framework 的開發環境,需要安裝下列的工具

  1. JDK 8
    到 Oracle 下載 JDK並安裝,安裝後設定環境變數
     JAVA_HOME=C:\java\jdk1.8.0_45
     PATH=%JAVA_HOME%\bin;%PATH%
    
  2. scala 2.11.6
    下載 scala-2.11.6.msi 並安裝,安裝後設定環境變數
     PATH=C:\java\scala\bin;%PATH%
    
  3. sbt 0.13.8
    下載 sbt-0.13.8.msi 並安裝,安裝後設定環境變數
     SBT_HOME=C:\java\sbt
     PATH=%SBT_HOME%\bin;%PATH%
    
  4. Eclipse Luna + WTP

  5. Scala IDE 4 + Play Support in Scala IDE
    在 Eclipse 的 Help -> Install New Software 增加一個網址 Scala IDE - http://download.scala-ide.org/sdk/lithium/e44/scala211/stable/site ,然後就能安裝 Scala IDE 與 Play Support。

  6. Play Framework Activator
    typesafe-activator-1.3.2-minimal.zip

     PLAY_HOME=C:\java\activator-1.3.2-minimal
     PATH=%PLAY_HOME%\bin;%PATH%
    

要建立一個 scala play project 可以遵循以下的步驟

  1. 啟動「命令提示字元」切換到 eclipse workspace 的資料夾,鍵入指令 activator new
    因為運作環境是使用類似 maven 的 ivy2,第一次執行會等很久,等到 script 把 jar 都存到 C:\Users{user.home}.ivy2\cache 的目錄中。
    第二次執行 activator new 之後,就不需要再等待下載 jar 了,在 script 裡面選擇 6,就會建立 play-scala project template,然後輸入 play-scala 作為 project folder 的名稱。
    ```
    D:\projectcase\trunk3>activator new

Fetching the latest list of templates...

Browse the list of templates: http://typesafe.com/activator/templates
Choose from these featured templates or enter a template name:
1) minimal-akka-java-seed
2) minimal-akka-scala-seed
3) minimal-java
4) minimal-scala
5) play-java
6) play-scala
(hit tab to see a list of all templates)

6
Enter a name for your application (just press enter for 'play-scala')
play-scala
OK, application "play-scala" is being created using the "play-scala" template.

To run "play-scala" from the command line, "cd play-scala" then:
D:\projectcase\trunk3\play-scala/activator run

To run the test for "play-scala" from the command line, "cd play-scala" then:
D:\projectcase\trunk3\play-scala/activator test

To run the Activator UI for "play-scala" from the command line, "cd play-scala"
then:
D:\projectcase\trunk3\play-scala/activator ui

```
  1. 建立 eclipse project settings
    切換到 play-scala project 目錄中,然後利用 sbt 建立 eclipse project settings

    D:\projectcase\trunk3\play-scala>sbt eclipse
    [info] Loading global plugins from C:\Users\{user.home}\.sbt\0.13\plugins
    [info] Updating {file:/C:/Users/{user.home}/.sbt/0.13/plugins/}global-plugins...
    [info] Resolving org.scala-sbt.ivy#ivy;2.3.0-sbt-fccfbd44c9f64523b61398a0155784d
    [info] Resolving org.fusesource.jansi#jansi;1.4 ...
    [info] Done updating.
    [info] Loading project definition from D:\projectcase\trunk3\play-scala\project
    [info] Updating {file:/D:/projectcase/trunk3/play-scala/project/}play-scala-buil
    d...
    [info] Resolving org.scala-sbt.ivy#ivy;2.3.0-sbt-fccfbd44c9f64523b61398a0155784d
    [info] Resolving org.fusesource.jansi#jansi;1.4 ...
    [info] Done updating.
    [info] Set current project to play-scala (in build file:/D:/projectcase/trunk3/p
    lay-scala/)
    [info] About to create Eclipse project files for your project(s).
    [info] Updating {file:/D:/projectcase/trunk3/play-scala/}root...
    [info] Resolving com.fasterxml.jackson.datatype#jackson-datatype-jsr310;2.5.3 ..
    [info] Resolving jline#jline;2.12.1 ...
    [info] Done updating.
    [info] Successfully created Eclipse project files for project(s):
    [info] play-scala
    
  2. 打開 Eclipse ,以 Import Existing Project 的方式,將 play-scala import 到 workspace 中

  3. 在剛剛的「命令提示字元」裡,切換到 scala-play 的目錄,然後鍵入指令 activator run ,就能啟動 play framework web server
    ```
    D:\projectcase\trunk3\play-scala>activator run
    [info] Loading global plugins from C:\Users{user.home}.sbt\0.13\plugins
    [info] Updating {file:/C:/Users/{user.home}/.sbt/0.13/plugins/}global-plugins...
    [info] Resolving org.scala-sbt.ivy#ivy;2.3.0-sbt-fccfbd44c9f64523b61398a0155784d
    [info] Resolving org.fusesource.jansi#jansi;1.4 ...
    [info] Done updating.
    [info] Loading project definition from D:\projectcase\trunk3\play-scala\pr
    oject
    [info] Updating {file:/D:/projectcase/trunk3/play-scala/project/}play-scal
    a-intro-build...
    [info] Resolving org.scala-sbt.ivy#ivy;2.3.0-sbt-fccfbd44c9f64523b61398a0155784d
    [info] Resolving org.fusesource.jansi#jansi;1.4 ...
    [info] Done updating.
    [info] Set current project to play-scala (in build file:/D:/projectcase/tr
    unk3/play-scala/)

--- (Running the application, auto-reloading is enabled) ---

[info] p.a.l.c.ActorSystemProvider - Starting application default Akka system: a
pplication
[info] p.c.s.NettyServer$ - Listening for HTTP on /0:0:0:0:0:0:0:0:9000

(Server started, use Ctrl+D to stop and go back to the console...)
```

  1. 瀏覽器瀏覽網頁 http://localhost:9000/ 就可以看到 play framework 的測試網頁