黑马程序员技术交流社区

标题: 我们如何才能更好地编程? [打印本页]

作者: 滔哥    时间: 2014-5-5 16:35
标题: 我们如何才能更好地编程?
本文作者 Chris Grainger 是开源 IDE Light Table 的开发者,之前在微软 Visual Studio 开发团队效力。本文是 Chris 根据他自己的演讲《Finding a way out》改写而成。

当开始设计 Light Table 的原型时,我并没有任何宏伟目标,只是一直在思考如何能更好地编程,还想看看做到这点有多难。直到最近,我才幡然醒悟:过去的十年努力:从Web框架,到Visual Studio,到 Light Table 的这段经历让我意识到:从一开始我就错了。事实上,我犯了一个典型的新手错误:想回答一个自己都不明白的问题。
如何更好地编程?

我只是不停地问自己:“我们怎样才能更好地编程?”但从来没有退一步,具体去想编程有什么地方不对。一直以来,通过对自己和他人的工作的观察,我得到了最完整的答案。以“Light Table”为例,如果缩短反馈循环会提升性能,虽然它的确可以,但却掩盖了一个事实:只是相同的老版本迭代。人们在痛苦的深渊中挣扎,我也是。“缩短反馈循环”并没有将我们从编写和调试代码的“深渊”中解救出来。所以,如果问题不只是反馈循环,那又是什么呢?编程的问题到底在哪?

要回答这个问题,我需要更多的数据,不仅仅从我的“后视镜”或自己的经验,而是从“现实世界”。于是我开始问大家两个问题:“什么是编程?它的问题到底在哪?”我问过从未编程的普通人,正在上班的白领,同行业中最好的工程师,等等。他们的答案让我吃惊不已。
什么是编程?

这个问题的答案真是令人沮丧。问了这么多人,居然没有一个人说“编程是用来解决问题的。”相反,大家更多的觉得它只是用半干的胶水把东西粘起来盛水,并祈祷在被新东西取代之前还可以继续盛水。我听别人说过无数遍,说我们只是水管工和胶水工厂。还有人说”编程主要解决自身不足“,这让我特别难过,因为它是众多答案中唯一接近正解的答案:我们把东西放到一起来解决某个问题,而“这个问题”是让程序员沮丧的源头之一。

编程本来是用来解决问题的,却变成了解决问题的问题(一个工程师朋友喜欢称之为“自舔冰淇淋”)。“胶水工厂”肯定不是我想要的答案,所以我一直在想一些可以行得通、说得过去的答案。到目前为止,我最喜欢的一个是:programming is our way of encoding thought such that the computer can help us with it. 编程是把我们思想转成代码,并让计算机可以帮助我们实现它的方式。当一天结束的时候,我们试图做的是构建一个新东西,并能够实现它——编程恰好是实现它的最好方式而已。


编程的问题在哪呢?

这个问题的答案也是我不想再问人(约400人)的原因。他们往往分为两类:他们要么随大流,并没有提供任何有用的信息,要么非常有个性的回答(当得到这些“死锁”时,我相当无语)。但总体而言,对于“编程的问题在哪?”这个问题的数百条答案,我提炼出了三类答案:不可察,非直达 和不简单。(unobservable, indirect, and incidentally complex)
编程是不可察

最近由于Bret和“Light Table”的开发工作,这点似乎是我们最为关注的。我们不能看到我们的程序是如何执行的。我们不能看到对程序的改变是如何影响项目。我们不能看到我们的程序是如何连接在一起。这基本上意味着我们观察不到任何东西。可观测性可以看做是一个一步一步查看状态的调试器,它强迫时间停止,并观察在某个时间瞬间的状态。但事实是,程序在某个时间瞬间基本上不会出错;大多数错误都是在一段时间内发生。就因为这一点,我们最好写一个print语句。但这十分荒谬。我们需要的是观察整个计划执行的过程,后进,后退,甚至未来——而不仅仅只是当我们的断点命中时。比这更可悲的是,我们似乎已经接受了不可观察性为一个既定的事实。例如下面这行代码:

person.walk();

它有什么作用?面向对象的封装的定义就是不可观察性。我不知道person.walk()有什么用。它可能做一些事情,像设置isWalking为true,但它也可以设置ateCarrots为true,它也可以决定我是否因疲惫而昏厥——我不知道,也没有办法知道。就好像,我们在一片漆黑中无所顾忌地扔飞镖并祈祷我们至少能射中靶心。不管你是刚刚起步或已经写了数以百万计的漂亮的代码行的程序员,根本无法看到我们的程序怎么运行,这是一个严重的问题。
编程是非直达的

写一个程序是一个容易出错的翻译工作。即使是数学——编程语言因其而生,都被翻译成这样了:

