一文講清楚什么是行為驅動開發
行為驅動開發(Behavior-Driven Development, BDD)的概念來自于測試驅動開發,強調使用DSL(Domain Specific Language,領域特定語言)描述用戶行為,定義業務需求,是需求分析人員、開發人員與測試人員進行溝通的有效方法。DSL是一種編碼實現,相比自然語言更加精確,又能以符合領域概念的形式滿足所謂“活文檔(Living Document)”的要求。可以說,行為驅動開發將編碼實現與業務行為描述***地結合起來,走出了一條業務分析人員、開發人員與測試人員都能接受的中庸之道。
行為驅動開發的核心在于“行為”。當業務需求被劃分為不同的業務場景,并以“Given-When-Then”的形式描述出來時,就形成了一種范式化的領域建模規約。編寫領域特定語言的過程,其實就是不斷發現領域概念的過程。因此,采用BDD進行開發,最重要的產出不是可以自動運行的驗收測試,而是它提供了團隊交流的平臺,并在其約束之下完成了領域建模。由于團隊的不同角色都參與了這個過程,就保證了領域模型的一致性與準確性。
在進行行為驅動開發時,需要避免兩種錯誤的傾向:
- 從UI操作去表現業務行為
- 描述技術實現而非業務需求
例如,我們要編寫“發送郵件”這個業務場景,可能會寫成這樣:
- Scenario: send email
- Given a user "James" with password "123456"
- And I sign in
- And I fill in "mike@dddpractice.com" in "to" textbox
- And fill in "test email" in "subject" textbox
- And fill in "This is a test email" in "body" textarea
- When I click the "send email" button
- Then the email should be sent sucessfully
- And shown with message "the email is sent sucessfully"
該業務場景描寫的不是業務行為,而是用戶通過UI進行交互的操作流程。這種方式實則是讓用戶界面捆綁了你對領域行為的認知。準確地說,這種UI交互操作并非業務行為,例如上述場景中提到的button與textbox控件,與發送郵件的功能并沒有關系。或許換一個UI設計,使用的控件又完全不同了。
那么換成這樣的寫法呢?
- Scenario: send email
- Given a user "James" with password "123456"
- And I sign in after OAuth authentification
- And I fill in "mike@dddpractice.com" as receiver
- And "test email" as subject
- And "This is a test email" as email body
- When I send the email
- Then it should connect smtp server
- And all messages should be composed to email
- And a composed email should be sent to receiver via smtp protocal
該場景的編寫暴露了不必要的技術細節,如連接到smtp服務器、消息組合為郵件、郵件通過smtp協議發送等。對于BDD而言,場景應該關注于做什么(what),而不是怎么做(how)。如果在業務分析過程中,糾纏于技術細節,就可能導致我們忽略了業務價值。在業務建模階段,業務才是重心,不能舍本逐末。
那么,該怎么寫?當我們使用DSL編寫業務場景時,不要考慮任何UI操作,甚至需要拋開業已設計好的UI原型,也不要考慮任何技術細節。在編寫好業務場景之后,可以驗證:如果我們更換了UI設計,調整了UI布局,是否需要修改業務場景?同理,如果我們改變了技術實現方案,是否需要修改業務場景?如下場景采用業務行為的形式編寫:
- Scenario: send email
- Given a user "James" with password "123456"
- And I sign in
- And I fill in a subject with "test email"
- And a body with "This is a test email"
- When I send the email to "Mike" with address "mike@dddpractice.com"
- Then the email should be sent sucessfully
我們要將DSL描述的場景視為一種可讀的需求規格(Specification),通過它準確地表現領域知識,就可以幫助我們提煉出隱含的領域概念。例如:
- Scenario: validate the given date for reporting period
- Given the reporting period as prior 13 month to report month
- And the reporting month is "April 2018"
- When user choose the "April 2017"
- Then validation result is true
- When user choose "March 2017"
- Then validation result is false
場景描述中的ReportingPeriod蘊含了與財務報表相關的領域知識,即有效報表周期為13個月,ReportingPeriod自身應該履行驗證給定日期是否有效的職責。
【本文為51CTO專欄作者“張逸”原創稿件,轉載請聯系原作者】