为什么你应该在开发之前进行文档编写

文档驱动开发将你的代码集中在应用程序应该如何工作的特定蓝图上。
648 位读者喜欢这篇文章。
Freer than free, opener than open: The fight for the learning management systems

Opensource.com

程序员和项目经理有时认为“文档驱动开发”意味着在代码中添加大量注释,或者在开发过程中与文档编写者密切合作。 这是因为很难想象开发如何在文档之后发生,因为在有实际文档记录的内容之前,文档肯定无法编写。

传统上,文档被视为一种新闻工作。 文档编写者得到一些软件,然后他们将其带到实验室并进行研究,直到他们弄清楚所有内容,然后他们将其写下来供其他人永远不阅读。

这忽略了一个非常重要的过程,这个过程在开发人员闲暇时喝着咖啡的某个晚上,突然想出一个应用程序的想法时自然发生。 开发人员可能没有意识到这一点,但是随着想法的形成,已经发生了一种文档编写。 想法不会只是完全形成,每个细节都绘制在一个整洁的蓝图中,可以连接到孤立的代码行。 想法是逐渐发生的。

代码可以说是一种艺术形式,所以这里有一个以艺术世界为背景的类比。

静物画代表了物理世界中的事物。 但是,静物艺术首先从抽象形状开始,然后逐渐完善为可识别的事物,然后添加纹理和阴影等等。

此过程可以称为自文档记录,因为在绘画生命周期的每个阶段,你都可以了解绘画的进展情况。

Still-life drawing of an orange

Seth Kenlon, CC0

在代码中,这些快照可能是 git 提交加上非常好的注释。 虽然这对以后加入并想了解代码库的哪个部分负责哪个任务的其他编码人员来说非常有用,但对于一般的最终用户来说通常没有用处。

在静物类比中,这意味着虽然绘画的自文档记录可能对有抱负的艺术家有用,但对目标受众没有太大帮助。

绘画的最终用户文档实际上是最终结果:艺术家在绘画时所看到的东西是绘画旨在捕捉的完全实现的图像。 如果绘画的“最终用户”想要以其最真实的形式理解绘画的主题,则最终用户指的是实际的物理对象。

信不信由你,代码也是如此。 唯一的区别是被记录的应用程序尚未存在。 但这几乎并不意味着你不能像记录它存在一样记录它。

为你想要的应用程序编写文档

当你坐下来编写应用程序时,你对应用程序打算做什么有一些想法。 我将以实用程序 trashy 为例,因为它范围很窄

Trashy is a command-line trash bin.

这通常是开发人员开始的地方,但是如果你实践文档驱动开发,那么这就是你的主页或用户手册的起点,并且它发生在开始编码之前。

如果你的唯一任务说明是“编写一个命令行回收站”,那么你的代码很可能会朝着首先碰到的任何方向发展。 你可能知道也可能不知道 Free Desktop 回收站规范,因此你可能一开始没有想到遵循它的方案。 你可能知道已经有一种回收站机制,因此你的代码的第一次迭代可能只是将文件转储到用户的已建立的回收站中,而没有考虑应该随附它的相关元数据。

但是,如果你先坐下来记录它,那么你将被迫考虑细节。 例如,将以下内容想象为 trashy 文档的初稿

    Trashy is a command-line trash bin.

    trash foo   : moves foo to system trash
    trash empty : empties system trash

它已经比最初的概念更加强大,因为它还提供了一种清空回收站的机制,而不仅仅是将文件发送到其中。 而它存在于此的唯一原因是,记录用户如何与你的应用程序交互的行为迫使你从用户的角度考虑应用程序。

这是绘画和实际将该画挂在画廊的墙上供其他人观看之间的区别的演练。

作为框架的文档

