两个程序员的寓言:2500行代码的程序,一定比500行的好吗?

编者按:2500行代码的程序一定比500行代码的程序好吗?写出简洁、高效、高可用的程序的开发者黯然离场,搞出庞大、复杂又难用的程序的人倒能加薪升职?究竟开发者的工作应该如何进行评价?来看看下面两个程序员的故事吧。本文译自RealMensch,作者 Neil W. Rickert,原标题为“The Parable of the Two Programmers”。

两个程序员的寓言

很久以前,有两家公司,分别是\”Automated Accounting Applications Association \”和 \”Consolidated Computerized Capital Corporatio\”,他们决定,需要一个程序来执行自己公司的某项业务,但这两家公司并不知道,对于他们的业务需求来说,要开发的程序是完全一样的。

Automated雇用了一位程序员分析师Alan来解决他们的问题。

与此同时,Consolidated决定让他们新招聘的一名初级程序员Charles来负责这项工作,看看他是否真的那么优秀。

Alan曾经有过操刀艰难的编程项目的经验,所以他决定使用PQR结构化设计方法。考虑到这一点,他要求部门经理再指派三名程序员作为编程团队。然后,这个团队就开始工作了,扑到了铺天盖地的初步报告和问题分析上。

再看Consolidated这边,Charles没忙着动手开干,他花了一些时间思考这个问题。Charles的同事们注意到,他经常坐在桌前,把脚抬起来放在桌子上,喝着咖啡。偶尔也会看到他在电脑前忙活,但同事们从他敲击键盘的节奏就能看出,他其实是在玩《太空侵略者》的游戏。

这时,Automated的团队已经开始写代码了。程序员们大约用了一半的项目时间来编写和编译代码,其余的时间都在开会,讨论各种模块之间的接口问题。

而Charles的同事注意到,他终于不再沉迷《太空侵略者》了。他现在要么就是把脚架在办公桌上喝咖啡,要么在小纸片上乱涂乱画。他写在小纸片上的字迹很潦草,当然看起来不是在玩Tic Tac Toe(一种游戏),但也没有什么意义。

两个月过去了,Automated公司的团队终于发布了项目实施时间表。再过两个月,他们将发布一个测试版的程序。然后再经过两个月的测试和优化,便会得到一个完整的最终版程序。

另一头,Charles的经理一直看着Charles上班摸鱼,已经厌烦了,他对Charles失去了耐心,决定和他摊牌。但当他走进Charles的办公室时,却惊讶地看到他在电脑前忙着输入代码。他决定等等看会发生什么,所以打了个哈哈,然后离开了。他开始密切关注Charles,以便抓住机会当面好好教训他一番。但是预期中那令人不快的对话并没有出现,因为他很高兴地注意到,Charles似乎大部分时间都在忙碌,甚至有人看到Charles忙得连午餐都很晚去吃,而且一周有那么两三天,下班后他还会留下来加班。

三个月结束时,Charles宣布他已经完成了这个项目。他提交了一个包含500行代码的程序。程序似乎写得很清楚,经过测试,它可以满足项目既定的所有需求。事实上,它甚至还有一些额外的便利功能,可能会显著提高程序的可用性。该程序投入实际测试使用后,除了发现一个可以快速纠正的疏忽外,表现良好。

到这时,Automated的团队已经完成了项目所需的四个主要模块中的两个。这些模块目前正在进行测试,而其它模块已经完成。

又过了三周,Alan宣布,初级版比原计划提前一周完成。他提供了一份待纠正的缺陷列表。该程序开始进行实际测试使用。除了缺陷列表中列举的问题,用户还发现了一些其它的错误和缺陷。正如艾伦所解释的那样,这并不奇怪。毕竟这是一个初级版本嘛,有错误是意料之中的。

又经过大约两个多月的时间,程序的正式版本开发完毕。它由大约2500行代码组成。测试时,它似乎满足了大部分项目需求。但是它削减了一两个功能,而且对输入数据的格式非常挑剔。然而,公司还是决定上马该程序了。他们可以随时对数据录入人员进行培训,让他们严格按照要求的格式输入数据。此后该程序移交给了一些负责维护的程序员去补全缺失的功能。

后记:

起初,Charles的上司对他在这个项目上的表现还是比较满意的。但当他通读程序源代码的时候,他发现这个项目真的比他最初想象的要简单得多。现在看来,即使是对一个初学编程的人来说,这显然也不是什么难事。

Charles每天确实产出了大约5行代码,这或许是略高于业内平均水平。然而,基于程序是这么简单,他的表现也就并没有什么特别了,而且他的上司还记得他那两个月的“摸鱼劣迹”。

在下一次薪酬调整时,Charles得到了加薪,加薪幅度约为这一时期通货膨胀率的一半(很可怜吧),公司没有给他升职。大约一年后,他变得心灰意冷,离开了Consolidated。

