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

2023年7月3日 星期一

為什麼開發人員會過度設計?

July 03 23:10~23:45


  

▲圖1:軟體開發的三個圈圈


前言

今天學生問Teddy一個問題:為什麼會產生過度設計(Over Design)?開發人員的時間不是都很寶貴嗎,怎麼會做出「超出目前需要」的設計?

***

原因很多

造成過度設計的原因很多,常見的有:

  1. 需求不清:很多開發人員沒有機會或意願接觸業務人員或領域專家去持續釐清需求,因此在開發系統的時候,只能依據文件或是對於需求模糊的認知來做設計。因此,很可能產生存在於設計中,但卻不存在於需求中的軟體,如圖1的區域6。
  2. 超前佈署:不管需求是否明確,開發人員通常會有一種「預留彈性」的傾向。「雖然客戶現在沒有要求,但是這個地方如果可以這樣再那樣設計,套某某設計模式,以後需求改變就輕鬆多了。」
  3. 改動架構成本很高:這一點和超前佈署有關,但發生在軟體架構層面。因為軟體架構的修改成本很高,所以如果可以在架構設計階段就「留有彈性」,那未來的日子就好過多了。很可惜,此時的彈性絕大部分都是開發人員腦補的結果,不但沒有幫未來鋪路,反倒增加人為的複雜度。
  4. 展現技術能力:有時候,過度設計就僅是開發人員展現自我技術能力的結果。「08學得一身功夫,就該好好施展一番。先來個23個設計模式漱漱口。」
  5. 演化的結果:有時候系統初期過度設計並不明顯,但隨著系統不斷開發與重構,演化的結果導致系統存在一些過於彈性的設計。例如,想要code reuse與去除重複程式碼,就很容易產生過於彈性的設計。

***

結論

過度設計的原因很多,Teddy覺得主要還是對於需求的理解是否到位,以及對於改變的反應能力是否足夠,會造成開發人員有沒有信心只要當下做出「將將好的設計」(Just Enough Design)即可。從敏捷開發的角度來看,採用TDD/BDD/SBE的開發方法,可以讓 (Specification = Test) = Program,在理想狀況下,可以大幅減少過度設計。

***

友藏內心獨白:要做到Lean,並不容易。

2021年12月23日 星期四

無痛將驗收測試文件寫在測試案例中

Dec. 23 20:18~21:45

▲新買的電腦還沒寫code先來寫部落格

 

前情提要

2017年Teddy寫過一系列關於行為驅動開發(Behavior-Driven Development,BDD)的文章,請參考以下列表:

  1. BDD(1):詳盡的文件就是可用的軟體
  2. BDD(2):大家來吃小黃瓜之Cucumber運作原理
  3. BDD(3):在Eclipse執行Cucumber-JVM
  4. BDD(4):第一個Cucumber-JVM範例,上集
  5. BDD(5):第一個Cucumber-JVM範例,下集
  6. 在IntelliJ IDEA使用Cucumber(上)
  7. 在IntelliJ IDEA使用Cucumber(下)
  8. BDD(6):讓Step找到Step Definition
  9. BDD(7):使用Transform讓稅金同時支援5%和0.05表達方式
  10. BDD(8):實作第一個開發票Scenario
  11. 在IntelliJ IDEA使用Cucumber(上)
  12. 在IntelliJ IDEA使用Cucumber(下)

 

當時學了一陣子Cucumber但後來一直沒有真正使用它。主要原因在於Teddy覺得「Cucumber將需求寫在feature file裡面,然後再轉成step definition程式碼,然後開發人員在這些step definition立面撰寫真正的測試邏輯」的這種流程不太流暢。完整開發一個功能,從寫feature file到寫完produciton code的過程會一直撞牆(卡住),尤其是feature file有參數要傳給step definition,真的不太直覺。

但當時Teddy也沒多想,就把這個問題放著。

***

活文件

前幾天讀了《Living Documentation: Continuous Knowledge Sharing by Design》,書中有一個例子如下圖所示:


▲圖1:Living Documentation書中範例

 

看到這個例子Teddy突然心中有感:「對了,就是這樣。應該要把Cucumber的feature file內容寫在程式碼中而不是與程式碼分離。」於是Teddy也試著修改ezKanban的測試案例看看效果如何,請參考下圖:


▲圖2:修改後的ezKanban驗收測試案例

 

Teddy覺得直接在測試案例程式碼加上Given-When-Than說明文字讓測試案例清楚很多,也免去了原本Cucumber在feature file與step definition之間做binding的麻煩。

至於圖2中Scenario(), When(), WhenFailure()是怎麼來的?其實很簡單,原本Teddy以為書中用了什麼工具,但找了一下沒找到。後來想到,自己寫一個不就好了。程式很簡單,長成下面這樣:


▲圖3:用來在測試案例中撰寫Given-When-Than說明文字的工具,算是一的超級簡單的DSL(domain specific language) 

 

這種做法,與程式語言和工具都無關。絕大部分的高階語言要寫出圖3中的程式應該是幾分鐘就搞定的事。

 

***

 

友藏內心獨白:本篇在新買的第12代i9電腦上撰寫XD。

2021年4月27日 星期二

領域驅動設計學習筆記(15):領域專家缺貨

April 27 17:12~17:48

▲David West提到在1968年代,銀行的開發人員就是領域專家


不少朋友問Teddy一個問題:「Event Storming工作坊的時候如果領域專家不願意參加,或是勉強參加但卻都在擺爛,被動等著開發人員去問他問題,這樣該怎麼辦?」

這是一個很常見的問題,因為許多公司,特別是大公司,雖然嘴上說導入敏捷好幾年了,但骨子裡還是傳統瀑布是開發方法,客戶(業務單位)與開發人員還是透過中間人所產生的文件來溝通。這個中間人可能是Scrum裡面的Product Owner(PO),或是傳統的專案經理或是系統分析師/商業分析師。客戶(業務單位)認為開發軟體是開發人員的事情,能講的他們都已經講完了,這些開發人員不要三不五時就跑來煩他們,趕快把東西生出來。

另一方面,客戶(業務單位)理論上雖然代表著領域專家的角色,但這並不表示他們有能力和開發人員一起析分商業流程,甚至有些商業邏輯的細節連他們也不十分清楚。再加上客戶(業務單位)的人日常工作量已經很多,自己的事都忙不過來,很難要求他們長時間配合開發團隊持續進行Event Storming並精煉領域知識以及共通語言。

***

所以,如果你的開發團隊有願意一起長時間配合的領域專家,恭喜你你的現況離理想狀況比較接近。如果沒有,也不要灰心喪志,日子還是要過下去。

領域專家「缺貨」怎麼辦?如果真的調不到「貨」,只好讓自己變成領域專家。

幾天前Teddy聽了David West的〈 The Past and Future of Domain-Driven Design〉演講,講者提到在1968年代,銀行的開發人員就是領域專家。在【搞笑談軟工臉書社群】上,有兩位朋友也分享了類似的經驗。


所以,萬一開發專案中真的沒有領域專案,而案子也還是要做下去,考慮訓練自己成為領域專家。這樣做一定會花費比較多的時間,走更多的冤枉路,但總是能緩慢往前移動,總比留在原地一動也不動來的好。

就算團隊中有領域專家,開發人員也不能完全信任領域專家,自己還是要動腦思考,畢竟要將問題領域(problem domain)轉化成解法領域(solution domain)的人,是開發人員,不是領域專家,開發團隊還是要多擔待一些。

***

友藏內心獨白:一個人或是一個團隊的End-To-End,就可以變得很靈活。

2020年12月29日 星期二

領域驅動設計學習筆記(13):幫Event Storming加上使用者介面

Dec. 29 09:43~11:39


問題

