l
顯示具有 Scrum 標籤的文章。 顯示所有文章
顯示具有 Scrum 標籤的文章。 顯示所有文章

2022年2月11日 星期五

愛上Mob Programming之突破瓶頸篇

Jan. 11 03:22~04:55

▲圖1:Pitest產生的涵蓋率報表

 

前言

今年初開始幫ezKanban的use case tests(使用案例的測試案例)改用Given-When-Then的格式讓它更接近Living Documentation,如圖2。改完之後發現use case tests與Aggregate Root測試案例(單元測試)有許多重疊的現象。因為ezKanban的所有Aggregate Root都包含了合約(Contracts),在程式執行期間會自動驗證程式正確性,因此Teddy就在想「是不是可以透過Specification by Example方式所撰寫的驗收案例,加上幫Aggregate撰寫合約,來省略entity layer的單元測試」。


▲圖2:加上Given-When-Then的測試案例

 

如果這個想法成立,就可以在確保程式正確性的前提之下少寫很多單元測試 。問題是怎麼知道拿掉entity layer的單元測試只要有Aggregate Root的合約依然可以確保程式正確性呢?軟體測試中有一種叫做Mutation testing(變異測試)的方法可以回答這個問題。

 

***

驗證關卡1

有兩位非常優秀的ezKanban的成員負責驗證這個想法,這個題目並成為其中一位的碩士論文。他們找到Pitest這個Mutation testing工具,但是使用在ezKanban的時候遇到問題一直無法解決。因為這是個最新冒出來的題目,所以還沒有機會在ezKanban團隊的mobbing活動中一起處理,這兩位成員是利用mobbing以外的時間去嘗試解決。

昨天和ezKanban團隊mobbing,上午把這幾周以來一直在處裡的持續整合工作告一段落。盤點一下手邊的工作,團隊決定一起看看Pitest的問題。團隊手邊有一個測試用的小專案,可以正常執行Pitest,但是當團隊在ezKanban的專案中執行Pitest卻會出現如圖3的不明錯誤訊息。


▲圖3:Pitest錯誤不明訊息

 

由於團隊是透過maven去執行Pitest,因此大家懷疑是不是maven專案的pom.xml檔案設定有問題。於是團隊試著修改pom.xml檔案但問題還是沒解決。後來Teddy想到,既然有一個可以正常執行的專案,那乾脆把ezKanban的程式碼複製到這個專案中看看能不能執行,這樣子就可以確定到底是ezKanban程式碼導致Pitest執行失敗,還是因為maven設定的問題。

將ezKanban程式碼複製過去之後可以正常執行Pitest,於是團隊試著比較兩個專案的pom.xml的差異。大家看來看去也看不出來到底是哪裡有問題,索性將兩個檔案文字比對,如圖四)。

 


▲圖4:比對兩個專案的pom.xml差異

 

發現原來ezKanban使用JUnit 5的artifactId是junit-jupiter-api,如下:

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.8.2</version>
</dependency>

 

而Pitest只支援JUnit 4,但有鄉民幫它加工之後讓它可以在Junit 5執行,但是此時artifactId要改成junit-jupiter。

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>

 

改用正確的依賴之後,Pitest就可以產生如圖1的報表。

***

 

驗證關卡2

ezKanban系統由若干的maven專案所構成,一開始團隊使用DDDCore這個相依性最簡單,只包含Clean Architecture的Entities Layer與Use Cases Layer,沒有使用到SpringBoot與資料庫的專案來測試Pitest。測試成功之後改用Account專案,這個專案除了包含Clean Architecture中的完整四個Layers,除了使用到SpringBoot與資料庫,還用到Java 17最新的預覽功能,例如Pattern Matching for Switch。

執行Pitest之後出現圖5所示的錯誤訊息:


▲圖5:Pitest無法辨認byte code格式

 

很簡單啊,就是執行Pitest的時候加上—enable-preview參數就好了啊。問題是,要加在哪裡?試了幾種方式,後來有團隊成員找到正確的格式,如圖6所示。


▲圖6:加上—enable-preview參數讓Pittest支援Java 17預覽功能

 

***

打破個人的瓶頸

瓶頸就是系統中生產力最弱的環節,每一個人都有自己擅長的地方,也有自己鬼遮眼的時候。軟體開發是一個動態的系統,採用傳統的單人開發模式(solo programming),每位開發人員同時各自開工,看似生產效率很高,但事實上很可能這些各自執行的thread經常處於block(卡住)狀態。

Pair programming可以稍微改善這種情況,但兩個人一組還是比不上全部的人一組。你可能會說:「全部的人一組還是會有盲點啊,可能這個鬼很厲害,把全部的人的眼睛都遮住了。」沒錯,可能會這樣。但從Boundary(邊界)的角度來看,整個團隊一起開發已經是這個團隊能力範圍內最大的「邊界」,也就是他們已經同時間盡其所能的一起合作解決問題。如果這個「鬼」那麼厲害能夠遮住全部人的眼睛,你派一個人或是兩個人去對付這個鬼,更加無法打敗它。

 

***

 

友藏內心獨白:團隊一起處裡有價值的工作。

2021年9月15日 星期三

成本與價值

September 15 18:36~19:02

▲ezKanban 團隊mobbing實況


學員:如何讓整個團隊,包含剛進來的新人,都可以學會用DDD(領域驅動設計)開發軟體?

Teddy:我有一個很簡單且有效的方法,但這個方法就算你知道了你們公司應該也不會採用。

學員:什麼方法?

Teddy:Mobbing,又稱為Mob Programming,整個團隊,包含測試、UI/UX與Product Owner,一起開發軟體。

學員:類似Pair Programming嗎?

Teddy:對,不過是Pair Programming的加強版,不只是兩個人一起開發,而是整個團隊。

學員:這樣的確是很難在公司推行,Pair Programming老闆都覺得成本太高

Teddy:那你們都怎麼帶新人?

學員:我們會指派一位導師帶著新人做一陣子。

Teddy:然後呢?是不是一、兩個禮拜之後就讓新人單飛,然後每天問他進度?

學員:(苦笑)沒有這麼慘啦,有問題還是會回答。

Teddy:軟體開發的成本,其實很難量化。老闆通常只看到「開發人員」的成本,因為這是最直接的成本。但除了直接寫code以外,其他的成本呢?

Teddy:你要不要Code Review?有bug要不要改?要改多久?做出來的東西客戶不要怎麼辦?舊員工離職新員工交接怎麼辦?軟體搞到變成硬體,改不動也沒人敢改怎麼辦?後端、前端、內人、外人互相等對方工作完成怎麼辦?需求不清楚開發人員亂寫怎麼辦?測試團隊自創需求,胡亂回報issues怎麼辦?

Teddy:從精實開發的角度來看,這些都是浪費。很多的等待(延遲)、重工、半成品、過度生產、交接、缺陷、工作切換、重複學習。我不敢說Mobbing可以完全消除這七種浪費,但以我的經驗,這種「看起來成本太高」的開發模式反而能夠消除浪費而降低成本並提高產品的品質與價值。

Teddy:老闆覺得開發成本太高,會不會是因為自身的產品在市場上的價值太低,或是想要犧牲品質來拉低成本,所以任何提高品質的活動都會被認為是增加成本。不管如何,這有可能是對於自己產品的定位不同,產生的價值觀落差。

***

沒有銀子彈,但是有高科技武器跟二戰時的武器之分。

***

友藏內心獨白:知道了也做不到。

2020年8月21日 星期五

三種團隊互動模式

August 21 18:15~19:01


前言

Teddy跟著ezKanban團隊兩年的時間,帶著幾位北科資工研究生開發ezKanban系統。當初是以DDD與Clean Architecture為研究主題當作切入點,這兩年來雖然有點進度,但軟體本身卻還沒達到Teddy認為可釋出的標準。

這個兩年的lead time真的有點長,今年七月初放暑假時,Teddy決定利用暑假時間和ezKanban團隊採用remote mobbing的方式一起開發。學生在學校實驗室,Teddy在家裡,透過Skype分享桌面的方式開發ezKanban,一個多月下來頗有進展。

***

幾個禮拜前在Amazon亂買書,買了一本《Team Topologies: Organizing Business and Technology Teams for Fast Flow》,有一天晚上睡不著翻了一下,沒想到還挺有趣的。書中提到四種團隊型態以及三種互動模式,特別適合軟體開發公司。今天用Teddy這兩年來和ezKanban團隊的合作模式,解釋書中提到的三種互動模式。

***

X-as-a-Service

