Smart and Get Things Done

上周在刘未鹏的博文里看到了Joel Spolsky关于招聘和管理的博客文集《Smart and Get Things Done》这本书,在网上辗转找到电子版并这几天在iPad上看完了(羞愧一下没买正版)。Joel的风格还是那么简单直白,切中要点,英文也非常好理解(移民的缘故?)。虽然书是从招聘者和公司老板的角度来谈的,不过里面很多内容还是值得广大IT从业人员一读的(特别是软件开发者)。对于短期内不会有机会参与雇佣的人来讲,也可以通过书中的一些例子来对雇佣的公司进行反向选择(如果你拥有多重选择的话)。
书里给我印象最深有两点:
1. 判断一个人是否聪明,看他能不能很快理解我(面试官)说的意思,而不是我再三解释;
2. 如果你对雇佣一个人犹豫不决,那就说“不”。
另外,他对“Hard-Core”的态度,也让我相信我当初选择从底层做起的决定是正确的。
p.s. 书名“Smart and Get Things Done”是Joel招人的最基本原则,来自于微软。

观止

从图书馆借的《观止》,基本上算是一口气读完了。当前世界上占有率最高操作系统(NT内核的Windows)的开发过程可以说是惊天地泣鬼神。很难想象如果NT失败了,或者像Vista那样恶评如潮,今天的微软会是什么样子。印象很深的有几处:dogfood文化、push文化和最后的death march。
根据Wikipedia,Eat your own dog food,来源于某电视广告。某明星为某狗食打广告,并宣称自己也用这个牌子的狗食喂自己的狗。而在IT界,最早使用是在1988年的微软,并在接下来的各种系统很好的坚持了这个原则。这是一个很优秀的软件工程实践,如果有条件的话,我强烈推荐开发团队采用它。在APIS的开发中曾经尝试过,效果很不错,立马揪出bug和糟糕的用户体验问题一坨。
因为导师曾经在微软工作过,因此对push文化也有所耳闻。对于微软之前是什么样,《观止》中没有交代,但NT的开发肯定给这个文化加上了浓重的一笔。而在最后的death march中,这种文化达到了极致。
对于本书署名的翻译,我倒是有所微词。对于这本书而言,showstopper指代的是最严重bug的类型;而“观止”这个词是明显带有褒义的,以此做书名似乎不太妥当。观止本身对应showstopper的另外一个意思,“因特别精彩而被掌声打断的表演或表演者”。当然我也没有什么特别的建议,只是觉得译为“观止”似乎丧失了原文的双关性。

简评 《天朝的崩溃》

首先,此天朝非彼天朝,牛同学看到标题以为是国内的非法出版物。

对于鸦片战争的了解,除了小学时看过的《上下五千年》和《近代八十年》以外,还有《鸦片战争演义》和电影《鸦片战争》,剩下的就是历史课本和其他零星的摘要描述。之前最近一次接触鸦片战争的历史,应该是去年十一的下关静海寺之旅(南京条约签订地),里面有个南京条约纪念馆,所描述的内容基本也和历史课本没有多少差别。然而这本《天朝的崩溃》,基本把我前20年关于鸦片战争的理解重新刷洗了一遍。不为其有多少翻案,而为其翔实的数据,丰富的引证以及客观的评述而折服。当我们脱离了狭隘的民族主义历史观和弱者受欺凌的悲情来看160多年前的硝烟和谈判桌,终于发现历史原来不是像我们一直接受灌输的那样,黑白分明,正义和邪恶势不两立。

全书从”琦善卖国论”谈起,点评了之前的主流史观的矛盾–在总体上把鸦片战争的失败归结于中国的落后,具体上归结于琦善等人的投降卖国;总体上承认大清无力挽回局势,具体上又认定林则徐等主战派代表了正确的方向,只要他们的主张得以实施,中国就有救。在绪论中,作者还提出,历史学的基本价值在于”以史为鉴”,坚持对自我历史的不断批判,不论是妥协者还是抵抗者,是避免它重蹈历史覆辙的坚实保证。

作者在第一章就从军事上给出了清军必败的理由。以往我们总是很难理解为什么远道而来区区几千人十几条船就打开了有百万军队国度的大门,在这里就可以找到答案:装备差,兵力分散,素质低下,战术落后。英军能够数千人一起用,但清军只能分散把守各个海口;清军的调兵经常要从四川贵州陕西湖北来,路途虽不比英军遥远,但走路显然没有坐船舒服,以逸待劳基本也谈不上。此外还有装备上以及作战思想的巨大落后。

