澳门新葡亰信誉平台游戏编程到底难在哪里?

by admin on 2020年3月20日

编程到底难在哪里?知乎上有人提出了这个问题,提问者似乎将这个问题上升到了哲学高度,他认为各种编程语言就好比文字,编程的过程就是用文笔书写文章,假设对于语言的应用已经十分熟练了,那么编程的难点到底在哪里呢?是使用语言的思路难,还是各种算法的运用难,亦或是明明是人脑却要用电脑的方式思考问题?

写在前面:我用自己不纯熟的英翻中把原文中程序员交流时经常使用的英文都换成了中文,翻译不好请谅解
-_-)

下面收集的语录涉及软件开发、代码维护、调试纠错、软件bug、系统设计、文档、代码质量、测试和软件开发团队管理等方面。虽然它们有些搞笑,但却真实无比。只有程序员才能理解这些编程语句里的真正内涵。程序员编程语录一个好的程序员是那种过单行线马路都要往两边看的人。程序有问题时不要担心。如果所有东西都没问题,你就失业了。程序员的麻烦在于,你无法弄清他在捣腾什么,当你最终弄明白时,也许已经晚了。我想大部分人都知道通常一个程序员会具有的美德。当然了,有三种:懒惰,暴躁,傲慢。编程时要保持这种心态:就好像将来要维护你这些代码的人是一位残暴的精神病患者,而且他知道你住在哪。一个人写的烂软件将会给另一个人带来一份全职工作。如果建筑工人像程序员写软件那样盖房子,那第一只飞来的啄木鸟就能毁掉人类文明。这世界最有可能毁灭的方式——大多数专家都同意——是次意外。这就是为什么会有我们,我们是计算机专家,我们创造意外。我们这个行业有个特别奇怪的现象:不仅我们不从失败里吸取教训,同时也不从成功中学习经验。一种新技术一旦开始流行,你要么坐上压路机,要么成为铺路石。如果没能一次成功,那就叫它1.0版吧。所有的程序员都是编剧,所有的计算机都是烂演员。工作进度上越早落后,你就会有越充足的时间赶上。当有这样的一种编程语言出现:它能让程序员用简单的英语编程,你将会发现,程序员都开始不会说英语。为什么我们没有时间把事情做对,却总有时间把事情做过头?傻瓜都能写出计算机能理解的程序。优秀的程序员写出的是人类能读懂的代码。任何你写的代码,超过6个月不去看它,当你再看时,都像是别人写的。编程/软件开发语录按代码行数来评估软件开发的进度,就如同按重量来评估飞机建造的进度。软件就像做爱。一次犯错,你需要用余下一生来维护支持。在水上行走和按需求文档开发软件都很容易——前提是它们都是冻结状态。最初90%的代码用去了最初90%的开发时间……余下10%的代码用去了另外90%的开发时间。注释代码很像清洁你的厕所——你不想干,但如果你做了,这绝对会给你和你的客人带来更愉悦的体验。如今的编程是一场程序员和上帝的竞赛,程序员要开发出更大更好、傻瓜都会用到软件。而上帝在努力创造出更大更傻的傻瓜。目前为止,上帝是赢的。软件设计最困难的部分……是阻挡新功能的引入。为了理解递归,我们首先要理解的是递归。世上只有两类编程语言:那些拥有被人诟病的和那些没人用的。布尔的最优秀之初,就是即使你错了,也仅仅是差了一位而已。如果Java能实现真的垃圾回收,那大部分的程序都会在执行时删除自己。理论上,理论和实践是没有差异的。但实践中,是有的。预备,开火,瞄准:这是最快的软件开发方法。预备,瞄准,瞄准,瞄准,瞄准:这是最慢的软件开发方法。编程是10%的科学,20%天份,和70%的让这天份符合科学。评估一个事情要比去理解你评估了什么容易。测评不会撒谎,但测评的人会。培养员工,即使他们有跳槽的风险。什么都不做而留他们在公司,这样风险更大。计算机科学的目标是做出一个东西,并且保证它至少能坚持到我们将它开发完成。Java之于JavaScript,如同Car之于Carpet。
起初就把事情做对是完全没必要的。但最后要把事情做对是绝对必要的。数组的起始索引应该从0开始还是从1开始?我的0.5的折中提议被他们未经认真考虑到拒绝了——我认为是这样的。程序必须是为了给人看而写,给机器去执行只是附带任务。
编程可以很有趣,你可以用它做密码学研究,但两者绝对不能合二为一。
“拷贝-粘贴”是一种设计错误。计算机善于遵循指令,但不善于理解你的思维。软件纠错语录删除的代码是没有bug的代码。如果纠错是消除软件bug的过程,那编程一定是把它们放进去的过程。代码纠错要比新编写代码困难一倍。因为,如果你写出了最聪明的代码,按此推算,你将没有更大的智慧来调试它。想在自己的代码里找出一个错误是十分困难的。而当你认为你的代码没有错误时,那就更难了。软件bug语录这不是个bug——这是一个未注明的功能特征。没有需求或设计,编程就是一种将bug添加到一个空文本文件里的艺术。烂代码并不烂,只是被误解了。有两种方法能写出没有错误的程序;但只有第三种好用。小心上面代码中的bug;我只知道这些代码是正确的,但没有试过。软件产品语录软件能够复用前,它必须要可用。软件通常在beta测试完成不久后发布。Beta在拉丁语中是“还不能用”的意思。最好的性能改进是将软件从不能用的状态变成可用。最廉价、最快速、最可信赖的组件是那些还未出现的组件。我觉得微软的
.Net,不会显示在 Unix
目录列表。软件和教堂非常相似——建成之后我们就在祈祷。除非最后一个用户死掉,软件是不会有完工的时候的。如今的大部分软件都非常像埃及金字塔,由成千上万的石块一个摞一个构成,没有结构上的集成,是由暴力强制和成千上万的奴隶完成。原文:theprofessionalspoint
/ 编译:外刊IT评论