將另一個團隊視為一種服務來使用,團隊之間只有最少的協作。這種情況發生在學生遇到問題詢問Teddy的時候,此時Teddy-as-a-Service,提供學生某種解答,這個過程中雙方並沒有很多協作關係。

***

Facilitating

協助另一個團隊釐清阻礙,這種情況發生在兩周一次的sprint review。Teddy會看學生的設計與程式碼,觀察有沒有什麼設計問題是學生沒有看出來的,並與他們討論並訂定後續修正計畫。下個sprint review會繼續相同步驟,經過迭代的過層,系統設計品質越來越好。

但是,因為兩周review一次兩小時,說真的能夠看到的程式碼真的不多,因此每個迭代的增量幅度相對來講就比較有限。另外一個問題是,因為學生還在學習的過程,很多Teddy沒有看到的地方,雖然程式可以動,但設計通常都存在一些大大小小的問題,長期而言阻礙系統的可維護性。

***

Collaboration

兩個團隊彼此緊密合作。在今年暑假之前,Teddy和ezKanban團隊的關係幾乎不存在Collaboration(協作)。之前也幾度思考過是不是跟學生一起寫程式,但又擔心如此一來學生偷懶,過於依賴Teddy,搞到後來變成Teddy幫他們做碩士論文研究 Orz,因此就作罷。

但隨著ezKanban慢慢成形,但又無法達到Teddy心中的釋出要求,有種恨鐵不成鋼的遺憾。幾經思考,加上今年因為因為疫情的緣故,泰迪軟體生意比較清淡,Teddy空閒時間也比較多,因此決定「撩落去」,利用暑假時間一起合作開發。

***

成本不同

這三種互動模式,適合解決的問題不同,成本也不同。對Teddy而言,開發軟體如果可以和團隊緊密合作當然是效果最好的。畢竟Teddy也比學生多活了20幾年,還是比他們更能夠看出設計不合適之處。

除了學生獲益,Teddy也從這個過程中獲得很多design bad smells的寶貴範例,平常可能想破頭都不一定生的出來這些例子。這是一個雙方都互相學習的過程。

很多時候,想要成事,還是需要走到前線,親自動手。

***

友藏內心獨白:If you stop coding, you stop learning, by Kent Beck.

2020年6月20日 星期六

為什麼不反駁?

June 01 09:20~10:26

▲學生發問的問題,圖由學生所繪製


好問題

Teddy這學期在北科教軟體架構課程,設計一個專案給學生練習,題目是:「用DDD + Clean Architecture + TDD,開發看板系統的後端。」這禮拜四在北科上課,學生DD問:「Calculate cycle time這個Command要傳送給哪一個Aggregate?還是應該把這個Command實作成一個Application service?」

由於這整學期Teddy都在教學生如何把Event Storming的產出透過一致性、固定的步驟,在套用Clean Architecture的前提之下,採用TDD方式將設計轉成程式碼,以達到Ubiquitous Language in Code的目的。因此當學生認為他們找不到合適的Aggregate來接收Command,Teddy直覺反應就是:「因為這個Aggregate還沒有存在你們的domain model裡面,是你們還沒開始找,而不是沒有合適的Aggregate。

後來Teddy詢問每一組,得到的回答大都是「沒有合適的Aggregate,直接把這個Command做成Application service。」只有一組將這個Command送給Workflow Aggregate,但Teddy覺得送給Workflow並不合適,因為Workflow沒有Card移動的資料,無法計算cycle time。

***

公堂之上大膽假設

最後Teddy提議增加Cycle Time Calculator這個Class,由它負責計算cycle time,並寫了一段程式碼給學生參考。

Teddy:Cycle Time Calculator是一個沒有狀態的service類別,service有兩種:domain service與application service,它應該屬於domain service,放在clean architecture的entity層。

學生DD:可是老師你說接收Command的對象是Aggregate,而Aggregate是有ID與狀態的類別。但是Cycle Time Calculator是service,它並沒有狀態,這樣不是違反了之前design level event storming的規範?

討論到這裡Teddy不得不稱讚一下這位同學,因為這個問題Teddy之前也沒想過…

Teddy:將design level event storming轉成clean architecture的程式碼的方法是我們自己定義的,我們可以加上一個規則「Aggregate與Service都可以接受Command」。

這種說法感覺有點硬坳,但乍看之下也還說得過去。

***

忙到忘記

回家之後過了一會Teddy才想起來:「這個問題之前和ezKanban團隊開會時曾經討論過!」當時Teddy告訴團隊:「計算cycle time是在Reporting bounded context,它不是看板系統的core domain。因為它是產生報表的domain,是唯讀的,所以我們不一定要套用DDD或是OOAD的方式來建這個reporting domain,也許可以用transaction script就可以產生報表。

但後來Teddy沒有進一步與ezKanban團隊review他們實作reporting domain的程式碼,所以細節上他們到底如何實作Teddy也不知道。

***

討論無身分高低

在這禮拜四上課時Teddy曾詢問ezKanban的人如何實作Calculate cycle time?只得到「設計成service」的答案。後來Teddy發表一堆「公堂之上大膽假設」的言論,ezKanban的人也沒跳出來 打槍 提醒Teddy,這個問題之前曾經討論過。

可能學生預設認為上課只是來聽老師開講,把所謂的「正確答案」記下來就好,不要質疑老師,也儘量不要跟老師對上眼、說上話。

但Teddy的課程不一樣,第一個禮拜上課Teddy就告訴學生:「叫我Teddy就好,不用叫我老師。別的課我不知道,但在我的課堂上我們的關係是平等的,不是上下階級。我只是在課題上扮演老師的角色,你們扮演學生的角色,僅此而已。修這門課我會問很多問題,你要願意與我互動,再來修這門課,不然就請退選。

▲課堂上老師與學生的關係是A還是B?


雖然第一周上課Teddy就把話說得很清楚,但學生心裡還是千百個不願意,可能還是怕被老師擺一道,萬一多說話得罪「方丈」日子就不好過了。但專業討論不應有身分高低,如果學生心中有看法,但礙於身分不敢說,這其實是陷老師於不義,阻礙了課堂上探索知識的機會

***

反思

敏捷開發強調要透明,唯有透明,探索調適才可能發生作用。很顯然Teddy與學生之間的互信可能還不夠,導致學生有看法不好意思公開表達。

不過,學生當下沒提出來也不能排除另一個原因,就是學生自己也忘了,根本沒想那麼多。

***

友藏內心獨白:腦補得太厲害。

2020年5月13日 星期三

學習總在下課後

May 13 18:11~18:59

▲別人的水總是比較甜,江山易改,喵性難移。


行為是否改變

成立泰迪軟體這幾年,遇到企業內訓課程,有些HR問Teddy:「能不能幫忙在課堂上看看誰比較認真,或是出考卷作為訓練成果評量,這樣學生才比較會專心上課。」

這些事當然都可以配合,但我總是跟對方說:「我覺得最好的評量就是同仁上完課之後行為有沒有改變,考試、打上課成績,頂多就是因應公司規定滿足交差的形式要求。」

上完課之後行為有沒有改變,是一件需要後續追蹤的工作,也是一件耗費時間與金錢的工作,絕大多數的公司都覺得:「公司已經出錢辦教育訓練,上完課之後同仁應該就具備那種能力才對。」

除非課程內容難易度不高,否則要求學員上完課之後立刻變成高手是不太可能的事情。不可諱言,有些天賦異稟或是努力很久終於時機成熟的同仁可以在上課當下「開悟」,課程結束之後行為為隨之改變,但大部分的同仁可以藉由上課「獲取新知」就已經很不容易了,要求他們上完課後立刻可以排除萬難做出有意義且持久的改變,實屬不易。就好像看了場精采的電影,觀眾(同仁)在心中對劇情與演員的表現留下深刻印象。但要讓觀眾看完電影之後就變身為導演,可以開工拍戲,那還需要長時間的努力。

下課之後回到工作上,面對的又是現實問題,被一大堆代辦事項追著跑,如果沒有外力協助,光靠員工自己很難有辦法靜下來思考如何改善。與其花錢辦大量的訓練課程,還不如思考是否有可能把部分上課費用拿來找顧問、教練,在課程結束之後和團隊一起,協助團隊改變行為,並且將改變後的行為固定下來,變成新的工作方式

***

終身學習

奧修在《草木自己生長》提到:「知識是借來的,而學習是你自己的;知識是透過文字、語言、和觀念,而學習是透過經驗;知識總是一個結束,你知道了它,它就結束了;學習永遠沒有結束,它總是在途中;學習是一個過程…」

上課可以獲得知識(收集名詞),但學習必須靠自己,它是一個終身的過程。很多教育訓練成效不彰,因為來上課的人頂多只想獲得(收集)知識,而不想學習。教的人也只是講述知識,沒有鼓勵學習。