#include
#include
#include
#include
#include
#include
#include

template
double standard_dev( Iterator begin , Iterator end ) {
   double mean = std::accumulate( begin , end , 0 ) / std::distance( begin , end ) ;
   std::vector squares ;
   for( Iterator vdi = begin ; vdi != end ; vdi++ )
      squares.push_back( std::pow( *vdi - mean , 2 ) ) ;
   return std::sqrt( std::accumulate( squares.begin( ) , squares.end( ) , 0 ) / squares.size( ) ) ;
}

int main( ) {
   double demoset[] = { 2 , 4 , 4 , 4 , 5 , 5 , 7 , 9 } ;
   int demosize = sizeof demoset / sizeof *demoset ;
   std::cout << "The standard deviation of\n" ;
   std::copy( demoset , demoset + demosize , std::ostream_iterator( std::cout, " " ) ) ;
   std::cout << "\nis " << standard_dev( demoset , demoset + demosize ) << " !\n" ;
   return 0 ;
}

而我们为什么不能直接看到:
aa


这个例子,还算是翻译的比较清晰了。那要是代码不是这么清晰,又会发生什么呢?我们能得到就只有符号了。我们从来没有看到或与真实的东西交互,他们只是象征性的表示交互。而在某些情况下,符号固然重要和强大,它们不必是不透明:

cards[0][12];

是啊,打牌的时候,当我拿到卡[0] [12],我会很开心。我们正在编写一个纸牌游戏,纸牌有自己的名称(黑桃A),为什么我们不能直接存储这个呢?

A

翻译很难,而且使用的符号又容易出错,尤其是当与其他元件的上层操作耦合时。这种间接性,导致其不能代表有意义的东西,如果直接使用它们,又会让我们抓狂。大量编程的错误仅仅是翻译问题。虽然我们的脑子里有解决方案,但在试图把它翻译成代码的时候,我们要不是忘了什么东西就是犯些小错误。所以,我们必须摆脱翻译。当我们设计UI,我们应该做一个可视化编辑器。当我们研究数学,我们手边应该有类似的Mathematica的工具。我们应该用最自然的方式展示他们,而不是混淆不清的方式。
编程是复杂的

在编程中通常带有许多的复杂性事件,你得是要做一堆并不与你要解决的问题直接相关的工作。试着计算即使得到最简单的运行结果所需的时间,至少要花一个星期的时间来搭建一个开发环境。这些例子都是一个系统中不必要的复杂性,但事实是这种偶然的担心普遍存在的整个编写软件的全过程。最糟糕的是,我们现在是在逻辑层用代码做时间管理。大多数人可能会反驳,我们只要立即跳转到并发和并行就行了啊,但实际问题不是这么简单的。每当我们添加一个事件处理程序或创建一个回调,我们就是在做时间管理。

考虑到交互模式越来越复杂,我们程序面临多内核增加的变化(随之而来的并发问题),很快我们得知回调是解决该问题的糟糕方案。每次我们想要自己手动管理事物的时候,我们都可以想出一个实现自动管理的方案。我们曾经手动处理二进制,后来我们创建了Fortran语言。我们曾经手动管理内存,后来我们创建了垃圾收集器。我们曾经管理数据的限制,后来我们有了类型系统。我认为,下一步优化代码的复杂性的重大举措将来自于实现自动时间管理,这将对我们清晰地表达意图的能力有重大的影响。

试图列举编程中所有复杂性的例子将会令人感到无望,但现在是时候要解决这些问题了。我们应该专注于解决问题——而不是解决问题的问题。这样我们就可以在一天之内从一无所有到生成解决方案,而不是需要几周或几个月的时间。
追求局部最优(Chasing local maxima)

如果你回顾在过去50年主流技术上的进步,他们虽然很大程度上提高了我们的效率,却没有真正改变程序的行为。之所以我在文章的开始暗示:一切都是被动的,因为我们往往只在战术层面上的修正。事实上,几乎每一个我们取得的进步已经完美的解决了以上三类问题。我们让事情变得更好,我们不断接近局部最优,因为我们认为这些东西能以某种独立的方式解决。我听过最好的比喻是茶杯堆叠效应,每次我们修复某件事情,就是在茶杯堆上继续放茶杯,但最终我们只是在抽象多层次的工作,而该塔也开始倾斜并快要倒塌。我们必须停止单独思考这些问题,而是要想怎样才能同时解决他们。

有一天,我突然开窍了:编程其实是一切的对立的统一。晦涩的语言,神秘的错误,缺乏(或大多是零散的)文档——就像坐在某个真人秀的现场(幕后还会传来阵阵笑声)故意为难你。在一定程度上,这是自虐,但我们这样做,因为它给了我们提供了一个难得的机会塑造世界。通过认真思考编程的定义和它的问题所在,我们可以找到消除多余内容的框架的机会。但为了做到这一点,我们不能只考虑我们现在拥有的。另一个抽象层是不够的。相反,我们必须从根本的层面解决问题。不要更多的茶杯,不要更多的妥协。
编程之人