澳门新葡亰信誉平台游戏 1

记得之前组里来了一个美国实习生小伙子,很极客的那种,干活快,一天能给你写2000行代码(我复查的速度跟不上他写的速度),让做什么东西,上午告诉做个这个功能,下午就能在测试环境跑起来演示了。跟他单独开会的时候,他说觉的普通的编程没什么意思,太简单了,写程序这方面已经没什么追求了,他比较想跟我研究大数据的框架,数据库,或者机器学习之类的工作,做设计,早日脱离代码这种无脑工作。

问题下边答主 Amazon 资深工程师阿莱克西斯的回答比较典型,获得了 10k+
的赞同,或许对你有所启发。

我足足花了1周时间,每天读他的代码到凌晨。给他写的评语反馈快赶上我在知乎写的答案文章之和了。。。期间几小时几小时的开会论战,孩子狂,语速快,脑力灵,辩论角度刁钻。他天天要与我论战,看我的评语,速度还算慢下来了。

阿莱克西斯介绍,他们组有一位美国实习生,这里暂且叫他 G,G 很
geek、干活快,一天可以写 2000 行代码,阿莱克西斯 code review
的速度跟不上他写的速度。G
认为普通的编程没什么意思,太过于简单,写程序这方面已经没什么追求了,他比较想研究大数据的框架、数据库,或者机器学习之类的工作,做设计,早日脱离代码这种无脑工作。

没来得及讨论完,隔周我要休假了,2周。交代了些他要做的工作。

有一次阿莱克西斯休假 2 周,交代了 G 一些工作,2 周后回来,发现让 G
改的那个 Java 包爆炸了,本来一个支持了 7 个功能的框架包,总代码量也就 5k
行,经过这两周 G 的发展,已经变成了 15k+ 行,也就是说 G
为了一个小功能在包里加了 1w 行代码。

