写点什么

对话 Ruby on Rails 之父 DHH:我们需要重新审视软件开发

2020 年 11 月 30 日

对话Ruby on Rails之父DHH:我们需要重新审视软件开发

或许这有点尴尬,即使在这个行业呆了好几年,我仍然不明白为什么软件公司如此迷恋交付速度。这种迷恋已经深植到软件语言中,他们用 Sprint 作为工作时间单位,用速度(velocity)来衡量进度。快速交付软件真有那么重要吗?我不知道。我自己不开发软件,但每天都会做故障排除工作,有时甚至希望工程师能慢一点。


我把这个问题抛给了 David Heinemeier Hansson(DHH)——Ruby on Rails 之父,Basecamp 联合创始人兼 CTO,畅销书《重来》的作者。他擅长分析软件行业的趋势,无论是技术层面的趋势(如微服务的日益普及),还是机构层面的趋势(如风险资本成为发展高科技业务的默认方式)。


近日,我与他聊了聊当今的软件开发方式、这些开发方式对开发者来说意味着什么,以及如何寻求替代方法。


问题 1:软件方法学成为了一个行业,涌现出 Scrum、敏捷以及各种各样的书籍等。但是,你和 Basecamp 团队却没有遵循这些做法。这是为什么?


答:首先,我们的软件开发方法主要受敏捷宣言和敏捷价值观的启发,而非现在的那些敏捷实践。


很多敏捷软件方法论侧重于产品开发,但这些领域其实并不难,它们与过程性的结构息息相关。与此相反,软件本质上是不可预测、不可知和不可塑的,就像气体一样,同一个基础思想可以有多种不同的开口。预估开发一个功能需要多长时间这种做法起不到什么作用,因为你不知道自己要开发什么东西,而且人类并不擅长对事情做出预估。纵观软件开发历史,一个软件项目要么延期,要么被取消。如果要总结软件开发的整个过程,你可能会说:“项目延期了,然后被取消了”。可以这么说,计划赶不上变化。


在 Basecamp,我们遵循的是“Shape Up”实践。通过这种方式,我们知道需要把重心放在哪里。我们尝试找到核心约束,也就是那些导致我们无法准确预先知道该做哪些事情的约束条件。我们只知道在约束条件范围内可以做些什么。但是,这与“做完了就是完了”又不一样,后者完全摒弃了产品管理思想。相反,我们的核心思想是:不要估算,要预算。 Shape Up 的核心是预算,重点不在于做一件事情要花多长时间,而是要知道做这件事有多大价值。做一件事情可能需要一周或几个月,关键是它的价值有多大?


有些事情值得花上一个工作周期(通常是极限),在我们这里就是 6 个星期,我们把它叫作“大批量”。如果只需要一个星期,或者两个星期,那就是“小批量”。添加一个项目描述(如“加个功能 A”),再指定约束条件,然后把它交给具体的开发人员。这里的关键在于,如果你有一个大的问题定义和一个固定的边界,并让有创造力的聪明人在这些约束条件内自由选择解决方案,他们将会做出令他们自己也深感自豪的工作。


问题 2:所以,这些方法的问题在于它们过分注重估算,而软件本身是不可能准确估算的?


答:我敢说,估算就是扯淡。它太不精确了,即使你有固定的输入信息也不管用,更何况你没有。在软件功能做出来之前,没有人能够准确地描述它应该像什么样子。在开始动手之前就可以预先描述某件事情应该像什么样子,这种想法就是胡扯。在某种程度上,敏捷就是要你通过运行软件来获得反馈,但现代敏捷实践却没能针对自身的问题做出反思。


问题 3:但软件技术非常笃信开发速度。如果你也重视开发速度,但又不相信估算,那该怎么做?


答:我们说的是进度和速度,它们实际上是两个不同的东西。你可以试着用更快的速度做事情,但可能并不会走得更远。对我们来说,Shape Up 的意义在于走得更远。项目的最终结果是要给客户和开发者带来让他们感到自豪和满意的有意义的大成果。将反馈循环缩得太小不会有任何好处。有一种观点认为,持续的反馈是一件好事。是的,但那也只是在某些情况下!我不想人们总是按照我所做的事情来评价我。例如,我们没有 Sprint。按照 Scrum(或其他方法)的要求,每两周就需要重新调整一次工作,这是一种压抑和混乱的工作方式,它只会让每个人精疲力竭,而不会真正交付任何东西。大多数人不可能在两周内交付真正的大功能。


