2012年9月13日 星期四

《笑談軟體工程:敏捷開發法的逆襲》筆記

一. 軟體工程的現況

1.需求不可以憑藉著想像力就隨便亂加。需求是軟體開發的根本,一旦需求錯誤,後面所有的努力都是白費。




二. 什麼是 Scrum

1.Scrum 雙重回饋機制:

(1)檢視會議(Review meeting):每個 sprint(從輸入經過開發流程到產品輸出的這段時間)結束時,開發團隊要 demo 本次所完成的功能給客戶看,讓客戶確定本次所開發的功能是否符合客戶期待。如果不符合,則可以在之後的 sprint 加以修正。

(2)自省會議(Retrospective meeting):旨在檢討與軟體開發流程有關的議題。在這個活動中,團隊成員們會探討:
  • 哪些開發做法是好的,應該要繼續維持下去。
  • 有哪些與開發流程有關的地方沒有做好且需要改善的。
  • 擬定改善行動計劃。

2.Scrum 強調「持續改善」,而且這種持續改善的過程是漸進式與演化式的過程,而非計劃性的過程。


3.角色(Role)

(1)Product Owner(PO):定義產品需求,負責產品成敗。PO 在 Scrum 專案中是「客戶代表人」,要負責寫出產品的需求,並決定需求的施工順序(以 story 的形式把產品需求寫出來)。當 Developer 對於產品需求不清楚時,PO 要負責回答問題與釐清需求。

(2)Scrum Master(SM):協助開發團隊依循 Scrum 的精神來開發軟體,確定 Scrum 所規範的幾個活動都有定時且正確地進行。協助團隊改善軟體開發流程,排除任何阻礙開發活動的事件。
*PO 和 SM 絕對不可以是同一人。

(3)Develpoer:負責開發軟體。Scrum 強調團隊成員的組成應包含所有能夠完成專案的「通才」,包含從使用者介面設計,程式開發到資料庫操作等。


4.活動(Activity)

(1)衝刺規劃會議(Sprint planning meeting):在每個 sprint 開發活動的第一天,團隊要舉辦此會議。每個角色都必須參與,目的在於:
  • 挑選這個 sprint 所要開發的需求(story)。
  • 逐一將每一個 story 細分為若干個施工項目(task),並且估算完成每一個 task 所需的時間(以小時計算)。
而在此過程中,強調 PODeveloper 之間的對話,藉由對話來讓需求變得更清楚。此會議結束後會產出「Sprint Backlog」,也就是這個 sprint 所要施工的需求(以 story 的方式撰寫)。

(2)每日站立會議(Daily scrum):團隊每天(通常是早上)「站著」開一個約 15 分鐘的會議,團隊成員要報告三件事:
  • 昨天做了哪些事。
  • 今天準備做哪些事。
  • 有沒有遇到任何問題或阻礙。
(3)衝刺(Sprint):為期 2~4 週的開發活動。當一個 Scrum 團隊選擇好 sprint 長度且實施過一段時間穩定下來之後,最好不要任意改變 sprint 長度,以避免打亂開發的步調。

(4)衝刺檢視會議(Sprint review meeting):在 sprint 結束的那一天會舉辦此會議,主要展示團隊在此 sprint 中所完成的每一個 story,並且讓 PO 確認這些 story 有做到他心目中所想要的程度。PO 透過實際的軟體展示,可能會引發新的想法,這些想法就可能變成新的需求,再移到後續的 sprint 中實作(PO 要決定需求的施工順序)。

(5)自省會議(Sprint retrospective meeting):參加對象主要是 SMDeveloper。此會議目為檢視與改善「軟體開發流程」,在會議中開發人員列舉出在此 sprint 中有哪些開發流程是好的,要繼續維持;有哪些是不好的或是沒做到的,應該要改善的項目。最後團隊討論出改善動方案,在下一個 sprint (或連續幾個 sprint 後)實施此改善項目。改善項目一次不要太多個,注意 sprint 的時間再決定改善的數量。

(6)產品清單精進會議(Product backlog refinement meeting):目的在於讓 PO 與開發團隊每個 sprint 抽出 5%~10% 的時間來檢視 product backlog 裡面的所有需求,然後挑選一些下一個 sprint 準備要施工的 story


