【读后感】程序员修炼之道——通向务实的最高境界

最近读了一本书——《程序员修炼之道》,颇有感悟。

你别被这个名字吓到了,程序员的修炼之道,听起来很悬,其实非常实用。

这本书,就是一个清单手册,有100条,每一条都是一个使用原则。如果你去读的话可能都不相信这是程序员写的,字里行间透露着幽默感。就比如其中有一节的标题是“我的源码被猫吃了”,这不是告诉你程序员养猫会咬坏键盘,其实是说,如果某一天你不小心把代码删掉了,别着急找借口甩自己的猫,而是要积极的寻找替代方案,这样幽默感在书里到处都是。

我读的是第二版。这本书的出版日期是2020年4月,第一版是在20年前出版的。在这20年里面,全世界有很多程序员都把这本书当作自己的进阶手册。这本书并不是一本程序员的入门书,而是让一个程序员从菜鸟进阶成高手的书。

很多外行人可能会觉得程序员就是一群手艺人,不爱交流,就是闷头做自己事儿,虽然看不懂他们在干什么,但是总能看到他们在学习,提高自己的手艺,甚至包括很多刚入门的程序员也有这么认为的。他们认为程序员就是一个手艺人,只需要实打实的经营自己的手艺,让自己的程序运行的更快,更好,更少出现bug,就一定可以成为程序员高手。他们认为程序员本质上和其他的手艺人没有区别,就像是日本的寿司之神——小野二郎一样,年复一年的经营自己寿司手艺,最后就能成为顶级大师。

其实程序员和手艺人还真不一样。

手艺人追求的是完美。他们会把经过自己创造的创造物,不论是一个寿司,亦或是一个机械零件,都要尽可能的做到完美。而程序员,更准确的说是软件工程师,他们不像手艺人那样有强烈的理想主义,总是追求完美。相反,他们是一群务实的高手。在务实这件事上,软件工程师不只有精湛的记忆,还有深刻的哲学思考。

这本书的中文副标题叫做通向务实的最高境界,作者有两位,分别是大卫托马斯和安德鲁亨特,他们在软件界可是非常有名的。他们是敏捷软件开发宣言17个创始人中的两位。

什么是敏捷软件开发你先不用在意,但当你听到宣言二字,先想到的是什么?美国独立宣言?或是世界人权宣言?每一个宣言的背后都有着深刻的哲学思考。敏捷软件开发宣言也经常被称作是敏捷宣言,这就是务实哲学的集中体现,可以说是现在程序员高手的必修课。

你也许会觉得敏捷宣言是一小撮程序员的自嗨。其实,这个宣言里面的敏捷思想早就已经破圈了。

如果你在公司里每天早上都要开十几分钟的站立会议,或者总是从领导的嘴里听到要快速迭代,再或者一个产品还在创意阶段,负责人总是要求先把最小可行性产品做出来,这就说明你和你的团队已经被程序员的务实哲学深深地影响了。

如果用一句话来概括程序员心中的务实,Facebook公司在墙上的一句话最能代表程序员的价值观,那就是——完成比完美更重要。这本书里面作者也是一直在强调这件事,告诉读者应该交付“够好即可”的软件,还嘱咐读者说,你无法写出完美的软件。其实都是在提醒程序员放弃对完美的执念。对完美的执念很可能就是阻碍一个程序员从菜鸟走向高手的最大障碍。

为什么说对完美的执着反而会成为程序员成长障碍呢?

我觉得当你在第一次听到完成大于完美的时候,一定会非常惊讶:放弃对完美的追求?!如果是一个普通的互联网产品,软件不能做到完美,可能就是用起来不太方便,但是如果是银行的管理系统,或是航空系统不完美,那就会出问题,不仅是对客户的不负责任,也是对自己的不负责任。乔布斯要求自己的工程师把就算是在客户看不到的内部电路板也必须设计的像艺术品一样,虽然这份执着对客户没有价值:因为很多客户可能根本就不知道,但是是自己对自己负责。

甚至你可能会想,难道高手需要放弃追求完美,变成一个世俗的,没有原则的人吗?那样的话,我宁愿不做高手!

你想错了,高手程序员,放弃对完美的追求,不是不负责的做法,而是最负责的做法。不只是对自己负责,更是对客户负责。

