浅谈领导和领导力

12 years ago

按:公司基层主管培训,安排我做关于领导力的讲座,效果尚可。我把PPT的内容总结成一篇文章,在这里与大家共享。 如今,市面上关于“领导”和“领导力”的文章和书籍已经数不胜数,却不让人厌烦,新的资料仍然层出不穷;另一方面,对相当一部分人来说,“领导”和“领导力”又确实难以捉摸,看书似乎明白了,做起来却全然不对劲。为什么会出现这种情况呢?根据我的观察和思考,主要原因在于:领导和领导力,都是与人密切有关的学问,一旦与人有关,就不能依靠硬性规则来行事。但是,没有硬性规则,又会感觉虚无缥缈无法把握,所以下面我尝试给出自己的几条经验,供大家参考。 很多人都想知道,为什么要有领导呢?或者说,什么样的人能成为领导呢?一个人被上级任命为“领导”,他就是领导了吗?不。他如果做得好,才可以成为领导,如果做不好,就不过是“空有个领导的名头”而已。另一方面,民间的很多“领导”(领头人物)并不需要任命,也可以获得大家的认可。如果从这个角度来看,一个人会想办法,能出主意,他就是领导了吗?似乎也不见得。古代的军师和谋士最擅长此道,但他们似乎和领导不沾边;但是一个人如果没有谋划,也没有规划,当然也不算“领导”。所以,”为什么要有领导“,确实不是个简单的问题。 我们可以换个角度,看看没有领导的情况是怎样的。此时,基本只有两个元素:人和任务,任务由人完成。通常,大家独自完成任务,也可能大家互相帮助,自发协同完成任务。 但是随着任务量的增加,任务复杂程度的增长,任务已经不能由个人单独完成,也不能由多人自发完成,这时就需要出现一个人来带领、协调、组织其他人,完成更重要、更复杂的任务。这个人就是通常所说的领导。从人的方面说,他有权力(影响力)去安排更多人的行为,这就是我们常说的“任命”的必要性(民间领袖通常依靠威信);从人物的方面说,他有办法让这些人完成更多更复杂的任务,无论这种办法是他自己提出的,还是采纳别人的。 这样就产生了一个问题:领导的工作,到底是应该看重人,还是应该看重任务呢?如果看重人,就需要给予下属更多的自主权,比如容许他们自行制定规划,自行安排进度,但领导需要承担放开的后果;如果看重任务,就会要求下属在规定的时间完成规定的事情,哪怕是疯狂加班也在所不惜。两种方式,究竟哪种更好呢? 其实答案比较复杂。在一般(非外包类)的公司,除去人力资源等几个部门,对领导的考核指标,并不会由对下属员工的考核所构成,而是强调领导的业绩,也就是任务的完成数量和质量;可是,领导并不能事必躬亲,自己去完成如此多如此麻烦的任务,而必须借助下属——也就是人——来完成。换句话说,领导需要完成更多更复杂的任务,但他必须通过下属来完成,或者说“迂回”地完成任务。所谓的领导力,就是这种迂回中需要的能力。 我把自己对领导和领导力的理解画成一张草图:任务是由人(下属)来完成的,领导的行为对象是作为下属的人,但其领导行为最终指向的,却是下属需要完成的任务。图中的橙色部分是领导的主要工作内容,黄色部分是下属的主要工作内容。两者有部分重叠,表示领导的工作不能止步于下属的具体内容之外,下属的工作也不能与领导的工作脱节。 现实生活中的很多例子都可以印证这一点。读过点历史的人都知道,“文革”结束之后,改革开放之初,老百姓之间流传有“要吃粮,找紫阳;要放米,找万里”的说法,称赞他们制定的“包产到户、包干到户”的农业政策。紫阳和万里并不种粮,也不是农业专家,但他们制定了正确的政策,调动了农民种粮的积极性,扭转了人民吃不饱饭的局面。虽然最终种粮的仍然是农民,但农民的种粮活动是受到紫阳和万里的领导行为的影响。也就是说,紫阳和万里“间接地”解决了吃不饱饭的问题。具体的任务还是那些任务,解决任务的人还是那些人,但换了领导,结果大不一样,这就是领导力的展现。 最开始说领导力是与人有关的学问,原因就在这里。这个道理,温伯格在《技术领导之路》中的表述更加清楚: 所谓领导力,就是创造出一个环境,提升其他人的创造力和生产力,让每个人都能发挥出更大的能力,创造出更大的价值。 或者用我的话说,同样的人,同样的事。没有领导,这些人就做不成/做不完这些事情;非得有领导才能完成。这就是领导的价值。 既然领导力与人有关,领导就不能不了解与人有关的知识。如果我们把“人完成任务的能力”粗略地称为“人力资源”,那么,人力资源有几种特性,是其它类型的资源所不具备的,值得领导特别关注。 第一种特性是,人力资源的输出是不稳定的。计算机每秒的计算量是稳定的,驴一天拉磨的圈数是固定的,泉水一天出产的水量也是相对稳定的;但人力资源不是这样,人力资源的输出受多种因素的影响。如果员工失恋了或者家人去世了,他可能每天都来上班,但上班的效率为零。当然,这只是极端的情况,但人的情绪和状态确实会极大地影响人力资源的输出。 为了保证人力资源输出的稳定,就必须保证下属的情绪和状态的相对稳定。首先,要尽量保证工作的自发自愿性,一个人是作为积极进取的公司职员,还是作为被迫劳作的农场奴隶,其生产效率绝对是有天壤之别的。在分配工作时,应当尽量考虑下属的兴趣、意愿,最糟糕的情况,就是让下属去做他非常排斥的事情,这样几乎不可能有好的收效,第一个需要反思的就是领导自己。其次,平时注意营造积极乐观的工作氛围,打消下属在工作时的过多顾虑和担忧,并注意观察下属的情绪,如果发现波动,应当及时了解、抚慰。最后,要建立信任,尤其是对喜欢多想的下属,如果没有建立足够稳定的信任机制,任何一点小变化、小波动,都可能严重影响他的情绪;如果让下属信任你对他的一贯态度,对他的工作的一贯态度,就可以避免此类问题的发生。 第二种特性是,人力资源是具有持续成长性的。要升级计算能力,你可能需要升级计算机;要烧更多的水,你可能需要更多的电,更多的煤。但是要完成更多更复杂的任务,公司给你的资源和人力编制,并不会有同步的增长。另一方面,大多数员工也有对自身发展的期望。培养下属持续成长,就可以解决以上两个问题。 要保持人力资源的持续成长,领导必须花很多的心思。一方面,根据未来的目标,有计划地培养、储备人才,以便用有限的资源,解决更多的问题。另一方面,也需要为下属考虑学习成长之路。我们在招聘时,面试者经常会说“希望能多学东西”,但是很多人并没有培养出自动自发学习进步的习惯和能力,然而如果公司没有给他“学到东西”的感觉,他又会对工作和公司失望。所以身为领导,往往必须为下属拟定一系列的学习发展步骤,并持续实施,这样既可以不断提供给下属学习的成就感和满足感,又可以培养出符合公司业务需要的,能力更强大更全面的员工。或许也正因为如此,希拉里才说:“优秀的领导,会带领人们去到他们想去的地方;卓越的领导,会带领人们去到他们没想到但应该去的地方”。 第三种特性是,人力资源的转移很快。这里说的“转移”,是指员工的流动。员工的流动会给业务的开展造成非常严重的影响——我想,再也没有什么消息,比在准备大干一场的前夜听到业务骨干离职,令领导沮丧的吧。 员工的流动是不可避免的,但身为领导,应当将其稳定在可控的范围之内。通常,员工会留在某个公司,有两个原因:第一是觉得自己的工作有希望,第二是觉得公司有希望;而且,两种希望有相当的重合。但是有些员工的“希望”很明确,有些员工的“希望”只是“有希望的感觉”而已;另一方面,员工对于“公司的希望”,其实是没有上级领导了解的全面和细致的。所以,身为领导,应当尽量向下属阐明公司的希望所在,并且照顾到员工的希望——对“希望”很明确的员工,要努力寻找他的希望与公司的希望的重合地带;对“希望”不那么明确的员工,应当从公司的角度出发,结合其个人特点,具体化并不断强化这种“期望”,得到员工的认可。如果员工的期望与公司的期望完全绝缘,找不到太多共同点,则应当尽早选定后备力量,以防下属离职给自己的工作造成困扰。

