写点什么

60 岁代码匠的几篇小作文,解决了大多数程序的迷茫(下)

作者:图灵社区
  • 2022 年 1 月 17 日
  • 本文字数:6020 字

    阅读完需:约 20 分钟

60岁代码匠的几篇小作文,解决了大多数程序的迷茫(下)

陈德伟 译


上篇 Bruce 分享了自己学习编程的心得,并在如何构建自己的核心竞争力方面给出诸多建议。


本篇将待大家一起探究,编程的本质是什么?


谷歌的首席 Java 架构师 Joshua Bloch 认为,“编程就像文学艺术,程序的可读性必须更好。如果你不擅长写作,就很难达到目标”。这和 Bruce 的观点不谋而合,希望本篇能带给你新的思考。


本文节选自《On Java 中文版 进阶卷》

编写软件就像写作



我终于找到了对软件开发的一种正确类比。唉,听到这个类比的开发者不会开心的。


为什么需要类比?我们对计算机进行编程,这牵扯到很多东西。我们知道这些东西都代表着什么,因为我们就是做这一行的。但对于利益相关者(经理、CEO、客户、股东等)而言,软件开发是一个谜。他们不想知道关于它的一切,但想了解足够能预测软件开发行为的部分,至少能预测个大概。


最初的程序员是数学家和工程师,所以我们很自然地尝试将软件比作一门科学,或者一项工程。在大多数情况下我们发现,无论我们多么希望软件像数学证明或桥梁建设一样,它都不像。


利益相关者试图遵循我们的类比,然后提出对他们来说很重要的问题: “如果编程就像数学,为什么程序会经常出故障?数学要么对、要么错,软件却会在运行一段时间后发生故障。”当我们放弃了科学的类比后,他们则会问:“如果程序员就像工程师,那么我可以用一个工程师替换另一个工程师,然后得到类似的结果,对吧?”


第二种类比一直在给利益相关者带来各种恐慌。总的来说,工程师的生产力水平相似,并且产生的结果是可验证的。工程中有很多一致性,既然我们称开发行为为“软件工程”,那么软件中也应该有类似的一致性。


解决这个问题的两种典型方法是大否认(“忽略差异并假装所有软件开发都相同”)和小否认(“差异是偶尔的。我们可以强制实现一致性”)。


大否认是行不通的。但小否认导致了对“软件工程师标准化”的反复尝试,其中最显著的做法就是认证考试。这类观点是这样的:如果我们有一个认证过程,软件工程师就会像真正的工程师一样,并且他们的水平也能保持一致。


幸运的是,认证考试从未走得太远,因为程序员永远不会认真对待这样的事情。雇主则希望雇用最好的程序员,而不管他们是否有任何特定的学位或证书。现存的认证计划大多是为了获利,这似乎不可避免地使曲线变平了。例如,我认识的所有人都没有认真对待过基础的 Sun Java 认证。更高级的 Java 认证似乎比较有趣,但对我来说,它们也更像研讨会而不是考试。


这些标准化的尝试通过将我们的工作简化为最简单的行为,使所有程序员变成一台机器上的相同齿轮。我有次将这种尝试嘲笑为编程即打字(Programming as Typing)。


所以我们既不是科学家,也不是工程师。那么该如何描述自己的工作,才能使程序员以外的人理解呢?特别是,如何以某种方式解释为什么程序员、编程项目以及项目的成功和失败之间存在如此大的差异呢?

下面是我的建议,我认为它解释了一切。


我们是作家。


大多数人可以将单词组合成句子。他们并不需要成为伟大的作家就能和别人顺畅地交流。大多数程序员能编写一些程序,尽管可能不是很好,但大多数公司也并不真正需要非常好的程序。这些公司只需要基本的编程技能。从任何地方获得的计算机“科学”学位都足够好,而工作就是工作。这些工作不需要你参加继续教育、会议或研讨会,不需要你对编程技艺特别感兴趣,也不需要你试图学习更多。


这样的人会写作,虽然只是基本的写作。他们不是散文家或小说家。请记住,有很多已发表的文章和小说并不是特别好,甚至不值得一读。而这些东西似乎也卖得很好,值得所有的努力和风险。