书中举了一个例子:17世纪的时候,著名的荷兰画家伦勃朗有一副经典的画《夜巡》,这幅画可以说是一件非常失败的产品。这幅画本来是伦勃朗收到阿姆斯特丹民兵队的委托——给民兵队的成员们画肖像。伦勃朗也的确用自己高超的技艺完成了这幅画,但是他的委托人却非常不满意,因为支付了同样报酬的画,有些人的脸画的就非常不明显,甚至还被人挡住脸。伦勃朗追求了画作本身的完美,贴近现实,但完全没有考虑客户的需求,其实就是对客户不负责任。然后客户就把布朗告上法庭,让他的生意大跌,最成了伦勃朗人生的转折点,他一步一步地走向了破产的边缘。

程序员之所以用不追求完美的方式对客服负责,就是因为在这件事儿上吃过太多亏了。

我自己就是软件工程专业毕业,我记得非常清楚,当时学习的时候,所有软件工程的教材里都会介绍一个软件项目的流程模型——瀑布模型。瀑布模型就是说,软件开发的过程从需求分析开始,设计,开发,测试,部署,每个过程都必须按照步骤一个一个结束了,再进行下一个步骤,就像是瀑布一样。这个模型可以说是很有名的模型,但是也是最不实用的模型。20世纪80年代之后,这个模型就几乎不再被使用了。相反,后来所有的软件开发模型都会把瀑布模型当作一个靶子,可以说都是针对它的问题进行的改进。

其实现在的软件开发模型中,瀑布模型里说的几个步骤也都需要,比如需求分析:要想开发软件,那你先知道软件给谁用,实现什么功能,有什么性能要求等等,知道了这些后面的设计开发才不会做无用功。万一需求没有搞明白,等设计开发完了才发现错,到头来还要浪费时间精力,所以按照这个开发模型去做的话,程序员想要对客户负责,对自己负责,必须把每个步骤都做到完美:需求完全搞清楚了,设计才不会出错。设计完美,开发才可以有效率。如果任何一个步骤,有一个小问题,在后续的过程中,这个问题就会被放大,导致软件无法满足需求,甚至还会重做。

可是没多久,程序员们就开始因为这个模型吃亏了。因为软件开发要做的事情发生了变化。

在计算机刚开始商用化时,软件开发要实现的产品,一般都是仓库管理系统,财务管理系统等等这样的商业项目,而且当时要做也是把原来需要人在做的事情搬到计算机上,所以这个时候程序员要实现的功能都是很明确的。仓库管理,财务管理,业务流程等等,这些都已经非常成熟了,程序员要做的只是把它们在软件上重做一遍。但是啊再往后就不是这样了,计算机不再只是满足商业需求,也就是开始进入个人和家庭了,也就是to C业务。尤其是当互联网发展起来之后,很多程序员要开发的软件满足的都是个人需求。

这里多说一下,软件交付对象在to B业务时,一般称为是客户,在to C业务,一般称为是用户。后面更多的时候我们是在讲to C业务,所以我就用用户这个词了。

个人市场上的需求发展很快,按照原来的开发方法,需求分析,设计,开发等等一套流程下来一两年都过去了,到那时候个人市场需求早就变了,做的再完美也已经过时了。更要命的是,软件用户自己都说不清楚自己需要什么。你可以想一下,微信做出来之前你会想到自己需要这么一个软件吗?是不是觉得短信,QQ就完全可以满足自己需求?

需求不清,这才是程序员面临的真正挑战。而他们的务实就是解决这个问题。其实这也是敏捷宣言提倡一个核心,它重新定义了软件的价值到底是什么。

每次开发出来的软件交给用户,它的价值不再只是把实现了某个功能的软件交给用户,它更是探索用户真实需求的催化剂。催化剂是什么?它虽然不是我们需要的结果,但它却是促成结果的关键要素。如果把软件的价值定义成交付给用户的产品和功能,那么,的确需要提供完美的产品,因为要对用户负责。但是如果把软件看作是催化剂,看作是探寻真实需求的工具,那么,追求完成,而不是完美,就会是一个更好的选择。

我们都有这样的经历:和朋友们聚在一起,想约着一起去吃饭,但是到底吃什么?大家都说不清,一直在那僵着。只要这个时候有一个人提出:要不还是去吃麦当劳吧?局面马上就打开了。有人就可能会说麦当劳距离太远了,还是附近的川菜比较好吃。然后又有人说最近就是想吃辣的,最好肉多一点。于是很快就定下来,最后去吃了火锅。

这里第一个人提出的麦当劳就是那个不完美的产品。它的价值不是真的让人去吃麦当劳,而是给了所有人一个靶子。让别人以它为基础,提出自己的需求。

软件开发也一样。当面对的是一个不确定的市场时,越早提出麦当劳,就可以越早的打破僵局,发现用户的真实需求。不论是不完美的软件,还是麦当劳,它们的价值重点不在于用户使用,而在于程序们可以通过它们更早的发现真正的需求。

