[知乎]当你读代码时在读什么?

谢邀

这其实是一个很有意思的问题,于是:我首先去读了一下题主贴出的那段程序,并且“同时注意反省自己在思考些什么”。

所以,当我发现题主现在又删除了那段代码的时候,感觉还是挺可惜的。

仔细回想一下,首先考虑的是:“这段代码是怎么执行的?”,为了得到答案,我会看变量名,然后看看这个变量是不是被用到,在哪里被用到的。

一开始,是一行一行的往下看,脑子里像一个暂存器,想着变量会怎么变化。然后,难免会发现不明白的问题,再上上下下的看。

如果还是不容易理解,就会试着折叠一些段落,看看能不能理解主要的路线。

有时候,会有些怀疑:这个代码没有bug吗?他的意思真的是这样吗?

搞不好,还是得放到IDE里,去尝试执行一下,确认看看:是不是真的没有bug。

如果要总结为一句话,那就是:“阅读代码,去理解这些代码究竟会做些什么事情,以及猜想代码的作者写出这些代码,打算做些什么事情。

是的,代码会做什么,与作者打算做什么,可能是不一致的。

[知乎]三层构架和 MVC 不同吗?

MVC是横向分工;三层架构,是纵向分层。

在大多数架构图中,MVC被画成三角形,View是使用者能够看到并操作的层(可能是Web页面,也可能是GUI),Controller是处理各种操作请求的核心,Model是用于保存各种数据,并且会影响View的显示结果。

而三层架构,通常会被画成上中下三层,上层是前端;中层是业务逻辑;底层是数据存储。

从这个介绍来看,MVC与三层架构的确似乎存在对应关系。在很多简单项目中,我们可以将业务逻辑写在Controller里,而保存数据的逻辑也无非是数据库的表与Mode的简单对应而已。

但是,随着项目越来越复杂,我们发现业务逻辑已经非常复杂,把所有的代码写在Controller里,是一种糟糕的实践,因此:我们将关键的业务逻辑抽取出来,形成一个独立的业务逻辑层。而且,这一层往往以某种Service API的方式,被Controller调用。

另一方面,我们也发现数据越来越多,越来越大,越来越复杂。简单的ORM已经不够用了,必须编写更加独立、通用的数据访问层。这时候,就需要改写原来的Model,对于上层应用而言,使用方式保持不变。

还有一些重要的技术发展,产生在前端领域,尤其是We前端的JS框架、CSS、HTML5等等技术,使得在前端,出现了完整的“前端MVC”,或者现在叫“前端MVVM”了。

大概是这么一个发展的路径,要详细谈的话,就太多了。

加班,该死的加班!

说实话,我原本没有写系列文章的打算的。

但是,今天我正好看到了两条条微博:

@玄了个澄的:在微信里看了@Fenng关于加班的言论,很想再听听@左耳朵耗子的评论(看热闹不嫌事大)
@左耳朵耗子:当然错了,不然大家怎么看我和大辉的热闹?! 文中提到了加班和效率,文中的观点是错的。我改天写一篇。
于是我又去看了Fenng的那篇微信文章。虽然文字有些散乱,不过大概的意思还是能看明白的,为了精简我的文章,就不再一一点评别人的言论了,进入正题。
1、加班绝不该是常态,如果有一个紧急的活,要怎么怎么快速的干完,或者有某个紧急的Bug,必须尽快修复,没话说,必须加班。但是,如果有一家公司,每一个人,每一天,都在加班,不是一个小时两个小时的加,而是11、12点下班为常态,那么这个公司一定不正常。
2、无论是资本主义国家还是社会主义国家,都存在劳动法,都会保障劳动者的基本权利。如果有老板跟你说:我们是创业公司,所以我们自然天天都要加班。那么,这种老板,就是在说:“白马非马,所以创业公司不是普通的需要遵守劳动法的公司。”
3、与Fenng的意见类似,我可以列出最厌恶的加班情况排行榜
    第一名:加班给老板看,而且,居然老板还在津津有味的看着。只要手下还在公司里呆着,老板就心满意足。这种没有任何产出的加班,还有些团队因此自诩为“创业氛围浓厚”,我就真的没法明白了。
    第二名:6点以后开会,老板的想法其实很实际。白天你们当然要实实在在的干活,晚上开点会,拖点时间也不算啥。正好可以把明天要干的活,先讨论清楚。这种思维的老板,我称之为鸡贼。
    第三名:将加班标榜为企业文化,以至于没人敢不加班。日本这种变态国家,将这一点发挥到淋漓尽致。即使不加班,都要在外面喝点酒再回家,否则没脸见老婆。
    第四名:效率低下导致加班,每天都有干不完的活,而且每天都只能加班加点的干活。其实那点活如果是安排得妥当,少出些纰漏,早就干完了。一将无能,累死三军。说的就是这种缺乏管理导致的加班。
    第五名:不切实际的进度计划,导致加班。或者是项目组成员的过度乐观估计,也可能是老板想要榨干员工的每一滴精血,总之,这种事情也挺常见的。
    第六名:正好兴致上来了,这个活不干完,我也睡不着觉。很多热爱编程的家伙,可能会体会过这种加班,甚至对这种加班还念念不忘,认为是难得的人生经历与宝贵的生活财富。