林则徐因战前”虎门销烟”战后抗英而成为民族英雄。尽管如此,他的战争准备严重不足,敌情判断出现了严重失误,制敌方略不合实际。一开始吃准英国不会轻易开战,后来认为即使开战也不会如此之快,再后来在战场上的战术也不对头。虽然他有一些洋务思想的萌芽,但已经跟不上历史的要求。”鸦片战争给中国提出的使命是近代化,偏离这一轨道就不可能真正的制夷,反有可能偾事。林则徐没有认识到这一点是他的错误,尽管他那对抗的姿态是可以表扬的。”后人也常把鸦片战争与后来东京湾的黑船做比较,分析为什么列强的出现在两个文化相近的东方国家造成了如此相反的结果。可以知道的是,清廷在战后没有进行任何的反省,对外政策依然为天朝对待番夷的”羁縻”,”清军战士的鲜血白流了”。

那些历史的”罪人”、”投降派”,如琦善、伊里布、牛鉴、奕山、杨芳、奕经、耆英等等,大多数一开始都是”力剿”的主战派。只不过有些人,如伊里布,还没打就知道必败,所以一直避免正面冲突,以妥协为主;有些尝过了英国人的苦头,才纷纷主和。而道光帝就夹在这帮官员当中,时而摇摆在”剿抚”之间,追求的是少花钱,早点了断。

战争的过程也与我印象中的历史不符。记得小时候看到英军第一次进攻厦门时,因闽浙总督邓廷桢早有准备,被迫北上攻打定海,颇为家乡自豪了一番。今次看此书外加一些其他材料,才了解到英军一开始的目标就是定海,在厦门无功而返大半是清军的邀功。而在战争的第二阶段,即使是城防最坚固的厦门石壁炮台(那时胡里山炮台还没建),也只让英军付出了死亡1人,受伤16人的代价,耗时仅3-4个小时。放足球来讲,基本算是”半场教学比赛”。

书里有句话,”知识给人力量,愚昧也给人力量,有时是更大的力量”。让我想到了《1984》里的名言:”Freedom is slavery, Ignorance is power”.

(author: marshall)

推荐《十亿消费者》

    在阅微堂上看到的推荐。豆瓣的地址在这里。由于有一些敏感的内容,在国内没有正式出版。可以在译言上在线阅读

    作者算是一位中国通,华尔街日报驻北京总编。曾在台湾呆过5年,北京呆过15年,会说中文。下面是主要内容:

    • 中国加入世贸的诸多内幕,包括中国高层和美国高层间的一些重要事件
    • 中金:摩根士丹利与建设银行的合资成败
    • 赖昌星小传
    • 新华社和道琼,路透争夺向中国股市传送世界财经新闻的“战役”
    • 道格拉斯和波音在中国投资前后
    • 美国媒体大王默多克在中国的起落,凤凰电视的起步,中国《财经》杂志的创办
    • 中国电讯集团,中国联合通信,UT斯达康的生成发展,和相互之间的争斗
    • 哇哈哈集团的发家史,潘石屹和张欣的地产王国

然后是我看到现在最有感触的一段文字:

在中国,从上而下的强力控制从来都被认为是达到和平和繁荣的唯一途径。其中一个原因是中国是一个基于耻辱感的社会,这和基于内疚感的西方社会有很大的不同。在西方,由于社会受到宗教的指引,很多控制是来自人们内心的。内疚,最终导致对罪恶和永远受到惩罚的恐惧,制止了不良行为的发生。然而在中国,人们害怕的是被揭露,以及随之而来给整个家族蒙羞所带来的耻辱感。因此,只要不被抓住,中国人做任何事都可以心安理得。在这种环境下,法律和秩序唯一有效的形式就是一个强权而又无处不在的政府,从而加大了你作恶之后被抓住的可能。

  虽然这段文字里的内容也许存在争议(在豆瓣上就看到了不同的意见),不过可以让大家从另一个角度,反思国内的现状。

企业应用架构模式读书笔记(二) Domain Model

