作者 | 李響
故事卡應(yīng)盡量簡(jiǎn)練,而非事無巨細(xì)應(yīng)寫都寫;同時(shí),應(yīng)盡量完整、準(zhǔn)確,而非缺少細(xì)節(jié)、模棱兩可。
這是我的基礎(chǔ)觀點(diǎn),我的考慮如下:
- 簡(jiǎn)練意味著讀者獲取的信息是經(jīng)過提煉的,讀者閱讀起來是更高效的。
- 簡(jiǎn)練意味著 BA 寫卡可以更高效,可以投入更多精力在其他更具挑戰(zhàn)的工作內(nèi)容上。
- 完整、準(zhǔn)確意味著故事卡是經(jīng)過討論并達(dá)成一致的。
- 完整、準(zhǔn)確意味著故事卡是有著清晰驗(yàn)收標(biāo)準(zhǔn)的。
- 完整、準(zhǔn)確意味著故事卡是便于追溯、便于傳遞的。
- ……
基于以上觀點(diǎn)再分類別展開聊下。
關(guān)于對(duì)頁(yè)面交互的描述
上圖展示了一個(gè)添加新賬號(hào)功能的 UI 設(shè)計(jì)。一種對(duì)該功能需求的描述可能是:
- 用戶通過主菜單進(jìn)入“權(quán)限管理”模塊,選擇“賬號(hào)管理” Tab 頁(yè),可以看到“新增賬號(hào)”按鈕。
- 點(diǎn)擊“新增賬號(hào)”按鈕,系統(tǒng)彈出新增賬號(hào)窗口(可能還會(huì)寫一句“背景置灰”)。
- 用戶可在窗口中填寫姓名、登錄郵箱……
- 若用戶未填寫必填字段,則點(diǎn)擊“確認(rèn)”時(shí)給出錯(cuò)誤提醒“請(qǐng)完成所有必填字段的填寫!”
- 點(diǎn)擊“確認(rèn)”按鈕后彈出二次確認(rèn)窗口,二次確認(rèn)信息為“確認(rèn)創(chuàng)建該賬號(hào)?賬號(hào)一旦創(chuàng)建成功即會(huì)郵件通知對(duì)應(yīng)用戶”。用戶再次選擇“確認(rèn)”則系統(tǒng)創(chuàng)建賬號(hào),若用戶選擇“取消”則返回填寫賬號(hào)窗口。
這些文字描述沒有任何錯(cuò)誤,應(yīng)該還符合不少 Dev 同學(xué)或 QA 同學(xué)的胃口,但在我看來過于臃腫。嘗試思考簡(jiǎn)化哪些信息不會(huì)影響 Dev 編碼和各角色理解業(yè)務(wù):
(1) 詳細(xì)的操作步驟描述是否必要?
通常是不必要的。一般情況下設(shè)計(jì)圖或簡(jiǎn)單的溝通是很容易表達(dá)這些內(nèi)容的,故事卡中簡(jiǎn)單地表述主要路徑即可,詳細(xì)的描述反而約束了設(shè)計(jì)和實(shí)現(xiàn),并且讓故事卡變得臃腫。
(2) 描述所有字段是否有必要?
通常是需要的,但應(yīng)該是從業(yè)務(wù)角度描述,后文有詳細(xì)聊到。
(3) 詳細(xì)地描述用戶操作后的系統(tǒng)反饋是否有必要?
通常不是必要的,因?yàn)榻^大多數(shù)的系統(tǒng)反饋是約定俗稱或顯而易見的。比如 popup 窗口下方的頁(yè)面是被置灰的,popup 窗口上的“取消”按鈕點(diǎn)了后會(huì)關(guān)閉窗口,等等。那什么是“不通常”的情況呢?常見的是期望系統(tǒng)根據(jù)業(yè)務(wù)目標(biāo)給出的反饋,比如我會(huì)注明“創(chuàng)建用戶成功后頁(yè)面應(yīng)跳轉(zhuǎn)回列表頁(yè)”,因?yàn)槲抑拦芾韱T通常會(huì)批量創(chuàng)建多個(gè)用戶,這樣效率更高。
(4) 二次確認(rèn)功能中的文案是否有必要詳細(xì)描述呢?
很多時(shí)候是需要的,因?yàn)檫@些文案通常是想表達(dá)特定的業(yè)務(wù)含義的,用完美的文案將這層業(yè)務(wù)含義表達(dá)出來是 BA 的職責(zé)。那反過來的情況呢?比如一些常規(guī)的刪除操作的確認(rèn)文案就不需要一一描述,可以與團(tuán)隊(duì)約定好所有的刪除操作都需要二次確認(rèn),所有的二次確認(rèn)文案都是“確認(rèn)刪除該xx?刪除后不可恢復(fù)”,如有特殊情況再單獨(dú)表述。
那么對(duì)于上面的需求,我的描述會(huì)是這樣的:
權(quán)限管理員可創(chuàng)建新的用戶:
(1) 路徑:后臺(tái)管理端 - 權(quán)限管理 - 賬號(hào)管理 - “新增賬號(hào)” button
(2) 新增賬號(hào)所需字段
- 姓名…
- 登錄郵箱…
- ……
(3) 確認(rèn)創(chuàng)建賬號(hào)需二次確認(rèn),文案“確認(rèn)創(chuàng)建該賬號(hào)?賬號(hào)一旦創(chuàng)建成功即會(huì)郵件通知對(duì)應(yīng)用戶”
簡(jiǎn)單總結(jié)一下,在我的觀點(diǎn)中,故事卡通常不應(yīng)對(duì)頁(yè)面交互做過多描述,這樣可能會(huì)約束設(shè)計(jì)和實(shí)現(xiàn),還容易讓故事卡失去業(yè)務(wù)焦點(diǎn)。但若某個(gè)期望的交互具有獨(dú)特性或交互本身就是重要的驗(yàn)收點(diǎn),那么將他們簡(jiǎn)練、準(zhǔn)確地表述出來也是必要的。
關(guān)于對(duì)業(yè)務(wù)邏輯的描述
這里的業(yè)務(wù)邏輯可以狹義地理解為功能需求中的規(guī)律或規(guī)則,是我認(rèn)為“如果有則必須體現(xiàn)在故事卡”的內(nèi)容。我的理由如下:
- 它們通常是適配特定業(yè)務(wù)場(chǎng)景的,不是可以通過普遍認(rèn)知推導(dǎo)出來的。
- 它們通常是核心的,直接決定著需求是否能達(dá)到預(yù)期收益。
- 它們通常是復(fù)雜的、難以記憶的。
所以我們可以直接討論下如何簡(jiǎn)潔、準(zhǔn)確地描述這些規(guī)則。
曾經(jīng)處理過一個(gè)關(guān)于預(yù)約送貨的需求。背景是客戶采購(gòu)“我們”的商品,物流承運(yùn)商負(fù)責(zé)將貨物運(yùn)送到客戶倉(cāng)庫(kù),但客戶倉(cāng)庫(kù)常出現(xiàn)沒有可用倉(cāng)位而導(dǎo)致承運(yùn)商送貨到庫(kù)卻又無法卸貨入庫(kù)的情況。解決方案是客戶側(cè)開發(fā)預(yù)約留庫(kù)位功能并提供接口,我們調(diào)用該接口,告訴客戶方系統(tǒng)預(yù)計(jì)送貨信息,客戶系統(tǒng)對(duì)應(yīng)預(yù)留倉(cāng)位并反饋期望送貨時(shí)間,承運(yùn)商確認(rèn)后按該時(shí)間送貨。
這個(gè)業(yè)務(wù)場(chǎng)景的特點(diǎn)在于每個(gè)節(jié)點(diǎn)都有多種不確定性,由此為后續(xù)流程帶來不同的影響。在業(yè)務(wù)已經(jīng)梳理清晰的前提下,這其實(shí)就是一個(gè)如何表達(dá)結(jié)構(gòu)化信息的問題。
首先試下 Given When Then 的表達(dá)方式:
AC01 預(yù)約日期在窗口范圍內(nèi)
When 客戶系統(tǒng)返回了“在預(yù)約窗口范圍內(nèi)”的預(yù)約日期
Then 郵件通知承運(yùn)商確認(rèn),變更預(yù)約單狀態(tài)為“待承運(yùn)商確認(rèn)”
AC02 預(yù)約日期在窗口范圍外
When 客戶系統(tǒng)返回了“不在預(yù)約窗口范圍內(nèi)”的預(yù)約日期,且未人工確認(rèn)
Then 郵件通知銷售負(fù)責(zé)人協(xié)調(diào)處理,變更預(yù)約單狀態(tài)為“待銷售確認(rèn)”
AC03 預(yù)約日期已人工確認(rèn)
WHEN 客戶系統(tǒng)返回了“不在預(yù)約窗口范圍內(nèi)”但被標(biāo)記為“已人工確認(rèn)”的預(yù)約日期
Then 預(yù)約成功,變更預(yù)約單狀態(tài)為“預(yù)約完成”,郵件通知承運(yùn)商按預(yù)約日期送貨
……
看起來能把每個(gè)細(xì)節(jié)表達(dá)清楚,但可讀性比較差,讀者可能需要額外的 effort 才能理清各場(chǎng)景間的邏輯關(guān)系。
然后嘗試下 “BA 式” 的偽代碼:
「
If 約定時(shí)限內(nèi)獲取到了客戶系統(tǒng)反饋的預(yù)約日期
{
if 日期在預(yù)約窗口范圍內(nèi)
郵件通知承運(yùn)商確認(rèn),變更預(yù)約單狀態(tài)為“待承運(yùn)商確認(rèn)”;
else if 日期已人工確認(rèn)
預(yù)約成功,變更預(yù)約單狀態(tài)為“預(yù)約完成”
else
郵件通知銷售負(fù)責(zé)人協(xié)調(diào)處理,變更預(yù)約單狀態(tài)為“待銷售確認(rèn)”
}
else…
」
邏輯關(guān)系表述清楚了,但閱讀大段滿載邏輯的文字的體驗(yàn)仍然不好,似乎可以再簡(jiǎn)潔點(diǎn)。
最終我將這些規(guī)則用狀態(tài)轉(zhuǎn)換圖描述出來,然后與 Dev 和 QA 同學(xué)溝通是否可以用這張圖當(dāng)做驗(yàn)收條件。在與他們講解了這個(gè)圖后,大家認(rèn)為只要對(duì)圖中各節(jié)點(diǎn)的業(yè)務(wù)意義達(dá)成一致并約定好 Scope(而這些是比較容易的),這樣的表述是更清晰、更友好的,于是我們愉快地接受了這種方式。
簡(jiǎn)單總結(jié)一下,在我看來,對(duì)業(yè)務(wù)邏輯的表述是寫故事卡的重點(diǎn)和難點(diǎn),BA 應(yīng)該結(jié)合項(xiàng)目和需求特征選擇最佳表達(dá)形式,不用拘泥于固定的格式,其中圖表經(jīng)常是不錯(cuò)的選擇。關(guān)于圖表的使用有以下 tips 供參考:
- 復(fù)雜條件組合產(chǎn)生不同系統(tǒng)行為 (比如積分判定規(guī)則)> 判定表、判定樹或事件 - 響應(yīng)表
- 復(fù)雜狀態(tài)規(guī)則(比如訂單狀態(tài)規(guī)則)> 狀態(tài)流轉(zhuǎn)圖或狀態(tài)表
- 復(fù)雜業(yè)務(wù)流程 (比如采購(gòu)流程)> 業(yè)務(wù)流程圖
- ……
另外,團(tuán)隊(duì)需要就如何理解這些新的表達(dá)方式達(dá)成一致。
關(guān)于對(duì)列表和表單的描述
列表和表單是最常見和最基礎(chǔ)的需求,往往套用固定的模式就可以將其表述清楚。
列表類需求常見的幾要素:
- 功能權(quán)限:誰在什么條件下可以使用該表單
- 數(shù)據(jù)權(quán)限:數(shù)據(jù)范圍的控制通常體現(xiàn)在列表上,比如用戶僅可見owner 是他自己的訂單記錄。
- 排序規(guī)則:列表中的記錄通常需要按一定的規(guī)則進(jìn)行排序以便查看
- 分頁(yè)規(guī)則:如果某些列表中可以預(yù)見地記錄不會(huì)太多,那么不一定需要分頁(yè),Dev 可以更簡(jiǎn)單地處理這樣的列表。
- 字段清單:對(duì)列表中所有字段的描述。UX 的設(shè)計(jì)圖中會(huì)有這部分內(nèi)容的體現(xiàn),但經(jīng)驗(yàn)看來設(shè)計(jì)圖中不容易也不需要很及時(shí)地反饋?zhàn)侄蔚淖兓谀承l件下設(shè)計(jì)圖也無法體現(xiàn)所有字段。
- 字段屬性:字段對(duì)應(yīng)的業(yè)務(wù)含義,告訴讀者這個(gè)字段的值從何而來,如果某字段有特殊規(guī)則也可以在這里體現(xiàn)。比如【持續(xù)時(shí)長(zhǎng)】字段是為了方便用戶查看,實(shí)際不對(duì)應(yīng)數(shù)據(jù)庫(kù)字段,那這里就可以描述它的取值規(guī)則為“【當(dāng)前時(shí)間】 - 【開始時(shí)間】,向上取整天”;再比如【門店名稱】通常較長(zhǎng)但又很重要,我會(huì)描述“鼠標(biāo)hover 在【門店名稱】時(shí)可查看其完整信息”。
一個(gè)有關(guān)列表的驗(yàn)收條件參考如下:
AC01 查看發(fā)貨單列表:
(1) 路徑:主菜單 > 發(fā)貨單列表
(2) 功能權(quán)限:權(quán)限管理中新增“查看發(fā)貨單”權(quán)限,僅具有該權(quán)限的用戶可見“發(fā)貨單列表”菜單并訪問列表數(shù)據(jù)
(3) 數(shù)據(jù)權(quán)限:承運(yùn)商用戶僅可查看他負(fù)責(zé)的發(fā)貨單,銷售用戶僅可查看他負(fù)責(zé)的客戶的發(fā)貨單,其他角色可見所有發(fā)貨單
(4) 排序規(guī)則:按發(fā)貨單創(chuàng)建時(shí)間倒序排列
(5) 分頁(yè)規(guī)則:15個(gè)/頁(yè)
(6) 字段詳情及順序
- 【發(fā)貨單創(chuàng)建時(shí)間】系統(tǒng)接收到承運(yùn)商 TMS 系統(tǒng)推送的發(fā)貨單的時(shí)間,精確到分鐘
- 【發(fā)貨單號(hào)】承運(yùn)商 TMS 系統(tǒng)的發(fā)貨單號(hào)
- 【門店訂單號(hào)】發(fā)貨單對(duì)應(yīng)門店訂單的編號(hào)
- 【門店名稱】發(fā)貨單對(duì)應(yīng)的收貨門店名稱,鼠標(biāo) hover 可查看完整名稱
- ……
關(guān)于表單類功能需求
表單通常是用于創(chuàng)建記錄、更新記錄、查看記錄的詳細(xì)信息,相比列表類需求對(duì)字段屬性的描述有以下幾點(diǎn)需要注意:
- 是否必須。
- 數(shù)據(jù)類型:比如對(duì)于時(shí)間類型字段,前端同學(xué)會(huì)處理為日期&時(shí)間選擇器。
- 校驗(yàn)規(guī)則:比如對(duì)用戶名格式或?qū)γ艽a復(fù)雜度的校驗(yàn)。
- 若是pick list,那么選項(xiàng)是什么:選項(xiàng)可能是一些枚舉值,也可能是自另外的一個(gè)業(yè)務(wù)實(shí)體(比如為訂單選擇客戶),需要詳細(xì)說明。
- 字符長(zhǎng)度:從業(yè)務(wù)角度給出字段長(zhǎng)度建議。
所以某個(gè)表單的描述可能是這樣的:
(1) ……
(2) 字段詳情及順序
- 【姓名】必填,50字符
- 【出生年月】必填,日期類型
- 【省份】必填,單選,從基礎(chǔ)數(shù)據(jù) region 表中取值
- 【城市】必填,單選,從基礎(chǔ)數(shù)據(jù) region 表中取值,與【省份】聯(lián)動(dòng)
- 【家庭成員數(shù)量】必填,正整數(shù)
- 【聯(lián)系郵箱】非必填,100字符,校驗(yàn)為郵箱格式
- ……
這里面也有幾個(gè)可以探討的問題:
(1) 對(duì)于【聯(lián)系人郵箱】字段,通常會(huì)有對(duì)于郵箱格式的校驗(yàn)。那么 BA 在故事卡里是否需要詳細(xì)描述校驗(yàn)規(guī)則?
我的建議是沒必要。因?yàn)猷]箱的格式校驗(yàn)是一個(gè)有著“普遍認(rèn)同”的規(guī)則,并不具備獨(dú)特的業(yè)務(wù)價(jià)值,不該因?yàn)?BA 的表述不同而不同。所以,這種問題可以交給 Dev 同學(xué)。
(2) 是否需要以及如何描述字符長(zhǎng)度/數(shù)值范圍?
我的建議是可以描述。以字符長(zhǎng)度為例,大多數(shù)字段其實(shí)是比較容易推斷出字符長(zhǎng)度的,比如“訂單狀態(tài)”,10個(gè)字符足矣,Dev 和 BA 從各自視角判斷通常也偏差不大。那既然如此,BA 就順手寫出來吧,更何況存在某些字段在特定業(yè)務(wù)場(chǎng)景下有特殊要求的可能。
可能還有其他問題可以進(jìn)一步討論,但總而言之,對(duì)于列表和表單類需求通??梢詮?fù)用一套模板,再結(jié)合業(yè)務(wù)場(chǎng)景調(diào)整就可以搞定。
關(guān)于對(duì)接口的描述
個(gè)人最喜歡的就是接口類的故事卡了,無他,但簡(jiǎn)單爾。
對(duì)于接口類需求,我通常做法是:
- BA 定義好接口業(yè)務(wù)上的數(shù)據(jù)結(jié)構(gòu)、業(yè)務(wù)主鍵
- 與 Dev 線下討論達(dá)成一致
- Dev 補(bǔ)充技術(shù)細(xì)節(jié)形成接口文檔
- 把接口文檔附在故事卡里,補(bǔ)充業(yè)務(wù)場(chǎng)景、調(diào)用頻率(對(duì)于主動(dòng)拉取數(shù)據(jù)類接口)、錯(cuò)誤處理機(jī)制(比如提交訂單失敗后應(yīng)重試還是立即報(bào)錯(cuò))、接口獲取/提供的信息的特殊處理(比如外系統(tǒng)給到的訂單我們要按照自己的規(guī)則生成新的訂單編號(hào))等必要信息。
最后,對(duì)用戶故事業(yè)務(wù)價(jià)值的描述和故事卡的拆分也簡(jiǎn)單分享下我的理解
我非常贊同每個(gè)故事卡都應(yīng)該產(chǎn)生業(yè)務(wù)價(jià)值,并且我們應(yīng)當(dāng)將這個(gè)價(jià)值顯式地表達(dá)出來。而實(shí)踐下來,我發(fā)現(xiàn)一段“freestyle” 式的描述常常比“作為一個(gè) <角色> , 我想要 <功能> , 以便于 <業(yè)務(wù)價(jià)值> ”這樣的表述方式更容易上手。
比如,某個(gè)需求是從主數(shù)據(jù)系統(tǒng)定時(shí)獲取最新的產(chǎn)品主數(shù)據(jù),那么我會(huì)用這樣的一段文字來描述:
Summary:當(dāng)前條件下,系統(tǒng)中的產(chǎn)品數(shù)據(jù)來自于每月客戶側(cè)產(chǎn)品經(jīng)理給到的Excel 文件更新??蛻糇灾餮邪l(fā)的主數(shù)據(jù)平臺(tái)已與上個(gè)月正式上線,并對(duì)外提供了數(shù)據(jù)分發(fā)接口,我們可以通過它提供的產(chǎn)品主數(shù)據(jù)接口每天獲取產(chǎn)品主數(shù)據(jù)的更新,以解決手工更新帶來的更新不及時(shí)、手工處理出錯(cuò)等問題。
基于這種更自然的表達(dá)方式,我可以輕松地描述更多有價(jià)值的信息。
最后是我對(duì) INVEST 原則(好的用戶故事的編寫應(yīng)滿足的幾個(gè)原則)的一些理解:
- 獨(dú)立性(Independent) :應(yīng)盡量避免故事間的強(qiáng)依賴,但若必須有強(qiáng)依賴,那么這些卡片應(yīng)該可以在同一個(gè)迭代中完成。非獨(dú)立的故事會(huì)造成估算、排優(yōu)先級(jí)和制定技術(shù)方案的難度。避免強(qiáng)依賴的方法可以有合并故事卡、換個(gè)維度拆分故事等,實(shí)在不行也不用強(qiáng)求,按依賴排好優(yōu)先級(jí)即可。
- 可討論的(Negotiable):實(shí)現(xiàn)方案是可討論的,但業(yè)務(wù)目標(biāo)應(yīng)是明確的;討論是必要的,對(duì)方案達(dá)成一致更不可缺少;可討論不是BA 不去提前思考具體解決方案的借口,更不是卡片中驗(yàn)收標(biāo)準(zhǔn)不明確的說辭。
- 有價(jià)值(Valuable):我想不出我們?nèi)プ鲆粋€(gè)沒有價(jià)值的需求的理由…… 姑且把這一條理解為在寫下這張卡片時(shí)我們應(yīng)該已充分了解它能解決的問題或帶來的收益,并且所有角色已經(jīng)對(duì)此達(dá)成一致。
- 可以估算(Estimable):估算通常是為了排期,為了可以估算故事的規(guī)模應(yīng)該足夠小,團(tuán)隊(duì)對(duì)故事應(yīng)該有充分的了解,并可以就故事內(nèi)容對(duì)技術(shù)實(shí)現(xiàn)方案基本達(dá)成一致。
- 足夠小(Small):更小的故事有助于更準(zhǔn)確的工作量評(píng)估或多人并行工作,可以讓故事卡在卡墻上更快流動(dòng)起來,但也不必過分追求小故事,不少情況下 Dev 一次代碼提交同時(shí)處理兩個(gè)關(guān)聯(lián)需求要比先后處理這兩個(gè)需求要更簡(jiǎn)單、高效,如果 Dev 經(jīng)常說“這幾張卡我一起開了吧”或“關(guān)了吧”時(shí),BA 可以請(qǐng)教一下他的想法,也許能發(fā)現(xiàn)值得改進(jìn)的地方。
- 可測(cè)試(Testable):故事卡中描述的輸入和輸出是明確的、可度量的。
文章的最最后,再總結(jié)下我的觀點(diǎn)
- 我認(rèn)同故事卡里非常詳細(xì)的描述可以帶來價(jià)值,但我也相信“簡(jiǎn)練的表述 + 充分的溝通”可以更高效、更靈活。
- 我認(rèn)同故事卡不是契約或合同,但我也相信完整、準(zhǔn)確的表述可以顯著降低各角色間的溝通成本。
- 我認(rèn)同可工作的軟件高于詳盡的需求文檔,但我也相信高質(zhì)量的需求文檔可以帶來很多收益。
- 我認(rèn)同最佳實(shí)踐和個(gè)人經(jīng)驗(yàn)(包括本文以上所有內(nèi)容)的參考價(jià)值,但我更相信因地制宜、團(tuán)隊(duì)共建的實(shí)踐才是最好的選擇。