行为驱动开发的简要介绍

行为驱动开发(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自身应该履行验证给定日期是否有效的职责。

您的赞赏是我创作的动力!