从玩扑克到软件开发

我以前不是做软件开发的。在加入ThoughtWorks两年之前,我主要靠玩扑克为生。当然,如果你曾跟我打听过我前臂上的纹身,那你肯定已然听过我的故事了。要是还没有,等下次我们一起喝一杯时,我可以讲给你听。

我从未因为花这么长时间玩牌而感到过遗憾,从中我学到了一些放之四海而皆准的知识。开发软件的时间愈久,我就愈加确信这二者之间具有令人难以置信的相似性。

学习

我学习打扑克和学习软件开发的方式是一样的:尽可能多读书。我用两年的时间,读完了所能找到的每一本有关扑克的书。最后竟至39本之多。编程亦如是。此刻,我面前仍然摆着接下来要读的5本书;而在过去三年ThoughtWorks的工作中,我放火烧掉的书亦不在少数。

我认为,无论编程还是玩牌,阅读书籍、博客与杂志都是要想有所成就的必备条件;而若要以二者为谋生之业,仅靠读书却是远远不够的。也许你可以把书本上的一切知识都装入脑中,但知道在何时应用何种规则,这才是真正高手的标志。

诚然,开卷有益。但总要走过万里路,方能对应用特定技术的具体环境烂熟于心。书本不可能把所有情况都囊括一空,只有通过亲身体会得来的经验,才能让你在某些状况下为自己或是雇主做出快速而正确的决策,而这些决策可能价值几千乃至数百万美元。

经验之宝贵,世间无物可代。

艺术的巅峰

你可以设计出击败普通扑克玩家的计算机程序。遵守一些基本规则,自然就可获胜。但迄今为止,还没有任何程序可以击败最好的扑克玩家。因为扑克技能达到巅峰时,也就成了一门艺术。软件开发亦如是。要想成为一个还不错的开发者,只要遵循一系列最佳实践即可。如果按照经典参考指南一类的书籍行事,开发出还不错的应用程序应该不成问题,而且效果会胜过其他最常见的做法。有了这么多失败的项目作为前车之鉴,我相信,还不错的应用就足以令大多数管理层甘心掏腰包了。

当然,有些经理有更高的标准。在银行、创业公司、医疗系统等领域,标准则更为严苛。“还不错”自是远远不够。那些经理会很乐意为最佳选择买单,他们期待的是远超常人的技能。但问题在于,专家级程序员的技能与普通程序员不同。普通程序员知道做事的方式;专家知道做事的目的。普通程序员会僵化跟随模式书籍中的指示,就如遵守参考指南一般;专家则明白对模式的创新可能会带来指数级的性能改善。

他们看到的绝非同一个世界,所以普通程序员很难跟专家对面交流。做艺术评论家易,做优秀的艺术评论家难。

决策技能

在扑克和编程中有一条绝对真理:几乎没人能像他自我感觉的那么良好。有自知之明是不错的开始,但人们依然很难知道自己与专家之间的差距。程序员接触专家的机会并不多,也就无法公正评判自己的技能。在牌桌上,每个人都是为了锦标而来,可大多数人都会过高评价自己的牌技,这总是让我惊讶不已。

程序员之间亦是如此,而且大多数人可以获得的信息更少得可怜。一个从不参加任何大会的技术领导人,只能跟自己的团队成员一比高下。当然,他可能已经很优秀了,否则也不会成为技术领导。但如果与整个行业中最出类拔萃的人相比,他又处于什么位置?如果觉得在自己的圈子里已经一览众山小了,那碰到不同意见时,他又会作何反应?有些人会视之为学习的契机并为此感到兴奋,但绝大多数都会对不同意见嗤之以鼻。

团队协作

乍看上去,扑克是一种彼此对抗的游戏。但事实很少如是。即使在赌注最小的牌桌上,通常也至少会有几个人常打交道。他们不会达成条件一致对付牌桌上的其他人——他们也不必如此。大家都明白一条道理:你不是要去跟牌玩得好的人对着干,赢他们的钱,而是要从水平低的人身上赚钱。专业牌手甚至会像一个团队一样协同工作。有些人彼此利益相关,故而一人得利则众人均有收益。他们不仅互相了解,而且认识很多人。如果出现一局精彩牌局,楼层经理会跟他们打招呼;侍者会为他们的对手调制酒精度高的饮品;荷官会故意“犯错”以影响某人心情(很少有人在心情不好的时候能够打好牌)。每个人都在协同工作,确保大家都能挣到钱。

颇为有趣的是,程序员的情况也与之相似。很多人都坐在格子里,完全依赖自己解决问题。他们往往工作在代码个人独有制模式之下。我曾亲眼目睹,在这种程序员交付的应用中,集成问题一直都是大家的心病。而更为不幸的是,集成之痛还只是最小的问题。假设IT部门把业务需求锁定为500页的需求文档。如果公司决定改变业务方向,随之而来的系统变更需求将令人痛不欲生。数以百万计的金钱付诸东流,因为程序员开发的特性已不再具备业务价值,而IT部门还没有找到更好的方式来应对业务变化。

