需求代码化

需求代码化,即将软件开发需求抽象为特定的领域语言,并使用管理代码一样的方式来管理需求,追踪需求的变化 。同时,为通过新的 API 来对接版本管理系统,以可视化需求,演变为看板代码化。

为了解决某种需求/需要,我们计划设计一个软件系统。通过与利益相关者进行交流之后,确认了新的系统是有必要存在的。于是,我们产生了一系列的概念和想法,并通过诸如愿景梳理、用户分析等一系列的想法,我们将这些想法明确下来。

在开始软件开发前,我们定义好了产品是什么,随后梳理出了用户故事地图。我们定义了在什么场景下,需要哪些用户,在哪里做些什么事情,并对这些行为做出响应。有了这些定义之后,我们作为这个系统的架构设计师,便开始思考需要保存、显示哪些数据,才能完成这个业务目标。

在进入开发之前,这些想法设计等,都被明确为软件需求,简称为需求。

软件需求指为用户解决某一问题或达到某一目标所需的软件功能;系统或系统构件为了满足合同、规约、标准或其他正式实行的文档而必须满足或具备的软件功能。

为了进入万物代码化的世界,首先我们得准备一堆机制,以将物理世界的目标转换为软件问题。即我们要将软件需求,转换为代码。

引子 1:需求关联对应代码

事实上,关于这部分的内容已经存在了很久了。

早期,我们在项目上使用 Atlassian Bamboo + Atlassian Jira 时,它们已经可以非常好地配合在一起。你可以从持续集成上,直接跳转到需求处。

另外一种模式,则是透明的开源模式。如 GitHub 的 issue 与提交信息的关联,使得我们可以通过 done #123 or fixed #123 的形式来关联一个 issue(可能是需求),并关闭这个 issue。

反之,我们可以通过一个需求,来找到对应的代码提交。

引子 2:提交信息规范化

作为一个懒散的开源项目造轮子工程师,我习惯性地采用了社区规范的提交信息,以便于生成项目的 ChangeLog。诸如于:docs(changelog): update change log to beta.5,它遵循的是如下的示例:

<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>

如下是部分类型的示例:

  • build: 影响构建系统或外部依赖关系的更改(示例范围:gulp,broccoli,npm)
  • ci: 更改我们的持续集成文件和脚本(示例范围:Travis,Circle,BrowserStack,SauceLabs)
  • docs: 仅文档更改
  • feat: 一个新功能
  • fix: 修复错误
  • perf: 改进性能的代码更改
  • refactor: 代码更改,既不修复错误也不添加功能
  • style: 不影响代码含义的变化(空白,格式化,缺少分号等)
  • test: 添加缺失测试或更正现有测试

为了这套提交信息模板,我们就可以结合 git-cz 这样的工具,在本地进行提交信息的规范化。同时,在 Git 服务器里,设置对应的提交信息门禁——即如果提交信息不满足规范,则代码无法提交到服务器中。

与之更为相似的一个概念是:

代码门禁能够确保每一个进入主分支的commit都达到了一定的质量标准,例如:编译必须通过,单元测试和接口测试必须通过,新代码的覆盖率不能低于某个水平,静态代码扫描必须通过。

引子 3:行为驱动开发语言

BDD 这个东西,大家都比较熟了。这里就不详细介绍了:

行为驱动开发(英語:Behavior-driven development,缩写BDD)是一种敏捷软件开发的技术,它鼓励软件项目中的开发者、QA和非技术人员或商业参与者之间的协作。

流行的 BDD 工具 Cucumber 背后是一个名为 Gherkin 的 DSL,它用于描述需求及测试。

功能:

  场景:
    假设:
    :
    并且:
    那么:

换句话来说,它可以作为我们的需求描述语言规范。

引子 4:三段式结构

三段式,大家都比较熟悉,我们可以按自己的需求,将所有的东西都转化为三段式:

  • BDD 的:Given - When - Then
  • UI 设计的显示 - 行动 - 响应
  • 前端开发的:展示 - 事件 - 响应
  • HTTP 请求的:request - handle - response
  • 代码的:输入参数 - 处理 - 输出结果
  • 测试的:Arrange-Act-Assert
  • ……

如果不熟悉的话, 可以简单地看一下我之前设计的一个设计语言示例:

SEE HomePage
DO [Click] "Login".Button
  REACT Success: SHOW "Login Success".Toast with ANIMATE(bounce)

就这么简单。

引子 5:源码控制管理而非数据库

在上一篇文章《文档代码化》中,我们已经建议了开发人员使用像代码一样的文档语言,使用 Git 来管理文档。它有这么一些优点:

  1. 高透明性
  2. 高自治性
  3. 不可篡改性
  4. 高安全性

这可不是区块链技术,这是需求代码化技术,【狗头】。当我们的需求变成了代码,那么我们就有了一个去中心化的看板。

需求代码化

好了,现在我们有相同的上下文,让我们回到正题上:

需求代码化,即将软件开发需求抽象为特定的领域语言,并使用管理代码一样的方式来管理需求,追踪需求的变化 。同时,为通过新的 API 来对接版本管理系统,以可视化需求,演变为看板代码化。

