很多
毕业设计的时候,一大把平时成绩优秀的同学,写出来惨不忍睹的代码,这还是计算机专业的呢。
有。
你只要在在这一行做得足够久,见的同行足够多,就知道干这行的人都有很多不适合编程。
我曾经带过一个女生。很伶俐大方的一个小姑娘,211院校毕业生,怎么都傻不了。
当时分配给她的是类似这样的一个任务。首先上游函数会传来这么一个文本表格:
1 2 3 4 T
2 4 6 8 F
1 3 5 7 T
这个表格存于变量textTable中,需要调用lines = split(textTable, ' ')按行拆分,执行后print lines[0]结果为:
1 2 3 4 T
其它依此类推。
然后,对每一行,继续line = split(lines[0], ' '),按空格把这一行内容分开。
这时候print line[4],输出为
T
如上检查每一行,如果其中至少有一行的第五列是F,那么返回false;否则返回true。
当然了,正常程序员接到的任务应该只有一句话:分析这个表格,第五列出现F就返回false,否则返回true。具体解决方案的设计是接任务者的工作。
她是初学者,所以我先问:“你对编程语言有了解吗?”
答曰:“计算机二级考过。”
“既然过了计算机二级,看来我不用从头给你讲什么常量变量分支循环了?”
“不用,不用!”
“这个命令”,我在TCL交互环境敲了个split,“知道敲哪里吗?知道怎样存成程序文件吧?”
“知道,知道!”
于是便直接开始分析任务。先介绍split函数的功能,然后在命令行直接敲出来给她看效果;如此两步split分解,任务轻松完成。
讲完,我就问:“能看懂吗?把这些步骤写进一个循环,问题就解决了……”
“懂了!懂了!”
评论区很多人对“通过二级不用讲基础知识”有疑问,我把那段对话修改了一下,避免了其中的歧义(时间太长,具体措辞肯定有出入;但按我的习惯,和一个陌生人对话,开场白应该是这样:先确认前置条件是否满足,然后在可以达成共识的最高断面的基础上开始讲解)。
另外说明一下:她们过来之前已经系统学习过TCL这门语言;给我们任务时也明确讲过,不需要教他们语法,因为他们全都学过、而且高分通过了考核——我们的工作很忙,基本语法培训是不可能让我们一对一做的。那是对资源的严重浪费。
我们要做的,就是带这些在公司前置培训中成绩优异、有一定可能真正学会编程的“尖子”们做一个实际项目中的简单功能,解决他们“学过了编程但不能编程”的老大难问题。
问她有没学过编程、是否知道我给她的演示代码应该敲哪里、如何运行,这种问话是一种常用话术:故意询问一些对方肯定能答对的问题,可以消除对方的紧张情绪,帮对方建立自信,为进一步的交流制造一个良好的开端。
反之,一上来直接丢个难题,很容易让人觉得你在为难他,甚至造成一种对抗氛围。
之前,我以为把这句对话写出来,就可以同时起到“讲故事”和“交代背景”两个作用;但看来太多人误解了,以为他们真的是一片空白过来、而我们则要从基础课教起……
不好意思,真没这个可能——你觉得公司会舍得雇一个在05年拿8K月薪的senior engineer,一对一教你基本语法?
现在培训班月薪4K的老师都不干这活。
说不好听的,讲这种有心学习者自己看一天就能掌握的东西,一班没十几个三五十个人,那就是在浪费老师的生命。
做慈善都不能是这种做法。
我们谋的,是利用程序员特有的Debug思路,帮这些“尖子生”找出他们的思维误区何在、然后纠正这些误区、从而把他们变成能给公司做贡献的人才——甚至,这都是我对自己要求过高,才会真的想帮她解决“不会编程”问题。
真正的、普遍的情况,只是让他们体验体验“真正的程序开发是怎么回事”、用火辣辣的现实把他们中的某些人从死记硬背的泥潭里拉回来,也算达到目的了。
我当初进这个公司,第一个任务就是完成一个完整的实际项目,而且还马上要用,比写这么个函数可难太多了。而且当时我那个导师还丢来个错误的示范框架、讲解的完全是另外一个系统的设计思路,和我实际面对的问题牛头不对马嘴。最终还是我自己通过询问别人、查阅资料,纠正了他的思路,这才把项目做出来、然后又花了不少口舌说服他。
后来在另一家公司,也是用一个完整的“读取ini文件”小项目锻炼新人。
这种“用实际工作中出现的一个简单函数带新人”是很罕见的事,而且带出来也只能做自动化测试之类简单工作——毕竟他们只被证明“有写一个完整函数的能力”离真正的开发差十万八千里。
写一个函数需要人带,和写出一个完整的小项目需要人带,那是完全不同的两码事。别想的太甜了。
换句话说,画龙点睛,龙早有人画好了;我们的任务就是用实际工作逼逼他们,看能不能一笔把他们点活了——这样用,才不至于浪费一线工程师的精力,不浪费公司付给工程师的高薪。
好钢要用到刀刃上。没有人会那么天真,以为让一群拙嘴笨舌的工程师高级工程师砸时间教人基础语法、做他们压根就不擅长的“初级培训班/幼儿园老师”的活——还是一对一做——就能大力出奇迹。
真敢这么做,安排这个任务的人早被公司开了。
第二天,她来找我了:“怎么不行啊……”
一看,她是这么写的:
split(textTable, ' ')
split(lines, ' ')
这是对变量完全没概念啊。
我就给她解释,split的结果你得先存到lines变量里,lines变量就好像一个盒子,textTable是一大盒粉笔,你用split之后就把它变成一打一打小包装的若干小盒粉笔,这些粉笔先放在lines这个盒子里;然后,你要用一个循环,把lines这个盒子里的每一小盒粉笔取出来,找其中的第五支……
仍然是一边说,一边把每条语句都敲出来给她看效果。当然,仍然没直接演示循环该怎么写——她能自己摸索出来才说明是真懂了。
讲完,再问:“能听懂吗?”
“好像没问题……”
“那你回去试试,有不明白的问我。”
第三天,她又来了:“还是不行啊……”
这次她是这么写的:
lines=split(textTable, ' ')
line=split(lines[0],' ')
line=split(lines[0],' ')
line=split(lines[0],' ')
line=split(lines[0],' ')
line=split(lines[0],' ')
这是对数组完全没概念啊。
我继续给她演示:“lines是一个数组,你看,它里面的内容打印出来是这个样子……”
一边说,一边敲了个print lines,屏幕显示:
["1 2 3 4 T",
"2 4 6 8 F",
"1 3 5 7 T"]
然后敲print textTable,屏幕显示:
"1 2 3 4 T
2 4 6 8 F
1 3 5 7 T"
提示她:“看出不同来了吗?textTable是一个字符串,lines是一个字符串数组。所以当我们敲print lines[0]时,就把lines里面的第一个字符串提取出来,传给了print……”
如此这般,把每一个细节都敲出来给她展示清楚。末了,问她:“能听懂吗?”
“能听懂,讲很清楚……”
“那能不能自己写出来呢?”
面露难色:“我试试吧……”
如此这般,第四天,第五天,第六天,第七天……
两个星期过去了,她终于……彻底把我敲出来的示例背下来了。
现在她的程序长这样:
lines=split(textTable, ' ')
line=split(lines[0],' ')
if line[4]=='F' return false
line=split(lines[1],' ')
if line[4]=='F' return false
line=split(lines[2],' ')
if line[4]=='F' return false
当时那个用作示例的表格有十几行,她一行一行都写了出来。
嗯,期间还发生了别的很多事情。比如刚开始我只要求她把每一行都分解成列表显示出来,她搞不定,私下找了其他同事帮忙——那个return false什么的都是别人教的。
总之吧,她总算是把虽然僵硬但毕竟还能通过示例数据的东西弄出来了。
“你这样可不行啊。将来表格内容是会变的。有的只有两行,你这个到后面就得出现非法访问;有的又可能有几千行……所以这里必须改写成循环。喏,你看……”
我敲了个:
foreach line in lines {
print line
}
“明白了吗?你看,循环可以把lines里面的每个元素依次提取出来,然后你把print那里替换成分析line的代码,问题就解决了……”
“好难……”
教你更难——这句话我没敢说出口。
没办法,照旧在命令行敲出来演示(脚本语言就这点好);为了方便她理解,从二级考试的C风格for循环、while循环开始演示,一路演示到foreach。
“懂了吗?”
“好像……还是有点不太明白……”
“那我再给你演示下……”
“不用不用,我都记住了……就是……嗯,我回去试试。”
之后又是好些天。我教的foreach语法在当时还是个新鲜玩意儿,学校不教;学院派当时习惯用for——她显然找人问了,我教她的简易又安全的foreach她不用,拿来个for版本的:
for(,,)
lines=split(textTable, ' ')
line=split(lines[0],' ')
if line[4]=='F' return false
line=split(lines[1],' ')
if line[4]=='F' return false
line=split(lines[2],' ')
if line[4]=='F' return false
还是一行行手工处理,就是额外加了个死循环;末尾的return true仍然不知道加上。
而且,这种语言,for后面不加括号直接换行就是个空白循环;还有,for里面是分号,用逗号是语法错误……
“编程语言语法很重要,格式一点都不能错。这是语言官方手册,看过吗?”
“看过……”
“喏,你看,这是for循环的语法……”
过了一天,她拿来这个:
for(,,);
lines=split(textTable, ' ')
line=split(lines[0],' ')
if line[4]=='F' return false
line=split(lines[1],' ')
if line[4]=='F' return false
line=split(lines[2],' ')
if line[4]=='F' return false
for里面两个逗号打死不改,死循环打死不改;for语句后面可省略的分号加上了——昨天发现的一切问题照旧。
没办法,从头给她讲格式,讲循环变量,讲循环体。末了,照例问“懂了吗?”
“不懂……”
“嗯……觉得哪里不明白?”
她眼圈直接红了,眼泪差点流下来:“都不懂……”
都不懂……这下麻烦大了。我从语句讲起,讲什么是一条完整的语句,讲语句中哪些地方可替换,讲编程手册那些符号的意思(人家明明一开始就讲了的)。很显然,这对她是天书……
没办法:“要不我给你写个正确的,你回去看看书,把它改成while版本的?”
“好”
于是我给她写了个for版的:
lines=split(textTable, ' ')
for(index=0; index<lines.length; inc index) {
line=split(lines[index],' ')
if line[4]=='F' return false
}
return true
照例把每个元素敲命令行让她看了一遍,确保没有不理解的地方。
其实这里用foreach更好:
foreach line in split(textTable, ' ') {
if split(line,' ') [4]=='F' return false
}
return true
四行代码解决问题。
不过我们的目标又不是教她写这个函数。真给我们干就几分钟的事,耗这么久就是要她真正掌握编程。所以我教她用for,还要她自己想办法改成while循环。
一天后,她还回来这样一个while版的:
lines=split(textTable, ' ')
while(index=0; index<lines.length; inc index) {
line=split(lines[index],' ')
if line[4]=='F' return false
}
return true
时间久,我记不清了。她写的错漏之处更多。
这简直要把人逼疯了。
没办法,一点点讲解,for是什么原理,while是什么原理,为什么她那个while不合语法……
同期的其他学员大多通过了考核,就剩她了。现在成了好多人教她一个的局面。当然,主要负责人还是我。
总之,我教她思路,然后她私下找人问;别人不愿直接给她代码,怕耽误她的学习,就故意给思路不同甚至绕个大弯的其他方案。于是每天她拿来的代码总带着别人帮忙的痕迹,然后又被她乱七八糟的糅合进去……
我就给她讲这些代码都是什么思路,为什么不能胡乱拼凑过来,告诉她必须自己理解了才能做对。但她就是不能理解。
我很快发现她只是在死记硬背,其实压根不知道每行代码的含义。只要顺序稍微一打乱、或者书写格式稍有变化、或者把split之类语句稍微绕个弯写(比如写成delimiter=' ',split(line, delimiter)),她就答的差三落四。
我就告诉她,一定把split、for等等东西都拆分出来,一个个敲命令行看看效果;变量和数据类型之类基本概念必须搞懂。我还一遍遍给她讲程序控制流的概念,给她描述CPU怎么执行这些语句,演示每一行执行前后的变化……
但是连一点用都没有。她完全理解不了这些字母的意义。大概在她看来,程序代码就是些神秘的咒语。你讲再仔细,咒语也只是不可理解的咒语……
如此熬了一个多月,任务时限到了。
她拿着我给她写的那个for版程序试图蒙混过关,然而验收者明察秋毫:“去把for改写成for(index=lines.length-1; ...)”
就这样,她又原形毕露了。
眼圈红红的找过来:“不会写……他还让我解释每一句都是干什么的……”
“……哪句不明白?我给你解释……”
“哪句都不明白……”,她突然崩溃,带着哭腔。整个实验室的人都转过头来看我们。
没办法,我只好再次一行行敲进去给她演示,解释那是干什么用的。但她心不在焉,一点都没听进去。
看她可怜兮兮的,我只好给她找个台阶下:“回去把那份初学者指引多看看,把里面的例程都敲出来试试。这个有点难,一上来就做这个门槛有点高。”
“好”,仍然带着哭腔。
之后,我再也没见到过她。
对编程没有兴趣的人都不适合编程。
看到代码就兴奋的人才适合编程。
编程有相当的学习曲线,而且知识点繁多,技术更新迭代很快,需要不断持续的自学钻研,需要不断的google,翻阅各种文档资料。没有自发的兴趣根本坚持不下去。所以对编程无兴趣,只是希望有一份好工作被迫学编程的人很难学好编程。