当然,情况并非总是如此。专家懂得协作。他们会跟其他专家协作,但也不排斥与经理、客户、业务部门、分析师、质保人员,以及所有可以为成功贡献力量的人协作。他们胸怀大局:只有协作,才能让每个人有所收获。

度量

雄心勃勃的牌手常常讨论他们赢了多少手牌,又输了多少手。他们讨论最多的还是本该赢但却输掉的那几手牌。有时人们会犯错误输钱,但他们一般都不会记得这几手是怎么输掉的。相反的是,如果有些牌局只是因为手气不好而输掉,他们就会记得那一局中的每一处细节,他们还会在故事中透露对手必然获胜的几率,来证明自己根本没有胜出的机会。真正的牌手知道他们输掉过多少手牌,以及失败的大概几率。他们懂得度量。而且专业牌手会专注于重要的度量标准。你赢了多少手,输了多少手,这无关紧要;重要的是你赢了多少钱,输了多少钱。而且,为你的狗屎运(译者注:bad beat,即开局时输家比赢家牌好,赢的几率更大,但关键时刻赢家却来了更好的牌。碰到狗屎运——take a bad beat——用来形容输家,来了狗屎运——lay a bad beat——用来形容赢家)苦恼实际上等于替你对手的牌运犯愁。既然你的收入来自于对手的错误,那你就是在抱怨为什么对手把钱给了你。

有度量标准是好事,不过专业人士懂得哪些标准重要,哪些只会分散注意力,哪些介于二者之间。

软件开发也有很多度量标准,而且有很多标准身上的光环已经远远超出了它们所应有的范围。例如,知道代码行数几乎不能带来任何价值。复杂应用需要相当多的代码,但这个“相当”到底是多少?它得依赖于语言、工具及其他因素。

修复的bug数量也是个很有趣的话题,只是略逊于前一个。为什么人们会在乎修复了多少个bug?Bug数量也许有其价值,但是修复的bug数目并不能为我们带来多少有用信息。

特性完成率是我自己最喜欢把玩的一个标准。除非我们使用特性来评估工作量,否则知道完成了多少特性又有何用?而且,如果已经对工作量做出了评估,那为什么不把剩余工作与已完成工作相比较,从而得到工作进度呢?我很难从特性完成率中看到价值所在。

代码覆盖率让我想起了记录狗屎运。这项度量是有意义的,但很多人都没抓住重点。代码覆盖率低意味着可能有问题存在,但是代码覆盖率高只能表示你有一个很大的代码覆盖率数值。高代码覆盖率与高质量之间没有必然联系。

注意人,而不是逻辑

如果看过有玩牌镜头出现的电影,你大概听过这样一句话:你不是在与扑克玩,而是与人玩。此言极是。牌手无疑都是心理学家。有时你确实需要某些牌,但拿一手好牌只是赚钱的一部分而已。一旦有了好牌,你就需要知道怎样利用好它们。你是应该加注,还是先让牌然后加注,还是彻底让牌,还是跟进?这些做法依赖于很多因素,但关键还是要了解牌桌上的对手。当你得到一手好牌,首要目标就是尽可能多地从对手那里赢钱,而达到这种目的的唯一方式则是想办法让对手给你更多的钱。了解逻辑可以帮助你赢得几手牌,了解人则可以帮助你赢钱。

在交付软件时,人处于同样重要的地位。如果软件只是让一切工作起来,那只要把它变成自动化的工作,事情就容易得多了。但软件却远非功能组合这么简单。在一场高尔夫球比赛中,人们会卖出软件包;在全家到迪斯尼免费旅游时,人们会签下软件服务合同;为了避免法律纠纷,人们会履行合同去构建已经毫无用处的软件;为了超越竞争对手,人们会使用软件来加快业务响应速度。

人们使用软件、开发软件、维护软件,或是在某种程度上依赖软件。软件开发与这个世界有着千丝万缕的联系,要把洋洋洒洒的变量组合成简单方程,生产出高质量的软件,又与登天何异?但是,软件开发高手需要考虑每个人引入的所有已知与未知的变量,做出他们力所能及的推测。知道应该做什么会让你受益,而知道必须做什么所带来的价值却是难以衡量。了解逻辑可以帮助你交付应用,了解人则可以帮助你交付价值。

在残缺的信息下工作