Teddy相信:「學習在下課之後才真正開始。」所以教學的主要目的,應該是讓學習者具備下課後持續學習的能力。為了達到這個能力,需要介紹基本的領域知識以及設計適合的體驗活動,讓學習者在一個比較輕鬆的情境下獲得這些知識與體驗。

***

友藏內心獨白:學習是軟體開發的瓶頸。

2020年5月12日 星期二

等一個人春天

May 12 14:25~15:50

▲浪浪也會自己生長。


緣起

Domain-Driven Design: Tacking Complexity in the Heart of Software》這本書出版於2004年,當時Teddy正在念博士班,忙著準備資格考與論文,根本不知道有這本書。後來好像曾經聽過DDD這個名詞,當時自己一直把它腦補成MDA(Model-Driven Architecture)。因為自己對MDA沒什麼好感,當然對DDD也就沒興趣 Orz。

***

一面之緣

2013年,在這本書出版9年之後,Teddy忘了在什麼機緣之下買了它。翻了翻書的內容,覺得:

  • Model-Driven Design和以前學過的OOAD(物件導向分析與設計)建domain model的內容大同小異。
  • Ubiquitous Language是一個新名詞,但是它目的和Alexander的Pattern Language很像—A common ground for communication,而且比Pattern Language還要簡單。

以上這兩個模式(Patterns)算是DDD的核心,先被Teddy給「鄙視」一番。繼續往下看,覺得比較「有用」的模式是:

  • Aggregate,將一群緊密相依的物件放在一起,這是一種人為的模組化單位,可以彌補一般程式語言在Package與Class之間的空白。
  • Context Map,表達bounded context之間的關係。

然後呢?就沒有然後了,書就被Teddy丟在一邊。

***

再續前緣

三年前指導教授想把他手邊的軟體架構這門課交給Teddy來教,Teddy參考了近10本軟體架構的書,最後選了當時剛出版的《Clean Architecture: A Craftsman's Guide to Software Structure and Design》。教軟體架構和DDD原本沒什麼直接的關係,因為實作Clean Architecture核心層(Entity Layer)需要建立domain model,而Teddy又不想只是使用原本OOAD的方法,想起DDD關於建立domain model的一些設計模式,於是又回頭探索DDD。

又過了一年,有一天Teddy在YouTube聽一個DDD演講,內容和講者是誰已經忘了,但是聽到一句ubiquitous language in code,好像被雷打到一樣,突然醒過來。這種感覺,就好像當年六祖慧能聽到金剛經的「應無所住而生其心」一樣,當下頓悟XD。

Alexander的pattern language使用對象是,人用它來設計住宅以及都市規劃。如果將pattern language應用在軟體開發上,則可以想像成套用了一群(數個)設計模式來解決一個大的設計問題,這也是原本Teddy對於ubiquitous language的看法。

但是,ubiquitous language不只是這樣。DDD的Model-Driven Design與Ubiquitous Language這兩個模式是一體兩面,如果只把它們應用在「概念層次」,只用來作為領域專家與開發團隊溝通的工具,那就只發揮了DDD一半的功力。還有另一半,而且是打通任督二脈的另一半,就是要將Ubiquitous Language表達在程式碼裡面。所以光是只談ubiquitous language還不夠,加上in code,才是畫龍點睛,才是幫佛像開光。

***

自然生長

Ubiquitous language in code,同樣一句話,當時的Teddy聽了有感覺,換成別人就不一定。就算是Teddy本人,如果早個幾年聽到這句話,也不一定有感覺。

奧修在《草木自己生長:禪的真隨》引用禪師齊內林的話:「靜靜地坐著,什麼事都不做,當春天來臨,草木就自己生長。」雖說「什麼事都不做」,實際上並不是「什麼事都不做」。而是以平常心,認真去做好每一件該做的事情

等到時機成熟,春天到來,草木自然生長。

***

友藏內心獨白:不能揠苗助長啊。

2020年5月4日 星期一

變成一個點

May 04 09:52~11:19

▲學習的過程就是填滿圖形。


加法

老子說:「為學日益」。學習者,心中有一個學習的標的物(目標),例如設計模式、敏捷開發、軟體架構、人工智慧、大數據、領域驅動開發、測試驅動開發等。

這個目標,在學習者的心中形成某種形狀form),它可能長得像圓形、三角形、不規則圖形。這個形狀的邊界(boundary)界定了學習者的守備範圍,邊界以內屬於學習內容,邊界以外屬於脈絡、背景知識(context)。隨著學習進程,範圍可能會改變,但它總是一個有邊界的形狀,不管這個形狀長得像什麼圖形。

這個形狀一開始是空的,因為學習者還沒學會所需的知識。他藉由讀書、上課、討論、Google、練習、參加社群聚會、模仿、實作等方式,充實自己,填滿這個圖形。

***

智光忽明忽滅

▲從某個角度來看,形狀好像已經填滿了。

在某些片刻,學習者一度以為自己已經完全掌握學習內容,他可以正確回答許多(特定)問題,相當於考試獲得100分的喜悅。他自得意滿地認為,形狀好像已經填滿了。

***

▲換個角度才發現空白處還很多。

但換個角度、換個環境、換個題目、換個發問方式、換個時間、換個專案、換個公司,此時才發現原來形狀之中空白之處還很多,還需要精進學習。

***

▲總是還有填不滿的空隙。

有一天,這位學習者越來越博學,領域知識的名詞幾乎都已經收集得差不多了,如果參加全國性考試一定可以得高分。但是,形狀還沒填滿,還是有一些空隙。

***

變成厲害的人

敏捷宣言說:

藉著親自協助他人進行軟體開發,
我們正致力於發掘更優良的軟體開發方法。

(We are uncovering better ways of developing
software by doing it and helping others do it.)

學習者自己變得厲害只是過程中的一個階段,他還需要練習幫助別人,讓別人在他的幫助之下,有能力完成原本認為很困難無法做到的事情,成為Kent Beck所說的那種「厲害的人」。

▲到了這個時候,形狀已經填滿。

***

減法

▲Quality without a name,特質本身非常具體,變成一個點。它沒有面積,不再是形狀。

老子的道德經在「為學日益」之後還有幾句:「為道日損,損之又損,以至於無為,無為而無不為。」知識的累積,越來越多,就算此時自己覺得已經「收穫滿滿」,但這個收穫滿滿轉眼間又變成空。因為環境改變、領域改變、競爭者改變、專案改變、團隊改變、慾望改變,你滿別人比你更滿,不滿之心因而升起。

心永遠靜不下來。

Alexander在《Timeless Way of Building》書中提到學習模式(pattern)的過程也是如此,透過學習模式來重拾人們設計與建造建築的能力。但這不是終點,不是目的。透過這個過程,喚回人原有之本性、本能。之後,這些模式都要忘記。

金剛經云:「知我說法,如筏喻者,法尚應捨,何況非法。」聽佛說法(學習pattern),是為了開悟(追求quality)。有了quality之後,那些names、那些patterns,就可以捨棄了。

***

友藏內心獨白:試求未開悟前之心理陰影面積。

2020年4月27日 星期一

怎麼當好一個ScrumMaster?

April 27 12:46~14:15


演給你看不好嗎?

接觸過Scrum鄉民應該都會同意,Scrum的三個角色:Product Owner、Development Team與ScrumMaster,其中ScrumMaste是最抽象、虛無飄渺的存在,最不容易了解,也最難扮演好這個角色。

曾經有幾位客戶要求Teddy到他們家去充當短期的ScrumMaster。這是一個很合理的速成方法,如果請有經驗的人來當ScrumMaster,團隊的新手ScrumMaster就有一個「具體的範本」可以參考。日後只要依樣畫葫蘆照著做,應該八九不離十差不到哪裡去。

但就算是在缺少業績的情況下,Teddy從來沒有答應過客戶去當短期的ScrumMaster。Teddy可以當敏捷顧問、敏捷教練、碎碎念講師(看你喜歡哪個稱呼),陪著PO、團隊與ScrumMaster一起成長,但無法擔任團隊的短期ScrumMaster。

為什麼?因為Teddy始終是個外人。ScrumMaster與Product Owner和Development Team之間是一種很緊密的團隊合作關係,唯有長期承諾,讓整個團隊知道「你是在玩真的」,這種關係才會是完整的。外在環境、專案特性、團隊成員等不斷地變化,沒有固定的公式可以遵循,很能靠一個外人「演給你看」就可以了解箇中精隨。

