技能点与职业选择

| Comments

暑期实习的时候知道了业务这个概念,作为一个比较单纯的码农,以前从没想过业务和技术的关系,一心的想法就是只要积累经验、多学东西,总是好的,然而随着自己经历的增长,对这些问题的认识也逐渐变得多元化。就比如业务这个问题,作为一个程序员,毕业后比较常规的思路就是进入一些big name的公司,诸如BAT之流,在旁人看来是一个好的开局,但个中滋味冷暖自知。虽然在大公司可以增加自己的简历分量、标准化流程知识等等,但是还有一个不可忽略的问题就是螺丝钉化。

一个非常常见的现象就是,在大公司里,每个人可以很高效的完成业务的编写,为公司创造巨大价值,但这些都是依附于公司已经存在的巨量基础之上的。大公司在给你提供了一个非常好的施展才能的平台的同时,也同样会限制你向更高的平台去进步。虽然这并不一定是公司的刻意而为之,但却会在很多方面让员工自然而然的走入这个怪圈:

其一,巨大存量并且十分好用的工具集,这几乎是大公司标配,有一整套人家已经为你设计好的非常好用的工具,让你能够轻松解决很多复杂问题,同时产生了“我很牛逼”的错误,殊不知其实是前人栽树后人乘凉的正常现象,也许换一个比你稍笨的人努努力同样可以搞定。如此,很多人就会失去了继续钻研的动力:一来性价比较低,因为从“用轮子”转向“造轮子”的门槛实在不低;二来公司也并不需要你这样,因为已经有大牛把造轮子的坑占了,并且占得不错,因而公司也就缺乏主动为你提供资源试错的根本动力。

其二,就是技能点的选择。总有那么一些人是不甘平庸的,想做出成绩,无论是处于功利还是兴趣,都会利用自己工作之外的20%时间进行技能加点。但是问题在于这些加点很难与公司对你的期望相契合。换个角度说,就是选择技能点的眼光是非常重要的。最近和别人聊天也聊到了这个,结论就是,努力就好,能不能碰上要看运气了。这也是“多学点东西总没有坏处”的基本出发点。从我个人的经历来看,之前非常喜欢尝试各种没有用过的东西,结果就是流行的语言几乎都会,但是并没有哪一个是从一而终的。现在看来,这虽然并没有什么问题(毕竟眼界宽了对打开思路是有好处的),但是在职业上,毕竟还是单一方向上的专注才能给自己带来职业和收入上的提升。因此,之后在进入职场后应该有意识的选择自己未来将专一的方向。

总结一下,算是给自己马上到来的职业生涯提个醒:

  • 尽快为自己找一个可以专注并前景还不错的领域;
  • 不要被永远做不完的业务缠得忘记思考加点的方向。

创造力笔记

| Comments

坐在去深圳的火车上,翻着MiPad里面的zguide,在不断吸取新的知识的同时,也在不断赞叹作者对于编程哲学的理解。作为一名从业30余年(书中作者自述)老程序员,作者不仅试图通过这篇大作教会我们使用zeromq,更试图将他多年沉淀下来的思考教给我们。这不禁让我想起小时候的课文:授之以鱼不如授之以渔。也正是作者这样的态度,让我对这本书格外的感兴趣,即便是阅读英文,也丝毫没有困意。

于是乎,看着看着,就勾起了我对一个老问题的思考。为什么这些大牛们能够想到做这么一个非常cool的东西呢,为什么我就不会想到做呢?就算鄙人暂时水平不够,但是至少也应该在生命中的某个时刻,有这样的灵感来想到做一个cool一点的东西吧。想想自己虽然不算是计算机天才,但是也是名牌大学出来的“优秀”学生,每想及此,就有那么些许的不甘心与气馁。不过好在自己总是有些阿Q精神和积极向上的心态,不至于精神出问题。

经过了小小思索,就产生了些感悟。其实并不是自己没有灵感,而是自己不善于抓住灵感,以及自己没有足够的执行力来保存灵感。为什么这么说呢?zguide作者在谈及zeromq的开发初衷时,谈的最多的就是大软件中关于messaging的复杂和高成本,并且许多项目处于各种原因,都会在TCP的基础上开发出专属自己的messaging模块,而这些模块大部分都是很类似的,即大家都在重复发明轮子。于是乎,作者经过自己的思考和抽象,写出了zeromq这个专门负责messaging的高效、轻便、嵌入式库,所谓嵌入是指能够轻易嵌入其他项目中,成为一个好用的“轮子”。

从这个过程中,我们不难看出,其实作者的灵感也不是凭空想出来的,而是从他工作中的实际例子转化而来。而且是程序员的最朴素的思想——不做重复的工作。那么反省自己作为程序员难道就没有这样的时刻?当然有,只不过时之前根本没有这样的意识,来保留自己的灵感。当然,“没有意识”这样的结论过于苍白无力,其实内在还有更多的原因,比如:惰性、“工作”的忙碌等,但是这些统统不能成为自己忽略灵感的理由(等同于碌碌无为的理由)。

今后

于是,为了不让以后的自己遗憾,给自己立下如下要求(建议):

  • 经常总结手头的工作,寻找灵感
  • 每每想到一个IDEA时,要尽快落笔,记之
  • 经常回顾自己的想法,尝试将他们付诸实施
  • 经常与同伴讨论自己的想法,期待思想的共鸣

暂时想到这些,继续坐火车,to be continued…

虚函数与接口

| Comments