這個月底Teddy去客戶家上了三天的【領域驅動設計與簡潔架構入門實作班】,有好幾位學員都問到:「Event Storming怎麼表達使用者介面設計?」使用者介面是軟體的外觀,關係著軟體好不好看以及好不好用,的確是軟體開發中一個重要的議題。

今天來談談這個問題。

***

Event Storming簡介

Event Storming(事件風暴)在領域驅動設計中經常被使用於讓利害關係人與團隊共同協作,用以釐清業務流程、討論商機、風險、區分bounded context、建立共通語言,乃至於設計與實做軟體的一種方法。Event Storming發明人Alberto Brandolini在《Introducing EventStorming》書中介紹這個方法,圖1為Event Storming工作坊所使用的主要便利貼,不同顏色有不用的用途。


▲圖1:Event Storming常用便利貼顏色與意義


依據《Introducing EventStorming》書中的介紹,Event Storming有三個階段,分別為:

  • Big Picture:依據時間發生先後,在一面「巨大」的牆上,貼上Domain Event、External System、People,並藉此流程觀察Hot Spot(對商業流程有模糊不清、商機、痛點等)。
  • Process Modeling:基於前一個階段的產出,加上Read Model、Policy、Command。
  • Design:加上Aggregate。

一般網路上常看到的Event Storming產出物如圖2所示。


▲圖2:Event Storming示意圖

***

UI/UX設計

▲圖3:《Introducing EventStorming》書中的「The picture that explains everything」


參考圖3,在Event Storming方法中原本就涵蓋了UI/UX。這張圖可以這樣解讀:

***

使用者要使用軟體系統執行某項任務,為了執行這項任務,他需要參考資料以協助他決策判斷。因此,他在真實世界看到一個畫面,這個畫面是由Read Model(綠色便利貼)所產生。例如,你去餐廳吃飯,為了點餐(執行任務)你需要看到菜單(畫面),這個餐單可能是中文、英文、日文,可能只有文字或是圖文並茂,但菜單背後都是該餐廳的菜單資料(Read Model)所後製而成。如何設計給客人看的菜單就牽扯到UI/UX的議題。

使用者獲得足夠決策資訊後,向系統發出一個命令(Command,藍色便利貼),這個命令交給系統中某個聚合(Aggregate,黃色便利貼)去執行,執行完畢後發出一個領域事件(Domain Event,橘色便利貼)。領域事件可能引發後續的處理流程,稱為Process、Rule或Policy(紫色便利貼),後續處理流程再執行另一個命令。例如,告訴服務生(Aggregate)你要點餐(Command),服務生完成點餐動作後產生Order Placed(Domain Event)。Order Placed觸發一個後續處裡的流程—請廚師出菜,因此呼叫「製作餐點」這個Command。

領域事件也可能是由外部系統(External System,粉紅色長方形便利貼)所產生,例如餐廳可能與Uber Eat或Foodpanda合作,由外部系統觸發Order Placed領域事件。

最後,領域事件代表「狀態改變」,因此可從領域事件產生Read Model,再透過這個Read Model製作使用者介面。例如廚師可以從Order Placed領域事件產生「出菜順序」的畫面,作為製作餐點的決策參考資料。

***

範例

看完上述對於「The picture that explains everything」 的說明,在Event Storming中加上使用者介面就很容易了。圖4展示在ezKanban中,Create Project與Move Board To Project這兩個命令(套用Clean Architecture之後,這兩個命令被實作成兩個Use Cases)。使用者介面加在綠色便利貼之前,為了執行Create Project,使用者看到一個畫面,按下Add按鈕,跳出一個New Project 對話框,輸入Project Name按下Submit,把team id與project name當作參數呼叫Create Project使用案例。該使用案例透過Team Aggregate產生一個Project,然後發出Project Created領域事件。該事件代表有一個新的Project產生,因此使用者在執行Move Board To Project使用案例的時候,就可以從畫面看到剛剛新增的Project。


▲圖4:ezKanban範例,在Event Storming加上使用介面。

***

使用者介面如何產生

團隊的UI/UI的人員,可以沿用原本熟悉的工具來繪製使用者介面或是UI操作流程圖,只要將最後的結果截圖貼在Miro上面即可(Teddy與ezKanban團隊使用Miro來繪製Event Storming),不會影響原本的UI/UI設計流程。

最後工商服務一下,想學習DDD + Event Storming + Clean Architecture + TDD,歡迎報名泰迪軟體的【領域驅動設計與簡潔架構入門實作班】。

***

友藏內心獨白:無縫接軌。

2020年12月27日 星期日

領域驅動設計學習筆記(12):Event Storming與User Story

Dec. 27 20:05~21:45

▲ezKanban團隊的開發流程


問題

有朋友問Teddy:「Event Storming做完之後,如何轉成user story與團隊溝通?」

在ezKanban開發過程中,團隊的開發流程從2020年暑假開始從Scrum轉成Kanban。團隊不再額外寫In order too [獲得什麼好處]….As a user, I want to [做什麼事] 這種格式的user story,而是直接將Event Storming的Command變成Use Case放到product backlog裡面。

傳統OOAD的Use Case其粒度一般來講比user story要大,一個Use Case可能有多個執行路徑或多個劇情,每一個執行路徑可視為一個user story。所以直接以Use Case來取代user story,有可能會違反敏捷與精實開發的小批量生產原則—開發的功能儘量切小,可獲得較短的交期(lead time)。不但bug會比較少,品質較好,也可以快速收集使用者回饋。

ezKanban團隊在Event Storming的過過程中不是從CRUD的角度來尋找領域事件,而是找出任務導向(task-oriented)的領域事件,並且採用TDD/BDD/SBE的方式實作Use Case。因此從實作面的角度,也是以step by step、piece by piece、scenario by scenario的方式完成使用者需求,並不會因為沒有將Use Case改寫成user story就造成溝通或是開發上的問題。

***

範例說明:Move Lane使用案例

圖1:Move Lane Command


視覺化是實施看板方法的第一條原則,因此ezKanban軟體自然要提供設計工作流程的功能,讓使用者可以新增Stage(垂直的工作階段)與SwimLane(水平的工作階段)。除此之外,使用者在視覺化工作流程的時候經常需要調整工作流程的順序與層級,因此Move Lane(移動工作階段)使用案例也很重要,如圖1所示。

使用者可以直接用滑鼠將最上層的工作階段拖拉到想要的順序,如圖2所示,使用者正在把Reviewed移到Ready to Deploy之後。


圖2:實作完成的Move Lane畫面

***

實作Move Lane使用案例

因為採用TDD方式開發,因此先撰寫第一個Use Case的測試案例—移動最上層的Stage。請參考圖3,這個測試案例代表最常見使用情況的happy path。


圖3:Move Lane的第一個測試案例

一開始這個測試案例根本無法編譯,因為都還沒寫production code。接著就按照TDD的流程,以最簡單的方式撰寫讓測試案例可以通過的production code,再透過重構來改善設計。

因為移動工作階段這個功能比較複雜,光靠Use Case的驗收測試無法涵蓋所有可能的移動情況,因此以specification by example的精神,以單元測試來代表移動工作階段的各種可能狀況,單元測試案例執行結果請參考圖4。


圖4:Workflow身上的moveLane方法的單元測試


針對move lane的各種狀況,ezKanban團隊目前一共寫了9個單元測試,從單元測試的名稱就可以很清楚看到所想要涵蓋的情況,例如以下兩個單元測試代表移動工作階段的邊界條件測案例。

  • should have correct order when move substage0 from order0 to order0 in the same parent
  • should have correct order when move substage4 from order4 to order4 in the same parent

單元測通過之後,回頭跑Use Case測試案例,順利通過就完成Move Lane使用案例的第一個happy path。