4、总的态度
前面的三种加班,我极度厌恶,这样的公司,我能逃就逃。第四种,是可以通过改进管理来解决的。第五种,这种事情成王败寇很难说对错的。第六种,如果是年轻人,倒不妨多体会几次,也是一种历练。
5、多说一句,关于加班费的问题,由于程序员的效率差别极大,如果加班都有加班费,老板就无法将必须的加班和为了领加班费而混加班区分出来,从这一点来说,我倒是同意不给加班费的做法。但是,相应,不给加班费却又要求员工“自愿加班”,那就有些…了。
btw:这个标题不错,也许可以继续写其他的一些《该死的XXX》

进度,该死的进度!

早在2005年,我在ITEye连载了一个系列文章,当时的标题起得很大气《定论——软件开发的方法论探讨》,在写完1~7之后,我突然偃旗息鼓,写下了最后一篇(完)。

有兴趣的朋友,不妨一读:定论——软件开发的方法论探讨(1)(2)(3)(4)(5)(6)(7)(完)

当年的这篇文章,也是有感而发,最大的困扰,来自于软件开发的进度,难以估算。按照传统的软件工程的做法,大多数的开发进度,都会不断延期,不仅仅是一个给定范围的开发任务,会出现估算偏差,更加糟糕的是:在一个不断延期的开发过程中,还会有新的功能需求,不断加入。

后来,软件大师们,发明了一个新的办法:既然不能指哪打哪,那就打哪指哪。既然不能在给定的时间内完成任务,那么就反过来画个圈,这个阶段咱们完成的任务,就是咱们的阶段目标。

在给这种“掩耳盗铃”开发模式,起了一个漂亮的名字之后,这种敏捷开发的方式,在全世界流行起来了!

但是,真正“精明”的老板,是不会上当的!在敏捷开发模式下,开发人员永远是无可指责的!所有的开发进度,开发人员拥有无可争辩的主导权:“每一个Story的开发工作量都已经被估算出来了,产品经理能够选择的,仅仅是在下个阶段先实现哪几个Story而已。”

老板们通常会说:“三个月内,我要看到这个上线,不要告诉我不可能!公司的信条是:没有借口!”

进度,有时候是一个刚性需求,比如说:双11促销配套网站,决不能在11月12日才上线!

另外还有一些原因,导致了老板的无法信任不再估算进度的敏捷开发方法。

1. 听说,程序员之间的开发效率,高手和低手之间,甚至可以相差100倍。你如何才能让老板相信,你已经竭尽全力了呢?(他已经发现,你一到6点就下班了)

2. 软件开发的过程,总是难以一帆风顺,老板就会深度怀疑,明明你们的开发是可以提前完成的(如果不出这个、那个的bug的话)。

3. 当然,过度乐观的程序员,给自己挖了深坑,也是可能出现的情况之一。

4. 很多老板有一种行之有效的方法:先给程序员们,定一个无法完成的进度,然后,程序员会出于内心的愧疚,而努力熬夜加班,最终:进度虽然也会拖延,但是却常常能令老板偷笑。

根本的原因在于,即使是经验丰富的开发者,面对复杂的项目,也难以准确的估算进度,更不要说对于软件开发一无所知的老板了。一方面,老板不知道这活需要干多久,另一方面,手下的开发者,又不能做出靠谱的估算。一个不甘被愚弄的老板,只剩下一个选择:督促开发,尽力赶工。(只有这帮家伙,真正干到精疲力竭,我才能够相信,他们没法更快了。)

正好今天在微博上看到两个段子,虽然都是在说产品经理的,但其实是在说软件开发进度的。

一位艺术青年去拜访大师在:“为什么我专心画一幅画,只消一周功夫,可卖掉它却要整整一年?”“请你倒过来试试。你花一年功夫画一幅画,兴许一周就能卖掉。”大师说。青年照办,第二个月就因为进度太慢被产品经理捅死了……(via @顾扯淡 )「段子」

天黑请闭眼,rd睁眼,rd开发,rd闭眼,qa测试,qa找rd的bug,qa闭眼,天亮了,pm死了

因为开发进度,大多数的公司内部,都存在各种紧张的关系和激烈的争吵。这几乎算是永恒的矛盾了。

 

回到我写的那篇文章,当年的《定论》之所以没有写完,当年我是这么说的:“要能够检验软件开发方法的优劣,必须基于对于软件开发本质的正确认识,这样才能量化两个因素:软件需求的复杂程度以及软件开发的实际工作量。”

但是,在当时,我并没有找到这样的方法,而现在,我猜测Trello也许是解开这一难题的关键一环。由于我们目前还在各种尝试的阶段,还难以提出太多明确的观点,简单随意的先抛出一些:

  • 软件开发的本质,是经验复用+智力探索,经验丰富与脑子好用,同等重要
  • 软件开发管理的主要目的,是减少团队配合中的各种浪费与等待时间,以达到开发效率最大化
  • 基于Trello的看板拖拽操作,有可能真正将开发过程中的实际工作情况,记录下来,而这是一切改进的前提
  • 进度估算,是一个伴随开发过程同时进行的行为,而不仅仅是开发工作的前置阶段。但是,不能因为估算困难,就放弃估算
  • 也许,我们能够找到一个更加直观与科学的办法,既让开发者感到舒适,又让老板感到满意

