Tag Archives: 思想

应届生求职和柠檬市场

  先说下什么是柠檬市场。其实就是指信息不对称的市场。即在市场中,卖方拥有对产品质量的信息比买方更多。在极端情况下,会逐渐驱逐质量高的产品,留下质量低的产品,最终使市场瓦解。比如作为典型案例的二手车市场。卖主对自己的车了解得一清二楚,但买家却不能在一时半会里知道车的质量,也信不过卖家的一家之言。于是就只愿意按市场上的平均质量出价,这样买到好的算赚了,买到差的也不至于亏太多。但是车的质量较好的卖家就不干了,凭啥我的车就只卖这点钱,于是就退出了市场。这样市场上车的质量降低,买家愿意出的钱也降低,就这样市场上的车越来越次,最终市场就会瓦解。

  那么,这和应届生求职有啥关系呢?现在大学生多如牛毛,能力也参差不齐。每到求职的季节,用人单位往往都会收到大量的简历。为了增加自己的面试机会,许多大学生会在简历里夸大自己的能力,掩盖自己的不足。如果只有少数人这么干,那么他们或许会占些便宜。但是当多数人发现这个现象时,为了让自己不吃亏,都开始给简历注水的时候,情况就不是这样了。这时,简历的可信度降低,用人单位为了降低筛选简历的工作压力,往往就会根据平均注水程度来筛选,一些比较热门的大公司还会用计算机来海选。这时候,少数诚实的学生进入好单位的机会就会减少,同样,单位招聘到诚实的,能力强的学生的概率也会减少。但和旧车市场不同,学生不能像卖车的那样不卖了,他们还得找工作,所以这个应届生就业市场还不会瓦解,但由于单位招聘到诚实而能力强的学生的概率减少了,他们愿意出的起薪也会降低(普遍反映现在大学生素质差),最终倒霉的还是大学生。

  另外,用人单位对于应届生来说信息的透明度也不够高。但相对来说,应届生要去了解用人单位还容易些,而且应届生就业市场是个买方市场,这个问题就没有那么明显。

  对于旧车市场,后来还是有解决方案。 比如通过保证金建立赔偿机制等等,加大对不诚信行为的处罚等,增大销售劣质的成本,使它们最终被驱逐出市场。说到底就是减少信息的不对称,让买家有更多的信心。那么对于应届生就业市场是否也能有类似的办法呢?

 

 

性格测试

  现在有各种各样的性格测试。有正规的,也有娱乐的。娱乐性的性格测试也就是娱乐而已,随便做做,做完了,不管结果如何看过就算。但是正规的测试就不一样了。正规的测试总有一定的目的,看测试结果的总是要把结果当回事的,不然也不用搞测试了。不过性格测试能否反映被测人真实的性格呢?

  或许有人不想让人知道自己的真实情况,估计在做题时制造某种想让别人知道的性格。会不会这样做取决于被测人对自己的道德要求(似乎这也是性格的一部分),这种情况另当别论。如果主观上并没有这种掩盖真实情况的想法,这个测试结果是否就真实呢?

  我做过几次性格测试,正规的。第一次是进大学的时候。在我看到结果时觉得,这个测试结果并不是很准确,难道那些专家都是忽悠人的?然后,我发现,这个测试结果实际上是介于真实情况和我理想中的自己之间。而我也想起来,在做测试的时候,我做的一些选择并不是反映真实的自己,虽然我并不想隐瞒什么。测试的结果评估本身没有问题。问题是在于做测试的人。或许很多人都是这样,在做这样的性格测试时,会下意识地选择一些理想中的自己的形象。这当然不是故意的,但是也会影响最后结果的准确性。在之后的测试中,我必须一直提醒自己,不要被这种下意识所影响,出来的结果总算比较可靠。

   性格测试算是心理学的一个应用吧。我觉得,心理学这样的学科介于人文学科和自然科学之间,虽然也有实验,也有基于数据的统计,但是对人的心理的描述和自然科学中对事物特性的描述还是有差别的。前者可能永远都无法精确地定量描述。况且,性格测试时,做题的人也就是被测试人,也可以说,是自己在测试自己。人的性格本身也会影响做题的方式,这就难免会受到干扰,而题目本身也可能影响被测试人的情绪,而无法准确客观地反映情况。

  不过性格测试的结果也不是完全无用。至少不会偏差太大。比如性格很外向的人无论如何都不会做出很内向的结果。只要不对数字进行定量的比较,这个结果也还是有参考价值的。