接著撰寫第二個Move Lane使用案例的驗收測試—should succeed when move second root stage containing sublane to first root stage,這個案例比較複雜,代表兩個平行的stage A 和stage B,其中stage B底下還有其他的stages,然後把stage B移到stage A底下。

這兩個驗收測試都通過之後,就可以撰寫rest controller,完成後再寫前端的react程式,把前後端接起來這個Move Lane功能就完成了……第一版。

上述提到兩個驗收測試都是移動Stage,還需要增加移動SwimLane的驗收測試,測試通過後整個Move Lane使用案例才可以算是完成。

目前ezKanban團隊的TDD僅限於use cases與entities這兩層的物件,這兩層以外的開發並沒有採用TDD,而是採用傳統code first方式。

***

通用語言表現在程式碼

領域驅動開發有一個重要的觀念—Ubiquitous Language in Code,能夠做到這個層次,開發團隊本身,以及開發團隊與stakeholders(尤其是domain experts)的溝通也就沒什麼問題。

Teddy整合了DDD、Event Storming、Clean Architecture與TDD/BDD/SBE,首先透過event storming建立ubiquitous language 與domain model,接著透過clean architecture與TDD將ubiquitous language落實在程式碼之中。以上這些都做到之後,如果覺得還是需要撰寫傳統的user story,那也沒關係,就去寫吧。

***

友藏內心獨白:到了離,就不用守了。

2020年2月20日 星期四

領域事件幫你切割使用案例

Feb. 20 13:45~14:36


售後服務

今天上午有一位剛上過【領域驅動設計與簡潔架構入門實作班】的學員B問Teddy一個關於如何切割使用案例(Use Case)的問題。為了不洩漏學員B的工作內容,以下的文章中Teddy將學員B的應用領域轉成開發看板系統,將他提出的問題改寫,再跟鄉民們介紹。

***

問題敘述

使用者想要列印看板系統中的卡片(Card),使用者可以選擇列印全部的卡片,或是只列印挑選過的若干卡片。開發團隊想到兩種可能的實作方式:

  • 方法一:實作一個PrintCardsUseCase使用案例,它接受兩個參數—boardId和filters。如果filters是空的,就列印該看板的全部的卡片;如果filters有資料,則先依據filters條件過濾不需要的卡片,再列印符合條件的卡片
  • 方法二:方法一需要在使用案例中加上一個if判斷,感覺不太好。因此衍生另一種想法,把使用案例拆成兩個—PrintAllCardsUseCase和PrintCardsByFilterUseCase,前者只需要boardId這個參數,後者則需要boardId與filters這兩個參數。

寶傑,你怎麼看?!

***

用領域事件思考

學員B遇到的問題很常見,Teddy年輕的時候學習物件導向分析與設計(OOAD)也遇過同樣的問題。學了領域驅動設計和Event Storming之後,這個問題的解決方式就變得很簡單。回到事件風暴(Event Storming)來思考:

  • 先寫出領域事件(Domain Event)


  • 幫每個領域事件加上Command


  • 幫Command寫上Input

分析到這裡就很清楚了(先不用管Aggregate與Policy),使用者的確需要兩個使用案例,但不是原本方法二的PrintAllCardsUseCase和PrintCardsByFilterUseCase這種切割方式,而是:

  • FilterCardUseCase
  • PrintCardUseCase

使用Event Storming,依據時間軸來思考領域事件,再寫出相對應的Command,系統的行為就會慢慢浮現出來。

***

友藏內心獨白:距離上市集資也就跨進一大步了。

2020年2月11日 星期二

領域專家X

Feb. 11 17:33~19:11

▲立志成為喵星人的領域專家


前言

無論是行為驅動開發(Behavior-Driven Development;BDD)、實例化規格(Specification By Example;SBE)或是領域驅動設計(Domain-Driven Design;DDD),共同存在一個非常重要的假設:「正確的需求可以藉由領域專家與開發團隊密切的迭代溝通所產生」。

在這個假設之下,領域專家彷彿「神一般的存在」,他的腦袋中似乎對所有問題都有答案,對於團隊的提問,他不會說:「都可以,由團隊決定」。

可能是領域專家知道的太多,他無法將所有事情主動告訴開發團隊,需要藉由團隊成員與他的互動,將完整的需求慢慢誘導出來。

這其實並不是什麼新觀念,傳統的軟體開發方法也都持相同看法,只不過BDD/SBE與DDD,特別是BDD/SBE這一系列的方法,特別強調此觀點。

***

落實BDD/SBE的困難

讀過BDD/SBE書籍的鄉民一定會發現,許多書本都會以一個例子來示範如何學習這些方法,例如停車費計算、搭乘巴士或捷運的車資計算、包裹運費計算。相對於一般的商業軟體,這些例子除了功能較少以外(系統較小),還有一個共同特色,就是有著非常明確的商業邏輯。

因為有著非常明確的商業邏輯,領域專家的角色就可以被簡化,也容易透過領域專家與開發人員之間的對話來釐清「規格」,進一步採取「舉例子」的方式來描述這些規格。作為學習目的,這樣的設計非常合理,並無不妥。

落實BDD/SBE的困難之一在於一個完整的系統除了「具備明確商業邏輯」的部分以外,也有許多功能的商業邏輯不是哪麼明確。又或者是這些邏輯不屬於核心商業邏輯(core business logic), 而是應用程式邏輯 (application logic)。換句話說,領域專家也許對於核心商業邏輯比較清楚,但不一定對於應用程式邏輯有特別的意見。這時候通常需要由開發團隊來主導,再與領域專家確認。這個部分的系統實作,在BDD/SBE的書籍討論的比較少,因為這原本就不是這系列方法所著重的焦點。

舉個例子,以看板系統(Kanban System)為例,它本身有一些相對明確的核心商業邏輯,例如看板核心三原則:

  • 視覺化
  • 限制WIP(work in progress/process)
  • 管理流

根據這三個原則可以舉出好幾的實例,這些都是領域專家比較熟悉的核心商業邏輯:

  • 工作流視覺化實例,包含垂直工作流、水平工作流(swim lane)。
  • 卡片(Card)視覺化:包含標準卡片、固定交期卡片、加急卡片、Bug修正卡片、技術工作卡片。
  • 工作流加上WIP限制之後,卡片數量符合與違反WIP限制的例子。
  • 阻礙(Blocker)的表達方式。
  • Lead Time、Cycle Time的定義與量測方法。

真正實作看板系統的時候,有一些不屬於核心商業邏輯的應用程式邏輯會跑出來,例如:

  • 一個使用者可以擁有多少個看板?
  • 不同的使用者是否可以共用看板?
  • 使用者要如何設計自己的看板?從頭開始設計,還是可以套用現成的模板(Template)?
  • 一個看板只能表達一種工作流程,還是可以同時表達多個工作流程,以便於讓多個團隊共用看板?
  • 已完成的卡片(當累積很多之後)要如何「收納」才不會阻礙使用者使用看板?
  • 如何表達看板的開始與結束,以便於計算lead time?

以上總總問題,雖然也屬於開發看板系統需要釐清的邏輯,但並不屬於核心商業邏輯,因為不同的看板系統,可以有不同的決定。例如,路人甲所開發的Simple Kanban系統決定一個看板只能有一個工作流程,而路人乙所開發的myKanban系統則是支援一個看板可以有多個工作流程。

***

落實BDD/SBE的困難

相較於BDD/SBE,DDD因為要探討領域模型(domain model)、通用語言(ubiquitous language)、bounded context、context map以及aggregate、entity、value object、repository、service、factory等DDD設計模式,因此需要一個相對比較完整的系統開發作為例子,例如《Implementing Domain-Driven Design》就以開發敏捷專案管理系統當作例子。