2周回来,让他改的那个java包爆炸了,本来我们一个支持了7个功能的框架包,总代码量也就5k吧,等我回来这包代码量1w5+。也就是说他为了一个小功能加了1w行代码。

阿莱克西斯表示这代码没法 review,于是让 G 解释这些代码都是干什么的。G
的回复:

澳门新葡亰信誉平台游戏 2

(沉思+100)这块我现在也看不太懂当时为什么这么写了。。。

(沉思)这边写的比较复杂是因为当初那边是那样写的,所以这边没办法才只能这么写。

(沉思)把当初那边改好很麻烦,影响也很大,不如就这样吧。

澳门新葡亰信誉平台游戏,(沉思)这里这么写是因为你看着里是这样的,
然后这里有这个逻辑,然后这里。。。(来回来去翻n个类之后)。。。
所以你看我这里虽然写的比较诡异,但是完全没问题的!(得意ing)

(沉思)这边做的这么奇怪是因为有个bug,通过这么写,这个就bug没了,我也不知道怎么回事。。。所以你看我在这边注释,这行不能删了。。。

(沉思)我觉得这个功能很酷,你们虽然现在不需要,不过有总比没有好吧,将来如果……%¥……&%&……%*7&%……*%…(我没听懂)的话,这个就很有用!!

这没法复审,只能跟他坐一块,先让他给我讲讲这代码都干什么的,然后他说:

G
的解释充满了”忘记为什么那样写、照着原有代码写、怕麻烦将就着写、只关注功能有没有实现去写、天马行空过度优化“……没办法,阿莱克西斯一次一次让
G 重写,他表示这样编程也太难了,后来总算简化成大概 5k
行。再后来阿莱克西斯重写了一遍这个库,总共只有不到 1k 行代码。

“en。。。这块我现在也看不太懂当时为什么这么写了。。。”

通过 G
的事例,阿莱克西斯想表达,编程的难处不在于代码能不能写得快,而在于需要对以下几个方面做出有效的交待:

“en。。。这边写的比较复杂是因为当初那边是那样写的,所以这边没办法才只能这么写。”

  1. 做出来容易,做正确难。做出来指没 bug
    且完成需要的功能,这是最基本要求。正确不是指功能正确,而是指程序可以很容易推理理解,理解意图,理解它是如何做到的,理解为什么系统不会出错,理解为什么要这么做。

  2. 编程是给未来的人讲故事。你无法知道将来这个人是谁,他都懂什么,他经历过什么,这个系统将来已经是什么样子了。我们需要在这种无知,缺乏信息的情况下做决定,从千万种把这件事做出来的方法里,选出你觉得最能把这个故事给讲好的那种方式,把故事写下来。编程是一种沟通,沟通是一种艺术,用程序跨越时空之沟通则是一门属于程序员的特有的艺术(就好比数学家用数学公式来沟通)。

  3. 坏的决定会导致坏的决定,甚至导致人们去扭曲一个好的决定去迎合坏的决定。垃圾会制造垃圾,一个放在系统里不经清理的额外复杂度,会导致更多额外复杂度的生成。

  4. 每个人甚至同一个人的不同时刻都有自己不同的制造额外复杂度的缺陷,回头看你昨天写的代码,可能会觉得都是垃圾。

“en。。。把当初那边改好很麻烦,影响也很大,不如就这样吧。”

你认为编程到底难在哪里呢?

“en。。。这里这么写是因为你看着里是这样的,
然后这里有这个逻辑,然后这里。。。(来回来去翻n个类之后)。。。
所以你看我这里虽然写的比较诡异,但是完全没问题的!(得意ing)”

(文/开源中国)    

“en。。。这边做的这么奇怪是因为有个bug,通过这么写,这个就bug没了,我也不知道怎么回事。。。所以你看我在这边注释,这行不能删了。。。”

