《敏捷軟體開發 原則、模式與實踐》的讀書筆記

magus_yang發表於2004-09-02

1.  前言
    1.  敏捷開發(Agile Development)是一種面臨迅速變化的需求快速開發軟體的能力。

2.  第一章 敏捷實踐 P2
    1.  不斷增加更多的約束和人為製品導致一個大而笨重的過程的產生。
        大而笨重的過程就是龐大、重型的過程方法。

    2.  敏捷軟體開發宣言:
        1.  個體和互動      勝過    過程和工具
        2.  可以工作的軟體  勝過    面面俱到的文件
        3.  客戶合作        勝過    合同談判
        4.  響應變化        勝過    遵循計劃

    3.  個體和互動勝過過程和工具
        1.  人是獲得成功的最為重要的因素。
            不好的過程會使最優秀的團隊成員失去效用。

        2.  合作、溝通以及互動能力要比單純的程式設計能力更為重要。
            所以一個優秀的團隊成員可能是一個平均水平的程式設計師,但是卻能夠很好地和他人合作。

        3.  合適的工具對於成功來說非常重要。
            但使用過多龐大、笨重的工具就像缺少工具一樣,都是不好的。

        4.  團隊的構建要比環境的構建重要得多。
            首先應該致力於構建團隊,然後在讓團隊基於需要來構建環境。

    4.  可以工作的軟體勝過面面俱到的文件
        1.  團隊需要編制易於閱讀的文件,來對系統及其設計決策的依據進行描述。

        2.  過多的文件比過少的文件更糟。
            文件和程式碼同步的惡夢。

        3.  文件應該短小並且主題突出。
            短小是指最多一二十頁。
            主題突出是指盡論述系統的高層結構和概括的設計原理。

        4.  Martin文件第一定律:
            直到迫切需要並且意義重大時,才來編寫文件。

    5.  客戶合作勝過合同談判
        1.  成功的專案需要有序、頻繁的客戶反饋。
            不是依賴合同或者關於工作的陳述,而是讓軟體的客戶和開發團隊密切地在一起工作,並儘量經常地提供反饋。

        2.  壞合同
            一個指明瞭需求、進度以及專案成本的合同存在根本上的缺陷。

        3.  好合同
            那些為開發團隊和客戶的協同工作方式提供指導的合同才是最好的合同。

        4.  合同中不應該詳細指明功能模組和驗收細節。

    6.  響應變化勝過遵循計劃
        1.  構建計劃時,應該確保計劃是靈活的並且易於適應商務和技術方面的變化。

        2.  較好的做計劃的策略是:
            為下兩週做詳細計劃,為下三個月做粗略計劃,再以後就做極為粗糙的計劃。

        3.  僅僅對於迫切的任務才花費時間進行詳細計劃。這樣計劃的其餘部分仍然保持著靈活性。

    7.  敏捷宣言遵循的12條原則:
        1.  我們最優先要做的是通過儘早的、持續(經常)的交付有價值的軟體來使客戶滿意。
            1.  兩個相關性
                儘早地交付具有部分功能的系統和系統質量之間具有很強的相關性。
                初期交付的系統中所包含的功能越少,最終交付的系統的質量就越高。

                以逐漸增加功能的方式經常性地交付系統和系統質量之間具有很強的相關性。
                交付得越頻繁,最終交付的系統的質量就越高。

        2.  即使到了開發的後期,也歡迎改變需求。敏捷過程利用變化來為客戶創造競爭優勢。
            1.  需求改變意味著團隊已經學到了很多如何滿足市場需要的知識。

        3.  經常性地交付可以工作的軟體,交付的間隔可以從幾周到幾個月,交付的時間間隔越短越好。
            1.  關注的目標是交付滿足客戶需要的軟體,而不是大量的文件或計劃。

        4.  在整個專案開發期間,業務人員和開發人員必須天天都在一起工作。
            1.  通過客戶、開發人員以及涉眾之間有意義的、頻繁的互動,對軟體專案進行持續不斷地引導。

        5.  圍繞被激勵起來的個人來構建專案。給他們提供所需要的環境和支援,並且信任他們能夠完成工作。
            1.  人是專案取得成功的主要因素。
                過程、環境、管理等都是次要因素。
                當次要因素對人有負面影響時,就要對次要因素進行改變。

        6.  在團隊內部,最具有效果並且富有效率的傳遞資訊的方式,就是面對面的交談。
            1.  交談是預設的溝通方式。

        7.  工作的軟體是首要的進度度量標準。
            1.  不是根據所處的開發階段、已經編寫的文件的多少或者已經建立的基礎結構(infrastructure)程式碼的數量來度量開發進度。

        8.  敏捷過程提倡可持續的開發速度。責任人、開發者和使用者應該能夠保持一個長期的、恆定的開發速度。
            1.  敏捷專案不是50米短跑,而是馬拉松長跑。

            2.  以快速但是可持續的速度行進。

        9.  不斷地關注優秀的技能和好的設計會增強敏捷能力。
            1.  高的產品質量是獲取高的開發速度的關鍵。

            2.  高質量就是儘可能的簡潔、健壯。

        10. 簡單--使未完成的工作最大化的藝術--是根本的。
            1.  採用和目標一致的最簡單的方法。

            2.  並不看重對於明天會出現的問題的預測,也不會在今天就對那些問題進行防衛。

            3.  深信如果在明天發生了問題,也會很容易進行處理。

        11. 最好的構架、需求和設計出自於自組織的團隊。
            1.  敏捷團隊的成員共同來解決專案中所有方面的問題。

        12. 每隔一定時間,團隊會在如何才能更有效地工作方面進行反省,然後相應地對自己的行為進行調整。
            1.  反省的方面包括:
                團隊的組織方式、規則、關係等。

    8.  敏捷過程有:
        1.  SCRUM

        2.  Crystal

        3.  特徵驅動軟體開發(Feature Driven Development)(FDD)

        4.  自適應軟體開發(Adaptive Software Development)(ADP)

        5.  極限程式設計(eXtreme Programming)(XP)