ScrumMaster必須現時現地去體驗各種作用力、各種限制、各種壓力、各種機會,並且不斷地嘗試、調整。只是短時間加入團隊的「外派」ScrumMaster頂多在敏捷形式提供團隊參考,但這種參考非常片面,也很容易讓人誤解。

***

動輒得咎

書上說,ScrumMaster要協助團隊排除阻礙,因此有些ScrumMaster從這一點著手,最後變成團隊有任何問題都找ScrumMaster來處理,團隊變成了媽寶,而ScrumMaster變成了寶媽

書上又說,ScrumMaster採取僕人式領導(Servant-Leadership),從這一點出發,有些ScrumMaster最後成為團隊的僕人,負責幫團隊訂會議室、安排議程、寄發會議通知、撰寫會議記錄、更新Scrum Board,以及催大家準時參加Scrum會議。僕人易做,領導難行。

也有人覺得引導技能很重要,ScrumMaster要引導團隊發現自身的問題,而不是跳下去幫團隊解決問題。再加上Scrum團隊是自組織團隊,應該有能力能夠從失敗中學習,逐漸改善。因此,當團隊成員向ScrumMaster求助時,ScrumMaster總是說:「由團隊決定」,弄到最後讓團隊成員覺得ScrumMaster的存在本身變成了一種阻礙。

***

云何應住?

依據Teddy的理解,ScrumMaster之所以存在,他要解決的問題是:「如何讓Development Team、Product Owner與組織獲得Scrum的好處?」可以從這個角度切入,來思考要怎麼做好ScrumMaster。

金剛經裡面有一段話:

「菩薩於法,應無所住,行於布施,所謂不住色布施,不住聲香味觸法布施。須菩提!菩薩應如是布施,不住於相。何以故?若菩薩不住相布施,其福德不可思量。」

把「菩薩」換成ScrumMaster,就可以知道ScrumMaster要怎麼做。

ScrumMaster依據敏捷精神,無須拘泥一定的形式與方法,只求能夠幫助開發團隊、PO與組織。不需拘泥教練、僕人領導、流程專家、干擾屏蔽、阻礙排除、變革代理。ScrumMaster要專注在協助開發團隊、PO與組織獲得敏捷的好處,不拘泥於特定形式,如此便可產生有利的效果。

有些ScrumMaster很認真,為了做好自己的工作,上了很多課。但回到團隊之後,如果做得好,他變成了一個教練、一個僕人式領導者、一個流程專家、一個保護者、一個石頭搬運者、一個敏捷轉型策略大師。做不好,他成為沒打過棒球的棒球教練、任勞任怨的僕人、技術控、太極高手(推拖工作)、吵架王、嘴砲王。

他已經不是ScrumMaster,他被切割成好幾塊

***

無為而無不為

扯了這麼多,到底ScrumMaster要怎麼做?很簡單,在敏捷精神之下,該做什麼,就做什麼。做了之後有幫助,就持續下去。沒有幫助,思考如何改善,不斷精進。

這個過程很漫長、很痛苦,因為現實世界很危險,你要靜心,忍得住孤獨、寂寞、羞辱。你可能需要一位師父、前輩、長者,與你同在,支持你走完這個過程。

最後,你渡過河,到達敏捷的彼岸,你有能力幫助其他ScrumMaster繼續他們的旅程。

***

友藏內心獨白:是在找聖人逆!

2020年4月20日 星期一

毛書一刀未剪大公開

April 20 11:28~12:45


Teddy在2012與2014年所出版的兩本書《笑談軟體工程:敏捷開發法的逆襲》與《笑談軟體工程:例外處理設計的逆襲》已經絕版一陣子了。上個周末上【Scrum敏捷方法實作班】,有學員知道書已絕版,詢問Teddy是否能提供第一本書的電子檔?Teddy也忘了之前有沒有公開提供過,所以今天就寫一篇文章把這兩本書的電子檔公開。

因為書本最後出版的格式經過悅知出版社編輯過,這個「排版編輯」版權屬於出版社,所以Teddy只能公開當初提供給出版社的原稿。編輯前的原稿與最後出版的內容略有差異,且可能有一些尚未訂正的錯字,請讀者自行除錯。

電子檔下載:

***

友藏內心獨白:紙本的比較香。

2020年4月19日 星期日

塞翁失馬

April 19 20:37~21:28


也是疫情受害者

這兩天(4/18~19)是第32梯次【Scrum敏捷方法實作班】上課日,這梯次課程很早就確定開課,但因為前一陣子境外移入的新冠肺炎案例大增,陸續有學員取消報名,最後上課學員只剩下七位,剛好湊成一組。

原本課程最低開課人數是10人,因為目前處於疫情的特殊狀況,Teddy也沒有取消該梯次。疫情期間人少一點也好,雖然收入變少免不了有點小失望,但加減賺,至少可以付房租。

***

趁亂做實驗?

Scrum課程有一個練習活動,讓學員透過User Story Mapping(使用者故事地圖;USM)作為敏捷需求管理工具。上課前一天(禮拜五)Teddy想:「既然這次只有一組,練習活動是不是可以做一些調整,試看看改用Event Storming Workshop(事件風暴工作坊)來收集需求的效果?」。

想了一天,覺得自己沒有把握在短時間的練習活動中可以讓Event Storming Workshop達到原本USM的效果,於是決定還是先維持原本的練習活動。

昨天上了一天課,因為只有一組,Teddy反而有更多的時間與學員討論(WIP=1),講得話比往常都還要多。今天(禮拜日)早上起床,邊吃早餐邊打開電視聽新聞。突然間,不知怎麼的靈光乍現,有點想通了Event Storming Workshop與USM的差別,以及兩種方法個別合適的應用情境。

雖然在Event Storming發明人Alberto Brandolini的書中提過這個問題,但讀書的當下Teddy並沒有特別深刻的領悟。也許是緣分到了,經過一段時間的醞釀,突然有點感覺了。

***

上了台就不要想賺多少錢

Teddy在吳宗憲的綜藝節目中聽憲哥說過一句話:「上了台就不要想賺多少錢」。言下之意是說,不管此次的收入多少,身為一個藝人上台之後就是要拿出最好的表演。

***

如果不是疫情,最後報名人數只夠湊一組,人數不足是不會開課的。

如果Teddy抱持著:「只有七個人,那就不用特別準備,照以往的方式上課就好。」這兩天也就這麼過去了,也不可能有今天關於USM與Event Storming Workshop的小小突破。

所以說,認真把事情做好,其他事情就交給老天爺吧。

***

友藏內心獨白:活在當下。

2020年3月11日 星期三

可是誤一生

March 11 12:36~13:47

▲Ada:我有問題!


可是思維

成立泰迪軟體這些年,教過的學員也有數幾千人次。Teddy很歡迎學員發問,從問題中可以了解學員的困難以及學習狀況,也可以檢驗自己的知識是否足以回答問題,並刺激自己思考的角度。

但有一種學員的反應讓Teddy很無言,Teddy稱之為可是學員,他們總是在聽了你的建議之後,經常使用可是作為拒絕改變的藉口。

***

可是學員:我們軟體的bug很多,有沒有什麼做法可以改善這個問題?

Teddy:你們有寫單元測試嗎?

可是學員:沒有。

Teddy:是不是可以考慮先從寫單元測試開始,至少可以確定基本軟體元件的正確性。

可是學員:可是我們工程師都沒時間啊,程式就寫不完了不可能要求他們寫單元測試。而且他們也不知道怎麼寫,專案時程那麼趕也沒時間讓他們學。要讓他們寫單元測試這不可能啦。

Teddy:Code review呢?

可是學員:可是我們工程師程度都不好,沒有能力review別人的程式。

Teddy:難道都沒有資深工程師嗎?

可是學員:是有幾位資深工程師,可是他們覺得code review很浪費時間,沒人想做。

Teddy:是不是可以跟團隊成員溝通,透過code review可以協助資淺人員能力成長,改善產品品質,提升整個團隊的能力?

可是學員:可是公司也不想浪費資深人員的時間,畢竟他們的薪水比較高。公司希望他們專心開發核心程式,而不是花時間去幫其他人做code review。

Teddy內心獨白: (我的棍子放在哪裡!)

Teddy:有試過Pair Programming嗎?

可是學員:我在社群活動中有聽過Pair Programming介紹,可是公司一定不會同意。專案那麼趕怎麼可能讓兩個人一起寫程式,這不可能,打死都不可能。

Teddy:那……找QA或工讀生,用人工測試呢?

可是學員:可是公司根本沒有QA部門,也不可能撥預算找工讀生來測試。

Teddy:那還有一招,外包給客戶,請客戶幫你們測了

可是學員:我們現在就是這樣啊。

***