“en。。。我觉得这个功能很酷,你们虽然现在不需要,不过有总比没有好吧,将来如果……%¥……&%&……%*7&%……*%…(我没听懂)的话,这个就很有用!!”

一次次被我打回去重写,后来总算简化成大概5k行了;临走时候跟我说:你这样编程也太难了。。。

再后来由于一些额外复杂的代码造成我们实现新东西会很复杂,我又重写了一遍,总共大概不到1k行代码。

澳门新葡亰信誉平台游戏 3

这里边有几件事情我想说

做出来容易,
做正确难
,这里做出来指没bug且完成需要的功能,这是最基本要求,不多加讨论。这里正确,不是指功能正确,而是指程序可以很容易推理理解,理解意图,
理解如何做到的,理解为什么系统不会出错。理解为什么要这么做。正确是现在怎么写不会挖坑害将来的人,现在怎么写能让别人1年后看你代码时候不可能理解错你现在的意图,现在怎么写能在别人将来犯错的时候提示他你错了。

编程是给未来的未知人讲故事,你无法知道将来这个人是谁,他都懂什么,他经历过什么,这个系统将来已经是什么样子了。我们需要在这种无知,缺乏信息的情况下做决定,从千万种把这件事做出来的方法里,选出你觉得最能把这个故事给讲好的那种方式,把故事写下来。编程是一种沟通,沟通是一种艺术,用程序跨越时空之沟通则是一门属于程序员的特有的艺术(就好比数学家用数学公式来沟通)
coding is all about the art of communication(引用)。

坏的决定会导致坏的决定,甚至导致人们去扭曲一个好的决定去迎合坏的决定。垃圾会制造垃圾,一个放在系统里不经清理的额外复杂度,会导致更多的额外复杂度的生成。

每个人甚至同一个人的不同时刻都有自己的不同的制造额外复杂度的缺陷,比如我每年去看去年自己写的代码,觉得都是垃圾。

然后我又想问几个问题

我们所在的部门,所在的组,公司,它们的文化,到底是关心做出了一个东西,还是关心做好了一个东西。一个总是给系统添加垃圾,留坑给后人,但是能很快做出能跑起来的系统的程序猿,我们到底认为他是做了好事还是做了坏事?我们到底认为他很强,还是他很弱?用超过必要而为了突显技术实力的复杂工具,技术框架搭建系统,做完跑路,在一个组,一个部门,一个公司,那里的文化,到底应该是鼓励还是抑制这种行为?我们又应该如何在一个环境中,去倡导推崇什么样的文化,相遇什么样的人?

人与文化,决定了什么人留在这里,什么人离开,什么人吸引什么人,什么人成长成什么样子。而设计/技术这些枝末细节则必顺应此中的人与文化而自然变化,或自愈,或走向毁灭;哪怕在恶劣的环境中,向下引导,向上规谏,潜移默化,最终改天换日,此为编程之大道也!

下边是定理证明

最小垃圾存在定律:定义垃圾为系统的总复杂度减去系统的本质复杂度;那么得到:如存在多种方法可以设计与实现一个系统或功能,存在且只存在一种实现会引入最少的垃圾;

垃圾与复杂度正比定律:根据定义可得,系统存在的垃圾越多,系统越复杂;

垃圾倍增定律:基于已有垃圾量a的现状来演化,进化此系统,增加的新垃圾量与已有垃圾量a成正比;

系统腐败定律:当基于垃圾量a来实现新功能的cost大于新功能本身的价值时,系统腐败,需要重构;

战斗人员负战力定律:如果程序员a引入的垃圾,在n次迭代中经过倍增所造成的成本,大于其所清扫的垃圾经过倍增所获得的机会成本,和其实现的新功能价值之和。此时,我们称此程序员战力为负值,其战力绝对值与其引入垃圾的能力和其清扫垃圾的能力的差值成正比