但是有些人愿意致力于写作,愿意努力奋斗并发现自己在世界上的位置。他们是一些截然不同的作家(无论写的是散文还是程序)。这些人可以更快地生产出更多的东西,结果也比其他人的更清晰、更深入。


小说写作是一项令人敬佩的壮举。写一些可能值得发表的文字是一项更伟大的壮举。但绝大多数已出版的小说不值得一读。只有小部分作家创造了真正有价值的东西,没有人真正知道他们是如何做到的。每个优秀的小说家都以自己的方式实现了他们的艺术品。非小说类的书呢?每年出版的小说大约有 5000 部,非小说类图书大约有 50 000 部。大多数非小说类图书只能算实用,无法带来很好的阅读体验。但它们包含了有用的信息,并且有足够多的人购买,也算是物有所值(至少对出版商而言是这样)。


这回答了一个最重要的问题:为什么不能用一个程序员替换另一个程序员并获得类似的结果?它还会启发你重新评估自己的一些项目,在这些项目里你可以自行决定团队成员以及项目如何运作。无论是悬疑小说、青春小说,还是海量的非小说类图书,每一本的创作都有其特定的结构和限制(你会惊讶于出版商对它们控制之严格,就好像他们正在制造某种基本商品一样——“谋杀必须发生在前 10 页”,等等)。这些大众市场畅销书(“杀手级应用程序”)的卖点并不是作者的想法和风格。大众市场畅销书通常不是伟大文学家之作,因为大多数人没有耐心阅读这些巨匠的作品,就像大多数程序员并不阅读编译器的源代码一样。


虽然利益相关者不一定了解写作和出版过程的复杂细节,但他们通常明白有不同的写作类型,明白写作是一项奇怪、无法预测的艺术过程,无法保证结果。因此,即使“编写软件就像是在写作”的类比不一定会提高我们工作的可预测性,也至少可以帮助非程序员理解其不可预测性。

编程即打字



我们如何以新的眼光看待在构建软件时遇到的问题呢?


(下文最初是对 John Camara 的回复,现在也可以单独拿出来阅读。)


我相信现在可以安全地假设,大多数软件开发人员和项目经理已经认识到了测试的重要性,所以我觉得没有必要再对测试发表评论了。


在我做过咨询顾问的一些公司里,测试仍然是一个新事物。我估计大多数软件开发人员还没有认识到测试的重要性,只有那些处于领先地位的噪声制造者在学习和谈论它,结果给人的印象就是测试现在已经被广泛接受了。


还有一个关于噪声与现实的例子:人们总是说 COBOL 和 FORTRAN 程序员比任何其他类型的程序员都多。但你最后一次见到这些人(更不用说和他们交谈了)是什么时候?根据这个指标,他们并不存在。但显然,COBOL 和 FORTRAN 程序员其实是有很多的。


尽管通过另一双眼睛来看问题可能很重要,但我觉得这不是代码审查最重要的好处。我认为代码审查提供了一种相互指导的方式。


是的,展示示例并讨论在理论上如何正确使用特定语言功能是一回事。但当一段代码真的对某人有利益关系时,它才变得真实而重要。(我只是出于需要才在书中创建了玩具示例。)


我认为概念越抽象,人们越需要通过实际尝试构建的项目来学习,以便脱离这种“抽象”的束缚。例如,在教授面向对象设计(比编程更抽象)时,我鼓励人们使用自己的设计,这样我们可以一起对其进行研究。这是对培训或咨询时间更好的利用,因为人们可以在自己的项目上取得实际进展,从而在研讨会中获得更多的好处。


这很可能是当今大多数开发人员所经历的唯一的指导形式。毕竟,在这个不惜一切代价来降低成本的悲伤时期,指导已经失去了大部分(如果不是全部)优先权。我们忘记了将集体经验代代相传是多么重要。


这可能源于对(自以为的)效率的考虑。定期指导似乎只是一种项目成本,它干扰了工作的完成。即使能在项目之间抽出一周零散的时间进行培训,你也只是按部就班地完成培训,然后收工,尽快回去鼓捣代码。这样的场景多不胜举。


