學生門戶示例
一所社區學院希望開發一個學生門戶,以提供學生在線服務。他們邀請了一名學生代表、部門職員以及門戶管理員成員組成團隊,參與學生門戶開發項目。以下是第一次會議的會議記錄。
利益相關者會議
議程
- 建議學生門戶的功能
- 討論所提功能清單的可行性
- 優先排序功能,作為核心功能、下一階段、可選功能等……
史蒂夫(開發團隊):歡迎……我們希望讓會議更具成效。當你們提出希望擁有的功能時,可以使用以下格式作為標準表達方式:誰(你是誰),想要什麼功能,以及為什麼想要它……這些功能將以使用者故事的形式記錄下來,作為本項目中溝通的工具。
接著,我們從不同利益相關者中集思廣益,列出了一系列使用者故事:
學生代表:註冊課程、繳交學費、查看時間表、編輯時間表、查看成績單、退選課程……
學術代表:新增課程資訊、編輯課程資訊、刪除課程資訊……
門戶管理員:備份課程資訊、編輯學生帳戶狀態
現在,我們有一堆卡片,可以整理成行和列

優先排序所提功能
開發團隊代表:我們有一份已優先排序的使用者故事清單,將在下一個迭代中實施。為此,我們需要針對每個使用者故事深入探討,以獲得更多資訊。讓我們來逐一檢視第一個核心功能「註冊課程」的使用者故事

我們從終端使用者獲取了以下額外資訊:
- 學術代表:學生必須是註冊的全日制學生
- 管理員:學生必須提供正確的帳戶憑證才能登入
- 學術代表:該課程尚未滿額
- 學術代表:必須滿足課程先修條件
- 管理員:選定加入時間表的課程,不得與其他課程的時段衝突
- 開發人員:你希望這個功能在目標系統中與哪些其他功能一起列為一組?
- 學生:退選課程、查看時間表、編輯時間表。
使用者故事的三C
優秀的使用者故事遠不止是陳述句。一個標準的使用者故事包含三個部分,通常稱為三C。每個使用者故事的第一個「C」應遵循標準格式:作為[角色],我想要[做某事],以便[獲得利益],這是最少應放入卡片中的內容。第二個「C」即對話(Conversations),代表終端使用者、專案負責人與開發團隊之間的討論內容。在這些對話中,會記錄口頭討論,以及其他有用資訊,例如電子郵件、線框圖或任何與專案相關的內容。使用者故事的最後一個「C」是確認(Confirmation),即用來確認使用者故事是否正確實現並成功交付的驗收標準。
讓我進一步說明如何開發使用者故事的確認部分。在這裡,我們使用最廣為人知的模板,稱為 Gherkin,它採用 Given-When-Then 的公式,以指導撰寫使用者故事的驗收測試:
- (Given.. and) 某些情境
- (When.. and) 執行某些動作
- (Then.. and) 執行某些動作
像 Cucumber 和 Jbehave 測試框架之類的工具,鼓勵使用 Given/Then/Then 模板進行自動化測試,儘管它也可以純粹作為一種啟發式方法使用,而不論是否使用工具。
讓我們收集「註冊課程」使用者故事的所有資訊,並以 3Cs 格式呈現:

現在,讓我們將這些資訊放入 UeXceler 中,其中包括我們先前開發的轉換與確認內容。

將巨集拆分為使用者故事
如果我們進一步深入探討「註冊課程」使用者故事,可能會發現它太大,無法放入一個迭代中。我們可以將其視為一個巨集(更大的使用者故事),可拆分為一組相關的較小使用者故事。我們可以將巨集拆分為任務,我稱之為水平拆分;或者,我們也可以將巨集拆分為情境,稱為垂直拆分。
水平拆分
傳統上,建構大型功能的方式是將其分解為各個架構層級所需完成的工作。例如,模型-檢視-控制(MVC)或客戶端-伺服器架構,以便為系統架構實現關注點分離,並進一步細化為多層架構,例如 GUI、控制邏輯、物件模型、物件關聯映射、資料庫層等。多層架構包含許多層級,我在此僅列出其中幾項:
- 讓我們能在某個架構層級上發展高深專業知識
- 其他應用程式將能夠重用由您的層級所公開的功能。
- 您能夠將您的層級分散到多個實體層級上。這可以對您的應用程式產生極大影響,提升效能(有時)、可擴展性與容錯能力。
- 由於各層之間的耦合度低,您的應用程式維護起來更簡單。
- 為您的應用程式增加更多功能變得更容易。
- 層級讓您的應用程式更具可測試性。
基於多層架構的成功實例非常多,例如 Ruby on Rails 和基於 Web 服務的架構。
使用者故事與水平拆分
雖然多層架構為我們的系統帶來許多好處,但當我們與使用者故事方法結合使用時,也存在一些缺點。根據功能的大小,它往往會導致非常緩慢的反饋循環,因為我們必須等待每個人完成各自的部分後才能整合並確保其運作正常。所謂「水平切片」,指的是將這種架構層級方法作為大型功能分解的主要方式。
垂直拆分
為了加快反饋循環,我們可以將一個巨集拆分為幾個使用者情境,這些情境橫跨各個架構層級。我們幾乎可以將任何功能拆分成切片,使得所有組件的建構、整合與測試最多只需幾天時間即可完成。每個切片都包含在架構層級中所需完成的工作,以及任何必要的測試與整合,以使其準備好發布。
通常,水平拆分會將功能拆分為架構元件層級的使用者故事或任務。例如:前端 UI、資料庫或後端服務。而垂直切片則會產生可運作、可展示且具備商業價值的軟體。因此,垂直拆分提升了團隊在每個迭代中交付可發布產品增量的能力。想像一下切一塊有奶油、巧克力、水果和蛋糕層的蛋糕。如果你水平切蛋糕,你的朋友只會得到一塊蛋糕、巧克力、奶油或水果。我確定你的朋友會更喜歡包含所有層的切片。僅得到單一層的蛋糕,無法讓他們品嚐到整塊蛋糕的真實風味。對你的朋友而言,更友善的做法是製作垂直切片(即所期望的價值)。