挑戰現況

凡事把可是兩字掛在嘴邊,很可能是一種不思改變只想找藉口拒絕改變的反射性動作。如果只是朋友之間互相訴苦,並不是真的想解決問題,那倒也無妨。但若是工作上遇到問題也抱持著這種心態,就無法突破現況並有所改善。

軟體工程,特別是敏捷實務做法,並不是什麼艱深理論,都是經過多年、多人、多團隊、多公司的實務經驗。也許這些經驗與你自己目前狀況不符,但也不要立刻否定,先把它當成一種假設,然後思考要做出何種改變、要如何努力,才有可能讓假設成真。

學員:我們軟體的bug很多,有沒有什麼做法可以改善這個問題?

Teddy:你們有寫單元測試嗎?

學員:沒有。

Teddy:是不是可以考慮先從寫單元測試開始,至少可以確定基本軟體元件的正確性。

學員:我們工程師都忙到沒時間,程式寫不完了要如何讓他們願意寫單元測試?

Teddy:你們應該是把寫production code和test code 看作是兩件事,而工作上只有要求完成production code即可,才會有這種「程式都寫不完了哪有時間寫測試」的想法。

學員:對啊,不都是這樣嗎?

Teddy:我認為單元測試是開發不可分割的一部分,所以做完的定義不是只有production code寫好就可以,應該也要包含足夠的單元測試。這在敏捷開發(Scrum)裡面叫做DoD—Definition of Done。藉由調整DoD(逐步增強),可以改善團隊的產品品質。

學員:聽起來滿有趣的,但我們團隊目前都沒有這樣的觀念,還是停留在犧牲品質以便趕上進度的狀況。短期間或許可以交差,但是對公司來說中長期發展會受到傷害。像最近客戶對於品質不良的抱怨聲音就很大,而且團隊成員工作也沒有成就感,流動率很高。

Teddy:解決方法不一定只有或只是單元測試,還有很多種解決方案,依據你們專案的情境(Context)可以選擇不同的方式。

學員:我回去跟我老闆討論一下,看看有沒有可能找一個新的小專案來試看看,做出一些改變。

***

想解決問題但卻不想做出任何改變,只想從別人口中聽到「你好辛苦」、「你好委屈」、「你好棒棒」、「公司好爛」、「同事好混」這類的話,那還是不要開口問Teddy問題好了。

***

友藏內心獨白:這樣不就不溫柔了XD。

2019年12月7日 星期六

感受作用力

Dec. 07 09:21~10:25

▲使用者故事對照(User Story Mapping;USM)活動


不是可不可以的問題

有一個問題每過一陣子Teddy就會被跑Scrum或Kanban的朋友被問一次:「可不可以用軟體加投影機取代實體Scrum Board或是Kanban Board?

這種問題,問「可不可以」之前,應該先問「Scrum Board或Kanban Board要解決什麼問題?」,然後再問「改用電子化之後,原本要解決的問題依然持續被解決嗎?有沒有產生新的問題?」。

***

低科技,高接觸

敏捷圈有一種說法:「Low Tech, high touch. High tech, low touch」。有好幾位跑Scrum的朋友跟Teddy提過,他們從實體Scrum Board(Task Board)改用軟體加投影機之後,原本Daily Scrum每個人都投入的狀況,變成傳統會議那種大家看著投影機「假裝有在聽」別人說話,但卻少了很多之前的互動,原本Daily Scrum每天「重新計畫」的目的因而大打折扣。

但也有朋友告訴Teddy,他們花重本買了大觸控電視用來取代實體Scrum Board,效果比起投影機要好很多,接近實體Scrum Board。

感受案發現場的作用力(forces),看看解決方案有沒有平衡這些作用力,你就可以判斷目前的解決方案是否合適。

通常會想用數位工具取代實體Scrum Board或Kanban Board,不外乎:

  1. 工作環境沒有牆面可以拿來建置實體Scrum Board或Kanban Board。
  2. 不是所有人都在同一工作地點,可以直接觀看實體Scrum Board或Kanban Board。
  3. 想要保存Scrum Board或Kanban Board的歷史紀錄。

第1點,工作環境不允許應該是要「突破」的限制而不是反過來被它限制。工作場所沒有電腦怎麼辦?總不能上班的時候把程式寫在紙上,回家再輸入自己的電腦中吧!沒有電腦公司要去買啊(或是凹員工自己帶)

至於其他兩點,Teddy建議以實體Scrum Board或Kanban Board為主,在讓團隊成員或指派特定人員每日更新電子看板即可。聽起來好像很麻煩,實體與電子各有一份,還要手動維持同步。但實際上,同步的工作一天頂多也就花個10分鐘,是值得的投資。

***

感受作用力

今年11月的【Scrum敏捷方法實作班】 ,不知道是不是因為學員組成比較多元,包含專案經理、產品經理、開發人員、主管,在各項練習活動中都特別投入,效果也很好。

特別是在使用者故事對照(User Story Mapping;USM)活動中,所有人一起同步討論需求。有幾位學員跟Teddy反應,和他們以往的需求討論會議有很大的差別,不只是在形式上USM比較有趣,在實質面獲得的有用資訊量也大勝傳統方式。

但這並不能完全歸功於USM,同樣的練習活動,Teddy也遇過產出空洞使用者地圖的團隊。所以說,好的團隊成員加上用對方法,身處現場便可感受到好的力場。

這不是風水,更不是迷信。認真做事,活在當下,便可察覺到團隊的狀況。

***

友藏內心獨白:工具與方法最後都是要遺忘的東西。

2019年11月26日 星期二

透過協作產生敏捷需求

Nov. 26 17:48~18:35


不是需求

許多跑敏捷的團隊會使用user story(用戶故事、使用者故事)來表達「需求」,大家一般認為寫user story是Product Owner的責任,團隊只要照著user story所描述的內容就可以做出PO所希望的功能。

但實際上功能做好之後卻經常被PO要求改東改西,導致開發團隊抱怨:「Product Owner寫的user story太簡略,害他們不能『按圖施工,保證成功』,要不斷地重工」。PO則是不滿開發團隊都不動腦筋,遇到問題也不及時跟他溝通與釐清。

其實user story不算是傳統軟體開發所說的需求或規格,user story只是引發團隊討論需求的一句話真正的需求,透過開發團隊、Product Owner與利害關係人的對話、討論、探索而產生。討論之後所產生的需求,可以透過specification by example(實例化規格)的方式記錄下來。

另外,撰寫user story的責任也不能全部推給PO。User story的「為了…(目的)」所描述的是使用者所遭遇的問題,這是PO需要負責搞清楚的部分。而「我想要…(做什麼)這句話已經包含某種解決方案,則是需要PO與開發團隊一起討論,尋求各種可能的做法

***

心態改變

上週Teddy在上【Scrum敏捷方法實作班】介紹user story的時候跟學員提到上述觀念,下課時有一位學員說…

以前團隊在product backlog refinement workshop的時候,我們都習慣要求PO要把user story寫清楚,如果有不清楚的地方,我們會責怪PO,覺得他沒有準備好就找我們來開會。但上完課之後,我才發現原來撰寫user story的責任不能完全推給PO一個人。下次再開refinement workshop,我會改變作法,多提供意見。

***

協作遊戲

敏捷開發是一種協同合作的活動,不是傳統瀑布式開發那種「透過文件溝通」的模式,更不是找個issue tracking system(議題追蹤系統)來「開票、領票」(分派、追蹤工作)。

只是做做敏捷的樣子,心態沒變,還是白搭。

***

友藏內心獨白:讓團隊每個人都動腦真的不容易。

2019年5月28日 星期二

不要只聽半套

May 28 23:11~23:54

▲這句怎麼都沒人聽進去XDD


故事一

有一個公司派了整個團隊來泰迪軟體上Scrum敏捷方法實作班,回公司之後團隊跑了一陣子Scrum。有一天因為產品出了包,非常緊急,Product Owner希望團隊加班趕緊把這個問題解決。沒想到,團隊中有成員居然回答PO:「我們去上Teddy的課,Teddy說跑Scrum不能加班。」

公司老闆得知後非常氣憤,有一次遇到Teddy,用開玩笑的語氣說:「我員工去上你的課,回來之後都不加班了」。

這,員工不想加班就大聲說「我不想加班」,幹嘛扯到Teddy頭上哩?!Teddy上課時是說:

敏捷開發講求「穩定的開發步驟」(sustainable pace),早期XP對於穩定開發步驟有一個簡單的說法,就是每週工作四十小時。我自己還在與Scrum團隊的時候,也是儘量利用上班專心把工作完成,以不加班為原則。