它具备这么一些特征:

  1. 使用标记语言编写内容。如 Cucumber
  2. 可通过版本控制系统进行版本控制。如 git
  3. 与编程一致的编程体验,还可以作为测试代码的一部分
  4. 支持集成到现有的看板系统中
  5. 可集成到 IDE 中协作
  6. 支持 Git 转换为 CRUD 接口

为了进一步实现万物即代码,它还具备这么一些特征:

  1. 可对需求进行重构
  2. 可转化为设计语言

或许,聪明的你已经知道了怎么做这样的系统了。

如何实现一个需求即代码和我比主

事实上,我们在五个引子中标明了我们所需要的要素:

  1. 设计需求代码化 DSL
  2. 过渡 API 设计
  3. REST 接口转换 SCM 接口(如 Git)
  4. 静态 API 生成(用于燃尽图等)
  5. IDE 集成看板
  6. DSL 可视化看板
  7. 删除原有的看板系统

稍有不同的是,我们要进一些额外的设计。

最小需求模型

在我们对需求进行建模的时候,我们需要考虑一个需求的最小要素,如下:

  1. ID
  2. 开始时间
  3. 结束时间
  4. 优先级
  5. 状态
  6. 作者
  7. 开发者
  8. 标题

【狗头】,这个是我在设计 phodal/design 时候设计的字段,顺便一提。

重新设计需求的组织形式

现有的看板系统都存在一个问题,只让业务人员写一个标准答案。而缺少中间的过程设计,因此如果想降低编写需求的成本,那么应该重新设计一下需求的组织形式。现有的需求的组织形式,有:『影响地图』和『用户旅程地图』。

其实我们要做的事情很简单,即我们只有最后能可视化出『用户旅程地图』即可,然后往 DSL 添加新的字段即可。

需求 DSL 的要素

如果现有的三段式 DSL 不满足需求,那么可以回过头来看看需求的要素是什么?

  • 目标。系统的业务价值,基于价值确定功能和需求的优先级。
  • 人员。使用系统的人员以及业务流程和目的。
  • 系统。存在什么系统,用户界面是什么样,系统间如何交付,系统的性能怎么样?
  • 数据。三者的关系,从最终用户角度看到的业务数据对象、数据的生命周期、报告中数据对决策的影响。

基于这四要素,我们可以重新设计我们的需求 DSL。

NLP 建模过程

在我们的系统进一步完善之后,我们要采用 NLP(自然语言处理)对需求进行分析,从中提取上述所涉及的四要素,进而将需求转换为代码。

  1. 提取名词
  2. 抽象行为
  3. 关注数据及状态
  4. 建模
  5. 实例化
  6. ……

考虑到写需求的业务人员并不会为难这个系统(譬如写一个多重否定),NLP 并不会太复杂的。

原型示例

接着,让我们来看我去年写的一个示例,基于 Cucumber + 其注释设计的:

# id: TUgT7FxZg
# startDate: 2019-11-22T01:56:41Z
# endDate: 2019-11-22T02:06:48Z
# priority: 
# status: thinking
# author: phodal
# title: image to dsl
# language: zh-CN
@math
Feature:image to dsl

  Scenario: 作为设计师,我想直接获得一份草图生成的 DSL
    Given 设计
    When 当我在设计的时候
    Then 我能将草稿转成 DSL
    Then 这样我能直接将草图转成 SVG
    Then 开发人员可以直接修改代码

通过 CLI 就可以查看对应的情况,诸如于:


+-----------+--------------------------------+----------------------+--------+--------+
|    ID     |             TITLE              |         DATE         | STATUS | AUTHOR |
+-----------+--------------------------------+----------------------+--------+--------+
| CYJlzObWR | add docs to README             | 2019-11-21T15:33:50Z |        |        |
+-----------+--------------------------------+----------------------+--------+--------+
| Dyp0iOxZg | use cucumber tag as file s     | 2019-11-21T15:45:47Z |        |        |
|           | group                          |                      |        |        |
+-----------+--------------------------------+----------------------+--------+--------+

并且它作为代码的一部分,贯穿在整个应用的生命周期中。

GitHub:https://github.com/phodal/story

需求代码化成熟度

为了方便大家后期完善这个系统,我决定写一个简单的成熟度模型。

0. 模板化需求

最简单的模式就是采用 Cucumber 的语法,它包含了现成的语法和 IDE 支持等。对于开发人员、测试人员、业务人员也比较熟悉。

1. 需求代码化

如上。

2. 需求像代码一样管理

  1. 设定需求门禁
  2. 不满足原则时(如 INVEST 原则),无法提交需求

3. 看板即代码

简单来说,就是:

  1. 支持 Git 的 CRUD
  2. 支持将现有的看板对接到 Git API

4. 需求关联设计

  1. NLP(自然语言处理),进行分词的状态转换设计。
  2. 需求建模语言。
  3. 需求的自动化测试

即能从需求中,识别中目标、系统、人员和数据等四个要素。

5. 需求转换代码

需求转换为设计代码 DSL,即我下一步要做的事情。

重构需求

Wow,现在我们已经成功地把文本代码化了,那么下一步就能重构这些代码(需求了)。

结论

参考书籍:

-《软件需求与可视化模型》