关键之处在于将你的思维方式从估算转变为预算。不要去想做一件事要花多长时间,而是想想你愿意花多长时间去做一件事情。这是一个具有颠覆性的想法。需求可以是浮动的,因为模糊的项目定义实际上更为现实。高度具体的项目定义通常很快就会迷失方向,而模糊的定义给了从事这项工作的人发挥创造性和选择性的余地。当你这么做的时候,就赋予了人们去做他们认为自己最擅长并可以将工作做到最好的权力,而不仅仅是让他们遵循规范。


敏捷的叛逆在于拒绝预先的大设计,但我认为敏捷并没有得出足够的结论。它的想法是:“我们不想要宏大的前期设计,我们只是想要小的预先设计”。但这样也好不到哪儿去。很多软件方法太过关注实现技术,这是短视的。开发软件的难点在于弄清楚它应该做什么,而不是如何让它工作。有一个关于 10x 程序员的神话,但它并不是指程序员在实现问题时有多英勇,而是指他们重述问题的能力。


问题重述确实应该作为软件方法论的前沿。


问题 4:当团队被 Sprint、评估和遵循规范绑架时,代码质量和决策制定会受影响吗?


答:当然会,甚至比这个更糟糕。它会给人们带来痛苦。在这种模式下工作的人只会被吃掉和唾弃。每两周就要不断地重新估算你所做的每件事,因为这是新的 Sprint——它进行得非常快,但没有任何进展。


这就是为什么我们没有每日站会。它不停地旋转,在缠得很紧的皮带上绕着圈旋转。我认为这实际上是不人道的。敏捷又说了:“你知道吗?你想提前计划一个两年的软件项目?那完全是胡扯。太遥远了。”是的,但敏捷方法有点矫枉过正了,它把时间单位缩得太短。它把包含每日站会的两周作为一个神奇的周期。不,人们需要放松一下,需要一些自主权和一些空间。


通过广泛的实验,我们发现大约六周的时间可以为我们提供足够的呼吸和思考空间。只要你设定了边界,就会取得进步,即使每天看起来并没有进展。在一个受到反馈循环严格约束的团队中,你可能会看到更多的活动。他们疯狂地翻动着,但最终没有取得更大的进展。有时候,跑得最快的团队是那些看起来非常安静的团队。他们不会一直基于一些方法论或每五秒钟就响一次的时钟做着单调的工作。


问题 5:你觉得 Shape Up 方法能在更大的组织中发挥作用吗?比如,一家拥有 500 或 5000 名工程师而非 50 名工程师的公司?


答:首先,在考虑软件方法论时,你不应该想着说它能够从 5 个人扩展到 5000 人。试图将 5000 人的工作计划作为一个单位是不切实际的,而且实际上没有人会这么做。你应该这么想:对于一家公司来说,合适的团队规模通常是多大?比如,一家 500 人的公司有 100 个 5 人的团队。这样比较才有意义。


并不是说 6 周这个神奇的数字对每家公司都管用。我认为这种方法在很多情况下是可行的,比两周的方法要常见得多。它慷慨得多,也现实得多,让你可以交付一个完整的东西。但如果在 6 周内,你还是无法交付一个完整的功能,那说明你的反馈周期仍然太短。如果我不能在一个周期内完成所有的事情——从开始,到实现,再到发布,那说明我的周期太短了。


如果你从事的是原生应用程序开发(这是一个名声很好的工作),也许 6 周的时间是不够的。你可能需要长一些,也可能不需要,这取决于你是否能够交付你想要交付的东西。但整个行业已经形成了这样的想法:“两周是一个很好的时间框架。”什么?为什么我们会这么肯定?即使对一家 5000 人的公司来说,6 周也是一个更现实的起点。


问题 6:你还谈到了软件开发中出现的其他趋势,比如微服务和无服务器或测试驱动开发。软件工程中有什么趋势是你真正觉得有吸引力的?


答:这个问题很难回答。不过,要说出那些我不喜欢的东西会容易得多。


显然,我是有一点偏见的,因为是我在推动这些事情。我在实现 Ruby on Rails 和 Shape Up,在分享一些我自己认为合适的软件开发方法。这并不是说其他方法都不可行,还有其他有各种各样的技术栈和 Web 开发方法,我觉得也不错。我很高兴看到我们在 JavaScript 开发方面取得的进步。在原子层面,前端开发领域的进展已经很出色了,但我们可能在分子层面上迷失了方向。前端的框架和方法并不是很好,但我认为基础技术在随着转译器、填充技术和 JavaScript 核心特性的进展在逐步改进。