有关这点,刚开始打牌的人处理的非常好:打好每一手牌,老老实实押注,从不虚张声势。这便是了,新手就应该只做该做的事情,除非你的钱多得没地方花了。难点在于如何从初学者的水平提升。大量信息霎那间纷至沓来,你需要注意牌桌上每个人的每一处细节:他们怎样交流,你从前跟他们每个人打过什么交道,他们所钟爱的玩牌方式,谁在赢,谁在输,凡此种种不一而足。而且,你也不可能知道对手手里的牌是什么,下一张牌又是什么。你所拥有的信息已超出所能处理的极限,而且这远非全部。

编程亦如是。领域专家无所不知,但把一切都向你倾囊相授却毫无意义。何况,你也不一定需要所有的领域知识。你需要熟悉团队,但同事总有些事情是你永远无法知晓,或者不能完全理解的。不过,编程高手能够把必要的领域知识融会贯通,掌握团队的动态,并始终提供技术上的真知灼见。他们知道他们永远无法成为百晓生,他们知道什么事情值得思考,哪些应该置之不理。纵使面前汹涌澎湃的信息仍是残缺不全,他们也总能做出正确的决定。

即时反馈

普通牌手在反馈信息少的游戏中表现最好。因为牌手是根据信息而赢钱的。在5张牌梭哈中只有一轮押注的机会。各位玩家只有一次机会来分析你给出的信息,而你也只有一次机会犯错。专家级牌手更喜欢多轮的游戏。游戏中的回合数越多,他们就有越多机会从低水平的对手身上捞到好处。他们喜欢即时反馈,并根据反馈做出调整。在有多个回合的游戏中,每一个回合都可以得到反馈,专业玩家就会根据当前局势调整打法。

编程高手同样喜欢即时反馈。从业务人员即时反馈回来的信息,可以避免你在构建业务应用时走上弯路。从另一个程序员即时反馈回来的信息,可以在软件产品化之前发现bug。持续集成服务器可以提供即时的集成反馈,从而避免集成之痛。喜欢敏捷的人能马上说出迭代是一个有着显著成效的实践,因为它可以让程序员和业务人员得到即时反馈。不过,作为一个编程高手,纵使他不喜欢敏捷,他也能够意识到即时反馈的价值;即使在非敏捷的环境中,他也会争取得到更多的反馈,从而避免浪费时间精力。即时反馈可以让你了解前行的方向正确与否,每一个专家都会珍视这些信息。

上下文为王

无论扑克还是编程,没有绝对正确或是绝对错误的选择。如果你有一对K,那么在翻牌之前你该不跟么?也许吧。这要看你是在打比赛还是赌钱、有上限还是没上限、你坐在哪个位置上、你是否已经不跟过一次还是已经封顶了等等。我在扑克中学到了一点,那就是在给出答案之前,一定要综合考虑所有的因素。

在编程中沉浸的时间愈久,同样的体会在我心里就愈加深刻。Java在有些时候是不错的选择,但它并非万能。所有的编程语言均如此。工具亦如是。Hibernate很不错,但它不适用的地方还有IBatis,当IBatis也不适用的地方还会出现或自己创造新的解决方案。几乎没有一款解决方案能够绝对有效,它只有在恰当的形势下才会发挥应有的作用。在错误的环境中,它也许会成为毒药。

所以,面对一门新的语言或者工具,无论是你是打算弃若敝履,或是爱不释手推而广之,不妨先想想它的适用环境,尽量做到对症下药,量体裁衣。


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

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

相关文章

什么是IPsec协议

IPSec 协议不是一个单独的协议,它给出了应用于IP层上网络数据安全的一整套体系结构,包括网络认证协议 Authentication Header(AH)、封装安全载荷协议Encapsulating Security Payload(ESP)、密钥管理协议Int…

python 字符串、列表和元祖之间的切换