3.  第二章 極限程式設計概述 P9
    1.  極限程式設計(eXtreme Programming,簡稱XP)
        極限程式設計是一組簡單、具體的實踐,這些實踐結合在一起形成了一個敏捷開發過程。

    2.  客戶作為團隊成員
        XP團隊中的客戶是指定義產品的特性並排列這些特性優先順序的人或團體。
        如果確定無法和客戶在一起工作時,那麼應該去尋找能夠在一起工作、願意並能夠代替真正客戶的人。

    3.  使用者素材(user stories)
        1.  使用者素材就是正在進行的關於需求談話的助記符。

        2.  使用者素材是一個計劃工具,客戶可以使用它並根據它的優先順序和估算代價來安排實現該需求的時間。

        3.  在離真正實現需求還很早時就去捕獲該需求的特定細節,很可能會導致做無用功以及對需求不成熟的關注。

    4.  短交付週期
        1.  XP專案每兩週交付一次可以工作的軟體。

        2.  每兩週的迭代(iteration,也可稱為重複週期或迴圈週期)都實現了涉眾的一些需求。

        3.  迭代計劃
            1.  迭代計劃是由客戶根據開發人員確定的預算而選擇的一些使用者素材。

            2.  開發人員通過度量在以前的迭代中所完成的工作量來為本次迭代設定預算。

            3.  一旦迭代開始,客戶就不再修改當次迭代中使用者素材的定義和優先順序別。

        4.  釋出計劃
            1.  一個釋出計劃規劃大約6次迭代的內容。

            2.  一次釋出通常需要三個月的時間。

            3.  同設定迭代預算一樣
                開發人員通過度量在以前的釋出中所完成的工作量來為本次釋出設定預算。

            4.  不用在初期就把全部6次迭代的內容都制定好,只需制定出釋出中最初幾次迭代的內容即可。

            5.  靈活性
                釋出計劃不是一成不變的,客戶可以隨時改變計劃的內容。

        5.  驗收測試
            1.  可以以使用者指定的驗收測試(Acceptance Tests)的形式來捕獲有關使用者素材的細節。

            2.  使用者素材的驗收測試是在就要實現該使用者素材之前或實現使用者素材的同時編寫的。

            3.  驗收測試使用能夠讓它們自動並反覆執行的某種指令碼語言編寫
                ,這些測試共同驗證系統按照使用者指定的行為運轉。

        6.  結對程式設計
            1.  所有的產品程式碼都是由結對的程式設計師使用同一臺電腦共同完成的。

            2.  結對的關係每天至少改變一次,以便於每個程式設計師在一天中可以在兩個不同的結對中工作。

            3.  在一次迭代期間,每個團隊成員應該和所有其他的團隊成員在一起工作過,並且他們應該參與了本次迭代中所涉及的每項工作。

            4.  結對程式設計的好處:極大的促進了專業知識在團隊中的傳播。

        7.  測試驅動的開發方法:
            1.  編寫所有產品程式碼的目的都是為了使失敗的單元測試能夠通過。

            2.  首先編寫一個單元測試,由於它要測試的功能還不存在,所以單元測試會執行失敗。然後編寫產品程式碼使單元測試通過。

            3.  最後可以得到一個非常完整的測試用例集。

            4.  測試驅動的一個好處:解除各個模組間的耦合。

        8.  集體所有權
            沒有程式設計師對任何一個特定的模組或技術單獨負責。

        9.  持續整合
            1.  XP團隊使用非阻塞的(nonblocking)原始碼版本控制工具。

            2.  檢入(check in)要確保所有的測試(單元測試和驗收測試)都能夠通過。

        10. 可持續的開發速度
            1.  軟體專案不是全速的短跑,它是馬拉松長跑。

            2.  團隊必須要有意識的保持穩定、適中的速度。

        11. 開放的工作空間
            充滿積極討論的屋子(war room)裡工作,生產率非但不會降低,反而會成倍地提高。

        12. 計劃遊戲(planning game)
            1.  計劃遊戲的本質是劃分業務人員和開發人員的職責。
                業務人員(即客戶)的職責是決定產品特性的重要性。
                開發人員決定實現一個產品特性所花費的時間。

            2.  客戶選擇使用者素材的規則:
                在每次釋出和每次迭代的開始,開發人員基於在最近一次迭代或者最近一次釋出中他們所完成的工作量,為客戶提供一個預算。
                客戶選擇那些所需的成本合計起來不超過該預算的使用者素材。

        13. 簡單的設計
            1.  XP團隊使他們的設計儘可能地簡單、具有表現力(expressive)

            2.  XP團隊僅僅關注於計劃在本次迭代中要完成的使用者素材,不會考慮那些未來的使用者素材。

            3.  三條XP指導原則(mantras)
                1.  考慮能夠工作的最簡單的事情。
                    XP團隊總是儘可能尋找能實現當前使用者素材的最簡單的設計。

                2.  你將不需要它。
                    引入基礎結構(如:資料庫、ORB等)的時機:
                    只有在有證據,或者至少有十分明顯的跡象表明現在引入這些基礎結構比繼續等待更加合算時,XP團隊才會引入這些基礎結構。

                3.  一次,並且只有一次。
                    極限程式設計者不能容忍重複的程式碼。
                    無論在哪裡發現重複的程式碼,都要消除他們。

                    消除重複最好的方法就是抽象。抽象又能進一步減少程式碼間的耦合,這是個良性迴圈。

        14. 重構
            1.  定義:
                重構就是在不改變程式碼行為的前提下,對其進行一系列小的改造,旨在改進系統結構的實踐活動。

            2.  作用:
                程式碼往往會腐化,重構的作用就是扭轉這種腐化。

            3.  重構是持續進行的,是每隔一個小時或者半個小時就要去做的事情。

        15. 隱喻
            1.  隱喻就是對整個系統做個比喻

            2.  隱喻是將整個系統聯絡在一起的全域性檢視,是系統的未來景象。
                隱喻使得所有單獨模組的位置和外觀變得明顯直觀。
                如果模組的外觀與整個系統的隱喻不符,那麼就知道該模組是錯誤的。

            3.  隱喻通常可以歸結為一個名字系統。
                這些名字提供了一個系統組成元素的詞彙表,並且有助於定義它們之間的關係。

            4.  把一個分析網路流量的系統隱喻成烤麵包機。
                資料塊被稱為“麵包切片”
                分析程式被稱為“烤制面包切片”
                整個系統被稱為“烤麵包機”
                資料塊中的單個變數被稱為“麵包屑”

