重新思考文档
简单的说主要几点:
- 支持对话和集中办公,而不是各种形式的文档。大多数只是已经存在,只需要把他们找出来即可。
- 大多数只是已经存在。你只需要用缺失的上下文、意图和原理来扩充它即可。
- 注意变更频率。
- 思考文档是将人们的注意力引到系统质量或缺乏质量上的一种方法。
DDD概述
DDD是一种解决软件开发核心复杂性的方法。它主要提倡将重点放在特定的业务领域上,即编写直接表达领域知识的代码,而不在领域缝隙和可执行代码之间践行任何转换。因此,与许多有关建模的文献相仿,它要求直接用编程语言编写的代码进行建模。
当活文档是DDD应用时
- 代码即模型: 代码即模型(反之亦然),所以你希望在代码中极可能多的了解模型。根据定义,这就是文档。
- 使代码表达所有知识的战术技术: 你想利用编程语言最大限度的表达内容,甚至表达在运行时未执行的知识。
- 随着DDD不断螺旋式发展知识: 知识笑话主要是业务领域专家和开发团队之间的写作问题。通过这个过程,一些最重要的知识会体现在代码中,甚至可能体现在其他一些工件中。因为所有知识随时都可能在发展,所以任何记录在案的知识都必须拥抱变化,而不能受维护成本的障碍的影响。
- 明确什么是重要的,什么是不重要的: 换句话说,重点需要放在管理上。“专注于核心领域”和“突出显示核心概念”的想法出自Evans的《驱动领域设置:软件核心复杂性应对之道》一书中。尽管人类的记忆力和认知能力有限,但你仍可以通过管理来帮助控制知识,从而完成更多事情。
- 注意些及: 许多DDD模式都强调注意细节。决策应该是审慎的而不是无端的,并且应该以具体反馈为知道。活文档方法必须通过使记录经过深思熟路的内容变得更容易,并在整个过程中给予有见地的反馈,来鼓励关注细节。
- 战略设计和大规模结构: DDD提供了在战略级别和大规模处理不断发展的知识的技术,也为更职能的编写文档提供了机会。
活文档与DDD对应关系
活文档模式 | DDD模式(出自Evans的书或者之后的贡献) | 说明 |
---|---|---|
现成的知识;承认参考书目 | 尽可能利用既定的形式主义;查阅书籍;应用分析模式 | 明确声明所有与参考资料一起使用的现成知识 |
常青文档 | 领域远景说明 | 高层级的知识可以在常青文档中编写稳定知识的好例子 |
代码即文档 | 模型驱动设计;释意接口;声明式设计;模型驱动设计的构建块(以实现表达性代码) | DDD是用纯代码建模的,目的是使所有领域知识都体现在代码及其测试中 |
活词汇表 | 通用语言 | 当代码在字面上遵循通用语言模式时,它会成为该领域词汇表的唯一参考 |
倾听文档 | 亲身实践的建模者 | 亲手用从代码中提取出来的活文档在代码中建模,能对设计质量提供快速反馈 |
易于修改的文档 | 通过重构得到更新层的理解;尝试,再尝试 | 使用XP、DDD和活文档是,“拥抱变化”是永远不变的主题 |
知识管理 | 突出核心;标明核心;分离核心;抽象核心 | 在DDD中,将特别重要的部分与其他部分分离开来时关键驱动力;目的是更好地分配经理和认知注意力 |
用典型案例展示活文档的方方面面
- 协作:BDD的主要工具是人与人之间的对话,确保三个(或更多)好朋友中的每个角色都在场。
- 省力:围绕具体实例进行的对话有助于达成共识。再额外做些工作,这些示例就会成为自动化测试核活文档,可谓是一箭多雕。
- 可靠(因为一致性机制):由于文本场景核实现代码同时对业务行为做了描述,所以像Cucumber核SpecFlow之类的工具可以确保场景和代码始终保持同步(或者至少在不同步时显示出来)。只要存在知识重复,这么做就是必要的。
- 有见地:对会话提供反馈,编写和自动化场景也是如此。例如,如果场景描述太长或太糟糕,BDD可能建议查找缺失的隐式概念,从而使场景描述更短、更简单。
- 目标受众:整个工作面向的是包括业务人员在内的受众,因此在讨论业务需求时,重点是使用清晰的非技术性语言。
- 想法沉淀:一般有对话就足够了,而且不是所有的内容都需要写下来。为了归档或自动化,只有那些最重要的场景(即关键场景)才需要被记录下来。
- 纯文本文档:纯文本很便于管理一直在变化的内容,并且它在源代码控制系统中与源代码和Tzatziki等工具提供了一种解决方案,他们可以将当前所有场景的快照导出并生成交互式网站或可打印的PDF文档。
知识增强
因此,要增强你所用的编程语言,以便代码能结构化的是叙述整个故事。为你自己定义一种方式,来声明每个关键决策背后的意图和推理。声明更高层次的设计意图、目标和决策依据。 不要依赖简单的注释。使用严格的命名约定或语言得扩展机制,例如Java得注解和.Net属性。注解越结构化越好。务必只是为了编写文档而写一些代码,不要犹豫。创建你的领域特定语言(DSL)或根据需要服用一种语言。合适时要依靠约定。 让增强得只是尽可能靠近与其有关的代码。理想情况下,应该将他们放在一起,以防重构。让编译器检查是否有错误。依靠IDE的自动补全功能。确保在你的编辑器或IDE中可以轻松搜索到增强的知识,并确保可以通过工具轻松的进行解析,从而保证能从整个增强代码中提取活文档。
实际上,你可以使用以下几种方法来增强代码:
- 固有文档
- 使用注解
- 按照约定
- 外部文档
- 使用车边文件
- 使用元数据库
- 使用DSL
文学式编程
让我们改变一下对程序构造的一贯态度:与其想象我们的主要任务是指导计算机做什么,还不如集中精力向人类解释我们想要计算机做什么。 --高德纳
几个概念:
- 在相同的工件中,文档与代码交织在一起,代码插入到文档的内容中。不要将它与文档生成混淆,文档生成是指从插入源代码的注释中提取出内容来编写文档。
- 文档复核程序员的思路,而不是受限于编译器强制的顺序:好的文档符合人类的逻辑顺序。
- 一种鼓励程序员认真思考每个决策的编程范例:文学式编程远远超出文档范围,旨在强迫程序员认真思考,因为他们必须明确阐述自己在编写程序时所持的想法。
突出启发性的范例
因此,在实际的生产代码中直接突出显示你倡导的内容,这些内容是具有良好风格或最佳实践的范例。将你的同事引导至这些范例,并告诉他们如何自行找到它们。管理好这些范例,使其能一直起到示范作用,以供所有人模仿,从而改善整个代码库。
创建活文档的步骤
- 选择存储在某处的一系列数据,例如源代码控制系统中的源代码。
- 根据文档目标过滤数据。
- 对于通过过滤器得出的每条数据,提取能用于文档的内容子集。它可以看作一幅投影图像,而且特定于绘制图表。
- 将数据集其中的关系转化为目标格式以生成文档。对于可视文档,这个目标可以是对渲染库APID的一系列调用;对于文本文档,它可以是工具生成PDF需要的文本片段列表。
词汇表
在领域模型中,代码表达业务领域,它会尽可能接近领域专家的思考和讨论方式。在领域模型中,出色的代码能描述领域业务:每个类名称、每个方法名称、每个枚举常量和每个接口名称都是领域通用语言的一部分。但并不是所有人都能读懂代码,而且几乎总是有一些代码与领域模型不太相关。
因此,要从源代码中提取通用语言的词汇表。将源代码视为单一信息源,在每个类、接口和公共方法表达领域概念时,要特别注意他们的名称。将对领域概念的描述直接添加到源代码中,作为可以由工具提取的结构化注释。提取词汇表时,找到一种方法来过滤掉那些没有表达该领域的代码。
活词汇表
活图表
自动化应该使安全地修改代码更容易,而不是更难。如果变得越来越困难,请删掉以写代码。永远不要自动化那些一直变化的东西。
太多的信息==没有信息
每一个图标都应该有一个目的,而且只能有一个目的。抑制在现有图表中添加额外信息的冲动。如果真的有需要,另外为这些额外信息新建一个图表,并删掉那些对这个新图表没什么价值的信息。主动过滤多余的信息,只有必不可少的元素才值得将其制作成图表。
代码即文档,偶尔可以供计算机执行
避免传统文档
文档只是一种手段,不是目睹,也不是产品
因此,所有参与者之间的对话优于书面文档。与所有书面工件不同,对话是交互性且快速的,能传达感情,并且带宽很高。
Wiio沟通定律
- 沟通往往会失败,成功只是意外。
- 如果沟通有可能失败,那就会失败。
- 如果沟通可能不会失败,它通常仍会失败。
- 如果沟通看起来会按预期的方式成功,那是存在误解。
- 如果你对自己的消息感到满意,沟通肯定会失败。
- 如果消息有多种理解方式,那么别人就会以造成最大损害的方式来理解。
协同工作,实现持续的知识共享
因此,向所有人保证,经常进行对话以及花更少的时间写作是完全没问题的,大家不需要为此感到内疚。推动跨岗位的合作。接受紧密协作能实现持续知识共享的理念。但是,请确保将少量最关键的知识记录下来并长期保存在某处。