假設公司因為產品出問題都火燒屁股了,作為員工此時還在「我跑敏捷我不加班」,如果Teddy是老闆,也會發火啊。古語有云:「善戰者無赫赫之功」,這也是好的敏捷團隊期望達到的狀態。但是,天有不測風雲,總是會遇到需要「江湖救急」的時候。此時願不願意跳下來解決問題,就不是敏不敏捷的問題,而是心態的問題了。

***

故事二

某PO質問Teddy:「為什麼你跟團隊成員說retrospective沒用?」聽到這樣的質問,Teddy也是滿頭黑人問號???

細問之下,原來是Teddy和團隊成員聊天時提到:

如果retrospective會議沒有訂定具體的改善執行計畫(action plan),或是改善計畫都沒有落實,相同的問題便會一再出現,導致每次retrospective都討論一樣的議題。有迭代沒有增量,久了之後團隊就會覺得retrospective沒有用。

不知道這位團隊成員是不是buffer不夠,只擷取到「retrospective沒有用」這幾個字。也未免斷章取義的太厲害了一點吧。

***

問題是自己狀況的投射

相信很多人都有這樣的經驗,聽了一場演講,或是經過一次對話,腦袋中留下來最深刻的只有「與自己現況不滿相關的記憶」。因為這些不滿的力量非常強大,強大到足以「扭曲力場」,把別人的意思曲解成自己的內心獨白,然後採用「借刀殺人」的手段,將自己一直想說卻不敢說出口的話,假借「別人的名義」說出來。

這種斷章取義、扭曲本意、沒有脈絡(context)的引用,並非全無意義。它往往透露出講話者內心真正的感受,只不過平常不敢說出來罷了。

為什麼敏捷開發的始祖XP要提「勇敢」?因為太多人不敢面對自己,不敢正視問題。真、善、美,只有真誠的表達自己的感受,改善才有可能發生。只有改善發生,才有可能逐步趨近完美。

***

友藏內心獨白:Teddy有說多讀書你怎麼都沒聽進去?!

2019年5月24日 星期五

一個Scrum各自表述

May 24 00:40~01:27

▲每個component team都在跑Scrum,啊不就好棒棒…Orz


沒事不要找Teddy聊天XD

去年在某個演講場合,演講結束後某位鄉民找Teddy聊天….

鄉民:Teddy你好,我是你部落格的忠實讀者。

Teddy:你好、你好,謝謝捧場。

Teddy:你看我的部落格,是因為你們有跑Scrum嗎?

鄉民:對,我在用戶研究團隊跑Scrum。

Teddy:喔……用戶研究團隊跑Scrum…..這麼神奇。這是什麼意思?

鄉民:就是我們團隊會在專案開始前期用迭代、增量的方式,跑幾個sprint產出用戶研究報告。

Teddy:然後把產出的報告交給開發團隊去實作?

鄉民:對。

Teddy:怎麼我聽起來好像是瀑布式開發?

鄉民:不是、不是,我們是跑Scrum。

Teddy:你們做出用戶研究報告交給開發團隊之後,需求都不會改變嗎?

鄉民:會啊。

Teddy:那之前花時間所做的用戶研究報告需要重做嗎?

鄉民:這……….

Teddy:你們就是waterfall啊。

鄉民:我們是Scrum啦……至少在公司內我們要說我們在跑Scrum。

Teddy:那你們當初為什麼想「跑Scrum」?

鄉民:因為總經理下令說要跑Scrum。

Teddy:喔,對、對。幾個月前我有看過你們公司發的新聞稿,說你們Scrum跑得很成功。


▲有功大家練,有敏大家捷。

***

高興就好

▲圖片來源在此


陳近南:反清復明 敏捷只不過是個口號,跟阿彌陀佛其實是一樣的。Waterfall一直欺壓我們公司,浪費我們的銀兩,所以我們要反Waterfall!

韋小寶:要反Waterfall搶回我們的錢,是不是?說來說去敏不敏捷根本就是脫褲子放屁!關人鳥事呀?行了,大家聰明人,了解!繼續!

陳近南:嗯。總之,如果成功的話,就有無數的銀兩,你願不願意去呀?

韋小寶:願意~!只不過你剛剛那句九死一生太嚇人了。

***

友藏內心獨白:敏捷就是專案出得去,錢進得來,公司發大財XD。


2019年5月7日 星期二

尋找第一個Pattern

May 07 14:11~15:07


很久以前有一次Teddy在某場合介紹Alexander的pattern languages,談到這個方法是一種「由上而下」的設計過程,透過一次套用一個pattern(one pattern at a time)的方式逐次展開,採用pattern為基礎的方式解決一個大問題。就好像人類使用「語言」解決問題一樣,Alexander把這種方法稱為pattern language。

聽完演講之後有一個聽眾問我:「要如何選擇最上層的第一個pattern?」當下Teddy心裡覺得:「啊不就是你書讀得少,pattern認識沒幾個,所以才不知道要如何選擇第一個pattern。」

事實上Teddy的想法並不完全正確,對方也許真的不熟pattern,但這個問題首要的重點不在於對方懂多少個pattern,而是「最上層的第一個pattern,就是你要解決的那個大問題,也就是你想要達到的目標 (goal)」。


***

設計模式的例子

 

▲Mediator範例


上周末在上【Design Patterns這樣學就會了:進階實作班】,討論到Mediator模式的時候有學員問…

學員:如果Mediator的coordinating logic太複雜,我是不是可以把 Mediator + Strategy或是Mediator + Command混和一起使用?

Teddy:你先不要把問題複雜化,想著把A模式加B模式結合起來的可能性。「理論上」很多模式可以被「一起使用」,但如果只從解決方案來看設計模式,你會有太多排列組合都可以達到「相同功能」。這樣子學習者會無所適從,不知道怎麼套用pattern解決設計問題才合適,很容易變成為了套pattern而套pattern,變成過度設計(over design)。

Teddy:你要先問自己「目前你首要想解決的設計問題是什麼?」以Mediator的例子來看,因為你想拿掉Colleague與Colleague之間多對多的相依性,所以找一個中間人來負責協調與溝通。此時此刻,根本還沒有「Mediator的coordinating logic太複雜」的問題,所以不需要討論Mediator + Strategy或是Mediator + Command的可能性。

Teddy:當你套了第一個Mediator pattern,過了一段時間後,你發現coordinating logic太複雜。這個複雜性已經強大到讓你修改coordinating logic變得很困難,你的軟體慢慢變成了硬體。此時,你再來考慮要採取什麼方式來對付這個force。

一次一個pattern,第一個pattern解決你目前首要凸顯出來的問題。套完第一個pattern之後,如果沒有其他未被處理問題,那就沒事了。如果還有(例如Mediator的coordinating logic變得太複雜),你再進一步思考要如何解決。

***

道理很簡單但你不一定能活用

幾年前有一次到客戶端幫忙看Scrum團隊運作情況,客戶覺得他們跑的卡卡的,劈哩啪啦跟Teddy描述一大堆「可疑現象」。經過Teddy實地觀察之後,發現問題的確並不單純。

要從何開始著手?如果用pattern解題的方式來思考,要先套用哪一個pattern?

Teddy發現客戶的Scrum團隊最大的問題就是他們並不是真正的跨職能團隊(cross-functional team),團隊成員主要都是程式設計師,沒有測試專長的人,也沒有UI/UX的人。上游(UI/UX)的步調搭不上下游開發團隊的步調。經常發生UI/UX自己覺得效率很好,但他們完成的工作,開發團隊可能好幾個sprint之後才會用到,甚至也有完全沒用到的時候,最後直接丟到「垃圾桶」。

伴隨著這個根本原因,團隊產生了很多病症,必且試圖用各種有創意的方式來延緩這些病症,但都無法長期維持下去。

其實這個問題很簡單,先讓自己笨一點,既然是跑Scrum,為什麼不直接聽Scrum的話,組織一個真正的cross-functional team,先傻傻套用這個pattern「試看看」。套用之後,跑一陣子,如果有其他的問題浮現,再思考要如何解決。例如,之後可能發現需求管理很困難,團隊對於產品願景與sprint目標不明確,此時再討論嘗試套用impact mapping與user story mapping的可能性,才顯得有其意義。

***

友藏內心獨白:這麼簡單的道理居然這麼久才想通啊。

2019年3月29日 星期五

Scrum讓你家庭更幸福

March 29 07:06~08:08

▲畫面節錄自維基百科


家庭也是一個團隊

昨天到信義區對一群非資訊業的美女、帥哥主管介紹敏捷精神。談到Scrum團隊cross-functional team(跨職能團隊)的時候,Teddy開玩笑說…