最近又有点空,翻出了《Linux多线程服务端编程:使用muduo C++网络库》随便看看,又看到了一些而之前没有注意过的问题,这要从我之前写Java的时候,一直存在的一个疑问开始说起。

在Java多线程中,如果要是实现一个线程,有两种方式:

  • 继承自Thread类,重载Thread类中的run()方法
  • 使用一个Runnable的对象new一个Thread,直接调用start()启动线程

于是,问题来了:

为什么Java要设计这两种方式?在什么场景下会有不同?

对于以上这个问题,这次在书中,我看到了一定的答案。

库的接口设计

要回答上面的问题,首先要从库的接口设计说起。库之所以提供接口,就是希望用户逻辑能够以某种方式被注入到库的逻辑中,因此,合理的设计接口可以让这种“注入”变得更加自然易用。传统上,库的接口通过虚函数的形式给出。库的用户只需要重在这些虚函数,就将业务逻辑注入到库中,达到利用库的目的。

这对于习惯使用面向对象的开发人员来说,是非常常规的思路,即使用了“多态”。但是继承本身就是一种非常强的耦合,如果现在的需求在未来需要改变,那么很可能面临着一种牵一发动全身的窘境。

摆脱继承和虚函数

如果对这个问题稍加分析,不难看出,其实我们需要的是“多态”,虚函数仅仅是一种手段。更深一点说,“多态”代表着一种动态绑定的手法,在不同情况下,需要绑定到不同的业务逻辑中。那么问题来了,我们能不能在不使用继承的同时,实现我们需要的“多态”功能呢。下面就要提到我们熟悉的另一个概念接口(interface)。(要注意,这里的接口和库的接口是两个概念,不可混淆)

熟悉Java的人都知道,接口是一种非常常用的手段,用来描述一个类的对外表现,而忽略它到底是什么,也不管这个类是如何实现这个接口的。在Java8中,由于闭包概念的引入,将接口和闭包组合在一起,又形成只有在函数编程中才能看到的强大的模块封装的效果。

下面用一个具体点的例子来说明:

传统方法中,我们可以用如下方法,实现一个线程:

1
2
3
4
5
6
7
8
9
10
11
public class ThreadA extends Thread {
    private Data data;

    public void run() {
        // do something with data
    }
}

// usage code
ThreadA threadA = new ThreadA();
threadA.start();

而如果我们使用接口+闭包的话,就可以用下面的方式:

1
2
3
4
5
6
7
8
9
// usage code
Data data = new Data();
Thread threadB = new Thread(new Runnable() {
    @Override
    public void run() {
        // do something with data
    }
});
threadB.start();

从上面的例子,我们可以看出,对于Thread这样一个库,它只需要一个实现了Runnalbe接口的类,就可以了,所以我们不再需要专门写一个类,去覆写Thread的run方法。同时,按照传统的做法,我们需要一个专门的类来同时实现Runnable接口,又包含一个Data型的对象,来实现业务逻辑。有了闭包之后,我们的编码就变得灵活了许多,我们不在需要把Datarun方法写在一个类里面,而是可以随这个具体业务的需求,把它们灵活的组合在一起,也就是说它们完全没有关系。

这样一来,我们的程序就可以很“轻”,我们可以轻而易举的重构任何一个组件,而不需要付出高昂的代价。这样我想起了ruby中的duck type,和go中的interface。二者都是强调的接口的灵活性。“duck type”的哲学是“像鸭子的东西就是鸭子”;而go的interface则更直接,只要符合一个interface的描述,一个类就是某个interface,而不需要像Java一样使用implements关键字指定。

小结

在Java中,这两种方式看似稀松平常,但是背后却是两种不同的设计思想:一种是以继承的方式将用户的逻辑注入库中,比较重一些;另一种则是以接口(或者说duck type、抑或tag)的形式将用户的逻辑注入库中,比较轻一些。无论是哪种,都是在软件发展史上经过前人的思考,并最终沉淀下来的经典方式。只不过是随着软件行业的发展,越来越多的需求在变化,因此,我们需要越来越灵活的编码方式来帮助我们开发罢了。

最后引用人家的一句话做结:

代码重用不是目的,目的是减少重复劳动、提高工作效率

2014 Review

| Comments

2014年,总体来说有点收获,也虚耗了不少时光。放个假回来,2个月就木有了。

写了三个月的C#,那是在学校旁边的微软,一边实验室一边偷偷的实习,赚点生活费,收获不多,最多就是对C#的重新认识,不得不说,C#确实优秀,谈得上是最优秀的静态语言。了解了什么事MVVM,初识了异步的概念(在这之前自己那点多线程的知识是在捉急啊)。

紧接着就是去了某游戏公司专心写了两个月的Lua,感觉收获颇丰,初识了什么叫函数式编程。在鑫哥的影响下,成为了多看的忠实粉丝,看了大半本《ruby元编程》,又看了松本行弘大神的《代码的未来》,学到了很多之前在Java重OO的影响下不会想象的编程原理。这两个月虽然加班多,但是收获多、快乐更多。

之后就回到了学校开始了伺候老板的生活,顺着之前的惯性,上了一半的cousera上的Programming Language,很遗憾,最后在毕业的压力下无耻的半途而退了。。。不过还是学到了不少东西,写了两个月的SML,对程序语言的一些知识有了了解,又开了眼界。同时跟我们屋的大神讨论了windows上m:n的异步调用实现,本想利用业余时间写个雏形练练手,最后还是在毕业的压力下无耻的暂停了,寒假一定要补上!