神和公理

  在那篇《从ruby的面向对象说起》的最后我说到了一些关于世界起源的问题。有人回复问神是谁创造的,这是个很有意思的问题。咱先回到ruby的世界。对于语言层,对于那些变量、常量等等符号而言,解释器就相当于是神。他操作了语言层的一切。而我们用语言写程序的时候一般是不会想到虚拟机的,而在代码里,无论如何,都无法超越虚拟机的限制,也是看不到“虚拟机”这个东西的。虚拟机所能做的就是语言所能做的极限。

  但是ruby虚拟机也是一个程序,它是运行在电脑硬件上的。一个二进制程序,哪怕是完全用汇编,甚至机器代码写的,直接操作存储器,寄存器,执行指令,操作外设,但是这些指令实际却是由CPU内部的微指令完成的。这些硬件的运算器,存储器的功能则是由更细化的触发器,门电路等等实现的。这条路甚至可以追溯到在硅锗上流动的电子。ruby解释器这个神可以说就是CPU,而CPU之上也还有许多层次。那么这个层次有没有头呢?在半导体这层,为什么他们可以单向导电?为什么会有放大效应?这是原子的物理特性决定的。这似乎就到头了因为还没法对物理特性的原因说什么。

  物理和其他科学都是人类发现的,或者是总结出来,通过实验验证,或者由现有的只是推演,都是在我们这个世界里进行的。或许就像前面所说的,无论我们对世界的认识增进多少,都只限于我们这个世界,而对于这个世界之外的世界我们是很难去认识的。就像Matrix里的人,根本不知道自己是在机器里。如果说我们这个世界存在某个“神”的话,这个“神”是否是创造出来的,是由谁创造的,这是我们没法知道的。

  咱都学过几何学。几何学的基础就是欧几里德的5个公理。从这5个公理可以推导出整个几何学体系。而这5个公理却是不能被证明的。或许对于几何学体系来说,这5个公理就是“神”。实际上,这些公理是建立在我们的意识深处的。关于点线面,我们都有一个自然而然的认识。或者说,这些公理既无法证明,也无须证明。对于那个可能存在的“神”也是如此,“神”在我们这个世界之上的,在我们这个世界的体系里,又如何能对上一层次的事物进行证明呢?还是不要去想太多关于“神”的来历的问题吧,或许就像公理,是无法证明也是无须证明的。

php的interface == 鸡肋?

话说当年,php5诞生的时候,向java,c++学了好多面向对象的语法元素。其中就有interface。在java圈子里,主流的观念是要面向接口编程而不是面向类编程,将接口与实现分离。记得在Spring in Action的例子里,要创建一个骑士对象,首先写一个Knight接口,里面定义了骑士可以做什么。具体怎么做则是在类KnightImpl里实现的。看上去似乎有一点麻烦。不过java大牛们教育我们,这是为了更好的灵活性。这样使用骑士的时候不用关心这是个什么样的骑士,而且可以在不修改代码,只修改工厂的配置文件,就可以用另一个实现来替换现有的实现。更寻常的说法是,比如Map接口,通常我们使用一个映射表的时候只要能够满足键值对应的操作就行。我们可以根据具体需要选用哈希表实现或是查找树实现,甚至自己定义一个存放在数据库中的Map。简单的说,接口定义了一组操作,实现了某个接口的对象也就能提供这个接口规定的一组操作。接口就像是一个协议或者说一个标准。这么说来,interface应该是一个好东西,似乎是面向接口编程所必不可少的,interface不就是接口的英文词么。那这篇文章的题目又是怎么回事呢?

还是拿例子说话。
interface Computer{
    function add($a, $b);
    function minus($a, $b);
….
}

class Mainframe implements Computer{
    function add($a, $b){
        //…
    }

    function minus($a, $b){
        //…
    }
}

class Calculator implements Computer{
    function add($a, $b){
        //…
    }