Teddy:很多人家庭不幸福,因為他們的家庭採取專業分工的component team。小孩只負責做小孩該做的事,只要乖乖讀書就好,什麼家事都不用幫忙。爸爸只負責賺錢,回家一屁股坐下來,不是看電視等吃飯,就是打電動。媽媽最可憐,下班之後還要煮飯、做家事、顧小孩。

Teddy:這是一種「區域最佳化」的做法,每個人都扮演好自己的「專業」,感覺好像很有「生產力」,但卻沒有顧及整個家庭價值鏈的最佳化。

***

魔戒遠征隊

很多人對於導入Scrum從專業分工的component team轉換到交付價值的cross-functional team,一開始在觀念上無法接受。「我是一位UI/UX設計師,現在Scrum團隊中明明就沒有符合我專長的工作,那我要幹嘛?」

還記得電影魔戒中的魔戒遠征隊嗎?魔戒遠征隊有兩個特性和Scrum團隊很像:

  • 跨職能團隊:團隊中包含了完成任務所需要的各種人才,包含巫師、人類、矮人、精靈、哈比人,每個角色都有特定的專長。
  • 自組織:這個特性是到團隊組成中期之後才出現,一開始團隊沒有共同目標,有的人是想完成消滅魔戒的任務,有的人是陪鄰居出門郊遊、有的人是想要搶魔戒、有的人是老闆派來的、有的人是憂國憂民的先知。到後來大家確定共同目標就是要消滅魔戒,各自盡其所能來達成這個目標。

如果你是魔戒遠征隊的哈比人「山姆」,你原本的「專長」是負責煮飯。遇到強獸人來攻擊,你可以說:「我只負責煮飯,不負責打仗。你們慢慢打,我要繼續煮飯了」嗎?當然不會,此時煮更多的飯已經沒有意義,你會拿起短刀,在旁邊偷偷地刺啊、刺啊。就算不能對敵人造成致命攻擊,但總也是想盡辦法幫助團隊其他成員達成退敵的共同目標。

***

當作自己的事

Teddy覺得,敏捷講到底,也沒什麼大學問。就是好好過生活,認真做事,活在當下,去感受各種 forces(作用力、限制條件)。提升自我能力,靈活地面對這些 forces 做出反應,讓身處的環境回復到一個穩定的狀態,繼續面對新的 forces

很多人在公司跑敏捷,覺得痛苦、遇到阻礙,講到底也都是人的問題。從個人的角度來看,如果把手中的工作看成是「別人的事情」、「公司的事情」、「我只是領薪水的」,做事的動機、態度、積極性自然和「這是我自己的事」差很多。

但這也不能怪員工,因為很多時候公司的大環境、文化,迫使員工採取保守的做事心態,少做少錯,防弊重於興利。但無論如何,認真做事、認真過生活,不管公司待你如何,這種做人處事的態度,會跟著自己一輩子,別人是搶不走的。

反正跑不跑敏捷都要痛苦,還不如嘗試點新鮮的玩意,苦中作樂、苦中學習,也是一種不錯的選擇。

***

廣告

對於敏捷開發、Scrum有興趣的鄉民,可參考泰迪軟體的【Scrum敏捷方法實作班】課程,上課日期為4月27、28日(六、日)。

***

友藏內心獨白:小刀刺久了也是會有殺傷力的。

2019年3月15日 星期五

落實TDD的三個難題(上):領域模型與軟體架構

March 15 07:11~09:11


緣起

幾年前有一位泰迪軟體忠實學員問Teddy:「我上過TDD的課,但回公司後卻不知道該怎麼落實,為什麼?」當時Teddy無法回答這個問題,因為:(1)他上的TDD課程不是Teddy教的,不知道他學了什麼;(2)Teddy以前工作上開發的軟體,只有不到10%是採用TDD,其他大部分都是用傳統OOAD,code first(先寫production code再寫test code)的方式,所以沒在工作上遇到全面落實TDD的問題。

雖然工作上TDD用的不多,但Teddy寫了很多測試案例,也做了持續整合,算一算也有16年的時間。這幾年因為教學需要,投資大量時間在TDD/BDD/SBE以及DDD/Clean Architecture上面,直到最近才慢慢有種可以清楚回答N年前這個問題的感覺。

***

例子太小

不少人都是透過網路上的例子或是TDD Kata來學習TDD,這些例子大多具備以下特點:

  • 所需物件很少:只有單一或少量物件、例如著名的Bowling Game Kata,只需要一個Game物件就搞定。
  • 商業邏輯明確:上述提到的Bowling Game Kata,或是計算不同方式的郵寄費用(平信、掛號、國內快捷、國際郵件)、商品費用(一般客戶、VIP、大量採購、特價商品)等例子,它們要解決的問題「商業邏輯」都非常明確,很容易透過TDD,採用逐次完成每一個例子的方式來實作完整商業邏輯。
  • 不須考慮架構:因為例子小,邏輯清楚,所以也不需要考慮軟體架構的問題。

以上特性,對於一個「以學習TDD為目的」的例子來說,原本都不是問題,反而是優點。因為例子很專注在特定的小問題上面,所以學習者可以在短時間內把握TDD的精神:

  • 寫一個失敗的測試案例
  • 用「最笨」的方式撰寫程式碼讓測試案例通過
  • 重構程式

***

問題在哪裡?

當使用者學了TDD要實際應用在工作上的專案,此時卻發現,實際要解決的問題放大了N倍。不只物件變多、商業邏輯複雜,連帶著軟體架構也需要一起考慮。這些都是在學習TDD階段沒有冒出來的因素(forces)。

奇怪,為什麼看別人TDD,只要透過撰寫測試案例,物件與介面好像信手拈來就有。換成我來TDD,就D不出來,最後只能XD。


▼如下圖所示,這個問題隨著驗收測試開發(ATTD)、行為驅動開發(BDD)、實例化規格(SBE)等方法,將原本傳統TDD「先撰寫失敗單元測試」提升為「先撰寫失敗驗收測試」之後稍有緩解。驗收測試提供TDD一個更大的Context (背景、脈絡),讓開發人員擁有更多的資訊來「隔空抓藥」,透過測試案例描述物件以及物件之間的互動關係。


▼Specification By Example範例


但就算有了驗收測試,整個系統的全貌還是無法清楚呈現,透過每次撰寫失敗測試案例來完成系統依舊屬於由下而上的開發方式。

由下而上的開發方式最大的問題就是:「最後兜出來的系統很容易長歪掉。」看到這裡鄉民們可能會想:「敏捷開發是一種迭代與增量的方法,這不也是一種由下而上的方式?難道敏捷開發也很容易長歪掉嗎?

沒錯,完全正確。這也是為什麼現在敏捷開發流行採用「影響力對照(impact mapping)」與「用戶故事對照(user story mapping)」協助團隊關照系統全貌。撰寫程式之前,不管這個程式是test code還是production code,如果對於所開發的系統缺少一種「整體的感覺」,最後的系統設計就很容易長歪掉。

***

怎麼辦?

其實答案很簡單,就是準備「剛剛好的事前設計」(just enough up-front design)。問題是怎麼拿捏這個「剛剛好」?

▼如下圖所示,對照OOAD與TDD/BDD/SBE的做法,後者少了強調「建立領域模型」(domain model)這個步驟,讓鄉民以為domain model裡面的物件,不需要特別分析與設計就會自然而然隨著撰寫失敗的測試案例而冒出來。就算是剛開始找到的物件不洽當,反正最後總是可以透過重構來改善設計品質。


能力強者如Kent Beck或Uncle Bob等級的人物,在腦海中已有某種 皇輿全覽圖「軟體全貌地圖」,因此可以信手拈來得到合適的領域物件。就算設計不小心歪掉,後續採用重構來改善系統設計品質對他們而言也不是難題。大師們只需極小化的事前設計便可順利透過TDD完成系統,但一般大眾畢竟敏捷性沒有那麼高,所以適量的事前設計有助於TDD。

扯了這麼久還是沒講到具體解法。以下是Teddy建議的方向:

  • OOAD:如果鄉民們學過OOAD,可以參考80-20原則。找出系統中20%最優先的use case或user story,花一點點時間地建立domain model。有了這個domain model,對於後續將「失敗測試案例」轉成test code會很有幫助。


▼cleanKanban系統的領域模型


  • DDD:參考領域驅動設計方法(Domain-Driven Design;DDD),建立domain model與通用語言(Ubiquitous Language)。有這兩項「致命武器」,後續不管你想「怎麼D」都可以得心應手。