先告一段落,等回头想得更加清楚一些时,再继续这个话题。

技术选型:效率至上与实用至上

当我们面对一个架构方面的决策时,通常会处于某种两难的境地,选A还是选B,”市面上”同时存在各种丰富多彩的说法,单独看去,往往各自言之成理,如果仔细对比,又往往莫衷一是。

在我目前所就职的公司,前段时间我刚刚做了一个架构决策:原来的系统,开发人员采用PHP编写后台执行的进程脚本,处理各种需要高性能的业务;另外,他们又用CoffeeScript编写了一个Web控制台,以配置、管理和监控这个系统。这令我感觉相当的怪异,因此我决定,后台关键进程,重新用nodejs编写,而Web控制台,则重新用PHP编写。

这个决策背后的逻辑是:一个复杂的系统,越来越多的是由多语言混合编写而成的,而在实际的系统中,所谓的架构决策,就是在不同的部分,选择不同却适合的语言和技术。

这个结论,我一直相当心安理得。直到上周,我去参加了ThinkInLAMP组织的PHP2013开发者大会。在会上,我听到了来自台湾的梁枫先生的一场演讲《在WEB之外——PHP》,在演讲中,他反复在问一个问题:PHP真的只能写Web吗?而他的开发实践相当的有趣,他在用PHP编写工业自动化控制方面的应用,编写串口通信的代码,同样的功能,用PHP编写的时间是2周,而用C语言编写的时间是8个月,而且PHP的2周,是他一个人完成的。这样的演讲,令人印象非常深刻,也引发了我更多的思考。

会后,我找到了梁先生,提出了我的疑问,举的就是我在公司里,颠倒两种语言的架构决策。蔡先生的回答是:对啊,当初我只用了2周,但是后来我们还是又花了8个月呀。PHP,主要可以快速的拿出原型,真正的产品,还要C语言去开发一遍的呀。

经过这番讨论,我得到了一个新的富有启发的结论:在快速原型的阶段,就可以选择快速开发的语言,而在实用的阶段,就应该选择更加实用的语言。

这么肤浅的结论,真的值得大肆宣扬,再写一篇Blog吗?自然不是,因为我在后来的一周里,一直在脑子里反复思考这个问题,然后,突然想明白了一些:

在一些极端的领域,效率至上与实用至上,可以毫不相干,各自有所追求,前期追求效率的开发产品,由于成本极低,大多是可以随时抛弃的。而真正的困难在于想要兼得。常见的与架构相关的两种痛苦:一种是,刚开始为了追求快速开发,在技术选型上怎么快怎么来,结果系统越来越大,越来越复杂,等到想要考虑架构优化,想要重构的时候,却已经积重难返,改起架构来伤筋动骨。另一种是一开始想得太多,架构做得太复杂,杀鸡用牛刀的技术用得太多,往往还没有等到系统开发完成,就已经Game Over了。

还有一个现象,也很常见,我们常常能够见到各种技术方面的争论,各执一词的原因,往往是由于各自的立场不同:你说某某语言效率极高,他说等到复杂了这个语言就撑不住了。一些常常被人引用的例子是:某某知名网站,放弃了PHP技术、放弃了.NET技术,放弃了Ruby技术等等,对立阵营的同学们,就感到欢欣鼓舞:看吧,就知道你们那个语言,只能拿来开发玩具应用…

长长的引言部分结束,开始系统性的阐述我的观点:
1. 选择技术,往往不是选择某种单一的技术,而是选择一个技术栈;
2. 有些技术一开始的出发点就是追求开发效率,然后在后续的发展中,逐步开始追求实用;
3. 有些技术一开始的出发点就是追求实用性,然后在后续的发展中,逐步开始追求开发效率;
4. 想要兼得鱼和熊掌,的确困难,但是并非没有可能,我们可以找到一些优秀的、可选的技术集合(兜售私货的伏笔);
5. 对于技术选型的判断,需要考虑理论情况与实际情况;

效率考虑
技术复杂度(复用性):学习并掌握一组技术栈,需要了解多复杂的技术;相应的,当我们掌握了这门技术,他可以在多少地方复用?
技术友好度(优雅性):在开发的过程中,会不会有各种莫名其妙的陷阱,会不会让我纠缠于各种莫名其妙的细节?
实用考虑
业务复杂度(组织性):随着业务的复杂,我们的代码会不会最终无法驾驭?无法维护?无人能懂?
性能提升度(潜力):随着业务的增长,压力的提升,我们会不会最终被迫放弃现有的技术架构,重头开始?

也许,我们可以凭借这四个维度,做一个雷达图,以便更加准确的评价候选的技术,这里就先靠文字描述粗略的表达一下吧。

LAMP,当然是最为知名也最为成熟的技术栈,随着技术的发展,Nginix、Memcached、Redis、LVS等等技术,也非常自然的加入到这个体系之中,常常有人宣称:LAMP是全能的,而我在大多数时候,也相当同意这一点。如果将LAMP拆开来看,除了PHP,其他的几项技术,并非LAMP独有,如果我们单独来看PHP的话,他在开发效率方面相当优秀,但是略弱于Ruby&Rails;在实用方面,却略胜于Ruby&Rails,因此:PHP始终是一个不算坏的选择。

