编程高手的进阶之路

对于外界,Coding是被神化的,似乎需要极高的智商和热情才能从事这个行业。

IT界聪明的人很多,但极具天赋真正的能称之为天才的人不多,一般人们口中所谓的天才,只不过是比平常人更快的掌握技能、完成工作罢了;只要你找到了正确的方向,并辅以足够的时间,你一样能够踏上成功彼岸。

工作中解决问题的途径有很多,你能最快想到的方法一部分取决于你的天赋另一部分是靠经验。事实上,大部分人由于平时的工作繁重,不会去思考寻找最优的解决方案,写的代码能刚好满足需求就算完事了。这样无法得到提示你甚至会无形中加重自己的工作量,因为随着年龄的增长,属于你自己的时间会越来越少,你的精力会被生活瓜分。

如何才能得到最优秀的方案呢?

首先,我们得知道什么才是最优秀的解决方案,最优解决方案需要你能够走在需求的前面,将当前需求里有的、没有直接提出来的、现在暂时没有但将来可能有的等等,及编程潜规则等各个方方面面都综合考虑,给出最优方案。以一招胜万招。

你不再被需求牵着走,而是你牵着需求走。注重细节,注意那些当前需求里没有明文给出的细节:代码性能的差异、运行平台(浏览器)的差异、需求的隐性扩展、代码的向后兼容等等。

搜索引擎是最好的老师

打开搜索引擎,穷举所有的搜索结果。自己建立测试环境一一验证这些代码:去揣摩每段代码的意图,去比较每段代码之间的差异。这两条路可以让你快速完成原始积累,当你再面对大多数需求时能够说这些问题我以前做过,那你就水到渠成地晋阶了。

积累各种能够解决需求的方案,然后再验证每个方案,在这些方案中选择最好的一种。因此该阶段的进阶之路就是”行万里路,看万卷书”,积累各个需求的各个解决方案。

举个例子:删除一字符串中指定的字符。

1
2
3
4
5
var str="www.baidu.com/?page=1";
str=str.replace('?page=1',"");
alert(str);
str=str.substring(0,str.indexof("/"));
alert(str);

首先不要苛责代码的对错严谨,毕竟每个程序员都有这样的一个过程;其次,这两段代码在这个实例里没有什么大过错,可能会有瑕疵,但能够解决问题(删除指定的字符),这就是这个级别的特征。

另外举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// 计算系统当前是星期几
var str = "";
var week = new date().getday();
if (week == 0) {
str = "今天是星期日";
} else if (week == 1) {
str = "今天是星期一";
} else if (week == 2) {
str = "今天是星期二";
} else if (week == 3) {
str = "今天是星期三";
} else if (week == 4) {
str = "今天是星期四";
} else if (week == 5) {
str = "今天是星期五";
} else if (week == 6) {
str = "今天是星期六";
}
// 或者更好一些
var str1 = "今天是星期";
var week = new date().getday();
switch (week) {
case 0 :
str1 += "日";
break;
case 1 :
str1 += "一";
break;
case 2 :
str1 += "二";
break;
case 3 :
str1 += "三";
break;
case 4 :
str1 += "四";
break;
case 5 :
str1 += "五";
break;
case 6 :
str1 += "六";
break;
}
alert(str);
alert(str1);

能够正确地解决问题。不管你是通过搜索网络,或者通过改造某些成品代码(jquery/dojo/ext/yui)案例,只要能够无错地完成需求。

“字符串剪裁”代码进化版:

1
2
3
var str="www.baidu.com/?page=1";
str=str.replace(/?page/,"");
alert(str);

说明:replace方法的第一个参数虽然可以支持字符串,但最佳的类型是正则表达式;

“计算系统当前星期几”代码进化版:

1
2
3
4
var a = new array("日", "一", "二", "三", "四", "五", "六");
var week = new date().getday();
var str = "今天是星期"+ a[week];
alert(str);

说明:不管是从代码量、代码效率、代码优美性、代码思路来说,这个版本的这个日期处理代码都要优秀很多。

到了进化版,是不是最优秀的解决方案了呢?不一定,很多时候还需要根据实际情况来决定。

比如“字符串剪裁”的例子 :

1
2
3
4
5
6
7
var str="www.baidu.com/?page=1";
// 1、字符串剪裁
str.substring(0, str.indexof("?page=1"));
// 2、正则表达式
str.replace(/?page=1/, "");
// 3、字符串分拆、合并
str.split("?page").join("");

1、2、3有什么区别呢?从代码量来说”正则表达式”最优秀;从代码执行效率来说: “字符串剪裁”法最高(chrome中”正则表达式”效率最高),split法最次;从可扩展性上来说,”正则表达式”法最优。具体使用那种方案视具体的需求环境而定。

再比如“计算系统当前星期几”的例子是不是最优秀的代码呢?请看下面的实现方式:

1
2
// 计算系统当前是星期几
var str = "今天是星期" + "日一二三四五六".charat(new date().getday());

不要问我为什么,要成为优秀的程序员就是要这么倔强地追去完美。

通过一段时间的努力,很多人能够达到这个水平,但是,很大一部分人的编程能力也就止步于此。或限于产品的需求单一性,或限于需求开发的时间紧迫性,或限于人的惰性,能够完美地解决当前的需求就够了。