落實DDD的困難之一在於如何找到一個「合適且完整的系統當作例子?」例子的問題領域很重要,因為學習者通常是軟體工程師,如果問題領域過於專業,例如健保系統、保險理賠系統、進銷存系統,軟體工程師很難在學習過程中弄清楚這些系統的核心商業邏輯與應用程式邏輯。如果例子太小,又失去套用DDD的意義。

為了解決缺少領域專家的問題,《Implementing Domain-Driven Design》作者選用了敏捷專案管理系統作為例子。一方面這個系統的大小適中,而問題領域又是開發人員比較容易理解的敏捷方法,因此開發人員可以自己腦補,同時扮演領域專家的角色。

***

真實世界的困難

剛剛從學習的角度來討論在學習BDD/SBE與DDD的時候,缺少真正領域專家所造成的問題。在真實世界中,這個問題是否就消失了?

雖然開發團隊應該會有專案經理、系統分析師、產品經理或Product Owner等角色來協助釐清系統需求,但實際上這些人很可能都不是真正的領域專家。就算團隊有領域專家的協助,但如前面所提到的,領域專家可以協助釐清核心商業邏輯,但對於應用程式邏輯的幫助相對較小。

此外,敏捷開發採用迭代與增量的方式,在開發過程需要持續與領域專家討論於釐清問題,但並不是所有領域專家都願意這樣子跟開發團隊配合。有些領域專家甚至認為:「這是開發團隊的工作,我為什麼要花自己的時間幫他們做事?」

所以,開發團隊不能無腦地一味將釐清商業邏輯的責任推給領域專家,而領域專家也應該多聽聽開發團隊的意見,不要把團隊提出的問題當成對自己專業知識的質疑,這是一種釐清問題的溝通過程。

***

友藏內心獨白:沒有的東西要去哪裡生?!

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年3月18日 星期一

落實TDD的三個難題(中):通用語言的建立

March 18 17:02~18:11

▲廣義的說,TDD、ATDD、BDD、SBE都是同義字。


難題二

落實TDD/ATTD/BDD/SBE的第二個難題就是通用語言的建立。傳統TDD(先寫失敗的單元測試)好像只是開發人員自己的事情,它被降級為一種開發方式的選擇(Test First VS. Code First),一種技術議題,與商業無直接關係。

但後來的TDD,也就是冠上ATTD/BDD/SBE之後的TDD,強調透過開發團隊與領域專家的合作,以「舉例」的方式一起釐清需求與商業價值。

這裡說的領域專家,可能是Scrum團隊的Product Owner,或是任何具備問題領域知識的stakeholders。這是一種頻繁、高互動性且非常燒腦的活動,而不是單方面由Product Owner寫好user story然後在sprint planning meeting「宣達聖旨」給團隊的那種溝通模式,更不是瀑布式開發那種「文件丟過牆」的溝通模式。

***

通用語言

通用語言(Ubiquitous Language)是領域驅動設計(Domain-Driven Design;DDD)所提出的觀念,意指「在一個特定領域中,所有人所固定使用的術語」。例如,在貓奴這個特定領域(bounded context),大家對於乾乾、濕濕、罐罐、浪浪、小橘、賓士、虎斑、三花、玳瑁、麒麟尾、鏟屎官、聖上、皇后、離胺酸、貓砂、逗貓棒、結紮、貓毛、掃地機器人等名詞有著高度共識。一群貓奴聚在一起,用他們的「通用語言」可以非常有效率溝通而且比較不會造成誤會。

這個概念,應用在軟體開發上面,當團隊建立了良好的的通用語言,問題領域的知識可以直接出現在解決方案領域,商業人士可以直接和技術人員用相同的語言溝通,表達商業邏輯。更進一步,在實作軟體系統時,這個通用語言將直接反應在程式碼裡面,也就是ubiquitous language in code。如此一來,程式將變得更加容易理解與維護,也更容易擴充。這是一種讓軟體變軟,擁抱改變的做法。

***

通用語言和TDD有什麼關係?

在〈落實TDD的三個難題(上):領域模型與軟體架構〉中Teddy提到建立領域模型對於TDD的重要性,而建立通用語言的過程,同時間幫助團隊建立領域模型,兩者相輔相成。

只要Teddy聽到有朋友「宣稱」採用TDD開發軟體,Teddy一定會問對方:「你們的需求如何產生(如何撰寫失敗的驗收測試)?」如果答案是「Product Owner寫好給我們照做」,那麼落實TDD的程度就還有不少改善的空間。

如果答案是「透過頻繁地與Product Owner溝通,討論列出需求中的重要例子(key examples)」,那就比單向的接受user story要好很多。如果答案是「透過與Product Owner以及stakeholder的討論,以舉例的方式,建立共同討論的語言,並以此為基礎來撰寫程式」,那就可以獲得一張「好棒棒」貼紙。

***

結論

TDD是透過先撰寫測試案例來釐清需求或規格,之後再考慮如何開發程式的一種設計方法。套用建築師Alexander的模式框架,這是一種「先決定Context,再決定Form」的設計方法。

為什麼網路上的TDD範例與TDD Kata你都做得嚇嚇叫,公司的專案做起來卻讓人很想睡覺?很簡單,因為前者具有定義清楚的Context,而後者的Context非常模糊。

一般來講,Product Owner與stakeholders擁有比較多的領域知識,換句話說他們比較了解Context。缺少這些角色的幫忙,開發人員很難獨自透過TDD的方式自行決定Context,這也是許多人在真實專案中落實TDD所遭遇到的困難。

在許多公司,Product Owner與stakeholders覺得「撰寫失敗的測試案例是開發人員的事」,人家不願意理你啊。

難怪你的TDD又變成XD了。

***

友藏內心獨白:不能放任開發人員自由發揮,結果會很恐怖。

2018年8月15日 星期三

為了快,你損失了什麼?

August 15 14:33~16:14

螢幕截圖 2018-08-15 16.15.02


問題

三不五時會聽到來自不同公司的朋友提起他們sprint planning meeting的進行方式…

在會議進行的時候,我們分別請UX/UI設計師與程式設計師分組估算他們各自擅長的工作,以便減少會議的時間。反正雙方人馬都不懂對方的工作性質與內容,一起討論實在是很沒效率。

這樣子做,好嗎?

***

緬懷大師

2018年8月7日,也就是一個禮拜前,軟體工程界大師Gerald M. Weinberg(傑拉爾德‧溫伯格)以85歲高齡過世。溫伯格一生寫了很多書,以生活化、輕鬆且風趣的筆法說明艱澀無趣的軟體工程觀念與方法。他的過世,著實是軟體工程界的一大損失。

在溫伯格與Donald C. Gause合寫的《Exploring Requirements: Quality Before Design》(中文版《從需求到設計:如何設計出客戶想要的產品》)書中提到:

發現什麼不重要,重要的是發現(探索)的過程…探索需求的工作事實上就是建立一個團隊。

沒錯,探索需求的工作事實上就是建立一個團隊。只為了「快」就將Scrum團隊依據「專長」畫分成小組,讓小組各自討論得出估算值。這種做法只比讓專案經理或團隊主管一人制定時程要來得好一點,但卻失去了Scrum建議組成跨職能團隊(cross-functional team)的目的,變成「跨職能團隊中的元件小組(component group)」。

***

大師開示

在溫伯格的書中接著提到,若以下任一條件不符合,專案就很可能失敗:

  1. 了解需求要件
  2. (大多數都)貫徹始終參與專案
  3. 知道如何使團隊有效運作

《Exploring Requirements: Quality Before Design》這本書是1989年出版,距今29年前,相信那時候Scrum應該還沒有正式誕生。有跑過Scrum經驗的朋友請回顧一下,這三點是否也都包含在Scrum之中呢?

***


友藏內心獨白:不需要做的事情,就不需要把它做好。