这个笔记主要记录一下领域模型。
第一次听说领域模型是在JavaEye的一个帖子上。 也就是那个经典的robbin总结。那时候看是一头雾水,根本不知所云,虽然当时已经是大三下半学期,开发了学院的那个CMS。从IBM回来以后,开始着手重新启动APIS的开发,同时引入了Spring框架。一些项目上的心得,再加上对APIS设计上的疑惑加在一起,重新再看那篇帖子,真是豁然开朗啊。同时也去了Martin Fowler的Bliki上看了那篇批判贫血模型的blog
其实所谓的领域模型,我在使用Hibernate的时候,就已经使用了这个模式。不过在Martin Fowler写这本书的时候,Hibernate不知道存不存在,即使存在,也肯定很不成熟吧。通过O-R Mapping,我们建立了领域模型。比如说,对于PoEAA书里那个例子来说,建立了Contract, Product, RevenueRecognition三个领域对象。这些对象之间通过引用互相联系。同时把一部分验证、计算的逻辑放在了领域对象里。非常重要的一点是,这些领域对象,或者说这些类,可以存在继承或者关联关系,也拥有多态、封装的特性。可以说把OO发挥得淋漓尽致(不过发挥过头了也不好)。先贴一张图吧,就是书里的类图。
(附带说一下,CSDN里图片上传以后的那个预览窗口里那些文字不知道为什么还保留着,根本没有用。这个FCKeditor改得不够?)
三个领域对象互相关联。同时对不同的产品,使用了不同的计算策略(Strategy模式)。
底层的数据映射模式,可以使用Data Mapper,或者是Active Record(就是RoR里的那个),前者通过另外一个类似DAO的类来处理CRUD,而Active Record在领域对象内部处理持久化。Fowler的观点好像是不需要DAO了。
另外,对x血模型我也不是很清楚。有很多种说法,就是在JavaEye上看到的,robbin说的都不一样。最典型的就是关于贫血模型了(Anemic Domain Model),根据Fowler的说法,就是把所有的Domain Logic抽到Service 层以后,只有单纯的getter和setter的领域对象模型。而充血模型(Rich Domain Model),在底层那些POJO里就包含了一部分的逻辑。但把事务处理等工作交给了Service Layer。另外还有一个胀血模型(Bloated Domain Model),是一个反模式,把所有的工作都交给了领域对象,包括事务(因为事务总是经常要涉及到其他部分)。
还有一个失血模型,英文不知道,内容也不太清楚。这是我的理解。还有另外一种说法,同样没有失血模型的描述。也是在JavaEye上,robbin总结的帖子

  1. Anemic Domain Model: Service –> DAO –> Domain Object
  2. Rich Domain Model: Service –>Domain Object <–> DAO
  3. Bloated Domain Model: Domain Object <–> DAO

如果是这样的话,其实这和Fowler所定义的的贫血好像并不一样。脑子有点被搞糊涂了,呵呵。不过我想追究这么多,搞清楚概念也没什么用。重要的是自己去实践一下,哪个好用,易于扩展、易于维护。到底是不是纯粹的OO,并没有那么重要。

JavaScript高级程序设计读书笔记(二)

终于有一本书的读书笔记写到第二篇了,呵呵~~不过这本书的第一篇读书笔记更像是速记的内容:)
1. Javascript只有public作用域,没有private,更不用说protected,另外也没有静态方法。
2. this指向的是调用该方法的对象
    obj.color = “red”;
    obj.show = function(){
       alert(this.color);    //output “red”
    }
3. 定义类的几种方法(略去最后一种,根本没看懂,而且说非常不推荐这种做法)
(1) Factory
function showColor(){
    alert(this.color);
}
function createCar(color, doors, mpg){
    var temp = new Object;
    temp.color = color;
    temp.doors = doors;
    temp.mpg = mpg;
    temp.showColor = showColor;
}

var car = createCar(“red”, 4, 23);
缺点:没有共享函数。不同的实例间可能有不同的函数调用。可以改变一个对象的函数绑定。不用new构造,不像是类(当然,只是不像)。
(2) Constructor
function Car(color, doors, mpg){
    this.color = color;
    this.doors = doors;
    this.mpg = mpg;
    this.showColor = function(){
       alert(this.color);
    }
}

var car = new Car(“red”, 4, 23);
优点:用new构造
缺点:同工厂的第一点。
(3)Prototype
function Car(){}
Car.prototype.color = “red”;
Car.prototype.doors = 4;
Car.prototype.mpg = 23;
Car.prototype.showColro = function(){
    alert(this.color);
}

var car = new Car();
优点:函数真正共享,不会出现不同实例之间使用不同函数的情况(指的是同一函数名的情况下,同时Javascript里不存在函数重载)。可以使用car instanceof Car
缺点:显而易见,函数共享的同时把属性也共享了,没什么比这个更糟糕的了。
(4) Mixed Constructor/Prototype
function Car(color, doors, mpg){
    this.color = color;
    this.doors = doors;
    this.mpg = mpg;
}
Car.prototype.showColor = function(){
    alert(this.color);
}