在Automated公司,Alan因如期完成了项目而受到嘉奖。他的上级看了看他们编写的程序,他浏览了几分钟,恩,是遵守公司关于结构化编程的标准的。然后他很快就不再继续尝试往下看了,这程序看起来似乎很难理解。这时他意识到,这个项目确实比他原先设想的要复杂得多,他再次对Alan的成就表示祝贺。

Alan团队的每个程序员每天产出3行多的代码。这在业内大约是平均水平,但考虑到这个项目所要解决的问题的复杂性,可以说是很不错的产出啦。Alan因此获得了丰厚的加薪,并被提升为系统分析师,以表彰他的成就。

来自Tim Mensch的评论:

我曾经是一名年轻但是聪明的程序员,这个故事令我产生了强烈的共鸣。即使在我还是个职场新人的时候,我也能做到令很多资深开发人员都感到有挑战的事情。在我的第一份工作中(作为游戏开发者),我的经理说我在几天内创建的代码,感觉比一个更有经验的开发者经过几个月的推敲后完成的代码都要好(从物理意义上讲)。在我的第二份工作中,我对一个有十年以上经验的高级开发人员编写的工具程序进行了优化,使其只需几分之一秒就能完成一个任务,而不用花费几分钟。我的整个职业生涯充斥了这样一连串的奇闻轶事。

在我从事编程以来的多年开发和学习经历中,我意识到经验确实很重要。但是,底层技能也同样重要。实际上,就像上面讲到的两个程序员的寓言一样,底层技能可能比经验更重要,我认为这个事实已经被许多当代的开发者忽略了。

话虽如此,我也曾经踩过坑,跟上文提到的第二个开发者类似,创建了一个比实际所需要的复杂得多的系统。我知道一个复杂的解决方案,并且知道自己可以实现它,但这并不意味着它就是最好的解决方案,我需要时不时地提醒自己这个事实。

于是,我尝试做出妥协,甚至质疑我自己的解决方案,持续寻找能够改进和简化的方法。我曾遭到指责:因为我倾向于花费更多的时间去思考一个问题,而不是仅仅用显而易见的方法去解决它;我希望能找到更简洁的方法去解决问题。因为花了很多时间思考,看起来好像不务正业,但是充分地思考可以让我产出更好的结果—-代码量更少,更健壮、更可扩展而且更容易阅读。

这就是为什么我认为上面这个寓言如此重要的原因。开发经验固然重要,但在项目设计和实施上的技能都可以完胜经验,如果你同时具备经验和技能,就可以实现相当的奇迹。只要你持续质疑自己的想法并持续思考如何更好地完善它,而不要一味地认为自己的第一个设计构思就是足够完美的。

译者:张茉茉

错误代码解析500、501、502、503、504

⼀:500错误

1、500 Internal Server Error 内部服务错误:顾名思义500错误⼀般是服务器遇到意外情况,⽽⽆法完成请求。

2、500出错的可能性:

a、编程语⾔语法错误,web脚本错误

b、并发⾼时,因为系统资源限制,⽽不能打开过多的⽂件

3、⼀般解决思路:

a、查看nginx、php的错误⽇志⽂件,从⽽看出端倪

b、如果是too many open files,修改nginx的worker_rlimit_nofile参数,使⽤ulimit查看系统打开⽂件限制,修

改/etc/security/limits.conf,还是出现too many open files,那就要考虑做负载均衡,把流量分散到不同服务器上去了

c、如果是脚本的问题,则需要修复脚本错误,优化代码

⼆:502、504错误

1、502 Bad Gateway错误、504 Bad Gateway timeout ⽹关超时

2、502、504出现的可能性

web服务器故障、程序进程不够

3、⼀般解决思路

a、使⽤nginx代理,⽽后端服务器发⽣故障;或者php-cgi进程数不够⽤;php执⾏时间长,或者是php-cgi进程死掉;已经fastCGI使⽤情况等都会导致502、504错误。

b、502 是指请求的php-fpm已经执⾏,但是由于某种原因⽽没有执⾏完毕,最终导致php-fpm进程终⽌。⼀般来说,与php-fpm.conf的设置有关,也与php的执⾏程序性能有关,⽹站的访问量⼤,⽽php-cgi的进程数偏少。针对这种情况的502错误,只需增加 php-cgi的进程数。具体就是修改/usr/local/php/etc/ php-fpm.conf⽂件,将其中的max_children值适当增加。这个数据要依据你的服务器的配置进⾏设置。⼀般⼀个php-cgi进程占20M内存,你可以⾃⼰计算下,适量增多。

/usr/local/php/sbin/php-fpm reload 然后重启⼀下.

c、504 表⽰超时,也就是客户端所发出的请求没有到达⽹关,请求没有到可以执⾏的php-fpm。与nginx.conf的配置也有关系。

501  服务器不具备完成请求的功能。例如,服务器⽆法识别请求⽅法时可能会返回此代码。

503  服务器⽬前⽆法使⽤(由于超载或停机维护)。通常,这只是暂时状态。(服务不可⽤)

