快手、孩子王、华为等专家分享大模型在电商运营、母婴消费、翻译等行业场景的实际应用 了解详情
写点什么

代码只能说明它能做什么

  • 2020-07-25
  • 本文字数:2924 字

    阅读完需:约 10 分钟

代码只能说明它能做什么

本文最初发布于 Marc Brooker 的个人博客,遵循Creative Commons Attribution 3.0 Unported License协议,经原作者授权由 InfoQ 中文站翻译并分享。


代码只能说明它能做什么。这对计算机而言很重要,因为我们是通过代码告诉计算机做什么。对人来说,只要我们不需要修改或调试代码,这就没什么问题。不过,如果我们要修改或调试,问题就来了。从根本上说,调试是一种活动,通过修改程序使它的行为与它应该做的事情保持一致。这就需要我们知道程序应该做什么,而这是无法从代码中获得的。有时候这很简单:它崩溃了,它应该做的肯定不是崩溃。除了这种简单的情况外,发现意图就比较困难了。


当应该做什么很微妙时,比如在构建分布式系统协议时,调试就特别困难。我们在论文“数以百万计的微型数据库”中写到:


我们在代码审查、simworld 测试和设计会议时经常回顾协议的 TLA+模型,以解决 Java 代码或书面交流中的歧义。


问题在于协议的实现(在 Physalia 的例子中是 Java 代码),它既不完美,又过于具体。它过于具体是因为它需要完全确定。计算机需要这样,而协议本身也有一定的回旋余地。它过于具体还因为它必须处理诸如底层性能问题等规范未考虑的问题。


那些值存储在 ArrayList 中是因为顺序很重要,还是因为 O(1)随机查找很重要,又或者是因为其他原因?还是因为这样写最容易?如果我把它改了会发生什么?


虽然不能和分布式协议相提并论,但业务逻辑代码存在更多这类问题。代码的业务逻辑过于具体,而又不够准确。我写这篇文章是因为 @mcclure111 的一条推特,她可以说是一语中的:


由于大多数软件都没有一个形式化的规范,所以大多数软件都是“做什么就是什么”,在编辑别人的代码时,要尊重作者的意图就要承受难以置信的压力。你不知道哪些怪异的模式是真正承担负载的。

(@mcclure111),2020年6月20日


这是代码的一个大问题:你不知道哪些怪异的模式是真正承担负载的。你可能记得,或者能够猜测,或者能够从基本原理中找出答案,或者你根本不关心,但是所有这些都会降低你的速度,并且容易出错。我们能做些什么呢?

设计文档

文档一点儿都不酷。大多数软件工程师从学校出来的时候,似乎都认为文档不是他们的工作(而是技术作家的工作),或者将其视为奇怪的东西,就像听他们的 SE 教授谈论那些像 Fortran 一样古老的东西一样。这在一定程度上是可以理解的。


我自己的软件工程课程就强调,要尽力用 UML 记录实现方式,此外没有提到其他文档。基本上,用 UML 重写软件对任何人都没什么帮助。我完成了我的学位,认为文档是不必要而又耗时的工作。甚至敏捷宣言也同意我的观点:


可工作的软件胜过面面俱到的文档。


后来我发现,设计文档记录了系统开发期间的意图和决策,可以帮助团队取得短期的成功,帮助人们取得长期的成功。我不再把所有的事情都记在脑子里,我有信心以后可以重新发现被遗忘的事实,这使我变得更加大胆,我能更快地行动。这同样适用于团队。


我看到,成功的团队不仅记录他们的设计内容以及背后的原因,而且还记录他们的决策过程。当需要对系统进行更改时,无论是为了调试还是为了响应不断变化的需求,这些文档都是非常宝贵的。如果你不知道当初为什么这样写,就很难确定更改某个东西是否安全。记录下你是如何做出决定的,这很重要,因为我们不是完美的人,知道以前的决策过程,有助于了解你的决定何时会显得奇怪或令人惊讶。


文档不必太繁琐。除非你认为它们有帮助,否则不必费心绘制ER图。你可能应该完全忽略 UML。取而代之,你应该尽可能清晰和简洁地用文字来描述这个系统。你可以从为团队构建 RFC 模板开始,该模板可能受你在网上找的模板的启发。SquareSpace的模板似乎就很合理。有些设计适合 RFC 格式,有些则不适合。尽可能地平铺直述。


然后,保存这些文档。把它们放在安全的地方。同时,要确保需要维护系统的人能够找到它们。在探索历史的过程中,让他们更像一个图书馆的访客,而不是劳拉·克罗夫特(古墓丽影的主角)。


我并不提倡预先进行大量设计。关于一个项目,我们学到的许多最重要的东西都是在实施过程中学习的。其中一些最重要的事情是我们在实施完成数年后才知道的。设计文档不是一个静态的一次性提前交付,而是一个持续的过程。最重要的是,设计文档并不是要恪守坏主意。如果有错误,就纠正它,然后继续前进。文档不是与魔鬼的交易。

注释

很少有话题像注释一样能引起程序员的激烈争论。我们被告知,注释是愚蠢的,或者是幼稚的,或者难以表现出你在编写令人费解的混乱代码时的男子气概。如果它很难编写,那么它也应该很难读懂。毕竟,你是编码界的詹姆斯·乔伊斯(爱尔兰作家)。


先不说这些愚蠢的想法,让我们回到 @mcclure111 的话题:


这意味着“揭示”作者意图的注释是有价值的,而揭示“作者没有意图”的注释则更有价值。如果没有这些提示,您只能迷信地编辑,即使不知道为什么也要保留那些怪异的模式。