2017年6月13日 星期二

敏捷開發的價值

June 13 22:16~23:13

螢幕截圖 2017-06-13 23.07.02

▲Eiffel內心獨白:幹嘛我做什麼你也跟著我做什麼!


問題

敏捷開發被稱為是一種「價值驅動」的開發方法,不知道鄉民們有沒有想過,敏捷開發所談的「價值」來自於何處?

***

顯而易見的價值

價值驅動最常顯現在兩個觀點上面:

  • 優先開發對使用者最有價值的功能:從使用者的角度來思考,哪些功能是他們最迫切需要的?迫切需要可能是可以幫助使用者賺更多錢、省更多成本或時間、提高服務品質、去除痛點等。
  • 減少上市時間:這也是許多人(特別是老闆)對於敏捷開發的第一印象:「敏捷就是快」。「快速上市」對於企業和客戶都是一種很高的價值,可以提早推出產品,就可以吸引喜歡嘗鮮的客戶,也可以因此獲得使用者的回饋進而修正下一代或下一版產品的開發方向。

以上兩點經常是彼此互相幫助的力量。因為「不知道(更常見的情況是沒有能力預知)」使用者真正想要的是什麼,所以只好透過「小步快跑」(縮短上市時間)的方式期望藉由不斷地迭代來改善產品,以便做出對使用者有價值的功能。

到此為止都很完美,為了做出對使用者最有價值的功能,所以採取小步快跑的模式。但是,鄉民們有沒有覺得哪裡怪怪的?

***

價值背後的價值

真的只要透過不斷地「小步快跑」就可以做出對使用的有價值的產品嗎?

是什麼機制讓團隊可以「持續」小步快跑下去,而不會變成「小步慢跑」、「小步亂跑」或是「腳麻了不能跑」?

要回答這兩個問題,企業需要注重以下價值:

  • 增加產品品質:品質的不好的產品,就算使用者因為新鮮感或獨特性而暫時忍受,日後等競爭產品出現很可能立刻投入敵人的懷抱。
  • 增加產品的彈性:敏捷開發強調「回應改變(responding to change)」甚至是「擁抱改變(Embrace Change)」,如果你的軟體已經變成硬體(請參考〈讓軟體變軟的兩個原則〉),要如何回應改變?無法回應改變,也就阻止團隊及時推出產品的能力(無法做到減少上市時間)。
  • 降低成本:在相似功能、相似品質、相似開發時間的條件下,開發成本越低的團隊或產品自然比較有競爭力。對企業或客戶來說降低成本也是一種重要的價值。
  • 增加產品的生命週期:簡單說就是比較耐用。花同樣的錢,有的產品過了保固期隔天馬上壞掉,有的產品過保固期之後還可以用好幾年,當然可以用越久的產品對客戶越有價值。

***

結論

產品價值來自於做對(do the right thing)、做好(do the thing right)、做得更快(do it faster),在Scrum框架下,同時具備這三者,需要Product Owner、開發團隊、Scrum Master一起合作,才可以達到價值驅動的目的。

***

友藏內心獨白:做對、做好,但做得比別人慢也是白搭。

2017年3月14日 星期二

BDD(17)Given-When-Then怎麼寫?

March 13 10:48~11:46

屏幕截图 2017-03-13 11.46.03

 

兩種寫法

在BBD中Given-When-Then格式被經常用來撰寫例子,撰寫的方式可分為兩大類:

  • Imperative:命令式,一步一步寫出使用者護系統互動的詳細步驟。
  • Declarative:宣告式、聲明式,著重在於使用者「做什麼」(What)而不是「怎麼做」(How)。

採用何種方式,對於可執行規格(executable specification)或驗收測試的可維護性有著很大的影響。在《Cucumber BDD How-to》書中有一個例子。

Imperative Step

Scenario: Write blog

Given I am on the blog homepage

When I click “New Post” link

And I fill “My first blog” as Title

And I fill “Test content” as content

And I click “Post” button

Then I should see the blog I just posted

相對於命令式的寫法,宣告式的寫法如下:

Declarative Step

Scenario: Write blog

Given I am on the blog homepage

When I write a new blog post

Then I should see the blog I just posted

***

有何差異?

採行BDD一般來說會推薦說使用宣告式的寫法,因為這種方法可以隱藏更多的實作細節,除了可讀性比較高以外,還可以更專注於描述系統行為而非系統如何實作。宣告式的作法會把實作細節放在測試自動化層,也就是Cucumber的step definition裡面。如此一來如果實作細節改變,例如網頁介面連結名稱改變,也不需要修改規格(不需要修改Cucumber的.feature檔案)。

命令式的方式也不是完全沒有好處,雖然採用命令式寫法很可能被使用者介面給綁架,但在某些情況之下命令式的寫法會比宣告式的寫法來的清楚。重點還是在於:

  • 清楚表達系統行為而非系統實作
  • 當實作方式改變時應該不需要修改系統規格,只需修改實作程式碼與測試自動化程式

***

小心怪味道

有一些鄉民在採行BDD的初期為了減少撰寫自動化驗收測試的時間,會等程式都寫好之後用「capture and replay」(擷取畫面,重複撥放)的工具來產生驗收測試案例。這種做法不能算是BDD,因為並沒有做到「測試先行」,也就是開發流程並沒有先撰寫一個失敗的驗收測試案例,而是反過來先寫production code,再用「capture and replay」的方式產生自動化驗收測試。

這種方式所產生的驗收測試,極度依賴於使用者介面,只要介面一修改,驗收測試往往也需要跟著修改,導致很高的維護成本,最終可能讓開發人員無以為繼,不想繼續維護大量與使用者介面緊密相關的驗收測試。

稍微好一點的,會先用Given-When-Then寫scenario,但很可惜寫出的例子也是從使用者介面思考,依然會造成不易維護的問題。這些都是在落實BDD的初期很容易發生的現象,也是要做好BDD需要突破的一個重要關卡。

***

友藏內心獨白:寫Use Case也不應該有太多介面細節。

2017年1月25日 星期三

從OOAD看User Story Mapping

Jan. 25 10:18~12:25

屏幕截图 2017-01-25 12.20.03

 

一位到大陸工作多年的學弟回台灣過農曆年,昨天下午學弟找Teddy聊天,談談敏捷開發與使用者故事對照(User Story Mapping)。學弟之前念書的時候修過物件導向分析與設計(OOAD),Teddy就從OOAD的角度切入,解釋使用者故事對照在軟體生命週期中所扮演的角色。

▼顧名思義,OOAD包含了兩大內容:A(Analysis,分析)與D(Design,設計)。傳統OOAD在分析的部分採用Use Case來幫需求「塑模」,基於這個Use Case Model接著建立起Domain Model,用來代表問題領域裡面重要的概念以及概念之間的關係。

屏幕截图 2017-01-25 11.03.44

需求分析完成之後,便可以依此來進行開發規劃。例如,在剛開始的若干個迭代(iteration)內將最重要與風險最高的前20% use cases開發完成,並且同時完成軟體架構雛形。

▼下圖是節錄自維基百科的一張use case diagram,每一個橢圓形代表一個use case,也就是一個系統功能。圖中的「火柴人」稱為Actor,代表一種使用者角色。這張use case diagram看起來是一個餐廳管理系統,使用者包含Waiter(服務員)、Client(客人)、Cashier(櫃台)、Chef(廚師)。Actor與use case中間的直線代表這個Actor可以使用這個use case。

屏幕截图 2017-01-25 11.15.20

 

▼接下來看一張使用者故事對照或稱為用戶故事地圖。簡單但不精確地來說,最上面紫色的框框可以想成是一個use case,只不過這些use case現在依據時間軸加以展開,這張地圖首先代表「主要使用者」使用這個系統的歷程。依據時間軸展開這些功能的好處是可以用講故事的方式來敘述與溝通使用者使用系統的方式。