4.  第三章 計劃 P17
    1.  初始探索
        1.  在專案開始時,開發人員和客戶會盡量確定出所有所有真正重要的使用者素材,但並不會確定所有的使用者素材。
            隨著專案進展,客戶會不斷編寫新的使用者素材。
            素材的編寫會一直持續到專案完成。

        2.  探究、分解和速度
            1.  任何過大的使用者素材都應該分解成小一點的部分。
                任何國小的使用者素材都應該和其它小的素材合併。

            2.  當分割或合併一個使用者素材後,應該對其重新進行估算。
                簡單地加上或者減去估算值都是不明智的。

            3.  對一個使用者素材進行分解或者合併的主要原因
                為了使其大小適於被準確地估算。

            4.  速度(velocity)因子
                將使用者素材的估算點數乘以速度得到實現該使用者素材的實際開發時間。

            5.  計算團隊的開發速度
                花費幾天時間去原型化一到兩個使用者素材來了解團隊的速度。
                這樣的一個原型化的過程稱為探究

    2.  釋出計劃
        當開發速度變得更準確一點時,可以再對釋出計劃進行調整。

        選擇釋出計劃中完成的使用者素材,屬於商務決策範疇。

    3.  迭代計劃
        1.  迭代期間使用者素材的實現順序屬於技術決策範疇。

        2.  一旦迭代開始,客戶就不能再改變該迭代期內需要實現的使用者素材。

        3.  即使沒有完成所有的使用者素材,迭代也要在預先指定的日期結束。

        4.  迭代完成後的工作:
            合計所有已完成的使用者素材的估算值,然後計算出本次迭代的開發速度。

        5.  為每次迭代做計劃時採用的開發速度,就是前一次迭代中測算出來的開發速度。

    4.  任務計劃
        1.  在新的迭代開始時,開發人員和客戶共同制定計劃。
            具體方法:
            開發人員把使用者素材分解成開發任務,一個任務就是一個開發人員能夠在4~16小時(半天~兩天)之內實現的功能。
            開發人員在客戶的幫助下對這些使用者素材進行分析,並儘可能完全地列舉出所有的任務。

        2.  迭代中點
            1.  在迭代進行到一般的時候,本次迭代中所安排的半數使用者素材應該被完成。
                如果沒有完成,那麼團隊應該設法重新分配沒有完成的任務和職責,以保證在迭代結束時能夠完成所有的使用者素材。

            2.  目標是要完成使用者素材,而不僅僅是任務。

            3.  在迭代的中點,希望看到擁有一半素材點數的完整的使用者素材被完成。

    5.  迭代
        每次迭代結束後的工作:
        1.  給客戶演示當前可執行的程式。

        2.  要求客戶對專案程式的外觀、感覺和效能進行評價。

        3.  客戶會以新的使用者素材的方式提供反饋。