正则学习问答

12 years ago

最近有幸在开源中国和51CTO两家网站作为嘉宾参与了于正则表达式的专题问答。在问答过程中,我收集到学习正则表达式过程中的某些普遍问题,在这里专门花一点篇幅来回答 正则表达式是难学的,这不存在疑义。但是我认为,难点也只在语法方面。正则表达式已经有年头了,它(的语法)诞生于上世纪七十年代。那是个怎样的情景?举个简单的例子吧,Unix下的usr、dev等名字,就是那时留传下来的,现在已经有很多人诟病了,usr不是user,dev不是device,难学,也难记。经过这些年的飞速发展,当年的很多问题已经被包装得美轮美奂,如今的用户可能更习惯直接点击“用户目录”、“驱动器”之类的图标,再也不用为那些不规则的简短名字发愁。但是不幸的是,一直以来正则表达式的语法却没有太多的变化,甚至后续增加的功能,也沿袭了之前的语法风格,在编程语言日渐人性化的今天,它自然显得非常难懂了。今天的开发人员可能更习惯Regex.CharRange('a', 'z')这样的写法,而不习惯[a-z];遇到(?![a-z])这样的结构就更是抓瞎,除非转为Regex.CheckRight(Regex.CharRange('a', 'z'))的写法。 不过,换一个角度来看,两者其实是一回事,只是表现形式不同,一个类似要诀,一个类似大白话。如果我们能在头脑里构建出从要诀到大白话的转换,正则表达式就简单了许多,甚至可以说就是模块的拼接。比如支付宝的流水号为18或26位数字,用正则表达式匹配,就是^([0-9]{18}|[0-9]{26})$,或者^[0-9]{18}([0-9]{8})?$。其中的逻辑很简单:^用来锁定开头,$用来锁定结尾,[0-9]匹配数字字符,([0-9]{18}|[0-9]{26})表示两个并列的选项,即数字字符串长度为18位或26位,而[0-9]{18}([0-9]{8})?表示至少需要出现18位的数字字符串,在这之后可能还有一个8位的数字字符串(所以总长度是26位)。一般的正则表达式应用,就是这么简单。 如果你觉得上面说的没错,那么学习正则表达式的难题就只剩下了选择得当的方法。我们学习编程语言时,都强调不能只看书,要动手写程序,甚至最好的办法是把书上的例子亲自输入运行一遍,这样才算真正学会了。但在许多人眼里,正则表达式或许算不上编程语言,所以学习是点到即止,甚至是满足于从网络上抄一些现成的表达式。所以,常见的问题之一是“有没有什么学习的捷径”,很不幸,答案是没有——既然拷贝他人的代码不能学会编程,抄阅现成的表达式、随便翻几篇文档,当然也学不会正则。不过也有幸运的消息,真正学会正则表达式并不需要花太长的时间。 以我的经验,学习正则表达式,真正要做的是深入理解常用功能:字符组、多选分支、匹配模式、环视。可以说,弄明白了这几点,80%的正则问题都可以解决。但是要弄明白这几点,就需要专门的学习:字符组是解决什么问题的,它是怎么使用的?多选分支是解决什么问题的,它是怎么使用的?应当抽一些时间专门学习、思考;这些都弄明白了,再研究解决复杂问题的表达式是怎么构成的。如果你可以每天抽1-2小时专门学习,两周内就会有明显收效,一个月几乎就可以修炼到相当水平。而且,以我的经验,在学习新的编程语言时,不但要把书上的例子都亲自输入运行一遍,更要自己动手去改一改示例代码,看看会出现什么现象,再想想为什么会这样。如果你在学习正则表达式时也做到这一点,必然能够事半功倍。 如果你真正理解了这些常用功能,对它们的价值和使用有清晰的概念,那么另一个麻烦也就迎刃而解了——不同语言的正则表达式不同,如何解决?虽然不同语言中的正则表达式规定各有不同,但背后的思想是统一的,不同的只是表现形式,或者说概念的落地方式。好处在于,编程语言的文档不会详细讲解什么是字符组,什么是多选分支,但会详细告诉你字符组在本语言中是如何表示的,多选分支又是如何表示的(不信你可以在这些文档中搜索character class或者alternation)。所以如果你的脑子足够清楚,即便不确定最终的表达式如何写,也只需要查文档就可以解决。举个例子,匹配空白字符的字符组\s,在Java字符串中要写作\\s,因为\s并不是Java字符串中的一个合法转义序列,所以之前还必须有\来转义\;在PHP中可以直接写作\s,因为PHP处理字符串时会把无法识别的转义序列原封不动地保存下去;在Unix下的某些工具中,必须写作[[:space:]],这是Perl风格的\s在POSIX规范中的表示法。看起来比较麻烦,也仅此而已,因为我们知道,这里需要用到的,就是“匹配空白字符的字符组”。 以上写了这么多,可能有人会说:正则表达式这东西,不登大雅之堂,没必要花那么多精力。或许正是这种观点,形成了“不认真学习正则表达式”思想根源。幸运的是,这个问题其实很好想明白,因为很多事情都是这个道理。比如写文章,我们不要求人人都是作家,但是人人都有可能在需要的时候写出几篇拿得出手的正经文章,“不是作家”并不是“需要时写不出正经文章”的理由。为了能在需要的时候写出正经文章,就必须专门抽出时间来学习和练习写作。正则表达式的学习,其实也是这个道理。 这种说法可以说服一些人,但还有一些人是说服不了的。同时据我观察,那些不能被说服的人,似乎也没有花太多精力在其它“正事”上,反而会不时为正则表达式所困扰。与此相反的是,真正有职业素质的程序员,就像the Productive Programmer中说的那样,会愿意花2小时写出一个正则表达式,为以后节省无穷无尽的时间。当然,以上说的这一切的前提,都是能端正学习正则表达式,或者说学习有价值技能的的态度。做软件的人大都读过布鲁克斯的名文《没有银弹》,所以这里不妨借用他的话说,正则表达式的学习,也不存在银弹。