问题在于,虽然许多程序员明白编程是在头脑里进行的,代码本身只是这个过程的产物,但在外行人看来,代码就是你正在做的事情。(这是可以理解的,因为代码就是核心的可交付成果。)因此,如果重点在于代码而不是代码背后的心理过程,那么你会用尽可能快且尽可能便宜的方式来生成代码,并丢弃任何会阻碍代码创建的东西。由此甚至可以得出“编程即打字”的逻辑。


如果这是真的,你会希望看到人们一直在打字。10 个人的打字速度比一个人快,因此,如果雇用 10 名海外程序员比一名美国程序员便宜,能完成更多的打字工作,那么就会获得巨大的经济利益。


实际上,一项又一项的研究表明:项目的成功来自于你雇用的人。这表明编程不是一种大规模的生产活动,程序员也不是可以替换的组件。


我认为一个很好的类比是写小说。假设你想写出一本像 Stephen King 的小说那样的畅销书(我不是很喜欢这类作品,但它们正是出版商熬夜试图弄清楚如何批量生产的那种书)。你可以说:“一本书是由字和词组成的,而字和词是由打字产生的,所以要创作一本书,我们必须让一群人打字。打字的人越多,创作一本书的速度就越快。打字员越便宜,创作出来的书就越便宜。”


这种逻辑很难反驳。毕竟,一本书确实是由字和词组成的,字和词也确实是打字产生的,等等。但读过小说的人都知道,这个逻辑一定有某些根本性的缺陷,因为有的作者你喜欢,有的作者你讨厌。字和词的选择以及书的结构造成了差异,而这取决于写书的人。你知道,无法用 10 个二流作者取代一个好作者,来获得该作者所能创作的内容,或者任何你想阅读的内容。


另一个例子是房屋。就像软件一样,房屋也是由相互配合的子系统组成的。就像构建软件一样,建造房屋也需要很多工人,其中一些人甚至是可以替换的。是谁在钉墙板并不重要。但是你会注意到房屋的设计,会注意到它组装得有多好,而这些都是由建筑师和建造者决定的。


很长一段时间以来,我一直在苦苦思考一个比较普遍的问题。那就是,你很难反驳“符合逻辑”的论据,例如“软件是通过打字生成的”。它表面上是对的,但是并不反映问题的本质。如果你继续针对这些字眼和别人争论,将白费力气,因为其逻辑是无可辩驳的。尽管这种逻辑完全忽略了问题的实质。


这也可能就是我一直在与静态−动态语言争论作斗争的原因,因为它让我有同样的感觉。你可以提出各种理由认为静态检查是一件好事,直到拥有了使用动态语言进行编程的经验,这时你的工作效率要比使用静态语言高得多。但是这种经验违背了用于支持静态语言背后推理的逻辑。


还有另一个原因:我认为“细节很重要”,而环境噪声真的会让你感到疲倦(研究也表明噪声会让人感到疲倦)。我在这里谈论的是视觉噪声和复杂性噪声。例如,Ruby 竟然有 begin 和 end 语句,而且还使用 new 创建对象。当看到这些时我很失望。这些都是来自以前语言的噪声功能,用来支持其编译器。如果你的语言在堆上创建所有对象,就无须用 new 来区分堆对象和栈对象了(就像在 C++中所做的那样,Java 盲目地模仿了这一点)。大家总是会缩进代码,所以你可以使用缩进来作为作用域。除了支持 Python 的极简主义设计外,当我提出这些想法时,可能还会有许许多多合情合理的借口,来告诉我为什么这是最好的做事方式。在不质疑这些论点所依据的基本原则的情况下,这些论点非常严密,不过它们实际上可以归结为“我已经习惯了,不想以不同的方式思考”。


Java 总是需要大量额外的打字输入。但是,像 IntelliJ IDEA 这样的 IDE 可以为你生成代码,这似乎证明了大量的视觉噪声是合理的。对于有这种想法的人来说,这很好,甚至是可取的:“它更清晰,因为它更明确。”(Python 甚至有一句格言:“明确优于隐含。”)甚至有比这更激进的观点,还得到了许多人的支持:每个类都应该有一个关联的接口。在我看来,这使代码变得更加复杂和混乱。所有这些细节的成本都很高,即使使用了为你生成大量代码的工具也是如此。