当你继续为你的命令行回收站应用程序编写文档时,你最终会提出其他“显而易见”的期望,作为用户而不是开发人员,你对这样的工具会有。 你会想到约定,例如能够列出当前在回收站中的文件,甚至恢复错误地移动到回收站的文件(反过来,这可能会引导你了解 Free Desktop 回收站规范,该规范会告知你应在文件移动到回收站时写入的元数据)。

更好的是,你的文档现在是你的伪代码。 你的应用程序开发已从编写在你进行第一次修订时会被丢弃的代码转变为拥有可以构建的代码骨架

    while [ True ]; do
    # trash --help: print a help message 
    if [ "$1" = "--help" -o "$1" = "-h" ]; then
       echo " "
       echo "trash [--empty|--list|--restore|--version] foo"
       echo " "
       exit
    # trash --list: list files in trash
    elif [ "$1" = "--list" -o "$1" = "-l" ]; then
        list
        shift 1
    # trash --version: print version 
    elif [ "$1" = "--version" -o "$1" = "-w" -o "$1" = "--which" ]; then
        version
        shift 1
    # trash --empty
    elif [ "$1" = "--empty" -o "$1" = "-e" -o "$1" = "--pitch" ]; then
        empty
    # trash --restore: restore a file to original location
    elif [ "$1" = "--restore" -o "$1" = "-r" ]; then
        RESTORE=1
        shift 1
    # trashy foo: moves foo to trash
    else
        break
    fi
    done

    # more code here...

作为路线图的文档

这是一个简化的示例,但是对于更大的项目,这些原则更为重要,并且文档通常来自并非开发人员的人。 结果是一个更加集中的开发周期,因为开发人员不再是朝着模糊的应用程序想法前进,而是朝着一个精确地了解应用程序应该如何工作的特定蓝图进行编码。 想象中的应用程序文档中已经绘制了每个菜单、每个按钮、每个上下文菜单。 开发人员需要做的就是填写代码。

敏捷的道路战士

如果所有这些听起来都非常规定且不灵活,请不要假设使用文档驱动开发无法应对敏捷挑战。 敏捷开发方法需要来自用户和利益相关者的反馈,以指导下一步的开发方向。 文档不会改变这一点。 实际上,在最好的文档驱动开发环境中,文档本身的处理方式与源代码完全相同。 它会与其余源代码一起提交到同一存储库,并且会在其他任何内容之前进行更新。

实际上,将文档视为错误报告和功能请求的第一层是保护项目免受 UI 蔓延的好方法。 当用户要求对某个 UI 进行看似无害的更改时,这肯定是一堆其他看似无害的更改中的一部分,UI 可能会迅速开始带有委员会设计的经典标记。 这是因为,如果程序员添加所有被请求的内容而没有通过具有全局视野的人进行审查,实际上它已经被设计了。

使用文档作为持续设计过程的一部分是有意义的。 这是一种廉价的原型设计。 五个错误请求在一个旨在成为干净的一键启动面板的主面板上添加一个新按钮等同于六个按钮使曾经简洁干净的面板变得混乱。 但是,如果首先记录并审查了启动面板,它们就不会脱离纸面。

就像编码一样,文档不是在应用程序生命周期的早期完成的一次性过程。 你的项目文档是一个动态文档,与代码相同,会不断更新和修订,以反映开发计划项目的当前状态。

一致性

文档往往会在应用程序的工作方式上产生一致性,因为内部逻辑已提前绘制出来。

在应用程序开发的第一个星期,很容易将一个函数编码为按钮单击,然后在 UI 空间处于溢价状态的第八周,将同样重要的函数委派给晦涩的右键单击菜单。

当你在为尚无房地产的东西编写文档时,很难做到这一点。 在文档编写阶段,一切都是虚构的,因此你会看到为一项任务提供一个按钮,但隐藏相关任务的逻辑违规行为。 当修复它的所有成本只是快速重写一段文字时,它不会被遗留下很长时间,这与更改许多文件中的多个代码块(并可能重新设计你已经花费数周时间完善的整个 UI)截然不同。 当你只是编写文档时,你可以编写任何你想要的东西; 这是一个低成本的修复,最终它为开发人员构建提供了更好、更智能的蓝图。