var car = new Car(“red”, 4, 23);
优点:函数真正共享,但不共享属性。不过我发现可以把属性加入prototype来实现静态的属性。也可以使用car instanceof Car
(5) Dymanic Prototype
function Car(color, doors, mpg){
    …
    if(typeof Car._initialized == “undefined”){
       Car.prototype.showColor = function(){
          alert(this.color);
        }
    Car._initialized = true;
    }
}
这个更大的进步就在于,函数的创建只有一次了。
4. 一个StringBuffer实例,通过Array.join()来实现append()。同时还有实现Array.indexOf()方法(这个Prototype.js里也有的)。前面一个用的是构造类,后面用的是prototype

企业应用架构模式读书笔记(一)

最近懂得要写写读书笔记了。平时看了一些书,看过就忘,真是坏习惯。但记在本子上又不怎么看,觉得BLOG还算个好地方。以后都记在这里吧。当然,这本书的笔记还要为技术沙龙做一些准备。
模式先不说,先把那个例子解释清楚。英文版的看起来还是有点难度的,要看两遍才知道(其实就是因为那个例子是什么意思不知道)。不过这种经典书应该是多看几遍的吧?
先把数据库表列出来
Prouducts

int id
varchar name
varchar type

Contract

int id
int product_id
int revenue
date signon

RevenueRecognition

int
contract_id
int amount
date recognizeon

有三种产品,数据库、字处理软件、电子表格软件。IBM三件套是DB2, Lotus Word, Lotus123,微软三件套大家都很了解了,不过是SqlServer, Word, Excel。产品表很好理解了。合同表里有个产品的ID,也就是说,一份合同只是一份软件(虽然听起来比较ridiculous),还有收入(估计每一份都不一样价钱吧)。比较难理解的是收确认。因为有这么一项业务逻辑:字处理软件在签合同的当天就确认收入;而电子表格是在签合同当日确认三分之一,60天后确认三分之一,90天后确认三分之一,有点像分期付款吧;数据库也分三份,当天、30天、60天。每一次确认收入都要记录在数据库里,这样可以计算在某一日前有多少已确认的收入。
服务有两项。第一项是计算某一个合同在某一天前所确认的收入。其实这靠一条SQL语句就可以办到的。第二项是向数据库里插入某项合同的确认收入条目。比如Word就插入一条,DB2就插入三条。
顺便说一说第一个模式,也是最简单的模式:Transaction Script吧。这个是初学者常用的办法,如果再高级一点,可以用上个Command模式,让所有的Script都继承一个接口。所有的业务都在一个Script里完成,包括了业务逻辑、数据库操作、甚至是事务处理。这种模式,毋宁说是反模式,成也简单、败也简单。当然做一个DEMO、或者是以后不需要扩展的程序还是可以考虑这种模式的,呵呵。

javascript高级程序设计读书笔记(一)

上“人机交互”课上时记的一些东西,留下来备忘。上次那个JVM书的读书笔记真的只有一篇了,因为只能在IBM里才能看到,呵呵~~
1. isFinit(Number) 判断数字是不是无穷大, isNan(..)判断是不是数字
2. parseInt(String, int), 可以解析各种进制的整数
3. Nan != NaN, typeof(null) == “object”
4. Stirng.charCodeAt(int)
5. String.slice()基本上等于String.substring,不同的是substring(3, -4) == substring(3),对于负数,substring是忽略的。
6. ===, !==
7. Array.push(), Array.pop(), Array.shift(), Array.unshift()
8. Array.splice(),可以插入、替换、删除数组中的元素
9. Global对象,很大部分全局函数是Global对象的属性
10. encodeURI(), encodeURIComponent()

“Working with Java Virtual Machine” 读书笔记(一)

在books24x7.com上在线看的这本书(不过不是免费的,IBM为员工买了这个网站的阅读权利),觉得有些东西有必要记下来。不知道有“一”还会不会有“二”,呵呵。
Chapter 2 Overview of JVM architecture, Section 2 Runtime Data Areas in JVM
JVM data area:
1. Method area
2. Heap
3. PC Register
4. Java Stack
5. Native Method Stack
Method area: Shared among all JVM thread
1. name
2. super class
3. class/interface
4. modifier
5. list of super interfaces
6. Other:
a. Constant pool
b. field info
c. method info
d. class var
e. ref to Classloader
f. ref to Class
Heap:
1. Handle pool: pointer to object(in object pool) & class(in method area)
2. Object pool (instances)
Such design is for the avoiding fragmentation
Stach: 2 types
1. Frame for func activation
2. Operand for instructions, arg & ret of JVM instruction
Java Stack Component
1. local var
2. execution env
3. operand stack
JDK — JRE — JVM — bytecode Interpreter, GC, Class manager, …
\            \
classlib — byte code
\
native