很多人可能都听过“最小可行性产品”,也就是MVP,这其实就是用产品当催化剂的最佳实践之一。开发一个新产品时,不要只相信创始人的个人经验,也相信用户调研,有了一个想法之后,要尽快的把一个功能最简单,开发时间最短,成本最低的产品做出来,从真实的用户那里获得反馈。

关于最小可行性产品的具体内容,可不是这里说的这么简单。什么样的产品算是最小可行性产品?如何获得真实反馈?又如何从反馈中发掘真实需求?这是有一整套方法论的。

我们回头再看”完成大于完美“这句话。为什么这句话是程序员务实的体现呢?因为它让程序员别把目标放在结果上,只想着结果要完美,更重要的是过程,也别光想着要做什么,更要知道,怎么才能做到。高手程序员不是放弃了完美,而是用更快的速度,更少的成本先完成,用真实的产品让用户去反馈。

通过前面的介绍,我想你应该也明白:完成,其实只是实现最终目标的第一步,快速完成最小可行性产品,用它获得了真实反馈,然后肯定还需要持续的变更和持续的改善。每一次完成其实都是实现最终目标的一小步。

那么问题来了,怎么才能做到持续变更持续改善?这就是程序员务实的另一面了。

在这本书里面,作者强调了一个编写代码的核心原则:ETC原则,也就是easier to change的缩写,让变更更容易。所有的编程技巧本质上都是在实现ETC原则。举个例子,对于程序员来说,普通台式电脑的硬件设计,就符合ETC原则: 如果内存不够,可以增加内存;如果CPU慢了,可以拆下机箱换一个。也就是说,你的需求发生变化后,通过很少的变更就可以满足自己的需求。(这个原则就像软件设计模式里的目标一样,程序员的天敌就是变化,这种变化也常常是我们加班的主要原因)。相反的,现在的手机就不符合ETC原则。别说是增加内存了,就是电池都不能随便更换。如果你需求变了,那只能重新买一个手机。

当然这里只是用硬件来举例子,硬件的更新周期比较短,那么容易变更也没有问题。但软件就不一样了。

前面讲了,程序员可不是做到完成大于完美就完了,更重要的是能持续改善。软件的持续改善,很可能是上午发布的内容,下午反馈就要进行改善。如果程序员写的代码不能应对这样的变更,每次都要把代码重写一遍,那成本可就大了。所以别看前面说了,每次都要做一个最小可行性产品,要赶快投放市场,获得真实反馈,这的确没错,但是只能说对了一半,还有另外一半也必须保证才可以,那就是这个最小可行性产品的实现,要符合ETC原则:容易变更。

当你听别人说他有一个好的想法,现在正在做小最小可行性产品,很快就要上线投入市场。你可别马上就认为很了不起,很务实。一定还要问他对于变更他还做了什么,如果他什么也没做,只是单纯的追求最小可行性产品,那么最后的成本反而会变高,甚至还不如最直接的做法:把所有功能都做出来再上线。

其实,ETC不仅是实现持续改善的一个原则,它本身就是一个实现持续改善的解决方案。如果给程序员最深恶痛绝的事情排个序的话,需求变更绝对可以排在前三。这其实可以理解,假如说你的老师给你布置作业,说今天晚上要把《出师表》背下来,第二天早上要检查。结果你晚上都快背完了,收到老师的短信:作业布置错了,明天不背《出师表》而是背《滕王阁序》,知道这个消息,你是不是也得崩溃?程序员也一样,每当产品经理提出需求后,他们恨不得让产品经理签字画押,承诺一定不能改需求了。可是需求不是产品经理说了算,真正决定需求的是用户,要想对用户负责,那就得允许需求变更。

在敏捷宣言提倡的价值观里面有一条:响应变化高于遵循计划。其实这也是普通程序员和高手程序员的重要区别。只有先具有了灵活的意识,才能有灵活的解决方案。当一个程序员认为一个需求就应该是板上钉钉的时候,错误的种子就已经被埋下了。一个高手程序员面对需求变更,想到的不是让产品经理签字画押,保证不变,而是利用ETC原则让变更更容易,为变更做好准备。

就比如说,假如你去学习编程了,那你一定会学到一个六字真言:高内聚低耦合,这句话的意思就是设计代码模块的时候,内部功能的聚合程度要尽可能的高,低耦合的意思是模块与模块之间的耦合程度, 要尽可能的低。可以把程序的模块化想象成是给快递打包,首先必须要把快递盒子给塞满了,然后还把盒子给封装好,多缠几卷胶带,不能让里面的东西露出来。快递露出来了,最多就是丢东西,代码如果露出来,影响的可是模块和模块之间的调用。 没有封装好的代码更新起来就会特别麻烦。代码模块有良好的设计,万一哪天需求变更了,就会出现两种情况,要么是代码模块本身可以不变,变得是模块相互之间的拼接,就像是乐高积木一样。要是某个模块性能跟不上,那只需要更新这个模块,不会影响到其他模块。