5.產出物(Artifact)

(1)遠景(Vision):客戶想要什麼軟體,團隊要把它變成需求,並產出實際的東西。

(2)故事(Story):把需求以 story 形式寫出來,類似於使用案例中的一條執行路徑或是一個劇情。

(3)產品清單(Product backlog):所有關於此專案或是產品的 story。放在 product backlog 裡面的 story 要經優先順序來排序。

(4)衝刺清單(Sprint backlog):某一個 sprint 準備施工的 story。放在 sprint backlog 裡面的 story 要經優先順序來排序。

(5)工作(Task):完成 story 的施工項目,在 sprint planning meeting時,團隊會將每一個 story 再細分為若干個 task。典型的 task 有設計使用者介面、寫程式、寫自動化單元測試、設計資料庫表格格式、寫資料庫存取物件(data access object)、寫自動化功能測試、寫使用手冊等。

(6)燒盡圖(Burndown chart):在 sprint planning meeting 結束之後,先把所有 task 的工時加總起來,假設為 X。然後每一天 Daily Scrum 會議之後,Developer 會報告說有一些 task 已經被做完了。假設過一天後有 Y 小時的工作已經完成了,則 Scrum 團隊可以畫張圖,把 X-Y ,剩下的就是尚未完成的工作,如此一來,團隊便可以知道進度是否正常。

(7)可執行軟體(Running software):在 sprint 結束時,團隊要能夠產出一份潛在可發佈軟體(potentially shippable product increment)。也就是說,如果這個 sprint 所增加的功能客戶馬上就要的話,就可以直接交付。因此,團隊要確定手邊所開發的軟體隨時都可以產生一份 runngint software(自己開發的軟體要隨時都處於可執行的健康狀態)。

(8)Sprint 資訊頁面(Sprint info page):當 sprint planning meeting 開完之後,Scrum Master 會寫一份 Sprint info page 文件。這份文件包含這個 sprint 的目標,以及列出這個 sprint 所要施工的 story、sprint 開始與結束時間、以及團隊成員。然後,Scrum Master 將份文件寄給團隊及其他輔助人員,讓他們知道一個新的 sprint 已經開始了。

(9)Sprint 檢視會議(Sprint review agenda):一個 sprint 結束的前一天,Scrum Master 要寫出 sprint review meeting 的議程表,並將此文件寄給團隊及其他輔助人員。此議程表包含所有要展示的項目、每一展示項目要花多少時間、由誰負責展示。所以當 Developer 收到該議程表時,就可以準備明天要展示的資料。

(10)Sprint 總結報告(Sprint summery report):當開完 sprint retrospective meeting 之後, Scrum Master 会準備此文件。文件內容包含對於本次 sprint 所完成功能的簡述、完成多少個 story point 、團隊成員在 sprint retrospective meeting 中所列出好的以及有待改善的項目(最多各列三點)、以及改善行動計劃,並將此文件寄給團隊及其他輔助人員,讓他們知這個 sprint 已經正式結束了。


6.要達成「具有擴充性的軟體架構」,必須利用「完成若干個功能性的 story」來達成。而要完成功能性的 story,必須先定義「什麼東西需要被擴充」。


7.解決 story 太大,在 sprint 快結尾時才發現做不完的方法:

將這個 story 移到下一個 sprint 繼續做(在目前的 sprint 中,這個 story 就不算完成,也不用展示)。

*若這個 sprint 就只有這一個 story:
  • 承認這個 sprint 失敗,並檢討原因。
  • 如果這個 story 可以被細分,就看看這個 sprint 完成的內容可否完整的自成一個 story,如果可以,就將沒做完的另外寫一個 story 移到下一個 sprint 繼續。
就算這個 sprint 有很多 story,而你認為這個未完成的 story 可以被切割,你還是可以展示已經完成的內容,並且將沒做完的需求另外寫一個 story 移到下一個 sprint 繼續。


8.需求撰寫無論是寫成使用案例或是 story,務必要寫成「首尾相接」(end-to-end)。