屏幕截图 2017-01-25 11.41.48

 

▼ 如果只是把類似use case這種大粒度的功能模組依據時間展開變成一張圖,那麼這張圖和use case diagram其實差異並不大。從說故事的角度來看,這樣子只能算是有「故事大綱」而已,接下來還要從這個故事大綱展開劇情細節,這才是使用者故事對照精彩的地方。

屏幕截图 2017-01-25 11.45.07

***

有了使用者故事對照(用戶故事地圖)某種程度算是可以取代或是說輔助傳統OOAD裡面的use case diagram,接下來後面要串什麼就看專案的需要。 例如:

  • 採用傳統瀑布式開發:使用者故事對照(用戶故事地圖)可以當成比use case diagram詳細的需求表達方式(如果願意也可以同時建立use case diagram與user story map),在傳統以文件為交接媒介的瀑布式開發流程中,可以幫用戶故事地圖中每一個user story撰寫完整的驗收測試,甚至是包含操作介面雛形作為詳盡需求文件的一部分。
  • 採用Scrum:採用敏捷方的的團隊可以依據這張用戶故事地圖安排產品釋出計畫(release plan),也就是每一個迭代預計要開發那些user story。這張圖可以取代線性的product backlog,讓需求比較像一棵樹,有樹幹也有樹葉。
  • BDD/TDD:在實作上,用戶故事地圖裡面的每一個user story可以做為BDD/TDD開發的需求源頭,接著透過撰寫「可執行規格(executable specification)」來具體化這些user story,並自動確保它們的實作是否完成。
  • 軟體架構:軟體架構主要用來滿足系統的功能與非功能需求,在用戶故事地圖裡主要看到的是功能需求,所以這張地圖可以在專案早期協助我們評估軟體架構是否可以滿足系統的功能性需求。至於非功能性需求,例如安全性、效能、可維護性、可靠性等,就必須要借用其他文件或工具來協助。

***

用戶故事地圖提供一個情境(context)指引團隊方向,避免團隊專心於眼下的開發工作而忘了產品整體目標。它不是什麼神奇工具可以解決所有產品需求的問題,但它的確是一個發展、梳理與溝通需求的好方法。最後打個廣告, 泰迪軟體的「使用者故事對照工作坊 (User Story Mapping Workshop)」 已經確定開課,上課日期為2月12日,對於產品需求管理有需要的朋友請不要錯過。

***

友藏內心獨白:在大陸住久了,聽口音還以為學弟是中國人。

2017年1月24日 星期二

阿嬤覺得你冷

Jan. 24 08:40~10:15

屏幕截图 2017-01-24 10.14.05

還在休育嬰假的老同學今年難得帶著小朋友從日本回台灣過年,昨天中午約了一起吃飯敘舊。同學推著嬰兒車和Teddy走在西門町前的中華路人行道上,昨天氣溫只有10幾度風又挺大的…

Teddy:風這麼大你不用把嬰兒車蓋起來嗎?

同學:喔…還好啦,讓小朋友透透氣。

Teddy:對喔,我去日本玩的時候看到日本小學生冬天也都是穿著短褲就上學了,日本人應該比較不怕冷。不過一般台灣家長在這種天氣帶小朋友出門一定包得緊緊的,深怕小朋友吹到風會感冒。

同學:你知道嗎,「有一種冷叫做阿嬤覺得你冷」,如果是他阿嬤在一定會叫我讓小朋友多穿幾件衣服。

未滿週歲的小朋友還不會開口說話,阿嬤覺得你冷,那你就冷瞜。

***

很多軟體專案也都存在這種「阿嬤覺得你冷」症候群:「有一種需要,叫做RD覺得你要(或覺得你不要)」(RD可以換成業務、行銷、PM、老闆,也都講得通)。客戶、Product Owner與開發人員雖然都有開口說話的能力,但卻不一定有機會經常溝通。就算專案跑Scrum,每個sprint都開planning meeting、review meeting,頻繁的溝通算是做到了,但卻不一定可以做到有效溝通。

敏捷開發的解法除了鼓勵頻繁溝通與回饋之外,還有一些「工具」可以搭配一起服用。例如這一陣子很熱門的「使用者故事對照 (User Story Mapping)」,透過視覺化以時間軸的方式展開用戶使用系統的歷程,讓所有專案相關人員對於要解決什麼問題(目標)、如何解決(功能)、何時解決(優先順序)可以產生共識。

屏幕截图 2017-01-24 09.18.54

 

另一種常見而且可以搭配「使用者故事對照 (User Story Mapping)」一起服用的方式就是BDD(行為驅動開發)。依據《BDD in Action》的說法BDD可以分成以下幾個步驟:

  • 客戶與商業分析師透過談論具體例子來溝通系統功能應該做哪些事
  • 商業分析師與開發和測試人員將這些例子以固定格式轉成一組需求。常見的方式為採用Gherkin格式,也就是Given-When-Then。
  • 開發人員使用BDD工具將用Gherkin寫成的需求轉成自動化測試,並且透過這些自動化測試連結到程式碼,用來客觀地判斷需求是否開發完成。
  • 開發人員使用測試結果作為手動與探索測試(exploratory tests)的起點。
  • 自動化測試作為低階技術文件,並且提供系統如何運作的最新實例。客戶或PO可以檢視測試報告以便得知那些功能已經交付給客戶,以及功能是否如他所預期的工作。

把溝通的結果透用可執行規格(executable specification)來記錄與驗證,「理論上」造成誤解的機率應該大大降低。

***

雖然「阿嬤」的意見有時候是正確的,但總是依靠「阿嬤覺得你冷」來決定產品要做什麼以及不做什麼,似乎不太靠譜。如果你的專案需求大部分還是來自於「阿嬤覺得你冷」,除非「你阿嬤是賈伯斯再世」,否則是時候做些改變了。

***

友藏內心獨白:友藏也覺得好冷。

2016年12月21日 星期三

軟體架構勒?

Dec. 21 16:12~17:17

擷取

 

很多跑敏捷開發的朋友對於在敏捷開發中如何設計軟體架構一直有不少疑問。廣義地說,無論是跑什麼開發流程,軟體架構設計本身都是一個傷腦筋的議題,只不過在傳統Waterfall流程當中,因為有專屬的「軟體架構設計」階段,所以讓人產生一種「在Waterfall中軟體架構設計非常明確」的 錯覺 感覺。實際上,跑Waterfall流程的確可以產生一份非常明確的軟體架構設計,只不過這份軟體架構的實用性經常被開發人員打上一個大問號,和最後開發人員實作出來的軟體系統之間存在很大的差異性,可能「連他爸爸(架構師)都認不出來這是他的親生架構」。

今天聽Erica提到有許多人在上完「使用者故事對照工作坊 (User Story Mapping Workshop)」之後跑來問他,當完成使用者故事對照(用戶故事地圖)之後,要如何將銜接軟體架構的設計。如何設計軟體架構這個問題,Teddy在跑Scrum以及學習User Story Mapping的時候也遇到,以下是Teddy的做法:

  • 套用物件導向設計與分析的做法:Teddy曾經在〈在領域模型上講故事〉文章中提到相關做法,如果把「使用者故事對照」這張地圖類比成UML裡面的Use Case Model,就可以從中找出重要的概念,並使用這些概念建立起軟體系統的「領域模型」。有了這份領域模型,就可以開始施考採用哪種軟體架構風格(software architecture style),例如MVC、Layered、Client-Server、Plug-ins、Microservice等,來「容納」這些重要的概念。
  • 向RUP(Rational Unified Process)學習:RUP也是一種疊代與增量開發方法,除了疊代(iteraion)以外,在RUP當中還將軟體專案分成四個階段:Inception、Elabration、Construction、Transition,每個階段可以包含若干的疊代。第一個階段用來驗證專案的可行性,通常很短,有點類似某些敏捷開發做法所說的「Iteration 0」的味道。第二個階段Elabration結束之後,大概會完成20%的 use case實作(RUP使用use case撰寫需求),主要的專案風險已經被釐清,並且產生「software architecture baseline」。換句話說這個階段結束之後產生軟體架構雛形,這個雛形可以支撐後續Construction階段的主要開發工作。