跟非程序员的聊天,他们会提供非常不同的看法。事实是,在我看来,他们大多也是程序员。他们只是不写“代码”而已。如果您使用Excel,你就是在编程——你要电脑根据你写的一个模块为你工作。 Excel是一个特别有趣的例子,这让它取得为人们能够解决问题的巨大成功。这也恰好满足我们的三个基本条件,并一些证据表明,它具有强大的解决问题的能力和“平易近人”的开发环境。

Excel是可观察的,因为它没有任何隐藏的状态,所有的值你的看到并操作。它也是直接的。你可以在表格中直接更改数值,拖放东西,选择性地计算等等。它设法回避了很多复杂性问题;电子表格是永久有效的,它没有安装程序,甚至没有的正在运行的概念。Excel通过权衡权限实现了这些。有很多事情是无法表达,因为放置在编程模型的约束条件非常好(或全部)。一个有趣的问题是,是否以类似的方式就可以解决我们的问题,但缓解了一些限制和保留更多的权力。

我们越多探讨过这个问题,就越会意识到,通过修复了这些问题我们在编程更加普遍的路上已经走了很远了。因此,如果这个有趣的问题的答案是肯定的,那大约有十亿人可以拥有现代超能力。试想一下,如果每个人都用电脑做到80%如今的程序员的工作。这样对什么的影响会最大?我不知道,但我认为它这将是我们人类作为一个集体的根本性转变,而且肯定是一件非常棒的事情。从长远来看,我相信操纵电脑将成为一项基本技能,但不像大多数的“编程是识字”(programming is literacy!)运动,我认为这将与能否写出’ if ‘语句无关。未来编程将会是大多数人都可以做到的事。任何以我们现在这样做事的方式,是注定要失败的。事实上“受虐狂”一点也不受欢迎。
文化差异

我的问题还没有解决的另外一个原因是:编程带来的社会问题,最近也得到了越来越多的关注。有许多方面对这个问题从编程已有的固有印象,到我们社区互动的方式,已经上升到了偏见和成见。我觉得编程最有趣的地方之一是它有可能引起的文化的重新定位。如果编程本身并不对立,那会变成什么样呢?如果只需要粗略地计划就能编程,又会是什么样?如果编程从一开始就是思路清晰的?这样的编程,与我们如今的编程没有一点共同之处。因为解决编程带来的文化问题才是真正地改变世界。
好,现在该怎么办?

我们找到一个解决问题的基础!没问题吧?在“Strange Loop”的演讲中,我展示了我们一直都在做的Aurora非常早期的原型。这里,我带来了新的进展。虽然我们的策略已经有了显著改变,其背后的概念仍然是相同——我们想要找更好的东西,不只是针对程序员或非程序员,而是完全消除这种区别。我们最近在这个方向做了些实实在在的进展,当稳定之后,我们将分享更多。但有一点我想说的是,大家一定要眼见为实。

原文链接: Chris Granger   翻译: 伯乐在线 - Stellar
译文链接: http://blog.jobbole.com/65896/
作者: luoyang316    时间: 2014-5-6 10:23
写的挺好的
作者: 攀攀    时间: 2014-5-6 13:32
学习  顶
作者: Maple_枫    时间: 2014-5-6 22:22
占楼求技术分进黑马踏入编程美好世界!噢耶!!!
作者: Union    时间: 2014-5-6 22:35
敲着敲着就成功了!
作者: houyudong    时间: 2014-5-7 09:14
看不懂了啊。。
作者: blz01003hm    时间: 2014-5-7 10:20
的确很好
作者: 种一棵树    时间: 2014-5-7 20:33
学习学习,走出不一样的风景
作者: 环球信息中心    时间: 2014-5-9 17:05
有启发。挺好的
作者: 环球信息中心    时间: 2014-5-9 17:06
houyudong 发表于 2014-5-7 09:14
看不懂了啊。。