浅谈编码

12 years ago

在《学到不会忘》中我提到,为了写《正则指引》,专门抽了些时间学习Unicode,也因此明白了很多与编码有关的问题,只是最后没有全部写进《正则指引》中,以免离题。不过,这并不妨碍专门用一篇文章来讲解编码问题。 其实所谓编码问题,不外乎若干概念,弄明白了这些概念,编码问题就可以迎刃而解了,所以这里按照概念来展开讲解。 字符和字符集 字符,就是我们日常使用的各种文字,比如中文的你、我、他,英文的A、B、C,日文的に、ほ、ん、ご,都是字符。手写可以用到的字符几乎是无限的,但在计算机中,必须事先约定好字符的范围,也就是穷举出所有“可以使用”的字符。这个范围,就是通常说的“字符集”(Character Set)。 ISO8859-1是开发中常见的字符集(MySQL默认就采用这种字符集),它支持的语言有英语、德语、法语等,也即包含了英语、德语、法语中的字符。GBK是另一种常见的字符集,它源自GB2312字符集,GB表示“国标”,GB2312即是国家标准,它的另一个名字是CP936(Code Page 936),以前在Linux下播放MP3,如果发现ID3标签乱码,设定为CP936就可以解决。因为制定较早,GB2312只包含6763个汉字,并不足够覆盖日常的使用,所以诞生了GBK,其中的K表示“扩展”。有意思的是,GBK是微软制定的字符集,而不是“国标”,只是曾由国家技术监督局标准化司、电子工业部科技与质量监督司公布为“技术规范指导性文件”。除此以外,港台地区以前使用Big5字符集,曾经在Dos下玩过港台游戏的朋友应该还记得“大五码”这个名字。 与字符相关的另一个概念是字形(glyph),它是字符显示出来的样子,同一个字符可以有好几种写法,每种写法其实对应一种字形。下面举例列出了“高”字的几种字形(资料来自Wiki)。 编码与码值 在计算机内部,所有的数据都是编码保存的,字符也不例外。因此,每一种字符集不但约定了可以使用的文字的范围,而且为每一个字符确定了唯一的代码,称为码值(Code Point,也叫“代码点”)。 在ISO8859-1字符集中,A的码值是41(十六进制),=的码值是3d(十六进制);在GBK字符集中,发的码值是b7 a1(十六进制),罚的码制是b7 a2(十六进制)。因为单个字节只能表示最多256个字符,而中文字符超过256个,所以GBK编码选用2个字节表示单个字符,相应的,其码值也是4位十六进制数值。 我们说的“GBK编码”、“ISO8859-1编码”,其实既指其对应的字符集,又指其对应的码值规定。通常,两者是一体的,但是在Unicode编码中的情况,却不是这样。 Unicode 随着计算机和互联网的发展,各自为战的字符集很快就遇到了问题:如果我需要在一篇文章中同时使用中文和日文字符,该怎么办呢?设定为日文编码(常用的为Shift-JIS、EUC-JP)则不能涵盖中文字符,设定为中文编码则必须放弃日文字符,所以需要一种统一的、可以覆盖各种语言的字符集,于是Unicode字符集应运而生了。 Unicode的最初想法是用2个字节(16位,65536个码值)来表示世界上所有的语言,所以它的字符集称为UCS-2(2 byte…

说说我理解的职业开发人员

12 years ago

应人民邮电出版社图灵公司的邀请,我有幸参与了Bob大叔所著Clean Coder(不是Clean Code)的翻译。 与前作Clean Code不同,这本书着重讲述的是开发人员的“职业素养”,也即职业开发人员应当如何做事。在阅读中,我时常会忍俊不禁,也会拍案叫绝,感叹Bob大叔把深刻的道理讲得这样通透。我虽然没有Bob大叔那样好的文笔,不过对“开发人员的职业素养”这个话题,也有很多话想说,索性分几个方面写下来。 学习 开发人员在工作之前,一般都已经经过大学阶段的专业学习。众所周知,大学的很多课程已经相当落后,教材也非常保守,所以我见过的好开发人员,不少都是自学成才。但是,这些问题并不能否认通过专业课程学习知识的意义,职业开发人员理解的“学习”,应当明确地区分知识、课程、教材:知识是重要的、稳定的,课程和教材是不那么重要的、变化的。 可以非常肯定地说,数据结构、编译原理、操作系统这类知识,是整个计算机世界的基石,是任何时候也不会过时的。即便毕业后不从事专门的科研,这类知识也会从你接触到的各种现象中体现出来。我在大学时基本抛弃了学校指定的课程和教材,但自己反复啃过影印版的《现代操作系统》,反复做过北大屈婉玲老师的三本《离散数学习题集》,后来在工作中受益匪浅——调优程序的性能,很可能需要理解调度、死锁、用户空间与系统空间等知识;重构复杂的布尔逻辑,很可能要依赖数理逻辑中的定律。如果当时没有反复的研习,没有深入理解这背后的原理,并且没有领悟到这些原理和各种现象之间的联系,遇到很多问题我很可能就会两眼抓瞎,充其量凭经验试错,无论如何,其效率远不及知识体系指导下的实践。 据我观察,大学生之所以对课程不感冒,除去学校和教师的原因,另一个因素是,几乎很少有教材能把看起来乏味的原理,和生活中遇到的问题讲清楚。学习图算法时,你是否想过“人、狼、羊、草过河”的问题可以直接由它来解决?学习内存管理时,你是否想过为什么Windows 95、Windows 98都那么容易蓝屏,到了Windows XP才有了长足的进步?我相信,如果能把原理与这类例子对应起来,你的理解就会深刻许多,印象也会深刻许多。不幸的是,这类“打通/联系”的工作,在国内教材基本是一片空白,国外教材也只有部分涉及。其结果就是,不少“有经验”的开发人员面对“32位机为什么只能支持4G内存”、“进程间通讯有哪几种方式,各有什么优劣”、“浮点数是怎么表示的,为什么是不准的”之类基本问题一脸茫然,不要小看了这些问题,不懂它们,你开发出来的程序只能凑合用,因为根子上就欠考虑,所以后期遇到问题要重构和调优,就会难比登天,最终搞到自己疲惫不堪。 对此,我的建议是:如果你现在还在学校,不妨仔细想清楚知识、课程、教材之间的关系,确定重要的知识,选择好的教材,自己安排自己的课程。如果你已经离开学校,而且感觉自己的基础并不牢靠,不妨从手头的工作开始,想想它用到了哪些原理,对应哪些知识,逐步、有针对性地补习。这其实并不难——我的朋友张东亮(@zhasm),之前几乎没有任何计算机基础知识,只是因为对正则表达式的爱好,找到了一份开发人员的工作,一年之后,他已经开始啃编译原理的书籍,而且确实学进去了。 以上说的主要是“专门”的学习,如果是工作之后的学习,会有很大的不同。 首先,工作之后的学习更多依靠自觉,没有几家公司会付出代价让员工像学生那样“学习”,所以更多时候,你只能花自己的时间、自己的金钱来学习。很多人一想到要花自己的时间,自己的金钱,心里就打了退堂鼓。要明确的是,公司没有老师那样强烈的责任培养员工“成长”,如果你找不到好的、薪水高的工作,很难责怪上一家公司没提供好的培训。所以,担心金钱和时间而放弃学习,最终的结果是自己的停滞,逐渐丧失竞争优势。相反,投入时间和金钱来学习,不但可以保持甚至扩大你的竞争优势,如果这种行为可以坚持、内化到生活中,也有助于保持健康、饱满的精神状态。 其次,工作以后的学习,需要努力摆脱工作环境的限制。我见过不少开发人员,因为工作限定在某个平台,某种语言,业余时间的学习便全部投入到这种平台、这种语言上,而没有思考自己是否合适做这些平台和语言,这些平台和语言是否处于没落期。在学校里,考分或许往往是唯一的度量,但在工作中,行将没落的语言和平台,你运用得再熟练,也于事无补。况且,过于专精于一门语言、一个平台,反而会限制你的思维和视野,影响迅速学习陌生知识的能力——要在短时间内熟悉陌生平台和语言的例子,在我们工作中并不少见,在整个IT业界中更是家常便饭。为了让它真的成为“便饭”,平时还是应当有意识地摆脱工作环境的限制,挑战自己的思维惯性。 责任 我曾经见过很多的简历,在“工作经历”里,项目描述写得天花乱坠,如何先进,如何复杂,采用了多少新技术,但是具体到个人责任,或者语焉不详,或者极其潦草。这样简历,体现的是责任感的缺失——对于自身责任没有明确的认知,也就没有足够的担当;这样的人,通常不用面试,就可以知道并不是合格的“职业开发人员”。 另一方面,我在面试时,经常会问两个问题,其中很重要的一个是:在你的工作经历中,收获最大或者印象最深的事件是什么。一般来说,如果能回答得有条理、有依据,大多可以判定为合格的职业开发人员。因为,有责任感的开发人员,大多不会把程序看成身外之物,更多地会把程序与自己的道德、声誉等等联系起来,甚至把程序看成自己的孩子;所以,必然会投入时间精力去总结、反思、完善、改进,就像照顾自己的孩子那样。其实,就我的经验看,真正的职业开发人员,不但能很好地回答这个问题,而且说起自己做过的事情,多有种充沛的自信感:XX项目是我做的,其特点是什么,我是如何如何做的,遇到什么问题,是如何解决的……涉及的技术不必很先进,开发的系统也不必很复杂,只要能够这么自信满满地一条条历数下来,你的职业素养就是无可厚非的。 业务…

学到不会忘

12 years ago

博文视点的张春雨编辑告诉我,八次印刷的《精通正则表达式》已经全部售罄了, O’Reilly 与电子工业出版社续签了版权合同,准备重新上市,让我写一点东西。 该写什么好呢? 2007 年 《精通》上市时,我还在中关村,天气好的时候可以望见颐和园的佛香阁;而现在,窗外景色已经换成了珠江边的小蛮腰;对正则表达式的使用,也从随手拈来变得生疏——许多问题需要翻查《精通》,翻查自己写的《正则指引》。究其原因,与正则表达式直接相关的开发做得少了,古话说“勤则立,嬉则荒”,就是这个道理。 荒是荒了,毕竟还没荒废,虽然有很多细节需要查阅,但是我很清楚,某个问题能不能用正则表达式解决,该怎样解决。或者说,虽然手上生疏了,心里其实没有忘记,而这一切,归源都是之前死啃过《精通》的缘故。 在阅读《精通》之前,我已经查阅了网上的不少资料,对正则表达式有了基本了解,能像模像样地解决一些实际问题,可算“够用”了。这时候遇见《精通》这样“现实价值不那么大”的书,能静下心去阅读,其实带着点毕业不久的傻气,只是单纯想把它弄懂搞透。所以,遇到匹配原理这类看来没多少实用价值的知识,还会愿意花时间去揣摩、研习。回头想想,也正是因为当时有这种傻气,可算是意外的收获:工作中经常需要学习一些工具和原理,虽然当时也“学会”了,但不久就忘个精光;相比之下,正则表达式却是学到了“不会忘”的程度。更典型的例子是游泳,几乎人人都可以做到“一朝学会,终身不忘”。同样是“学会”,为什么差距这么大呢? 这个问题我想了很久,最后的答案是,“学会”的定义是不同的。 通常我们说“学会”了某项技术、某门语言,意思是“凑合能用”,或者说“可以对照文档( Google )解决问题”的程度——你用 Python 解决了一个问题,就说明你“学会”了Python ,哪管是步步 Google ,还是照抄现成的代码。而我们说“学会”了游泳,意思是可以在水里行动而不沉下去,更重要的是在游泳时不需要时刻背诵各种口诀:吸气—伸手—划水—蹬腿—抬头—呼气……,如果你在泳池里还要时时谨记这些口诀,是绝对谈不上“学会”的。 两者虽然都叫“学会”,其实相差迥异:第一种“学会”是“照猫画虎”,第二种“学会”是“融会贯通”,虽然都可以解决问题,但从第一种“学会”到达第二种“学会”,其实需要经历漫长的过程。而且,两种“学会”都能解决问题,所以在达到第二种“学会”的漫长过程中,你很可能感觉不到自己的进步,反而会困惑继续学习的意义乃至放弃——既然能对着文档操作,既然有现成的资料,为什么要去理解背后的原理呢。 对我来说,第二种“学会”的好处是显而易见的,最重要的一点就是不会忘记——学习的时间增长一倍,遗忘的难度将会增加十倍、二十倍甚至一百倍。这些年来,我见到了太多这样的例子:有人每次用到正则表达式都会抓狂,都要四处极力搜索、反复盲目尝试,花很长时间才能凑出、蒙对解决方案;另一方面,他们又不愿意花时间潜心学习《精通》这样的经典。因为反复遗忘,需要反复学习,最终浪费了大量的时间。…

《正则指引》上市了

13 years ago

经过各位读者和出版社的辛苦努力,《正则指引》终于上市了,以下是主要的购买链接: 亚马逊:http://www.amazon.cn/%E6%AD%A3%E5%88%99%E6%8C%87%E5%BC%95-%E4%BD%99%E6%99%9F/dp/B007X6O6J0/ 当当:http://product.dangdang.com/product.aspx?product_id=22702127 京东:http://book.360buy.com/10972570.html China-Pub:http://product.china-pub.com/199266 有趣的是,预售阶段就登上了京东的24小时分类畅销榜,感谢大家的厚爱。      

关于程序员学英语的经验

13 years ago

按:本文为《程序员》杂志约稿,刊发于2012年3月号,名为《程序员学英语三部曲》,http://www.programmer.com.cn/10833/。 总的来说,程序员可算是英语水平比较好的群体,因为在这个行业,英文资料是最全面、最及时,对英文资料的需求也最迫切的。因此,就我的观察,即便刚入门不久的程序员,面对陌生的问题,一般也能查阅英文文档,找到需要的信息。但是另一方面,我也发现,经常阅读英文文档的程序员,英语水平许多时候却不像“经常阅读英文”的样子。应《程序员》的编辑邀约,我在这里列几点自己的学习心得,供大家参考。 第一,既要看代码,也要读文档。 读文档只读代码,是很多程序员的习惯,也是导致程序员虽然读了很多英文资料,英文水平却没有相应提高的原因之一。以前曾在《程序员》上看到介绍阅读技术图书方法的文章,提出过“先代码后文字”的方法,也就是“先看代码,看不明白再看文字”。这种阅读法能极大提高阅读效率,但如果技术图书只看代码就足够,还要文字干什么呢?很多时候,代码只是冰山一角,代码背后的思维和逻辑才是真正的重头戏,只有写成文字才能解释,也只有阅读文字才能理解。 比如,两段代码都是 x = 5; 看起来没差别,但一段的文字说明是“x should be not more than five”,另一段的文字说明是“x should be no more than…

闲谈跨界

13 years ago

我的朋友韩磊曾说:跨界(工作)真是一件刺激好玩的事情。彼时我还无法体会这句话的真义,直到去年因缘际会自己也投身跨界,终于有机会切身体会到其中的滋味,所以有这篇文章。 其实在此之前,我一直混迹于互联网的圈子,自认为接触过一些真正的东西,比如大规模数据的抓取,海量数据的存储和处理,在线系统的维护……客服、文案等等工作也有涉及。我想,太阳底下没有新鲜事,跨界虽然是在不同的领域,做的事情大抵还是这些。但是真正投身实业,才发现事实远非自己想象的那样。 这方面突出的例子之一,就是虚拟世界和现实世界的交流。从某种方面来说,互联网或者纯软件开发,更像在理想的虚拟世界中进行,可以脱开现实的束缚,只关心核心的模型。“发一条确认的消息”是非常普通而且常用的操作,你用Java也好,C#也好,PHP也好,只要按照约定发送这条消息,结果都不会有多大差别;落实到现实世界中,情况要复杂许多:消息必须有实际的载体,有发送的动作,不同的载体和动作,又对应到不同的效率和准确率。举个现实的例子:许多客户端软件,通常要求输入条码识别产品,然后用键盘(鼠标)操作一系列对话框、选择框,执行后续的操作。这个流程看起来没什么问题,但是“扫描-敲键盘”的操作在对处理效率要求很高的情况下,却会成为瓶颈。对此,可行的解决办法是,将键盘/鼠标操作统一为几种消息,比如“是”、“否”、“取消”、“确认”,把这几种消息对应到特殊的条码,将这些条码打印出来,贴在墙上,并辅以不同的提示音。这样,需要输入“是”的时候,只需要用扫描枪扫墙上贴着“是”的条码,并确认听到提示音,就可以完成。大部分时候,操作员的手不用离开扫描枪,甚至不怎么用看屏幕,效率自然大大提高。深入学习了解每个操作、每种功能的具体发生情境,是从互联网/纯软件转到实业开发中,相当重要的一点。 另一方面,实业里有许多领域和环节,因为某些限制,一直没有建立完善的虚拟世界(概念模型),如果能够妥善运用技术突破这些限制,同样能够大大提高操作的效率和质量。比如在物流运输中,“封箱带”部分承载着“保证货物运输过程中不被调换”的职能,但其实“保证不被调换”并不只能依靠封箱带这种手段。如今可以通过先进的设备和完善的系统,记录追踪每一个环节中货物的状态,尤其是重量——进入某个环节时,重量是多少,离开某个环节时,重量又是多少,即便货物被拆分,总重也应当保持不变……前一段时间报道出来的iPhone手机在运输过程中被调包的案件,我注意到,盗贼精心制作了和真iPhone手机同样重量的模具,这样瞒过了各个环节,到最终开箱才被发现,看来是深入了解过整个流程的。 以上都是比对技术思维和现实思维,如果换一个角度,从互联网的视角来看企业开发,又会有新的感受。就我的经验,企业开发中,有两个方面可以大量借鉴互联网开发。 第一是借鉴互联网开发的松耦合、混搭(mashup)思维。传统的企业开发虽然也强调分层,但大多必须严格地按照某些框架和套路来进行,开发人员更主要的工作都是“填格子”,这样有两个弊端:选用的框架和套路并不一定合适,尤其不适合今天迅速变革发展的节奏,开发人员的思维和视野也比较受限,难以交付高质量的成果。而互联网开发虽然比较“乱套”,但天生就强调松耦合,强调“服务意识”,许多开发人员天生就知道调用网上的各种服务,受其影响,也愿意将自己的功能做成服务(而不是一段源代码或一个二进制程序)。在一个相对复杂的系统里,完善的文档说明固然不可缺少,但架构同样重要,各个功能是做成服务,还是做成源代码、二进制程序,很可能极大地影响未来的开发难度和开发成本。这方面,企业开发可以多向互联网开发取经,实际上,许多从互联网行业总结的经验,已经被证明完全可以用于企业开发,比如如今流行的REST模式,就不乏成功的企业实施案例。 第二是借鉴互联网的产品思维。传统的企业开发,更像功能的堆砌,功能的组织和引导都很成问题。我曾留意观察过一些大型企业的ERP系统,虽然看似强大,员工使用起来却叫苦不迭,突出问题界面无序,功能杂乱,数据密密麻麻,很难找到自己需要的信息,操作也很繁琐。而互联网开发早已进入“体验至上”的年代,用户习惯了“凭直觉”操作;在这表象之下,功能并不是少了,而是多了,并不是简单了,而是复杂了,只是以更直观、更清楚地方式呈现给用户,并且需要分析用户的行为,不断调整。两相对比,如果能在企业开发中多一些产品的思考,多一些用户体验的思考,往往会受到良好的效果。现身说法是,我们分析了几个月内,所有员工对系统中某个功能的调用操作行为,总结出若干特点,再加以优化,服务器的负载减轻了很多,员工的操作也简便了很多。在企业系统里,这类工作往往是大有可为,而且收效显著的。

《正则指引》前言

13 years ago

  前言 提到正则表达式,许多人很有点不屑一顾:这东西,不登大雅之堂,再说也不是总要用到,何必专门花时间学习? 没错,正则表达式并不是“总要用到”,但到了需要的场合用不上,往往产生“一分钱难倒英雄汉”的尴尬。经常需要处理文本的程序员自然会知道正则表达式的价值,其它的程序员如果不会正则表达式,即便开发的领域与文本处理没什么关系,也难免“躺着中枪”的命运——前几天我遇到一个问题,将一行长长的地址拆分成多行,负责这部分的程序员日常的工作只是制作PDF而已,拆分地址是很“边缘”的功能,但不会正则表达式就无法准确折行(一般需要在标点符号出现的地方折行,而不能只在空白字符处折行,但是不同语言中的标点符号各有不同),结果一筹莫展;相反,如果了解正则表达式,就可以很容易地处理各种语言中的标点字符。 以我的开发经验来看,专门花点时间掌握正则表达式,确实是非常有必要的。目前可以见到的关于正则表达式的书籍和资料已经有不少,但又各有不足。 在互联网上,流传着一些编程语言的正则文档和《30分钟教会你正则表达式》之类的帖子。这类资料的好处是简单直接,查到了,如果有现成的例子,而且适用于自己的语言,可以直接拿来用;然而,其坏处也是简单直接,因为缺乏背后原理的讲解,如果找不到现成的例子,或者找不到能在自己所使用语言中行得通的例子(须知道,同样的正则表达式并不能直接套用到不同的语言中),则束手无策。 在正式的出版领域,已经有《精通正则表达式》、《正则表达式必知必会》之类的书籍出版,尤其是前者,堪称关于正则表达式的经典著作,如果想认真学习正则表达式,这类书籍是必须阅读的。但是这类书籍也有一个弱点,即它们都是从英文版本翻译而来,更多地侧重英文文本的处理,身为中文世界的开发人员,我们经常需要处理中文文本,对于处理英文之外的字符,正则表达式已经提供了足够丰富的功能,但如何用对、用好这些功能,资料却很匮乏。 我经常需要给人讲解正则表达式的相关知识,时常惋惜的是,开发人员为这些问题所困然;正因为如此,本书的写作动机便是着力弥补现有资料的缺陷。 相对于正则文档和速成教学帖子,它深入讲解了匹配背后的原理,往往会举一反三,告诉读者,这里为何这样写,如果改成其它形式,会造成什么结构;并且,集中讲解和比较了多种语言中正则表达式用法的异同,方便读者把现成的正则表达式“移植”到自己的工作环境中。 相对于《精通正则表达式》等正式的书籍,本书辟出专门的内容讲解语言和编码,告诉读者如何设定编码,如何正确处理中文等字符,另外,本书还涵盖了.NET、Java、JavaScript、PHP、Python、Ruby六种常用语言,对每种语言给出专门章节,不但详细介绍了语言中正则表达式的用法,更点明了版本之间的细微差异,不但可以作为专门学习的教材,还可以成为有用的参考手册。 本书的结构 本书可以分为三大部分。 第一部分主要讲解正则表达式的基础知识,覆盖常见正则表达式中的各种功能和结构。看完前面三章,就可以基本弄明白现在流行的各种正则表达式;尤其如果你之前有一些经验,会觉得阅读起来并不困难。但是我也希望读者不要忽略其它的内容,断言和匹配模式现在已经是正则表达式的“标准配备”了,而且确实可以派上大用场,所以第4章和第5章的内容,即便不是很熟悉,阅读起来可能有一些麻烦,也不应该忽略。最后的第6章,则厘清了正则表达式在使用中的若干疑惑,了解它们,你就可以相对自由地在正则表达式的世界里行走了。 第二部分主要讲解关于正则表达式的更深入的知识,这一部分用三章的内容,详细探讨了编码问题、匹配原理、解题思路。这部分内容更抽象,需要多花一点时间来阅读和理解,但是它们确实可以帮你在正则表达式的世界里登堂入室,脱离“术”的层面,掌握万变不离其宗的“道”。 第三部分的作用是接地气,将之前介绍的各种知识落实到六种常用语言.NET、Java、JavaScript、PHP、Python、Ruby中来。每一章的开头有正则功能列表,其中的功能都对应到前面部分的讲解,这些功能的具体应用实例,以及不同版本之间的差异,则在章节中详细讲解,每一章的最后还给出了常见任务的示例代码,方便日后查询。在最后,第16章简要介绍了正则表达式在Linux下常用工具vi、grep、awk、sed中的使用,并通过一个实际的例子将这几种工具串起来,对比说明了它们适合解决的问题。 在本书的最后提供了用作参考的附录,分为三部分。 第一部分是正则表达式的常用功能在不同语言中的比对,希望能给需要在多种语言中使用正则表达式或者移植正则表达式的读者来说提供一份有用的参考;第二部分给出了若干常见的正则表达式,比如匹配邮政编码、身份证号、手机号、QQ号、电子邮件地址等等,希望能成为常见问题的“速查手册”;最后一部分列出了常用正则表达式的工具和资源,方便大家调试自己的正则表达式,以及继续深入学习。 本书的读者 本书适合以下几类读者。 经常需要进行文本处理(比如日志分析或网络运维)的技术人员。这些读者或许已经熟悉了正则表达式的基本用法,但面对日益复杂化和海量化的数据,阅读本书可以帮助你更准确、更高效地处理文本,提升自己工作的价值。…

太阳底下有没有新鲜事?

13 years ago

太阳底下到底有没有新鲜事?这是一个问题。如果有,为什么会有老话说“太阳底下没有新鲜事”;如果没有,我们每天分明又见到各种新奇的事情和问题。这到底是怎么回事呢? 不妨来看个具体的例子:同样是产生热量,我们可以给电热元件通电,也可以点天然气,还可以依靠摩擦生热,甚至还有很多我们意想不到的方式,每一种方式都其独特之处,这么看来,确实是总有新鲜事;但是从另一方面来看,这些方式可以归类为物理的、化学的等几大类,而其本质,无非是能量的转移,这么看来,说“太阳底下没有新鲜事”,又的确有道理。换句话说,“有没有新鲜事”取决于看问题的层面。通常,从具体细节来看,总是有新鲜事发生,但是分类归纳之后,往往并无新鲜可言。 不过,无可否认的是,面对新鲜事物,一句“太阳底下没有新鲜事”,即便是漫不经心说出来的,也非常有分量,充分体现出极具洞察力的专家的自信——我就知道会是这样;更进一步,不止自然科学领域,在社会科学领域,许多人也在寻找那些恒常不变的规律(或者也可以叫共性、要诀、招式),期望从此收获“太阳底下没有新鲜事”的自信。但是,他们真的能做到这一点吗? 且以近年来受极大追捧的经管类畅销图书为例,这些书之所以畅销,光看名字就已经可知道原因了:《追求卓越》、《基业常青》、《从优秀到卓越》……作者毫无例外地宣称运用科学方法分析得到了伟大(卓越)公司的经营秘诀,并且尽力将书写的生动有趣、引人入胜,旨在让读者闲庭信步间领略到“伟大的公司何以伟大”的秘诀——比如四大要素、六个步骤、八大法则等等,告诉读者成就伟大的公司并不是什么新鲜事。继而,依葫芦画瓢,也可以将自己的事业做到优秀,做到卓越……但是,就我的经验,这么做多半是缘木求鱼,充其量,可以算一厢情愿,只能体现人们对美好图景的幻象,具体原因在下面详述。 首先,经营公司要解决的问题,与自然科学的问题并不一样。自然科学解决的典型问题类似:生产某样产品需要多少原料,经过怎样的物理化学处理等等。但是公司经营要解决的典型问题则类似:根据有限的资源,到底是生产产品甲,还是产品乙,如果选择产品甲,需要按照什么次序,投入多少资源,有多大的市场,预期可以获得多少回报……每一个问题都是新鲜的,都需要具体分析。实际上,畅销的经管书籍也被迫承认这些方面没有多少成文的规律可循,它们大多以“需要有一个清楚而持续的战略”之类的说辞来敷衍。实际上,战略是否清楚,很可能是随着公司的经营而逐渐明晰的,而且很可能需要经常调整战略,所谓“清楚而持续的战略”,更多是事后的总结和包装,并不能在事前确认。 其次,公司经营的成败,很大程度上取决于与竞争对手的互动态势,而经管畅销书往往对此语焉不详,似乎更注重“内功”。实际上,与竞争对手的互动是非常考验脑力的:对这个对手,可能需要采取这种方式,对另一个对手,又需要采取另一种方式;更复杂的是,对手可能会根据你的应对做出调整,于是这一轮应对结束,下一轮应对开始……了解博弈论的人知道,随着双方的互动,形势的复杂程度可能呈指数级增长。同样的策略不可能适用于所有的对手,甚至对同一个对手,在不同的时机,也需要采取不同的策略。某个企业努力将生产效率提高了一倍,同时竞争对手提高了三倍,或者另辟蹊径抢走了市场,这样的例子是屡见不鲜的。 再次是执行,现在流行的说法是“执行至上”、“无缺陷执行”,但是经营过公司的人都知道,不同的人对“执行”的理解并不相同,同一个目标,不同方面的执行力度也是不同的。有时候需要“一鸣惊人”,确保产品在交付时没有任何缺陷,有时候又需要“先开火再瞄准”,一边运营一边改进。在这样复杂的局面下,“执行至上”或者“无缺陷执行”更像是动听的口号,却并不能产生现实的意义。 最后,卓越的公司,很少有始终“追求卓越”,从一而终地贯彻某些恒常不变法则的,它们的“卓越”,更像是一根链条——在每一个时期,在每一种环境下,采取了正确(或者说没太多错误)的策略。Intel在1985年决定全力进入周期较长但利润丰厚的微处理器领域,这是一个冒险的决定,可以肯定的是,当时的Intel并没有刻意追求“卓越”。这些环节前后相继,总的来看才能成就“卓越”,但由结果去倒推,断言甚至要求一直追求长期的“卓越”,则属于本末倒置了。 所以,我的观点是,在社会科学领域,尤其是在公司的经营管理上,很难说“太阳底下没有新鲜事”——每个阶段,每个方面,我们需要解决的问题都是新鲜的,正像之前在《收割庄稼V.S.砍伐大树》里面说的:解决这些问题并不像收割庄稼,而更像砍伐大树,而砍伐每一颗树时,都需要注意到它的形状和方向。如果一定要追求“没有新鲜事”的境界,找到什么恒常不变的法则,很可能只能“到此为止”:这些法则是每个阶段、每个方面、解决每个问题都必须遵循的一定步骤,却不是伟大公司的充分保证。当然,“成就伟大公司并没有什么恒常不变的法则”,倒真不是什么新鲜事。