前面讲的这些方法,还都是程序员在编程技巧上做出的应对。为了应对变更,程序员高手的方法可不是只停留在技术层面上的。他们还会在组织团队,制定流程的层面上给出自己的解决方案。

比如站立会议,不要觉得会议只是把原来坐着开会变成了站着开会,其实这是用站着的方式倒逼缩短开会的时间,因为坐着开会比较舒服,不自觉的就会拖延开会时间,保证每一次站立会议不会超过15分钟,这样才能让站立会议成为每天的日常会议。每天十几分钟还是可以承受的,这样团队里的每个人每天都可以和其他人做一次同步,知道其他人做了什么,项目都发生了什么变化,自己是否需要做相应的调整。

除了站立会议,看板方法也是最常用的技术。它除了让编程这种看不见的工作量变得可见可衡量之外,他也是所有人同步进度的公告栏,有了看板,就不需要刻意通知了,团队里的每个人都能知道项目的进展情况。其实敏捷宣言就是程序员应对变更的指导方针。

通过前面程序员面对完美和变更的态度,我想你和我一样有这样一个感觉:高手程序员都是一群能给自己重新设计议题的人,他们本来是用编程方法实现用户需求的一群技术人员,但是他们并没有把自己限制在一个确定的框架内去解决问题,当他们发现无法获得确定需求时,不是要求用户或者产品经理必须把需求确定下来,而是跳出编程技术的框架,他们重新定义了产品价值,产品不再是简单地给用户提供功能,而是变成了探寻用户需求的工具。在更高层次上把问题解决掉,面对持续改善问题时也一样,程序没有停留在原有的议题里面想着怎么减少变更,而是跳出了原有的框架,想着如何可以适应变更。为了做到适应变更,不只是在编程技术这一个层面给自己找到了解决方案,在团队建设和流程制定上也有自己的解决方案,都总结出来相应的指导思想,所以如果让我说什么是程序员的务实,我会说不是此刻追求完美的精神,而是为了实现最终目标,总能跳出框架,为自己重新设计议题的能力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/811068.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode题练习与总结:不同路径Ⅱ--63

一、题目描述 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。 现在考虑网格中有障碍物。那么从…

自动化运维(二十四)Ansible 实战查找插件和策略插件

Ansible 支持多种类型的插件,这些插件可以帮助你扩展和定制 Ansible 的功能。每种插件类型都有其特定的用途和应用场景。今天我们一起学习查找插件和策略插件。 一、查找插件(Lookup Plugins) Ansible 查找插件允许用户从外部数据源或在 An…

我企业的业务需要制作企业网站吗?11个支持的理由以及5个反对的理由!

如果你的企业经营得还不错,你可能会找出很多理由,说明为什么一个高效的网站对你来说并不那么重要。确实,你明白企业需要在互联网上有一定的存在感,但你可能并不认为一个高效的网站会对你的特定业务产生太大的影响——尤其是当你已…

【Linux】Socket编程接口 | 实现简单的UDP网络程序

文章目录 一、预备知识理解源IP地址和目的IP地址理解源mac地址和目的mac地址认识端口号理解源端口号和目的端口号理解“端口号(PORT)”和“进程ID(PID)” 认识TCP和UDP协议TCP协议UDP协议 网络字节序为什么网络字节序采用的是大端…

循环单链表算法库

学习贺老师数据结构 数据结构之自建算法库——循环单链表_循环单链表 csdn-CSDN博客​​​​​​ 整理总结出的循环单链表算法库 v1.0 : 基本实现功能 v2.0(2024.4.6): 修复Delete_SpecificLocate_CyclicList()删除节点函数bug,添加验证删除节点是否超范围判断 目录 1.主要功能…

react17中配置webpack:使用@代表src目录

在vue的项目中可以使用表示src目录,使用该符号表示绝对路径,那么在react中想要使用怎么办呢? 在react中使用表示src目录是需要在webpack中配置的,在核心模块node_modules-》react-scripts-》config-》webpack.config.js中搜索找到…

【数据结构与算法】之8道顺序表与链表典型编程题心决!