9 .估算 Story point 的方法:

估算 story 採用 story point,估算 task 採用小時。story point 本身沒有單位,每一個 story 的 story point 是採用「相對大小」來估算。至於每個 sprint 可以完成多少 story,則是以 task 加總的時數來計算。

在 sprint planning meeting 開始時,要先計算團隊在這個 sprint 可用的「工作時數」:
開發人數*可以獲得的工作時數*每日工作小時


10.不要事先估算全部 story 的 story point,只要先估算這個 sprint 預計要完成的 story。


11.團隊必須有一個對於「完成的定義」(The definition of done;DoD),如此才能知道每個 sprint 真正完成了多少個功能。而定義 DoD 的時間點,應該在 sprint planning meeting


12. 處理 bug 的方法:
  • 在下一個 sprint 規劃一個 technical story,設計一組產生資料庫測試資料的公用程式,以簡化測試案例的撰寫。
  • 著手整理使用者介面查核清單(UI checklist)與使用者介面模式(UI pattern),以降低使用者介面不一致與不方便的問題。
  • 對於全新開發的功能,一律增加一個撰寫驗收測試的工作,以減少因為對於需求細節不清楚,而造成自作主張的問題。
  • 對於所有發現的 bug,一律要先撰寫一個自動化單元測試來重新產生該 bug。

13.避免 bug 發生的手段:

(1)Pair programming:兩人共用一部電腦開發,一個動手,另一個看著,提供意見。

(2)Continuous integration:持續整合,才能在早期就發現整合錯誤。

(3)Sitting together:團隊面對面坐在一起開發。

(4)Real customer involvement:讓真正的客戶參與軟體的開發,或是至少和開發團隊有很密切的互動。

(5)Daily deployment:每天都讓開發中的軟體保持可部署的狀態。


14.實施「程式碼共享」的要點:
  • 剛開始先依據每個人的專長或細去分配到若干個專案。
  • 要儘早導入持續整合,確定不同的模組可以整合在一起。
  • 要求開發人員一定要寫單元測試
  • 等系統雛型大致穩定之後,鼓勵大家 pair programming。在這個過程中,由不同模組的創始人帶領另一個開發人員,讓他可以慢慢具備接手的能力。
  • 持續下去,達到每一個模組至少都有兩個人非常熟悉為止。

15.敏捷開發的教義:
  • 個人與互動重於流程與工具。
  • 可用的軟體重於詳盡的文件。
  • 與客戶合作重於合約協商。
  • 回應變化重於遵循計劃。




三. 精實生產,減少不必要的浪費

1.解決軟體開發中的七種浪費:

(1)半成品(Partially Done Work):為每一項 task 與每一個 story 定義完成條件(DoD)。

(2)多餘功能(Extra Feature):定期且頻繁地與客戶或 PO 溝通、透過每日站立會議了解開發人員的工作狀況,判斷是否有製造多餘功能的問題。

(3)重複學習(Relearning):將程式正常行為的「知識」記錄在自動化測試程式中,當有人不小心產生 bug 實,能夠透過記錄下的知識立即發現問題。

(4)交接(Handoff)
  • 把所有軟體開發需要的人才全部編列在同一個團隊裡面,使團隊成員具有「跨領域」的能力,以減少交接造成的浪費。
  • 盡可能用面對面溝通來取代文件式溝通。
  • 程式開發人員應儘早且頻繁地釋出部分作品以便於獲得測試人員的回饋。

(5)工作切換(Task Switching)
  • 讓兩個人(或兩個小組)每個月(或每個開發週期)輪流負責開發與維護的工作。
  • 每天早上花兩個小時讓整個團隊處理維護的工作,其餘時間則專注於新功能的開發。
  • 先將每一位客戶所提出的維護需求加以分類,只立即處理「緊急」的維護需求,然後每一週或兩週再看看有哪些維護需求是真正需要處理的。
  • 把所有不同客戶所使用的軟體版本都放在單一的代碼庫(code base),然後每週或每一個開發週期(定期)釋出一個更新版本。