如果你的專案需求相對比較明確一些,則可以套用RUP的做法,首先透過User Story Map上規劃產品釋出計畫(release plan),或是規畫好幾個「最小可行性產品(MVP)」的學習計畫。把每個release plan開發週期視為一個RUP專案,然後朝向當完成20%最重要的user story的時候,能夠讓軟體架構成型,設計「足夠的軟體架構」來支持這些產品釋出或學習計畫。在每一個疊代週期挑選user story的時候,除了考量user story對客戶的價值以外,有時也要考慮挑選對軟體架構風險比較高的user story優先開發。

  • 重構:敏捷開發的主要目的之一就是要對付複雜的軟體開發專案,也就是要避免「計畫趕不上變化」的情況。所有原本可行的事物,都可能因為「發生改變」而導致失敗。這時候只能藉助重構的力量,讓軟體架構可以重新回到正軌。要讓重構可行,除了需要了解重構的技巧,還必須有足夠的測試案例以及持續整合來驗證重構沒有讓系統「越補越大洞」。

***

接下來打個廣告,泰迪軟體在2017年1月8日舉辦「使用者故事對照工作坊 (User Story Mapping Workshop)」一日課程,歡迎對這個主題有興趣的朋友一起學習、成長。

***

友藏內心獨白:關關難過關關過。

2016年8月3日 星期三

【工商服務】使用者故事對照工作坊

August 02 22:00~22:40

螢幕截圖 2016-08-02 22.36.16

 

身為一個老闆、產品經理、產品負責人(Product Owner)、專案經理、技術主管或開發團隊的一員,針對軟體需求你有以下問題嗎?

  • 如何有系統性的讓產品需求逐步成長?也就是如何用漸進方式探索與管理需求?
  • 只有產品的大方向,卻不知如何展開細項需求?
  • 寫了一堆需求但開發團隊卻總是「目光如豆」,只看到手邊正在開發的需求卻沒有具被產品的整體觀?
  • 如何在迭代式開發流程中(例如Scrum)規劃最小可行性產品(MVP)?
  • 如何溝通客戶、老闆、業務、行銷、測試、開發等不同角色對於產品需求的理解並獲得共識?

九月份新開課程:「使用者故事對照工作坊」(User Story Mapping Workshop)針對上述問題提供藥方。使用者故事(user story)是敏捷開發中用來記錄需求的一種最常使用工具,使用者故事對照(用戶故事地圖)將使用者故事以時間順序展開,讓專案相關人員可以透過視覺化、說故事的方式,逐次展開需求。這張「用戶故事地圖」將引導開發團隊界定問題、映射問題全貌、深入探索問題、訂定產品釋出計畫、安排最小可行性產品與學習策略,最後將產品計畫對應到開發計畫中(安排每個sprint要開發的需求)。

課程內容包含:

  • 使用者故事對照(User Story Mapping)的六步法

    • 構思問題
    • 描繪及對照整體圖像
    • 探索
    • 分割出釋出策略 (Rlease)
    • 分割出學習策略 (Learning)
    • 分割出開發策略 (Development)
  • 深入了解使用者故事(User Story)、生命週期與陷阱
  • 動手練習:

    • Morning Map
    • 逐步聚焦打造最有價值產品
    • Design Studio
    • 應用與案例分享

上課日期2016年9月25(週日) 13:00-18:00,共五小時。

image

***

友藏內心獨白:自己看書太慢不如上課直接吸收日月精華。

2016年5月9日 星期一

透過System Context Diagram講故事

May 06 08:40~10:00

螢幕截圖 2016-05-06 09.59.22

▲畫面節錄自Google搜尋「System Context Diagram」結果

 

前幾天提了〈在領域模型上講故事〉,今天介紹另外一種講故事的方法:System Context Diagram(系統關係圖)。

前一陣子跟Erica討論這學期北科「軟體生命週期管理」課程的專案需求。這學期將全班學生編成三組,在Scrum框架下共同開發一個專案。為了讓專案具體且貼近業界實際狀況,今年的Product Owner改由助教Erica擔任,專案內容就是開發一個支援泰迪軟體開課活動的系統。Erica是Product Owner也是真正的使用者,和學生討論需求會具體很多。

▼Erica首先建好「現況」的user story map(用戶故事地圖):

螢幕截圖 2016-05-06 09.01.12

 

接著應該在這個user story map上以「用戶期待的成果」來講故事,藉此發展新的需求並且安排軟體釋出計畫(release plan)。但是,這個專案比較特別,主要的force(限制)有:

  • 開發時間只有4個為期3周的sprint(共12周)
  • 開發人員是學生(不是全職的專業工程師)
  • 希望學期結束的產出物真正可以派上用場

因此,如果單純以「用戶期待的成果」這個觀點來規劃專案,最後切出來的最小可行性產品(minimum viable product,MVP)不見得可以在4個sprint完成。此外,目前泰迪軟體採用Google表單讓學員填寫報名表,這部分暫時沒有要替換。因此衍伸出「舊系統」(Google表單)與新系統之間的整合問題。理論上「技術問題」主要應交給團隊去傷腦筋,不太需要Product Owner來煩惱。但因為這是學校課程的專案,授課講師(就是Teddy)需要事前規劃讓這個專案可以在一學期內順利進行,所以在撰寫user story與準備產品釋出計畫的同時,不得不先考慮這部份的技術問題。

***

瞪著user story map看了老半天,不容易從上面思考整合的問題。這實屬正常現象,因為從使用者的角度,根本不管你「課程報名採用Google表單,課程其它行政活動支援採用另一個系統」這件事。這是比較偏設計與實作面的問題。

▼怎麼辦?回到OOAD(物件導向分析與設計)老方法,畫個system context diagram來協助思考新系統與其他系統之間的關係:

螢幕截圖 2016-05-06 08.59.04

 

▼畫好system context diagram之後開始在上面「講故事」,最後找出9個最重要的user story作為初始product backlog的內容,然後用便利貼標示它們的優先順序(照片中黃色便利貼)。

螢幕截圖 2016-05-05 23.52.58

***

接下來事情就簡單很多了。回到user story map,此時思考幾種情境:

  • 立即享受:開課單位(泰迪軟體)想要在最短的時間內獲得這個系統的幫助。
  • 最大痛苦解除:目前哪些活動最花時間、最容易出錯?
  • 最完美狀況:在最理想的情況下,這個系統需具備哪些功能?例如有自己的報名功能、可以串接金流、開立電子發票、學員關係管理等。如果達到這個狀態,這個系統本身也可以拿去賣錢了XD。

考量到只有12周的開發時間,最後選擇「最大痛苦解除」作為第一個釋出計畫的目標。有了目標之後,在回頭重新檢視需求的優先順序,就容易許多。

***

這整個準備過程中還有遇到很多細節,例如因為技術問題(與Google表單整合)而「綁架」了user story的優先順序安排。Product Owner最痛苦的點就是每次課程結束之後要花很多時間製作與寄發學員結業證書,因此自動製做與寄發結業證書的user story價值最高,優先權也最高。但是,問題來了,學員的所有資料都在Google表單裡面,這些資料沒有匯入到新系統裡面,怎麼自動寄發結業證書?那到底匯入資料的user story要先做,還是寄發結業證書的user story要先做?此外,三個開發團隊如何處理具有相依性的user story?這些都是需要思考與解決的問題。