Ruby&Rails,是一个较新的技术栈(当然,我们可以说它仅仅替换了LAMP中的P),但是,Rails在快速开发领域的贡献是划时代的,具有开风气之先的意义。现在的Rails,也开始越来越大,越来越复杂,逐步的开始追求实用,这也造成了另一个有趣的现象:Ruby whitout Rails的兴起。甚至可以认为:Ruby社区一个非常显著的特点,就是强烈的追求开发效率,不太强烈的追求实用性。

nodejs,是目前最新的一个技术栈,他最大的一个优势,就是前后端只需要一种编程语言,使得原本就熟悉JavaScript的程序员,爆发了极大的向后端进军的热情。而另一方面,由于nodejs的异步响应的高效特性,使得其在实用性方面,有相当宽广的未来。但是,现在的nodejs,对于业务复杂度的支持,还远远不够。

Java是一门老牌的语言,说实话,我已经早就背叛了这个阵营,原因很简单,Java仅仅在组织复杂业务代码的能力上,有不小的优势;但是:这是以一开始就引入的架构复杂度为代价的。Java社区的众多框架,似乎也忘记了对开发效率的追求,一门心思为了展现更多的设计模式…(纯吐槽,请无视)

HTML5,也是相当火爆的热门领域,很大的一个原因,就在于:HTML5的知识,可以复用于Browser、Mobile、Tablet等原本差异极大的多个领域,因此在开发效率上,对程序员产生了极大的诱惑。只是在实用性方面,目前还有一些疑问。经常听人提到的HTML5&Native混合编程,我的直觉是:这样只会造成更多复杂的问题需要解决。

Golang、Erlang,本身就是根植于实用性(尤其是性能)追求的技术,在开发效率方面弱于其他技术,原本就是合理和正常的,对于某些预期肯定会非常复杂的系统,一开始就选择这样的技术,可以说是相当正确的选择。

Redis是一个好的技术,无论是自己一个人做个玩具小应用,还是在关键领域,承担核心性能组件。REST是一个好技术,无论是开发一个DEMO,还是用于整个SOA架构的核心,都非常合适。这样的技术,的确不多。