思考着看,别急
作者: 余翔    时间: 2014-5-9 19:20
越来越头疼。
作者: ender    时间: 2014-5-11 18:55
学习学习 。。。
作者: 炎星辰    时间: 2014-5-12 16:57
没看懂                                       
作者: 西瓜    时间: 2014-5-14 10:27
学习了!顶 !
作者: 幸福专卖店    时间: 2014-5-14 14:43
写的很好的额啊
作者: 满面春风    时间: 2014-5-14 23:31
多思考,多敲代码,多总结,多练习,细心,耐心
作者: 情祭    时间: 2014-5-15 11:59
学习了!!!
作者: houyudong    时间: 2014-5-17 22:07
en ,bucuo 学习学习
作者: caijunsong    时间: 2014-5-17 23:16
说的很好  但是我现在的水平  好没到考虑到这些问题  说不定以后我也会有想到这个问题的一天
作者: 小黑驴    时间: 2014-5-18 00:11
楼主 辛苦了
作者: ˙▎._灬乖囧猫    时间: 2014-5-18 13:13
看完了,还筛选了一些自我感觉很不错的东西制作了word文档,以便以后还用的到,帮顶。。。加油
作者: Queen123    时间: 2014-5-25 21:52
感悟不错,值得见解
作者: 风的尾巴    时间: 2014-5-27 21:27
略深~学习下
作者: 王雪冬    时间: 2014-5-29 05:28
学校学习......
作者: 韩天雷    时间: 2014-5-31 00:12
一定要眼见为实
作者: yueyuanlin    时间: 2014-5-31 23:33
其实,真没看明白。    百度了一下:编程就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果的过程。为了使计算机能够理解人的意图,人类就必须要将需解决的问题的思路、方法、和手段通过计算机能够理解的形式告诉计算机,使得计算机能够根据人的指令一步一步去工作,完成某种特定的任务。这种人和计算机之间交流的过程就是编程。

  
作者: 詹绪长    时间: 2014-6-1 05:52
受教了。
作者: 森林之王    时间: 2014-6-2 21:13
编程是为了解决问题的,但是为编程本身就是一个很难的问题。
开发编程工具的公司,他们的目标是让编程不再是问题。
编程本来是用来解决问题的,可是工作中却总是出现软件自身的问题。
软件就是胶水,坏了再补补,不能满足使用了再修修,这就是软件当前的现状。

编程是非直达的,没有 数学公式那么直观


上面楼发表的文章,我看是一个做编程工具的人先讲一些现在编程的 不可察 非直达  编程难

他说编程应该达到像excel表格一们  不管是程序员还是非程序员 都能感觉很容易使用

作者: 这个夏天的芬芳    时间: 2014-6-3 01:51
很深刻的问题

作者: -_-#    时间: 2014-6-7 10:48
学习学习。。。。。。
作者: 杨胜男    时间: 2014-6-7 21:21
好深奥,
作者: koukou    时间: 2014-6-7 21:47
有启发!
作者: XCodeRush    时间: 2014-6-7 22:37
程序员的自我修养啊{:3_62:}
作者: 宋文辉    时间: 2014-6-8 19:54
滔哥 写的好啊~!
作者: 徐开伟    时间: 2014-6-8 21:48
不是很懂。。。。
作者: aigosun    时间: 2014-6-9 15:34
学习了!!!!!!!!!
作者: luyi1009    时间: 2014-6-9 21:00
曾经一个学长告诉我说,刚开始接触代码肯定不懂,但一定要多写多想多敲......写着写着你就发现你已经迈进了变成的大门
作者: 叶飞翔    时间: 2014-6-10 14:32
好像很深奥的,不太懂。
作者: 宋文辉    时间: 2014-6-10 22:40
你让我灌醉,你让我流泪 让我感动啊
作者: 黑马—张帅    时间: 2014-6-11 08:20
学而不思则罔,思而不学则殆
作者: XCodeRush    时间: 2014-6-11 09:01
不可察,非直达 和不简单
作者: 赵孝鹏    时间: 2014-6-11 19:53
虽然现在还看不太懂   收藏以备后用 ....
作者: 小小菜鸟101    时间: 2014-6-13 01:20
不一样的思维,不一样的代码世界
作者: 不可言    时间: 2014-6-13 12:54
第3个回复
作者: suiseo    时间: 2014-6-13 14:34
它有什么作用?面向对象的封装的定义就是不可观察性。我不知道person.walk()有什么用。它可能做一些事情,像设置isWalking为true,但它也可以设置ateCarrots为true,它也可以决定我是否因疲惫而昏厥——我不知道,也没有办法知道。就好像,我们在一片漆黑中无所顾忌地扔飞镖并祈祷我们至少能射中靶心。不管你是刚刚起步或已经写了数以百万计的漂亮的代码行的程序员,根本无法看到我们的程序怎么运行,这是一个严重的问题。
作者: Rodgers    时间: 2014-6-13 15:20
哎,要熬多少年才能达到作者的层次啊
作者: Shakuntala    时间: 2014-6-14 01:33
小白占座位学习中。对涛哥无比膜拜,愿将来也可步入这样的世界,身心合一
作者: 界界的说    时间: 2014-6-16 22:29
看看的存在--
作者: 沐子松/kf    时间: 2014-6-17 13:39
学习                




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2