由于长期处于技术平台期,技术上得不到提高,通常这个级别的工程师会比较燥。技术上小有所成;或追求个人的突破;或追求产品差异性带来的新鲜感;或者只是想换个心情;因此很多此级别的工程师会经常换公司。

如何走在需求前面?

“字符串剪裁”的例子已经很完美的解决了当前的问题,但如果有一天原始的url变成了“www.baidu.com/?size=10&page=1”呢?所以当我们拿到“www.baidu.com/?page=1”的需求后,需要考虑很多没有直接提出来的、现在暂时没有但将来可能有的情况,如下面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var str = "http://www.xxx.com/?pn=0";   // 删除指定字符 pn=0
// 我将这个字符串里所可能想到的各种情况都列举出来
var a = [
"http://www.xxx.com/vmpn=?pn=0"// pn= 可能出现在 ? 前
, "http://www.xxx.com/vmpn=?pn="// url里允许pn 值为空
, "http://www.xxx.com/vmpn=?pn=0&a=1"// url 里可有多个字段
, "http://www.xxx.com/vmpn=?a=1&pn=0"// 可能排在最后
, "http://www.xxx.com/vmpn=?a=1&pn=0&pn=1"// 可能有多个 pn 字段
, "http://www.xxx.com/vmpn=?a=1&pn=0&b=2"// 可能在中间
, "http://www.xxx.com/vmpn=?a=1&pn=0&pn=1&b=1" // 可能在中间成组
, "http://www.xxx.com/vmpn=?a=1&pn=0&b=1&pn=1" // 可能零星分布
];
/* 需求的不言之秘:
? 若出现在字符串最尾则要去之
? & 两个符号不可重叠
*/
var reg = /((\?)(pn=[^&]*&)+(?!pn=))|(((\?|&)pn=[^&]*)+$)|(&pn=[^&]*)/g;

for (var i = 0; i < a.length; i++) {
alert(a + "\n" + a.replace(reg, "$2"));
}

这里不再追求一招一式,对你来说不是使用什么创新绝招解决需求,而是给出成熟稳重的方案,从根上解决问题。针对某个当前需求你的代码可能不是最优,但是针对此类的需求你的代码却是最优秀的代码。

到了这一步单单依靠技巧和数量的累积已经没有什么效果了,建议在这个阶段末尾着重关注编程理论:面向对象/过程、代码组织形式、编译、代码规范、其它的框架设计等等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
* 在拼接正则表达式字符串时,消除原字符串中特殊字符对正则表达式的干扰
* @author: fun90
* @version: 2012/12/16
* @param {string} str 被正则表达式字符串保护编码的字符串
* @return {string} 被保护处理过后的字符串
*/
function escapereg(str) {
return str.replace(new regexp("([.*+?^=!:\x24{}()|[\\]\/\\\\])", "g"), "\\\x241");
}

/**
* 删除url字符串中指定的 query
* @author:fun90
* @version:2012/12/16
* @param {string} url url字符串
* @param {string} key 被删除的query名
* @return {string} 被删除指定 query 后的url字符串
*/

function delurlquery(url, key) {
key = escapereg(key);
var reg = new regexp("((\\?)("+ key +"=[^&]*&)+(?!"+ key +
"=))|(((\\?|&)"+ key +"=[^&]*)+$)|(&"+ key +"=[^&]*)", "g");
return url.replace(reg, "\x241")
}
// 应用实例
var str = "http://www.xxx.com/?pn=0"; // 删除指定字符 pn=0
delurlquery(str, "pn");

这段代码与前一段代码从实现上来说没有太大的区别,但是从思路上来说却有着本质的区别:1、不再是就事论事,头疼医头,而是把一类问题抽象理论化,一招破万招;2、有封装的概念,不再是每次从零开始,而是站在半山腰开始爬。

现在可以多观察语言的组织结构,语言设计;看看原型链,链式语法编程,泛型,接口编程,dom遥控器等等;仔细阅读成熟的web前端开发框架的设计文档,看他们为什么要这样设计。

自成体系,化茧成蝶

知道为什么这样设计,也知道什么样的设计最好。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 库文件 /util/string/escapereg.js
/**
* 在拼接正则表达式字符串时,消除原字符串中特殊字符对正则表达式的干扰
* @author: fun90
* @version: 2012/12/16
* @param {string} str 被正则表达式字符串保护编码的字符串
* @return {string} 被保护处理过后的字符串
*/
util.string.escapereg = function (str) {
return str.replace(new regexp("([.*+?^=!:\x24{}()|[\\]\/\\\\])", "g"), "\\\x241");
}

// 库文件 /util/url/delquery.js
/// include util.string.escapereg;
/**
* 删除url字符串中指定的 query
* @author:meizz
* @version:2010/12/16
* @param {string} url url字符串
* @param {string} key 被删除的query名
* @return {string} 被删除指定 query 后的url字符串
*/
util.url.delquery = function (url, key) {
key = util.string.escapereg(key);
var reg = new regexp("((\\?)("+ key +"=[^&]*&)+(?!"+ key +
"=))|(((\\?|&)"+ key +"=[^&]*)+$)|(&"+ key +"=[^&]*)", "g");
return url.replace(reg, "\x241")
}

// 应用实例
/// include util.url.delquery;
var str = "http://www.xxx.com/?pn=0"; // 删除指定字符 pn=0
util.url.delquery(str, "pn");

经过不懈努力,经历思索磨砺,积累发散,成就辉煌。