我们现在做的很多 Web 开发工作都是基于 25 年前的基础知识。核心的创新更多的是意识到应该把重点放在哪里、什么才是重要的以及应该推动哪些东西。例如,前端和后端的交互应该使用 JSON(服务器端只负责提供 API,让 API 返回 JSON),这是一种糟糕的迂回。我们应该重新拥抱 HTML,把 HTML 作为我们工作的中心,通过网络发送 HTML,这样在第一次加载页面时就会返回完整的 Web 文档,然后使用 HTML 进行后续的更新。


问题 7:我想回到微服务话题。我之前采访过一位工程师,他说采用微服务是因为单体系统变得过于复杂而难以维护。你对微服务有什么不满意的地方?


答:单体系统变得过于复杂……这里的“变成”是指什么?这个只发生在我们身上吗?我们是完全无辜的旁观者吗?复杂性在碾压我们而我们却无能为力?这个假设就是扯淡,我们需要反驳一下。你没有必要被复杂性困扰,如果有,那也是你自己选择的。一旦你选择了复杂性,那么一个很自然的反应就是尝试把复杂性塞进更多不同的盒子里,因为你不能一次处理所有问题,对吧?错了!你要做的是先把复杂性问题处理好。事情为什么会这么复杂?有必要这么复杂吗?它们能不这么复杂吗?在我看来,答案是:它们可以不那么复杂。


我想要解决这里的根本问题。Web 开发在很大程度上应该比以前更简单,在压缩概念开销方面,我们取得了巨大的进步。在以前,这些领域非常复杂,需要人们非常谨慎地思考。但人们仍然在开发庞大而复杂的应用程序,这是他们自己造成的。他们不去想可以做些什么,而是在想:“我们应该把复杂性放在哪里”?不如我们先来讨论一下为什么我们会有这种复杂性?


他们说的复杂性是指偶发复杂性和固有复杂性。偶发复杂性存在于实现过程当中,固有复杂性是指领域的复杂性。大多数 Web 应用程序的固有复杂性与以往一样,我们倒退的地方是引入了大量的偶发复杂性。如果你解决不了单体系统的复杂性,那么凭什么认为你能够将这些复杂性分散到众多的微服务中,况且微服务还引入了通信、网络不可靠、重试、两阶段提交和其他各种复杂性问题,而这些复杂性在处理方法调用、参数和运行基本的单进程时是不存在的。在复杂性层面,没有什么比分布式应用程序更糟糕的了。即使是很小的问题,只要你把它变成分布式的,它的复杂性就会增加一个数量级。


问题 8:其他行业,甚至是政治家们都将科技视为创新的源泉。与此同时,我听到越来越多的开发人员说,整个领域已经从根本上被破坏了……


答:不,不,不。这是一种误解,他们认为大多数软件开发都是工程学,但我不这么认为。当你从工程师的角度来看软件开发时,是的,事情看起来很糟糕。工程师会说:“你们的规范太松散了,容忍度也没有定义”。都是类似这样的东西,包括工程评估等等。这是对软件开发的根本性误解。软件开发与建造桥梁不同,它们不只是同一学科的不同分支。


很多软件工程师的这种自我厌恶是没有意义的,而且永远得不到解决。软件开发是一个年轻的行业,如果我们再给它 30 年时间,让它遵循 ISO 标准或者更严格的标准,我们将会达到一种理想化的水平,就像航空航天、电梯或桥梁建设方面的工程那样……不,我们不会这样。软件开发是一种完全不同的领域,它需要一种完全不同的方法。


我们有了很多答案,只是不敢接受。例如,在传统工程中,估算占了很大一部分比重。事情的进展通常基于估算和关键路径图,因为这是建造摩天大楼最简单的方式。你不能在浇筑混凝土后重新配置塔架,但软件开发不是这样的。软件在很多方面与写作、游戏制作、电影制作等创作过程更类似。当你在设计未知的东西时,你并不知道它好不好,直到你可以亲眼目睹。


我们先来说说电影制作。电影已经有一百多年历史了,我们不是已经弄清楚创作的过程了吗?不,我们还没有。即使有伟大的导演和强大的演员阵容,仍然可能制作出一部非常糟糕的电影。但在建筑领域,很大程度上,如果你找到一个伟大的建筑师、一家伟大的工程公司和一家伟大的承包商,就可以建出一栋好建筑。你可能会犯一些小错误,但基本的结构是健全的,除非有人重大疏忽。在电影制作、音乐创作和软件开发中,总会有失败的情况发生。即使懂技术的人聚在一起工作,仍然可能以失败告终。


问题 9:还有一件事,工程师们对编程语言的选择非常在意。编程语言有好坏之分吗?


