为什么你应该始终在开发前编写文档

文档驱动开发将你的代码专注于应用程序预期工作方式的特定蓝图。
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 设备)。我们最终给自己找了一位用户体验设计师,与一些测试对象进行了一些实验室实验,并制作了一个交互模板,我们用它来完成我们的开发。

知识共享许可协议本作品根据知识共享署名-相同方式共享 4.0 国际许可协议获得许可。
© . All rights reserved.