相比之下,当我教授 OO 设计时,我最喜欢的方法是:(1)使用客户实际正在处理的项目,以及(2)快速完成设计过程,并使用动态语言(我最擅长的是 Python)对结果进行建模。在大多数情况下,客户不了解 Python,但这并不重要。我们仍然能很快地将系统模型建立并运行起来,在此过程中,我们会发现最初设计阶段所没有发现的问题。因此,由于动态语言的速度和敏捷性,我们能较早且迅速地发现设计问题,并且可以改进设计,然后用重量级语言重新实现。


我认为,如果用重量级语言完成初始代码,那么:

  • 将设计变成代码会存在阻力,因为需要更多的付出——这不是一个轻量级的工作;

  • 出于同样的原因,对设计进行更改也会存在阻力。


然而,会有许许多多的人和我争论,说这种方法没有意义,他们有着完全合理的论据。我通常发现这些论据不是基于经验,而是基于对编程世界的基本假设得出的。


当谈到编程时,很多事情甚至无法从逻辑上进行证明。我们以这种方式得出的许多结论似乎是错误的。这就是为什么我喜欢《人件》和 Software Conflict 2.0 这两本书。这些书指出,在许多地方,我们做事情的基础虽然看似完全合乎逻辑,但实际上是错误的。(我在《人件》中最喜欢的一项研究表明,在所有形式的估计中,最有效的是根本不进行任何估计。)


我听说,希腊自然哲学家(我们今天称之为物理学家)更感兴趣的是事物如何运作,而不是某件事物实际上是如何运作的。因此,他们会根据自己的假设来辩论,而不会扔出小石头和大石头,来确定一个石头下落的速度是否比另一个快。


在我看来,当我们试图针对编程争论时,双方处于相同的立场。编程启蒙的很大一部分来自于向科学方法的转变,这看似是很小的一步,但其实是非常大的一步,影响也非常大。也就是说,你可以争论自己认为某事将如何如何,但是必须去实际实验。如果实验和你的论点不一致,你就必须改变自己的论点,然后尝试另一个实验。


关键就在于进行实验,并关注结果,而不是从信念出发并试图让世界与这种信念保持一致。即使已经过去了 500 多年,人类社会仍然在向理性时代努力。


我认为敏捷主义者所做事情的本质,就是通过科学方法来发现问题,二者之间可以进行完美的类比。不要编造东西(回顾一下我们为解决软件复杂性问题而发明的所有“解决方案”,这基本上就是在编造东西),而是做一个实验,看看发生了什么。如果实验否定了你过去使用过的论点,不要丢弃实验的结果,而是必须改变自己的论点。


当然,你不会被迫改变自己的论点。但即使改变不发生在一夜之间,那些看到实验并意识到事情与他们想象不同的人,也会超过你并进入新的领域。如果你的公司拒绝改变想法,他们就无法进入这个领域。

做热爱的事情


“1960 年,一位研究人员采访了 1500 名商学院学生,并将他们分为两类:为钱而入行的人,有 1245 人;以及打算利用获得的教育做自己深切关心的事情的人,另外 255 人。20 年后,研究人员对这些毕业生进行了调查,发现其中 101 人是百万富翁,而这些百万富翁中除了一个人之外,都来自那 255 个做自己所热爱的事情的人!


“既然如此,你可能认为自己对巴洛克时期的冰岛诗歌、蝴蝶收藏、高尔夫或社会正义的热情可能会永久阻隔你所爱和所做的事情。其实不一定如此。作为本世纪最伟大的小说家之一,弗拉基米尔·纳博科夫(Vladimir Nabokov)对蝴蝶收藏的热情远远超过了写作。他的第一份大学教学工作实际上是关于鳞翅类动物的。在过去 40 年中对超过 400 000 名美国人的研究表明,追求激情——即使很小的激情也是,每天从各种地方获取一点儿——可以帮助你充分利用自己目前的能力,并鼓励你开发新的能力。”


——出自 The Other 90%,Robert K. Cooper 著


另外,请参阅 Po Bronson 的书 What Should I Do With My Life?,对这些想法进行更多的探索。


用户头像

图灵社区

关注

好书,让编码更高效 2019.02.22 加入

IT出版旗舰品牌

评论

发布
暂无评论
60岁代码匠的几篇小作文,解决了大多数程序的迷茫(下)