IT职场人生系列之二十二:如何学习新语言(二)
(续上篇)
获取帮助
谦虚、大胆、再谦虚地尝试
这几个词看起来很不搭嘎,但我细细回忆起来10多年编程的经历,这句话很可能是高手与低手最后产生差别的关键,所以重点写一整篇。
菜鸟不是低手,低手指的是工作了很久,但技术能力上很落后的家伙。如果作为菜鸟,怎么才能避免成为低手呢?那就是谦虚、大胆、谦虚地尝试。
未必所有问题都能百度到,也未必身边一定有高人给予指点,那么遇到困难的时候,我怎么知道有还是没有方法解决、方法是什么呢?
1. 谦虚地认识自己面临的困难
这是第一个谦虚。
02年遇到一段程序,那个程序员水平不错,但他偏偏不懂C++中的“模板template”(就是Java和C#中的泛型),所以在处理13种不同数据的时候,不得不编写了13个函数,正赶上这个函数还在5种参数下运行,结果是编写了13×5=65个函数。不过最后被发现了,一个下午就缩减到一个函数,一个月的工作量被扔掉。
“作为一个即没见过又没听过模板的程序员,我怎么能预见到会有一种技术解决这些问题呢?”可能会觉得他很冤,对吧?
这就要解释“谦虚”的用意:当我们觉得这段代码很别扭的时候(比如65个函数长得差不多,编程困难,维护更困难),就要尝试处理它,如果他有这个心态,至少那个“5种情况”可以用一个循环解决掉的。那泛型呢?
如果用尽了招数,还是剩下13个new不同类型的问题,用自己所学所知都解决不掉,心里要这么想:“我还是一个菜鸟,我不是站在世界边缘,我遇到的问题,早就有人遇到过了,他们也早就解决了。”有了这个心态,就会去寻找答案,找人或找网络都无所谓了。事实上,他的项目经理就坐在离他隔一个人的位置上,这位项目经理是个设计模式专家,就别提泛型这点小事了。
多数人找不到答案,是没有去找答案,因为认为自己正面临世界难题,这个问题无法解决。
一年前开发的时候,我们面临很多难题,确切说我们真的“站在世界边缘”,因为还没进去呢,呵呵。下面是一些大大小小的我们猜测有答案,而最终果然也有的“难题”。拥有多年经验的开发者可能对这些问题不以为然,但是对于真正两眼一抹黑一行C#/Web/...代码没写过的新手,相信这些问题存在答案是很困难的:
a. 我们猜测,一个Ajax调用完成后可以调用两个以上的JS函数作为OnSuccess参数
b. 我们猜测,一个页面的菜单部分,可以延时1秒后再加载,以便整个页面显示的更快
c. 我们猜测,一定可以截获数据库的“写”操作,以便在写操作发生时同步更新我们的应用缓存,而不是完全销毁并重建整个缓存
d. 我们猜测,Html的backgound-image应该可以设置偏移量,以便让底图出现在合适的位置
e. 我们猜测,一定可以写一个类封装MVC中的Repository(Nerddinner中没有封装),以便完成任何表的简单增删改查
f. 我们猜测,一定可以把不同的类保存在一张表里边(Nerddinner里边从没提过),拿出来的时候自动生成不同的类型
g. 我们猜测,一个js script可以用Html的Helper生成,而不止限于div/img这些常见的东西
h. 我们猜测,一个类可以在另外一个类的某个函数上方生成(也就是类包含着类,C++里边是不允许的),因为我们太需要他们两个定义在一起以便对照了
……(说不上来一年里边做了多少猜测了,呵呵)
这些问题,有些有现成的答案,比如f是用Discrimitor字段,c是有个ChangeSet,只要定位了问题,都是google到的答案。
但是并非所有问题都这么解决的,因为有些问题不太好描述,而且也很找到答案,我们还用了下面一些其他的手段。
2. 大胆地尝试
我们当时设置了一种class为tip的<p>,当其母体(class = "withtips")被鼠标悬停时会弹出,其左上角上有个小图标(tip是16×16的问号,还有其他种类),以便和warning/notice有所区别。
可是,由于这个问号图片是用backgound-image: url(...)做的(因而你代码里边无需提及这个图片,只需要加上class = "tip"),当我们写成
background-image: url('../Resouces/Images/Others/Tip16.png');
background-position:top left;
的时候,它总是紧紧地贴在p的左上角,没有留出空白,显得很难看。查了很多资料,都没有提怎么办。
当然,惹不起躲得起,有一种很简单的方法:不用backround了,在每个tip里边手工加一个图片,这样就可以用style来控制其margin了。这个,就属于笨方法,经常这样思考问题,水平就很难提高。
怎么办?那就是想象:“我是这种语言的设计者,如果让我来全权设计,我会写成这样……”
结果是:
background-image: url('../Resouces/Images/Others/Tip16.png');
background-position:top 8px left 5px;
没想到,成了。
d、g、h这三个问题,都是这么解决的。
确切说,在这一年里边很多问题都是这么解决的,不是个例。如果被七八种新技术围住,光靠google百度突围是不可能的。
后面会看到,大胆=谦虚,看上去很奇怪的表达式。
3. 谦虚地尝试
有些人刚学一种新语言,因为不懂,又加上自己很谦虚,所以单子就小,就不敢尝试,其实这里边反而有问题。
他们想:“我是想这么设计,因为这样设计最好;可实际设计这些语言的大师们也这么想的吗?他们真的做到了吗?”
怀疑大师们的能力?怀疑你的想法大师想不到?其实这实际上隐藏着一种不谦虚的想法。
所以,越大胆的尝试,越表明我们谦虚地认为前人早就思考和解决过这些问题了,我们只是试试具体写法是不是正确而已。
“如果尝试失败了怎么办?”
尝试失败,往往是因为我们的想象力与大师有差距造成的。一定要做最大胆、最优化的尝试,这反而会“蒙中”大师们当年的设计。
作为菜鸟,要大胆地想象:“大师们不会设计一种语言,让我只能重复拷贝代码65次,或者每次写tip都必须加上这张冗余的图片代码,或者……”,要谦虚地认为大师们早就实现了我们的梦想,天下已经没有难题了。
为什么很多人编写了很多年的代码,有些很有用的东西从来没用过呢(比如前面65个函数的例子)?原因就是,连想象力都距离大师们甚远,能力差得就更多了。
这也是为什么提倡编码要精益求精的原因(参考2月5日和2月20日的5篇文章),如果平时就喜欢写垃圾代码,是很难猜中大师的设计的,因为他不会做垃圾设计。
我有一个不等式是这么写的:
我们的技术能力 < 我们的想象力 < 大师们已经实现的 < 大师们的想象力
为什么肯定地说大师们已经实现的比我们的想象力还多?因为拿起一个语言,会发现里边有很多“没用的”或“暂时没用到过的”东西,这些东西就是两者之差。
所以,阻碍我们的第一个东西是我们的想象力,而不是某种语言或技术的自身限制,连自己的想象力都受到限制,就不可能学好这种语言。
总结一下本篇:大胆谦虚地与大师共振
01年我在一个非常有进取心的团队工作了接近两年(他们的产品后来占据国内市场60%份额),在那里我们有很多技术梦想,有些我们手工实现了一半,有些限于当年的技术条件无法实现,比如:
1. OODB,一个把数据库和C++对象映射起来的东西,就是现在的EF和LINQ
2. 限制C++模板的传入类型,就是现在C#泛型中的where关键字
3. MVC分离,当时还只是一个概念,尽管我们努力手工做了很多工作,而现在直接框架化了
……等等
由于存在梦想,想象力的边缘就会扩大,而看到LINQ、泛型、MVC这些全新内容的时候,不但不会觉得奇怪和难以理解,反而立刻就会共振起来。
因此,当想象力越来越大的时候,反而学习一种语言越来越容易,因为它多半正好实现了我们想做的事情。
如果长期这样思考问题,想象力就会接近大师们当前能实现结果,因此会达到共振状态,连实现的方法都和自己想象的差不多,学习一种新技术就没有什么太大的难度了。