    function minus($a, $b){
        //…
    }
}

不管是大型机还是小计算器,都可以算加减法。想要算加法的时候只要拿一个实现了Computer接口的东西就行。比如
function doAdd(Computer $c, $a, $b){
    return $c->add($a, $b);
}
看起来不错。不过能算加减法的不仅仅是那些用电的东西。我国古代劳动人民的智慧结晶——算盘也能算加法。那么如果要拿算盘算加法,就要有一个算盘类。那这个算盘类该不该实现Computer接口呢?这个算盘似乎也算不上是一个计算机啊。或许该另外建立一个Calculatable的接口,让计算机和算盘都去实现这个接口,这样似乎就不错了。有时候我们只需要用到Calculatable的一部分功能。比如Calculatable定义了基本的加减乘除,但我们买菜算账的时候通常只需要加法。这时候如果用Calculatable的话就需要接受一些无用的东西。再用一个php的SPL里的例子。SPL里有一个ArrayAccess接口,可以让对象像数组一样用下标去访问。这是一个很有意思的语法糖。不过有时候只需要按下标读功能就可以了,但是为了要满足规定,还是要把ArrayAccess接口的所有方法都实现一遍,于是就要写好几个throw new Exception(‘xxx is not writable’);之类的东西。这实在有点罗嗦。

为什么不换一个写法呢?扔掉那些interface,直接写
class Mainframe{
    function add($a, $b){
        //…
    }

    function minus($a, $b){
        //…
    }
}

class Calculator{
    function add($a, $b){
        //…
    }

    function minus($a, $b){
        //…
    }
}

class Abacus{
    function add($a, $b){
        //…
    }

    function minus($a, $b){
        //…
    }
}
在需要计算的时候,也不用限定一定要是Computer,把对象直接扔过去。
function doAdd($c, $a, $b){
    return $c->add($a, $b);
}

如果在试图在一个不能算加法的东西比如易拉罐上执行add,解释器自然会报错。也就是说,只有满足接口的对象才能够正常运行。你看,不用interface一样可以实现面向接口编程,而且更加灵活。

不用interface搞面向接口编程这听起来还是有点玄乎。毕竟这个interface就是接口的英文单词啊。好吧,interface确实是英文单词,但并不代表interface这个语法元素就等价于接口。就好像把狗的尾巴也叫做腿,这狗也不是就有了五条腿。interface只是叫了这个名字而已。当然,interface在一定程度上也为面向接口编程提供了方便,比如提供了编译期的检查。而且对于强类型语言来说,这样的语法元素是很重要的,比如java。而对于弱类型语言,比如php,却不是必须的。而对于一些更动态的语言,比如python,ruby来说,更是很难相容的。

 

从ruby的面向对象说起

ruby是一个完全面向对象的语言。在许多其他语言里不是对象的东西在ruby里也都是对象,比如整数。更神奇的是,类也是对象。为什么说神奇呢?看一下下面的代码:

class A
end
puts A.class

结果是Class。可以看到,类A 也是一个对象,它是类Class的实例。接着看

puts Class.class

原来Class是Class类自己的实例。

puts Class.superclass
puts Module.superclass
puts Object.superclass
puts Object.class

类Class的爸爸是Module,Module的爸爸是Object。而Object是所有类的祖宗。但是类Object还是类Class的实例。很神奇吧。

我们知道,对象是类的实例,是由类创建的。而在ruby中,类本身也是一个对象,这就形成了一种鸡生蛋蛋生鸡的循环。似乎这是周而复始,无穷无尽的,就像下面那幅埃舍尔的名画

这两个相互描绘的手就像是ruby中的类和对象。两只手相互描绘在现实世界里是不可能的。那么在ruby中,又是如何打破这个僵局的呢?其实很简单,这两只相互描绘的手只是一幅画而已。而让两只手相互描绘则是画家。在画面内部无法解决的矛盾跳到画面外面就很简单了。在ruby里也是如此。在语言层面,类和对象似乎也像是这两只相互描绘的手,但不要忘了,还有一个ruby虚拟机的存在。一切的对象都是由它创建,而语言里的ClassName.new并没有直接创建对象。在一切的开始,虚拟机创建了Class,Module,Object,之后,这三个东西就可以滋生出整个对象世界。虚拟机就像是至高无上的神,创建了整个世界。但是在一个ruby代码的世界里,能看到的却只有对象,而不能直接看到虚拟机的存在。我们可以写完全面向对象的代码,而不用去操心这些对象究竟是怎么来的。