最后需要表达的一个观点是:以上这些点评,仅仅出于我对这些技术的了解(你看,我根本不懂Python/C#,所以也不敢点评什么)。 对我而言,在目前的阶段,nodejs是一个非常值得加大投入,深入学习的技术栈(私货在此)。

希望这篇文章,不致令各位朋友失望…

我怎么面试

最近换到一家新的公司,开始组建一个新的团队,于是又开始了新的一轮看简历与面试的过程。正好今天在微博上看到了相关话题的碰撞,我也因此想聊聊自己的面试观与面试方法。

先做引用与简单的点评:

@寒冬Winter 谈谈面试与面试题 这篇博客,我认为相当有道理,也在微博上转发推荐了一下。

@左耳朵耗子:要考倒一个人真是太简单了,只需要把他拉到我擅长的地方来用预设好的答案就可以随时秒了他。在我们这个长期受『应试教育』的国度里,我们一方面在抨击『应试教育』,另一方面却不知不觉地把面试变成『考试』。我们仅关注于知道什么,却忘了人的能力和热情,忘了面试是为了了解对方的亮点和长处。

@左耳朵耗子:关于面试的文章我写过好几篇文章,大家可以去看看:2009年的【我是怎么招聘程序员的】http://t.cn/h5RbVQ,2011年的【再谈我是怎么招聘程序员的(上)】http://t.cn/hdLouf,【再谈我是怎么招聘程序员的(下)】http://t.cn/hdLou5。2012年的【为什么我反对纯算法的面试】http://t.cn/zWRf5Be

说实话,我一直是以陈皓的方式,来做面试的。但是,我不太同意陈皓给寒冬扣的帽子。

最近我的面试方案

  • 不需要对方做自己介绍,简历上都有。而是我先做自我介绍,公司如何,团队如何,我们在用的技术是什么,我们想要找什么样的人,等等。
  • 如果对方对于这样的介绍表现出兴趣,对于加入这样的团队感到有吸引力,那么,开始换他做自我介绍。要点是:
    • 在你的经历中,介绍你认为自己符合这个岗位的相关能力,相关经验
  • 基于他的自我介绍,做进一步的反复追问,比如在过去的工作中,解决过什么样的难题
  • 有些问题,我通常都会问:
    • 遇到问题到哪里找答案(回答度娘的,直接请他走人)
    • 会阅读开源项目的源代码吗?
    • 试着改过别人的开源项目吗?
    • 试着提交过补丁,或者自己发起过什么开源项目吗?
  • 在面试高端人才方面,我还采用过另一个方案。开头是:我们现在遇到了一个技术难题,表面的现象是这样的…接下来换你来向我提问,如果你问对问题,我就如实回答,如果你没有问到,我也不会主动告诉你。等你问得差不多了,就告诉我你的解决方案。
  • 如果有可能,我希望能够看到你写的源代码(这个最能够代表实力)

相关理念

  • 面试是繁重的脑力,如果完全顺着对方的路子进行追问,我会很辛苦。
  • 另一方面,对于不同的面试者,提一些共同的问题,有利于横向比较。
  • 设置一些简单问题,能够在一开始就请走部分不靠谱的面试者,能够节约大家的时间。
  • 共同探索性的问题,当然能够充分考查面试者的水平,但是:这样对于双方而言都是最累的。
  • 面试主要考察的是表达能力(或者说由表达能力而传递出来的其他能力),但是,最好能够看看应聘者代码,以免走眼。
  • 面试不是为了发现人才,而是为了比较人才。每天面试1~2人,一个月下来就是30~40个人,挑选其中最值得招聘的对象,不仅仅是我个人的判断,还有前面的简历筛选,以及后面的HR交流等等环节。

结论

  • 我会有一些固定题与一些针对题,以及一些更加困难的题,多种手段,是为了更加准确的判断应聘者的能力。
  • 多年以前我写过一篇《招人不难》,现在感觉还是太难了。

警惕雄辩家

一个原来写了一篇《完全用Linux工作》的王垠,又写了一篇《漫谈 Linux,Windows 和 Mac》,居然又引起了轩然大波。还引得徐宥写文章批评了一番,真是不值得。

以前他说:Unix 是简单的,你不需要成为一个天才也能理解这种简单。

现在他说:Linux 和 Unix 里面包含了一些非常糟糕的设计。学不会有些东西不是你的错,是 Linux 的错,是“Unix 思想” 的错。

以前他说:高明的 UNIX 程序员不用 IDE,IDE 从来就是给初级 Windows 程序员用的。

现在他说:有些人鄙视图形界面,鄙视 IDE,鄙视含有垃圾回收的语言(比如 Java),鄙视一切“容易”的东西。他们却不知道,把自己沉浸在别人设计的繁复的规则中,是始终无法成为大师的。

以前他说:Xwindow是一个出色的设计,它把显示服务器和客户程序分开……

现在他说:Linux 的图形界面(X window)在本质上几乎是不可治愈的恶疾。

当我们分开看两篇文章的时候,几乎会被他说服两次。当我们做点简单的比对工作,就会发现:“雄辩家都是健忘的。”只要我们记性好一点,就不容易被迷惑了。

附带链接:

完全用Linux工作:http://www.cnbeta.com/articles/76147.htm

漫谈Linux、Windows、MacOS:http://bbs.hupu.com/5187888.html

答Unix痛恨者王垠:http://blog.youxu.info/2013/03/03/unix-haters-2/

[知乎回答]如何提高阅读源代码的能力?

谢邀,这是一个非常好的问题,也正是我想要认真思考,然后回答的问题!

@johnniechau 推荐的《代码阅读方法和实践》,是一本好书,我只打算在这里简单的聊一聊自己的经验与思考。

我们先假设一种最恶劣的状况,你被迫接手一个遗留项目,原来做项目的家伙,全都四散逃亡了,不但没有任何说明文档,而且还找不到人,老板给你一段并不宽裕的时间,你得读懂他们的代码,然后接着维护……通常,这是噩梦的开始。

当然,从提高能力的角度而言,这是一个好机会。所以,@刘立 虽然只说了两个字“压力”,我认为的确正中要害!

我们可以用拼图这样的游戏,来做一个比喻。一地的碎片,你如何将他们尽快的拼在一起?

  1. 寻找边角的块(除了四边都是凹凸的块之外,其他有一到两条边是直线的块,会少得多,也更容易辨认与拼接。)
  2. 将碎块按大的色块分类,从一次查找,变成二次查找。
  3. 一开始碎块最多的时候,是最困难的时候,需要足够的耐心、细心,以及一点点的运气。
  4. 如果你的记忆力足够的好,碰到的碎块能够在脑子里留下一定的印象,那么有助于你快速找到匹配的碎块。
  5. 经验能够帮助你提高效率,熟能生巧。

回到代码阅读,我们来做一个类比:

  1. 寻找代码中最明显的入手处,比如main函数,core文件夹,model、view、controller的三种大类等等。
  2. 从理解文件夹、文件名开始,而不是一上来就埋头进入源代码之中。
  3. 一个好的全文搜索工具,能够帮你找到相关的代码与片段,渐渐的,看起来一团乱麻的代码,就会显现出各种可以被理解的关联出来。
  4. 记忆力总是有用的,在脑子里绘出整个系统的架构,并且补充越来越的,越来越清晰的细节。
  5. 一样是熟能生巧。
  6. 相比拼图,代码阅读还要容易一些,你不需要理解全部的代码,有一个大致的理解以后,就可以先放过一些不太重要的细节。

另外推荐阅读我目前正在写作的一份文档《借助开源项目,学习软件开发》——第五章:理解开源项目:link
引用较为相关的一段在下面,供参考:

5.5. 知其所以然
有一句俗语叫做:“知其然,更要知其所以然”。用在任何学习科目上,几乎都是恰当的。本章叫做《理解开源项目》,而之前的4个小节,可以说都是属于“知其然”的功夫。如何才能知其所以然呢?

所以然包括哪些内容?
往大了说,整个这份文档,希望帮助读者达到的,就是能够对于开源软件“知其所以然”。这样才算是真正提高了软件开发的能力。因此,我们可以将“架构决策”、“代码风格”、“领域知识”、“编程技巧”等等内容,都算作是所以然的一部分。
架构决策 通过深入阅读和分析源代码,理解整个项目,为何像这样,而不是那样做架构设计。其间蕴含着项目作者的经验和智慧,理解了这个,将是一种巨大的收获。
代码风格 每一种语言、每一个社区、每一个开发者群体,甚至每一个开源项目,都有其独特的代码风格,这种风格,有其背后的合理性,也有很多是来源于某种开发哲学的思 考。理解一种代码风格,就是理解一种思考的模式,一种思想的体系。能够多了解一些不同种类的代码风格,对于提高软件开发能力,将有很大的帮助。
领域知识 有些代码不容易看懂,很重要的一个原因,是这个项目所涉及的领域,我们没有什么深入的了解。多年的程序员经验告诉我,要做好某一个行业的软件,一定要成为 某一个行业的内行。甚至要比那个本行业的业内人士,更加精通。因此,一个优秀的程序员,通常是能够跟你聊多个不同行业的话题的。强大到你几乎无法分别他的 是不是业内人士。因此,通过理解开源项目,进而理解相关的领域知识,会有很多收获。
编程技巧 阅读优秀的开源项目的代码,有时候很像是看一本好书。细细品味,慢慢的体会。我们会发现一点一滴的“妙处”。这些妙处凝聚了程序员的巧思妙想,能够体会得越多,对我们的帮助也就越大。

所以然还包括的一些内容:
个人偏好 开源作者也是普通人,他们有很多观点和取舍,未必能够说服他人,只能算是他们自己的偏好。而他们将自己的偏好表达在代码里,有些时候,我们能够很容易理解 (因为我们也是这样想的)。有些时候,我们就会感觉很不解,而且,常常会发生的一类故事就是:某某大牛写了一个开源项目,另一个大牛有感觉不爽的地方。提 了意见建议,人家又不肯改。结果,这另外一个大牛,就一怒之下,另起炉灶,写了一个新的开源项目。
历史原因 有一篇很有意思的文章,解释了《为什么Vim使用HJKL键作为方向键 》,其实原因很简单。当Bill Joy创建Vi文本编辑器时,他使用的机器机器是ADM-3A终端机,这机器就是把HJKL键作为方向键的。

如何搞清楚这些所以然呢?
思考 当然,这种思考应该伴随我们“通过开源项目,学习软件开发”的始终。但是,从方法论来说,可以尝试从以下一些角度出发来思考:

  • 如果我来做一个,会如何去做?
  • 如果能够对这个项目做减法,我可以去掉那些模块和代码?真的能够去掉吗?
  • 通过阅读单元测试,理解开发者的设计思路。
  • 尝试做一些破坏或者修改,来理解项目中的那些做法。这个在下一章会更详细的讨论。

讨论 到开源社区去,发起一些讨论。当然,前提是你必须经过足够深入的思考。不要尽是问一些傻问题
向作者提问 与上面的讨论类似,前提是要先思考。当然,还有一个讨巧的办法,你可以提出:翻译这个开源项目的英文文档,然后,对方当然会很高兴——国际化了嘛。然后,你可以在翻译的过程中,提出各种各样的问题。。。
阅读指南 有些著名的开源项目,本身也非常复杂,所以会有一些文档与书籍:linux内核代码分析、MySQL源码解读、PHP源码分析等等。如果有心学习这样的大 型开源项目,这种入门指南,也是很有价值的。但是,这毕竟是别人嚼过的饭,肯定不如自己去啃来的香。所以,还是回到那句老话,源代码才是最有营养的。

程序员与政治

零、缘起

这个话题很大,但是又不得不谈,原本大多数程序员,都是完全与政治绝缘的人,现在,政治却迎面撞了上来,不谈都不行了。

最近发生的,与程序员相关的,最大的一件事情,与github有关,github被GFW封锁了,后来李开复老师在微博上发起了一个抗议,目前又恢复了。
李开复微博抗议封锁GitHub

另一件事情,是有人发起了一个呼吁:People who help internet censorship, builders of Great Firewall in China for example, should be denied entry to the U.S.。在这个呼吁中,又包含了一个github的gist的link,列出了一些与GFW相关的人名与信息。又一次引发了大量的争论。

最直接的一个争论,来自@左耳朵耗子 与@范凯robbin 。首先争论在twitter上发生,又在新浪微博上发展,最后在知乎上形成了一个大讨论《有关 github 问题 @左耳朵耗子 和 @范凯robbin 的争论大家有什么看法?》我的这篇blog,也打算最终写成以后,贴到知乎去,那里算是一个不错的深入讨论问题的地方。

一、界定

所谓政治,就是众人之事。一件事情,如果与众人的利害相关,大家都有权力参与讨论,这就是政治讨论与政治权力的根源。对于程序员而言,能够自由的、不受阻碍的访问互联网,尤其是google、sourceforge、github、stackoverflow这样的技术网站,就是程序员的权利所在。从这个简单的逻辑出发,我们可以确定:GFW如果封锁了Github这样的网站,损害了所有程序员的利益。

针对损害自身利益的行为,作为受损的一方,可以做些什么,也许能够争取回自己的权利,对于这样的行为取舍与争论,就构成了目前政治讨论的核心话题。

简单说:我们可以画一个九宫格,来做分析:

利人 未知 损人
利己 双赢 争论 共诛
未知 赞扬 争论 痛骂
损己 烈士 争论 蠢货

其中,对于某些行为是否能够利人,存在未知或者争议的情况,这种事情,往往是争论的焦点,但是,如果能够肯定是利己的情况下,争论会小很多(大多都会被骂,少部分人会说说公道话)。最容易争议的情况,就是肯定损己或者至少不利己,却不能判断是否对众人的利益造成损害的情况,争论是最严重的。这一次的gist上张贴GFW参与者的行为,就是处于这种情况,所以争论也尤其剧烈。

二、分析

要谈到我自己的观点,首先需要分析的是这个行为本身,是不是对于程序员有利。我的看法是:长期可能有利,短期可能不利。

先说为何长期可能有利:参与开发、部署、实施GFW,就是作恶,这个大家都应该同意。既然作恶,总应该付出某种代价。换言之,如果,作恶者需要冒着付出代价的风险,那么,他们的行为也许会有所收敛,至少参与者会越来越少。再次,我还想呼吁,如果各位IT从业者,只要手中有一点点的人事权力,就绝对不要放一个GFW参与者加入自己的公司。各位拥有话语权的朋友,只要了解到一点点相关的事情,就对人对事口诛笔伐。总之,我们需要想尽一切办法给这些人制造实质的损害,使得他们从道义上羞愧,从利益上受损,这才是应做之事。

目前,我们可以看到在微博上@韩伟力 老师站出来主动的撇清自己,希望大家相信他没有为GFW做出过直接贡献,我想,至少他已经意识到参与GFW是一件可能使自己利益受损的事情,这就是效果。希望这样的效果,越来越大。

再说为何短期可能不利:是的,因此Github可能更快的被GFW封锁。使得大多数程序员访问Github产生困难。这是一件糟糕的事情,全体程序员的利益都可能因此受损。

再其次,说说为何两个判断,都仅仅是可能:咱们自己的GFW的事情,居然去指望美国政府能够帮助我们,这是不靠谱之一;一群人冲过去注册账号然后投票,难免会被人看做刷票(虽然我也干了),这是不靠谱之二;在Gist上列了区区三个人,还有一个只是疑似,既不全面又不准确,这是不靠谱之三;禁止进入美国,究竟算作什么样的惩罚?一方面太飘渺,一方面也太轻,这是不靠谱之四。因此,所谓的长期有利,仅仅是一种可能。

说说一些往事,SourceForge被封,因为曾经有一个软件叫做FreeGate放在上面。FreeBSD被封,因为他的项目名称里有free。Python网站被封,因为版本号出现了6.4。vim.org被封,我至今不知道由于什么原因。RubyGems.org被封过,我也不知道是由于什么原因。还有很多很多的网站被封,是由于各种各样奇怪的原因,有些我们能够猜出来,有些我们至今依然猜不出来。

另外一些反例是:维基百科曾经被封却目前健在,以下词条现在可以自由的访问:中华人民共和国网络审查防火长城方滨兴。事实上,维基百科也曾经有过严格自我审查的一个历史阶段,我曾经在维基百科中文创建过一个“蒙古问题”的词条,后来他们自己删除了。但是,即使如此,再后来维基百科依然被封,无法幸免。再后来,维基百科的解封,又是很多很多的幕后英雄的努力,这个现状,有趣的说明了一些问题。

自我审查未必能够幸免于难,坚持独立与中立,却能够维持长久的生命力。所以,Github上这条小小的gist,未必会导致Github被封,不必大惊小怪。

三、我的观点

1. 讨论问题,尽可能以理服人,对事不对人。范凯在知乎的回答,至少前三条我是同意的,第四条我有所保留,第五条我也基本同意。但是,在他twitter上被人截屏的爆粗口言论,我是完全不能同意的。

2. 在那个gist上,以各种粗口痛骂范凯的人,我也非常反感。

3. 在中国古代,有连坐的法律,仅仅因为某人是我的邻居,我就可能被抓取砍头。后来,法律有所进步,不再牵连无关的邻居,只是诛杀同族同宗的亲戚。再后来,法律继续进步,只判当事人的罪行,不再牵涉他人。而现在GFW的做法,极其恶劣,因为他在针对少数人的行为做出处罚所有人的封锁。更加恶劣的是,他没有任何的成文法,告诉公众,何种行为,就会导致某某网站被封锁。这完全是一种:以无差别、无理由的惩罚构成的政治恐怖!面对这样的政治恐怖,我们应该意识到,它比当年的连坐,要恶劣无数倍,也要荒谬无数倍!

令人不解的是,面对这样荒谬的恐怖,很多人却开始了自我反省、自我审查与自我阉割。我想,这是一种本末倒置。

4. 鲁迅有一篇著名的讽刺小说,在百度百科上,就能够看到。《聪明人和傻子和奴才》,推荐一读。

5. 在评价@ghosTM55 的一条微博时,@lidaobing 说了一句我非常同意的话:自我审查会降低审查成本,让审查的均衡点往审查方移动,进一步压缩被审查方的利益。我想再补充一句:自我审查也就罢了,逼使别人同样做自我审查,甚至痛骂不愿意自我审查的人,我认为已经大大的超过了明哲保身的底线。但是,我必须申明一点,我并不认为范凯是出于明哲保身的原因而发布那些言论,以我对他的了解,他真的是出于大多数程序员的利益,而义愤填膺的发言的。

6. 最后谈一点感想,因为这个事件中的很多人,都是我的朋友,我只能感叹,有太多人在政治方面,缺乏基本的常识与素养啊。抄一句自己在微博上的观点作为结束吧:有分歧的地方,却能够学会各自客客气气的将观点表达清楚,也是政治素养的一部分。

自学与拜师求学

这个事情的起因,其实比较有趣,算是一次微博上的联合恶搞的行为。某硅谷猎头发了一篇煞有介事的微博,讨论程序员要不要学JSON,并且给出了一张更加煞有介事的趋势图,似乎JSON技术的薪水连年上涨,而且涨势喜人!第一张截图,是我在开玩笑,而第二张截图,则是大家一起开玩笑之后,出现了JSON培训的市面良心价(1元课程秒杀)。

image

image

 

之所以会有这样一个玩笑,原因很简单:JSON实在是太简单了,几乎不值得专门去学习。也由此可以看出,给予所谓的统计趋势给出某某技术的薪资增长水平,是多么的不靠谱。

当然,对于这个问题,我们可以再多问一句:究竟哪些知识,是可以仅仅通过自学就能掌握的呢?又有哪些知识,是需要拜师求学,才能真正学到的呢?

一、第一判据:能否自我检查?

所有自学的公共前提,只有一个:你能否判断自己是否学会了?目前学到哪个阶段?接下来该学些什么?如果,你无法自我检查与判断,那么,在这个方面,你就是无法自学的。打个比方:背单词是最适合自学的功课,因为我们很容易检查自己是不是已经能够背出那个单词了。而很多与形体动作相关的学习,就很难自学,因为我们无法判断自己的动作是否正确,是否规范。

一个极端的例子,是梅超风练九阴白骨爪,结果把自己给练废了,这就是没有找到师傅,自己瞎练的后果。

二、师傅领进门,修行靠个人

在入门之前,就开始自学,很有可能各种误打误撞,上下求索却不得其门而入。如果能够有一个靠谱的师傅,将我们领进门,接下来的自学,就会少走很多弯路。也可以说,我们首先得学会,如何在这个领域自我检查,否则根本无法开始自学。

市面上有很多的书,书名都起得很诱人:《XXX21天从入门到精通》,这样的书靠谱吗?多半不靠谱。不过,也的确有很多朋友,借助于这样的书,新学乍练,从此走上了程序员之路。等到多年以后,又往往会感叹:“自己当初的基础,太不扎实了。”

三、节约时间与积累经验

在很多时候,自学与拜师求学之间,并不矛盾,都是可以的。而且,如果能够有一个师傅的话,会节约很多的时间。不过,我们会因此而发现各种不同的“教学风格”,有的老师,倾囊相授,事无巨细都告诉你了。有的老师,却惜墨如金,往往会把你打回去,让你自己去想。

实际上,存在着这样的两难情况:如果在你发生疑问的时候,老师都原原本本的告诉你答案,你的确是迅速的解决了疑问,但是却形成了依赖心理,并且长进缓慢。反之,如果你能够努力的思考、求索,甚至走了很多的弯路。这些努力,都会给你带来更多的收获,俗话说得好:天道酬勤,功不唐捐。

四、提问的智慧与心态

在网络时代,学习的方式非常多种多样,在自学与求师之间,存在一个中间状态:就是在各种各有的社区,提问并等待回答。看起来,这是自学过程中的一部分,但是也可以认为那些回答了你的问题的人,都是你的老师。

不过,现在的人都急躁得很,找答案的时候,卑躬屈膝,发现找不到好答案的时候,又心急火燎。自己的问题提得不清不楚,别人追问几句,却又恶言相向。在网络上,流传这很多种不同版本的《提问的智慧》,这里只给一个链接:http://www.iteye.com/topic/7991

但是,关键问题并非缺乏智慧,而是没有端正提问的心态。古人云一字可以为师,既然提问,自然要正心诚意,出于求学问道之心。而现在,往往提问的人也不自觉为学,回答的人也不自觉会师,这样一来,多半就搞不好了。

五、不迷失的诀窍

互联网上,不靠谱的人、不靠谱的话,实在是太多了。如何判断呢?胡适教人“不受人惑的办法”,就一句话:拿证据来!事实上,直到现在,这仍然是最有效的办法,当然,可以进一步推而广之,对方如果没有证据,咱们就自己去追,自己去求证。在软件编程的领域,这就更加容易一些,写点代码自己验证一下,大致就清楚了。

当然,那些无法以代码来衡量的事情,的确比较麻烦,比如这位猎头先生发出来的统计图表,如何判断呢?常识+逻辑,常识要多积累,逻辑要多磨练,如此而已。