5.  第四章 測試 P21
    1.  編寫單元測試是一種驗證行為,也是一種設計行為,更是一種編寫文件的行為。

    2.  編寫產品程式碼就是為了通過測試。

    3.  測試驅動的開發方法產生的效果:
        1.  程式中的每一項功能都有對應的測試來驗證他的操作的正確性。

        2.  可以使開發人員使用不同的觀察點。
            從程式呼叫者的有利視角去觀察將要編寫的程式。
            這樣就會在關注程式的功能的同時,直接關注程式的介面。
            就可以設計出便於呼叫的軟體。

        3.  迫使開發人員把程式設計為可測試的。
            為了成為易於呼叫和可測試的,程式必須和它的周邊環境解耦。
            在編寫產品程式碼之前,先編寫測試程式碼常常會暴露程式中應該被解耦合的區域。
            產品程式越是具有可測試性,耦合關係就越弱。

        4.  測試可以作為一種無價的文件。
            測試就像一套範例,它幫助其他程式設計師瞭解如何使用程式碼。
            單元測試是可編譯、可執行的有關係統內部結構的文件。它始終保持最新,不會和產品程式不同步。
            程式設計師能輕鬆閱讀單元測試。

    4.  有意圖的程式設計(intentional programming)
        相信只要按照測試所暗示的結構去編寫產品程式,就能夠通過測試。

    5.  MOCK OBJECT(仿製的物件)模式
        在被測試的類以及它的所有協作者之間插入介面,建立實現這些介面的測試樁(test stub)

    6.  單元測試的功能:
        單元測試用來驗證系統的小的組成單元應該按照所期望的方式工作。
        單元測試是用來驗證系統中個別機制的白盒測試(white-box tests)。

        單元測試沒有驗證系統作為一個整體時工作的正確性。

    7.  驗收測試的功能:
        驗收測試是用來驗證系統滿足客戶需求的黑盒測試(black-box tests)。

        驗收測試是可編譯、可執行的有關係統特性的文件。
        客戶能輕鬆閱讀驗收測試。

        為了使系統具有可測試性,就必須要在很高的系統構架層面對系統進行解耦合。

    8.  編寫驗收測試
        通常使用專為應用程式的客戶建立的指令碼語言來編寫驗收測試。

        驗收測試應該便於編寫並且易於改變,所以採用簡單的文字檔案來編寫。
        CSV檔案是編寫驗收測試的不錯選擇。

    9.  驗收測試是關於一項特性的最終文件。