回到现实世界。不知道大家有没有想过我们的现实世界是怎么来的。根据被普遍接受的物质不灭理论,物质不会消失,也不会凭空出现。那么这些物质最初又是怎么来的呢?话说我们的宇宙是由一个很小的核心爆炸,不断膨胀而产生的,又话说宇宙在膨胀到极限后又会重新收缩,又变回一个很小的核心,周而复始。那么这一切又是如何开始的呢?在这个宇宙之外又是什么样呢?如果这些问题存在答案的话,要么接受一个创造这一切的“神”的存在,要么就只能说,物质是无须创造而自然存在的。

论霸天虎之失败

  星期二公司里组团去看变形金刚。由于之前没有抱太大的希望,所以后来也没失望。电影是典型的美国大片,而且还是植入式广告的典型。下面是一些感想。

  电影里霸天虎一方共有8个机器人,汽车人一方只有5个,无论从数量上还是力量上从处于劣势。但是最后汽车人一方却取得了最终的胜利。原因有以下几点:

  1、霸天虎一方过早的暴露了目标。毒蝎没事去袭击什么美军基地做啥,暴露了目标,引起了地球人的警觉。在随后的战斗中就有了准备(比如知道了机器人的弱点)。

  2、汽车人代表的是最广大人民群众的利益。由于霸天虎的行动威胁到了地球人的生存,因此汽车人和地球人为了公共的目标联合起来,使得霸天虎陷入到了人民战争的汪洋大海之中。其中有3个?是倒在了地球人的枪炮下。

  3、威震天做为恶势力的首领,恶的还不够。要是他不是用言语来威胁Sam这个小孩,而是直接一枪轰死把方块抢过来,后面的戏也就演不下去了。尤其是最后,威震天实在是死得太窝囊了。

  4、机器人的战斗力并没有绝对的优势。一个战斗小队就可以解决掉几个霸天虎,那么全人类的战斗力量,就算再来10个霸天虎也不成问题。你想,5个常任理事国有多少atombomb啊,就算是常规武器,美军的贫铀弹也足够把霸天虎烧化了。

  5、霸天虎一方总是各自为战,没怎么看到有协同作战的。其结果就是被各个击破。

 

说说trackback

  trackback是blog的一个重要功能,一个没有trackback的blog都不能算是一个完整意义上的blog。trackback的功能是,当你看到别人的文章,有一大堆话想说,可以放在自己的blog上写,同时也能够让对方知道。trackback使blog之间可以互通, 不过这个看起来不错的功能似乎用的人不太多(也可能是中国特色?)。或许是trackback用起来不太方便吧。要先找出对方的trackback地址,复制下来,然后加到自己日志的trackback里去。尤其是第一步,往往需要点好几下鼠标。那么有没有什么更好的办法呢?或者可以像rss feed自动发现那样,加入到日志页的meta段里去,这样不需要找trackback地址,只需要直接复制日志地址就可以,或者仿照emule,弄一个trackback://的协议,通过浏览器插件,点击这个地址就能自动跳到自己blog的后台。但是无论哪种方法,都需要有一个统一的标准,才能够真正实现,这个看上去就比较遥远了。那么现阶段,除了在一个BSP内部可以动一点手脚,把trackback弄得方便一点以外,似乎也只能如此了?

 