根據目標進行巨集的水平拆分
請回想一下,在利益相關者會議中,我們針對「註冊課程」使用者故事所進行的轉換,該功能最初由學生(主要角色)提出,並獲得其他利益相關者的支持。當我們深入探討使用者故事的細節時,發現其他將以支援角色參與此故事的利益相關者,保留了相當多的資訊。
實際上,有些學生可能不在乎,甚至不願意接受「支援角色」所設定的限制。例如,學生遺忘密碼並連續輸入錯誤三次,他/她可能不願經歷重設密碼的流程,但仍自信可以再嘗試多次;或學生不希望對圖書館借書數量或借閱期限設限,等等。那些希望將某些商業規則或限制設定為其使用者目標的人,正是在使用者故事中擔任支援角色的人。如果未將商業規則與第二目標強制套用至所提出的功能,該功能就不應運作。若我們根據次要角色的目標,將巨集進行水平拆分,形成一組使用者故事,便能同時滿足次要角色的目標,使使用者故事具備可測試性,並直接從正確的人那裡獲得反饋。

讓我們檢視轉換與確認部分的資訊,以了解如何將較大的故事「註冊課程」拆分為一組相關的使用者故事。
- 學生必須是註冊學生,否則將無法獲得新學生通知所發放的憑證。若他已收到通知但帳戶尚未啟用,則需線上註冊新帳戶(標示為紅圈 1)
- 若我們進一步深入探討登入流程,便知道若學生連續三次輸入憑證錯誤,則需進入「重設密碼流程」(標示為紅圈 2 與 3)

一般使用者故事區
讓我們在 UeXceler 中建立這些使用者故事:
登入帳戶的使用者故事已建立於一般使用者故事區段中。除了登入相關的使用者故事外,還在一般使用者故事區段中建立另外兩個相關的使用者故事,分別是「重設密碼」和「建立新的學生帳戶」,原因如下:
- 如果學生連續三次輸入帳戶憑證錯誤,將會觸發「重設密碼」的使用者故事;
- 而如果一位新學生尚未註冊學生帳戶,他/她可以在登入畫面中觸發「建立新的學生帳戶」使用者故事。
- 作為一名學生,我希望能夠登入學生入口網站,以便……
- 作為入口網站管理員,我希望能夠驗證登入者是否為註冊學生,以便……
- 作為課程負責人,我希望在允許所選課程加入學生課程表之前,先確認其合適性,以便……
我們可以認為這三個使用者故事是從「註冊課程」這個巨集故事中水平拆分出來的,但這些使用者故事將實現某些支援角色的目標,你可以從他們那裡獲得反饋並加以確認。如果前提條件未達成,主使用者故事將完全失去意義。
你可以看到,我們將所有這些使用者故事放在一般使用者故事區段中,原因在於它們很可能與同一呼叫頁面中的其他相關功能(使用者故事)共享相同的前置條件,例如「檢視課程表」、「編輯課程表」、「退選課程」等。
用例區段
如上圖所示,還有三個被紅圈標記的項目分別為 4、5 和 6。它們是「註冊課程」巨集故事的替代情境。只要其中任一條件不成立,就會產生對應的替代情境,並可表示為拆分後的使用者故事。我們或許可以選擇水平或垂直拆分,但垂直拆分是否總是更優?不一定,實際上取決於具體情況。世界上並不存在放之四海皆準的解決方案,我們需要根據你的實際情況來判斷哪種方法更適合。讓我進一步說明。
舉例來說,如果你打算將主使用者故事分配給一位開發人員,而將登入、註冊新帳戶和重設密碼這三個使用者故事分配給另一位開發人員。你可能會希望負責主使用者故事的開發人員先在當前迭代中開發順利情境,然後由同一開發人員在後續迭代中逐步開發替代情境(若時間允許)。但如果時間緊迫,同時你又覺得讓同一開發人員承擔整個巨集故事負擔過重,那麼就可以將其水平拆分為多個任務,分配給多位開發人員並行處理。
將巨集故事拆分為情境
如果我們考慮巨集故事確認部分所描述的情境細節,便能輕易找出一組相關使用者故事的垂直切片。
- 作為課程負責人,我希望在允許所選課程加入學生課程表之前,先確認先修課程要求,以便……
- 作為課程負責人,我希望在允許課程加入學生課程表之前,先檢查課程是否可選,以便……
- 作為課程負責人,我希望在允許所選課程加入學生課程表之前,先確認學生的時段是否可用,以便……
將巨集故事拆分為任務
如果我們希望將巨集故事分解為較小的任務,以便在同一迭代中並行開發,如下所示:
- 檢查課程名額狀態
- 檢查課程先修要求
- 檢查時段
現在,你可以根據自己的選擇,將巨集故事拆分為適合敏捷開發流程的使用者故事。你可以看到「註冊課程」使用者故事及其相關的使用者故事都放在一個用例區段(你的巨集故事)中,這個區段也稱為「註冊課程」,用作佔位符,以容納所有主要使用者故事以及從主故事拆分出來的其他使用者故事。