505  服务器不⽀持请求中所⽤的 HTTP 协议版本。(HTTP 版本不受⽀持)

附:新增全部状态码含义

状态码分类

整体范围 已定义范围 分类

100~199 100~101 信息提⽰

200~299 200~206 成功

300~399 300~305 重定向

400~499 400~415 客户端错误

500~599 500~505 服务器错误

100(continue):说明收到了请求的初始部分,请客户端继续。

客户端发送⼀个携带值为100 Countinue的Expect请求⾸部,意味着客户端在发送实体前等待100 Continue响应。这是⼀种优化,客户端在避免向服务器发送⼀个⼤实体时,才使⽤。

101(Switching Protocols):说明服务器正在根据客户端的指定,将协议切换成Update⾸部所列的协议。

200(OK):请求没问题,实体的主体部分包含了所请求的资源。

201(Created):⽤于创建服务器对象的请求的响应(例如PUT)。实体主体部分包含各种引⽤了已创建的资源的URL。

202(Accepted):请求已被接受,但服务器还未对其执⾏任何动作,⽆法保证服务器会完成这个请求。

203(Non-Authoritative Information):实体⾸部包含的信息不是来⾃于源端服务器,⽽是来⾃资源的⼀份副本。

204(No Content):响应报⽂有状态⾏和⾸部,但没有实体的主体部分。

205(Reset Content):告知浏览器清除当前页⾯中的所有HTML表单元素。

206(Partial Content):成功执⾏了⼀个部分或Range(范围)请求。

重定向状态码要么告知客户端使⽤替代位置来访问他们所要访问的资源,要么提供⼀个替代的响应⽽不是资源的内容。

资源被移动的情况下,发送⼀个重定向状态码和⼀个可选的Location⾸部告知客户端资源已被移动,并且可以在哪⾥找到。

300(Multiple Choices):客户端请求⼀个实际指向多个资源的URL时会返回这个状态码。

301(Moved Permanently):请求的URL已经被移除,响应中Location⾸部包含资源现所处的URL。

302(Found):与301类似,但是客户端应该⽤Location⾸部的URL来临时定位资源,将来的请求仍⽤⽼的URL。

303(See Other):告知客户端应该⽤另⼀个URL来获取资源,新URL位于Location⾸部,允许POST请求的响应将客户端定向到某个资源上去。

304(Not Modified):客户端可以通过所包含的请求⾸部,使其变成有条件的。

305(Use Proxy):说明必须通过⼀个代理来访问资源,代理位置由Location⾸部给出。

306(未使⽤)

307(Temporary Redirect):和302⼀样。

400(Bad Request):⽤于告知客户端它发送了⼀个错误的请求。

401(Unauthorized):与适当的⾸部⼀起返回,在这些⾸部中请求客户端在获取对资源的访问权之前,对⾃⼰进⾏认证。

402(Payment Required):保留状态码,未来之⽤。

403(Forbidden):说明请求被访问权拒绝。拒绝原因可能在实体的主体部分。

404(Not Found):服务器⽆法找到所请求的URL。

405(Method Not Allowed):发起请求中带有所请求的URL不⽀持的⽅法。响应中有Allow⾸部,告知客户端对所请求的资源可以⽤哪些⽅法。

406(Not Acceptable):客户端可以通过参数说明它们接受什么类型的实体,服务器没有和客户端可接受的URL相匹配的资源时⽤此代码。

407(Proxy Authentication Required):和401相似,但⽤于要求对资源进⾏认证的代理服务器。

408(Request Timeout):如果完成请求所花时间太长,服务器可以返回此状态码。

409(Confict):说明请求可能在资源上引发的⼀些冲突。

410(Gone):与404类似,只是服务器之前有过此资源。

411(Length Required):服务器要求在请求报⽂中包含Content-Length⾸部。

412(Precondition Failed):客户端发起了条件请求,且其中⼀个条件失败了。

413(Request Entity Too Large):实体主体部分过⼤。

414(Request URI Too Long):URL⽐服务器能处理的长。

415(Unsupport Media Type):⽆法理解或⽆法⽀持客户端所发实体的内容类型。

416(Requested Range Not Satisfiable):请求报⽂请求的是指定资源的某个范围,⽽此范围⽆效或⽆法满⾜。

417(Expectation Failed):请求的Expect请求⾸部包含⼀个期望,但服务器⽆法满⾜此期望。

500(Internal Server Error):服务器遇到⼀个妨碍它为请求提供服务的错误。

501(Not Implemented):客户端发起的请求超出服务器的能⼒范围。

502(Bad Gateway):作为代理或⽹关使⽤的服务器从请求响应链的下⼀条链路上收到了⼀条伪响应。

503(Service Unavailable):说明服务器现在⽆法为请求提供服务,将来可以。

504(Gateway Timeout):与408相似。

505(HTTP Version Not Support):服务器收到的请求使⽤了它⽆法或不愿意⽀持的协议版本。

本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com

点赞 0
收藏 0

文章为作者独立观点不代本网立场,未经允许不得转载。