从MSNSpace开始说

  现在的BSP用户最多的就是MSNSpace和QZone(虽然这个不怎么能算blog)了。自从MSNSpace变成Live之后,用户就开始怨声载道。说实话,原来的MSNSpace还是不错的,只是我不喜欢它千篇一律的样子。但后来的Live顶上一个大广告不说,整体设计没原来精致,速度也变得爆慢。但很奇怪的是,许多用户虽然对Space很不满,但还是没有转到其他BSP。了解之下发现,许多人根本不知道MSNSpace之外还有其他BSP,顶多知道一个新浪博客(用space的一般不会去用QZone)。

   互联网的圈子其实不大。圈子里发生些什么事我们这些关注互联网人都会知道。而圈外人就不同了,他们不会主动去关心互联网的变动。许多人对圈子里许多很“有名”的网站都一无所知。比如SNS的We@link,垂直搜索的jobui等等。我的很多朋友都是在我推荐了以后才知道有这些。他们是既然他们对此一无所知,就很难成为用户的。而这些人恰恰占了大多数。web2.0讲的是草根,长尾效应。如果不能抓住这些广大的潜在用户,又如何能发挥web2.0的威力呢?那些老牌网站依托积累的名声,以及强大的宣传力量,却能够把推广的触手伸到很远。从这方面说,老牌网站与新兴的web2.0网站在宣传方面的较量绝对是一场不对称的战争。

  前一阵5q、校内、占座都到各个学校做推广。这些都是社区类网站,也算是web2.0吧。看起来也花了不少成本。但效果却很有限。喜欢玩社区的
同学们还是去天涯、猫扑。其实天涯、百度知道、土豆之类的似乎也并没有做多少推广,也不算什么新的概念(百度知道很像n年前的凯利灵通),但是同样赢得了
大量的用户。看来money也不是决定性的。

  来得早了不如来得巧了。在市场刚开始孕育的时候,进入得早并不能形成多少壁垒。比如BSP。Blogcn,
Blogchina是最早的几家,当初也积累了不少用户。但和2005、2006年,博客蓬勃发展的年代相比,那点用户又是微不足道的。在那段时间里,能
抓住最多的用户的才是推广最成功的。当然来得早还是非常重要的。在快速发展期占据优势以后,后来者再要来竞争难度就很大了。因此,后来亿唐搞一个叫ET的IM,尽管它可以兼容MSN,功能也不差,但还是没多少人去用。

   

失去的链接

  人工智能里有一个语义网的概念。比如下面这个图是一个简单的语义网。

 

 

  语义网在人工智能中应用这里就不说了,但这个语义网也在一定程度上反映了人类思维的方式。比如 ,对于歼10,对它的基本认识是这是一种国产的战斗机;而战斗机是一种军用飞机;飞机有翅膀,也就是机翼;而飞机是一种人造的能飞的机器。如果有一个从没见过飞机的人,我们对他说了歼10是一种国产的战斗机,一种用来打仗的飞机,他一定还是迷迷糊糊。因为在告诉他这些之后,他的语义网中从“飞机”这个词出发的链是没有的。也就是说,他不了解“飞机”是个什么东西,也就无法认识战斗机,也就无法认识歼10。

  我们平时经常会碰到这种情况:比如在教一个不怎么会电脑的人用某个软件,他经常会提出一些在我们看来是很低级很莫名其妙的问题;而我们的讲解也很难是他明白过来。对照上面的例子,就会知道,这是因为他的语义网中少了一些必要的节点和链接,这就使得一些在我们看来是天经地义的事情对他们来说却是一无所知的。很多时候,这些对我们来说是“天经地义”的事情让我们我们忘了我们是如何一步步理解这些知识的。这时候,我们往往就会觉得对方怎么就那么不开窍呢?事实上,这个时候需要我们更耐心地去了解他究竟少了哪些节点和链接,在逐步补上后,相信一个正常人是能够理解的。当然,有时候如果对方缺少的背景知识太多的话就会费不少时间和精力。当累计到一定程度的时候就教不了了。比如,没法在一星期内教会一个从没见过电脑的人用C语言写程序。

白马非马

  战国的时候有一位公孙龙先生,提出了这么一个观点,说“白马非马”。我们的教科书上说那叫诡辩,白马明明也是马么。那么咱先写个程序来验证一下:

python程序:
class Horse:
    pass

class WhiteHorse(Horse):
    pass

print WhiteHorse == Horse

结果是:
False

再用ruby写一个:
class Horse
end

class WhiteHorse < Horse
end

puts Horse == WhiteHorse