6.  第五章 重構 P28
    1.  重構的目的是使每一個軟體模組都具有下列三項職責。
        1.  第一個職責是每一個軟體模組執行起來所完成的功能。

        2.  第二個職責是每一個軟體模組要應對變化。

        3.  第三個職責是每一個軟體模組要和閱讀它的人進行溝通。

    2.  原則和模式可以幫助開發人員建立更加靈活和具有適應性的軟體模組。
        但是要使軟體模組易於閱讀和修改,就不僅需要原則和模式,還需要紀律約束和開發人員創造美的激情。

    3.  一個素數產生程式的例子,演示簡單的重構 P29

    4.  IntelliJ Idea 一個JAVA IDE,內建重構瀏覽器
        官方網站
        http://www.jetbrains.com/idea/

        IntelliJ IDEA v4.5.1 註冊碼
        Name:crsky
        Code:12919-DD8VQ-UVPQ0-10TMG-F5VNN-B2OA7

    5.  一般方法名是一個動詞短語,類名是一個名詞短語。

    6.  多個細小的重構之後,要再全部讀一遍產品程式碼。
        因為重構的都是程式碼片斷,最後再讀一遍可以看看把這些片斷結合在一起是否是一個具有可讀性的整體。

    7.  重構和單元測試密不可分。
        每次小碎步的重構之後,都要確保產品程式碼能正確通過單元測試。


    8.  為重構投入的時間和隨後為自己和他人節省的努力相比起來是非常少的。

    9.  一個很貼切的把重構比喻成清潔工作的例子 P38
        用重構來保持程式碼的清潔。

7.  第六章 一次程式設計實踐 P39
    1.  一個開發保齡球比賽計分程式的敏捷實踐過程。

    2.  從簡單考慮,加入類Frame並非必要,只要加入一個整數陣列就能實現期望的功能。

    3.  讓程式遵循原則的事情,可以稍後交給重構做。
        而不需要在最初的設計階段就很小心的讓程式遵循原則。

    4.  先使程式更易讀。
        再繼續向程式中新增更多功能。

    5.  不僅產品程式碼需要重構,測試程式碼也需要重構。

    6.  如果程式碼使用了區域性變數,就不能被提取函式,除非把這些區域性變數變為成員變數。

    7.  通過重構,儘量使產品程式碼的結構更像易讀的虛擬碼。

    8.  何時不需要圖示
        在建立了它們而沒有驗證它們的程式碼就打算去遵循它們時,圖示就是無益的。

        畫一副圖來探究一個想法是沒錯的。但是,畫一副圖後,不應該假定該圖就是相關任務的最好設計。

        最好的設計是首先編寫測試,然後一小步一小步前進時逐漸形成的。

相關文章