(6)延遲(Delay)
  • 組織跨領域團隊。
  • 讓團隊成員坐在一起。
  • 採用比較短的開發週期並經常與客戶互動。
  • 指定專人排除障礙。
  • 改善開發與測試環境。

(7)缺陷(Defect):實施需求審查、測試案例審查、架構審查、設計審查、程式碼審查、自動化測試、持續整合。


2.Stop the Line:一發現 bug 就必須暫停所有人的工作,直到找到問題的根源為止


3.測試驅動開發(TDD):先開發測試,再實作功能程式碼。可確保當功能完成之後,一定會有自動化測試程式之外,主要的目的在於強迫開發人員從「使用者的角度」來思考自己準備開發的功能,如果開發完成之後,使用者將會如何使用它。


4.撰寫測試案例務必記得前置條件(precondition)原則。




四. 軟體工程的全新思維

1.面試時應詢問該公司的軟體開發模式,包含採用何種開發流程、有沒有做測試、實施哪些軟體實務做法、團隊內與跨團隊的成員彼此是如何互動、公司如何與客戶互動、人員流動率與原因、公司導入某種軟體開發方法的實際成效等。


2.我們需要允許其他人犯錯的勇氣,因為這是學習的唯一方法。


3.避免產生重複程式碼的方法:確定資料、城市結構、程式邏輯在系統中僅存在一個地方。




五. 軟體架構

1.持續整合 Problem Domain 概念:

(1)持續整合的主要目的,就是要找出「整合」的問題。那麼,哪些算是「整合」的問題?

(2)針對不同性質的專案,持續整合的內涵需要包含哪些項目(如編譯或測試)?

(3)當一個軟體專案大到一定程度,為了分工以及組織(模組化與管理相依性)的目的,專案通常會被切割成若干個小專案,而最終的產品將由這些小專案組合而成。
  • 專案相依性對於持續整合有何影響?
  • 公用(共用)元件對於持續整合有何影響?
  • 持續整合的產出物有哪些?

(4)持續整合的執行速度是否會影響到軟體開發活動?


2.軟體應具彈性、可擴充性,以隨時因應需求的變化。


3.設計出有彈性軟體架構的方法:

(1)*插件架構(Plug-in Architecture):藉由動態抽換與增加插件,進而擴充既有系統功能。

(2)階層式架構(Layered Architecture):只有上、下兩層的物件會彼此耦合,而其他層的物件之間則互相獨立。

(3)MVC架構(Model-View-Controller):將資料(model)、顯示資料(view)、控制資料顯示邏輯(controller)三者各自獨立的做法。有助於開發人員的分工,以及簡化測試工作。

(4)服務導向架構(Service-Oriented Architecture,SOA):將軟體視為一種「服務」。強調服務之間彼此透過網路來合作,屬於一種鬆散耦合架構。


4.針對介面寫程式,而非實作


5.寫網路應用程式務必記得 Use Timeout




六. 人機介面

1.軟體為了處理錯誤而設計的做法:

(1)了解錯誤發生的根本原因,並在設計時盡可能避免這些錯誤發生。

(2)讓使用者有機會可以反悔(undo);如果有些操作是無法反悔,就應該要讓使用者再三確認後才執行該操作。

(3)如果錯誤無法從根本上(在設計的時候)避免,至少要能夠想方法讓「偵測錯誤」與「修復錯誤」變得簡單一點。

(4)改變我們對使用者犯錯的態度。


2.把必要的知識放在外在世界中。不要強求使用者一開始便可在腦袋中記憶所有相關知識。但是系統可允許有經驗的使用者採取方便的捷徑來使用系統


3.善用自然或人工限制,如:實體限制、邏輯限制、語意限制、文化限制,以及使用強制功能與自然對應。


4.強制功能(forcing function):

(1)連鎖(Interlock):強制某些操作只能在特定的順序之下才可發生。

(2)封鎖(Lockin):使某個操作維持在作用中的狀態,以避免不小心提早中斷該操作。

(3)閉鎖(Lockout):避免使用者進入危險的地方。


5.讓執行與評估的結果可以被看到。在執行面,只顯示可操作的選項。在評估面,讓每個操作的結果都可以很清楚地被觀察到

沒有留言:

張貼留言