>>> s[http,://,www,baidu,.com] >>> url.join(s) >>> url http://wwwbaidu.com >>> 上面的代码片段是将列表转换成字符串>>> s(hello,world,!) >>> d .join(s) >>> d hello world ! >>> 以上代码片段…

你真的懂函数吗?

函数声明方式 匿名函数 function后面直接跟括号,中间没有函数名的就是匿名函数。 let fn function() {console.log(我是fn) } let fn2 fn console.log(fn.name) //fn console.log(fn2.name)//fn,fn和fn2指向的是同一个function。 复制代码具名函数 fun…

静态html的ajax如何发请求,静态页面ajax - 冥焱的个人空间 - OSCHINA - 中文开源技术交流社区...

1.静态页面$.ajax({type:"get",url:"http://localhost:8080/app/register/sendSMS",//请求地址必须带http协议data:{"phone":phone},async:false,//是否异步dataType: "jsonp",//固定格式jsonp: "callback",//固定格式jsonp…

Diango博客--12.开发 Django 博客文章阅读量统计功能

文章目录0.models中增加新字段1.models中增加方法2.迁移数据库3.修改视图函数4.在模板中显示阅读量0.models中增加新字段 为了记录文章的浏览量,需要在文章的数据库表中新增一个用于存储阅读量的字段。 文件位置:blog/models.py class Post(models.Mo…

c++ try_catch throw

使用throw抛出异常 本人节选自《21天学通C》一书 抛出异常(也称为抛弃异常)即检测是否产生异常,在C中,其采用throw语句来实现,如果检测到产生异常,则抛出异常。该语句的格式为: throw 表达式…

数字证书和数字签名

什么是数字证书?由于Internet网电子商务系统技术使在网上购物的顾客能够极其方便轻松地获得商家和企业的信息,但同时也增加了对某些敏感或有价值的数据被滥用的风险. 为了保证互联网上电子交易及支付的安全性,保密性等,防范交易及支付过程中的欺诈行为&a…

域名劫持

转载于:https://www.cnblogs.com/xinghen1216/p/8548323.html

cesium html源码,Cesium源码的本地运行及调试

CesiumJS源码运行有两种方式:基于node.js运行官方下载地址:https://cesium.com/cesiumjs/下载解压后,在根目录安装依赖后,就可直接运行npm initnpm start如果调试代码呢,官方的示例都是在Sandcastle里放着,…

Diango博客--13.将“视图函数”类转化为“类视图”

文章目录0.思路引导1.ListView2.将 index 视图函数改写为类视图3.将 category 视图函数改写为类视图4.将 archive 视图函数改写成类视图5.将 tag 视图函数改写成类视图6.DetailView7.将DetailView视图函数改写成类视图0.思路引导 1)在开发网站的过程中,…

es6之数据结构 set,WeakSet,mapWeakMap

{let list new Set();list.add(1);list.add(2);list.add(1);console.log(list); //Set(2) {1, 2} let arr[1,2,3,1,2] let list2new Set(arr); console.log(list2); //Set(3) {1, 2, 3} } Set ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的&a…

关于C语言中继承和多态的实现

以下的内容综合了多篇文章,加上一点自己的理解而成。目的为了给自己阅读他们文章后做一个笔记。在末尾给出了这些文章的地址。 多态的实现可以采用以下几种方式: (1)使用 vod * (万能指针)来实现“编译时多态”。 (2)使用函数指针来实现“运行时…

边界测试

边界条件边界测试是单元测试中最后的也可能是最重要的任务。 软件常常在它的边界上失效,例如,处理n元数组的第n个元素时,或做到i次循环中的第i次重复时,往往会发生错误。 使用刚好小于、刚好等于和刚好大于最大值或最小值的数据结…

阿里云上Kubernetes集群联邦

摘要: kubernetes集群让您能够方便的部署管理运维容器化的应用。但是实际情况中经常遇到的一些问题,就是单个集群通常无法跨单个云厂商的多个Region,更不用说支持跨跨域不同的云厂商。这样会给企业带来一些担忧,如何应对可用区级别…

缺氧游戏计算机,缺氧PC最低什么配置一览 你觉得高吗

缺氧PC最低什么配置一览,你觉得高吗。游戏对于电脑有不同程度的要求,缺氧这款游戏也有着自己的配置要求,看看下面的缺氧PC最低什么配置一览,你的硬件够得上吗。缺氧最低配置:首先公布的是官 方配置需求,目前…

Diango博客--14.使用 Django 项目中的 ORM 编写伪造测试数据脚本

文章目录0.思路引导1.脚本目录结构2.使用 Faker 快速生成测试数据3.批量生成测试数据4.执行脚本5.效果展示0.思路引导 1)为了防止博客首页展示的文章过多以及提升加载速度,可以对文章列表进行分页展示。 2)不过这需要比较多的文章才能达到分…

基于Sql Server 2008的分布式数据库的实践

配置Sql Server 2008(Win7) 1.打开SQL server2012,使用windows身份登录 2.登录后,右键选择“属性”。左侧选择“安全性”,选中右侧的“SQL Server 和 Windows 身份验证模式”以启用混合登录模式 3.选择“连接”&#x…

横向技术分析C#、C++和Java优劣

本文将从技术人员的角度横向分析C#、C和Java优劣,其实选择Java阵营还是.NET阵营,大家可以根据自己的实际需要来确定。 C#诞生之日起,关于C#与Java之间的论战便此起彼伏,至今不辍。抛却Microsoft与Sun之间的恩怨与口角,…

软件测试中的存根程序

存根程序用来代替被测试的模块所调用的模块,因此存根程序也称为“虚拟子程序”,它利用被它代替的模块的接口,只做尽可能少的数据操作。

计算机网络应用云计算,计算机网络云计算的类型

原标题:计算机网络云计算的类型随着现代计算机网络技术的不断发展,越来越多的与计算机网络有关的现代化技术得以出现,并且有着广泛的应用,其中云计算技术就是比较常见的一种,在实际应用中发挥着较高的价值。在信息时代…