结果是:
false

  你看,白马还真就不是马。

  回头来看看公孙龙先生是怎么解释的:“马者,所以命形也;白者,所以命色也。命色者非命形也,故曰:白马非马。”“求‘马’,‘黄’‘黑’马皆可致,求‘白马’,‘黄’‘黑’马不可致。”“马固有色,故有白马。使马无色,有马如己耳。安取白马?故白者,非马也。白马,马与白也,白与马也。故曰:白马非马也。”马和白马不是同一个概念,所以白马不是马。我们的教科书说这是否认种概念包含于其类概念外延之中的逻辑错误,也就是说,马包含白马,抽象概念包括具体概念。所以说,白马是马。这似乎是不错的。那前面的程序的结果又明明白白的说,白马不是马,也就是说,抽象概念和具体概念是不相等的。这应该也是对的。那问题处在了哪里呢?实际上,白马是不是马取决于对“是”的理解。在E文里,有两种不同的写法:is a和is the。a white horse is a horse是对的,the “white horse” is the “horse”是错的。结合前面的程序,这就很明显了。说白马是马的意思是,白马是马的子类。说“白马不是“马的意思是,“白马”和“马”是不同的实体。而我们之所以会对“白马非马”产生争论就是因为这个“非”或者“是”有不同的意义。

  不是所有的语言都能写出上面的程序的。在python和ruby中,类本身也是对象,所以才可以进行比较。在面向对象语言中,类和对象都是基本的概念。类是对象的描述,对象是类的实例。比如,可以定义一个马的类,其中有一个属性是颜色,然后建立一个马的对象,把它的颜色属性设为白色,这就是白马了。但是,白马也有许多,刘备的的卢和唐僧的白龙马是不一样的。所以,可以建立一个白马的类,让它继承马这个基类。它的所有实例对象的颜色属性都是白色。

  什么时候需要建立像白马那样的类呢?有种说法是,任何抽象的描述都是类,具体的东西是对象。那抽象和具体的界限是什么呢?比如在M$的VS的GUI程序里,通常每一个窗体都有一个自己的类,虽然通常他们都只有一个实例,但也有有许多实例的窗体,比如MDI界面种的子窗体。在网上书店里,同一版的书被认为是同一本书例如,每一本1991年版第一次印刷的《三国演义》都是一样的。但在图书馆管理系统中就需要区分每一本书。但不管在网上书店还是图书馆管理系统,都不会去建立“1991年版第一次印刷的《三国演义》”这样的类,虽然这仍然可以说是一个抽象的概念。事实上,如果真的为每一个抽象概念都建立一个类的话,类的数量就会达到无法维护的地步。而我们往往也并不需要在实际应用中建立如此细致的抽象概念,比如在网上书店中,抽象概念只需要具体到“这是一本书”就可以了。其实在日常也是如此。

  现代的面向对象理论认为,面向对象编程不是面向类编程,而应该是面向接口编程。一个对象是什么取决于它实现的接口,也就是它能做什么。如果在某个环境中,一个能象鸭子那样摇摇摆摆得走,并且嘎嘎叫的就是一只鸭子,那么哪怕它只是个上发条的玩具,在这个只关心这两电环境中,它也就是一个真的鸭子。这就是所谓的duck typing。这里的“接口”并不等同于java等语言中的interface,interface更像是一个缩水的类。比如,只要有一个bark方法的对象就是能叫唤的东西,这个back方法本身就是一个接口。而类只是类型的一种实现方式,可以说是对象的一个模板,用来方便得建立一些具有共性的对象。

  回到开头的程序。我们是不是需要建立像“白马”这样的类呢?这是要看具体情况的。比如开始我们只有几匹马,客户也不挑剔马的颜色,那么就没有这个必要。但是如果有了很多喜欢白马的公主或是喜欢黑马的,为了能更方便的满足他们的需求,就有可能需要建立“白马”类来更方便得创建白马。但是在许多编程语言中,“类”都是比较硬的。改变一个对象的类经常会牵一发而动全身,需要修改许多地方的代码。所以就有了设计模式,让这些改动变得容易一点。而在动态语言中,并不在编译期检查对象的类型,只要对象有这个方法或属性,就可以访问。从这方面说,动态语言更接近于真正的面向对象编程,而不是面向类编程。