***

友藏內心獨白:魔鬼藏在細節中。

2016年5月6日 星期五

在領域模型上講故事

May 05 15:52~17:10

螢幕截圖 2016-05-05 17.05.09

▲畫面節錄自滾石愛情故事 In Love臉書貼文。

 

User story(用戶故事)是許多敏捷開發團隊用來溝通需求與建立共識(shared understanding)的方法。在Scrum框架中,sprint planning meeting與product backlog refinement workshop(PBR)是Product Owner(PO)與團隊討論user story內容的主要場合。常見的討論模式有:

  1. PO念完story card上面所撰寫的user story內容,然後口頭解釋再請團隊發問。
  2. 同1,但PO同時還準備草圖(假畫面)、操作流程等輔助資料。
    螢幕截圖 2016-05-05 23.50.03
    ▲參考畫面與操作流程
  3. 同1或加上2,PO與團隊討論結束後,為了確認團隊真的有聽懂,PO請團隊寫下每一個user story的驗收條件(acceptance criteria),雙方透過檢視user story的驗收條件作為是否已經建立共識的依據。
  4. 採用user story mapping的團隊,可以直接在user story map(用戶故事地圖)上透過講故事的方式來解釋需求。

螢幕截圖 2016-05-05 23.48.39

▲User Story Map

***

今天在北科上課的時候,有一位學生甲針對目前這個sprint正在開發的user story—「為了知道報名是否成功,身為學員,當我送出報名資料後希望立即收到報名結果通知」問了一個問題…

學生甲:不同的課程(例如Design Pattern與Scrum)寄發的報名成功email通知內容都不同,例如課名、課程網址不同。這個user story我們只要建立一種課程的通知就好,還是要完成好幾種課程的通知?

Teddy:這兩者有什麼不同?

▼當下學生甲也不太清楚要如何解釋這兩者的差異,於是Teddy請全班學生一起幫這個user story建「領域模型」(domain model,又稱為概念模型,conceptual model)。

螢幕截圖 2016-05-05 17.16.26

 

最後找到幾個重要的概念:

  • Student
  • Class
  • RichText eMail Template
  • eMail

以下開始講故事:「【學生】選【課程】成功之後,【課程】依據設定好的【電子郵件範本】寄出【電子郵件】」。

現在回到學生甲的問題,不同課程寄發電子郵件通知的時候,郵件的內文會不一樣,例如課名、課程網址等資料會改變。原本學生甲認為這種改變會影響user story的scope(範圍),造成工作量增加,所以詢問Teddy這個user story只要針對一個課程寄發報名成功的電子郵件就好,還是要支援多個課程?

上圖這個簡單的domain model其實已經回答了這個問題:支援一個課程就等於支援多個,因為只要把變動的資料(課名、課程網址)記錄在Class類別即可,即便只有一個電子郵件的範本,也可以支援多個課程的報名成功通知。

***

這個domain model其實已經包含了一點點設計的概念,不過不算嚴重且有助於團隊釐清需求,所以尚可接受。一個簡單的domain model,有時比千言萬語還要來的有助於建立共識(shared understanding)。

***

友藏內心獨白:不要光唱歌,要講故事XD。

2016年5月2日 星期一

會用才算學會

April 29 11:23~12:03

擷取

 

▼4月28日在北科上課,進行第二個sprint的planning meeting。Product Owner帶來9個user story(用戶故事),在介紹完這9個user story之後,請三組學生先從前三個最重要的user story開始挑選:

擷取

 

因為「寄證書」、「開課程」、「匯入舊有報名資料」這三個user story之間有很大的相依性,各組挑選完各自要做的user story之後開始討論要如何合作。此時突然聽到有學生說「資料庫」、「key」等實作層面的字眼,於是Teddy請他們暫停討論,嘗試先找出這三個user story中的重要「概念」以及概念彼此之間的關係。

▼後來大家一起找到四個概念:證書、課程、學員、信。

擷取

 

透過這個簡單的「概念模型(conceptual model,又稱為domain model)」,能夠清楚看出這三個user story之間的關係,不需要討論到資料庫設計或是使用者介面這些實作細節。這其實就是學生在OOAD(物件導向分析與設計)課程所學到有關「分析」的方法。這些方法學生都知道,但是當他們遇到問題(story之間有何關係?)的時候,當下的直覺反應還是回到自己舊有的解題習慣,從「解法、實作面」來思考。

這是一個很常見的現象,代表新學到的方法或技術,還沒有成為自己不可分割的一部分,所以遇事又打回原型,沿用自己最習慣的老方法來解決問題。

當天三小時的課程體驗到很多有趣的事,Teddy並沒有教學生什麼新的東西,只是提醒他們在什麼時間點,可以採用哪些他們已知的方法來處理問題,僅此而已。

學了100種方法但從不使用,不如好好使用1種有用的方法。

***

友藏內心獨白:OOAD真的很重要。

2016年4月29日 星期五

品質的取捨

April 26 08:53~10:21

擷取

 

4/21日第44次C. C. Agile活動邀請阿官來分享他在新創公司工作,奮鬥兩年的「失敗經驗」。創業的道理書上也許都有寫,但「當局者迷」,當自己身歷其境的時候,反倒察覺不出來。在阿官的結論中,提到一個觀點:「對新創公司而言,找到對的問題比做出功能來的重要。」

擷取

 

▼因此當你確定產品真的有市場之前,「品質不是那麼重要」。

擷取

 

▼換句話說,需求比品質來的重要。

擷取

***

除了阿官以外,網路上也有很多人分享過類似的經驗,有些人甚至用更聳動的方式宣稱:「對新創公司而言,什麼品質、流程都不重要,最重要是驗證你的產品符合客戶需要」。

品質到底重不重要?如果重要,是軟體生命週期中一直都重要,還是某個時間點之後才重要?可以透過犧牲品質來達成其他的目標嗎(例如趕工的時候犧牲品質)?

這個問題可以放到建築師Alexander的pattern框架中來思考。如果問題是:「品質是否重要?」為了回答這個問題,要先探索這裡所討論的「context」(情境)是什麼?以吃飯為例,用餐的品質是否重要?如果你是 金正恩 好野人或富二代,每餐都要到「星級餐廳」用餐可能是你的最低標準。如果你是三級貧戶或是正處於鬧飢荒時期的遊民,只要能夠維持生命跡象,任何可以入口的東西可能都是選項。

一個東西或是屬性的重要性,經常是經過權衡、取捨之後的判斷。例如,行車的安全性重不重要?當然重要啊,但你不會為了提高安全性而買一台坦克車上路,因為這樣就太over了。現實狀況是,你很可能為了經濟性的理由而犧牲(一點點)安全性。例如,因為價錢而選擇日系車款而非號稱「鋼板很厚」的歐系車款。

取捨的依據來自於達到force(作用力)之間的平衡關係。回到阿官的例子,他建議「當你確定產品真的有市場之前,品質不是那麼重要。」所以「尋找符合市場的產品」這個作用力在某個時間點大於「提供高品質產品」這個作用力。但是,這個取捨點不能太超過,導致「品質過低以至於妨礙新創公司尋找符合市場的產品」,取捨錯誤因此無法完成原本想要達到的目標。

***

很多問題的答案不是Yes/No那麼絕對,而是什麼東西多一點,什麼東西少一點的取捨平衡。「品質不是那麼重要」並不表示「品質(完全)不重要」。從Scrum的角度來談,你的DoD(definition of done)在「product market fit(PMF)」之前可以「鬆一點」,在PMF之後應該要嚴謹一點,這也是很常見的一種做法。

***

友藏內心獨白:對新創公司而言,老闆口袋的深度最重要。