以一敌百存在定律:由负战力定律可知,对所有的自然数n,一个正战力的战斗人员的战力
> (负战力战斗员1+负战力战斗员2+ … 负战力战斗员n)的战力和

系统本质复杂度不可知定律系统表征复杂度无限接近本质定律:取决于战斗人员的知识量,经验,天赋等,对于任何战斗人员n,都必定存在一个战斗人员m(考虑历史长河)使得战斗人员n观察系中的纯净无垃圾系统(复杂度总为1)是战斗人员m观察系中的含垃圾系统(复杂度为1+x),这使得在所有观察系中(包含外星生物),系统的表征复杂度(或者说观察复杂度)无限趋近与本质复杂度。然而我们只能通过观察来感知事物的本质复杂度,却永远无法得知我们离本质复杂度还有多远。

以有限的生命去追求可以无限的提升的净化方法与视野,我们称之程序艺术家,也就是SDA(Software
Development Artist)

… it’s extraordinarily important that we in computer science keep fun in
computing…

——— Alan J. Perlis (April 1, 1922-February 7, 1990) 《SICP》

打星际… 哦,不, 错了重来…  写程序,你快乐嘛?

澳门新葡亰信誉平台游戏 4

写在最后,看到大家最关心的是他拿到正式录取资格了么?还有也许通过我的描述关于他的这个侧面,你会觉得他很不称职。其实不是的,他代码写的绝对是平均值往上的水平,他的问题在于:

1、是他根本没有想过去简化业务逻辑,所以很多符合最初需求的代码在简单优化业务逻辑之后完全不需要;

2、是自己加了很多功能;

3、是自己加了很多自以为是的优化,比如用一个算法估算某个函数的输入数组的最大可能值,然后用那个值来初始化一个数组,因为这样就不会重新分配内存了(他原话)

4、抽象能力有限,这个毕竟经验少, 年轻;

5、滥用设计模式(关于设计模式,最多程序员被绊住的一关:设计模式是面向对象编程模型中,应对经典问题的经典解决方案。

这里有两个问题

第一,设计模式的场景用对了么

第二,为什么要用面向对象范式,选择编程语言范式时,要从表达力最弱最简单的语言范式开始选择。

这叫做最弱表达力原则,而面向对象范式作为最复杂,表达力最强的语言范式,在大多数时候都可以避免使用。关于第二点的论述证明,你可以看concept
techniques and models of computer
programming这本书。注意,这里说的是语言范式,而不是语言。即使你用java,如果你从来不使用mutable(专业词汇)的功能,和继承。那么你就没有使用面向对象范式)

他其实有非常强的解决问题的能力,想法天马行空,通过自己设计算法来猜函数可能需要的数组大小就可见一斑,还有一个从s3(专业词汇)读数据的需求,他不是简单调api完了,而是写了一个环状buffer(专业词汇),使得网络,硬盘,app可以在理论上最大效率的适应程序当时的场景(为了协调异步,他自己发明了一个很笨拙的promise(专业词汇))

这非常厉害,一般的实习生哪怕sde1可能都写不出来(可惜的是场景会随业务逻辑激烈变化,今天的优化可以是明日的累赘,这就叫做过度优化,过度优化是一种强耦合,会把你的系统死死的钉死在当前版本)。他只是不明白简单是美这件事情而已。如果能有人帮他斧正,日后必成大器。

他最终拿到了正式录取资格,这其中还有个小波折,终审的bar
raiser(amazon内部的一个可以一票否决招聘结果的角色)看到他在代码复查系统里跟我的各种激辩,觉得这人不能留。好说歹说才给了正式录取资格。不过最后人家没接,去读博啦。

最最后,在一个相对干净的环境写程序,不断找出新的本来以为不是垃圾的垃圾,对我来说,是一件非常愉快的事情。然而帮别人打扫他本就不该制造的垃圾则是非常痛苦的一件事。

写程序,本应是多么快乐的一件事啊!

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图