▼透過事件風暴(event storming)找出領域事件與建立領域模型


  • Clean Architecture:軟體架構百百種,屬於「插件式架構」的Clean Architecture,因為具備高度擴充性與可測試性,很適合作為各種軟體的「預設架構」。搭配Clean Architecture,撰寫TDD的失敗驗收測試直接對應到呼叫Use Case,而Clean Architecture的Use Case有著固定的結構,需要定義清楚的Input與Output介面。也就是說,Clean Architecture限縮了開發者的「選擇性」,而讓TDD的開發的工作變得更簡單。

▼搭配Clean Architecture採用TDD開發所撰寫的失敗驗收測試。

***

結論

敏捷開發與TDD都不鼓勵大量事前設計(Big Up-Front Design;BUFD),但並不是說不需要任何事前設計直接「帶著鋼盔往前衝」就可以攻克敵軍山頭。合適的事前設計,可以幫助開發人員釐清目標,支撐後續迭代與增量式開發活動,讓整體設計慢慢湧現。

***

友藏內心獨白:緣分到了,問題就想通了。


廣告

對於Clean Architecture搭配TDD與Event Storming(事件風暴)有興趣的鄉民,可參考泰迪軟體的【Clean Architecture這樣學就會了實作班】,2019年4月份課程已確定開課。

2019年2月13日 星期三

Scrum團隊如何落實自動化測試與持續整合?

Feb. 13 15:25~16:26


問題

朋友的Scrum團隊跑了半年,每個sprint結束所產生的可執行軟體離「潛在可釋出」還有一大段距離(品質不是很好)。團隊開始思考要如何提升品質,讓每個sprint可以交付「潛在可釋出的產品增量」。

團隊從QA部門借調一位測試人員—QA甲,希望借助他的力量提升軟體品質。但是QA甲以往都是用人工手動測試來驗證功能的正確性,並不會撰寫自動化測試案例。因此,QA甲需要等待團隊成員完成user story之後才可以開始測試。但通常user story完成後也接近sprint尾聲,沒剩多少時間讓QA甲去手動測試。

有團隊成員建議,請QA甲在下個sprint測試上個sprint的功能,但是這又引發出其他的問題,例如:

  • 程式碼凍結:QA甲要測試上個sprint的功能,就必須要求開發團隊不要修改上個sprint所完成的功能。實務上並不可行,因為下個sprint很有可能就是要基於上個sprint所完成的功能繼續開發,要求程式碼凍結會讓開發流程過於僵硬。
  • Done Done:因為上個sprint完成的功能留到下個sprint才驗收,那到底上個sprint做完的功能真的有做完嗎?換句花說,上個sprint的Done不是真的Done,還要經過下個sprint的驗證後才知道是不適真的Done。那如果下個sprint找出上個sprint的bug,又該在何時處理?如此一來,沒完沒了,整個開發時程也不容易掌握。

***

理想狀況

自動化測試與持續整合是軟體開發(不管是否採用敏捷)不可分割的一部分,團隊一開始在撰寫功能之前,就要先把持續整合環境架設好,讓自己的空專案可以在持續整合系統上建構,之後才逐一開發新功能。而每一個新功能,都要有足夠的自動化單元測試、整合測試與驗收測試。

為了達到測試自動化的目的,在Scrum團隊中的QA人員(Scrum團隊成員通稱為開發人員)需要具備撰寫自動化測試案例的能力。如果負責測試的開發人員沒有撰寫自動化測試案例的能力,就要考慮:

  • 是否願意學習新技能,並且與開發人員一起緊密合作
  • 考慮離開Scrum團隊

Teddy的意思並不是說所有的測試案例都必須要自動化,有些測試案例,例如UX方面的測試,或是自動化成本太高的UAT,或是探索式測試,還是可以用人工的方式來做。但大原則是絕大部分的測試必須要自動化,而身處Scrum團隊的測試人員也必須具備撰寫自動化測試案例的能力。

***

非理想狀況怎麼辦

如果團隊已經跑Scrum一陣子,一開始沒有落實自動化單元測試與持續整合,要怎麼「半路出家」?

假設團隊中沒有任何一個人具備自動化測試與持續整合個觀念,最快的方式就是請人教,或是去上課,把基本的知識在短時間先補齊。

接下來可以在DoD(Definition of Done)中訂定自動化驗收測試的標準,讓往後所開發的功能都有基本的自動化驗收測試。至於之前所開發的功能,可以採用以下兩種方式來補寫自動化測試:

  • Bug-driven:當發生bug的時候,先寫一個自動化測試案例來反映這個bug。此時這個測試案例一地會失敗,然後去修改程式碼,直到測試案例通過就知道bug改好了。
  • 預算制度:每個sprint投資固定時間去補寫之前的自動化測試案例。

***

測試先行或測試後行?

有些技術能力比較好的團隊,會採用測試先行(test first),也就是測試驅動開發(test-driven development)、行為驅動開發(behavior-driven development)、實例化規格(specification by example)的方式,讓撰寫測試案例成為開發流程中的上游,test code先於production code,以避免測試後行(test last)的缺點—先寫production code,永遠沒有時間寫test code。

Teddy覺得測試先行或是後行都可以,但重點是「測試一定要行」。只要有紀律,養成測試是開發不可分割的一部分,測試先行或測試後行可以依據團隊的能力與專案特性自行調整。

***

友藏內心獨白:自動化才能提高QA的價值。

2019年1月30日 星期三

流程權威

Jan. 29 21:28~22:31

▲起床了


問題

上周末在泰迪軟體上【Scrum敏捷方法實作班】,休息時間有一位學員問Teddy…

學員:《Essential Scrum》書中提到Scrum Master的責任,其中有一點是「流程權威(Process Authority)」。請問我要怎麼讓自己變成流程權威?

***

狹義來說

Scrum Master協助團隊、Product Owner、與公司獲得Scrum的好處(請參考〈Scrum Master 的存在〉) 。因此Scrum Master對於Scrum框架與價值、原則、實務做法等,都必須要非常熟悉。

換句話說,Scrum Master必須是敏捷專家。這一點聽起來好像很簡單,但Teddy遇過很多Scrum Master,即使已經上過CSM、CSPO的課程,但對於基本的敏捷精神與Scrum框架還是一知半解。

舉幾個例子:

  • 只有Product Owner能撰寫user story。
  • 只有在review meeting時可以review做完的user story。
  • Sprint長度越短越敏捷,所以團隊不管怎樣就是要採用一周一個sprint。
  • 在Review meeting討論流程改善,在retrospective meeting討論需求。
  • 把cross-functional與multi-skills搞混。
  • 把actively doing nothing搞成passively doing nothing。
  • 這個sprint兩個禮拜功能做不完,所以動態調整把sprint改成三周。
  • Sprint review只管完成user story的個數,忽略交付給使用者的價值。

***

廣義來說

Teddy認為敏捷開發的各個派別,XP、Scrum也好,精實開發、看板方法也罷,只是不同人對於追求 「The timeless way of software development(軟體開發的永恆之道)」所提出來的見解。

「能量不滅」,傳統軟體工程所探討的問題,敏捷開發幾乎都會碰到,只是敏捷開發採取的應對策略可能有所不同,但要解決的共同大問題就是那一個。所以要成為流程權威,就必須知道軟體工程所探討的問題,然後回頭對應敏捷方法如何處理這些問題。

最好有自己參與過軟體開發的經驗,包含專案與產品開發,與不同程度與背景的人合作,越多樣性越好。親身體驗軟體開發的各種forces(作用力、限制條件),越能夠感受軟體開發的Quality Without A Name(無名的特質)。

***

誰適合當Scrum Master

經常有朋友問Teddy:「哪種人適合當Scrum Master?」依據《Essential Scrum》的看法,Scrum Master必須是:

  • Coach
  • Servant leader
  • Process authoring
  • Interference shield
  • Impediment Remover
  • Change Agent

以上任何一點只要做到極致,就已經是該領域的專家了。而Scrum Master居然要同時精通「武當六絕」,這根本需要百年難得一見的練武奇才方能達成使命。難怪有一位HR曾經跟Teddy開玩笑說:「找Scrum Master好像在找聖人一樣」。

誰適合當Scrum Master?不同背景的人,只要具備上述能力其一,就有機會擔任Scrum Master。Scrum Master也是人,也需要持續學習。如果是coach背景的人當任Scrum Master,也許對於軟體開發流程不熟,就需要補足這方面的能力。如果是老闆的兒子或女兒當任Scrum Master,應該在阻礙排除、干擾屏蔽與變革代理有很大的貢獻,但其他責任可能就需要補強。

總之,將相本無種,人類當自強。

***

友藏內心獨白:把自已當成一座橋梁,理論與實務的橋樑。