答:对个人来说是有的。对个人而言,一种编程语言可能比其他的更好或更差。客观地说,它们确实存在好坏之分,但关于编程语言之争的讨论没什么意思。对我来说,个人的选择更有意义。


例如,一直以来,关于编程语言好坏之争的一个方面是是否使用了静态类型还是动态类型,或者是强类型还是弱类型。Ruby 没有静态类型,所以存在一些动态类型处理不好的地方。而 Java 是强类型语言的一个标准例子,它的工作方式很不一样。对拥有不同大脑的人来说,他们与不同语言之间的关系也是不一样的,学习方式也不一样。有些人通过视觉来学习,有些人通过听觉来学习,这些方式对个人来说不分对错。如果你是一个视觉学习者,试图通过听觉或触觉的方式来学习是行不通的。对我来说,Ruby 是一种比我尝试过的任何一种其他编程语言都要优越得多的编程语言,因为它与我的大脑非常契合。


当我在讨论软件开发以及我的选择和观点时,我总是坚信什么对我来说是正确的。别人可以决定他们更偏向谁,可以选择是否对我和 Ruby 之间的浪漫恋情产生共鸣。如果他们不会,那也没什么大惊小怪的!


原文链接:


https://medium.com/computers-are-hard/computers-are-hard-building-software-with-david-heinemeier-hansson-c9025cdf225e


2020 年 11 月 30 日 13:472283
用户头像

发布了 114 篇内容, 共 26.3 次阅读, 收获喜欢 291 次。

关注

评论 1 条评论

发布
用户头像
还坚持 Ruby?太过于坐井观天了
2021 年 07 月 17 日 23:01
回复
没有更多了
发现更多内容

DFC的推出,去中心化金融的潮流

股市老人币圈新

【最不佳实践】文件上传并不简单

刘宇

Python Serverless 文件上传

为什么需要数据库连接池

赖猫

MySQL 数据库 后端开发 连接池

Linux之watch命令

入门小站

Linux

03 设计模式之工厂模式

陈皮的JavaLib

Java 面试 设计模式 工厂模式 8 月日更

Hbase 入门详解

Se7en

弱口令到底是什么牛马?

网络安全学海

黑客 网络安全 信息安全 渗透测试 漏洞挖掘

我测了啊,我真测了!

QualityFocus

测试 质量保障 线上问题 缺陷

2020-2021京东Java面试真题解析

Geek_f90455

Java 程序员 后端

各种消息队列设计要点与对比

海明菌

消息队列 消息队列对比 消息队列系统设计

JDK 从8升级到11,使用 G1 GC,HBase 性能下降近20%。JDK 到底干了什么?

毕昇JDK社区

黄金圈法则解读数据中台(1):为什么需要数据中台

水滴

数据中台 黄金圈法则 8 月日更

2020-2021华为Java面试真题

Geek_f90455

Java 程序员 后端

王者并发课-钻石2:分而治之-如何从原理深入理解ForkJoinPool的快与慢

技术八点半

Java 多线程 并发

Windows10下JDK8下载及java环境配置

Bob

8 月日更

【收藏】Java 8的 Stream 玩法大全

小阿杰

stream java8 8 月日更

Vue组件通信之ref

Augus

八月日更

关于 go run 命令执行过程中的“坑坑点点”

liuzhen007

8月日更 8 月日更

SpringBoot 中的事务处理

xcbeyond

事务 springboot 8月日更

第一次凡尔赛,字节跳动3面+腾讯6面一次过,谈谈我的大厂面经

编程菌

Java 编程 程序员 面试 计算机

12年高级工程师的“飞升之路”

Geek_f90455

Java 程序员 后端

2020-2021阿里巴巴Java面试真题解析

Geek_f90455

Java 程序员 后端

趁着课余时间学点python(二)缩进 标识符 保留字 注释 输入输出的理解

ベ布小禅

8月日更 8 月日更

DDD领域驱动设计·学习应用·一

小诚信驿站

领域驱动设计 领域驱动模型DDD 中台架构 领域驱动

网络攻防学习笔记 Day94

穿过生命散发芬芳

网络攻防 8月日更

缓存数据历险记(一)--被缓存警察上课一天

卢卡多多

redis 缓存 8 月日更

在线网页快捷方式创建工具

入门小站

工具

2021Java不死我不倒

Geek_f90455

Java 程序员 后端

Druid 通过 dsql 进行查询

HoneyMoose

Elasticsearch VS ClickHouse

Se7en

奥运“哮喘”运动员为什么越来越多?

脑极体

低代码的认知误区与落地实践

低代码的认知误区与落地实践

对话Ruby on Rails之父DHH:我们需要重新审视软件开发-InfoQ