今天试驾一个文档

文档驱动开发可能最棒的事情是它没有入门门槛。 任何非编码人员都可以为不存在的应用程序发明文档,并且它非常有用。 我在电影行业和教育领域编写的应用程序都是由我以外的其他人设计的。 当然,仍然存在来回的用户测试和对在纸面上看起来不错但最终运行不如设计师希望的那样顺利的东西的改进,但这远少于没有设计师的东西。 当然,有时非编码人员会梦见超出范围的东西并且必须收回,但有时这导致开发人员学习一些新的技巧来使以前认为无法实现的东西真正起作用。

无论你是开发人员还是只是有一些好主意的用户,都请坐下来为你希望看到的应用程序编写一些文档。 或者,为你认为可以改进的现有应用程序的版本编写一些文档。 你会惊讶地发现它在多大程度上影响了你对软件、直观设计和开发的思考方式。

标签
Seth Kenlon
Seth Kenlon 是一位 UNIX 极客、自由文化倡导者、独立多媒体艺术家和 D&D 爱好者。 他曾在电影和计算机行业工作,通常同时从事这两项工作。

5 条评论

1979年我刚开始当程序员的时候,我们总是先编写文档,然后再编写代码。文档是一份详细的程序规格说明书,并且成为了用户手册的基础。在系统编码过程中,设计可能会发生变化,但规格说明书会随之更改以反映这些变化。

这些天我很少写代码了,但如果我写,我仍然会先写规格说明书。旧习惯(在这种情况下是好习惯)很难改掉。

非常酷的故事!我认为“需求”的概念在某种程度上发生了转变,最近可能由于闭源、现成软件的普及。如果你所知道的只是如何妥协,那么如何*首先*列出软件的要求? 整个行业已经训练用户接受以下顺序:1) 具有最吸引人的营销活动的,2) 可以勉强塞进他们工作流程的,以及 3) 或多或少接近他们实际需求的。

我们大多数人都忘记了,软件之所以被称为“软”,是因为它应该具有足够的延展性来适应我们的需求。 希望开源+良好的文档能够解决这个问题。

回复 MartyMonroe

我记得曾建议客户,我们需要在编写规格说明书之前以及开始编码之前完成用户文档。 引起了很多惊讶的目光,但我解释了原因:它是软件的架构图,引导出规格说明书(蓝图),然后引导出构建。 很难推销! 我还解释说,这样做会将最终的审批流程从“这是你想要的吗?”更改为“这是否与之前每个人都批准的用户指南相符?” 换句话说,我们事先聚在一起看看我们想要什么并达成一致。

最重要的是,编码开始之前需要更长的时间(让管理者感到紧张),但由于返工和“嘿,顺便说一下”效应而缩短了编码时间。 由于返工减少,项目的完成时间通常会大大缩短,并且最终的合规性测试也很容易。

尽管如此,这个概念在许多组织中仍然很难推销。

Dave,

好极了! 是的,我认为对于许多客户来说,“规格说明”的概念几乎比“文档”的概念更有价值。 人们很容易问“你为什么要首先编写文档?” 但由于某种原因,“让我们编写一份规格说明书,以便你最终得到的东西就是你脑海中看到的东西”听起来更像是优质服务。

回复 Dave Boland (未验证)

我看到过一些项目由于缺乏关于用户交互方式的适当文档而举步维艰。 我领导了一个 Eclipse 插件项目,该项目最初是相关技术的集合,用于构建开发移动 Web 应用程序的编辑器和构建链。(想想带有浏览器的前 iPhone 设备)。 我们最终找到了一个 UX 设计师,进行了一些实验室实验与一些测试对象,并制作了一个交互模板,我们用它来完成我们的开发。

Creative Commons License本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
© . All rights reserved.