照着别人的代码敲进去,和太平洋岛屿上那些见过二战时美军机场工作人员,就戴着耳机形的木头块叽哩哇啦、以为经过这种祈祷仪式就能把“神灵的大铁鸟”召唤下来的野蛮人没有两样。
编程和飞机领航员一样,都不是跳大神。
恰恰相反,你得先明白飞机是什么、领航员发出的每一条指令起什么作用、为什么要发这条指令、遇到另外的情况如何解决、如何把解决方案翻译成指令,然后才有资格去看别人的指令、猜测他的意图、比较你和他的思路的优劣。
而为了达到这个目的,严肃的、负责任的教材才会鼓励你从helloworld写起、然后逐渐学习交换两个数字之类更多更复杂的花样――这才叫临摹。
老老实实从自己独立编写helloworld开始,踏踏实实一步一步前进,出的错才是你有可能解决的――搞不明白helloworld,敢从抄冒泡排序这种东西开始,就和幼童识字不学楷书练狂草一样,纯属扯淡。这是稍微有点编程经验就知道的常识。
编程和口语不同,口语起码你理解它的字面意思,还有可能“书读百遍其义自见”。编程是规则语法生效机制完全不同的另外一整套系统,中文说出它的思路你都看不懂,跟着太平洋岛上跳大神的叽哩哇啦叫唤一天你居然真把大铁鸟喊下来了?你自己信不信?
没错,哪怕领航员这种人类语言的工作,不明白含义,跟着喊泥嚎金田田起补挫,也永远都是个跳大神的。计算机语言可又隔一层了。
受不了一群人胡扯八道了。
编程是脑力劳动,不是体力劳动。
这是程序:
拧你面前的圆盘子!右边!快!90°!
保持!保持!
圆盘子拧回来!180°!
脚!右脚!从现在的位置向左挪10厘米,踩!快!快!
圆盘子下面有个钥匙,逆时针拧。拧到拧不动。
右边,中间,看见那个向前的把手了吗?拉起来!
下车,跟着警察叔叔走。
嗯,你抄吧。我看抄一辈子你能不能学会开车。
这是思路:
圆盘子是方向盘。
旋转方向盘就可以让车辆向对应方向转弯。
有人过马路,要踩刹车避让。刹车是油门左边紧挨着那个。
如果撞到人了,停车,熄火,拉手刹,等警察带走。
明白了思路,再上车熟悉下每个控制接口的作用,然后沿着道路因地制宜体会体会如何使用。很容易就能学会开车,知道遇到各种场景如何应对。
但反过来,你看看程序。那只是一些直接的操作步骤而已。设计意图、设计思路、面对场景等等信息全都丢了。
思路和程序隔太多了。这还是日常语言,程序隔的更厉害。
隔的越厉害,被丢弃的信息就越多。
你抄这种不明所以的咒语能有用?抄吧。反正耽误你一辈子我又不疼不痒。
想有用,你必须先搞明白:
1、每样东西是干嘛的(各种基本语句的作用、使用方法等,从最简单的范例开始)
2、需要用到的东西都在哪找、如何和你的程序互动(输入输出库、数学库、图形库等等)
3、实现一个东西的基本思路是什么(最好看文字描述;但如果你已经有了比较好的基础,也可以看别人程序)
注意,注意:想看懂一个程序,比看懂一段文字要难得多得多!
因为程序只是“机械执行步骤”,重要的信息全都给丢了——因此“写程序必须写注释、注释必须真正解释设计意图,乱写是不行的”才会成为稍微有点追求的公司的基本规范,不然过些天经常作者自己都搞不懂了,何况别人?何况你们这些鸟都不会的初学者?
就好像前面那个指挥开车的咒语一样,除非你已经对汽车了如指掌,否则绝对看不懂那东西说的是什么;甚至,哪怕你已经是几十年经验百万里驾驶里程的老司机,不给你解释只让你看驾驶员的手脚,你也不会知道他遇到了什么、打算做什么。
想学会开车,你需要知道油门方向盘刹车的作用,需要理解交通规则。闭上眼睛,靠师傅在旁边报“左手上移10厘米,右手上移5厘米,双手握紧,向右旋转90度”(没错,程序满篇写的都是这个),那是学不会开车的。
把咒语翻译过来、用简单平易的汉语给你说清楚你都搞不懂,跑去抄一段咒语,抄多了就懂了?不觉得滑稽吗。
教育是一门科学,是必须贴合受教育者的实际、一步一步引他入门的。
学不会程序的原因可能有无数种;但归根结底,无非如下几类:
1、没见过车,压根不知道车上有什么(没学过计算机语言基础)
2、见过车,但不知道圆盘子等等都起什么作用(缺乏分支/循环等各种语句的基础训练)
3、知道车上的东西都是干嘛的,但不知道怎么用(简单的hello world会写,排序就瞎了)
4、套路会了,但实际上路两眼一抹黑(死记硬背了很多知识,但不会用)
请问,抄程序针对的是以上哪个缺陷?纯属胡闹。
写程序和画画不一样。画画的话,颜色、执笔、涂抹你都用不着像解数学题一样学很多理论,动作和结果联系紧密,所以直接跟着名画临摹是有用的。
但写程序你跟着“拧盘子踩刹车打电话等警察带走”这段不明所以的咒语能学到什么?
写程序说白了就是解数学题;但比解数学题更坑的是,它甚至没有办法直接表达“求和、平均、任取”之类基本概念——有的时候,调用random是“任取”;也有的时候,直接取输入数据地一个值、正中间的一个值或者倒数第N个值,或者取INT_MAX、0、-1,这些也都是“任取”。
直接抄证明/抄解题过程连数学题都学不会,何况比数学题绕了更多弯、表述方式更随心所欲千奇百怪的代码?
换句话说,因为从问题-方案到编码过程中的信息丢失,很多时候,这个过程是单向的,哪怕你找世界顶级专家来,他们也不可能完全解读每一段代码的意图——尤其是程序员脑抽时写的代码。
有一句著名的注释是这样写的:“当写这段代码时,只有我和上帝知道它要干什么。现在只有上帝知道了。”
上帝才能搞定的事,你推荐给初学者?
这样只能无端的无限抬高初学者的入门门槛,而且将使他们永远做不到“彻底搞懂一个程序”——因为信息丢了。
跟风者/破解者通常永远追不上开创者。很简单,他们知其然不知其所以然;因此经常把一些“不明觉厉”的东西奉为经典——实际上那些东西很可能只是最初搞他出来那个人脑抽、或者二道贩子脑抽。典型如i+++++i。
而开创者呢?我不需要知道你为什么搞这么个玩意儿出来,但我可以用自己的方式从头设计、并且比你做的更好:现在,你那段只有上帝知道意图的代码,我压根用不着看。因为我自己写的比你的更好更清晰易懂。
一边满是窟窿而且绝无弥补的可能;一边毫无死角遇到问题马上可以对症下药彻底解决,哪边更有前途?
事实上,所有宣传“抄程序有用”的人,他们都没有意识到他们自己已经承认了抄程序屁用没有。
因为他们的逻辑是,先“抄程序”,后通过修改观察程序变成什么了、然后慢慢揣摩出写程序的诀窍来。
书上已经清清楚楚的解释了每个关键字所有方面的细节;还设计一大堆例程,帮你彻底读懂每条语句的作用、细节,甚至逼你思考它们对计算机隐藏状态的深刻改变都是什么,这些现成的好东西你不要,反而随便到哪找一段咒语,想尽办法揣摩它的用意——然后自己总结出别人的设计思路、再通过来回篡改所表露出的蛛丝马迹,慢慢把“X语言程序设计基础”这本书琢磨出来?
知道什么是事倍功半吗?
老老实实从hello world开始,逐渐学会if、学会for/while循环,学会各种算法的设计思路;然后你自己就明白“排课算法该怎么写”。
反之,到网上找个“排课算法源程序”,自己敲进去——浪费时间。
敲完了,还得自己意识到“我都干了些什么啊?一点用没有”——继续浪费时间。
甚至有人抄一堆代码仍然悟不出这点,只好承认“我不是学编程的料”然后永远放弃——误人子弟。
没被彻底引上歧路的,终于开始通过胡乱修改、揣摩出每个语句成分的作用——书上早写的清清楚楚、还设计很多练习帮你掌握了;你自己揣摩出的敢保证对吗?浪费时间+事倍功半+极易误入歧途。
谭浩强被人诟病,就是因为他就是这样揣摩出来每个语句的作用,然后写到书上。
所以,他才会把“未定义行为”当宝:因为通过胡乱修改、观察编译器反应所摸出的规律太诡异了,好不容易才总结出来。这玩意儿当然只能是难点、重点。
其实都是c标准文档一句话说清楚的事。他给搞的那么复杂,还特么搞错了!
这就好像通过现象学车,拧钥匙打火学会了;又发现上坡跑不动了拧打火钥匙也能辅助爬坡,于是写进教科书!
这种学法是不行的。太容易泥沙俱下了。
而且,换了一键启动的车,换了自动启停,换了电子手刹,你都得从头更新知识。
中国教育落后,老师自己都不会。很多人就这样不知不觉走了弯路、“倒着”学会了编程序——然后他们就以为倒着来才是正统。
错了。
倒着学门槛太高(从一堆鬼画符揣摩出程序作者以及语言设计者的意图,这门槛能不高!)
倒着学容易学偏(从现象学偏,因此喜欢拿i=i++ + i++当宝,这都应该算是学废了,不改没法用)
倒着学极易沾染不良习惯(先找“模子”后改来改去凑需求,这代码质量能高?彻底学通什么叫设计,从设计开始一步到位多好)
倒着学夹生饭太多、而且容易把不明觉厉的东西奉为经典,从而彻底断绝自己更进一步的可能。
打个比方的话,书上清清楚楚通过图画、语言描述给你解释发动机四个冲程都是什么,结果你扔一边不看;自己找个发动机,拆开,啊,这个齿轮大点,这个齿轮小点,改了……卡住了……挪走……啊,这个转一圈那个转一圈半,明白了……哎呀我太伟大了,只要把这一千个零件都拆下来,就能看懂发动机如何工作的了……
你觉得这样效率高?你觉得这样学能识别出什么是“脑抽设计”并改良它?
效率低都还不是致命问题。致命问题是,他们是通过“抄程序就是好”这个恰好搞反了方向的宣传,希望别人自行琢磨出“抄程序没用,你必须自己改一改、揣摩它的作用”这个“深刻”哲理。
这不是害人吗?
你自己已经走了弯路,还要信誓旦旦骗人往反方向走?