个人主页:秋风起,再归来~ 数据结构与算法 个人格言:悟已往之不谏,知来者犹可追 克心守己,律己则安! 目录 1、顺序表 1.1 合并两个有序数组 1.2 原地移除数组中所有的元素va…

51-37 由浅入深理解 Stable Diffusion 3

2024年3月5日,Stability AI公开Stable Diffusion 3论文,Scaling Rectified Flow Transformers for High-Resolution Image Synthesis。公司像往常一样承诺后续将开源代码,开源之光!!! 在LDW潜在扩散模型论文…

​​​​网络编程学习探索系列之——广播原理剖析

hello !大家好呀! 欢迎大家来到我的网络编程系列之广播原理剖析,在这篇文章中, 你将会学习到如何在网络编程中利用广播来与局域网内加入某个特定广播组的主机! 希望这篇文章能对你有所帮助,大家要是觉得我写…

c#中怎么自动下载软件

以下是一个简单的 C# 示例,演示如何使用 WebClient 类下载软件: using System; using System.Net; class Program { static void Main(string[] args) { // 要下载的文件 URL string fileUrl "https://example.com/path/to/file"; // 本地保…

Leetcode算法训练日记 | day24

一、组合问题 1.题目 Leetcode:第 77 题 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1: 输入:n 4, k 2 输出: [[2,4],[3,4],[2,3],[1,2],[1,3],[1,4…

java中的Optional类和线程

Optional类&#xff1a; public static <T> Optional<T> of(T value) Returns an Optional describing the given non-null value. 通过非null值构建一个Optional容器&#xff0c;注意value不能为null&#xff0c;否则抛出异常 public static <T> Optional&…

福建单航次最大批量汽车“出海”

3月12日这一天&#xff0c;在福州海关的严密监管下&#xff0c;共有4000辆上汽名爵品牌的汽车被高效有序地装载到“安吉智慧”号滚装船上&#xff0c;这批车辆即将启程前往荷兰、埃及、英国等多个海外市场。在这批出口汽车中&#xff0c;新能源车型占据了显著的比例&#xff0c…

PostgreSQL高级sql积累

1&#xff1a;----查询postgresql数据中系统表与自己建立表结构做了个对比 select cl.relname,att.attname,att.atttypid,f.* from pg_class cl LEFT JOIN pg_attribute att on att.attrelid cl.oid LEFT JOIN td_f_field_info f on f.party_table_namecl.relname and f.fi…

[运维|GB28181] wvp-GB28181-pro+ZLMediaKit部署GB28181协议视频平台(windows)-个人笔记

相关软件下载地址 mysql下载地址 redis下载地址 vc运行库 linux安装说明 wvp-GB28181-proZLMediaKit部署GB28181协议视频平台全流程(ubuntu2204) wvp-GB28181-proZLMediaKit部署GB28181协议视频平台全流程(centos7) 若需要协助部署可私信我

OceanMind海睿思助力企业“数据入表”经济利益流入与生命周期管理

通过多年信息系统的建设与应用&#xff0c;企业积累了大量的数据。同时随着时间的推进&#xff0c;数据规模正以加速度快速增长。从国家到企业&#xff0c;都越来越关注所拥有的数据资源及其蕴含的深厚价值。很多企业已经逐渐认知到数据是重要的战略资源&#xff0c;数据资产化…

游标的定义和类型

Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 游标的基本概念 游标从字面上理解为游动的光标&#xff0c;可以使用 Excel 表格来想象游标的作用&#xff0c;游标指向每一行&#xff0c;通过游标访问每行数据。 在 Orac…

UVA10391 Compound Words 复合词 解题报告

UVA10391 Compound Words 复合词 解题报告 题目链接 https://vjudge.net/problem/UVA-10391 题目大意 给出一个词典&#xff0c;找出所有的复合词&#xff0c;即恰好有两个单词连接而成的单词。输入每行都是一个由小写字母组成的单词。输入已按照字典序从小到大排序&#xf…

2024/4/5—力扣—字符串相乘

代码实现&#xff1a; 方法一&#xff1a;常规解法——超出整数表示范围 long long char_to_num(char *str) {long long num 0;for (int i 0; i < strlen(str); i) {num num * 10 (str[i] - 0);}return num; }char* multiply(char *num1, char *num2) {long long a cha…

“Python爬虫实战:高效获取网上公开美图“

如何通过Python创建一个简单的网络爬虫&#xff0c;以爬取网上的公开图片。网络爬虫是一种自动化工具&#xff0c;能够浏览互联网、下载内容并进行处理。请注意&#xff0c;爬取内容时应遵守相关网站的使用条款&#xff0c;尊重版权和隐私权。 ### 网络爬虫简介 网络爬虫&…