(@mcclure111),2020年6月20日


注释让我们可以将作者的意图编写到代码中,而编程语言本身并不总是能做到这一点。类型、特性、接口和变量名确实可以将意图置入代码中,但并不完全是这样(我看到您了,类型系统最高纲领派)。这些东西是可以传达缺失的意图——考虑一下RandomAccessArrayList——但这也是不完整的。注释良好的代码应该清晰描述作者的意图,特别是当意图在转换为代码的过程中丢失,或者实现约束隐藏了设计意图时。可以链接到设计文档的代码注释特别有用。


有些语言比其他语言更需要注释。我发现,有些语言(比如 SQL)几乎总是掩盖了实现细节背后的设计意图。

形式化规范

在“谁不画蓝图就建房子?”一文中,Leslie Lamport 写道:


对规范的需求来自两个观察结果。首先,在做之前先想好我们要做什么是个好主意,正如漫画家 Guindon 所说:“写作是一种自然的方式,让你可以知道你的想法有多草率。”

第二个是,要编写出一个好程序,我们需要考虑代码层面之上的问题。


我发现,从平铺直述的非形式化规范到 TLA+形式化规范,都能加快程序的编写速度,帮助我们减少错误。尽管我很喜欢那篇文章,但我认为 Lamport 忽略了形式化规范的一个重要价值:它是一个很好的交流工具。在开发我所构建的一些最棘手的系统时,我发现,有大量注释的形式化规范是非常有用的文档。规范说明语言都是描述意图的,有些可以很容易地将意图与实现区分开来。


下面这段话还是来自论文“数以百万计的微型数据库”:


在亚马逊,我们广泛使用了 TLA+,事实证明,它在 Physalia 的开发中非常有用。在我们的团队中,TLA+有三种用法:编写协议规范,从而检查我们是否对协议有了深入的理解;使用 TLC 模型检查器针对正确性和活跃度设计检查规范;编写带有大量注释的 TLA+代码,作为分布式协议的文档。虽然这三种方法都增加了价值,但对 TLA+而言,作为一种自动测试的(通过 TLC)、极其精确的协议文档格式,可能是最有用的。


形式化规范可以帮助我们编写优秀的文档。就像设计文档一样,它们不是不可变的工件,而是反映了我们对这个问题的了解。

总结

构建长期的、可维护的系统不仅需要与计算机通信,还需要与他人交流,并与未来的自己沟通。沟通、记录和索引设计背后的意图是这个情景的重要组成部分。请抓紧时间,否则以后可能会后悔的。


英文原文:


Code Only Says What it Does


2020-07-25 10:001592
用户头像

发布了 722 篇内容, 共 458.3 次阅读, 收获喜欢 1537 次。

关注

评论

发布
暂无评论
发现更多内容

杀无赦!斩了Java拦路虎之红黑树篇

Java 程序员 后端

树莓派3B搭建Flink集群

Java 程序员 后端

毕业三年,从小公司到大厂,先后四面阿里、小米、美团等

Java 程序员 后端

没想到-Springboot-+-Flowable-开发工作流会如此简单

Java 程序员 后端

无锁并发框架-Disruptor的使用(二)

Java 程序员 后端

日志规范多重要,这篇文章告诉你!

Java 程序员 后端

最快最强?腾讯高级技术专家深入浅出整理Java性能优化全栈笔记,强了不止一点

Java 程序员 后端

求职经历,三轮技术面 +HR 面,面试也不过如此

Java 程序员 后端

数据结构之链表复习

Java 程序员 后端

树莓派3B+搭建OpenCV3(1)

Java 程序员 后端

案例教你一步步设计DDD微服务项目

Java 程序员 后端

死磕18个Java8日期处理,工作必用!

Java 程序员 后端

每天5分钟吃透华为18级架构师推荐252页Docker容器技术入职华为云

Java 程序员 后端

新年红包封面来了,3000万份红包封面来啦!到点直领!(1)

Java 程序员 后端

树莓派3B+搭建OpenCV3

Java 程序员 后端

正则表达式--只求能看懂别人写的正则表达式是什么意思

Java 程序员 后端

来自一位阿里朋友的组件化架构实践

Java 程序员 后端

来自北京大学NOIP金牌选手yxc的常用代码模板1——基础算法

Java 程序员 后端

最新美团滴滴Java岗虚拟机面经:2020下半年你还想不想涨薪?

Java 程序员 后端

死锁终结者:顺序锁和轮询锁!

Java 程序员 后端

数据结构之栈应用

Java 程序员 后端

新鲜的字节跳动、美团、B站、京东Java面经,程序员你眼馋了吗

Java 程序员 后端

来自北京大学NOIP金牌选手yxc的常用代码模板3——搜索与图论

Java 程序员 后端

来说说缓存穿透、缓存击穿、缓存雪崩都是什么?怎么解决?

Java 程序员 后端

毕业参加工作了,记住一句话,攒钱绝对靠谱(1)

Java 程序员 后端

新人一看就懂:Dubbo+Zookeeper的RPC远程调用框架demo

Java 程序员 后端

新年红包封面来了,3000万份红包封面来啦!到点直领!

Java 程序员 后端

普通本科毕业一年,刷完这 1000 道 JAVA 面试题,成功逆袭上岸

Java 程序员 后端

最新阿里Java面试题整理+进阶资料分享,看完直接收藏

Java 程序员 后端

月薪3K与月薪3万的程序员,差距在哪里?

Java 程序员 后端

毕业参加工作了,记住一句话,攒钱绝对靠谱

Java 程序员 后端

代码只能说明它能做什么_语言 & 开发_Marc Brooker_InfoQ精选文章