<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>为之漫笔</title>
	<atom:link href="http://www.cn-cuckoo.com/feed" rel="self" type="application/rss+xml" />
	<link>http://www.cn-cuckoo.com</link>
	<description>为之漫笔（李松峰），本博客专注于Web前后端技术、移动平台开发技术、交互设计和技术翻译。声明一下，因为时常需要外出审稿，而且基本不带笔记本，所以有时可能会迟一点回复大家的留言。</description>
	<lastBuildDate>Mon, 12 Dec 2011 01:43:07 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>使用JavaScript和Canvas开发游戏（五）</title>
		<link>http://www.cn-cuckoo.com/2011/08/17/game-development-with-javascript-and-the-canvas-element-5-2645.html</link>
		<comments>http://www.cn-cuckoo.com/2011/08/17/game-development-with-javascript-and-the-canvas-element-5-2645.html#comments</comments>
		<pubDate>Wed, 17 Aug 2011 00:22:03 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[编程技术]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2645</guid>
		<description><![CDATA[原文作者：Matthew Casperson • 编辑：Michele McDonough 原文链接: Game Development with JavaScript and the Canvas element 1、认识一下Canvas 2、在Canvas上绘图 3、通过Canvas元素实现高级图像操作 4、写一个游戏框架（一） 5、写一个游戏框架（二） 6、通过Canvas实现视差滚动 7、动画 8、JavaScript键盘输入 9、综合运用 10、定义级别 11、跳跃与坠落 12、添加道具 13、加载资源 14、添加主菜单 在Canvas元素上实现视差滚动 http://www.brighthub.com/internet/web-development/articles/40511.aspx 视差滚动是在2D应用中创造立体纵深感的一种技术。这篇文章就来看一看在我们刚刚创建的游戏框架基础上实现视差滚动有多容易。 视差滚动 有了游戏框架，就可以通过画布元素来做一些好玩的东西了。 视差滚动指的是屏幕上的几个图层发生相对位移的效果，换句话说，背景图层滚动得比它前面的那些图层要慢一些。这种创造视觉纵深感的技术在2D游戏中的应用极为普遍。 RepeatingGameObject.js /** 这个类可以重复显示纹理图像，支持纹理图像在x轴或y轴偏移 @class */ function RepeatingGameObject() { /** 最终图像占据的宽度 @type Number */ this.width = 0; /** 最终图像占据的高度 @type Number */ [...]]]></description>
			<content:encoded><![CDATA[<p>原文作者：Matthew Casperson • 编辑：Michele McDonough<br />
原文链接: <a href="http://www.brighthub.com/hubfolio/matthew-casperson/blog/archive/2009/06/29/game-development-with-javascript-and-the-canvas-element.aspx" target="_blank">Game Development with JavaScript and the Canvas element</a></p>
<p>1、认识一下Canvas<br />
2、在Canvas上绘图<br />
3、通过Canvas元素实现高级图像操作<br />
4、写一个游戏框架（一）<br />
5、写一个游戏框架（二）<br />
6、通过Canvas实现视差滚动<br />
7、动画<br />
8、JavaScript键盘输入<br />
9、综合运用<br />
10、定义级别<br />
11、跳跃与坠落<br />
12、添加道具<br />
13、加载资源<br />
14、添加主菜单</p>
<h1>在Canvas元素上实现视差滚动</h1>
<p><a href="http://www.brighthub.com/internet/web-development/articles/40511.aspx" target="_blank">http://www.brighthub.com/internet/web-development/articles/40511.aspx</a></p>
<p>视差滚动是在2D应用中创造立体纵深感的一种技术。这篇文章就来看一看在我们刚刚创建的游戏框架基础上实现视差滚动有多容易。</p>
<h2>视差滚动</h2>
<p>有了游戏框架，就可以通过画布元素来做一些好玩的东西了。</p>
<p>视差滚动指的是屏幕上的几个图层发生相对位移的效果，换句话说，背景图层滚动得比它前面的那些图层要慢一些。这种创造视觉纵深感的技术在2D游戏中的应用极为普遍。</p>
<h2>RepeatingGameObject.js</h2>
<pre class="brush: js; ">

/**
    这个类可以重复显示纹理图像，支持纹理图像在x轴或y轴偏移
    @class
*/
function RepeatingGameObject()
{
    /** 最终图像占据的宽度
 	@type Number
    */
    this.width = 0;
    /** 最终图像占据的高度
    	@type Number
    */
    this.height = 0;
    /** 绘制时应用多少scrollX和scrollY
	@type Number
    */
    this.scrollFactor = 1;

    /**
        初始化对象
        @return 对初始化对象的引用
    */
    this.startupRepeatingGameObject = function(image, x, y, z, width, height, scrollFactor)
    {
        this.startupVisualGameObject(image, x, y, z);
        this.width = width;
        this.height = height;
        this.scrollFactor = scrollFactor;
        return this;
    }

    /**
        清理对象
    */
    this.shutdownstartupRepeatingGameObject = function()
    {
        this.shutdownVisualGameObject();
    }

	/**
        把当前元素绘制到后台缓冲
        @param dt 自上一帧绘制起经过的秒数
		@param context 绘制上下文
		@param xScroll x轴的全局滚动值
		@param yScroll y轴的全局滚动值

    */
    this.draw = function(dt, canvas, xScroll, yScroll)
    {
        var areaDrawn = [0, 0];

        for (var y = 0; y &lt; this.height; y += areaDrawn[1])
        {
            for (var x = 0; x &lt; this.width; x += areaDrawn[0])
            {
                // 绘制下一张贴片左上角的点
		var newPosition = [this.x + x, this.y + y];
		// 剩余的绘制空间
                var newFillArea = [this.width - x, this.height - y];
		// 第一次必须从图像的中央开始绘制
		// 后续贴片从上方或左侧绘制
                var newScrollPosition = [0, 0];
                if (x==0) newScrollPosition[0] = xScroll * this.scrollFactor;
                if (y==0) newScrollPosition[1] = yScroll * this.scrollFactor;
                areaDrawn = this.drawRepeat(canvas, newPosition, newFillArea, newScrollPosition);
            }
        }
    }

    this.drawRepeat = function(canvas, newPosition, newFillArea, newScrollPosition)
    {
        // 找到重复绘制纹理图像的起点（左上角）
        var xOffset = Math.abs(newScrollPosition[0]) % this.image.width;
        var yOffset = Math.abs(newScrollPosition[1]) % this.image.height;
        var left = newScrollPosition[0]&lt;0?this.image.width-xOffset:xOffset;
        var top = newScrollPosition[1]&lt;0?this.image.height-yOffset:yOffset;
        var width = newFillArea[0] &lt; this.image.width-left?newFillArea[0]:this.image.width-left;
        var height = newFillArea[1] &lt; this.image.height-top?newFillArea[1]:this.image.height-top;

        // 绘制图像
        canvas.drawImage(this.image, left, top, width, height, newPosition[0], newPosition[1], width, height);

        return [width, height];
    }
}
RepeatingGameObject.prototype = new VisualGameObject();
</pre>
<p>这个RepeatingGameObject类可以让图像在一个确定的区域内重复和滚动。此前，我们已经实现了绘制整幅图像。而RepeatingGameObject的不同之处在于，它拿到一幅图像并用它来填充一块范围既定的区域（其尺寸与绘制的图像无关）。我们通过这个类每次显示一幅大图像（如一座山的全景图）的一小部分，从而创建出一个背景。</p>
<p>也许你已经注意到了GameObjectManager的xScroll和yScroll属性，它们被传递给了GameObject的draw和updata函数。这两个值定义的是摄像机沿x轴或y轴移动了多远。RepeatingGameObject使用这两个值来它们显示的纹理，以创造移动的假象。</p>
<p>首先，定义RepeatingGameObject要绘制的区域。底层的GameObject类的x和y属性定义了左上角位置，而新的width和height属性定义的是绘制区域。</p>
<pre class="brush: js; ">

    /** 最终图像占据的宽度
 	@type Number
    */
    this.width = 0;
    /** 最终图像占据的高度
    	@type Number
    */
    this.height = 0;
    /** 绘制时应用多少scrollX和scrollY
	@type Number
    */
</pre>
<p>而scrollFactor属性用于改变RepeatingGameObject滚动的量，该变化是通过传递到draw函数的xScroll和yScroll来控制的。将scrollFactor设置为小于1的值，会导致滚动变慢，从而造就画面中的远景。</p>
<pre class="brush: js; ">

    /** 绘制时应用多少scrollX和scrollY
	@type Number
    */
    this.scrollFactor = 1;
</pre>
<p>最后两个draw和drawRepeat函数具体负责渲染贴片及偏移的纹理。</p>
<pre class="brush: js; ">

	/**
        把当前元素绘制到后台缓冲
        @param dt 自上一帧绘制起经过的秒数
		@param context 绘制上下文
		@param xScroll x轴的全局滚动值
		@param yScroll y轴的全局滚动值

    */
    this.draw = function(dt, canvas, xScroll, yScroll)
    {
        var areaDrawn = [0, 0];

        for (var y = 0; y &lt; this.height; y += areaDrawn[1])
        {
            for (var x = 0; x &lt; this.width; x += areaDrawn[0])
            {
                // 绘制下一张贴片左上角的点
		var newPosition = [this.x + x, this.y + y];
		// 剩余的绘制空间
                var newFillArea = [this.width - x, this.height - y];
		// 第一次必须从图像的中央开始绘制
		// 后续贴片从上方或左侧绘制
                var newScrollPosition = [0, 0];
                if (x==0) newScrollPosition[0] = xScroll * this.scrollFactor;
                if (y==0) newScrollPosition[1] = yScroll * this.scrollFactor;
                areaDrawn = this.drawRepeat(canvas, newPosition, newFillArea, newScrollPosition);
            }
        }
    }

    this.drawRepeat = function(canvas, newPosition, newFillArea, newScrollPosition)
    {
        // 找到重复绘制纹理图像的起点（左上角）
        var xOffset = Math.abs(newScrollPosition[0]) % this.image.width;
        var yOffset = Math.abs(newScrollPosition[1]) % this.image.height;
        var left = newScrollPosition[0]&lt;0?this.image.width-xOffset:xOffset;
        var top = newScrollPosition[1]&lt;0?this.image.height-yOffset:yOffset;
        var width = newFillArea[0] &lt; this.image.width-left?newFillArea[0]:this.image.width-left;
        var height = newFillArea[1] &lt; this.image.height-top?newFillArea[1]:this.image.height-top;

        // 绘制图像
        canvas.drawImage(this.image, left, top, width, height, newPosition[0], newPosition[1], width, height);

        return [width, height];
    }   
</pre>
<h2>ApplicationManager.js</h2>
<pre class="brush: js; ">

/**
    ApplicationManager用于管理应用
    @class
*/
function ApplicationManager()
{
    /**
        初始化对象
        @return A 对初始化对象的引用
    */
    this.startupApplicationManager = function()
    {
        this.startupGameObject();
	this.background3 = new RepeatingGameObject().startupRepeatingGameObject(g_back2, 0, 100, 3, 600, 320, 1);
        this.background2 = new RepeatingGameObject().startupRepeatingGameObject(g_back1, 0, 100, 2, 600, 320, 0.75);
        this.background = new RepeatingGameObject().startupRepeatingGameObject(g_back0, 0, 0, 1, 600, 320, 0.5);
        return this;
    }

	/**
        更新当前对象
        @param dt 自上一帧绘制起经过的秒数
        @param context 绘制上下文
        @param xScroll x轴的全局滚动值
        @param yScroll y轴的全局滚动值
    */
    this.update = function(/**Number*/ dt, /**CanvasRenderingContext2D*/ context, /**Number*/ xScroll, /**Number*/ yScroll)
    {
		g_GameObjectManager.xScroll += 50 * dt;
	}
}
ApplicationManager.prototype = new GameObject
</pre>
<p>在这里，我们通过ApplicationManager创建了三个RepeatingGameObject类的实例，每个实例分别显示为一个图层，使用z（深度）和scrollFactor值来创造RepeatingGameObject 渐远和渐慢的效果。</p>
<p>最终结果很不错。视差滚动为画布赋予了完美的纵深感，而整个效果只多编写了一个类就实现了。</p>
<p>看一看视差滚动的Demo吧。<a href="http://webdemos.sourceforge.net/jsplatformer4/jsplatformer4.html" target="_blank">http://webdemos.sourceforge.net/jsplatformer4/jsplatformer4.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/08/17/game-development-with-javascript-and-the-canvas-element-5-2645.html/feed</wfw:commentRss>
		<slash:comments>71</slash:comments>
		</item>
		<item>
		<title>使用JavaScript和Canvas开发游戏（四）</title>
		<link>http://www.cn-cuckoo.com/2011/08/15/game-development-with-javascript-and-the-canvas-element-4-2639.html</link>
		<comments>http://www.cn-cuckoo.com/2011/08/15/game-development-with-javascript-and-the-canvas-element-4-2639.html#comments</comments>
		<pubDate>Mon, 15 Aug 2011 11:56:57 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[编程技术]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2639</guid>
		<description><![CDATA[原文作者：Matthew Casperson • 编辑：Michele McDonough 原文链接: Game Development with JavaScript and the Canvas element 1、认识一下Canvas 2、在Canvas上绘图 3、通过Canvas元素实现高级图像操作 4、写一个游戏框架（一） 5、写一个游戏框架（二） 6、通过Canvas实现视差滚动 7、动画 8、JavaScript键盘输入 9、综合运用 10、定义级别 11、跳跃与坠落 12、添加道具 13、加载资源 14、添加主菜单 4、写一个游戏框架（二） 在这篇文章里，我们继续介绍构成这个基本JavaScript游戏框架的其他必要的类。 前一篇文章介绍了GameObjectManager类，该类负责画布的渲染并允许GameObject类更新和删除它们自己。下面就来看一看GameObject类。 GameObject.js /** 游戏中出现的所有元素的基类 @class */ function GameObject() { /** 显示的深度次序。较小的zOrder值表示先渲染，因而会在背景中。 @type Number */ this.zOrder = 0; /** x轴的坐标 @type Number */ this.x = 0; [...]]]></description>
			<content:encoded><![CDATA[<p>原文作者：Matthew Casperson • 编辑：Michele McDonough<br />
原文链接: <a href="http://www.brighthub.com/hubfolio/matthew-casperson/blog/archive/2009/06/29/game-development-with-javascript-and-the-canvas-element.aspx" target="_blank">Game Development with JavaScript and the Canvas element</a></p>
<p>1、认识一下Canvas<br />
2、在Canvas上绘图<br />
3、通过Canvas元素实现高级图像操作<br />
4、写一个游戏框架（一）<br />
5、写一个游戏框架（二）<br />
6、通过Canvas实现视差滚动<br />
7、动画<br />
8、JavaScript键盘输入<br />
9、综合运用<br />
10、定义级别<br />
11、跳跃与坠落<br />
12、添加道具<br />
13、加载资源<br />
14、添加主菜单</p>
<h1>4、写一个游戏框架（二）</h1>
<p>在这篇文章里，我们继续介绍构成这个基本JavaScript游戏框架的其他必要的类。</p>
<p>前一篇文章介绍了GameObjectManager类，该类负责画布的渲染并允许GameObject类更新和删除它们自己。下面就来看一看GameObject类。</p>
<h2>GameObject.js</h2>
<pre class="brush: js; ">

/**
    游戏中出现的所有元素的基类
    @class
*/
function GameObject()
{
    /** 显示的深度次序。较小的zOrder值表示先渲染，因而会在背景中。
        @type Number
    */
    this.zOrder = 0;
    /**
        x轴的坐标
        @type Number
    */
    this.x = 0;
    /**
        y轴的坐标
        @type Number
    */
    this.y = 0;

    /**
        初始化游戏对象，并将其添加到GameObjectManager维护的对象列表中
        @param x        x轴的坐标
        @param y        y轴的坐标
        @param z        元素的z次序（背景元素的z值较小）
    */
    this.startupGameObject = function(/**Number*/ x, /**Number*/ y, /**Number*/ z)
    {
        this.zOrder = z;
        this.x = x;
        this.y = y;
        g_GameObjectManager.addGameObject(this);
        return this;
    }

    /**
        清理当前对象，将其从GameObjectManager维护的对象列表中删除
    */
    this.shutdownGameObject = function()
    {
        g_GameObjectManager.removeGameObject(this);
    }
}
</pre>
<p>这个GameObject类（是一个引擎类）的目的，是为游戏中将会出现的所有对象定义一些共有的属性，包括它们的位置（x和y）和深度（z）。需要注意的是，我们不会直接创建GameObject类的实例，而是会再创建一个类来扩展它。</p>
<p>这个类的x和y坐标值没有什么好说的——就是相应对象左上角位置在画布上的坐标。关键是GameObject中的z值，这个值定义的是对象的深度。理解这个值很重要，这个值较小的GameObject会先绘制到画布上。换句话说，z值较大的GameObject将被绘制到z值较小的GameObject上面。<br />
<span id="more-2639"></span><br />
上一篇文章里介绍过，所有类都是通过一个类似startupClassName的函数完成自身初始化的。因此，GameObject类就有一个名为startupGameObject的函数。在这个函数里，除了初始化所有变量外，还会通过addGameObject函数把当前的GameObject添加到由GameObjectManager维护的GameObject列表中。</p>
<pre class="brush: js; ">

    /**
        初始化游戏对象，并将其添加到GameObjectManager维护的对象列表中
        @param x        x轴的坐标
        @param y        y轴的坐标
        @param z        元素的z次序（背景元素的z值较小）
    */
    this.startupGameObject = function(/**Number*/ x, /**Number*/ y, /**Number*/ z)
    {
        this.zOrder = z;
        this.x = x;
        this.y = y;
        g_GameObjectManager.addGameObject(this);
        return this;
    }
</pre>
<p>函数shutdownGameObject用于清除GameObject。这里所谓的清除，是指GameObject通过removeGameObject函数将自身从GameObjectManager中删除。</p>
<pre class="brush: js; ">

    /**
        清理当前对象，将其从GameObjectManager维护的对象列表中删除
    */
    this.shutdownGameObject = function()
    {
        g_GameObjectManager.removeGameObject(this);
    }
</pre>
<h2>VisualGameObject.js</h2>
<pre class="brush: js; ">

/**
    出现在游戏中的所有元素的基类
    @class
*/
function VisualGameObject()
{
    /**
        由当前对象显示的图像
        @type Image
    */
    this.image = null;

    /**
        将当前元素绘制到后台缓冲
        @param dt 自上一帧绘制起经过的秒数
    */
    this.draw = function(/**Number*/ dt, /**CanvasRenderingContext2D*/ context, /**Number*/ xScroll, /**Number*/ yScroll)
    {
        context.drawImage(this.image, this.x - xScroll, this.y - yScroll);
    }

    /**
        初始化当前对象
        @param image 要显示的图像
    */
    this.startupVisualGameObject = function(/**Image*/ image, /**Number*/ x, /**Number*/ y, /**Number*/ z)
    {
        this.startupGameObject(x, y, z);
        this.image = image;
        return this;
    }

    /**
        清理当前对象
    */
    this.shutdownVisualGameObject = function()
    {
        this.shutdownGameObject();
    }
}
VisualGameObject.prototype = new GameObject;
</pre>
<p>VisualGameObject也是一个引擎类，它扩展了GameObject类，为将在屏幕上绘制的对象定义了更具体的属性和函数。顾名思义，可见对象显然是需要绘制的对象，因此VisualGameObject定义了一个image属性，当把当前对象绘制到后台缓冲时，将以这个属性作为图形的来源。</p>
<pre class="brush: js; ">

    /**
        由当前对象显示的图像
        @type Image
    */
    this.image = null;
</pre>
<p>此外，还需要写几行代码，以便把这个对象实际地绘制到后台缓冲——这就是draw函数了，它接受图像并基于GameObject类中定义的x和y值将其复制到后台缓冲。</p>
<pre class="brush: js; ">

    /**
        将当前元素绘制到后台缓冲
        @param dt 自上一帧绘制起经过的秒数
    */
    this.draw = function(/**Number*/ dt, /**CanvasRenderingContext2D*/ context, /**Number*/ xScroll, /**Number*/ yScroll)
    {
        context.drawImage(this.image, this.x - xScroll, this.y - yScroll);
    }
</pre>
<h2>ApplicationManager.js</h2>
<pre class="brush: js; ">

/**
    ApplicationManager用于管理应用
    @class
*/
function ApplicationManager()
{
    /**
        初始化对象
        @return 对初始化对象的引用
    */
    this.startupApplicationManager = function()
    {
        this.bounce = new Bounce().startupBounce(g_image);
        return this;
    }
}
</pre>
<p>ApplicationManager是第一个应用类，之所以将其归为应用类，是因为它用来定义应用的运行方式，而不是定义与浏览器的底层交互。这个类非常简单，只用来创建并初始化Bounce类的一个新实例。表面上看，创建一个类仅仅是为了创建一个对象有点多此一举。但在更复杂的应用中，把创建和管理游戏对象的逻辑放到一起是很有必要的。</p>
<h2>Bounce.js</h2>
<pre class="brush: js; ">

/**
    测试类，用于演示VisualGameObject类的用法
    @class
*/
function Bounce()
{
	/** x轴的运动方向
        @type Number
    */
	this.xDirection = 1;
	/** y轴的运动方向
        @type Number
    */
	this.yDirection = 1;
	/** 运动速度
        @type Number
    */
	this.speed = 10;

	/**
        初始化对象
        @return 对初始化对象的引用
    */
	this.startupBounce = function(image)
	{
		this.startupVisualGameObject(image, 0, 0, 0);
		return this;
	}

	/**
       更新对象
        @param dt 自上一帧绘制起经过的秒数
        @param context 绘制上下文
        @param xScroll x轴的全局滚动值
        @param yScroll y轴的全局滚动值
    */
	this.update = function (/**Number*/ dt, /**CanvasRenderingContext2D*/context, /**Number*/ xScroll, /**Number*/ yScroll)
	{
		this.x += dt * this.speed * this.xDirection;
		this.y += dt * this.speed * this.yDirection;

		if (this.x &gt;= 450)
		{
			this.x = 450;
			this.xDirection = -1;
		}
		else if (this.x &lt;= 0)
		{
			this.x = 0;
			this.xDirection = 1;
		}

		if (this.y &gt;= 250)
		{
			this.y = 250;
			this.yDirection = -1;
		}
		else if (this.y &lt;= 0)
		{
			this.y = 0;
			this.yDirection = 1;
		}
	}
}
Bounce.prototype = new VisualGameObject;
</pre>
<p>Bounce是第二个应用类，它扩展了VisualGameObject类，并将把自己绘制到屏幕上。Bounce类会显示一幅在屏幕上反弹的图像，效果非常类似第一篇文章中举的例子。这个类是在前面所有类的基础上实现最终动画的关键。</p>
<p>startupBounce函数接受一幅图像，通过调用startupVisualGameObject来初始化这个基本的类。</p>
<pre class="brush: js; ">

	/**
        初始化对象
        @return 对初始化对象的引用
    */
	this.startupBounce = function(image)
	{
		this.startupVisualGameObject(image, 0, 0, 0);
		return this;
	}
</pre>
<p>而update函数（将被GameObjectManager在渲染期间调用）会更新图像的位置，在图像到达画布边缘时反转方向。</p>
<pre class="brush: js; ">

	/**
       更新对象
        @param dt 自上一帧绘制起经过的秒数
        @param context 绘制上下文
        @param xScroll x轴的全局滚动值
        @param yScroll y轴的全局滚动值
    */
	this.update = function (/**Number*/ dt, /**CanvasRenderingContext2D*/context, /**Number*/ xScroll, /**Number*/ yScroll)
	{
		this.x += dt * this.speed * this.xDirection;
		this.y += dt * this.speed * this.yDirection;

		if (this.x &gt;= 450)
		{
			this.x = 450;
			this.xDirection = -1;
		}
		else if (this.x &lt;= 0)
		{
			this.x = 0;
			this.xDirection = 1;
		}

		if (this.y &gt;= 250)
		{
			this.y = 250;
			this.yDirection = -1;
		}
		else if (this.y &lt;= 0)
		{
			this.y = 0;
			this.yDirection = 1;
		}
	}
}
</pre>
<p>就这些了。你可能会想，怎么没有与绘制这个对象有关的代码呢？相应的代码都在VisualGameObject类的draw函数中了。而且，由于VisualGameObject类扩展了GameObject类，所以我们知道每渲染一帧都会调用一次update和draw函数。Bounce类中的所有代码只跟让图像反弹有关，也就是修改变量x和y。</p>
<p>好啦，我们已经创建了一批类，基于这些类也实现了与第一个示例相同的效果。而有了这个框架，再创建游戏就不必因为绘制画布等底层逻辑以及管理游戏对象等问题而重复编码了。</p>
<p>看看示例Demo吧。<a href="http://webdemos.sourceforge.net/jsplatformer3/jsplatformer3.html" target="_blank">http://webdemos.sourceforge.net/jsplatformer3/jsplatformer3.html</a></p>
<p>为之漫笔 最后编辑于：<br />
2011/08/15 @ 22:25</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/08/15/game-development-with-javascript-and-the-canvas-element-4-2639.html/feed</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>使用JavaScript和Canvas开发游戏（三）</title>
		<link>http://www.cn-cuckoo.com/2011/08/14/game-development-with-javascript-and-the-canvas-element-3-2604.html</link>
		<comments>http://www.cn-cuckoo.com/2011/08/14/game-development-with-javascript-and-the-canvas-element-3-2604.html#comments</comments>
		<pubDate>Sun, 14 Aug 2011 00:16:38 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[编程技术]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2604</guid>
		<description><![CDATA[原文作者：Matthew Casperson • 编辑：Michele McDonough 原文链接: Game Development with JavaScript and the Canvas element 1、认识一下Canvas 2、在Canvas上绘图 3、通过Canvas元素实现高级图像操作 4、写一个游戏框架（一） 5、写一个游戏框架（二） 6、通过Canvas实现视差滚动 7、动画 8、JavaScript键盘输入 9、综合运用 10、定义级别 11、跳跃与坠落 12、添加道具 13、加载资源 14、添加主菜单 4、写一个游戏框架（一） http://www.brighthub.com/internet/web-development/articles/40512.aspx 在知道了如何使用画布元素之后，接下来我教大家写一个框架，有了这个框架，我们就可以把它作为基础来创建游戏。在这第一部分，我们会介绍前两个文件/类。 编写代码之前，我们先来看一看随后几篇文章将致力于创建的示例Demo。表面上看起来，这个Demo跟第二篇文章里的那个没啥区别，但如果你看看后台（查看网页源代码）就会发现，为了更方便地创建这个最终效果，一个凝聚不少心血的基础框架已经写好了。 下面我们要介绍的JavaScript代码使用面向对象的方式来编写。对于没有编写过多少JavaScript代码的人来说，恐怕第一眼看到它们会觉得有点奇怪。如果你真的不太熟悉JavaScript的面向对象编程，建议通过Mozilla Developer Network的这个教程https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript来补补课。这篇教程里解释了我们稍后会用到的一些编程技术。 从设计思想上来看，这个框架可以分成两部分：与底层的2D引擎交互的类（用于操作画布、控制渲染循环、处理输入等的代码）和用来创建对象以便构成游戏的类。前者可以归为引擎类，后者可以归为应用类。由于应用类要构建于引擎类之上，所以我们需要先来创建引擎类。 Main.js 如果你研究了前面例子中的代码，就会发现Main.js文件中包含了不少代码。 /** 每秒多少帧 @type Number */ var FPS = 30; /** 两帧间间隔的秒数 @type Number */ var SECONDS_BETWEEN_FRAMES = [...]]]></description>
			<content:encoded><![CDATA[<p>原文作者：Matthew Casperson • 编辑：Michele McDonough<br />
原文链接: <a href="http://www.brighthub.com/hubfolio/matthew-casperson/blog/archive/2009/06/29/game-development-with-javascript-and-the-canvas-element.aspx" target="_blank">Game Development with JavaScript and the Canvas element</a></p>
<p>1、认识一下Canvas<br />
2、在Canvas上绘图<br />
3、通过Canvas元素实现高级图像操作<br />
4、写一个游戏框架（一）<br />
5、写一个游戏框架（二）<br />
6、通过Canvas实现视差滚动<br />
7、动画<br />
8、JavaScript键盘输入<br />
9、综合运用<br />
10、定义级别<br />
11、跳跃与坠落<br />
12、添加道具<br />
13、加载资源<br />
14、添加主菜单</p>
<h1>4、写一个游戏框架（一）</h1>
<p><a href="http://www.brighthub.com/internet/web-development/articles/40512.aspx" target="_blank">http://www.brighthub.com/internet/web-development/articles/40512.aspx</a><br />
在知道了如何使用画布元素之后，接下来我教大家写一个框架，有了这个框架，我们就可以把它作为基础来创建游戏。在这第一部分，我们会介绍前两个文件/类。</p>
<p>编写代码之前，我们先来看一看<a href="http://webdemos.sourceforge.net/jsplatformer3/jsplatformer3.html" target="_blank">随后几篇文章将致力于创建的示例Demo</a>。表面上看起来，这个Demo跟第二篇文章里的那个没啥区别，但如果你看看后台（查看网页源代码）就会发现，为了更方便地创建这个最终效果，一个凝聚不少心血的基础框架已经写好了。<br />
<img class="colorbox-2604"  src="/cache/img/2604_1.jpg" /></p>
<p>下面我们要介绍的JavaScript代码使用面向对象的方式来编写。对于没有编写过多少JavaScript代码的人来说，恐怕第一眼看到它们会觉得有点奇怪。如果你真的不太熟悉JavaScript的面向对象编程，建议通过Mozilla Developer Network的这个教程<a href="https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript" target="_blank">https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript</a>来补补课。这篇教程里解释了我们稍后会用到的一些编程技术。</p>
<p>从设计思想上来看，这个框架可以分成两部分：与底层的2D引擎交互的类（用于操作画布、控制渲染循环、处理输入等的代码）和用来创建对象以便构成游戏的类。前者可以归为引擎类，后者可以归为应用类。由于应用类要构建于引擎类之上，所以我们需要先来创建引擎类。<br />
<span id="more-2604"></span></p>
<h2>Main.js</h2>
<p>如果你研究了前面例子中的代码，就会发现Main.js文件中包含了不少代码。</p>
<pre class="brush: js; ">

/** 每秒多少帧
    @type Number
*/
var FPS = 30;
/** 两帧间间隔的秒数
    @type Number
*/
var SECONDS_BETWEEN_FRAMES = 1 / FPS;
/** GameObjectManager 实例的全局引用
    @type GameObjectManager
*/
var g_GameObjectManager = null;
/** 应用中用到的图像
    @type Image
*/
var g_image = new Image();
g_image.src = &quot;jsplatformer3-smiley.jpg&quot;;

// 将应用的入口设置为init函数
window.onload = init;

/**
    应用的入口
*/
function init()
{
    new GameObjectManager().startupGameObjectManager();
}
</pre>
<p>首先是定义全局变量的代码。然后，跟以前一样，当页面加载完毕后立即运行init函数。在init函数里，创建GameObjectManager类的实例。</p>
<p>这里在GameObjectManager类的实例上调用了startupGameObjectManager函数。这篇文章以及后面的几篇文章还将多次提到几个命名上具有startupClassName形式的函数。这些函数实际上充当了各自类的构造函数，这样做有两个原因。</p>
<p>首先，JavaScript不支持函数重载（至少不容易实现）。如果你想让一个类有多个构造函数，那么这就成了问题。而通过把构造工作分配给另一组函数（如startupClassName1、startupClassName2），就可以比较容易地定义构造类的不同方式了。</p>
<p>第二个原因（很大程度上也是个人的问题）是我经常会在构造函数中引用尚未定义的变量。这可能是我使用C++、Java和C#这些语言落下的毛病，在这些语言里，类变量在源代码中的位置对其在构造函数中的可见性没有影响。拿下面这个C#类为例：</p>
<pre class="brush: js; ">

class Test
{
	public void Test() {this.a = 5;}
	public int a;
}
</pre>
<p>这些代码是合乎语法的，可以正常工作。下面再看看JavaScript中一个相同的例子：</p>
<pre class="brush: js; ">

function Test()
{
	this.a = 5;
	var a;
}
</pre>
<p>这段代码的问题在于，局部变量a在我们把数值5赋给它的时候还不存在。只有运行到var a;这一行，变量a才存在。尽管这个例子有点故意编排的意味，但的确能够说明我所遇到的问题。通过把类的创建放到一个类似startupClassName这样的函数中完成，并且在构造函数中定义（但不初始化）局部变量，然后当我在这些构建函数中引用相应的局部变量时，就能够确保它们一定是存在的。</p>
<h2>GameObjectManager.js</h2>
<pre class="brush: js; ">

/**
    管理游戏中所有对象的管理器
    @class
*/
function GameObjectManager()
{
    /** 保存游戏中对象的数组
        @type Arary
    */
    this.gameObjects = new Array();
    /** 上一次帧被渲染的时间
        @type Date
    */
    this.lastFrame = new Date().getTime();
    /** x轴的全局滚动值
        @type Number
    */
    this.xScroll = 0;
    /** y轴的全局滚动值
        @type Number
    */
    this.yScroll = 0;
    /** 对ApplicationManager实例的引用
        @type ApplicationManager
    */
    this.applicationManager = null;
    /** 对画布元素的引用
        @type HTMLCanvasElement
    */
    this.canvas = null;
    /** 对画布元素2D上下文的引用
        @type CanvasRenderingContext2D
    */
    this.context2D = null;
    /** 对内存中用作后台缓冲区的画布的引用
        @type HTMLCanvasElement
    */
    this.backBuffer = null;
    /** 对后台缓冲画布的2D上下文的引用
        @type CanvasRenderingContext2D
    */
    this.backBufferContext2D = null;

    /**
        初始化这个对象
        @return A reference to the initialised object
    */
    this.startupGameObjectManager = function()
    {
        // 设置引用this对象的全局指针
        g_GameObjectManager = this;

        // 取得画布元素及其2D上下文的引用
        this.canvas = document.getElementById(&#039;canvas&#039;);
        this.context2D = this.canvas.getContext(&#039;2d&#039;);
        this.backBuffer = document.createElement(&#039;canvas&#039;);
        this.backBuffer.width = this.canvas.width;
        this.backBuffer.height = this.canvas.height;
        this.backBufferContext2D = this.backBuffer.getContext(&#039;2d&#039;);

        // 创建一个新的ApplicationManager
        this.applicationManager = new ApplicationManager().startupApplicationManager();

        // 使用setInterval来调用draw函数
        setInterval(function(){g_GameObjectManager.draw();}, SECONDS_BETWEEN_FRAMES);

        return this;
    }

    /**
        渲染循环
    */
    this.draw = function ()
    {
        // 计算从上一帧到现在的时间
        var thisFrame = new Date().getTime();
        var dt = (thisFrame - this.lastFrame)/1000;
        this.lastFrame = thisFrame;

        // 清理绘制上下文
        this.backBufferContext2D.clearRect(0, 0, this.backBuffer.width, this.backBuffer.height);
        this.context2D.clearRect(0, 0, this.canvas.width, this.canvas.height);

        // 首先更新所有游戏对象
        for (x in this.gameObjects)
        {
            if (this.gameObjects[x].update)
            {
                this.gameObjects[x].update(dt, this.backBufferContext2D, this.xScroll, this.yScroll);
            }
        }

        // 然后绘制所有游戏对象
        for (x in this.gameObjects)
        {
            if (this.gameObjects[x].draw)
            {
                this.gameObjects[x].draw(dt, this.backBufferContext2D, this.xScroll, this.yScroll);
            }
        }

        // 将后台缓冲复制到当前显示的画布
        this.context2D.drawImage(this.backBuffer, 0, 0);
    };

    /**
        向gameObjects集合中添加一个GameObject
        @param gameObject The object to add
    */
    this.addGameObject = function(gameObject)
    {
        this.gameObjects.push(gameObject);
        this.gameObjects.sort(function(a,b){return a.zOrder - b.zOrder;})
    };

    /**
        从gameObjects集合中删除一个GameObject
        @param gameObject The object to remove
    */
    this.removeGameObject = function(gameObject)
    {
        this.gameObjects.removeObject(gameObject);
    }
}
</pre>
<p>首先看一看GameObjectManager类。GameObjectManager是一个引擎类，用于管理画布的绘制操作，还负责分派GameObject类（下一篇文章里介绍）的事件。</p>
<p>GameObjectManager类的startupGameObjectManager函数的代码如下：</p>
<pre class="brush: js; ">

    /**
        初始化这个对象
        @return A reference to the initialised object
    */
    this.startupGameObjectManager = function()
    {
        // 设置引用this对象的全局指针
        g_GameObjectManager = this;

        // 取得画布元素及其2D上下文的引用
        this.canvas = document.getElementById(&#039;canvas&#039;);
        this.context2D = this.canvas.getContext(&#039;2d&#039;);
        this.backBuffer = document.createElement(&#039;canvas&#039;);
        this.backBuffer.width = this.canvas.width;
        this.backBuffer.height = this.canvas.height;
        this.backBufferContext2D = this.backBuffer.getContext(&#039;2d&#039;);

        // 创建一个新的ApplicationManager
        this.applicationManager = new ApplicationManager().startupApplicationManager();

        // 使用setInterval来调用draw函数
        setInterval(function(){g_GameObjectManager.draw();}, SECONDS_BETWEEN_FRAMES);

        return this;
    }
</pre>
<p>前面已经说过，我们会把每个类的初始化工作放在startupClassName函数中来做。因此，GameObjectManager类将由startupGameObjectManager函数进行初始化。</p>
<p>而引用这个GameObjectManager实例的全局变量g_GameObjectManager经过重新赋值，指向了这个新实例。</p>
<pre class="brush: js; ">

        // 设置引用this对象的全局指针
        g_GameObjectManager = this;
</pre>
<p>对画布元素及其绘图上下文的引用也同样保存起来：</p>
<pre class="brush: js; ">

        // 取得画布元素及其2D上下文的引用
        this.canvas = document.getElementById(&#039;canvas&#039;);
        this.context2D = this.canvas.getContext(&#039;2d&#039;);
</pre>
<p>在前面的例子中，所有绘图操作都是直接在画布元素上完成的。这种风格的渲染一般称为单缓冲渲染。在此，我们要使用一种叫做双缓冲渲染的技术：任意游戏对象的所有绘制操作，都将在一个内存中的附加画布元素（后台缓冲）上完成，完成后再通过一次操作把它复制到网页上的画布元素（前台缓冲）。</p>
<p>双缓冲技术（<a href="http://www.brighthub.com/internet/web-development/articles/11012.aspx" target="_blank">http://www.brighthub.com/internet/web-development/articles/11012.aspx</a>）通常用于减少画面抖动。我自己在测试的时候从没发现直接向画布元素上绘制有抖动现象，但我在网上的确听别人念叨过，使用单缓冲渲染会导致某些浏览器在渲染时发生抖动。</p>
<p>不管怎么说，双缓冲还是能够避免最终用户看到每个游戏对象在绘制过程中最后一帧的组合过程。在通过JavaScript执行某些复杂绘制操作时（例如透明度、反锯齿及可编程纹理），这种情况是完全可能发生的。</p>
<p>使用附加缓冲技术占用的内存非常少，多执行一次图像复制操作（把后台缓冲绘制到前台缓冲）导致的性能损失也可以忽略不计，可以说实现双缓冲系统没有什么缺点。</p>
<p>如果将在HTML页面中定义的画布元素作为前台缓冲，那就需要再创建一个画布来充当后台缓冲。为此，我们使用了document.createElement函数在内存里创建了一个画布元素，把它用作后台缓冲。</p>
<pre class="brush: js; ">

        this.backBuffer = document.createElement(&#039;canvas&#039;);
        this.backBuffer.width = this.canvas.width;
        this.backBuffer.height = this.canvas.height;
        this.backBufferContext2D = this.backBuffer.getContext(&#039;2d&#039;);
</pre>
<p>接下来，我们创建了ApplicationManager类的一个新实例，并调用startupApplicationManager来初始化它。这个ApplicationManager类将在下一篇文章中介绍。</p>
<pre class="brush: js; ">

        // 创建一个新的ApplicationManager
        this.applicationManager = new ApplicationManager().startupApplicationManager();
</pre>
<p>最后，使用setInterval函数重复调用draw函数，这个函数是渲染循环的核心所在。</p>
<pre class="brush: js; ">

        // 使用setInterval来调用draw函数
        setInterval(function(){g_GameObjectManager.draw();}, SECONDS_BETWEEN_FRAMES);
</pre>
<p>下面来看一看draw函数。</p>
<pre class="brush: js; ">

    /**
        渲染循环
    */
    this.draw = function ()
    {
        // 计算从上一帧到现在的时间
        var thisFrame = new Date().getTime();
        var dt = (thisFrame - this.lastFrame)/1000;
        this.lastFrame = thisFrame;

        // 清理绘制上下文
        this.backBufferContext2D.clearRect(0, 0, this.backBuffer.width, this.backBuffer.height);
        this.context2D.clearRect(0, 0, this.canvas.width, this.canvas.height);

        // 首先更新所有游戏对象
        for (x in this.gameObjects)
        {
            if (this.gameObjects[x].update)
            {
                this.gameObjects[x].update(dt, this.backBufferContext2D, this.xScroll, this.yScroll);
            }
        }

        // 然后绘制所有游戏对象
        for (x in this.gameObjects)
        {
            if (this.gameObjects[x].draw)
            {
                this.gameObjects[x].draw(dt, this.backBufferContext2D, this.xScroll, this.yScroll);
            }
        }

        // 将后台缓冲复制到当前显示的画布
        this.context2D.drawImage(this.backBuffer, 0, 0);
    };
</pre>
<p>这个draw函数就是所有渲染循环的核心。在前面的例子中，渲染循环的函数会直接修改要绘制到屏幕上的对象（笑脸）。如果只需绘制一个对象，这样做没有问题。但是，一个游戏要由几十个单独的对象组成，所以这个draw函数并没有直接在渲染循环中直接处理要绘制的对象，而是维护了一个保存着这些对象的数组，让这些对象自己来更新和绘制自己。</p>
<p>首先，计算自上一帧渲染所经过的时间。即便我们在代码里写了每秒钟调用30次draw函数，但谁也无法保证事实如此。通过计算自上一帧渲染所经过的时间，可以做到尽可能让游戏的执行与帧速率无关。</p>
<pre class="brush: js; ">

        // 计算从上一帧到现在的时间
        var thisFrame = new Date().getTime();
        var dt = (thisFrame - this.lastFrame)/1000;
        this.lastFrame = thisFrame;
</pre>
<p>接着清理绘制上下文。</p>
<pre class="brush: js; ">

        // 清理绘制上下文
        this.backBufferContext2D.clearRect(0, 0, this.backBuffer.width, this.backBuffer.height);
        this.context2D.clearRect(0, 0, this.canvas.width, this.canvas.height);
</pre>
<p>然后，就是调用游戏对象（这些对象是由GameObject类定义的，下一篇文章将介绍该类）自己的更新（update）和绘制（draw）方法。注意，这两个方法是可选的（这也是我们在调用它们之前先检查它们是否存在的原因），但差不多每一个对象都需要更新和绘制自已。</p>
<pre class="brush: js; ">

        // 首先更新所有游戏对象
        for (x in this.gameObjects)
        {
            if (this.gameObjects[x].update)
            {
                this.gameObjects[x].update(dt, this.backBufferContext2D, this.xScroll, this.yScroll);
            }
        }

        // 然后绘制所有游戏对象
        for (x in this.gameObjects)
        {
            if (this.gameObjects[x].draw)
            {
                this.gameObjects[x].draw(dt, this.backBufferContext2D, this.xScroll, this.yScroll);
            }
        }
</pre>
<p>最后，把后台缓冲复制到前台缓冲，最终用户就可以看到下一帧了。</p>
<pre class="brush: js; ">

        // 将后台缓冲复制到当前显示的画布
        this.context2D.drawImage(this.backBuffer, 0, 0);
</pre>
<p>理解了draw函数，下面再分别讲一讲addGameObject和removeGameObject函数。</p>
<pre class="brush: js; ">

    /**
        向gameObjects集合中添加一个GameObject
        @param gameObject The object to add
    */
    this.addGameObject = function(gameObject)
    {
        this.gameObjects.push(gameObject);
        this.gameObjects.sort(function(a,b){return a.zOrder - b.zOrder;})
    };

    /**
        从gameObjects集合中删除一个GameObject
        @param gameObject The object to remove
    */
    this.removeGameObject = function(gameObject)
    {
        this.gameObjects.removeObject(gameObject);
    }
</pre>
<p>利用addGameObject和removeGameObject（在Utils.js文件里通过扩展Array.prototype添加）函数，可以在GameObjectManager所维护的GameObject集合（即gameObjects变量）中添加和删除游戏对象。</p>
<p>GameObjectManager类是我们这个游戏框架中最复杂的一个类。在下一篇文章中，我们会讲解游戏框架的另外几个类：GameObject、VisualGameObject、Bounce和ApplicationManager。</p>
<p>好了，现在放松一下，<a href="http://webdemos.sourceforge.net/jsplatformer3/jsplatformer3.html" target="_blank">看一看Demo吧</a>。</p>
<p>为之漫笔 最后编辑于：<br />
2011/08/14 @ 23:19</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/08/14/game-development-with-javascript-and-the-canvas-element-3-2604.html/feed</wfw:commentRss>
		<slash:comments>28</slash:comments>
		</item>
		<item>
		<title>使用JavaScript和Canvas开发游戏（二）</title>
		<link>http://www.cn-cuckoo.com/2011/08/11/game-development-with-javascript-and-the-canvas-element-2-2585.html</link>
		<comments>http://www.cn-cuckoo.com/2011/08/11/game-development-with-javascript-and-the-canvas-element-2-2585.html#comments</comments>
		<pubDate>Thu, 11 Aug 2011 11:41:56 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[编程技术]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2585</guid>
		<description><![CDATA[原文作者：Matthew Casperson • 编辑：Michele McDonough 原文链接: Game Development with JavaScript and the Canvas element 1、认识一下Canvas 2、在Canvas上绘图 3、通过Canvas元素实现高级图像操作 4、通过Canvas实现视差滚动 5、写一个游戏框架（一） 6、写一个游戏框架（二） 7、动画 8、JavaScript键盘输入 9、综合运用 10、定义级别 11、跳跃与坠落 12、添加道具 13、加载资源 14、添加主菜单 3、通过Canvas元素实现高级图像操作 http://www.brighthub.com/internet/web-development/articles/39509.aspx 这篇文章将带领大家学习使用JavaScript和Canvas元素操作图像了几种不同的方式，这些方式在Canvas元素出现之前是不可能的事儿。 上一篇文章演示了如何利用Canvas实现一个基本的图像动画。那个例子很简单，同样的效果通过修改IMG或DIV等标准HTML元素的一些属性，照样也可以轻易实现。下面我们就来演示一下画布元素的高级应用，展示一下它的真正威力。 首先，还是准备一个HTML页面。 &#60;!DOCTYPE HTML PUBLIC &#34;-//W3C//DTD HTML 4.01//EN&#34;&#62; &#60;html lang=&#34;en&#34;&#62; &#60;head&#62; &#60;title&#62;JavaScript Platformer 2&#60;/title&#62; &#60;script type=&#34;text/javascript&#34; src=&#34;jsplatformer2.js&#34;&#62;&#60;/script&#62; &#60;style type=&#34;text/css&#34;&#62; body { font-family: Arial,Helvetica,sans-serif;} &#60;/style&#62; [...]]]></description>
			<content:encoded><![CDATA[<p>原文作者：Matthew Casperson • 编辑：Michele McDonough<br />
原文链接: <a href="http://www.brighthub.com/hubfolio/matthew-casperson/blog/archive/2009/06/29/game-development-with-javascript-and-the-canvas-element.aspx" target="_blank">Game Development with JavaScript and the Canvas element</a></p>
<p>1、认识一下Canvas<br />
2、在Canvas上绘图<br />
3、通过Canvas元素实现高级图像操作<br />
4、通过Canvas实现视差滚动<br />
5、写一个游戏框架（一）<br />
6、写一个游戏框架（二）<br />
7、动画<br />
8、JavaScript键盘输入<br />
9、综合运用<br />
10、定义级别<br />
11、跳跃与坠落<br />
12、添加道具<br />
13、加载资源<br />
14、添加主菜单</p>
<h1>3、通过Canvas元素实现高级图像操作</h1>
<p><a href="http://www.brighthub.com/internet/web-development/articles/39509.aspx" target="_blank">http://www.brighthub.com/internet/web-development/articles/39509.aspx</a></p>
<p>这篇文章将带领大家学习使用JavaScript和Canvas元素操作图像了几种不同的方式，这些方式在Canvas元素出现之前是不可能的事儿。</p>
<p>上一篇文章演示了如何利用Canvas实现一个基本的图像动画。那个例子很简单，同样的效果通过修改IMG或DIV等标准HTML元素的一些属性，照样也可以轻易实现。下面我们就来演示一下画布元素的高级应用，展示一下它的真正威力。</p>
<p>首先，还是准备一个HTML页面。</p>
<pre class="brush: js; ">

  &lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01//EN&quot;&gt;
  &lt;html lang=&quot;en&quot;&gt;
     &lt;head&gt;
        &lt;title&gt;JavaScript Platformer 2&lt;/title&gt;
        &lt;script type=&quot;text/javascript&quot; src=&quot;jsplatformer2.js&quot;&gt;&lt;/script&gt;
        &lt;style type=&quot;text/css&quot;&gt;
           body { font-family: Arial,Helvetica,sans-serif;}
        &lt;/style&gt;
     &lt;/head&gt;
    &lt;body&gt;
       &lt;p&gt;
          &lt;a href=&quot;http://www.brighthub.com/internet/web-development/articles/38364.aspx&quot;&gt;
             Game Development with Javascript and the canvas element
          &lt;/a&gt;
       &lt;/p&gt;
       &lt;canvas id=&quot;canvas&quot; width=&quot;600&quot; height=&quot;400&quot;&gt;
          &lt;p&gt;Your browser does not support the canvas element.&lt;/p&gt;
       &lt;/canvas&gt;
       &lt;br /&gt;
       &lt;button onclick=&quot;currentFunction=alpha;&quot;&gt;Change Alpha&lt;/button&gt;
       &lt;button onclick=&quot;currentFunction=shear;&quot;&gt;Shear&lt;/button&gt;
       &lt;button onclick=&quot;currentFunction=scale;&quot;&gt;Scale&lt;/button&gt;
       &lt;button onclick=&quot;currentFunction=rotate;&quot;&gt;Rotate&lt;/button&gt;
    &lt;/body&gt;
 &lt;/html&gt;
</pre>
<p>与上个一例子的HTML页面相比，唯一的区别就是添加了一些按钮。单击这些按钮，就会设置currentFunction变量（稍后介绍）的值，用以改变在渲染循环中运行的函数。<br />
<span id="more-2585"></span><br />
以下是 jsplatformer2.js 的代码。</p>
<pre class="brush: js; ">

 // 每秒多少帧
 const FPS = 30;
 const SECONDSBETWEENFRAMES = 1 / FPS;
 const HALFIMAGEDIMENSION = 75;
 const HALFCANVASWIDTH = 300;
 const HALFCANVASHEIGHT = 200;
 var image = new Image();
 image.src = &quot;jsplatformer2-smiley.jpg&quot;; //还是第一个例子中的图像
 var canvas = null;
 var context2D = null;
 var currentFunction = null;
 var currentTime = 0;
 var sineWave = 0;

 window.onload = init;

 function init()
 {
    canvas = document.getElementById(&#039;canvas&#039;);
    context2D = canvas.getContext(&#039;2d&#039;);
    setInterval(draw, SECONDSBETWEENFRAMES * 1000);
    currentFunction = scale;
 }

 function draw()
 {
     currentTime += SECONDSBETWEENFRAMES;
     sineWave = (Math.sin(currentTime) + 1) / 2;

     context2D.clearRect(0, 0, canvas.width, canvas.height);

     context2D.save();

     context2D.translate(HALFCANVASWIDTH - HALFIMAGEDIMENSION, HALFCANVASHEIGHT - HALFIMAGEDIMENSION);

     currentFunction();

     context2D.drawImage(image, 0, 0);

     context2D.restore();
 }

 function alpha()
 {
     context2D.globalAlpha = sineWave;
 }

 function shear()
 {
     context2D.transform(1, 0, (sineWave - 0.5), 1, 0, 0);
 }

 function scale()
 {
     context2D.translate(HALFIMAGEDIMENSION * (1 - sineWave), HALFIMAGEDIMENSION * (1 - sineWave));
     context2D.scale(sineWave, sineWave);
 }

 function rotate()
 {
     context2D.translate(HALFIMAGEDIMENSION, HALFIMAGEDIMENSION);
     context2D.rotate(sineWave * Math.PI * 2);
     context2D.translate(-HALFIMAGEDIMENSION, -HALFIMAGEDIMENSION);
 }
</pre>
<p>跟前面一样，这个JavaScript文件先定义了一些全局变量。</p>
<ul>
<li>
FPS：每秒多少帧
</li>
<li>
SECONDSBETWEENFRAMES：两帧之间间隔的秒数（FPS的倒数）
</li>
<li>
HALFIMAGEDIMENSION：要绘制图像的宽度/高度的一半，用于把图像定位到画布的中心点
</li>
<li>
HALFCANVASWIDTH：画布宽度的一半，用于配合HALFIMAGEDIMENSION使用，以便在画布上居中图像
</li>
<li>
HALFCANVASHEIGHT：画布高度的一半，用于配合HALFIMAGEDIMENSION使用，以便在画布上居中图像
</li>
<li>
currentFunction：渲染循环（参见上一篇文章）中运行的函数
</li>
<li>
currentTime：应用已经运行了多少秒
</li>
<li>
sineWave：0到1之间的一个值，用于控制图像的运动
</li>
<li>
image：要在画布上绘制的图像
</li>
<li>
canvas：画布元素的引用
</li>
<li>
context2D：画布元素的2D上下文的引用
</li>
</ul>
<p>然后，跟前面一样，要设置在window的onload事件发生时立即调用init函数（关于init函数的介绍，请参见上一篇文章）。</p>
<h2>draw函数</h2>
<p>下面来看一看draw函数：</p>
<pre class="brush: js; ">

function draw()
{
    currentTime += SECONDSBETWEENFRAMES;
    sineWave = (Math.sin(currentTime) + 1) / 2;

    context2D.clearRect(0, 0, canvas.width, canvas.height);

    context2D.save();
    context2D.translate(HALFCANVASWIDTH - HALFIMAGEDIMENSION, HALFCANVASHEIGHT - HALFIMAGEDIMENSION);
    currentFunction();
    context2D.drawImage(image, 0, 0);
    context2D.restore();
}
</pre>
<p>这个例子要演示4种效果：修改alpha值（透明度），以及缩放、旋转和切变图像。为了展示这些效果，需要基于某一范围内的值来应用变化。变量sineWave就用来定义这个范围值的基准。</p>
<p>标准的正弦函数能够在-1到1之间产生非常完美的波形图。首先，我们通过递增currentTime变量来反映动画已经运行了多长时间，然后再利用这个值在正弦曲线上找到一个点。给正弦函数返回的值（从-1到1）先加1再除以2，就可以把它们转换成0到1这个范围内的值。</p>
<pre class="brush: js; ">

    currentTime += SECONDSBETWEENFRAMES;
    sineWave = (Math.sin(currentTime) + 1) / 2;
</pre>
<p>然后，调用clearRect方法清空画布，以便为后面的绘图准备一个干净的版面。</p>
<pre class="brush: js; ">

    context2D.clearRect(0, 0, canvas.width, canvas.height);
</pre>
<p>应用到画布上面的效果是可以累积的，因而就可以利用几个简单的函数来“组合”出效果来。例如，在向屏幕上绘制之前，可能会有一艘飞船需要旋转、变换和缩放。因为所有效果都对画布起作用，所以这些效果会应用到将被绘制在屏幕上的所有对象，而不仅仅是某一幅图像或某一个形状（比如一艘飞船）。</p>
<p>其中，save和restore函数为应用这些累积的效果提供了一种简单的机制，可以将应用了这些效果的图像或图形绘制到画布上，然后“撤销”这些改变。后台的操作是什么呢？save函数把当前的绘制状态推进栈里，而restore函数则把最后一个状态弹出栈。还拿前面提到的飞船为例，需要执行下列操作：</p>
<ul>
<li>调用save函数（保存当前的绘制状态）</li>
<li>旋转、变换和缩放上下文</li>
<li>绘制飞船</li>
<li>调用restore函数，移除自上一次调用save方法以来所添加的任何效果，也就是撤销之前的变化</li>
</ul>
<p>在这里，我们就是要组合起来使用这两个方法。首先，在把任何效果应用到画布之前，先保存绘制状态。</p>
<pre class="brush: js; ">

    context2D.save();
</pre>
<p>保存了绘制状态之后，就该应用目标效果了。为此，首先调用translate函数，从而将随后要绘制的图像在画布上居中。</p>
<pre class="brush: js; ">

    context2D.translate(HALFCANVASWIDTH - HALFIMAGEDIMENSION, HALFCANVASHEIGHT - HALFIMAGEDIMENSION);
</pre>
<p>接下来，调用由变量currentFunction引用的函数。正是这些被引用的函数，是让图像发生alpha（透明度）变化以及缩放、旋转和切变的关键。这些函数我们稍后再介绍。</p>
<pre class="brush: js; ">

    currentFunction();
</pre>
<p>为图像应用完效果之后，就可以把它绘制到画布上面了。所以，接下来就是调用drawImage来绘图。</p>
<pre class="brush: js; ">

    context2D.drawImage(image, 0, 0);
</pre>
<p>最后，再调用restore函数，把自调用save函数以来应用的所有效果从画布上移除。</p>
<pre class="brush: js; ">

    context2D.restore();
</pre>
<h2>alpha函数</h2>
<pre class="brush: js; ">

 function alpha()
 {
     context2D.globalAlpha = sineWave;
 }
</pre>
<p>通过修改上下文对象的globalAlpha属性，所有后续绘制操作的透明度都会被修改。将globalAlpha设置为0，意味着被绘制的任何对象都将完全透明，而将这个属性设置为1，则意味着任何绘制操作都会保持原有的透明度级别。在此，我们通过修改这个globalAlpha属性，可以实现笑脸的淡入和淡出效果。</p>
<h2>shear函数</h2>
<pre class="brush: js; ">

 function shear()
 {
     context2D.transform(1, 0, (sineWave - 0.5), 1, 0, 0);
 }
</pre>
<p>切变操作是通过transform函数向画布应用一个矩阵来实现的。变换矩阵本身就是一个值得研究的主题，但对我们来说，如果不想理解背后的数学原理，可以在网上找到很多标准的2D变换矩阵（<a href="http://en.wikipedia.org/wiki/Transformation_matrix#Examples_in_2D_graphics" target="_blank">http://en.wikipedia.org/wiki/Transformation_matrix#Examples_in_2D_graphics</a>），直接使用transform函数来应用它们即可。所谓切变，其实就是把图像的顶部或底部推到一边。</p>
<h2>scale函数</h2>
<pre class="brush: js; ">

 function scale()
 {
     context2D.translate(HALFIMAGEDIMENSION * (1 - sineWave), HALFIMAGEDIMENSION * (1 - sineWave));
　   context2D.scale(sineWave, sineWave);
 }
</pre>
<p>顾名思义，scale（缩放）函数修改的是图像的大小。但在此之前，我们还调用了一次transalte函数。这是为了让缩放后的图像在画布上居中。如果你把这行代码注释掉，就会发现图像会从左上角向右下角膨胀。调用translate函数就是为抵消其圆心的位移，让图像始终居中。</p>
<h2>rotate函数</h2>
<pre class="brush: js; ">

 function rotate()
 {
     context2D.translate(HALFIMAGEDIMENSION, HALFIMAGEDIMENSION);
     context2D.rotate(sineWave * Math.PI * 2);
     context2D.translate(-HALFIMAGEDIMENSION, -HALFIMAGEDIMENSION);
 }
</pre>
<p>与scale函数类似，rotate（旋转）函数的作用也正如其名：旋转图像。与scale函数同样类似的是，这里也额外调用了translate函数以确保图像围绕中心点而不是左上角旋转。建议大家把对translate函数的调用注释掉，自己看一看结果有什么不同。</p>
<p>刚刚我们看到了使用画布元素实现的4种也还算简单的效果，这些效果使用标准的HTML元素几乎是不可能做到的。其中，有的效果可以使用scale和rotate等内置函数来实现，而使用transform函数则可以完成大量的图像操作（切变只是其中之一）。</p>
<p>看看Demo吧。<a href="http://webdemos.sourceforge.net/jsplatformer2/jsplatformer2.html" target="_blank">http://webdemos.sourceforge.net/jsplatformer2/jsplatformer2.html</a></p>
<p>为之漫笔 最后编辑于：<br />
2011/08/12 @ 06:29</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/08/11/game-development-with-javascript-and-the-canvas-element-2-2585.html/feed</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>使用JavaScript和Canvas开发游戏（一）</title>
		<link>http://www.cn-cuckoo.com/2011/08/10/game-development-with-javascript-and-the-canvas-element-2554.html</link>
		<comments>http://www.cn-cuckoo.com/2011/08/10/game-development-with-javascript-and-the-canvas-element-2554.html#comments</comments>
		<pubDate>Wed, 10 Aug 2011 12:26:29 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[编程技术]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2554</guid>
		<description><![CDATA[原文作者：Matthew Casperson • 编辑：Michele McDonough 原文链接: Game Development with JavaScript and the Canvas element 1、认识一下Canvas 2、在Canvas上绘图 3、通过Canvas元素实现高级图像操作 4、通过Canvas实现视差滚动 5、写一个游戏框架（一） 6、写一个游戏框架（二） 7、动画 8、JavaScript键盘输入 9、综合运用 10、定义级别 11、跳跃与坠落 12、添加道具 13、加载资源 14、添加主菜单 1、认识一下Canvas http://www.brighthub.com/internet/web-development/articles/38364.aspx Canvas元素以及JavaScript引擎中新增的一些特性，让Web开发人员不必借助第三方插件，即可设计开发出精细且具有交互性的2D网页。这篇文章就向大家介绍一下Canvas元素，以及它的一些可能的用途。 JavaScript与Canvas元素 HTML是为创建静态页面而生的。HTML所能实现的动态效果，也仅限于显示GIF动画和闪烁的文本。JavaScript改变了这一切，通过它能够动态修改网页。今天，很多Web服务都利用AJAX来创建网页，为用户提供更加流畅的体验，也超越了标准HTML页面中常见的“点击－重新加载－点击”式的交互模式。 然而，JavaScript的某些功能会受到其宿主浏览器的制约。尽管可以在网页中创建和修改任何元素，但JavaScript不能（轻易地）让浏览器显示一种新对象。通过JavaScript修改文本、插入图像或者缩放表格都很容易，因为这些对象本来就是HTML所支持的。如果你想再玩得刺激一点，比如写一个网页游戏，怎么办？那恐怕就得苦心积虑地改变标准HTML元素的用途，克服种种不测才能达到目的。要么，你就得求助于Flash或Silverlight这样的插件。 Canvas元素登场了。这个新HTML元素为JavaScript开发者提供了一种无需插件即可在网页中直接绘图的机制。Canvas元素最早是由苹果公司在其WebKit框架中引入的，Safari浏览器和Dashboard微件都在使用。Canvas元素现在也被建议加入了HTML5规范，得到了最新的Chrome、Firefox、Opera以及Konqueror等浏览器的支持。Internet Explorer（至少在IE8之前）还不支持Canvas，但ExplorerCanvas项目倒是为IE提供了与Canvas元素类似的功能。 Canvas元素对做过2D图形编程的人是小菜一碟。可以在这个元素上画线、画各种形状、画渐变，甚至可以利用与其他2D API中类似的函数来修改其中的每一个像素。得益于Chrome的V8、Firefox的SpiderMonkey以及Safari的Nitro等最新JavaScript引擎的性能，创建精细且具有交互性的Web应用已经完全没有问题。 我们这一系列文章将教会大家使用JavaScript和Canvas元素创建一个简单的平台游戏。将要涉及的内容包括动画、加载资源、分层渲染、滚动和交互。通过一步一步地展示示例代码和实际效果，你可以很快学会如何驾驭强大的Canvas元素。 2、在Canvas上绘图 http://www.brighthub.com/internet/web-development/articles/38744.aspx 下面，我们就通过一个循序渐进的示例及实时演示，来介绍如何使用JavaScript在Canvas元素上绘图及实现动画。 准备工作 知道了什么是Canvas元素之后，该学习在屏幕上绘图了。首先，需要一个HTML页面来放置和显示Canvas元素。 &#60;!DOCTYPE HTML PUBLIC &#34;-//W3C//DTD HTML 4.01//EN&#34;&#62; &#60;html lang=&#34;en&#34;&#62; &#60;head&#62; &#60;title&#62;JavaScript Platformer [...]]]></description>
			<content:encoded><![CDATA[<p>原文作者：Matthew Casperson • 编辑：Michele McDonough<br />
原文链接: <a href="http://www.brighthub.com/hubfolio/matthew-casperson/blog/archive/2009/06/29/game-development-with-javascript-and-the-canvas-element.aspx" target="_blank">Game Development with JavaScript and the Canvas element</a></p>
<p>1、认识一下Canvas<br />
2、在Canvas上绘图<br />
3、通过Canvas元素实现高级图像操作<br />
4、通过Canvas实现视差滚动<br />
5、写一个游戏框架（一）<br />
6、写一个游戏框架（二）<br />
7、动画<br />
8、JavaScript键盘输入<br />
9、综合运用<br />
10、定义级别<br />
11、跳跃与坠落<br />
12、添加道具<br />
13、加载资源<br />
14、添加主菜单</p>
<h1>1、认识一下Canvas</h1>
<p><a href="http://www.brighthub.com/internet/web-development/articles/38364.aspx" target="_blank">http://www.brighthub.com/internet/web-development/articles/38364.aspx</a></p>
<p>Canvas元素以及JavaScript引擎中新增的一些特性，让Web开发人员不必借助第三方插件，即可设计开发出精细且具有交互性的2D网页。这篇文章就向大家介绍一下Canvas元素，以及它的一些可能的用途。</p>
<h2>JavaScript与Canvas元素</h2>
<p>HTML是为创建静态页面而生的。HTML所能实现的动态效果，也仅限于显示GIF动画和闪烁的文本。JavaScript改变了这一切，通过它能够动态修改网页。今天，很多Web服务都利用AJAX来创建网页，为用户提供更加流畅的体验，也超越了标准HTML页面中常见的“点击－重新加载－点击”式的交互模式。</p>
<p>然而，JavaScript的某些功能会受到其宿主浏览器的制约。尽管可以在网页中创建和修改任何元素，但JavaScript不能（轻易地）让浏览器显示一种新对象。通过JavaScript修改文本、插入图像或者缩放表格都很容易，因为这些对象本来就是HTML所支持的。如果你想再玩得刺激一点，比如写一个网页游戏，怎么办？那恐怕就得苦心积虑地改变标准HTML元素的用途，克服种种不测才能达到目的。要么，你就得求助于Flash或Silverlight这样的插件。</p>
<p>Canvas元素登场了。这个新HTML元素为JavaScript开发者提供了一种无需插件即可在网页中直接绘图的机制。Canvas元素最早是由苹果公司在其WebKit框架中引入的，Safari浏览器和Dashboard微件都在使用。Canvas元素现在也被建议加入了HTML5规范，得到了最新的Chrome、Firefox、Opera以及Konqueror等浏览器的支持。Internet Explorer（至少在IE8之前）还不支持Canvas，但ExplorerCanvas项目倒是为IE提供了与Canvas元素类似的功能。</p>
<p>Canvas元素对做过2D图形编程的人是小菜一碟。可以在这个元素上画线、画各种形状、画渐变，甚至可以利用与其他2D API中类似的函数来修改其中的每一个像素。得益于Chrome的V8、Firefox的SpiderMonkey以及Safari的Nitro等最新JavaScript引擎的性能，创建精细且具有交互性的Web应用已经完全没有问题。</p>
<p>我们这一系列文章将教会大家使用JavaScript和Canvas元素创建一个简单的平台游戏。将要涉及的内容包括动画、加载资源、分层渲染、滚动和交互。通过一步一步地展示示例代码和实际效果，你可以很快学会如何驾驭强大的Canvas元素。</p>
<h1>2、在Canvas上绘图</h1>
<p><a href="http://www.brighthub.com/internet/web-development/articles/38744.aspx" target="_blank">http://www.brighthub.com/internet/web-development/articles/38744.aspx</a></p>
<p>下面，我们就通过一个循序渐进的示例及实时演示，来介绍如何使用JavaScript在Canvas元素上绘图及实现动画。</p>
<h2>准备工作</h2>
<p>知道了什么是Canvas元素之后，该学习在屏幕上绘图了。首先，需要一个HTML页面来放置和显示Canvas元素。<br />
<span id="more-2554"></span></p>
<pre class="brush: html; ">

  &lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01//EN&quot;&gt;
  &lt;html lang=&quot;en&quot;&gt;
     &lt;head&gt;
        &lt;title&gt;JavaScript Platformer 1&lt;/title&gt;
        &lt;script type=&quot;text/javascript&quot; src=&quot;jsplatformer1.js&quot;&gt;&lt;/script&gt;
        &lt;style type=&quot;text/css&quot;&gt;
           body { font-family: Arial,Helvetica,sans-serif;}
        &lt;/style&gt;
     &lt;/head&gt;
    &lt;body&gt;
       &lt;p&gt;
          &lt;a href=&quot;http://www.brighthub.com/internet/web-development/articles/38364.aspx&quot;&gt;
             Game Development with Javascript and the canvas element
          &lt;/a&gt;
       &lt;/p&gt;
       &lt;canvas id=&quot;canvas&quot; width=&quot;600&quot; height=&quot;400&quot;&gt;
          &lt;p&gt;Your browser does not support the canvas element.&lt;/p&gt;
       &lt;/canvas&gt;
    &lt;/body&gt;
 &lt;/html&gt;
</pre>
<p>这些HTML代码很直观。其中有两个重要的元素。</p>
<pre class="brush: js; ">

&lt;script type=&quot;text/javascript&quot; src=&quot;jsplatformer1.js&quot;&gt;&lt;/script&gt;
</pre>
<p>这里包含的是将会修改Canvas元素的JavaScript代码，对应的Canvas元素的标记如下：</p>
<pre class="brush: js; ">

&lt;canvas id=&quot;canvas&quot; width=&quot;600&quot; height=&quot;400&quot;&gt;
	&lt;p&gt;Your browser does not support the canvas element.&lt;/p&gt;
&lt;/canvas&gt;
</pre>
<p>以上代码创建了一个Canvas元素。不支持Canvas的浏览器，比如Internet Explorer（IE8之前的版本），会忽略这个元素，而只显示其子元素。在这个简单的例子中，这个子元素就是一个段落，其中的文本告诉用户他们的浏览器不支持Canvas元素。而对于那些支持Canvas元素的浏览器，如Chrome、Opera和Firefox，则会忽略Canvas元素的子元素。</p>
<p>这个Canvas元素的ID属性很重要，因为后面的JavaScript将通过它来取得对该元素的引用。而width和height属性指定了画布的宽度和高度，这两个属性跟table或img等其他HTML元素中的同名属性作用一样。</p>
<p>以下是 jsplatformer1.js的代码：</p>
<pre class="brush: js; ">

//每秒钟target帧
const FPS = 30;
var x = 0;
var y = 0;
var xDirection = 1;
var yDirection = 1;
var image = new Image();
//建议读者将图片下载到本地加载（经测试，此图片响应头部的Content-Type为application/empty，浏览器无法识别）
image.src = &quot;http://javascript-tutorials.googlecode.com/files/jsplatformer1-smiley.jpg&quot;;
var canvas = null;
var context2D = null;

window.onload = init;
function init(){
	canvas = document.getElementById(&#039;canvas&#039;);
	context2D = canvas.getContext(&#039;2d&#039;);
	setInterval(draw, 1000/FPS);
}
function draw(){
	context2D.clearRect(0, 0, canvas.width, canvas.height);
	context2D.drawImage(image, x, y);
	x += 1* xDirection;
	y += 1* yDirection;

	if (x &gt;= 450) {
		x = 450;
		xDirection = -1;
	}else if(x &lt;= 0){
		x = 0;
		xDirection = 1;
	}
	if (y &gt;= 250) {
		y = 250;
		yDirection = -1;
	}else if(y &lt;= 0){
		y = 0;
		yDirection = 1;
	}
}
</pre>
<p>如果只是一个Canvas元素，也没有什么用。JavaScript必须要在这块画布上面画点什么，相应的代码保存在 jsplatformer1.js中。简单来说，JavaScript在这里先加载了一幅图像，然后将其画在画布上面，最后让它在画布上移动。</p>
<p>首先，定义一些全局变量。</p>
<pre class="brush: js; ">

const FPS = 30;
</pre>
<p>FPS定义的是画布重绘的频率。</p>
<pre class="brush: js; ">

var x = 0;
var y = 0;
var xDirection = 1;
var yDirection = 1;
</pre>
<p>变量x、y、xDirection和yDirection用于定义图像（相对于画布左上角）的位置，以及它在任意一时刻移动的方向。</p>
<pre class="brush: js; ">

var image = new Image();
image.src = &quot;http://javascript-tutorials.googlecode.com/files/jsplatformer1-smiley.jpg&quot;;
</pre>
<p>要把图像画到画布上，必须先加载一幅图像。为此，我们创建一个Image对象，将其src属性设置为一幅图像文件的URL（建议把图片下载到本地。——译者注）。</p>
<pre class="brush: js; ">

var canvas = null;
var context2D = null;
</pre>
<p>我们还需要取得对Canvas元素以及绘图上下文（稍后再详细介绍绘图上下文）的引用。稍后我们会把正确的值赋给这两个变量，现在先把它们设置为null。</p>
<pre class="brush: js; ">

window.onload = init;
</pre>
<p>最后，当页面加载完成后，我们必须知道立即运行绘制画布的代码；因此，在window对象的onload事件发生时，立即调用init函数。</p>
<h2>init函数</h2>
<pre class="brush: js; ">

function init(){
	canvas = document.getElementById(&#039;canvas&#039;);
	context2D = canvas.getContext(&#039;2d&#039;);
	setInterval(draw, 1000/FPS);
}
</pre>
<p>页面加载完毕后就会调用上面这个init函数。在这个函数中，我们先通过在HTML文件中指定的ID属性取得画布元素（毫无疑问，除了把它叫做画布，还能叫个啥？），然后再取得这个画布的2D绘图上下文对象。</p>
<p>上下文对象用于定义如何在画布上绘图。顾名思义，2D上下文嘛，支持在画布上绘制2D图形、图像和文本。支持画布元素的浏览器都支持2D上下文，除了2D上下文，还有其他试验性的上下文对象。Opera有一个专门为游戏设计的2D上下文，而Mozilla则有一个能够显示3D场景的上下文。可惜呀，目前这些上下文对象只有特定的浏览器才支持。如果你想用画布来创建Web应用，最好还是只使用常见的2D上下文。</p>
<p>因为我们在这里是想绘制一幅能移动的图像，所以必须建立渲染循环（render loop）。所谓渲染循环，实际上就是一个被重复调用的函数，渲染循环的每一次迭代，（在这个例子中）都可以让图像在屏幕上产生一点位移，如此循环往复就能给人图像在移动的感觉。为此，我们调用了setInterval函数，它的第一个参数是应该被重复调用的函数，这里的函数名是draw。setInterval函数的第二个参数指定调用函数的频率。这个参数值的单位是毫秒，而用1000除以早先定义的FPS得到的就是每次调用之间相隔的毫秒数。</p>
<p>这里需要注意一下，虽然我们指定每秒钟调用30次draw函数，但实际上不会调用30次。多长时间调用一次draw函数，取决于底层JavaScript引擎的速度和要执行的draw函数代码的复杂程度。如果系统很慢的话，很可能每秒钟只能调用一次draw函数。所以说，这里指定给setInterval的频率只是一种最理想的情况。</p>
<h2>draw函数</h2>
<p>在画布上绘图的操作实际上都是由draw函数来完成的。下面我们就一步一步地说明其中的绘图操作。</p>
<pre class="brush: js; ">

context2D.clearRect(0, 0, canvas.width, canvas.height);
</pre>
<p>所有绘图操作都是在上下文对象上发生的，并不是在画布元素上发生的。这里首先清空上下文，以便为绘制每一帧画面准备一个干净的版面。</p>
<pre class="brush: js; ">

context2D.drawImage(image, x, y);
</pre>
<p>紧接着，就把图像绘制到上下文对象中，参数x和y指定了绘制图像的左上角坐标。</p>
<pre class="brush: js; ">

x += 1 * xDirection;
y += 1 * yDirection;
</pre>
<p>为了让图像在画布上移动，需要根据xDirection和yDirection是等于1（向右或向下）还是等于-1（向左或向上），来递增或递减x与y的值。</p>
<pre class="brush: js; ">

if (x &gt;= 450){
	x = 450;
	xDirection = -1;
} else if (x &lt;= 0) {
	x = 0;
	xDirection = 1;
}
if (y &gt;= 250) {
	y = 250;
	yDirection = -1;
} else if (y &lt;= 0) {
	y = 0;
	yDirection = 1;
}
</pre>
<p>如果图像移动到了画布外面，则反转图像的移动方向。我们知道图像的大小是150×150像素，而画布的大小的是600×400像素，因而就有了450（600 &#8211; 150）和250（400 &#8211; 150）这两个值。</p>
<p>最后的效果就是笑脸图像会在画布的范围内反弹往复。此时此刻，有读者可能会想：同样的效果如果通过修改DIV元素的位置来实现可能更容易一些。这一点我不否认。但这个例子只演示了画布元素所能实现的简单效果。下一篇文章我们就会介绍使用画布元素能够实现的高级效果，同样的效果若采用其他方式，恐怕就要困难多了。</p>
<p>为之漫笔 最后编辑于：<br />
2011/08/12 @ 06:39</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/08/10/game-development-with-javascript-and-the-canvas-element-2554.html/feed</wfw:commentRss>
		<slash:comments>28</slash:comments>
		</item>
		<item>
		<title>Martin Fowler谈软件专利</title>
		<link>http://www.cn-cuckoo.com/2011/08/08/martin-fowler-on-software-patent-2560.html</link>
		<comments>http://www.cn-cuckoo.com/2011/08/08/martin-fowler-on-software-patent-2560.html#comments</comments>
		<pubDate>Mon, 08 Aug 2011 12:55:26 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2560</guid>
		<description><![CDATA[原文地址：http://martinfowler.com/bliki/SoftwarePatent.html 在软件开发领域中，几乎所有我认识的人都对专利以及我们利用它的方式深恶痛绝。很长时间以来，我一直准备写篇文章，谈谈专利这玩艺儿，但一直迟迟没有动笔。最近，在收听了This American Life制作的一期特别棒的新闻观察节目（http://www.thisamericanlife.org/radio-archives/episode/441/when-patents-attack）之后，才决定把这篇文章写出来。我这篇文章的大致意思就是，虽然专利（包括软件专利）从原理上讲是个不错的想法，但在实践当中，各种专利已经给我们带来了无法容忍的灾难，取消这玩艺儿才是上策。 不过，首先还是来看一看为什么我说专利从原理上讲是个不错的主意，而且堪称人类历史上一个最有价值的“发明”。 关于专利在人类发展史中扮演的这个重要角色，Willian Rosen在他的书 The Most Powerful Idea in the World 中给出了很好的论述。Rosen在这本书里回顾了工业革命，而且他把工业革命刻画成了人类历史中最重要的事件，一个使人类财富得以向前迈进了一步的事件。 在17世纪的英格兰、法国，甚至中国，一名熟练的体力劳动者（比如纺织工或铁匠），每周工作的小时数大致相同，生产的布和钉子的数量也大致相同，而且跟他们奥古斯都时代（公元前63年至公元前14年。——译者注）的远祖也没有多大差别。他们能挣到相同数量的货币，能买到相同数量和种类的食物。他们的妻子，同样跟她的远祖一样，忙着准备一日三餐；她们也许会从本村面包师傅那儿买点面包，但除此之外，差不多什么都是自己亲自动手加工。她们甚至还要给全家人做衣服，天气变幻无常，衣服的样式也不尽相同。而且，这在很大程度上也让人无法把当时的家庭与10个世纪前的家庭区分开来，差不多清一色的自织土布，产麻区也会用亚麻布来做衣服。这样的劳动者和他的妻子，一般会生育八到十个后代，但能活到成年的差不多只有三个。如果这个劳动者要出门，那他只有靠步行；当然，如果他们家日子特别富裕的话，会花钱雇一辆两轮或四轮的马车。步行的话，每小时走三英里，坐马车则每小时走七英里。当然，时速跟他们的祖先也一样。而这就意味着，他的世界也就是他出生的地方加上方圆五、六英里远的范围这么大。 之后，历史上第一次，一切都发生了变化。这些劳动者的境况发生了最根本的变化。14世纪君士坦丁堡的一名熟练织工，只要工作三个小时就可以挣够买一磅面包的钱。到1800年，诺丁汉的一位织工为此则至少要工作两个小时。但到了1900年，买这块面包只要工作不到15分钟就够了。而到2000年，只要5分钟。这个已经是老生常谈的事实告诉我们，在发达的21世纪，一个中产阶级家庭所能享受到的奢华生活，在两个世纪以前，是连国王都很难承受得起的。 ——William Rosen 由工业革命导致的这个变化是不可思议的。我们都认为自己所处的是一个不断变化的时代，但前面的描述让我们想起了已经遗忘的过去。眼下，我们对变化已经习以为常，但在工业革命以前，人类生活的变化却极为缓慢。工业革命揭示出的最大变化就是变化本身。 我想研究人类历史的学生极少有人不会承认工业革命的极端重要性，但这也引出了两个重要的问题：为什么它会在那个时候、那个地方发生？18世纪末诞生蒸汽火车的英格兰有什么特殊之处？Rosen的观点是专利起到了重要作用，因为它为发明家和企业家提供了赚钱的刺激和平台。如果没有专利的话，那么就只有富人（或者获得了资助的人）才有条件去革新，而他们革新的动机其实是很弱的。 按照Rosen有说服力的论证，专利不仅仅是一件好事，更是我们人类迄今为止最伟大的一项创举。那为什么我还如此讨厌软件专利呢？ 这可以归结到一个事实：与工业革命时的专利相比，目前的专利保护总体上来讲已经严重地变质了。变质最严重的当数所谓的新颖性。专利保护的重中之重，无非就是由法律授予对某种新东西（有限期）的垄断权。《美国专利法》规定，如果“从总体上看，标的物在被发明的时候，对于一个拥有相应技艺领域普通技能的人来说显而易见”，则无法取得专利权。这一规定可以追溯到1623年制定的英国垄断条例[1]，这个条例首次提出只有具有新颖性和实用性的发明才能申请专利。 软件专利的核心问题就是这个关键的原则已经被扔到了一边。软件领域的每个人亲眼见证了，那么多专利摆在那除了声称对已经用了多少年的技术拥有垄断权之外，没有任何意义。更不用说那些尽管新，但对我等拥有普通编程技能的人而言却是显而易见的成果了。 虽然这种变质已经足以破坏软件专利的纯正性，但其他方面的变质也同样值得讨论。最初，专利都是有年限规定的——1623年的法律规定的是14年。当然，制定这个规定的年代其变化要比今天的变化慢得多，更不要说跟我们这个行业比了。正常的软件专利应该比这个年限更短才对。再一个变质的地方就是不明确——大多数软件专利都宽泛和含糊得不可思议，但专利的范围最早都很窄，也很明确。专利范围窄能够刺激人们思考解决同一问题的不同方法，从而达到鼓励创新的目的，而宽泛的专利则会扼杀创新。 这几方面的变质造成了专利不再激励和导向新发明，而是沦为了对簿公堂的武器。对于大公司来讲，专利诉讼既让人分心，又会带来经费负担，至少表面上看如此。但诉讼其实对小公司的伤害最大，因为他们没有时间和金钱为了专利去打官司。因而我们就看到了利用专利来敲诈，而这也抑制了创新。 灾难的是，专利已经演变成增强已有实力的途径。大公司可能会认为专利带来的是无尽的麻烦，但专利最终还是对保持当前公司的巨头地位十分有利，因为依靠专利可以强迫更小的对手出局。这正是难以改变现状的原因，那些具备强大实力的公司不可能有动力放弃专利。 最令我痛心疾首的是，我熟识的很多程序员都是这场灾难的同谋。程序员谈论自己正在申请某某专利，而自己又知道那有多么荒谬的事例并不少见。想让别人高看自己一眼很容易，但我真的认为参与取得那些子虚乌有的专利的程序员，应该为自己的所做所为感到耻辱。这暴露出了我们缺少责任感，我们应该被世人当作专业人士，但我们自己却在自毁长城。 理论上，假如专利能够回归到其核心的互利原则，而且能够得到适当的贯彻，我也不反对软件专利。这恐怕就意味着要有一个流程，能够确保只把专利授予那些真正新颖的思想。但除非这样一个流程能够很好地运作，否则我宁愿看到软件专利被彻底废除。一个没有软件专利的世界，总归要比我们现在所处的这个专利泛滥的世界要好得多。 延伸阅读 有关专利的文章资料可谓汗牛充栋。Tim Bray去年写的关于“放弃专利”的文章（http://www.tbray.org/ongoing/When/201x/2010/02/22/Patent-Fail）中给出了很多不错的参考资源。不少类似的观点也都证明了软件专利确实导致了创新的减少。 Planet Money对This American Life的相关话题做了一个语音跟踪报道（http://www.npr.org/blogs/money/2011/08/05/138934689/the-tuesday-podcast-the-patent-war），其中给出了他们自己总结的一些研究成果。 “在一个我们未来的财富如此依赖创新的时代，我们已经滑向了一种既不能实现其合理功能——激励创新，却又极力阻碍着创新的专利制度。”——WW.W. of The Economist（http://www.economist.com/blogs/democracyinamerica/2011/08/intellectual-property） [1] 我更喜欢这个条例最初的名字《Act concerning Monopolies and Dispensations with penall Lawes and the Forfeyture thereof》（关于垄断和特许以及相关刑法及罚没的法案）]]></description>
			<content:encoded><![CDATA[<p style="text-align: right;">原文地址：<a href="http://martinfowler.com/bliki/SoftwarePatent.html" target="_blank">http://martinfowler.com/bliki/SoftwarePatent.html</a></p>
<p>在软件开发领域中，几乎所有我认识的人都对专利以及我们利用它的方式深恶痛绝。很长时间以来，我一直准备写篇文章，谈谈专利这玩艺儿，但一直迟迟没有动笔。最近，在收听了This American Life制作的一期特别棒的新闻观察节目（<a href="http://www.thisamericanlife.org/radio-archives/episode/441/when-patents-attack" target="_blank">http://www.thisamericanlife.org/radio-archives/episode/441/when-patents-attack</a>）之后，才决定把这篇文章写出来。我这篇文章的大致意思就是，虽然专利（包括软件专利）从原理上讲是个不错的想法，但在实践当中，各种专利已经给我们带来了无法容忍的灾难，取消这玩艺儿才是上策。</p>
<p>不过，首先还是来看一看为什么我说专利从原理上讲是个不错的主意，而且堪称人类历史上一个最有价值的“发明”。</p>
<p>关于专利在人类发展史中扮演的这个重要角色，Willian Rosen在他的书 <em>The Most Powerful Idea in the World</em> 中给出了很好的论述。Rosen在这本书里回顾了工业革命，而且他把工业革命刻画成了人类历史中最重要的事件，一个使人类财富得以向前迈进了一步的事件。</p>
<div style="font: .8em; border-left: 3px solid #ddd; padding-left: 1em;margin-left:1em;">
<p>在17世纪的英格兰、法国，甚至中国，一名熟练的体力劳动者（比如纺织工或铁匠），每周工作的小时数大致相同，生产的布和钉子的数量也大致相同，而且跟他们奥古斯都时代（公元前63年至公元前14年。——译者注）的远祖也没有多大差别。他们能挣到相同数量的货币，能买到相同数量和种类的食物。他们的妻子，同样跟她的远祖一样，忙着准备一日三餐；她们也许会从本村面包师傅那儿买点面包，但除此之外，差不多什么都是自己亲自动手加工。她们甚至还要给全家人做衣服，天气变幻无常，衣服的样式也不尽相同。而且，这在很大程度上也让人无法把当时的家庭与10个世纪前的家庭区分开来，差不多清一色的自织土布，产麻区也会用亚麻布来做衣服。这样的劳动者和他的妻子，一般会生育八到十个后代，但能活到成年的差不多只有三个。如果这个劳动者要出门，那他只有靠步行；当然，如果他们家日子特别富裕的话，会花钱雇一辆两轮或四轮的马车。步行的话，每小时走三英里，坐马车则每小时走七英里。当然，时速跟他们的祖先也一样。而这就意味着，他的世界也就是他出生的地方加上方圆五、六英里远的范围这么大。</p>
<p>之后，历史上第一次，一切都发生了变化。这些劳动者的境况发生了最根本的变化。14世纪君士坦丁堡的一名熟练织工，只要工作三个小时就可以挣够买一磅面包的钱。到1800年，诺丁汉的一位织工为此则至少要工作两个小时。但到了1900年，买这块面包只要工作不到15分钟就够了。而到2000年，只要5分钟。这个已经是老生常谈的事实告诉我们，在发达的21世纪，一个中产阶级家庭所能享受到的奢华生活，在两个世纪以前，是连国王都很难承受得起的。</p>
<p>——William Rosen
</p></div>
<p><span id="more-2560"></span><br />
由工业革命导致的这个变化是不可思议的。我们都认为自己所处的是一个不断变化的时代，但前面的描述让我们想起了已经遗忘的过去。眼下，我们对变化已经习以为常，但在工业革命以前，人类生活的变化却极为缓慢。工业革命揭示出的最大变化就是变化本身。</p>
<p>我想研究人类历史的学生极少有人不会承认工业革命的极端重要性，但这也引出了两个重要的问题：为什么它会在那个时候、那个地方发生？18世纪末诞生蒸汽火车的英格兰有什么特殊之处？Rosen的观点是专利起到了重要作用，因为它为发明家和企业家提供了赚钱的刺激和平台。如果没有专利的话，那么就只有富人（或者获得了资助的人）才有条件去革新，而他们革新的动机其实是很弱的。</p>
<p>按照Rosen有说服力的论证，专利不仅仅是一件好事，更是我们人类迄今为止最伟大的一项创举。那为什么我还如此讨厌软件专利呢？</p>
<p>这可以归结到一个事实：与工业革命时的专利相比，目前的专利保护总体上来讲已经严重地变质了。变质最严重的当数所谓的新颖性。专利保护的重中之重，无非就是由法律授予对某种新东西（有限期）的垄断权。《美国专利法》规定，如果“从总体上看，标的物在被发明的时候，对于一个拥有相应技艺领域普通技能的人来说显而易见”，则无法取得专利权。这一规定可以追溯到1623年制定的英国垄断条例<a name="backTo1623" href="#1623">[1]</a>，这个条例首次提出只有具有新颖性和实用性的发明才能申请专利。</p>
<p>软件专利的核心问题就是这个关键的原则已经被扔到了一边。软件领域的每个人亲眼见证了，那么多专利摆在那除了声称对已经用了多少年的技术拥有垄断权之外，没有任何意义。更不用说那些尽管新，但对我等拥有普通编程技能的人而言却是显而易见的成果了。</p>
<p>虽然这种变质已经足以破坏软件专利的纯正性，但其他方面的变质也同样值得讨论。最初，专利都是有年限规定的——1623年的法律规定的是14年。当然，制定这个规定的年代其变化要比今天的变化慢得多，更不要说跟我们这个行业比了。正常的软件专利应该比这个年限更短才对。再一个变质的地方就是不明确——大多数软件专利都宽泛和含糊得不可思议，但专利的范围最早都很窄，也很明确。专利范围窄能够刺激人们思考解决同一问题的不同方法，从而达到鼓励创新的目的，而宽泛的专利则会扼杀创新。</p>
<p>这几方面的变质造成了专利不再激励和导向新发明，而是沦为了对簿公堂的武器。对于大公司来讲，专利诉讼既让人分心，又会带来经费负担，至少表面上看如此。但诉讼其实对小公司的伤害最大，因为他们没有时间和金钱为了专利去打官司。因而我们就看到了利用专利来敲诈，而这也抑制了创新。</p>
<p>灾难的是，专利已经演变成增强已有实力的途径。大公司可能会认为专利带来的是无尽的麻烦，但专利最终还是对保持当前公司的巨头地位十分有利，因为依靠专利可以强迫更小的对手出局。这正是难以改变现状的原因，那些具备强大实力的公司不可能有动力放弃专利。</p>
<p>最令我痛心疾首的是，我熟识的很多程序员都是这场灾难的同谋。程序员谈论自己正在申请某某专利，而自己又知道那有多么荒谬的事例并不少见。想让别人高看自己一眼很容易，但我真的认为参与取得那些子虚乌有的专利的程序员，应该为自己的所做所为感到耻辱。这暴露出了我们缺少责任感，我们应该被世人当作专业人士，但我们自己却在自毁长城。</p>
<p>理论上，假如专利能够回归到其核心的互利原则，而且能够得到适当的贯彻，我也不反对软件专利。这恐怕就意味着要有一个流程，能够确保只把专利授予那些真正新颖的思想。但除非这样一个流程能够很好地运作，否则我宁愿看到软件专利被彻底废除。一个没有软件专利的世界，总归要比我们现在所处的这个专利泛滥的世界要好得多。</p>
<h2>延伸阅读</h2>
<p>有关专利的文章资料可谓汗牛充栋。Tim Bray去年写的关于“放弃专利”的文章（<a href="http://www.tbray.org/ongoing/When/201x/2010/02/22/Patent-Fail" target="_blank">http://www.tbray.org/ongoing/When/201x/2010/02/22/Patent-Fail</a>）中给出了很多不错的参考资源。不少类似的观点也都证明了软件专利确实导致了创新的减少。</p>
<p>Planet Money对This American Life的相关话题做了一个语音跟踪报道（<a href="http://www.npr.org/blogs/money/2011/08/05/138934689/the-tuesday-podcast-the-patent-war" target="_blank">http://www.npr.org/blogs/money/2011/08/05/138934689/the-tuesday-podcast-the-patent-war</a>），其中给出了他们自己总结的一些研究成果。</p>
<p>“在一个我们未来的财富如此依赖创新的时代，我们已经滑向了一种既不能实现其合理功能——激励创新，却又极力阻碍着创新的专利制度。”——WW.W. of The Economist（<a href="http://www.economist.com/blogs/democracyinamerica/2011/08/intellectual-property" target="_blank">http://www.economist.com/blogs/democracyinamerica/2011/08/intellectual-property</a>）</p>
<p><a id="1623" name="1623" href="#backTo1623">[1]</a> 我更喜欢这个条例最初的名字《Act concerning Monopolies and Dispensations with penall Lawes and the Forfeyture thereof》（关于垄断和特许以及相关刑法及罚没的法案）</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/08/08/martin-fowler-on-software-patent-2560.html/feed</wfw:commentRss>
		<slash:comments>35</slash:comments>
		</item>
		<item>
		<title>美国第二大连锁书店Borders CEO致会员的一封信</title>
		<link>http://www.cn-cuckoo.com/2011/07/26/to-borders-rewards-member-2545.html</link>
		<comments>http://www.cn-cuckoo.com/2011/07/26/to-borders-rewards-member-2545.html#comments</comments>
		<pubDate>Mon, 25 Jul 2011 23:07:06 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[出版]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2545</guid>
		<description><![CDATA[原文地址：http://ebm.e.borders.com/c/tag/hBOKNiQAQfEXsB8cdgOAESqwkGW/doc.html 新爱的Borders Rewards会员， 相信你们已经听说了，Borders在经过40多年为几代读者点燃热爱阅读的薪火之后，将要全面关门停业了。宣布这个消息，我们也感到非常抱歉，因为在我们奋力拯救公司之际，你们始终与我们站在一起。我想以个人名义向你们表示感谢，感谢你们的忠实与支持，无论你是180万Borders Rewards Plus计划的注册会员之一，还是曾在我们的商店或Borders.com上买过东西，或者花时间通过邮件或电话方式向Borders表示过支持。 你可能会想，发生了什么事？Borders怎么就经营不下去了呢？简单地说，相关各方经过反复协商，也都尽了最大努力，没有出价人正式提议我们公司继续经营。因此，根据我们的债务持有人融资协议，我们向法院递交了申请，请求批准其他公司购买我们商店的资产，并执行清算程序。 为了避免这个结果发生，我们已经尽了很大努力。但事实上，很长时间以来，Borders一直面对不利的市场形势，包括图书业的迅速变化、电子阅读器的革命，以及动荡的经济。我们也曾奋力一搏，绝地反击，但令人遗憾的是，我们最终没有战胜这些外来的力量。 所有门店将于7月22日星期五开始停业甩卖。希望大家利用这次绝无仅有的机会，以意想不到的折扣买到自己心仪的图书或其他商品。清算销售期间，礼品卡可以继续使用，Borders Rewards Plus会员到8月5日之前仍将享受其会员折扣。此外，全部Borders Bucks在7月31日前仍然可以使用，过期作废。 几十年来，Borders商店一直是读者寻求知识、快乐和灵感，以及与那些充满激情的人交流思想的地方。我很荣幸，能够有机会领导Borders并在扩大阅读范围和传播阅读兴趣的伟大事业中扮演了一个角色。作为一家公司，对于你们能接受我们的服务，对于另外几百万客户数年来从我们商店购物，我们感激不尽。我衷心希望Borders永远活在读者的心中。 非常感谢， Mike Edwards Borders公司CEO]]></description>
			<content:encoded><![CDATA[<p style="text-align: right;">原文地址：<a href="http://ebm.e.borders.com/c/tag/hBOKNiQAQfEXsB8cdgOAESqwkGW/doc.html">http://ebm.e.borders.com/c/tag/hBOKNiQAQfEXsB8cdgOAESqwkGW/doc.html</a></p>
<p>新爱的Borders Rewards会员，</p>
<p>相信你们已经听说了，Borders在经过40多年为几代读者点燃热爱阅读的薪火之后，将要全面关门停业了。宣布这个消息，我们也感到非常抱歉，因为在我们奋力拯救公司之际，你们始终与我们站在一起。我想以个人名义向你们表示感谢，感谢你们的忠实与支持，无论你是180万Borders Rewards Plus计划的注册会员之一，还是曾在我们的商店或Borders.com上买过东西，或者花时间通过邮件或电话方式向Borders表示过支持。</p>
<p>你可能会想，发生了什么事？Borders怎么就经营不下去了呢？简单地说，相关各方经过反复协商，也都尽了最大努力，没有出价人正式提议我们公司继续经营。因此，根据我们的债务持有人融资协议，我们向法院递交了申请，请求批准其他公司购买我们商店的资产，并执行清算程序。</p>
<p>为了避免这个结果发生，我们已经尽了很大努力。但事实上，很长时间以来，Borders一直面对不利的市场形势，包括图书业的迅速变化、电子阅读器的革命，以及动荡的经济。我们也曾奋力一搏，绝地反击，但令人遗憾的是，我们最终没有战胜这些外来的力量。</p>
<p>所有门店将于7月22日星期五开始停业甩卖。希望大家利用这次绝无仅有的机会，以意想不到的折扣买到自己心仪的图书或其他商品。清算销售期间，礼品卡可以继续使用，Borders Rewards Plus会员到8月5日之前仍将享受其会员折扣。此外，全部Borders Bucks在7月31日前仍然可以使用，过期作废。</p>
<p>几十年来，Borders商店一直是读者寻求知识、快乐和灵感，以及与那些充满激情的人交流思想的地方。我很荣幸，能够有机会领导Borders并在扩大阅读范围和传播阅读兴趣的伟大事业中扮演了一个角色。作为一家公司，对于你们能接受我们的服务，对于另外几百万客户数年来从我们商店购物，我们感激不尽。我衷心希望Borders永远活在读者的心中。</p>
<p>非常感谢，</p>
<p>Mike Edwards<br />
Borders公司CEO</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/07/26/to-borders-rewards-member-2545.html/feed</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>JavaScript是Web的汇编语言（二）：疯狂，亦或只是精神错乱？</title>
		<link>http://www.cn-cuckoo.com/2011/07/21/javascript-is-assembly-language-for-the-web-ii-2531.html</link>
		<comments>http://www.cn-cuckoo.com/2011/07/21/javascript-is-assembly-language-for-the-web-ii-2531.html#comments</comments>
		<pubDate>Thu, 21 Jul 2011 00:40:28 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[编程技术]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2531</guid>
		<description><![CDATA[原文地址：JavaScript is Assembly Language for the Web: Part 2 &#8211; Madness or just Insanity? 有些人认为“JavaScript是Web的汇编语言”完全是精神病说的话。为此，我询问了几位JavaScript权威，比如Brendan Eich（JavaScript之父）、Douglas Crockford（JSON之父），还有Mike Shaver（Mozilla技术副总裁）。以下都是从个人邮件里摘过来的，得到了以上几位的许可。 Mike Shaver： 以前我就听说过这种比较，我认为很大程度上确实如此。但是，这种说法忽视了JS开发人员与机器之间的人机工程学方面的大量努力，因为汇编语法设计得没有那么人性化（特别是现代的汇编语言）。 Brendan Eich： 几年前，我曾说过“JS是Web的x86”（好像是在一次JSConf上），不过我不敢说我是第一个这么说的。（Nick Thompson今年也在Hacker News中这么说过。） 关键在于，JS确实在按照我们想的，越来越往低级方向发展了。但它也具备高级的特性。 Shaver说得没错，汇编缺少可靠的宏处理器，因此不适合程序员，也不够安全。但JS可不是这样。所以，这个比喻需要加点限制条件，不然就要闹出笑话来了。 无论从高级函数式编程还是内存安全角这个角度看，还是从低级特性，像类型化数组以及即将成为现实的ES中类型化数组的扩展、二进制数据，等等来说，JS都是一个比汇编更加强大的编程语言。当然了，内存安全是首要的区别。 Douglas Crockford： 就这个问题来说，我觉得说JavaScript是Web的虚拟机更接近一些。过去我们一直都把Java的JVM看成是Web的虚拟机，但结果呢，JavaScript才是。 从提供代码安全的角度说，JavaScript的解析器比JVM的字节码验证器更有效。就兑现“编写一次，到处运行”这个诺言来看，JavaScript更出色；这或许正是因为它是在较高层次上运行，才得以避免触及一些底层的棘手问题。因为它把剩下的事儿都交给图灵去解决了。 当然啦，也有不少人始终不肯承认JavaScript能把一切都处理好，我过去就是这样一个人。而现在我则不断地被眼前这种百花齐放的景象震撼着。 Brendan Eich，补充： Doug说源代码强过字节码，说得太好了。很早以前，我的朋友，加州大学欧文分校的Michael Franz教授就指出了Java验证器O(n^4)级别的复杂性（计算机时钟周期失控，拒绝服务）。精简之后的JS呢，确实传输更便捷，而且词法/语法分析也相当快。 （JS）源代码作为“字节码”同样也避免了Java字节码的一个很傻的问题：冻结设计不良的Java低级形式，导致高级形式的源代码也无法解决这个问题。换句话说，Java唯恐破坏其字节码的兼容性。而这严重影响了Java内部类及其泛型的设计。——不管怎么说，Sun最后还是破坏了字节码的兼容性。 以下是前一段时间Nick Thompson在YCombinator说过的话： 这只是我个人的看法：我花了自己两年时间，想尽可能让JVM能够与JavaScript互通。当时的Netscape有不少人认为字节码作为移动代码的基础比较好。但Sun从头搭建了自己大而全的软件体系，把问题搞得很复杂。他们没有想让Java与其他语言沟通，更别提让Java能嵌入其他软件中了。他们的字符串处理代码都是用一种解释型语言来写，而不肯用C来玷污自己！有什么我就说什么，Netscape，这个当时Java唯一的一个大客户，在Sun眼里无非就是一个用来实现他们取代Windows梦想的工具而已。所有想用Java的人都是自己给自己找罪受。 在此期间，Brendan一个人干了10个工程师，外加3个客户服务人员的活儿，同时还要关注Web作者在乎的一些事，比如把JS代码混合到HTML中、即时加载、与浏览器其他模块的集成等等，此外还要协调其他浏览器厂商，以便让JS成为一个开放标准。 因此，今天的JS作为Web的x86汇编程序，并没有像它本该的那样完美，但你通过它真能把事情稿定（GWT就是一个最明显的例子）。这可以说是一个经典的“更差就是更好”的例子，只不过Java也就是从下往上那么看起来更好罢了。而JS则在此期间取得了相当不错的成就。要想取代它的地位可没那么容易。 当然，这个比喻不一定准确。JavaScript代码无论从外观到行为，肯定不像ASM。但作为一个比喻，至少可以说明： JavaScript无所不在； 它速度快而且越来越快； JavaScript酷似低级的Web编程语言； 它可以通过手工编写，也可以从另一种语言编译而来。 诸如此类的话题也经常在Hacker News中出现： “现在的JavaScript其实就是客户端的汇编语言。想改它太难了，所以得想办法开发一些工具来解决这个问题。”—— jonnycat 好啦，能听到如此有见地、有深度，而又详尽的讨论，该满足了吧。亲爱的读者，你们太棒了。]]></description>
			<content:encoded><![CDATA[<p style="text-align: right;">原文地址：<a href="http://www.hanselman.com/blog/JavaScriptIsAssemblyLanguageForTheWebPart2MadnessOrJustInsanity.aspx">JavaScript is Assembly Language for the Web: Part 2 &#8211; Madness or just Insanity?</a></p>
<p><strong>有些人认为“<a href="http://www.cn-cuckoo.com/2011/07/20/javascript-is-assembly-language-for-the-web-i-2511.html">JavaScript是Web的汇编语言</a>”完全是精神病说的话。</strong>为此，我询问了几位JavaScript权威，比如Brendan Eich（JavaScript之父）、Douglas Crockford（JSON之父），还有Mike Shaver（Mozilla技术副总裁）。以下都是从个人邮件里摘过来的，得到了以上几位的许可。</p>
<p><a href="http://en.wikipedia.org/wiki/Mike_Shaver" target="_blank">Mike Shaver</a>：</p>
<div style="border-left: 2px solid #ddd; margin-left: 1em; padding-left: 1em;">以前我就听说过这种比较，我认为很大程度上确实如此。但是，这种说法忽视了JS开发人员与机器之间的人机工程学方面的大量努力，因为汇编语法设计得没有那么人性化（特别是现代的汇编语言）。</div>
<p><a href="http://en.wikipedia.org/wiki/Brendan_Eich" target="_blank">Brendan Eich</a>：</p>
<div style="border-left: 2px solid #ddd; margin-left: 1em; padding-left: 1em;">
<p>几年前，我曾说过“JS是Web的x86”（好像是在一次JSConf上），不过我不敢说我是第一个这么说的。（Nick Thompson今年也在Hacker News中这么说过。）</p>
<p>关键在于，JS确实在按照我们想的，越来越往低级方向发展了。但它也具备高级的特性。</p>
<p>Shaver说得没错，汇编缺少可靠的宏处理器，因此不适合程序员，也不够安全。但JS可不是这样。所以，这个比喻需要加点限制条件，不然就要闹出笑话来了。</p>
<p>无论从高级函数式编程还是内存安全角这个角度看，还是从低级特性，像类型化数组以及即将成为现实的ES中类型化数组的扩展、二进制数据，等等来说，JS都是一个比汇编更加强大的编程语言。当然了，内存安全是首要的区别。</p>
</div>
<p><a href="http://en.wikipedia.org/wiki/Douglas_Crockford" target="_blank"><span id="more-2531"></span>Douglas Crockford</a>：</p>
<div style="border-left: 2px solid #ddd; margin-left: 1em; padding-left: 1em;">
<p>就这个问题来说，我觉得说JavaScript是Web的虚拟机更接近一些。过去我们一直都把Java的JVM看成是Web的虚拟机，但结果呢，JavaScript才是。</p>
<p>从提供代码安全的角度说，JavaScript的解析器比JVM的字节码验证器更有效。就兑现“编写一次，到处运行”这个诺言来看，JavaScript更出色；这或许正是因为它是在较高层次上运行，才得以避免触及一些底层的棘手问题。因为它把剩下的事儿都交给图灵去解决了。</p>
<p>当然啦，也有不少人始终不肯承认JavaScript能把一切都处理好，我过去就是这样一个人。而现在我则不断地被眼前这种百花齐放的景象震撼着。</p>
</div>
<p>Brendan Eich，补充：</p>
<div style="border-left: 2px solid #ddd; margin-left: 1em; padding-left: 1em;">
<p>Doug说源代码强过字节码，说得太好了。很早以前，我的朋友，加州大学欧文分校的Michael Franz教授就指出了Java验证器O(n^4)级别的复杂性（计算机时钟周期失控，拒绝服务）。精简之后的JS呢，确实传输更便捷，而且词法/语法分析也相当快。</p>
<p>（JS）源代码作为“字节码”同样也避免了Java字节码的一个很傻的问题：冻结设计不良的Java低级形式，导致高级形式的源代码也无法解决这个问题。换句话说，Java唯恐破坏其字节码的兼容性。而这严重影响了Java内部类及其泛型的设计。——不管怎么说，Sun最后还是破坏了字节码的兼容性。
</p></div>
<p>以下是前一段时间<a href="http://nixweb.com/" target="_blank">Nick Thompson</a>在YCombinator说过的话：</p>
<div style="border-left: 2px solid #ddd; margin-left: 1em; padding-left: 1em;">
<p>这只是我个人的看法：我花了自己两年时间，想尽可能让JVM能够与JavaScript互通。当时的Netscape有不少人认为字节码作为移动代码的基础比较好。但Sun从头搭建了自己大而全的软件体系，把问题搞得很复杂。他们没有想让Java与其他语言沟通，更别提让Java能嵌入其他软件中了。他们的字符串处理代码都是用一种解释型语言来写，而不肯用C来玷污自己！有什么我就说什么，Netscape，这个当时Java唯一的一个大客户，在Sun眼里无非就是一个用来实现他们取代Windows梦想的工具而已。所有想用Java的人都是自己给自己找罪受。</p>
<p>在此期间，Brendan一个人干了10个工程师，外加3个客户服务人员的活儿，同时还要关注Web作者在乎的一些事，比如把JS代码混合到HTML中、即时加载、与浏览器其他模块的集成等等，此外还要协调其他浏览器厂商，以便让JS成为一个开放标准。</p>
<p>因此，今天的JS作为Web的x86汇编程序，并没有像它本该的那样完美，但你通过它真能把事情稿定（GWT就是一个最明显的例子）。这可以说是一个经典的“更差就是更好”的例子，只不过Java也就是从下往上那么看起来更好罢了。而JS则在此期间取得了相当不错的成就。要想取代它的地位可没那么容易。</p>
</div>
<p>当然，这个比喻不一定准确。JavaScript代码无论从外观到行为，肯定不像ASM。但作为一个比喻，至少可以说明：</p>
<ul>
<li>JavaScript无所不在；</li>
<li>它速度快而且越来越快；</li>
<li>JavaScript酷似低级的Web编程语言；</li>
<li>它可以通过手工编写，也可以从另一种语言编译而来。</li>
</ul>
<p>诸如此类的话题也经常在Hacker News中出现：</p>
<div style="border-left: 2px solid #ddd; margin-left: 1em; padding-left: 1em;">
“现在的JavaScript其实就是客户端的汇编语言。想改它太难了，所以得想办法开发一些工具来解决这个问题。”——<br />
<a href="http://news.ycombinator.com/item?id=2451594">jonnycat</a></div>
<p>好啦，能听到如此有见地、有深度，而又详尽的讨论，该满足了吧。亲爱的读者，你们太棒了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/07/21/javascript-is-assembly-language-for-the-web-ii-2531.html/feed</wfw:commentRss>
		<slash:comments>43</slash:comments>
		</item>
		<item>
		<title>JavaScript是Web的汇编语言（一）：语义Web已死！</title>
		<link>http://www.cn-cuckoo.com/2011/07/20/javascript-is-assembly-language-for-the-web-i-2511.html</link>
		<comments>http://www.cn-cuckoo.com/2011/07/20/javascript-is-assembly-language-for-the-web-i-2511.html#comments</comments>
		<pubDate>Wed, 20 Jul 2011 12:59:04 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[编程技术]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2511</guid>
		<description><![CDATA[原文地址：JavaScript is Assembly Language for the Web: Sematic Markup is Dead! Clean vs. Machine-coded HTML （更新）有些人认为“JavaScript是Web的汇编语言”完全是精神病说的话。为此，我询问了几位JavaScript权威，比如Brendan Eich（JavaScript之父）、Douglas Crockford（JSON之父），还有Mike Shaver（Mozilla技术副总裁）。他们的评论发表在下一篇文章里。 昨天我跟Erik Meijer聊天，他说： JavaScript就是一个汇编语言。JavaScript加上生成的HTML就像是.NET汇编一样。浏览器可以执行这些代码，但没人真的关心里面到底写的是什么。 ——Erik Meijer 怎么会说起这件事儿呢？当时我正在试用Google+，就跟上大多数让我印象深刻的网站一样，我立即就查看它的源代码。不看不要紧，一看吓一跳： 咱就将就说吧，我看到了1300行代码，密密麻麻的，大约90KB。上面图片显示的只是最前面的一小部分，基本上都是“瘦身后”的JavaScript代码。再往下看，页面中间呢，全都是像下面这样的span、div以及生成的类和id： 我勒个去，满篇都是GUID（Globally Unique Identifier，全局唯一标识符）。 话又说回来了，http://msn.com、http://www.bing.com、http://.www.facebook.com，全都这样啊。就连http://www.twitter.com也都开始有点“瘦身”的迹象了。所有大点的网站好像都丝毫不在乎什么标记之美。这是为什么呢？ 这样有效率啊，性能高啊。Google很多最出色的网站背后都依赖GWT呢。在这种情况下，要是这一类网站的里头和外头全都一样漂亮，你反而会觉得不可思议了。 不能不说这可真有点讽刺的意味。曾几何时，ASP.NET的开发人员对ViewState可是怨声载道啊。“简直太笨了”的意思就是“我看不懂它都干什么了。”ViewState曾经（现在也）是一项让Web开发效率提高很多倍的技术。它跟Google Web Toolkit（GWT）不一样，但GWT与WebForms的出发点也并非完全没有相似之处。看看GWT网站自己怎么说： Google Web Toolkit（GWT）是一个开发工具包，用于构建和优化基于浏览器的复杂应用。GWT的目标是提高高性能Web应用开发的效率，而且无需开发人员熟悉浏览器的各种怪癖，以及XMLHttpRequest，还有JavaScript。 这个出发点可真是值得赞美，不对？难道不可以这样说（抱歉，开个玩笑而已）： “ASP.NET WebForms”是一个开发工具包，用于构建和优化基于浏览器的复杂应用。它的目标是提高高性能Web应用开发的效率，而且无需开发人员熟悉浏览器的各种怪癖，以及XMLHttpRequest，还有JavaScript。 本文的目的不是想夸奖WebForms，也不是给WebForms正名。WebForms对于某些应用是不二之选，正如GWT对其他一些应用那样。我真正想说的是，使用服务器端的工具包，没有办法像使用jQuery写出清晰的JavaScript，或者使用Razor或HAML写出清晰、清楚的标记一样，给Web开发带来真正的快乐。归根结底，其实就是你选择的抽象级别的问题。 所谓的语义标记在这种情况下仍然是被隐藏的，而诸如http://schema.org之类的站点也仍然非常重要，只不过可别指望你能在心仪的站点里看到缩进得像俳句一样整齐的源代码。 大家知道，精简和压缩属于正交优化。而我要说的是，一点也不在乎标记和脚本发送到客户端之后是否美观，确实太草率了。假如谁都不在乎发送到浏览器的标记，只在乎结果，那谁的标记和JS就那么不值钱啊，谁还愿意主动公开自己的源代码呢？反正，网站不是运行得挺好嘛，谁还在乎其他的？ 现在我要给亲爱的读者提个问题，你觉得自己为什么那么在乎点击“查看网页源代码”之后的结果呢？难道HTML5和JavaScript是Web的新汇编语言不成？ （更新）声明一下： 当然，这个比喻不一定准确。JavaScript代码无论从外观到行为，肯定不像ASM。但作为一个比喻，至少可以说明： JavaScript无所不在； 它速度快而且越来越快； JavaScript酷似低级的Web编程语言； 它可以通过手工编写，也可以从另一种语言编译而来。 作为开发人员或者设计人员，如果有工具提供了你需要的控制和你需要的结果，你最关心哪一个？我认为Rails、ASP.NET，甚至GWT，都没有100%做到这一点。它们都有自己的问题，但我认为将来的Web不会再专注于清晰的标记，而是夺目的用户体验和语言、工具的天下，开发人员会很享受，效率也会更高。 亲爱的读者，你愿意HTML和JavaScript再多抽象一点吗？还是希望它少抽象一点？ （再更新）为了让大家明白，我得再说一遍。本文讨论了两个独立的问题。一个当然就是源代码经过了精简和通常的混淆。但这只是第一个问题。真正的问题在于，JavaScript已经成了其他多种语言的目标语言。GWT是一个用JAVA来写Web应用的框架，它产生的字节码是“JavaScript”。GWT为原来天然的语言（HTML+JS）选择了一个设计好的高级语言，并将整个浏览器当成了一个VM。好，问题来了：我们是在写汇编呢，还是在写某种更高级点的代码？而且，我刚知道Google+是用Closure来写的，但这不影响前面的问题。]]></description>
			<content:encoded><![CDATA[<p style="text-align: right;">原文地址：<a href="http://www.hanselman.com/blog/JavaScriptIsAssemblyLanguageForTheWebSematicMarkupIsDeadCleanVsMachinecodedHTML.aspx">JavaScript is Assembly Language for the Web: Sematic Markup is Dead! Clean vs. Machine-coded HTML</a></p>
<p><strong><span style="color:red;">（更新）</span>有些人认为“JavaScript是Web的汇编语言”完全是精神病说的话。为此，我询问了几位JavaScript权威，比如Brendan Eich（JavaScript之父）、Douglas Crockford（JSON之父），还有Mike Shaver（Mozilla技术副总裁）。<a href="http://http://www.cn-cuckoo.com/2011/07/21/javascript-is-assembly-language-for-the-web-ii-2531.html">他们的评论发表在下一篇文章里</a>。</strong></p>
<p>昨天我跟Erik Meijer聊天，他说：</p>
<div style="border-left: 2px solid #ddd; margin-left: 1em; padding-left: 1em; font-weight: bold;">JavaScript就是一个汇编语言。JavaScript加上生成的HTML就像是.NET汇编一样。浏览器可以执行这些代码，但没人真的关心里面到底写的是什么。<br />
——Erik Meijer</div>
<p>怎么会说起这件事儿呢？当时我正在<strong>试用Google+</strong>，就跟上大多数让我印象深刻的网站一样，我立即就查看它的源代码。不看不要紧，一看吓一跳：<br />
<img class="colorbox-2511"  src="http://www.cn-cuckoo.com/cache/img/2511_image_1.png" alt="" /></p>
<p>咱就将就说吧，我看到了1300行代码，密密麻麻的，大约90KB。上面图片显示的只是最前面的一小部分，基本上都是“瘦身后”的JavaScript代码。再往下看，页面中间呢，全都是像下面这样的span、div以及生成的类和id：<span id="more-2511"></span></p>
<p><img class="colorbox-2511"  src="http://www.cn-cuckoo.com/cache/img/2511_image_2.png" alt="" /></p>
<p><strong>我勒个去，满篇都是GUID（Globally Unique Identifier，全局唯一标识符）。</strong></p>
<p>话又说回来了，<strong><a title="http://msn.com" href="http://msn.com" target="_blank">http://msn.com</a>、<a title="http://www.bing.com" href="http://www.bing.com" target="_blank">http://www.bing.com</a>、<a title="http://.www.facebook.com" href="http://.www.facebook.com" target="_blank">http://.www.facebook.com</a></strong>，全都这样啊。就连<strong><a title="http://www.twitter.com" href="http://www.twitter.com" target="_blank">http://www.twitter.com</a></strong>也都开始有点“瘦身”的迹象了。所有大点的网站好像都丝毫不在乎什么标记之美。这是为什么呢？</p>
<p>这样有效率啊，性能高啊。Google很多最出色的网站背后都依赖GWT呢。<strong>在这种情况下，要是这一类网站的里头和外头全都一样漂亮，你反而会觉得不可思议了。</strong></p>
<p>不能不说这可真有点讽刺的意味。曾几何时，ASP.NET的开发人员对ViewState可是怨声载道啊。“简直太笨了”的意思就是“我看不懂它都干什么了。”ViewState曾经（现在也）是一项让Web开发效率提高很多倍的技术。它跟Google Web Toolkit（GWT）不一样，但GWT与WebForms的出发点也并非完全没有相似之处。看看GWT网站自己怎么说：</p>
<div style="border-left: 2px solid #ddd; margin-left: 1em; padding-left: 1em;">Google Web Toolkit（GWT）是一个开发工具包，用于构建和优化基于浏览器的复杂应用。GWT的目标是提高高性能Web应用开发的效率，而且无需开发人员熟悉浏览器的各种怪癖，以及XMLHttpRequest，还有JavaScript。</div>
<p>这个出发点可真是值得赞美，不对？难道不可以这样说（抱歉，开个玩笑而已）：</p>
<div style="border-left: 2px solid #ddd; margin-left: 1em; padding-left: 1em;">“<strong>ASP.NET WebForms</strong>”是一个开发工具包，用于构建和优化基于浏览器的复杂应用。它的目标是提高高性能Web应用开发的效率，而且无需开发人员熟悉浏览器的各种怪癖，以及XMLHttpRequest，还有JavaScript。</div>
<p>本文的目的不是想夸奖WebForms，也不是给WebForms正名。WebForms对于某些应用是不二之选，正如GWT对其他一些应用那样。我真正想说的是，使用服务器端的工具包，没有办法像使用jQuery写出清晰的JavaScript，或者使用Razor或HAML写出清晰、清楚的标记一样，给Web开发带来真正的快乐。归根结底，其实就是你选择的抽象级别的问题。</p>
<p>所谓的语义标记在这种情况下仍然是被隐藏的，而诸如<strong><a title="http://schema.org" href="http://schema.org" target="_blank">http://schema.org</a></strong>之类的站点也仍然非常重要，只不过可别指望你能在心仪的站点里看到缩进得像俳句一样整齐的源代码。</p>
<p>大家知道，精简和压缩属于正交优化。而我要说的是，一点也不在乎标记和脚本发送到客户端之后是否美观，确实太草率了。<strong>假如谁都不在乎发送到浏览器的标记，只在乎结果，那谁的标记和JS就那么不值钱啊，谁还愿意主动公开自己的源代码呢？</strong>反正，网站不是运行得挺好嘛，谁还在乎其他的？</p>
<p>现在我要给亲爱的读者提个问题，你觉得自己为什么那么在乎点击“查看网页源代码”之后的结果呢？难道HTML5和JavaScript是Web的新汇编语言不成？</p>
<p><strong>（更新）声明一下：</strong><br />
当然，这个比喻不一定准确。JavaScript代码无论从外观到行为，肯定不像ASM。但作为一个比喻，至少可以说明：</p>
<ul>
<li>JavaScript无所不在；</li>
<li>它速度快而且越来越快；</li>
<li>JavaScript酷似低级的Web编程语言；</li>
<li>它可以通过手工编写，也可以从另一种语言编译而来。</li>
</ul>
<p>作为开发人员或者设计人员，如果有工具提供了你需要的控制和你需要的结果，你最关心哪一个？我认为Rails、ASP.NET，甚至GWT，都没有100%做到这一点。它们都有自己的问题，但<strong>我认为将来的Web不会再专注于清晰的标记，而是夺目的用户体验和语言、工具的天下，开发人员会很享受，效率也会更高。</strong></p>
<p>亲爱的读者，你愿意HTML和JavaScript再多抽象一点吗？还是希望它少抽象一点？</p>
<p><strong>（再更新）</strong>为了让大家明白，我得再说一遍。本文讨论了两个独立的问题。一个当然就是源代码经过了精简和通常的混淆。但这只是第一个问题。真正的问题在于，JavaScript已经成了其他多种语言的目标语言。GWT是一个用JAVA来写Web应用的框架，它产生的字节码是“JavaScript”。GWT为原来天然的语言（HTML+JS）选择了一个设计好的高级语言，并将整个浏览器当成了一个VM。好，问题来了：我们是在写汇编呢，还是在写某种更高级点的代码？而且，我刚知道Google+是用Closure来写的，但这不影响前面的问题。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/07/20/javascript-is-assembly-language-for-the-web-i-2511.html/feed</wfw:commentRss>
		<slash:comments>57</slash:comments>
		</item>
		<item>
		<title>松本行弘说：我想让Ruby更快地发展</title>
		<link>http://www.cn-cuckoo.com/2011/07/13/matz-qa-after-joining-heroku-2504.html</link>
		<comments>http://www.cn-cuckoo.com/2011/07/13/matz-qa-after-joining-heroku-2504.html#comments</comments>
		<pubDate>Wed, 13 Jul 2011 06:22:11 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[编程技术]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2504</guid>
		<description><![CDATA[日文版：Mr Junichi Niino，Rubyの進歩がより速くなることを期待している 英文版：I am looking forward to accelerating Ruby&#8217;s progress 我在前一篇文章里已经提到过了，松本行弘（Yukihiro Matsumoto，或Matz）已经加入了Heroku，成为该公司的首席Ruby架构师。我通过电子邮件询问了Matz对自己未来的设想。 “让Ruby核心功能更丰富、品质更高是我的使命。” PublicKey（以下称Q）：能不能介绍一下你怎么就换工作了呢？ 松本行弘先生（以下称Matz）：上一次跟Marc Benioff先生（Salesforce.com的CEO）碰面时，他就问我，怎么才可以支持Ruby的开发。 于是，我就说了，我说我想要改变当前大多数Ruby核心开发人员面临的窘境：这些人有的是牺牲自己的闲暇时间来完成自己的工作，有的还在为自己的职业前途担心。 然后，他就说他可以为我们提供一些支持，而这也是我通过Heroku加入Salesforce.com的原因（注意：目前还有几位Ruby核心开发人员也正协商加入Heroku）。 也就是说，我们工作的核心内容没有变。我们的使命依旧还是开发Ruby核心，把它变得功能更丰富、品质更高。如此说来，我期待着我们提供的职业前景，以及来自包括Heroku在内的大量Ruby用户的反馈，能够加速Ruby开发的进程。要不然，我换这次工作就没有什么意义了。 不过，加入Heroku并担任他们的首席架构师，并不意味着我只关心Heroku和Salesforce.com的发展。我加入他们不会改变我与NaCI还有Rakuten的合作关系，后两者仍然会继续支持我，而且我还将继续担任Ruby协会的会长一职。 我为什么选这个头衔？因为我觉得“首席架构师”这个名字听起来显得最容易与业务撇清关系。我不打算将来在Heroku参与任何业务上的决策。 Q：你对自己在Heroku的角色有什么期许？ Matz：刚才不是已经说了嘛，我的工作没有什么变化，但我们的开发进度会加快。除此之外，我还能与Heroku进行更加密切的沟通，以便尽早解除Ruby对云计算平台的限制（如果有限制的话）。 而且，我还会继续与Engine Yard、VMWare等公司保持良好的关系，即使我加入了Heroku，我仍然还是那个“Ruby的Matz”，不会辜负他们的信任。 Q：此时此刻，你对Ruby和云计算有什么看法？ Matz：说实话，很多Ruby核心开发人员（包括我自己）都对Web没有多大的兴趣，但云计算会变得越来越重要，这一点是显而易见的。所以，我希望能从这些云计算运营商那里得到更多的需求，以便将其反映到未来的Ruby中。 Q：你会去硅谷上班吗，还是在松江远程工作？ Matz：我的生活方式不会变（但工作方式会变），所以多数时候我会在松江的家里远程参与开发。 就我自己而言，搬到硅谷去工作不一定会比现在这个环境更好。 不过，我想我每年都会跟旧金山/硅谷（包括Heroku）的那些人直接沟通几次。 （注意：大家别误会，Heroku的总部在旧金山，不在硅谷，但他们在新闻稿里自称是“硅谷公司”。） Q：还有别的要说的吗？ Matz：我听说很多（日本之外国家的）人并不知道，Ruby核心团队迄今还没有一个可持续的发展模式。我希望我这次换工作能为代表日本发布消息的日本软件开发人员树立一个榜样。 Q：谢谢你接受采访。]]></description>
			<content:encoded><![CDATA[<p style="text-align: right;">日文版：Mr Junichi Niino，<a href="http://www.publickey1.jp/blog/11/ruby_heroku.html">Rubyの進歩がより速くなることを期待している</a><br />
英文版：<a href="http://blog.new-bamboo.co.uk/2011/7/12/translation-of-matz-q-a-article-after-joining-heroku">I am looking forward to accelerating Ruby&#8217;s progress</a></p>
<p>我在前一篇文章里已经提到过了，松本行弘（Yukihiro Matsumoto，或Matz）已经加入了Heroku，成为该公司的首席Ruby架构师。我通过电子邮件询问了Matz对自己未来的设想。</p>
<p style="text-align: center;padding:1em;border:1px dashed #ddd;">“让Ruby核心功能更丰富、品质更高是我的使命。”</p>
<p><strong>PublicKey（以下称Q）：能不能介绍一下你怎么就换工作了呢？</strong></p>
<p><strong>松本行弘先生（以下称Matz）</strong>：上一次跟Marc Benioff先生（Salesforce.com的CEO）碰面时，他就问我，怎么才可以支持Ruby的开发。</p>
<p>于是，我就说了，我说我想要改变当前大多数Ruby核心开发人员面临的窘境：这些人有的是牺牲自己的闲暇时间来完成自己的工作，有的还在为自己的职业前途担心。</p>
<p>然后，他就说他可以为我们提供一些支持，而这也是我通过Heroku加入Salesforce.com的原因（注意：目前还有几位Ruby核心开发人员也正协商加入Heroku）。</p>
<p>也就是说，我们工作的核心内容没有变。我们的使命依旧还是开发Ruby核心，把它变得功能更丰富、品质更高。如此说来，我期待着我们提供的职业前景，以及来自包括Heroku在内的大量Ruby用户的反馈，能够加速Ruby开发的进程。要不然，我换这次工作就没有什么意义了。</p>
<p>不过，加入Heroku并担任他们的首席架构师，并不意味着我只关心Heroku和Salesforce.com的发展。我加入他们不会改变我与NaCI还有Rakuten的合作关系，后两者仍然会继续支持我，而且我还将继续担任Ruby协会的会长一职。</p>
<p>我为什么选这个头衔？因为我觉得“首席架构师”这个名字听起来显得最容易与业务撇清关系。我不打算将来在Heroku参与任何业务上的决策。</p>
<p><strong>Q：你对自己在Heroku的角色有什么期许？</strong></p>
<p><strong>Matz：</strong>刚才不是已经说了嘛，我的工作没有什么变化，但我们的开发进度会加快。除此之外，我还能与Heroku进行更加密切的沟通，以便尽早解除Ruby对云计算平台的限制（如果有限制的话）。</p>
<p>而且，我还会继续与Engine Yard、VMWare等公司保持良好的关系，即使我加入了Heroku，我仍然还是那个“Ruby的Matz”，不会辜负他们的信任。</p>
<p><strong>Q：此时此刻，你对Ruby和云计算有什么看法？</strong></p>
<p><strong>Matz：</strong>说实话，很多Ruby核心开发人员（包括我自己）都对Web没有多大的兴趣，但云计算会变得越来越重要，这一点是显而易见的。所以，我希望能从这些云计算运营商那里得到更多的需求，以便将其反映到未来的Ruby中。</p>
<p><strong>Q：你会去硅谷上班吗，还是在松江远程工作？</strong></p>
<p><strong>Matz：</strong>我的生活方式不会变（但工作方式会变），所以多数时候我会在松江的家里远程参与开发。</p>
<p>就我自己而言，搬到硅谷去工作不一定会比现在这个环境更好。</p>
<p>不过，我想我每年都会跟旧金山/硅谷（包括Heroku）的那些人直接沟通几次。</p>
<p>（注意：大家别误会，Heroku的总部在旧金山，不在硅谷，但他们在新闻稿里自称是“硅谷公司”。）</p>
<p><strong>Q：还有别的要说的吗？</strong></p>
<p><strong>Matz：</strong>我听说很多（日本之外国家的）人并不知道，Ruby核心团队迄今还没有一个可持续的发展模式。我希望我这次换工作能为代表日本发布消息的日本软件开发人员树立一个榜样。</p>
<p><strong>Q：谢谢你接受采访。</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/07/13/matz-qa-after-joining-heroku-2504.html/feed</wfw:commentRss>
		<slash:comments>56</slash:comments>
		</item>
		<item>
		<title>JavaScript，只有你想不到</title>
		<link>http://www.cn-cuckoo.com/2011/06/22/time-to-learn-javascript-2463.html</link>
		<comments>http://www.cn-cuckoo.com/2011/06/22/time-to-learn-javascript-2463.html#comments</comments>
		<pubDate>Wed, 22 Jun 2011 13:59:27 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[编程技术]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2463</guid>
		<description><![CDATA[原文地址：http://radar.oreilly.com/2011/06/time-to-learn-javascript.html作者简介：Mike Loukides 很长时间以来，JavaScript在我眼里都是编程语言中的二等公民。早先，它经常是很多安全问题的发源地，就像是胶水一样，它能把HTML应用与样式粘到一块，可没有人拿它来正正规规地写程序；这样的情形太普遍了。而Java、Ruby、Python，这些才是真正能用来写程序的语言。 过去几年间，我对JavaScript的态度有了彻底的改变。JavaScript已经“长大成人”了。我敢保证很多JavaScript开发人员都不会认同我前面的说法，他们会说JavaScript一直都是一个十分强大、成熟、深得人心的语言。或许他们说得没错，事实上只要是一门完整的编程语言，就能拿来写程序，也包括BASIC这种滥东西。而一门语言真正有用，必须一方面自身具备很强的表达能力，另一方面还要有众多的库和开发工具。显然，JavaScript的表达能力早就没有问题了，即便是创建对象的方式有点不好让人接受，其实问题也不大。直到最近，一些极其重要的扭转局面的技术出现了：jQuery、JSON、Node.js和HTML5。或许JavaScript以前就是一门完善的语言了，但却是这些重要的相关技术（以及其他一些没有在这里提及的），让JavaScript成为了每一个开发人员都知道的语言。如果明年你要学一门新语言的话，那一定就是JavaScript。 潜力无限的Node.js 说Node.js潜力无限的意思，就是它有可能引发Web开发的革命。Node.js是一个框架，用于构建高性能Web应用——即使是巨量的请求也能应对如流。虽然Node本身作为一个底层框架，能够用于构建任何应用，但它还是最适合构建Web服务器。它的异步事件驱动模式与传统的请求-响应模式相比，无疑更适合Web应用。 有两方面因素更让人看好Node。首先，Google在提升JavaScript性能方面掀起了一场革命。这句话的意思并不是说你随时随地都可以用上最好的JavaScript引擎（尽管这也是我们一个美好的期望）。但可以肯定的是，Google在其他竞争对手还没有上心的情况下，真的把JavaScript性能当成了一回事儿。如此一来，就把Mozilla、Apple、Microsoft、Opera，还有其他浏览器开发商逼到了性能竞赛的跑道上。结果导致我们现在使用的JavaScript引擎较之几年前快了不知道有多少倍，完全有能力运行复杂的大型Web应用。 其次，Node有着庞大的开发人员基础。不管大家在服务器端使用的是什么语言，但在客户端却鲜有不使用JavaScript的。有的人可能是“剪刀加浆糊”式的东拼西凑，有的人则可能用JavaScript做出了高超的Ajax应用，而有的人甚至实现了全功能的应用程序，像Twitter或Gmail。可不管怎么说，JavaScript开发人员的数量无疑是非常庞大的。而Doug Crockford等作者更是极力宣传所有人都应该把JavaScript当成一门严肃正经的编程语言来看待——尽管它还有不少缺点。 当时当下，编写Node应用相对还是个“粗”活儿，毕竟它只是一个底层库。想象一下单纯使用JavaScript写代码，对，就是这种感觉，Node当前还是一个beta版的格局，与Rails或Django这样成熟的Web开发框架还没法比。这种状况无疑会改变。一些轻量级的框架，比如Express，已经出现了；我坚信更多基于Node的全功能框架将继续不断涌现。 前面提到过一些几乎完全在浏览器中运行的高级Web应用。那些都已经不算什么新鲜事儿了，Gmail多大了？Google Maps贵庚了？不过，用JavaScript编写在浏览器中运行的应用的客户端无疑是越来越有吸引力了。HTML5则继续推高了人们对这一趋势的期许。 HTML5就是JavaScript 我不知道已经说过多少次了，HTML5实际上并没有多少与HTML有关，它其实就是JavaScript。HTML本身有什么变化？不过一些新标签而已，况且哪个新标签都不难理解。HTML5的威力在于让你能用JavaScript来创建这些标签。假如没有后台代码通过Canvas来创建动画、游戏，或者通过它来实现一些数据的可视化，这个标签也没有大用处。从浏览器开始支持Canvas开始，我已经看到了Asteroids（行星游戏）的上百个实现，那都是开发人员为熟悉这个新特性所做的练习。有的比较粗糙一些，而有的则极其精美。这些完全都要归功于JavaScript。 由此可见，HTML5并不是以尖括号为特征的标签语言的一次大的改进，其实质是赋予了JavaScript更强大的能力。WebGL库（当前还羽翼未丰）支持在HTML5的画布中绘制实时的3D图形。HTML5的地理位置支持在浏览器中实现LBS（Location Based Service）应用——这都是手机的基本配置。而持久存储以及离线功能则为开发能与桌面应用媲美，但却在浏览器中运行的全功能应用奠定了基础。目前，就连增加多点触摸事件的实验性的库也已经出现了。凡此种种，无一不是实实在在的JavaScript特性。HTML5只是为这些高级功能的发挥提供了舞台。 退一步讲，不依赖于HTML5的浏览器端开发库也取得了长足的进步。长久以来，JavaScript一直都是在HTML中实现动态效果的不二之选。可两个问题迟迟得不到解决：一是浏览器兼容性问题，二是直接操作DOM太麻烦。jQuery让这两个问题霎那间消失得无影无踪，这个库已经成为现代基于浏览器的客户端开发的基本配置。不过，并非只有jQuery。Protovis、还有D3，都可以让你直接在浏览器中创建复杂的交互性数据可视化效果，有史以来第一次让浏览器成为了展示数据的一个重要媒介。 JavaScript与数据库，编译器与语言 就连数据库里都开始广泛使用JavaScript了！当前如火如荼的NoSQL运动的三只领头羊：CouchDB、MongoDB和Riak，都是“文档数据库”。它们保存的不是表，而是文档。这几个数据库所谓的“文档”，其实就是JSON文档，而不是Word或Excel。（Riak除了JSON文档，还支持XML和纯文本。）JSON已经成为一种被广泛采用的数据交换格式（所有现代的编程语言几乎全都有解析JSON的库），不过请注意，JSON实际上不就是一种序列化JavaScript对象的格式嘛！因此，虽然你可以在任何语言中使用JSON，但在JavaScript开发中使用它则是再自然不过的事了。况且，JSON 这个格式成为一种跨语言的标准，而不是Python、Ruby或Java等语言的序列化格式，这个事实本身足以说明JavaScript将在更加广阔的舞台上大显身手。还不仅仅如此，上述三个数据库都内置了支持JavaScript查询的能力。未来几年，更多的人都将会惊讶地发现，JavaScript和JSON还会内置到其他应用程序中！ JavaScript时代的大幕才刚刚拉开。在今年的JSConf上，一个核心主题就是“JavaScript到JavaScript的编译器”，也被人们看成是未来的一个主要趋势。Google在“编译生成JavaScript代码”方面是首开先河者。据我所知，GWT（Google Web Toolkit）应该是通过编译（从Java代码）生成JavaScript代码的第一个框架。以前我对GWT并没有太重视，只是觉得它是一个致力于拯救那些Java程序员的框架，好让他们不必因为（学习）编写JavaScript而浪费时间。可是，GWT在编译过程中对JavaScript做了那么多的优化，简直是太神了。Closure就是一个“JavaScript到JavaScript的编译器”，能够实现同样级别的优化。Traceur，这是几个星期前才冒出来的一个框架，通过它能够试验JavaScript的新特性，换句话说，它可以把带有实验性语言特性的JavaScript代码编译成可以在所有现代平台中运行的JavaScript代码。 最后，我们也开始看到了当初Java大旗下JVM语言的蓬勃景象：很多语言都在致力于编译成JavaScript！其中有一些语言比较有意思，像Coffeescript和Kaffeine，它们在风格上酷似JavaScript，但更关注弥补JavaScript的一些不够完善的地方。是不是觉得JavaScript的对象模型特有意思，可怎么看怎么有点笨笨滴，有木有？是不是一想到基于原型创建一个实际的对象都需要反反复复地定义这定义那，就望而却步了，有木有？Coffeescript对此作了明显的改进。除了完善对象模型，Coffeescript 还添加了类似列表解析（list comprehensions）的新特性，去掉了大部分花括号。就像在Python中一样，要使用缩进来区分代码块。 未来的Web服务器、取之不尽的客户端库、HTML5、数据库，乃至基于JavaScript的语言——我现在一睁眼看到的就是JavaScript！假如你曾经对JavaScript敬而远之，今年可是该学习它了。没有任何理由，真的，再不学，恐怕你就没机会跟上时代了！]]></description>
			<content:encoded><![CDATA[<p style="text-align: right;">原文地址：<a href="http://radar.oreilly.com/2011/06/time-to-learn-javascript.html">http://radar.oreilly.com/2011/06/time-to-learn-javascript.html</a><br />作者简介：<a href="http://radar.oreilly.com.cn/user/michael_loukides">Mike Loukides </a></p>
<p><a href="http://radar.oreilly.com.cn/user/michael_loukides"><img class="colorbox-2463"  src="/images/loukides.jpg" style="float:left;margin:0 1em 1em 0;" /></a>很长时间以来，JavaScript在我眼里都是编程语言中的二等公民。早先，它经常是很多安全问题的发源地，就像是胶水一样，它能把HTML应用与样式粘到一块，可没有人拿它来正正规规地写程序；这样的情形太普遍了。而Java、Ruby、Python，这些才是真正能用来写程序的语言。</p>
<p>过去几年间，我对JavaScript的态度有了彻底的改变。JavaScript已经“长大成人”了。我敢保证很多JavaScript开发人员都不会认同我前面的说法，他们会说JavaScript一直都是一个十分强大、成熟、深得人心的语言。或许他们说得没错，事实上只要是一门完整的编程语言，就能拿来写程序，也包括BASIC这种滥东西。而一门语言真正有用，必须一方面自身具备很强的表达能力，另一方面还要有众多的库和开发工具。显然，JavaScript的表达能力早就没有问题了，即便是创建对象的方式有点不好让人接受，其实问题也不大。直到最近，一些极其重要的扭转局面的技术出现了：jQuery、JSON、Node.js和HTML5。或许JavaScript以前就是一门完善的语言了，但却是这些重要的相关技术（以及其他一些没有在这里提及的），让JavaScript成为了每一个开发人员都知道的语言。如果明年你要学一门新语言的话，那一定就是JavaScript。</p>
<h2>潜力无限的Node.js</h2>
<p>说<a href="http://nodejs.org/">Node.js</a>潜力无限的意思，就是它有可能引发Web开发的革命。Node.js是一个框架，用于构建高性能Web应用——即使是巨量的请求也能应对如流。虽然Node本身作为一个底层框架，能够用于构建任何应用，但它还是最适合构建Web服务器。它的异步事件驱动模式与传统的请求-响应模式相比，无疑更适合Web应用。<span id="more-2463"></span></p>
<p>有两方面因素更让人看好Node。首先，Google在提升JavaScript性能方面掀起了一场革命。这句话的意思并不是说你随时随地都可以用上最好的JavaScript引擎（尽管这也是我们一个美好的期望）。但可以肯定的是，Google在其他竞争对手还没有上心的情况下，真的把JavaScript性能当成了一回事儿。如此一来，就把Mozilla、Apple、Microsoft、Opera，还有其他浏览器开发商逼到了性能竞赛的跑道上。结果导致我们现在使用的JavaScript引擎较之几年前快了不知道有多少倍，完全有能力运行复杂的大型Web应用。</p>
<p>其次，Node有着庞大的开发人员基础。不管大家在服务器端使用的是什么语言，但在客户端却鲜有不使用JavaScript的。有的人可能是“剪刀加浆糊”式的东拼西凑，有的人则可能用JavaScript做出了高超的Ajax应用，而有的人甚至实现了全功能的应用程序，像Twitter或Gmail。可不管怎么说，JavaScript开发人员的数量无疑是非常庞大的。而<a href="http://www.crockford.com/">Doug Crockford</a>等作者更是极力宣传所有人都应该把JavaScript当成一门严肃正经的编程语言来看待——尽管它还有不少缺点。</p>
<p>当时当下，编写Node应用相对还是个“粗”活儿，毕竟它只是一个底层库。想象一下单纯使用JavaScript写代码，对，就是这种感觉，Node当前还是一个beta版的格局，与Rails或Django这样成熟的Web开发框架还没法比。这种状况无疑会改变。一些轻量级的框架，比如<a href="http://expressjs.com/">Express</a>，已经出现了；我坚信更多基于Node的全功能框架将继续不断涌现。</p>
<p>前面提到过一些几乎完全在浏览器中运行的高级Web应用。那些都已经不算什么新鲜事儿了，<a href="http://en.wikipedia.org/wiki/History_of_Gmail">Gmail多大了</a>？<a href="http://en.wikipedia.org/wiki/Google_Maps#History">Google Maps贵庚了</a>？不过，用JavaScript编写在浏览器中运行的应用的客户端无疑是越来越有吸引力了。HTML5则继续推高了人们对这一趋势的期许。</p>
<h2>HTML5就是JavaScript</h2>
<p>我不知道已经说过多少次了，HTML5实际上并没有多少与HTML有关，它其实就是JavaScript。HTML本身有什么变化？不过一些新标签而已，况且哪个新标签都不难理解。HTML5的威力在于让你能用JavaScript来创建这些标签。假如没有后台代码通过Canvas来创建动画、游戏，或者通过它来实现一些数据的可视化，这个标签也没有大用处。从浏览器开始支持Canvas开始，我已经看到了<a href="http://www.kevs3d.co.uk/dev/asteroids/">Asteroids</a>（行星游戏）的上百个实现，那都是开发人员为熟悉这个新特性所做的练习。有的比较粗糙一些，而有的则极其精美。这些完全都要归功于JavaScript。</p>
<p>由此可见，HTML5并不是以尖括号为特征的标签语言的一次大的改进，其实质是赋予了JavaScript更强大的能力。<a href="http://en.wikipedia.org/wiki/WebGL">WebGL</a>库（当前还羽翼未丰）支持在HTML5的画布中绘制实时的3D图形。HTML5的地理位置支持在浏览器中实现LBS（Location Based Service）应用——这都是手机的基本配置。而持久存储以及离线功能则为开发能与桌面应用媲美，但却在浏览器中运行的全功能应用奠定了基础。目前，就连<a href="http://ajaxian.com/archives/iphone-web-multitouch-javascript-virtual-light-table">增加多点触摸事件的实验性的库</a>也已经出现了。凡此种种，无一不是实实在在的JavaScript特性。HTML5只是为这些高级功能的发挥提供了舞台。</p>
<p>退一步讲，不依赖于HTML5的浏览器端开发库也取得了长足的进步。长久以来，JavaScript一直都是在HTML中实现动态效果的不二之选。可两个问题迟迟得不到解决：一是浏览器兼容性问题，二是直接操作DOM太麻烦。<a href="http://jquery.com/">jQuery</a>让这两个问题霎那间消失得无影无踪，这个库已经成为现代基于浏览器的客户端开发的基本配置。不过，并非只有jQuery。<a href="http://vis.stanford.edu/protovis/">Protovis</a>、<a href="https://github.com/mbostock/d3">还有D3</a>，都可以让你直接在浏览器中创建复杂的交互性数据可视化效果，有史以来第一次让浏览器成为了展示数据的一个重要媒介。</p>
<h2>JavaScript与数据库，编译器与语言</h2>
<p>就连数据库里都开始广泛使用JavaScript了！当前如火如荼的NoSQL运动的三只领头羊：<a href="http://couchdb.apache.org/">CouchDB</a>、<a href="http://www.mongodb.org/">MongoDB</a>和<a href="http://wiki.basho.com/">Riak</a>，都是“文档数据库”。它们保存的不是表，而是文档。这几个数据库所谓的“文档”，其实就是<a href="http://www.json.org/">JSON</a>文档，而不是Word或Excel。（Riak除了JSON文档，还支持XML和纯文本。）JSON已经成为一种被广泛采用的数据交换格式（所有现代的编程语言几乎全都有解析JSON的库），不过请注意，JSON实际上不就是一种序列化JavaScript对象的格式嘛！因此，虽然你可以在任何语言中使用JSON，但在JavaScript开发中使用它则是再自然不过的事了。况且，JSON 这个格式成为一种跨语言的标准，而不是Python、Ruby或Java等语言的序列化格式，这个事实本身足以说明JavaScript将在更加广阔的舞台上大显身手。还不仅仅如此，上述三个数据库都内置了支持JavaScript查询的能力。未来几年，更多的人都将会惊讶地发现，JavaScript和JSON还会内置到其他应用程序中！</p>
<p>JavaScript时代的大幕才刚刚拉开。在今年的<a href="http://2011.jsconf.us/">JSConf</a>上，一个核心主题就是“JavaScript到JavaScript的编译器”，也被人们看成是未来的一个主要趋势。Google在“编译生成JavaScript代码”方面是首开先河者。据我所知，<a href="http://code.google.com/webtoolkit/">GWT（Google Web Toolkit）</a>应该是通过编译（从Java代码）生成JavaScript代码的第一个框架。以前我对GWT并没有太重视，只是觉得它是一个致力于拯救那些Java程序员的框架，好让他们不必因为（学习）编写JavaScript而浪费时间。可是，GWT在编译过程中对JavaScript做了那么多的优化，简直是太神了。<a href="http://code.google.com/closure/compiler/">Closure</a>就是一个“JavaScript到JavaScript的编译器”，能够实现同样级别的优化。<a href="http://code.google.com/p/traceur-compiler/">Traceur</a>，这是几个星期前才冒出来的一个框架，通过它能够试验JavaScript的新特性，换句话说，它可以把带有实验性语言特性的JavaScript代码编译成可以在所有现代平台中运行的JavaScript代码。</p>
<p>最后，我们也开始看到了当初Java大旗下JVM语言的蓬勃景象：<a href="https://github.com/jashkenas/coffee-script/wiki/List-of-languages-that-compile-to-JS">很多语言都在致力于编译成JavaScript</a>！其中有一些语言比较有意思，像<a href="http://jashkenas.github.com/coffee-script/">Coffeescript</a>和<a href="http://weepy.github.com/kaffeine/">Kaffeine</a>，它们在风格上酷似JavaScript，但更关注弥补JavaScript的一些不够完善的地方。是不是觉得JavaScript的对象模型特有意思，可怎么看怎么有点笨笨滴，有木有？是不是一想到基于原型创建一个实际的对象都需要反反复复地定义这定义那，就望而却步了，有木有？Coffeescript对此作了明显的改进。除了完善对象模型，Coffeescript 还添加了类似列表解析（list comprehensions）的新特性，去掉了大部分花括号。就像在Python中一样，要使用缩进来区分代码块。</p>
<p>未来的Web服务器、取之不尽的客户端库、HTML5、数据库，乃至基于JavaScript的语言——我现在一睁眼看到的就是JavaScript！假如你曾经对JavaScript敬而远之，今年可是该学习它了。没有任何理由，真的，再不学，恐怕你就没机会跟上时代了！</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/06/22/time-to-learn-javascript-2463.html/feed</wfw:commentRss>
		<slash:comments>83</slash:comments>
		</item>
		<item>
		<title>MVC之父对“模型-视图-控制器”的最初定义</title>
		<link>http://www.cn-cuckoo.com/2011/06/22/mvc-originals-2454.html</link>
		<comments>http://www.cn-cuckoo.com/2011/06/22/mvc-originals-2454.html#comments</comments>
		<pubDate>Tue, 21 Jun 2011 23:01:38 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[交互设计]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2454</guid>
		<description><![CDATA[出处：http://heim.ifi.uio.no/~trygver/1979/mvc-2/1979-12-MVC.pdf 我创立的Model-View-Controller（MVC）模式作为一个直观的解决方案，针对的是一个一般性的问题，即让用户能够支配自己从多个角度看到的信息。MVC引起了的关注之多，让人有点始料不及。有些教材对MVC的改造甚至到了离经叛道的程度，企图达到让计算机来控制用户的悖谬目的。 而MVC的根本目的是在人类头脑中的心智模型和计算机中的数字模型之间架起一座桥梁。理想情况下，MVC的实现方案与用户直接查看和操作领域信息的直觉吻合。假如用户想在不同的上下文中以及/或者以不同的视角看到相同的模型要素，那MVC就有了它的用武之地。 模型 模型，表示知识。它既可能是一个对象（当然，如果仅一个对象就没多大意思了），也可能是由许多对象组成的结构。 模型及其组成部分是一方，而模型创建者意识中要表现的世界则是另一方，这两方应该一一对应。自然地，模型的每个节点都应该明确对应于问题的一个部分。 模型的所有节点都应该把问题解决到相同的程度，把面向问题的节点（例如，在日程中添加约会活动）与实现细节（例如，用段落展示）混在一起不容易理解，是应该避免的做法。 视图 视图是模型的（可见的）表现。视图通常会突出模型的某些属性，同时隐藏其他属性。从这个意义上讲，视图就像是一个展示过滤器。 视图依赖于模型（或模型的一部分），通过询问问题的方式从模型中获得用于展示的必要数据。视图通过发送适当的消息，也可以更新模型。这些问题和消息都要按照模型的术语来传达，由此视图必须得知道自己所要表现的模型，它的属性都有什么语义。（比如说，视图可能会询问模型的标识符，期待返回一个Text的实例，但它可能并不认为模型就是Text类。） 控制器 控制器是用户与系统之间的纽带。它为用户提供输入，即它会将相关的视图显示在屏幕适当的位置上（供用户浏览查看）。它为用户提供输出的手段，即它会向用户展示菜单以及其他能接受命令和数据的控件。控制器接收到上述的用户输出，将其转换为适当的消息，然后再将这些消息传递给一或多个视图。 控制器不应该当作视图来用，例如，不能用控制器来画箭头以连接视图的节点。 从另一方面讲，视图也不应该关心用户输入，比如鼠标操作或按键操作之类的。在任何情况下，都应该能够在控制器里编写一个方法，该方法将消息发送到视图，以便原原本本地再现用户的命令。 编辑器 控制器负责连接其所有的视图，这些视图是该控制器的组成部分。有的视图会提供一个特殊的控制器，叫编辑器（editor），以便用户通过它来修改由视图表现的信息。这种编辑器可以被挂接到控制器与其视图之间的路径上，类似于控制器的扩展。编辑完成之后，则从路径上将编辑器移除并丢弃。 注意，编辑器要通过相关视图的具体表现来与用户沟通，因此编辑器与视图是紧密相关的。控制器通过询问视图来获悉编辑器的存在，除此之外没有其他适当的信息来源。 参考 Trygve Reenskaug简介 什么是MVC模式？]]></description>
			<content:encoded><![CDATA[<p style="text-align: right;">出处：<a href="http://heim.ifi.uio.no/~trygver/1979/mvc-2/1979-12-MVC.pdf">http://heim.ifi.uio.no/~trygver/1979/mvc-2/1979-12-MVC.pdf</a></p>
<p>我创立的Model-View-Controller（MVC）模式作为一个直观的解决方案，针对的是一个一般性的问题，即让用户能够支配自己从多个角度看到的信息。MVC引起了的关注之多，让人有点始料不及。有些教材对MVC的改造甚至到了离经叛道的程度，企图达到让计算机来控制用户的悖谬目的。</p>
<p>而MVC的根本目的是在人类头脑中的心智模型和计算机中的数字模型之间架起一座桥梁。理想情况下，MVC的实现方案与用户直接查看和操作领域信息的直觉吻合。假如用户想在不同的上下文中以及/或者以不同的视角看到相同的模型要素，那MVC就有了它的用武之地。</p>
<h2>模型</h2>
<p>模型，表示知识。它既可能是一个对象（当然，如果仅一个对象就没多大意思了），也可能是由许多对象组成的结构。</p>
<p>模型及其组成部分是一方，而模型创建者意识中要表现的世界则是另一方，这两方应该一一对应。自然地，模型的每个节点都应该明确对应于问题的一个部分。</p>
<p>模型的所有节点都应该把问题解决到相同的程度，把面向问题的节点（例如，在日程中添加约会活动）与实现细节（例如，用段落展示）混在一起不容易理解，是应该避免的做法。</p>
<h2>视图</h2>
<p>视图是模型的（可见的）表现。视图通常会突出模型的某些属性，同时隐藏其他属性。从这个意义上讲，视图就像是一个展示过滤器。</p>
<p>视图依赖于模型（或模型的一部分），通过询问问题的方式从模型中获得用于展示的必要数据。视图通过发送适当的消息，也可以更新模型。这些问题和消息都要按照模型的术语来传达，由此视图必须得知道自己所要表现的模型，它的属性都有什么语义。（比如说，视图可能会询问模型的标识符，期待返回一个Text的实例，但它可能并不认为模型就是Text类。）</p>
<h2>控制器</h2>
<p>控制器是用户与系统之间的纽带。它为用户提供输入，即它会将相关的视图显示在屏幕适当的位置上（供用户浏览查看）。它为用户提供输出的手段，即它会向用户展示菜单以及其他能接受命令和数据的控件。控制器接收到上述的用户输出，将其转换为适当的消息，然后再将这些消息传递给一或多个视图。</p>
<p>控制器不应该当作视图来用，例如，不能用控制器来画箭头以连接视图的节点。</p>
<p>从另一方面讲，视图也不应该关心用户输入，比如鼠标操作或按键操作之类的。在任何情况下，都应该能够在控制器里编写一个方法，该方法将消息发送到视图，以便原原本本地再现用户的命令。</p>
<h2>编辑器</h2>
<p>控制器负责连接其所有的视图，这些视图是该控制器的组成部分。有的视图会提供一个特殊的控制器，叫编辑器（editor），以便用户通过它来修改由视图表现的信息。这种编辑器可以被挂接到控制器与其视图之间的路径上，类似于控制器的扩展。编辑完成之后，则从路径上将编辑器移除并丢弃。</p>
<p>注意，编辑器要通过相关视图的具体表现来与用户沟通，因此编辑器与视图是紧密相关的。控制器通过询问视图来获悉编辑器的存在，除此之外没有其他适当的信息来源。</p>
<div style="padding: 1em; border: 1px dashed #ddd;">
<h2>参考</h2>
<ul>
<li><a href="http://www.umlchina.com/Chat/Reenskaugnews2010.htm">Trygve Reenskaug简介</a></li>
<li><a href="http://codeigniter.org.cn/forums/thread-1338-1-1.html">什么是MVC模式？</a></li>
</ul>
<div></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/06/22/mvc-originals-2454.html/feed</wfw:commentRss>
		<slash:comments>33</slash:comments>
		</item>
		<item>
		<title>编程语言教程书该怎么写: 向K&amp;R学习！</title>
		<link>http://www.cn-cuckoo.com/2011/06/05/lax-language-tutorials-2450.html</link>
		<comments>http://www.cn-cuckoo.com/2011/06/05/lax-language-tutorials-2450.html#comments</comments>
		<pubDate>Sun, 05 Jun 2011 04:59:05 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[原创]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2450</guid>
		<description><![CDATA[原文地址：Lax Language Tutorials Andrew Binstock 每年在评审Jolt Awards图书的时候，我都会被一些语言教程类图书弄得心力交瘁。从这些年的评审经验来看，这些语言类教程的写得都不错，但除此之外，少有亮点。换句话来说，这些书都很严谨、很精密，如果读者有足够的定力，通过它们掌握一门语言的编程技术还是不成问题的。可是，即便对那些卖得最好的书，除此之外我都想不出来还能多说几句什么样的赞美的话了。 这些书普遍存在的一个缺点就是把简单的任务复杂化。最大的或者说最常见的一个问题，是作者们混淆了教程与一本面面俱到地介绍一门语言的专著的区别。由于种种原因，出版行业似乎特别热衷于后一种体裁，结果就导致了一些令人瞠目的大部头。我曾经看到过一本“介绍”Java语言的书，厚达1480页。如果说入门读物都得这么厚，显然是不合理的。不消说，这本书深入地讨论了一下AWT和Swing，然后笔锋一转，又给读者罗列出各种各样的第三方库，关于虚拟机的研究当然少不了，而最终则收尾于并行程序设计。谢天谢地，到这里终于全书完。鉴于这本书已经出到了眼前的第4版，有理由认为它体现了作者对它最终的心理预期。那就是，这实际上是教程兼参考书。而且，既然书的重量都达到了4.5磅（约2.04千克），我想多半也只能把它当作参考书来用了。Mark Lutz的《Learning Python》是Python语言图书中与此类似的一本。其他语言类图书中，像把Ruby介绍给西方读者的“鹤嘴锄书”（《Programming Ruby: The Pragmatic Programmers&#8217; Guide》），作为此类图书也是当之无愧。书的前一半是教程，后一半明说就是参考。这种方法就好多了。不用管其中的Ruby教程占了多少篇幅（418页），仅就其质量而言，就充分说明它大受欢迎是有理由的。 第二个常见的问题，就是作者忘了读者在打算学一门新语言的时候，最想做的是什么；当然，无非就是要写几个小程序，借以熟悉语法。然而，很多教程通篇都是只有一两行的微型代码示例，只够演示某个功能，但没有一个独立有用的程序。如果语言还有一个内置的shell（或解释器），比如像Ruby、Groovy、Scala，那这个倾向就越发地明显了。 比如说，Odersky、Spoon和Venners合著的Scala教程（《Programming in Scala》）就能清楚地反映出这个问题。在这本书的前200页里面，超过20行代码的示例只有一个；大部分都不会超过10行。[而在K&#038;R（Brian W. Kernighan和Dennis M. Ritchie）那本书（稍后会说到）里，第一个20行代码的示例出现在第26页。]结果呢，按照我自己的经验，就是看了半天书，也敲了不少代码，由此了解了不少功能，但却始终没有写出一个有点什么用的程序来。实话实说，这种现象简直太普遍了。现在，我眼前就摆着两本书，一本Clojure，一本Groovy，也都是这个套路。 最后一个问题在编辑不给力的书中经常会发现：一心只想展示一门语言的聪明技巧或者能做到的一些小hack。个人认为，读者是想来学语言的，不是来欣赏语言特技的。这个问题最常见于那些函数式语言，或者像Groovy一样有意设计得比竞争性语言（对Groovy来说就是Java）更好的语言的教程。 以上三个问题之所以让人感到难以理解，关键在于长期以来一直都有一本绝好的榜样：Kernighan和Ritchie的《C Programming Language》（K&#038;R）。拿这本书跟其他教程比一比，差异立现。先从最明显的地方开始，K&#038;R的教程部分只有177页，随后是40页的附录，附录是极其简明的参考。在这种篇幅适中的情况下，任何读者都能轻松看完，并且做完全部示例。其次，大多数程序都在20行代码以上，既有相应的用途，也不让人感到陌生，而且相对完整。即便是到了这本书的第125页左右，示例程序中都包含main()函数。这里说的可不是代码片段，而是虽短但却真实的程序。最后，书中对所有程序的解释分析十分透彻，而且前后相继，由浅入深。没有对功能漫无边际的简单罗列，所有示例都有一种内在的线索，让读者在任何时候都知道自己掌握了哪些基础知识，还需要探索哪些基础知识。 那在K&#038;R中看不到什么呢？最明显的是，书中没有解释标准库中每个函数功能的部分。Java图书也应该把这个部分删掉。（对Java知识体系介绍得最为全面的两本书，就是Horstmann和Comell合著的《Core Java》卷I和卷II。但在两卷合起来1800页的篇幅中，没有包含教程，也没有像书中所说的那样讲述。） K&#038;R也没有填鸭式的说教。看这本书必须边看边思考。所有信息都摆在那儿，但你必须动手去做每一个例子，才能理解这门语言。作者希望看这本书的读者很用心很专注，因此会在你迅速学会这门语言的过程中，随时为你提供帮助，但不会强迫你一页接一页地阅读那些对理解语言没用的东西。 恐怕有人会说，C只不过是一门小型语言，所以介绍它自然用不着大部头。要是你也这么认为，请睁开眼来看看别的C语言教程，看有哪一本书像K&#038;R这么薄，而且写得又那么好。要不然，再看看JavaScript，JavaScript也是一门小型语言，但还没有哪本书是篇幅又短，又容易理解的。 我想说明一下，前面提到的那几本书都是着意挑选出来的，因为这几本书在我看来都是相应语言领域的最佳教程。Odersky等写的Scala、Thomas写的Ruby，还有Lutz那本Python，这些都是学习相应语言的最佳起点。我只是希望这些书要是能更像K&#038;R那样就好了。 ——Andrew Binstock 《Dr. Dobb&#8217;s》主编]]></description>
			<content:encoded><![CDATA[<p>原文地址：<a href="http://drdobbs.com/tools/229700183">Lax Language Tutorials</a><br />
Andrew Binstock</p>
<p>每年在评审Jolt Awards图书的时候，我都会被一些语言教程类图书弄得心力交瘁。从这些年的评审经验来看，这些语言类教程的写得都不错，但除此之外，少有亮点。换句话来说，这些书都很严谨、很精密，如果读者有足够的定力，通过它们掌握一门语言的编程技术还是不成问题的。可是，即便对那些卖得最好的书，除此之外我都想不出来还能多说几句什么样的赞美的话了。</p>
<p>这些书普遍存在的一个缺点就是把简单的任务复杂化。最大的或者说最常见的一个问题，是作者们混淆了教程与一本面面俱到地介绍一门语言的专著的区别。由于种种原因，出版行业似乎特别热衷于后一种体裁，结果就导致了一些令人瞠目的大部头。我曾经看到过一本“介绍”Java语言的书，厚达1480页。如果说入门读物都得这么厚，显然是不合理的。不消说，这本书深入地讨论了一下AWT和Swing，然后笔锋一转，又给读者罗列出各种各样的第三方库，关于虚拟机的研究当然少不了，而最终则收尾于并行程序设计。谢天谢地，到这里终于全书完。鉴于这本书已经出到了眼前的第4版，有理由认为它体现了作者对它最终的心理预期。那就是，这实际上是教程兼参考书。而且，既然书的重量都达到了4.5磅（约2.04千克），我想多半也只能把它当作参考书来用了。Mark Lutz的《Learning Python》是Python语言图书中与此类似的一本。其他语言类图书中，像把Ruby介绍给西方读者的“鹤嘴锄书”（《Programming Ruby: The Pragmatic Programmers&#8217; Guide》），作为此类图书也是当之无愧。书的前一半是教程，后一半明说就是参考。这种方法就好多了。不用管其中的Ruby教程占了多少篇幅（418页），仅就其质量而言，就充分说明它大受欢迎是有理由的。</p>
<p>第二个常见的问题，就是作者忘了读者在打算学一门新语言的时候，最想做的是什么；当然，无非就是要写几个小程序，借以熟悉语法。然而，很多教程通篇都是只有一两行的微型代码示例，只够演示某个功能，但没有一个独立有用的程序。如果语言还有一个内置的shell（或解释器），比如像Ruby、Groovy、Scala，那这个倾向就越发地明显了。</p>
<p>比如说，Odersky、Spoon和Venners合著的Scala教程（《Programming in Scala》）就能清楚地反映出这个问题。在这本书的前200页里面，超过20行代码的示例只有一个；大部分都不会超过10行。[而在K&#038;R（Brian W. Kernighan和Dennis M. Ritchie）那本书（稍后会说到）里，第一个20行代码的示例出现在第26页。]结果呢，按照我自己的经验，就是看了半天书，也敲了不少代码，由此了解了不少功能，但却始终没有写出一个有点什么用的程序来。实话实说，这种现象简直太普遍了。现在，我眼前就摆着两本书，一本Clojure，一本Groovy，也都是这个套路。<br />
<span id="more-2450"></span><br />
最后一个问题在编辑不给力的书中经常会发现：一心只想展示一门语言的聪明技巧或者能做到的一些小hack。个人认为，读者是想来学语言的，不是来欣赏语言特技的。这个问题最常见于那些函数式语言，或者像Groovy一样有意设计得比竞争性语言（对Groovy来说就是Java）更好的语言的教程。</p>
<p>以上三个问题之所以让人感到难以理解，关键在于长期以来一直都有一本绝好的榜样：Kernighan和Ritchie的《C Programming Language》（K&#038;R）。拿这本书跟其他教程比一比，差异立现。先从最明显的地方开始，K&#038;R的教程部分只有177页，随后是40页的附录，附录是极其简明的参考。在这种篇幅适中的情况下，任何读者都能轻松看完，并且做完全部示例。其次，大多数程序都在20行代码以上，既有相应的用途，也不让人感到陌生，而且相对完整。即便是到了这本书的第125页左右，示例程序中都包含main()函数。这里说的可不是代码片段，而是虽短但却真实的程序。最后，书中对所有程序的解释分析十分透彻，而且前后相继，由浅入深。没有对功能漫无边际的简单罗列，所有示例都有一种内在的线索，让读者在任何时候都知道自己掌握了哪些基础知识，还需要探索哪些基础知识。</p>
<p>那在K&#038;R中看不到什么呢？最明显的是，书中没有解释标准库中每个函数功能的部分。Java图书也应该把这个部分删掉。（对Java知识体系介绍得最为全面的两本书，就是Horstmann和Comell合著的《Core Java》卷I和卷II。但在两卷合起来1800页的篇幅中，没有包含教程，也没有像书中所说的那样讲述。）</p>
<p>K&#038;R也没有填鸭式的说教。看这本书必须边看边思考。所有信息都摆在那儿，但你必须动手去做每一个例子，才能理解这门语言。作者希望看这本书的读者很用心很专注，因此会在你迅速学会这门语言的过程中，随时为你提供帮助，但不会强迫你一页接一页地阅读那些对理解语言没用的东西。</p>
<p>恐怕有人会说，C只不过是一门小型语言，所以介绍它自然用不着大部头。要是你也这么认为，请睁开眼来看看别的C语言教程，看有哪一本书像K&#038;R这么薄，而且写得又那么好。要不然，再看看JavaScript，JavaScript也是一门小型语言，但还没有哪本书是篇幅又短，又容易理解的。</p>
<p>我想说明一下，前面提到的那几本书都是着意挑选出来的，因为这几本书在我看来都是相应语言领域的最佳教程。Odersky等写的Scala、Thomas写的Ruby，还有Lutz那本Python，这些都是学习相应语言的最佳起点。我只是希望这些书要是能更像K&#038;R那样就好了。</p>
<p>——Andrew Binstock<br />
《Dr. Dobb&#8217;s》主编</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/06/05/lax-language-tutorials-2450.html/feed</wfw:commentRss>
		<slash:comments>44</slash:comments>
		</item>
		<item>
		<title>犀牛书作者David Flanagan谈盗版</title>
		<link>http://www.cn-cuckoo.com/2011/05/04/david-flanagan-on-piracy-2429.html</link>
		<comments>http://www.cn-cuckoo.com/2011/05/04/david-flanagan-on-piracy-2429.html#comments</comments>
		<pubDate>Wed, 04 May 2011 10:41:20 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[出版]]></category>
		<category><![CDATA[好书]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2429</guid>
		<description><![CDATA[原文链接：JavaScript: The Definitive Guide Sixth Edition pdf download ebook 每次，只要我的新书一出来，我准会因为盗版生一肚子气。为这事，我都在Twitter上发过消息了，但在Google搜索框里只有写长一点你才会发现微妙的差异。这篇文章题目是什么意思？就是Google对搜索我的书的人给出的建议。 要是有足够多的人把链接指向我这篇文章，没准搜索建议会把那些找盗版书的人都引到我这个页面，而不是盗版电子书网站 。[更新：太好了，到今天晚上为止，选择上面截图中的任何一条搜索建议，我的这篇文章都会排在那些电子书下载站点前面！庆祝一下这个象征性的胜利！] 好，下面我就想到哪说到哪，不过可不止140个字符啊，谈谈我对盗版图书的看法。 我认真看过Tim O&#8217;Reilly谈盗版的两篇文章：Tim O&#8217;Reilly on Piracy, Tinkering, and the Future of the Book和Piracy is Progressive Taxation, and Other Thoughts on the Evolution of Online Distribution。我也同意其中的一些观点。比如，默默无闻比盗版更糟糕。我知道有些作者一方面让读者免费（也是合法地）下载自己的书，一方面还能取得不错的销售业绩。我知道有些世俗小说作家搞自出版，一本书只卖99美分，同样取得了成功。（但我对那个世界知之甚少，没办法链接到其中任何一位作者。）然而，对大多数上述作者来说，“成功”的含义是“我的书卖99美分比卖3.99美元挣得还要多”。靠卖99美分一本书来养家糊口的幸运儿只是凤毛麟角。我不认为自出版定价99美分就是技术书的未来。 15年来，我完全依靠图书版税收入来维持自己和家庭的开支，也算是少数幸运作者之一了。但自从.COM泡沫破裂以后，随着出版业日益衰退，我的版税收入差不多也在稳步下降。我已经决定去找一份工作，去挣工资了。对我来说，这标志一个时代结束了。（听起来像是抱怨吗？别忘了这对我意味着什么。要是在自己的博客上都不能抱怨了，我还能到哪里去抱怨？:-)） 我不知道我的收入减少到底是不是因为盗版，或者说多大程度上因为盗版。我怀疑互联网以及从纸质书向电子书的过渡除了做到像盗版那样还能有什么可为的。但我也同样怀疑盗版的影响再大能大到哪里去。 不过，抛开无法统计的财务影响不谈，我想，我还是可以告诉大家，对我的书的盗版已经让我苦恼至极。2008年，我的Ruby书出版后一周左右，盗版就可以随便下载了，那时我就感到很悲哀。今年年初，我的jQuery参考手册上市，令我震惊的是Google居然把下载站点链接放得比这本书的评论链接还靠前。现在，JavaScript: The Definitive Guide出来了，我连样书都还没收到呢，违法的电子版就已经谁想下都能下了。而且，Google还向那些搜索这本书的人推荐那些违法的下载链接（见上面的屏幕截图）。为了写这本书，我花了不知道有多少心血，我想说，这种感觉不啻掏走了我的心肝一样。 我在Twitter上也试着挑衅过，我的那条微博写道：“难道Google支持盗版？”但我确实认为这是一个实实在在的问题。如果Google索引ebookee之类的直接包含下载链接的站点，为人们寻找盗版内容提供便利，甚至还建议人们去搜索下载链接，那么我认为就足以说明Google在鼓励盗版。而这里边最最关键的是，盗版内容那么轻易就能到手，人们就是想“做贼心虚”，恐怕都找不到理由了。Google会给恶意软件站点打上“这个站点可能伤害你的计算机”的标签，默认会把色情图书过滤掉。但对违法的电子书采取什么措施了？这些下载链接就堂而皇之地明摆在那——还不就是告诉人们，下载没错。 我知道盗版电子书无法消灭。而且，我不认为我们应该（或能够）通过严格DRM（Digital Rights Management，数字版权管理）来锁住一切。但我也认为对盗版放任自流的态度是错误的。即使出版商无法战胜盗版，他们至少应该能够据理相持，而不是甘认失败。 为此，我给出几个可能有用的小建议。 Google可以过滤自己的搜索建议项，不要积极地推荐盗版。我怀疑在有人输入某个艳星的名字时，Google会不会过滤掉建议的关键词？Google已经有了一个受版权保护图书的数据库了（Google Books），因此在有人搜索一本书时，过滤掉这些建议项应该很简单。 Google可以给那些可能链接到盗版内容的链接加上标签（不用过滤）。Google已经在给某些搜索结果加“this site may harm your [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: right;">原文链接：<a href="http://www.davidflanagan.com/2011/04/javascript-the-1.html">JavaScript: The Definitive Guide Sixth Edition pdf download ebook</a></p>
<p>每次，只要我的新书一出来，我准会因为盗版生一肚子气。为这事，我都在Twitter上发过消息了，但在Google搜索框里只有写长一点你才会发现微妙的差异。这篇文章题目是什么意思？就是Google对搜索我的书的人给出的建议。</p>
<p><img class="aligncenter colorbox-2429" title="googlesuggest" src="http://www.davidflanagan.com/images/googlesuggest.png" alt="" width="600" height="156" /></p>
<p>要是有足够多的人把链接指向我这篇文章，没准搜索建议会把那些找盗版书的人都引到我这个页面，而不是盗版电子书网站 <img src='http://www.cn-cuckoo.com/main/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley colorbox-2429' /> 。[更新：太好了，到今天晚上为止，选择上面截图中的任何一条搜索建议，我的这篇文章都会排在那些电子书下载站点前面！庆祝一下这个象征性的胜利！]</p>
<p>好，下面我就想到哪说到哪，不过可不止140个字符啊，谈谈我对盗版图书的看法。<span id="more-2429"></span></p>
<p>我认真看过Tim O&#8217;Reilly谈盗版的两篇文章：Tim O&#8217;Reilly on Piracy, Tinkering, and the Future of the Book和Piracy is Progressive Taxation, and Other Thoughts on the Evolution of Online Distribution。我也同意其中的一些观点。比如，默默无闻比盗版更糟糕。我知道有些作者一方面让读者免费（也是合法地）下载自己的书，一方面还能取得不错的销售业绩。我知道有些世俗小说作家搞自出版，一本书只卖99美分，同样取得了成功。（但我对那个世界知之甚少，没办法链接到其中任何一位作者。）然而，对大多数上述作者来说，“成功”的含义是“我的书卖99美分比卖3.99美元挣得还要多”。靠卖99美分一本书来养家糊口的幸运儿只是凤毛麟角。我不认为自出版定价99美分就是技术书的未来。</p>
<p>15年来，我完全依靠图书版税收入来维持自己和家庭的开支，也算是少数幸运作者之一了。但自从.COM泡沫破裂以后，随着出版业日益衰退，我的版税收入差不多也在稳步下降。我已经决定去找一份工作，去挣工资了。对我来说，这标志一个时代结束了。（听起来像是抱怨吗？别忘了这对我意味着什么。要是在自己的博客上都不能抱怨了，我还能到哪里去抱怨？:-)）</p>
<p>我不知道我的收入减少到底是不是因为盗版，或者说多大程度上因为盗版。我怀疑互联网以及从纸质书向电子书的过渡除了做到像盗版那样还能有什么可为的。但我也同样怀疑盗版的影响再大能大到哪里去。</p>
<p>不过，抛开无法统计的财务影响不谈，我想，我还是可以告诉大家，对我的书的盗版已经让我苦恼至极。2008年，我的Ruby书出版后一周左右，盗版就可以随便下载了，那时我就感到很悲哀。今年年初，我的jQuery参考手册上市，令我震惊的是Google居然把下载站点链接放得比这本书的评论链接还靠前。现在，JavaScript: The Definitive Guide出来了，我连样书都还没收到呢，违法的电子版就已经谁想下都能下了。而且，Google还向那些搜索这本书的人推荐那些违法的下载链接（见上面的屏幕截图）。为了写这本书，我花了不知道有多少心血，我想说，这种感觉不啻掏走了我的心肝一样。</p>
<p>我在Twitter上也试着挑衅过，我的那条微博写道：“难道Google支持盗版？”但我确实认为这是一个实实在在的问题。如果Google索引ebookee之类的直接包含下载链接的站点，为人们寻找盗版内容提供便利，甚至还建议人们去搜索下载链接，那么我认为就足以说明Google在鼓励盗版。而这里边最最关键的是，盗版内容那么轻易就能到手，人们就是想“做贼心虚”，恐怕都找不到理由了。Google会给恶意软件站点打上“这个站点可能伤害你的计算机”的标签，默认会把色情图书过滤掉。但对违法的电子书采取什么措施了？这些下载链接就堂而皇之地明摆在那——还不就是告诉人们，下载没错。</p>
<p>我知道盗版电子书无法消灭。而且，我不认为我们应该（或能够）通过严格DRM（Digital Rights Management，数字版权管理）来锁住一切。但我也认为对盗版放任自流的态度是错误的。即使出版商无法战胜盗版，他们至少应该能够据理相持，而不是甘认失败。</p>
<p>为此，我给出几个可能有用的小建议。</p>
<ul>
<li>Google可以过滤自己的搜索建议项，不要积极地推荐盗版。我怀疑在有人输入某个艳星的名字时，Google会不会过滤掉建议的关键词？Google已经有了一个受版权保护图书的数据库了（Google Books），因此在有人搜索一本书时，过滤掉这些建议项应该很简单。</li>
<li>Google可以给那些可能链接到盗版内容的链接加上标签（不用过滤）。Google已经在给某些搜索结果加“this site may harm your computer”（这个站点可能伤害你的计算机）之类的标签了，为什么不能给盗版站点加上这样的标签：“Downloading content from this site may result in legal action by the copyright holder”（从这个站点下载内容可能招致版权所有人的法律诉讼）？或者更友好简洁一些：“this site may harm your karma.”（这个站点可能会给你招来报应）。</li>
</ul>
<p>最后，就引用我新书前言里的一个附注“A Note about Piracy”（关于盗版的说明）作为结尾吧：</p>
<div style="border:1px dashed #E6DB55; background:#ffffe0;margin:2em;padding:1em;">
如果你正在阅读本书的电子版，而你（或你的老板）并没有付钱（或者也不是从花钱买它的人那里借来的），那么你看的可能就是盗版。写本书第6版是我的专职工作，花了一年多时间。付出这么多时间得到回报的唯一途径，就是读者能够花钱买这本书。而保证我能继续写本书第7版的唯一途径，就是我可以从现在这第6版中拿回报酬。</p>
<p>我不会原谅盗版行径，但假如你看的真是盗版，继续再看几章也没问题。我想，你会发现这本书对于学习JavaScript一定很有价值，与那些在网上随处可见的免费（甚至不合法的）内容相比，这本书组织得更好，质量更高。如果你同意这是一本有价值的书，那就请去买一本正版来看（纸版或者电子版都行）。话说回来，如果你认为这本书与网上那些免费信息也差不了多少，那麻烦你把盗版扔掉，去看那些免费的信息。
</p></div>
<p>更新：感谢大家诚挚的鼓励和有见地的留言！今天晚上，我已经回复了你们大多数留言。但我还得认真去准备我参加JSConf的演讲，所以未来两天恐怕不能再给大家回复了。</p>
<p>更新：又多了很多高水平的留言！我真希望这个博客能有一个按线索串起留言的系统。以前这不是问题。</p>
<p>（完；以下——在翻译本文时——是109条留言）</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/05/04/david-flanagan-on-piracy-2429.html/feed</wfw:commentRss>
		<slash:comments>35</slash:comments>
		</item>
		<item>
		<title>华山论剑：世界顶尖程序员论语言及测试</title>
		<link>http://www.cn-cuckoo.com/2011/04/28/got-any-quotes-from-coders-at-work-2416.html</link>
		<comments>http://www.cn-cuckoo.com/2011/04/28/got-any-quotes-from-coders-at-work-2416.html#comments</comments>
		<pubDate>Thu, 28 Apr 2011 01:01:06 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[好书]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2416</guid>
		<description><![CDATA[原文地址：Got Any Quotes from Coders At Work 最近，我看完了Peter Seibel的《编程人生》。哈，这是一本世界顶尖程序员和计算机科学家的访谈。看看都有谁，这些牛人在Wiki上都有自己的条目：Jamie Zawinski、Brad Fitzpatrick、Douglas Crockford、Brendan Eich、Josh Bloch、Joe Armstrong、Simon Peyton-Jones、Peter Norvig、Guy Steele、Dan Ingalls、Peter Deutsch、Ken Thompson、Fran Allen、Bernie Cosell和Don Knuth。 这本书固然非常棒，我非常喜欢，不过囿于访谈这种体裁，比较被采访人关于相同话题的观点也确实有点麻烦。但不管怎么说，作者Peter Seibel还是忠实地记录了他们的言论，所以我就想自己从这些智慧箴言中再提炼出一些真正有用的观点来。 经过一番努力，我按照自己的兴趣（静态类型和不变量）分别挑选出了一些重要的话。我这种分法未必合理，供大家参考吧。 大牛们谈“静态类型” Brad Fitzpatrick：“我也希望能够在编译时得到一些警示，希望它能提醒我‘你看看，你这都干了些什么呀’之类的。而有时候呢，我又觉得无所谓，希望在运行时再被曝光问题或者什么的。” Doug Crockford：“可是你在经典继承当中做不到这一点——你只能一味地按照抽象到实例的思维方式去想。在这个思想框架中，很难设计出合理的层次关系。等后来你真的理解了问题所在之后，你就不得不再回过头来对它进行重构。这时候再重构对代码的影响可就不是一星半点了，如果在你幡然醒悟的时候，原来的代码已经变得非常庞大了，你怎么办？” Doug Crockford：“在JavaScript中，我发现重构真是很简单的一件事。可是如果要对一个层层递进的类层次进行重构，那可就要多难有多难了。” Brendan Eich：“那些疯疯颠颠、几近白痴的话不能信，说什么动态语言终有一天会完全把Java还有静态语言取而代之，这不是混话吗？” Josh Bloch：“OO很有意思。可以从两方面看，首先就是模块化。模块化很了不起啊。不过，我倒不觉得这是OO的人的专利。……其次就是继承，而我对继承的看法跟现在很多人的看法一样，那就是继承有利也有弊。” Josh Bloch：“这个例子就说明，必须要有安全的语言。这个问题（栈溢出）本来就不是人应该考虑的事。” Josh Bloch：“我还是喜欢泛型。泛型可以帮我找出代码中的bug，可以让我把通常得写在注释里面的约定拿出来写在代码里面，然后通过编译器来保证它们得到强制遵守。” Joe Armstrong：“然后支持静态类型的人就说了，‘好，在封送数据结构的时候我们的的确确能感受到动态类型的好处。’如果你随便在网上发一段程序，如果你不知道数据类型，就没办法重建原来的数据。” Joe Armatrong：“我们缺少两类东西之间的一个协议：你发给我一个那种东西，我再发给一个这种东西，怎么办？数据包以及它们的类型有多种方式可以描述，但描述协议的方式却非常有限。” Simon Peyton-Jones：“其中一个不常提及的例子就是维护。当你面对一堆3年前写的不那么完美的代码，又想对它进行系统性地改进，怎么办？注意是系统性、全局性的改进，不是单单修改哪个例程。在这种情况下，类型系统的作用一下就显现出来了。” Simon Peyton-Jones：“只要静态类型合适，你就尽管放心地用，光从维护角度看，你就值了。” Dan Ingalls：“类型就相当于程序中的断言。我认为尽量保持事情简单很有价值，包括连类型都不必提。” Ken Thompson：“有bug就有bug呗。谁写代码都会有bug，那都是人的问题。如果说它是一种运行时安全的语言，那么遇到bug时，操作系统应该崩溃，用不着什么缓冲区溢出，也就不会被利用了。” 大牛们谈“不变量和断言” [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: right;">原文地址：<a title="got-any-quotes-from-coders-at-work" href="http://whiley.org/2011/04/25/got-any-quotes-from-coders-at-work/" target="_blank">Got Any Quotes from Coders At Work</a></p>
<p><a href="http://product.china-pub.com/197294"><img class="colorbox-2416"  style="float:left;margin:0 1em 1em 0;width:200px;" src="http://img3.douban.com/lpic/s4549954.jpg" alt="编程人生" /></a>
<p>最近，我看完了Peter Seibel的《编程人生》。哈，这是一本世界顶尖程序员和计算机科学家的访谈。看看都有谁，这些牛人在Wiki上都有自己的条目：Jamie Zawinski、Brad Fitzpatrick、Douglas Crockford、Brendan Eich、Josh Bloch、Joe Armstrong、Simon Peyton-Jones、Peter Norvig、Guy Steele、Dan Ingalls、Peter Deutsch、Ken Thompson、Fran Allen、Bernie Cosell和Don Knuth。</p>
<p>这本书固然非常棒，我非常喜欢，不过囿于访谈这种体裁，比较被采访人关于相同话题的观点也确实有点麻烦。但不管怎么说，作者Peter Seibel还是忠实地记录了他们的言论，所以我就想自己从这些智慧箴言中再提炼出一些真正有用的观点来。</p>
<p>经过一番努力，我按照自己的兴趣（静态类型和不变量）分别挑选出了一些重要的话。我这种分法未必合理，供大家参考吧。</p>
<p><span id="more-2416"></span></p>
<h2>大牛们谈“静态类型”</h2>
<div style="margin:0 3em;background-color:#FFFBCC;border:1px solid #e6db55;padding:2em;line-height:1.6;">
<strong>Brad Fitzpatrick</strong>：“我也希望能够在编译时得到一些警示，希望它能提醒我‘你看看，你这都干了些什么呀’之类的。而有时候呢，我又觉得无所谓，希望在运行时再被曝光问题或者什么的。”</p>
<p><strong>Doug Crockford</strong>：“可是你在经典继承当中做不到这一点——你只能一味地按照抽象到实例的思维方式去想。在这个思想框架中，很难设计出合理的层次关系。等后来你真的理解了问题所在之后，你就不得不再回过头来对它进行重构。这时候再重构对代码的影响可就不是一星半点了，如果在你幡然醒悟的时候，原来的代码已经变得非常庞大了，你怎么办？”</p>
<p><strong>Doug Crockford</strong>：“在JavaScript中，我发现重构真是很简单的一件事。可是如果要对一个层层递进的类层次进行重构，那可就要多难有多难了。”</p>
<p><strong>Brendan Eich</strong>：“那些疯疯颠颠、几近白痴的话不能信，说什么动态语言终有一天会完全把Java还有静态语言取而代之，这不是混话吗？”</p>
<p><strong>Josh Bloch</strong>：“OO很有意思。可以从两方面看，首先就是模块化。模块化很了不起啊。不过，我倒不觉得这是OO的人的专利。……其次就是继承，而我对继承的看法跟现在很多人的看法一样，那就是继承有利也有弊。”</p>
<p><strong>Josh Bloch</strong>：“这个例子就说明，必须要有安全的语言。这个问题（栈溢出）本来就不是人应该考虑的事。”</p>
<p><strong>Josh Bloch</strong>：“我还是喜欢泛型。泛型可以帮我找出代码中的bug，可以让我把通常得写在注释里面的约定拿出来写在代码里面，然后通过编译器来保证它们得到强制遵守。”</p>
<p><strong>Joe Armstrong</strong>：“然后支持静态类型的人就说了，‘好，在封送数据结构的时候我们的的确确能感受到动态类型的好处。’如果你随便在网上发一段程序，如果你不知道数据类型，就没办法重建原来的数据。”</p>
<p><strong>Joe Armatrong</strong>：“我们缺少两类东西之间的一个协议：你发给我一个那种东西，我再发给一个这种东西，怎么办？数据包以及它们的类型有多种方式可以描述，但描述协议的方式却非常有限。”</p>
<p><strong>Simon Peyton-Jones</strong>：“其中一个不常提及的例子就是维护。当你面对一堆3年前写的不那么完美的代码，又想对它进行系统性地改进，怎么办？注意是系统性、全局性的改进，不是单单修改哪个例程。在这种情况下，类型系统的作用一下就显现出来了。”</p>
<p><strong>Simon Peyton-Jones</strong>：“只要静态类型合适，你就尽管放心地用，光从维护角度看，你就值了。”</p>
<p><strong>Dan Ingalls</strong>：“类型就相当于程序中的断言。我认为尽量保持事情简单很有价值，包括连类型都不必提。”</p>
<p><strong>Ken Thompson</strong>：“有bug就有bug呗。谁写代码都会有bug，那都是人的问题。如果说它是一种运行时安全的语言，那么遇到bug时，操作系统应该崩溃，用不着什么缓冲区溢出，也就不会被利用了。”
</div>
<h2>大牛们谈“不变量和断言”</h2>
<div style="margin:0 3em;background-color:#FFFBCC;border:1px solid #e6db55;padding:2em;line-height:1.6;">
<strong>Jamie Zawinski</strong>：“显而易见，放一条断言语句进去对调试而言肯定有用，而且就像你说的，对写文档也有用。”</p>
<p><strong>Brad Fitzpatrick</strong>：“我主要会在开始的时候考虑很多条件，然后在构造函数中和函数的开头再一一检查。”</p>
<p><strong>Brendan Eich</strong>：“那些写得不好的断言就不提了，反正在Mozilla，随着时间推移，好的断言越来越多。由此，我们觉得也受到了一些启发，明白了什么是不变量，而这些恐怕只有在理想的类型系统中才能表达。”</p>
<p><strong>Doug Crockford</strong>：“说简单点，软件其实就是一套关于软件该怎么工作的规范。任何不完整的规范，都不能告诉你软件最终会怎么实现它的功能。”</p>
<p><strong>Doug Crockford</strong>：“我觉得Eiffel确实更有意思一些，我喜欢的是它的precondition/postcondition契约。我真希望自己在用的无论哪种语言能支持这个特性，遗憾的是，这个特性跟很多其他想法一样，都没有流行起来。”</p>
<p><strong>Josh Bloch</strong>：“你应该知道，断言是我在Java Programming Language中第一批加入的特性，而且我也深知，这些特性永远不进入主流文化。”</p>
<p><strong>Josh Bloch</strong>：“我说过，我使用断言是为了确保编译后的不变量是可以维护的。如果不变量出了问题，我觉得应该知道是什么时候出的问题。”</p>
<p><strong>Simon Peyton-Jones</strong>：“你可以给一个函数写一个类似这样的一样契约：‘你给我一个大于零的参数，我再给你一个小于零的结果。’”</p>
<p><strong>Simon Peyton-Jones</strong>：“假设你宣称你的目标是让一切都能通过机器检查来验证其正确性。但这句话的意思仍然还是不够明确。机器验证可以，但根据什么来验证呢？”</p>
<p><strong>Simon Peyton-Jones</strong>：“我想在真正的开发中，最好还是把那些你希望程序有的属性都写下来。比如说，‘这个阀门不能跟那个阀门一起关。这棵树应该始终保持匀称地生成。这个函数任何时候都得返回一个大于零的结果。’这些全都是规格说明书中的一小部分，构不成一个完整的规格说明书。它们只是你希望的东西。”</p>
<p><strong>Peter Norvig</strong>：“跟循环不变量一样，我始终认为它带来的问题比好处多。”</p>
<p><strong>Guy Steele</strong>：“我对应该记录什么有了更深入的理解，我觉得更多地应该是数据结构，我觉得应该更多地应该是它们的不变量。”</p>
<p><strong>Guy Steele</strong>：“举个例子吧，这儿有一个数组和一个整数，而这个整数应该是数组中的一个有效索引。这个关系在Java中就不容易表达。”</p>
<p><strong>Dan Ingalls</strong>：“假如在程序中什么危险的事儿都允许做，那么当你坐下来进行形式验证的时候，麻烦就都来了。你想啊，每一步你都得这么考虑，‘嗯，这个有可能发生，那个有可能发生，那个也有可能发生。’”</p>
<p><strong>Peter Deutsch</strong>：“我的看法还是那样，如果你把数据结构和它们的不变量弄好了，大多数代码你就自然而然知道该怎么写了。”</p>
<p><strong>Peter Deutsch</strong>：“现在想一想，要想让软件去做我们想让它做的事，不能依赖断言，或者说归纳断言，而要依靠更好、更强大、更深层次的声明性语法。”</p>
<p><strong>Peter Deutsch</strong>：“在我看来，把定理验证技术当作改进软件可靠性的实用技术来用，已经基本宣告失败，而这就是原因。把想要证明的那些属性都逐个地规范起来，简直是不可能的事儿。”</p>
<p><strong>Don Knuth</strong>：“有人可能会说自己的程序经过验证了，而且之所以能通过验证，是因为根据某些验证器的验证，只有该程序达到了相应规范的要求。可是，验证器就没有bug吗，规范本身也难免会有bug。”
</div>
<h2>结论</h2>
<p>这些言论恐怕都让你眼花缭乱了吧……我想，你此刻的问题一定是：你相信谁说的？（不告诉你。）这本书里还有很多有意思的话题，等着你、你，还有你去开采呢。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/04/28/got-any-quotes-from-coders-at-work-2416.html/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>我的创业故事：从灵光一现到事业有成</title>
		<link>http://www.cn-cuckoo.com/2011/04/23/a-startup-story-2409.html</link>
		<comments>http://www.cn-cuckoo.com/2011/04/23/a-startup-story-2409.html#comments</comments>
		<pubDate>Sat, 23 Apr 2011 03:22:50 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[创业]]></category>
		<category><![CDATA[编程技术]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2409</guid>
		<description><![CDATA[原文地址：My startup story: from big idea to thriving business in 8 short years 2003年夏天，我还在打理自己第一个小公司的时候，突然想到一个“好主意”：社交新闻阅读器。有点类似后来的Google阅读器加智能收件箱（Priority Inbox）和社会化推荐。我没日没夜地想着这件事，觉也睡不着了。每天人虽然躺在床上，脑子里一直在苦思冥想怎么把这个东西做出来。我可能是得了“痴心妄想症”了。“这个阅读器一定会大受欢迎！”，我想。这个想法太好了，要是你的话，恐怕你早就拿着它去招徕风险投资了。可我在温莎（Windsor），加拿大呀，硅谷对我来说太远了，再说我那时候还没听说过VC啊投资啊什么的。我只能靠自己，什么事都从头来。 2003年还没有Google阅读器，Fackbook还在娘胎里，RSS新闻源也少得可怜。找不着RSS源？不要紧，我自己来，我可以自己写一个程序，一个网站一个网站地分析，自动采集新闻或者新内容。没有Faccbook提供社交用户资料？这还真是个问题。没有这些用户，还做什么社交新闻阅读器呢。对，没有用户不行，不仅如此，用户太少也不行。看来我这个“好主意”一时半会是不太可能有结果了，为了吸引用户，我决定先做个简单的东西，免费供人们下载。我对计算机通话还有些经验，开发个小桌面应用，显示来电者的ID对我来说不过举手之劳。两个月后，PhoneTray Free呱呱坠地。 2003年我可真是熬过来的。我的第一家创业公司本来还小有成就，但很快就下滑到了破产的边缘。由于我签证上的身份，我也不能给别人做任何咨询。照直说吧，这一年我没挣多少钱，我差一点就把自己的公司扔掉，然后去找一份全职工作。幸好我妻子还有工作，我们也还有点存款，合计了一下，我们决心一块挺过去，我还接着做自己想做的事。 一方面是继续设法实现我的那个“好主意”，另一方面就是我第一家公司的一些琐事。我的PhoneTray Free也有人赏脸，肯下载了。后来，我就陆续收到PhoneTray用户的一些反馈邮件，看得出来，他们都很喜欢我这个小应用。“嘿，我们单位的头儿老给我打骚扰电话”，一封邮件里这么说，“你的程序能帮我把他屏蔽掉吗？”我想“这有什么难的？”于是就在程序里加了屏蔽特定号码的功能。没想到所有人都喜欢这个功能。PhoneTray Free一下子火了。到2004年年底那会儿，每天的下载量达到了几百次，反馈邮件也越来越多。 “我喜欢你的程序，”有一封邮件说，“可我们怎么办，我们是拔号上网用户？我们上网的时候有可能错过重要的电话！”“嗯，这是真的吗？”我想，“还有人拔号上网吗？”我用Google一搜，结果显示美国当时的互联网用户确实还有65%通过拔号的方式上网。等等，呼叫等待（modem-on-hold）和V.92标准不就是解决这个问题的吗？很明显，不是，因为我很快就找到了答案。V.92标准只是规定了如何在硬件上实现来电检测和呼叫等待，并没有对软件或者API作出规定。Windows操作系统也没有内置对呼叫等待的支持。虽然有几家调制解调器制造商也提供了支持呼叫等待的软件，但那些软件都只能在特定的调制解调器上使用。大多数调制解调器还是没有随机附送的呼叫等待软件。可不可以在PhoneTray中增加这个功能，让所有拔号用户都能在上网的时候接听电话？ 噢，这件事可不容易。要实现呼叫等待功能，没有任何标准可以参照。现有的几款软件都是使用内部API直接调用“猫”的驱动程序，当然也没有文档可查。而且不同调制解调器芯片提供商又各自有各自的API。更有甚者，某些提供商不愿自找麻烦，干脆连API都没有。这对我而言，不啻为一个挑战，但是谁不喜欢挑战呢？于是，我翻出了以前学过的讲x86汇编程序的旧书，打开自己一直不离不弃的IDA，开始从头研究调制解调器驱动程序的工作原理。我反汇编了几个驱动程序，弄明白了开发驱动程序的步骤，也知道了自己下一步该怎么做。下一步，我要自己开发一个核心驱动程序，以调制解调器的驱动程序为依托，来监控调制解调器驱动程序的行为。这样，PhoneTray就可以与我自己的驱动程序通信，进而控制调制解调器。 我说过我喜欢挑战，是吗？要是你曾经给哪个调制解调器开发过内核驱动程序，你就能体会到我要为自己这个爱好付出多大代价了。远程内核调试器、BSOD/重启、核心内存转储……，这些事儿忙得我是不亦乐乎，而我的那个“好主意”呢，早被我给抛到爪哇国里去了——至少暂时没时间想它了。为了让我的驱动程序兼容所有调制解调器，我花了5个月时间。但不管怎么说，2004年5月，PhoneTray Dialup的第一个版本终于整装待发了。这可是一个能真正解决人们问题的产品，我打算通过它收点钱。一开始，卖得并不好，而且PhoneTray Dialup本身还有一些bug，但到了2.10版，这个产品就已经非常完善了，销量也随之直线上升。 2004年底的时候，PhoneTray Dialup达到了每月几千的销量，而且还在增长。而我呢，也成了加拿大的永久居民，可以通过开展一些咨询业务挣钱了。我感觉到自己的前途真是一片光明！我接着思考自己那个“好主意”，给别人提供一些咨询，时不时地还升级一下PhoneTray Free和PhoneTray Dialup。就这样，突然有一天，一个小ISP所有人给我发了一封邮件，说是希望为他们的用户提供PhoneTray Dialup。“就是啊！为什么我就没有想到呢？”我心里暗自思忖，“这可是一个全新的市场啊！”很快，我就专门针对ISP定制开发了一个新版本，让他们可以把它当作自己的软件来提供给用户。同时，我也拉来了一个人，帮我一起推销这个新版本。两年后，这个新版本已经授权给了几十家ISP，其中最大一家是沙特阿拉伯的，有30万用户。 我们的生意越做越好，而我要处理的事也越来越多。为此，我妻子辞掉了自己的工作，加入Traysoft来帮我。我的那个好主意呢，我又忘了。眼瞅着拔号上网的经营模式渐渐日薄西山，我还得赶紧想点别的办法好继续赚钱。这些年来，我收到过不少公司发来的邮件，想请我帮他们开发PhoneTray Free的定制版。我没有打算那么做，我想让开发人员能够自己根据需求去自己开发。我把PhoneTray的核心电话功能拿出来，移植到C#上面，又添加了一些必要的东西，最后发布了一个基于.NET的电话功能库（AddTapi.NET）。这个新产品很成功，它的收入占到了我们公司收入的一半以上。PhoneTray呢，也越来越有声色，用不了多久，我们先进的电话管理软件PhoneTray Pro也要问世了。 这就是我8年以来的创业故事，现在我的小公司生机勃勃，养活我和我的家人已经没有问题了。而这个公司最早只不过是一个免费的小应用而已。什么，我的那个“好主意”怎么办？也许有一天我会实现那个梦想的，也许。]]></description>
			<content:encoded><![CDATA[<p style="text-align: right;">原文地址：<a href="http://blog.traysoft.com/2011/04/my_startup_story/">My startup story: from big idea to thriving business in 8 short years</a></p>
<p>2003年夏天，我还在打理自己第一个小公司的时候，突然想到一个“好主意”：社交新闻阅读器。有点类似后来的Google阅读器加智能收件箱（Priority Inbox）和社会化推荐。我没日没夜地想着这件事，觉也睡不着了。每天人虽然躺在床上，脑子里一直在苦思冥想怎么把这个东西做出来。我可能是得了“痴心妄想症”了。“这个阅读器一定会大受欢迎！”，我想。这个想法太好了，要是你的话，恐怕你早就拿着它去招徕风险投资了。可我在温莎（Windsor），加拿大呀，硅谷对我来说太远了，再说我那时候还没听说过VC啊投资啊什么的。我只能靠自己，什么事都从头来。</p>
<p>2003年还没有Google阅读器，Fackbook还在娘胎里，RSS新闻源也少得可怜。找不着RSS源？不要紧，我自己来，我可以自己写一个程序，一个网站一个网站地分析，自动采集新闻或者新内容。没有Faccbook提供社交用户资料？这还真是个问题。没有这些用户，还做什么社交新闻阅读器呢。对，没有用户不行，不仅如此，用户太少也不行。看来我这个“好主意”一时半会是不太可能有结果了，为了吸引用户，我决定先做个简单的东西，免费供人们下载。我对计算机通话还有些经验，开发个小桌面应用，显示来电者的ID对我来说不过举手之劳。两个月后，PhoneTray Free呱呱坠地。</p>
<p>2003年我可真是熬过来的。我的第一家创业公司本来还小有成就，但很快就下滑到了破产的边缘。由于我签证上的身份，我也不能给别人做任何咨询。照直说吧，这一年我没挣多少钱，我差一点就把自己的公司扔掉，然后去找一份全职工作。幸好我妻子还有工作，我们也还有点存款，合计了一下，我们决心一块挺过去，我还接着做自己想做的事。<span id="more-2409"></span></p>
<p>一方面是继续设法实现我的那个“好主意”，另一方面就是我第一家公司的一些琐事。我的PhoneTray Free也有人赏脸，肯下载了。后来，我就陆续收到PhoneTray用户的一些反馈邮件，看得出来，他们都很喜欢我这个小应用。“嘿，我们单位的头儿老给我打骚扰电话”，一封邮件里这么说，“你的程序能帮我把他屏蔽掉吗？”我想“这有什么难的？”于是就在程序里加了屏蔽特定号码的功能。没想到所有人都喜欢这个功能。PhoneTray Free一下子火了。到2004年年底那会儿，每天的下载量达到了几百次，反馈邮件也越来越多。</p>
<p>“我喜欢你的程序，”有一封邮件说，“可我们怎么办，我们是拔号上网用户？我们上网的时候有可能错过重要的电话！”“嗯，这是真的吗？”我想，“还有人拔号上网吗？”我用Google一搜，结果显示美国当时的互联网用户确实还有65%通过拔号的方式上网。等等，呼叫等待（modem-on-hold）和V.92标准不就是解决这个问题的吗？很明显，不是，因为我很快就找到了答案。V.92标准只是规定了如何在硬件上实现来电检测和呼叫等待，并没有对软件或者API作出规定。Windows操作系统也没有内置对呼叫等待的支持。虽然有几家调制解调器制造商也提供了支持呼叫等待的软件，但那些软件都只能在特定的调制解调器上使用。大多数调制解调器还是没有随机附送的呼叫等待软件。可不可以在PhoneTray中增加这个功能，让所有拔号用户都能在上网的时候接听电话？</p>
<p>噢，这件事可不容易。要实现呼叫等待功能，没有任何标准可以参照。现有的几款软件都是使用内部API直接调用“猫”的驱动程序，当然也没有文档可查。而且不同调制解调器芯片提供商又各自有各自的API。更有甚者，某些提供商不愿自找麻烦，干脆连API都没有。这对我而言，不啻为一个挑战，但是谁不喜欢挑战呢？于是，我翻出了以前学过的讲x86汇编程序的旧书，打开自己一直不离不弃的IDA，开始从头研究调制解调器驱动程序的工作原理。我反汇编了几个驱动程序，弄明白了开发驱动程序的步骤，也知道了自己下一步该怎么做。下一步，我要自己开发一个核心驱动程序，以调制解调器的驱动程序为依托，来监控调制解调器驱动程序的行为。这样，PhoneTray就可以与我自己的驱动程序通信，进而控制调制解调器。</p>
<p>我说过我喜欢挑战，是吗？要是你曾经给哪个调制解调器开发过内核驱动程序，你就能体会到我要为自己这个爱好付出多大代价了。远程内核调试器、BSOD/重启、核心内存转储……，这些事儿忙得我是不亦乐乎，而我的那个“好主意”呢，早被我给抛到爪哇国里去了——至少暂时没时间想它了。为了让我的驱动程序兼容所有调制解调器，我花了5个月时间。但不管怎么说，2004年5月，PhoneTray Dialup的第一个版本终于整装待发了。这可是一个能真正解决人们问题的产品，我打算通过它收点钱。一开始，卖得并不好，而且PhoneTray Dialup本身还有一些bug，但到了2.10版，这个产品就已经非常完善了，销量也随之直线上升。</p>
<p>2004年底的时候，PhoneTray Dialup达到了每月几千的销量，而且还在增长。而我呢，也成了加拿大的永久居民，可以通过开展一些咨询业务挣钱了。我感觉到自己的前途真是一片光明！我接着思考自己那个“好主意”，给别人提供一些咨询，时不时地还升级一下PhoneTray Free和PhoneTray Dialup。就这样，突然有一天，一个小ISP所有人给我发了一封邮件，说是希望为他们的用户提供PhoneTray Dialup。“就是啊！为什么我就没有想到呢？”我心里暗自思忖，“这可是一个全新的市场啊！”很快，我就专门针对ISP定制开发了一个新版本，让他们可以把它当作自己的软件来提供给用户。同时，我也拉来了一个人，帮我一起推销这个新版本。两年后，这个新版本已经授权给了几十家ISP，其中最大一家是沙特阿拉伯的，有30万用户。</p>
<p>我们的生意越做越好，而我要处理的事也越来越多。为此，我妻子辞掉了自己的工作，加入Traysoft来帮我。我的那个好主意呢，我又忘了。眼瞅着拔号上网的经营模式渐渐日薄西山，我还得赶紧想点别的办法好继续赚钱。这些年来，我收到过不少公司发来的邮件，想请我帮他们开发PhoneTray Free的定制版。我没有打算那么做，我想让开发人员能够自己根据需求去自己开发。我把PhoneTray的核心电话功能拿出来，移植到C#上面，又添加了一些必要的东西，最后发布了一个基于.NET的电话功能库（AddTapi.NET）。这个新产品很成功，它的收入占到了我们公司收入的一半以上。PhoneTray呢，也越来越有声色，用不了多久，我们先进的电话管理软件PhoneTray Pro也要问世了。</p>
<p>这就是我8年以来的创业故事，现在我的小公司生机勃勃，养活我和我的家人已经没有问题了。而这个公司最早只不过是一个免费的小应用而已。什么，我的那个“好主意”怎么办？也许有一天我会实现那个梦想的，也许。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/04/23/a-startup-story-2409.html/feed</wfw:commentRss>
		<slash:comments>63</slash:comments>
		</item>
		<item>
		<title>每一位想有所成就的程序员都必须知道的15件事</title>
		<link>http://www.cn-cuckoo.com/2011/04/19/how-to-advance-your-career-read-the-passionate-programmer-2391.html</link>
		<comments>http://www.cn-cuckoo.com/2011/04/19/how-to-advance-your-career-read-the-passionate-programmer-2391.html#comments</comments>
		<pubDate>Tue, 19 Apr 2011 00:28:34 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[好书]]></category>
		<category><![CDATA[翻译]]></category>
		<category><![CDATA[程序员]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[职业]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2391</guid>
		<description><![CDATA[原文地址：How to advance your career? Read the Passionate Programmer! 我刚看完Chad Fowler的Passionate Programmer（中文版《我编程，我快乐：程序员职业规划之道》），这本书讲的是如何在软件开发行业中取得非凡的成就。 以下是根据这本书总结的，作为程序员，要取得非凡成就需要记住的15件事。 1、走一条不一样的路 在有利于自己的市场中竞争，如果你满足于“泯然众人矣”，那恐怕就得跟那些低工资国家的程序员们同场竞技了。 2、了解自己的公司 以我在医院、咨询公司、物流企业以及大技术公司工作的经验来看，这一点所言不虚。 不同公司的运营模式差异极大。如果你理解企业的运营模式，那你就不一样了！在这家公司中（或者对客户而言），你是参与业务运营的资产，你的工作能直接产生效益！ 3、与最优秀的人为伍 很早以前，我喜欢打篮球，被分配到一个水平比较高的队里。一开始适应的确很困难，但环境的压力越大（重大比赛），我的长进也就越明显。 每个领域其实都一样：你周围人的水平（以及对你的期望）越高，你就会变得越优秀。 4、制造差异 每年学习一门新编程语言。为什么不呢？不断尝试新事物，你关注的技术种类越多，脚下的路就越宽广，你的职业生涯就会日新月异。不知道几年后Java的趋势如何？那就学习Clojure。学Ruby还是Python？这两种语言都可以试试啊。然后你才能知道哪种语言更适合某个特定的项目。看，掌握的语言多了，才能在需要的时候信手拈来吧。 5、畏惧，是最大的敌人 还是直接从书中摘一句吧：“在畏惧中做出的职业规划，很可能会让自己后半辈子就一直被‘圈禁’在小隔断里，永远不会有创造明天辉煌的时刻。没错，那样是安全，但有意思吗？” 6、要成为多面手 如果你掌握了所在领域的知识，那你只能是一名专业人士。用PHP编程？花点时间设置一台Apache服务器，让PHP和MySQL都跑起来。一直在用jQuery？试试Prototype。你懂了吧。 7、一个字：做 别指望别人过来教你该怎么做，出去，自己学着去做！ 8、找一位好老师 找一位好老师可以让你在学习技术的时候有的放矢。作者给我们讲述了别人是怎么指导他学习的（顺便说一句，作者在这本书里讲了很多个人经历的小故事，他居然从一位演奏家转行来做软件开发！）：“好好研究一下目录服务，熟悉一种UNIX变体，然后再掌握一门脚本语言。” 请记住这句禅宗谚语：“循路觅宗师，形影不相离，师知吾亦知，吾乃成宗师。” 9、主动教会别人 教会别人是一种最好的学习方式。写一篇博客能帮你搞清楚一个问题。为此，你必须先掌握很多材料，同时还要有条有理地讲给别人听（写作技能）。如书中所言：“要想知道自己是不是真的明白，你就讲给别人听听。” 10、实践，实践，再实践（训练） 只有进行大量实践（花大量的时间）才能掌握某种技术。看的很多，写的很少，遇到问题，改一改，又去读代码，……（这样下去是不行的）。 要特别警惕拖延症。其实，往往只要有了开头就好办了。 自我加压，效果会更好。我曾在一篇博客中提到帕金森定律：紧张的时限可以让你提高工作效率。为什么不把这个定律用到学习上呢，比如说在y时间内学会x？ 11、从小处入手 每天都取得一项小成果，每天都要坚持做（写在博客上？）。这样一来，你只能让自己比昨天更进步，而不能说自己比上星期进步了一点。 12、享受过程 关注当下，而不是目标，享受那些在追逐未来目标的途中可能无暇顾及的小胜利。人总要生活在当下。我享受编程的过程，就像享受编程的结果一样。 13、不要丧失危机感 越是成功，就越容易犯重大错误。永远不要忘了危机感，特别是要认识到你今天所知道的，到了明天可能就会一文不值。过去的荣耀不能保你永远无虞。 据书中所说，你最好是要让自己能够“通用”，而不要对哪种技术或哪个公司产生依赖。你所掌握的某些技能，甚至你的工作，到了明天都可能会变得毫无价值。因此要不断提高/丰富/扩展自己的技能。 14、推销自己 为某个项目贡献自己的一份力量，写一篇博客，共享自己的源代码，成为对某个社区有用的人。 当然，做这些事可能需要激情，要看你的爱好，但这些事也会间接地推广你的工作成果，证明你的实力，提高你的知名度。 15、关注市场 书中还提到了“预警极客”，也就是那些始终引领技术发展的人。这些人说过的话往往带有预见性，他们提到事物也许过几天就会成为头条新闻。关注这些人，常看他们的Twitter和博客。]]></description>
			<content:encoded><![CDATA[<p style="text-align: right;">原文地址：<a href="http://bobbelderbos.com/2011/04/advance-career-read-passionate-programmer/">How to advance your career? Read the Passionate Programmer!</a></p>
<p><a href="http://bobbelderbos.com/2011/04/advance-career-read-passionate-programmer/"></a></p>
<p>我刚看完Chad Fowler的Passionate Programmer（中文版《我编程，我快乐：程序员职业规划之道》），这本书讲的是如何在软件开发行业中取得非凡的成就。<a href="http://product.china-pub.com/196966" title="我编程，我快乐：程序员职业规划之道"><img class="colorbox-2391"  style="border:2px solid #ddd;float:right;margin-top: 1em; margin-right: 0px; margin-bottom: 1em; margin-left: 1em;" title="我编程，我快乐：程序员职业规划之道" src="http://img10.360buyimg.com/n11/15855/fdd3bac6-9244-4079-bca5-b6c561838574.jpg" alt="我编程，我快乐：程序员职业规划之道" width="200"  /></a></p>
<p>以下是根据这本书总结的，作为程序员，要取得非凡成就需要记住的15件事。</p>
<p>1、走一条不一样的路<br />
在有利于自己的市场中竞争，如果你满足于“泯然众人矣”，那恐怕就得跟那些低工资国家的程序员们同场竞技了。</p>
<p>2、了解自己的公司<br />
以我在医院、咨询公司、物流企业以及大技术公司工作的经验来看，这一点所言不虚。</p>
<p>不同公司的运营模式差异极大。如果你理解企业的运营模式，那你就不一样了！在这家公司中（或者对客户而言），你是参与业务运营的资产，你的工作能直接产生效益！</p>
<p>3、与最优秀的人为伍<br />
很早以前，我喜欢打篮球，被分配到一个水平比较高的队里。一开始适应的确很困难，但环境的压力越大（重大比赛），我的长进也就越明显。</p>
<p>每个领域其实都一样：你周围人的水平（以及对你的期望）越高，你就会变得越优秀。</p>
<p>4、制造差异<br />
每年学习一门新编程语言。为什么不呢？不断尝试新事物，你关注的技术种类越多，脚下的路就越宽广，你的职业生涯就会日新月异。不知道几年后Java的趋势如何？那就学习Clojure。学Ruby还是Python？这两种语言都可以试试啊。然后你才能知道哪种语言更适合某个特定的项目。看，掌握的语言多了，才能在需要的时候信手拈来吧。</p>
<p>5、畏惧，是最大的敌人<br />
还是直接从书中摘一句吧：“在畏惧中做出的职业规划，很可能会让自己后半辈子就一直被‘圈禁’在小隔断里，永远不会有创造明天辉煌的时刻。没错，那样是安全，但有意思吗？”</p>
<p>6、要成为多面手<br />
如果你掌握了所在领域的知识，那你只能是一名专业人士。用PHP编程？花点时间设置一台Apache服务器，让PHP和MySQL都跑起来。一直在用jQuery？试试Prototype。你懂了吧。</p>
<p>7、一个字：做<br />
别指望别人过来教你该怎么做，出去，自己学着去做！<br />
<span id="more-2391"></span><br />
8、找一位好老师<br />
找一位好老师可以让你在学习技术的时候有的放矢。作者给我们讲述了别人是怎么指导他学习的（顺便说一句，作者在这本书里讲了很多个人经历的小故事，他居然从一位演奏家转行来做软件开发！）：“好好研究一下目录服务，熟悉一种UNIX变体，然后再掌握一门脚本语言。”</p>
<p>请记住这句禅宗谚语：“循路觅宗师，形影不相离，师知吾亦知，吾乃成宗师。”</p>
<p>9、主动教会别人<br />
教会别人是一种最好的学习方式。写一篇博客能帮你搞清楚一个问题。为此，你必须先掌握很多材料，同时还要有条有理地讲给别人听（写作技能）。如书中所言：“要想知道自己是不是真的明白，你就讲给别人听听。”</p>
<p>10、实践，实践，再实践（训练）<br />
只有进行大量实践（花大量的时间）才能掌握某种技术。看的很多，写的很少，遇到问题，改一改，又去读代码，……（这样下去是不行的）。</p>
<p>要特别警惕拖延症。其实，往往只要有了开头就好办了。</p>
<p>自我加压，效果会更好。我曾在一篇博客中提到帕金森定律：紧张的时限可以让你提高工作效率。为什么不把这个定律用到学习上呢，比如说在y时间内学会x？</p>
<p>11、从小处入手<br />
每天都取得一项小成果，每天都要坚持做（写在博客上？）。这样一来，你只能让自己比昨天更进步，而不能说自己比上星期进步了一点。</p>
<p>12、享受过程<br />
关注当下，而不是目标，享受那些在追逐未来目标的途中可能无暇顾及的小胜利。人总要生活在当下。我享受编程的过程，就像享受编程的结果一样。</p>
<p>13、不要丧失危机感<br />
越是成功，就越容易犯重大错误。永远不要忘了危机感，特别是要认识到你今天所知道的，到了明天可能就会一文不值。过去的荣耀不能保你永远无虞。</p>
<p>据书中所说，你最好是要让自己能够“通用”，而不要对哪种技术或哪个公司产生依赖。你所掌握的某些技能，甚至你的工作，到了明天都可能会变得毫无价值。因此要不断提高/丰富/扩展自己的技能。</p>
<p>14、推销自己<br />
为某个项目贡献自己的一份力量，写一篇博客，共享自己的源代码，成为对某个社区有用的人。</p>
<p>当然，做这些事可能需要激情，要看你的爱好，但这些事也会间接地推广你的工作成果，证明你的实力，提高你的知名度。</p>
<p>15、关注市场<br />
书中还提到了“预警极客”，也就是那些始终引领技术发展的人。这些人说过的话往往带有预见性，他们提到事物也许过几天就会成为头条新闻。关注这些人，常看他们的Twitter和博客。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/04/19/how-to-advance-your-career-read-the-passionate-programmer-2391.html/feed</wfw:commentRss>
		<slash:comments>34</slash:comments>
		</item>
		<item>
		<title>NetBeans之父Jaroslav Tulach谈软件框架设计</title>
		<link>http://www.cn-cuckoo.com/2011/03/07/interview-jaroslav-tulach-2367.html</link>
		<comments>http://www.cn-cuckoo.com/2011/03/07/interview-jaroslav-tulach-2367.html#comments</comments>
		<pubDate>Mon, 07 Mar 2011 06:27:16 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[出版]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2367</guid>
		<description><![CDATA[Interview: Jaroslav Tulach, Author of &#8220;Practical API Design&#8221; 2008-8-11 Jaroslav Tulach（见图），NetBeans之父、NetBeans API首席架构师，《软件框架设计的艺术》一书的作者。 此次访谈，Jaroslav Tulach会介绍他的这本书，并与大家分享关于设计API的一些独到见解。 你好，Jaroslav，你是不是先作个自我介绍啊？ 好，我懂。让我提到自己的是 NetBeans 之父，就是想吸引读者都来看一看这本书，对吧？ 。但是，如果一个人的名字让说英语的人完全看不懂，要想达到这个目的可不是那么简单的。我遇到这个问题可不止一次了，在设计这本书封面的时候就碰到了。想了解我的读者，下面就是我的一些背景资料。关于这本书，我想说：我在这本书里真的讲了很多有用的东西，而且我也尽了全力把枯燥的内容讲得更好玩一些。 亲爱的读者朋友， 也许你现在正在书店里，手里拿着这本书，问自己：“到底该不该买呢？”让我来告诉你：如果你写过很多代码，而且其他人要在你写的代码基础上编译他们的代码，那结论显而易见：“你早该想一想怎么设计API这个问题了，而本书就是你的得力助手。” 请注意，这可不是一本“5天掌握API设计”之类的书。而且你不可能“只用3天就能看完！”。假如你想找一本简单的参考手册，本书不属于那种类型。不过，要是你对深入了解API设计非常感兴趣，不仅仅满足于怎么设计，还想进一步搞清楚为什么那样设计，那在你把这本书放回书架之前，先听一听我的自我介绍，好吗？ 我叫Jaroslav Tulach，我是 NetBeans 的创建人和首任架构师，NetBeans不仅是一个广为人知的IDE，也是第一个用Java写的模块化的桌面应用程序框架。这本书是在我过去10年工作笔记的基础上写成的。10年来，我的工作就是设计和维护 NetBeans API，并把相关的知识传递给其他的开发人员。这本书是来自 NetBeans 核心开发一线的工作实录，其中描述了我们曾经面临的问题，对这些问题逐步深入的理解，以及我们的对策和实施结果。虽然我们的经验来自于 NetBeans 的开发，但这些经验对大多数软件项目都是非常有价值的。 掌握正确设计API的知识，是在21世纪成功实现软件项目的根本所在。希望本书能在你设计世界级API的过程中助你一臂之力！ Jaroslav Tulach http://wiki.apidesign.org/wiki/InvitationForReaders 介绍一下，为什么要写《软件框架设计的艺术》？ 原因很多。在动笔之前，我也时不时地会产生写本书的冲动。但真正促使我下决心写书，还是在一次家庭聚会上。我当时跟表弟谈到想写一本书，他问我：“既然你知道一些别人不知道的东西，也有那么多写书的素材，连出版社都是现成的……，那你还犹豫什么呢？这样不对啊，赶紧写吧！”于是，我决定联系一家合适的出版社，写作和出版这本书。 说说这本书吧。什么是API，准确地说？ “准确地说？”好吧，API就是沟通。你可能会感到意外，我说的沟通不是指开发人员与计算机之间的沟通，而是人与人之间的对话。正因为如此，“什么是API”这个问题才会有各种各样的答案。一切有助于开发人员之间沟通的东西，都可以或者说都应该称为API，比如数据库的结构、硬盘里保存文件的路径、文件的内容、应用程序监听的端口，以及服务器的URL，等等。 那这本书的读者对象就是那些设计API的人了？ 这本书适合所有希望跟其他人对话的开发人员。不用说，只要是编写代码并需要与团队其他成员共享代码的程序员，都有必要看一看这本书。我把这本书分成三在部分。第一部分介绍一些与API有关的面上的知识，包括API相关的术语及评价其质量的方法和标准。接下来的部分进入实战，讨论了不同的API设计模式。最后一部分更进一步，展示了前两部分的建议在实际中的应用、如何组织API设计团队的工作，以及需要在哪些问题前作出妥协。除了这三部分，书前书后的前言和后记为这三部分提供了背景和上下文。 读者看了这本书能学习到什么？ 我以前一位领导常说：“正确的决断源于经验，而经验源于错误的决断。”我相信，从这个意义上说，NetBeans 团队已经掌握了非常高的API设计技术。然而技术虽高明，却不是什么魔法。我们能对API设计有这样深刻的认识，完全是因为10年来犯过了许许多多的错误。读者通过看这本书，有可能会避免重犯我们犯过的错误，提高自己在设计API时的决断力。 能不能通过一个例子展示一两个建议？ 一两个建议还真是很难给，因为这样很容易让人觉得这两个建议比其他建议更重要，搞清楚这两个建议就万事大吉了。所以，我给不出两个这样的“魔法”建议。 不过，如果必须要找两个结论讲一讲，我可以推荐下面这两个： “API的第一个版本绝对不会完美” “不可能知道使用你的库的所有人” 这两个结论道出了构建带有API的库和构建内部系统之间的根本差异。API就像是星星， 一旦被人发现，就要永远悬挂在苍穹，发出永恒的光辉。星星不能突然无缘无故地从人们的视野中消失。如果一个库随便跟用户玩消失，你的信誉何在？这违背了正确设计的规则。库应该根据API设计领域的规则不断地改进。 你希望本书读者通过这本书获得哪些知识？ 各个方面的知识，我在书中讨论的都是广义的API设计命题。我相信，这些话题触及了任何API设计的本质，对开发现代软件至关重要。但大家对这个问题的重视程度还远远不够，对设计API与设计常规的内部系统有什么区别也没有认识到位。欢迎大家访问http://wiki.apidesign.org/，跟我和其他人分享自己的经验。 我注意到，越来越多的（主要的）开源库需要更多开发人员。我希望能够为所有这些框架的维护人员节省一点时间，让他们不要再重蹈我们的覆辙。希望大家积极地分享经验，而且都能使用切实有效的工作方法。这样，才能开发出更好的库，只有开发出更好的库，才能在它们基础上构建出更好的应用。 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://java.dzone.com/news/interview-jaroslav-tulach-auth">Interview: Jaroslav Tulach, Author of &#8220;Practical API Design&#8221;</a><br />
2008-8-11</p>
<p><img class="colorbox-2367"  style="float:left;margin:0 1em 1em 0;" src="http://java.dzone.com/sites/all/files/Tulach.png"/>Jaroslav Tulach（见图），NetBeans之父、NetBeans API首席架构师，《软件框架设计的艺术》一书的作者。</p>
<p>此次访谈，Jaroslav Tulach会介绍他的这本书，并与大家分享关于设计API的一些独到见解。</p>
<h2>你好，Jaroslav，你是不是先作个自我介绍啊？</h2>
<p><img class="colorbox-2367"   style="float:left;margin:0 1em 1em 0;" src="http://ww4.sinaimg.cn/large/46402b23gw6deva6onmmqj.jpg" />好，我懂。让我提到自己的是 NetBeans 之父，就是想吸引读者都来看一看这本书，对吧？ <img src='http://www.cn-cuckoo.com/main/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley colorbox-2367' /> 。但是，如果一个人的名字让说英语的人完全看不懂，要想达到这个目的可不是那么简单的。我遇到这个问题可不止一次了，在设计这本书封面的时候就碰到了。想了解我的读者，下面就是我的一些背景资料。关于这本书，我想说：我在这本书里真的讲了很多有用的东西，而且我也尽了全力把枯燥的内容讲得更好玩一些。</p>
<div style="padding:1em;margin-top:1em;background:#eee;">
<a name="about_Jaroslav">亲爱的读者朋友，</a></p>
<p>也许你现在正在书店里，手里拿着这本书，问自己：“到底该不该买呢？”让我来告诉你：如果你写过很多代码，而且其他人要在你写的代码基础上编译他们的代码，那结论显而易见：“你早该想一想怎么设计API这个问题了，而本书就是你的得力助手。”</p>
<p>请注意，这可不是一本“5天掌握API设计”之类的书。而且你不可能“只用3天就能看完！”。假如你想找一本简单的参考手册，本书不属于那种类型。不过，要是你对深入了解API设计非常感兴趣，不仅仅满足于怎么设计，还想进一步搞清楚为什么那样设计，那在你把这本书放回书架之前，先听一听我的自我介绍，好吗？</p>
<p>我叫Jaroslav Tulach，我是 NetBeans 的创建人和首任架构师，NetBeans不仅是一个广为人知的IDE，也是第一个用Java写的模块化的桌面应用程序框架。这本书是在我过去10年工作笔记的基础上写成的。10年来，我的工作就是设计和维护 NetBeans API，并把相关的知识传递给其他的开发人员。这本书是来自 NetBeans 核心开发一线的工作实录，其中描述了我们曾经面临的问题，对这些问题逐步深入的理解，以及我们的对策和实施结果。虽然我们的经验来自于 NetBeans 的开发，但这些经验对大多数软件项目都是非常有价值的。</p>
<p>掌握正确设计API的知识，是在21世纪成功实现软件项目的根本所在。希望本书能在你设计世界级API的过程中助你一臂之力！</p>
<p>Jaroslav Tulach<br />
<a href="http://wiki.apidesign.org/wiki/InvitationForReaders">http://wiki.apidesign.org/wiki/InvitationForReaders</a>
</div>
<h2>介绍一下，为什么要写《软件框架设计的艺术》？</h2>
<p>原因很多。在动笔之前，我也时不时地会产生写本书的冲动。但真正促使我下决心写书，还是在一次家庭聚会上。我当时跟表弟谈到想写一本书，他问我：“既然你知道一些别人不知道的东西，也有那么多写书的素材，连出版社都是现成的……，那你还犹豫什么呢？这样不对啊，赶紧写吧！”于是，我决定联系一家合适的出版社，写作和出版这本书。</p>
<h2>说说这本书吧。什么是API，准确地说？</h2>
<p>“准确地说？”好吧，API就是沟通。你可能会感到意外，我说的沟通不是指开发人员与计算机之间的沟通，而是人与人之间的对话。正因为如此，“什么是API”这个问题才会有各种各样的答案。一切有助于开发人员之间沟通的东西，都可以或者说都应该称为API，比如数据库的结构、硬盘里保存文件的路径、文件的内容、应用程序监听的端口，以及服务器的URL，等等。<br />
<span id="more-2367"></span></p>
<h2>那这本书的读者对象就是那些设计API的人了？</h2>
<p>这本书适合所有希望跟其他人对话的开发人员。不用说，只要是编写代码并需要与团队其他成员共享代码的程序员，都有必要看一看这本书。我把这本书分成三在部分。第一部分介绍一些与API有关的面上的知识，包括API相关的术语及评价其质量的方法和标准。接下来的部分进入实战，讨论了不同的API设计模式。最后一部分更进一步，展示了前两部分的建议在实际中的应用、如何组织API设计团队的工作，以及需要在哪些问题前作出妥协。除了这三部分，书前书后的前言和后记为这三部分提供了背景和上下文。</p>
<h2>读者看了这本书能学习到什么？</h2>
<p>我以前一位领导常说：“正确的决断源于经验，而经验源于错误的决断。”我相信，从这个意义上说，NetBeans 团队已经掌握了非常高的API设计技术。然而技术虽高明，却不是什么魔法。我们能对API设计有这样深刻的认识，完全是因为10年来犯过了许许多多的错误。读者通过看这本书，有可能会避免重犯我们犯过的错误，提高自己在设计API时的决断力。</p>
<h2>能不能通过一个例子展示一两个建议？</h2>
<p>一两个建议还真是很难给，因为这样很容易让人觉得这两个建议比其他建议更重要，搞清楚这两个建议就万事大吉了。所以，我给不出两个这样的“魔法”建议。</p>
<p>不过，如果必须要找两个结论讲一讲，我可以推荐下面这两个：</p>
<ul>
<li>“API的第一个版本绝对不会完美”</li>
<li>“不可能知道使用你的库的所有人”</li>
</ul>
<p>这两个结论道出了构建带有API的库和构建内部系统之间的根本差异。API就像是星星， 一旦被人发现，就要永远悬挂在苍穹，发出永恒的光辉。星星不能突然无缘无故地从人们的视野中消失。如果一个库随便跟用户玩消失，你的信誉何在？这违背了正确设计的规则。库应该根据API设计领域的规则不断地改进。</p>
<h2>你希望本书读者通过这本书获得哪些知识？</h2>
<p>各个方面的知识，我在书中讨论的都是广义的API设计命题。我相信，这些话题触及了任何API设计的本质，对开发现代软件至关重要。但大家对这个问题的重视程度还远远不够，对设计API与设计常规的内部系统有什么区别也没有认识到位。欢迎大家访问<a href="http://wiki.apidesign.org/">http://wiki.apidesign.org/</a>，跟我和其他人分享自己的经验。</p>
<p>我注意到，越来越多的（主要的）开源库需要更多开发人员。我希望能够为所有这些框架的维护人员节省一点时间，让他们不要再重蹈我们的覆辙。希望大家积极地分享经验，而且都能使用切实有效的工作方法。这样，才能开发出更好的库，只有开发出更好的库，才能在它们基础上构建出更好的应用。</p>
<p>最后，我想再强调一下，前面提到的一个人不可能预知所有用户这个结论是很重要的。即使是开发内部系统，即使你真的知道所有用户， 这个结论也是非常有用的。从编写代码之初就准备好应对未来的变化，可以为将来发布新版本避免很多麻烦。对于那些30几个人或更多人组成的开发团队来说，本书讨论的API设计方法绝对是非常有用的。</p>
<h2>谈谈写这本书的感受？花了多长时间？你觉得写书是一件好玩的事吗？</h2>
<p>写这本书的素材我已经收集了10年之久了，因此我知道这本书绝不可能在短时间内写完。自从去年夏天，我表弟促使我下定决心之后，写这本书大概花了整整一年时间，包括整理笔记和修改润色。我很欣慰，现在，过了一年，这本书已经上市了，在此我想感谢所有帮我把出书这件事做成的人。如果大家想知道都有谁，可以看看这里：<a href="http://thanks.apidesign.org">http://thanks.apidesign.org</a>。</p>
<h2>对其他想写编程类图书的作者，你有什么建议？</h2>
<p>我发现很多讲编程的书没有使用语法高亮。比如，关键字没有加粗，运算符和字符串与常规的文本也没有区别。虽然是意外发现这个问题，但这让我思考怎么在自己书里的代码示例中加点“高亮”。做到这一点不容易，因为出版社还没有注意到这个问题，也没有什么现成的解决方案。不过，我相信我们最终成功了。本书中所有代码的“颜色”是灰色，这样至少要好一点，而且读者看起来也会感觉更自然。我的建议是：如果你想写编程方面的书，别忘了也给自己的代码示例加点“颜色”。</p>
<h2>还有其他话想对大家说吗？</h2>
<p>分享！我是说，大家一起分享。我自认为对设计API有一定的研究，但同时我也深知，我对设计API仍然还是知之甚少。如何设计API，还需要大家共同探索，希望大家踊跃加入我们的发现之旅。如果你有什么提示、建议、想法、模式，欢迎到<a href="http://wiki.apidesign.org">http://wiki.apidesign.org</a>发表。大家需要这些知识让将来的软件开发更简单，也更可靠。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/03/07/interview-jaroslav-tulach-2367.html/feed</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>2010年美国计算机图书市场报告五：完结篇及数字出版</title>
		<link>http://www.cn-cuckoo.com/2011/02/26/2010-book-market-of-usa-5-2279.html</link>
		<comments>http://www.cn-cuckoo.com/2011/02/26/2010-book-market-of-usa-5-2279.html#comments</comments>
		<pubDate>Sat, 26 Feb 2011 12:43:00 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[出版]]></category>
		<category><![CDATA[编程技术]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2279</guid>
		<description><![CDATA[http://radar.oreilly.com/2011/02/2010-book-market-5.html Mike Hendrickson 2011-2-23 报告内容 第一部分：市场综述 第二部分：分类市场 第三部分：出版商 第四部分：编程语言 第五部分：完结篇及数字出版 下载完整版（PDF） 在最后这一部分中，我们将对前四部分作一番总结，深入了解一些畅销书作者，同时展示一些电子图书销售的数据，分析一下为什么部分电子图书的市场表现已经超过纸版图书。 首先来对本报告的前四部分作个简单的总结。 总体来看，2010年美国图书市场的总销量比2009年下降了4.54%。技术图书市场下降了6.46%，技术书出版商比其他同行承受了更多的压力。然而，与2009年技术图书市场下降13.05%相比，这已经是一个进步了。市场趋势的季节性特征仍然十分明显，2010年初的市场快速启动，到了6月份开始骤降，到了秋季又恢复正常。在Bookscan Top 3000中，2010年计算机类图书比2009年增加了268种（包括不同版权年份出版的图书），而2009年比2008年增加了260种，相当于年增长率为3.5%。单品平均销量从2009年的39.64册下降到2010年的37.92册。根据数据统计，2010年少出版图书104种，但单品平均销量增加了6册。注意，这些图书的出版年份都是2010年。 移动开发类图书成为市场主力军。Android编程和Android设备（面向用户）类图书都有极大的增长，而iOS和Objective-C的市场份额进一步扩大。Windows 7的表现也相当不俗，重现了原来Windows XP曾经达到过的市场份额（Vista从未达到过）。平板电脑异军突起，成为2010年底的一大亮点。在多款Android平板电脑即将上市的背景下，有理由相信平板电脑图书市场一定会继续高歌猛进。另一方面，网页制作、Web设计工具以及Web编程类图书都明显下滑。由于Snow Leopard的突破没有前几个版本的OS那么大，Mac OS图书市场多年来首次出现下滑。Flash和Silverlight的市场也有较大幅度的下滑，原因是HTML5能够提供类似的功能，导致了它们的市场关注度下降。 从出版商的角度看，O&#8217;Reilly在2010年底爬升至第二位，位居Wiley之后，以微弱优势领先于Pearson。O&#8217;Reilly和Dummies这两家出版公司涉足的出版门类最为多样，而它们在6大技术门类中的表现也非常令人瞩目。至于最受欢迎的图书，从码洋来看是PMP Exam Prep, Sixth Edition: Rita&#8217;s Course in a Book for Passing the PMP Exam，从销量来看是Windows 7 For Dummies。2009和2010年的最热门语言都是Java，JavaScript和VBA在2010年也增长了不少。简单的回顾到此为止。 下面我们把注意力转移到出版背后的最重要因素——作者上面。作者是实际创造各种内容的人。作者的类型也很多。有的实际上很像小型的出版工作室，让其他“合著者”完成大部分写书工作；有的则从头到尾大包大揽，从编辑、写作、测试到编写代码，全都自己干，等书出版之后，还会参与推广、活动和销售。后一类作者的活动决定了我们所说的“作者平台”。有些作者凭自己的名气或自己的全职工作，拥有一个稳定的平台。而另外一些作者则不得不苦心经营，不断培养自己的平台。在我们数据库中，最成功的作者都解决了前期内容生产和后期发行销售的问题。在对前15位作者的数据（实际上，他们书的销量和码洋还会更多）进行分析的基础上，可以得到下列两张柱形图，其中展示的是2004-2010年的图书总销量和总码洋情况。 总销量 总码洋 2010年，Paul McFedries的名字出现在了58本不同的图书上（出版日期从2001年到2010年），反映在我们的数据中，这些书的总销量为112,152册。他的书在2010年卖得最好，2010年他有12本新书出版，这是我们的数据。他的总销量比David Pogue多20,000册，后者在我们的数据中有13本书出版，总销量为92,000册。从单品平均销量看，Pogue是7,000册，而McFedries只有1,900册。销量前5名中的其他三位作者是：Andy Rathbone、Greg Harvey和Dan Gookin。如果从码洋的角度来看，前5名的作者从多到少分别是：Paul McFedries、David Pogue、Andy Rathbone、Rita Mulcahy和Scott Kelby。 电子书发行与销售 好了，说完了2010年纸质书的销售情况，接下来就看一看至少已经部分脱离传统发行渠道的电子书的发行情况。下面这张表显示的是2008年的电子书销售情况，数据来源于AAP（Association [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://radar.oreilly.com/2011/02/2010-book-market-5.html">http://radar.oreilly.com/2011/02/2010-book-market-5.html</a><br />
Mike Hendrickson<br />
2011-2-23</p>
<div style="float:right; border:1px solid #ddd;border-width:0 0 1px 1px;padding:0 .5em;margin:0 0 0 .5em;">
<p style="font-weight:bold;">报告内容</p>
<ol>
<li><a href="http://www.cn-cuckoo.com/2011/02/26/2010-book-market-of-usa-1-2287.html">第一部分：市场综述</a></li>
<li><a href="http://www.cn-cuckoo.com/2011/02/23/2010-book-market-of-usa-2-2329.html">第二部分：分类市场</a></li>
<li><a href="http://www.cn-cuckoo.com/2011/02/23/2010-book-market-of-usa-3-2270.html">第三部分：出版商</a></li>
<li><a href="http://www.cn-cuckoo.com/2011/02/23/2010-book-market-of-usa-4-2265.html">第四部分：编程语言</a></li>
<li><a href="http://www.cn-cuckoo.com/2011/02/25/2010-book-market-of-usa-5-2279.html">第五部分：完结篇及数字出版</a></li>
</ol>
<div style="text-align:center;">
<a href="http://u.115.com/file/f661fc6f86"><br />
<img class="colorbox-2279"  style="border:1px solid #eee;" src="http://ww1.sinaimg.cn/large/61baa48djw6deqves2ryvj.jpg"/><br />
</a><br />
<a href="http://u.115.com/file/f661fc6f86">下载完整版（PDF）</a>
</div>
</div>
<p>在最后这一部分中，我们将对前四部分作一番总结，深入了解一些畅销书作者，同时展示一些电子图书销售的数据，分析一下为什么部分电子图书的市场表现已经超过纸版图书。</p>
<p>首先来对本报告的前四部分作个简单的总结。</p>
<p>总体来看，2010年美国图书市场的总销量比2009年下降了4.54%。技术图书市场下降了6.46%，技术书出版商比其他同行承受了更多的压力。然而，与2009年技术图书市场下降13.05%相比，这已经是一个进步了。市场趋势的季节性特征仍然十分明显，2010年初的市场快速启动，到了6月份开始骤降，到了秋季又恢复正常。在Bookscan Top 3000中，2010年计算机类图书比2009年增加了268种（包括不同版权年份出版的图书），而2009年比2008年增加了260种，相当于年增长率为3.5%。单品平均销量从2009年的39.64册下降到2010年的37.92册。根据数据统计，2010年少出版图书104种，但单品平均销量增加了6册。注意，这些图书的出版年份都是2010年。</p>
<p>移动开发类图书成为市场主力军。Android编程和Android设备（面向用户）类图书都有极大的增长，而iOS和Objective-C的市场份额进一步扩大。Windows 7的表现也相当不俗，重现了原来Windows XP曾经达到过的市场份额（Vista从未达到过）。平板电脑异军突起，成为2010年底的一大亮点。在多款Android平板电脑即将上市的背景下，有理由相信平板电脑图书市场一定会继续高歌猛进。另一方面，网页制作、Web设计工具以及Web编程类图书都明显下滑。由于Snow Leopard的突破没有前几个版本的OS那么大，Mac OS图书市场多年来首次出现下滑。Flash和Silverlight的市场也有较大幅度的下滑，原因是HTML5能够提供类似的功能，导致了它们的市场关注度下降。</p>
<p>从出版商的角度看，O&#8217;Reilly在2010年底爬升至第二位，位居Wiley之后，以微弱优势领先于Pearson。O&#8217;Reilly和Dummies这两家出版公司涉足的出版门类最为多样，而它们在6大技术门类中的表现也非常令人瞩目。至于最受欢迎的图书，从码洋来看是<em>PMP Exam Prep, Sixth Edition: Rita&#8217;s Course in a Book for Passing the PMP Exam</em>，从销量来看是<em>Windows 7 For Dummies</em>。2009和2010年的最热门语言都是Java，JavaScript和VBA在2010年也增长了不少。简单的回顾到此为止。<br />
<span id="more-2279"></span><br />
下面我们把注意力转移到出版背后的最重要因素——作者上面。作者是实际创造各种内容的人。作者的类型也很多。有的实际上很像小型的出版工作室，让其他“合著者”完成大部分写书工作；有的则从头到尾大包大揽，从编辑、写作、测试到编写代码，全都自己干，等书出版之后，还会参与推广、活动和销售。后一类作者的活动决定了我们所说的“作者平台”。有些作者凭自己的名气或自己的全职工作，拥有一个稳定的平台。而另外一些作者则不得不苦心经营，不断培养自己的平台。在我们数据库中，最成功的作者都解决了前期内容生产和后期发行销售的问题。在对前15位作者的数据（实际上，他们书的销量和码洋还会更多）进行分析的基础上，可以得到下列两张柱形图，其中展示的是2004-2010年的图书总销量和总码洋情况。</p>
<h3>总销量</h3>
<p><img class="colorbox-2279"  src="http://radar.oreilly.com/upload/2011/02/Author2004_2010Units.jpg"/></p>
<h3>总码洋</h3>
<p><img class="colorbox-2279"  src="http://radar.oreilly.com/upload/2011/02/Author2004_2010Dollars.jpg"/></p>
<p>2010年，Paul McFedries的名字出现在了58本不同的图书上（出版日期从2001年到2010年），反映在我们的数据中，这些书的总销量为112,152册。他的书在2010年卖得最好，2010年他有12本新书出版，这是我们的数据。他的总销量比David Pogue多20,000册，后者在我们的数据中有13本书出版，总销量为92,000册。从单品平均销量看，Pogue是7,000册，而McFedries只有1,900册。销量前5名中的其他三位作者是：Andy Rathbone、Greg Harvey和Dan Gookin。如果从码洋的角度来看，前5名的作者从多到少分别是：Paul McFedries、David Pogue、Andy Rathbone、Rita Mulcahy和Scott Kelby。</p>
<h2>电子书发行与销售</h2>
<p>好了，说完了2010年纸质书的销售情况，接下来就看一看至少已经部分脱离传统发行渠道的电子书的发行情况。下面这张表显示的是2008年的电子书销售情况，数据来源于AAP（Association of American Publishers，美国出版商协会）。最令人惊讶的是增长规模，从2008年1800万美元，到2010年1.2亿美元，增长了近10倍。随着各种平板阅读设备的纷纷上市，电子图书将会迎来其黄金时代。即使市场增速不变，2013的电子图书市场规模也将到达10亿美元。</p>
<h3>2008年电子书市场</h3>
<p><img class="colorbox-2279"  src="http://radar.oreilly.com/Trade%20Stats_04_08.jpg"/></p>
<h3>2010年电子书市场</h3>
<p><img class="colorbox-2279"  src="http://radar.oreilly.com/upload/2011/02/Trade%20Stats_Master_10Q3_fnl.jpg"/></p>
<p>AAP对自己发布的数据给出了如下说明。</p>
<ul>
<li>以上数据仅代表美国的收入。</li>
<li>以上数据仅代表通过批发渠道交易的电子书销售额。考虑到批发折扣，零售渠道的销售额可能会是以上数字的两倍左右。</li>
<li>以上数据仅代表12到15家出版商提供的交易额数据。</li>
<li>以上数据不包含图书馆、教育及专业类电子书销售。</li>
<li>以上数据反映的是出版商的批发收入（出版实洋）。</li>
<li>报告中所称的电子书是指“所有以电子形式通过Internet交付或传输到手持设备的图书”。</li>
<li>相关数据由IDPF和AAP从2006年第一季度开始共同收集。</li>
</ul>
<p>根据以上说明，我个人认为，电子书交易到2013年达到10亿美元的规模还是保守的估计。</p>
<p>下面的两张图展示了Safari收入的增长情况及oreilly.com直接销售的情况。展示这两张图的原因是，纸质图书的内容会以不同的数字形式出现。Safari本身是一个订阅服务，拥有50多万用户，其主要业务是B2B服务，定位于让世界各大公司的开发人员能够访问Safari Books Online。为此，一个显著的区别就是那些以普通读者为对象的书，以及很多数字媒体类图书，在Safari中的表现都不佳。从下图可以看出，我们Safari中的内容销售每年都能实现稳定的增长。</p>
<h3>Safari中O&#8217;Reilly图书的增长情况</h3>
<p><img class="colorbox-2279"  src="http://radar.oreilly.com/upload/2011/02/safariRevenueGrowth.jpg"/></p>
<p>下面这张图更有意思一些，因为它反映了真实的市场情况。其中显示的是2010年通过oreilly.com卖出的纸质书、电子书和视频的数据。这三类出版物的内容大部分都是相同的，其中电子书无非就是我们纸版书的数字版而已。但从图中可以看出，我们电子书的销量占到总销量的88%，占到了总码洋的79%。真正值得注意的是，我们数字产品的市场增长速度超过了纸质书的市场下滑速度。这表明我们不同形式产品的销售并没有此消彼涨，而是出现了互为补充的良好局面。</p>
<h3>oreilly.com销售多种形式产品的情况</h3>
<p><img class="colorbox-2279"  src="http://radar.oreilly.com/upload/2011/02/oreilly_com.jpg"/></p>
<p>第三张图展示了出版物形态变迁的本质，其中的百分比值表示每种特定出版物形态，以及相应年度的销售量。我个人认为，这张图显示了的出版业转型的一个趋势。纸质书慢慢减少，EPUB、Mobi及Ebooks的快速上升速度比纸质书下降的速度更快。PDF的销量在下降，想一想，也在情理之中。O&#8217;Reilly以前只提供两种图书产品形式：纸版书和PDF版。而现在，我们提供读者需要的任何一种形式。因此，在提供Mobi、EPUB和Ebook的情况下，不那么有用的PDF在显著下降。</p>
<h3>O&#8217;Reilly各类产品的销售情况</h3>
<p><img class="colorbox-2279"  src="http://radar.oreilly.com/upload/2011/02/ormDistro.jpg"/></p>
<p>再强调一下，这些数据来自O&#8217;Reilly和oreilly.com，不一定能反映整个计算机图书市场。我从其他出版商那里了解过，比如Prags的Dave Thomas曾告诉我，以上分布情况与他们的出版模式大致相同，有时候可能会比他们落后一些。一些成长型的小出版商致力于数字出版的积极性明显高于纸质出版，而对于我们这种具有相当规模的传统纸质出版模式的出版商来说，数字出版的增长速度也会超过纸质出版。在纸质出版前面冠以“传统”两个字好像有点新鲜，但这种说法的确是名副其实。难道这表明计算机图书市场真的要发生质的变化了吗？</p>
<p>感谢您看完这几篇报告。如果您想再看到某些细节（或者弄得更明白一点），请跟我联系，我一定尽力提供帮助。我打算今年在Twitter上摘录对这几篇报告中内容的更新信息。这些消息将通过@mikehatora发布，然后可能会由@oreillymedia转发，敬请关注。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/02/26/2010-book-market-of-usa-5-2279.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>2010年美国计算机图书市场报告四：编程语言</title>
		<link>http://www.cn-cuckoo.com/2011/02/25/2010-book-market-of-usa-4-2265.html</link>
		<comments>http://www.cn-cuckoo.com/2011/02/25/2010-book-market-of-usa-4-2265.html#comments</comments>
		<pubDate>Fri, 25 Feb 2011 07:53:45 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[出版]]></category>
		<category><![CDATA[编程技术]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2265</guid>
		<description><![CDATA[http://radar.oreilly.com/2011/02/2010-book-market-4.html Mike Hendrickson 2011-2-21 报告内容 第一部分：市场综述 第二部分：分类市场 第三部分：出版商 第四部分：编程语言 第五部分：完结篇及数字出版 下载完整版（PDF） 这是《2010年计算机图书市场报告》的第四部分，我们来看一看编程语言市场，对各种编程语言作一备盘点。 与2009年相比，2010年编程语言市场总体下滑，幅度为-6.27%。从销售总量看，2009年图书共售出6,303,125册，而2010年共售出5,931,452册，减少了371,673册。其中，Java语言类图书销量增长最多，2010年比2009年多售出28,633册，而PHP语言类图书销量降低最多，比上一年减少了38,614册。 在盘点各种语言之前，有必要先明确一下“语言维度”这个概念。语言维度是我们对语言类图书进行分类的一个标准，这个标准就是看图书中的代码示例是使用什么语言编写的。比如，Flash Programming with Java这本书，它的基本分类是Flash，但按语言维度分，则属于Java类。同样，Head First Design Patterns中的示例是用Java写的，因此按语言维度分，这本书也属于Java类。 综合来看，2009和2010年编程语言类图书的市场表现是最糟糕的。下面这张图中不包括谈方法论的、项目管理的、消费者操作系统的，以及其他不涉及具体语言的图书。因此，我们现在对编程语言类图书的分析，与本报告第一部分的总体评价出发点是不一样的。这张图显示的是以周为单位的所有语言类图书的市场表现情况，其中2009年和2010年与其他年份比，依旧是最差的。 2008年，我们在报告中分析C#超过Java成为了最热门的语言。但时隔不久，Java图书就在2009年发力反弹，终于在2010年王者归来，重新登上编程语言图书第一位的宝座。通过下面这张2010年最畅销语言的柱状图可以看出，Java在这些语言里遥遥领先，而Objective-C则迅速攀升至第三位，仅次于C#。 2010年市场份额 再看看下面这张图，哪些语言的图书对2004年至2010年的码洋贡献最大可以一目了然。比较新的语言，或者说“时尚”的语言，由于时间太短，它们市场表现如何一时可能还看不出来。这张表基本上根据这些语言在相应时间段内的实际销量绘制的。其中，前10位的图书7年总共销售7,655,365册，后10位的图书7年总共销售1,919,691册。从份额来看，前10位大约占80%。从这些语言7年来的趋势看，C#在2009年之前一直是稳步增长的，Java则正好相反，2009年之前它的市场表现是越来越差的。2009到2010年，除了Java、VBA、VBScript、SAS、JavaScript、C++和C呈现上升态势，其他13门语言的销量都减少了。 编程语言类图书市场表现的Treemap 在上面这张Treemp图中，我们对比的是2010年第四季度和2009年第四季度，两年的同期相比，可以看到不少亮绿色区域、几块深绿色区域，黑色及红色区域也占相当面积。Objective-C之所以会下降12%，因为它在2009年的表现实在太好，很难维持。但由于它的在图中面积很可观，结果就让这张图显得有些压抑了。 深入数据分析之前，我们先了解一下这些语言的总体情况。首先，对它们进行了分组，分组依据是它们在2004-2010年间的总销量。通过下面这张表就可以看出来，只有Mid-Majo组的销量在2010年是增长的，其他组的销量都在减少。而Mid-Major组中销售增长幅度最大的是R。有意思的是，像R这样的统计分析语言基本上都在增长（和Strata大会的结论类似）。实际上，R、SAS、Matlab、Labview、Mathematica以及SPSS这些语言加在一起，总共增长了49,504册，增幅达到了102.87%。也许是因为Hal Varian关于统计将成为“最有前途的工作”的论调，刺激了开发人员都去学习这些语言。 Group Unit Range Y2010 Units Y2009 Units Y2010 # Y2009 # 10MketShar 9MketShar Large 50,000 &#151 200,000 1,051,945 1,069,762 1,590 1,433 75.96% 75.00% Major 10,000 &#151 49,000 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://radar.oreilly.com/2011/02/2010-book-market-4.html">http://radar.oreilly.com/2011/02/2010-book-market-4.html</a><br />
Mike Hendrickson<br />
2011-2-21</p>
<div style="float:right; border:1px solid #ddd;border-width:0 0 1px 1px;padding:0 .5em;margin:0 0 0 .5em;">
<p style="font-weight:bold;">报告内容</p>
<ol>
<li><a href="http://www.cn-cuckoo.com/2011/02/26/2010-book-market-of-usa-1-2287.html">第一部分：市场综述</a></li>
<li><a href="http://www.cn-cuckoo.com/2011/02/23/2010-book-market-of-usa-2-2329.html">第二部分：分类市场</a></li>
<li><a href="http://www.cn-cuckoo.com/2011/02/23/2010-book-market-of-usa-3-2270.html">第三部分：出版商</a></li>
<li><a href="http://www.cn-cuckoo.com/2011/02/23/2010-book-market-of-usa-4-2265.html">第四部分：编程语言</a></li>
<li><a href="http://www.cn-cuckoo.com/2011/02/25/2010-book-market-of-usa-5-2279.html">第五部分：完结篇及数字出版</a></li>
</ol>
<div style="text-align:center;">
<a href="http://u.115.com/file/f661fc6f86"><br />
<img class="colorbox-2265"  style="border:1px solid #eee;" src="http://ww1.sinaimg.cn/large/61baa48djw6deqves2ryvj.jpg"/><br />
</a><br />
<a href="http://u.115.com/file/f661fc6f86">下载完整版（PDF）</a>
</div>
</div>
<p>这是《2010年计算机图书市场报告》的第四部分，我们来看一看编程语言市场，对各种编程语言作一备盘点。</p>
<p>与2009年相比，2010年编程语言市场总体下滑，幅度为-6.27%。从销售总量看，2009年图书共售出6,303,125册，而2010年共售出5,931,452册，减少了371,673册。其中，Java语言类图书销量增长最多，2010年比2009年多售出28,633册，而PHP语言类图书销量降低最多，比上一年减少了38,614册。</p>
<p>在盘点各种语言之前，有必要先明确一下“语言维度”这个概念。语言维度是我们对语言类图书进行分类的一个标准，这个标准就是看图书中的代码示例是使用什么语言编写的。比如，Flash Programming with Java这本书，它的基本分类是Flash，但按语言维度分，则属于Java类。同样，Head First Design Patterns中的示例是用Java写的，因此按语言维度分，这本书也属于Java类。</p>
<p>综合来看，2009和2010年编程语言类图书的市场表现是最糟糕的。下面这张图中不包括谈方法论的、项目管理的、消费者操作系统的，以及其他不涉及具体语言的图书。因此，我们现在对编程语言类图书的分析，与本报告第一部分的总体评价出发点是不一样的。这张图显示的是以周为单位的所有语言类图书的市场表现情况，其中2009年和2010年与其他年份比，依旧是最差的。</p>
<p><img class="colorbox-2265"  src="http://radar.oreilly.com/upload/2011/02/AllYearsLanguages.jpg"/></p>
<p>2008年，我们在报告中分析C#超过Java成为了最热门的语言。但时隔不久，Java图书就在2009年发力反弹，终于在2010年王者归来，重新登上编程语言图书第一位的宝座。通过下面这张2010年最畅销语言的柱状图可以看出，Java在这些语言里遥遥领先，而Objective-C则迅速攀升至第三位，仅次于C#。<br />
<span id="more-2265"></span></p>
<h2>2010年市场份额</h2>
<p><img class="colorbox-2265"  src="http://radar.oreilly.com/upload/2011/02/Top20_langs_2010.jpg"/></p>
<p>再看看下面这张图，哪些语言的图书对2004年至2010年的码洋贡献最大可以一目了然。比较新的语言，或者说“时尚”的语言，由于时间太短，它们市场表现如何一时可能还看不出来。这张表基本上根据这些语言在相应时间段内的实际销量绘制的。其中，前10位的图书7年总共销售7,655,365册，后10位的图书7年总共销售1,919,691册。从份额来看，前10位大约占80%。从这些语言7年来的趋势看，C#在2009年之前一直是稳步增长的，Java则正好相反，2009年之前它的市场表现是越来越差的。2009到2010年，除了Java、VBA、VBScript、SAS、JavaScript、C++和C呈现上升态势，其他13门语言的销量都减少了。</p>
<p><img class="colorbox-2265"  src="http://radar.oreilly.com/upload/2011/02/AllYearsT20Langs.jpg"/></p>
<h2>编程语言类图书市场表现的Treemap</h2>
<p><img class="colorbox-2265"  src="http://radar.oreilly.com/upload/2011/02/prog_lang_tree.jpg"/></p>
<p>在上面这张Treemp图中，我们对比的是2010年第四季度和2009年第四季度，两年的同期相比，可以看到不少亮绿色区域、几块深绿色区域，黑色及红色区域也占相当面积。Objective-C之所以会下降12%，因为它在2009年的表现实在太好，很难维持。但由于它的在图中面积很可观，结果就让这张图显得有些压抑了。</p>
<p>深入数据分析之前，我们先了解一下这些语言的总体情况。首先，对它们进行了分组，分组依据是它们在2004-2010年间的总销量。通过下面这张表就可以看出来，只有Mid-Majo组的销量在2010年是增长的，其他组的销量都在减少。而Mid-Major组中销售增长幅度最大的是R。有意思的是，像R这样的统计分析语言基本上都在增长（和Strata大会的结论类似）。实际上，R、SAS、Matlab、Labview、Mathematica以及SPSS这些语言加在一起，总共增长了49,504册，增幅达到了102.87%。也许是因为Hal Varian关于统计将成为“最有前途的工作”的论调，刺激了开发人员都去学习这些语言。</p>
<table border=1 cellpadding=1 cellspacing=1>
<tr>
<td>Group</td>
<td>Unit Range</td>
<td>Y2010 Units</td>
<td>Y2009 Units</td>
<td>Y2010 #</td>
<td>Y2009 #</td>
<td>10MketShar</td>
<td>9MketShar</td>
</tr>
<tr>
<td>Large</td>
<td>50,000 &#151 200,000</td>
<td align=right>1,051,945</td>
<td align=right>1,069,762</td>
<td align=right>1,590</td>
<td align=right>1,433</td>
<td align=right>75.96%</td>
<td align=right>75.00%</td>
</tr>
<tr>
<td>Major</td>
<td>10,000 &#151 49,000</td>
<td align=right>227,306</td>
<td align=right>254,587</td>
<td align=right>450</td>
<td align=right>456</td>
<td align=right>16.41%</td>
<td align=right>17.85%</td>
</tr>
<tr>
<td>Mid-Major</td>
<td>3,000 &#151 9,999</td>
<td align=right>53,152</td>
<td align=right>44,909</td>
<td align=right>104</td>
<td align=right>85</td>
<td align=right>3.84%</td>
<td align=right>3.15%</td>
</tr>
<tr>
<td>Mid-Minor</td>
<td>1,682 &#151 2,999</td>
<td align=right>20,818</td>
<td align=right>20,965</td>
<td align=right>61</td>
<td align=right>58</td>
<td align=right>1.50%</td>
<td align=right>1.47%</td>
</tr>
<tr>
<td>Minor</td>
<td>1,000 &#151 1,680</td>
<td align=right>13,000</td>
<td align=right>15,517</td>
<td align=right>46</td>
<td align=right>31</td>
<td align=right>0.94%</td>
<td align=right>1.09%</td>
</tr>
<tr>
<td>Linelist</td>
<td>399 &#151 999</td>
<td align=right>6,299</td>
<td align=right>6,350</td>
<td align=right>25</td>
<td align=right>19</td>
<td align=right>0.45%</td>
<td align=right>0.45%</td>
</tr>
<tr>
<td>TheRest</td>
<td>< 399</td>
<td align=right>3,370</td>
<td align=right>6,368</td>
<td align=right>49</td>
<td align=right>43</td>
<td align=right>0.24%</td>
<td align=right>0.45%</td>
</tr>
</table>
<p>为了以分组方式更清楚地展示这些信息，我们使用了这些表头对这些语言进行了分类。</p>
<table border="1">
<tr>
<td align="center">*<strong>Large</strong>*</td>
<td colspan="2" align="center"><b>U N I T S</b></td>
<td colspan="2" align="center"><b>T I T L E S</b></td>
<td colspan="2" align="center"><b>M A R K E T S H A R E</b></td>
</tr>
<tr>
<td height="13" align="center"><b>1.</b> Language</td>
<td align="center"><b>2.</b> 2010 Units</td>
<td align="center"><b>3.</b> 2009 Units</td>
<td align="center"><b>4.</b> 2010 Titles</td>
<td align="center"><b>5.</b> 2009 Titles</td>
<td align="center"><b>6.</b> 10Mkt Share</td>
<td align="center"><b>7.</b> 09Mkt Share</td>
</tr>
</table>
<ol>
<li>语言的名字或简写形式</li>
<li>2010销售量</li>
<li>2009销售量</li>
<li>2010年Bookscan监控销量前3000名中的品种数</li>
<li>2009年Bookscan监控销量前3000名中的品种数</li>
<li>2010年市场份额</li>
<li>2009年市场份额</li>
</ol>
<p>下面这个表展示的是Large语言组的数据。排名前10位的语言中，在Java止跌回涨的带领下，有5种在2010年是增长的。本报告前几部分也介绍过，Java语言类图书的销量一直在持续减少，到2009年甚至延续到2010年都是如此。难道是Android开发为Java的复活注射了强心剂？而Objective-C虽然在2010年销量减少，但依旧跻身前10之列。此前Objective-C的排名差不多是在第20位左右。JavaScript保持了稳步增长态势，作为Web编程中最常用也是最重要的一门语言，它的地位如今已经不可动摇了。</p>
<h3>Large组的编程语言（2010年销量在50,000-195,000之间）</h3>
<table border="1">
<tr>
<td align="center"><b>*Large*</b></td>
<td colspan="2" align="center"><b>U N I T S</b></td>
<td colspan="2" align="center"><b>T I T L E S</b></td>
<td colspan="2" align="center"><b>M A R K E T S H A R E</b></td>
</tr>
<tr>
<td align="center"><b>Language</b></td>
<td align="center"><b>2010 Units</b></td>
<td align="center"><b>2009 Units</b></td>
<td align="center"><b>2010 Titles</b></td>
<td align="center"><b>2009 Titles</b></td>
<td align="center"><b>10Mkt Share</b></td>
<td align="center"><b>09Mkt Share</b></td>
</tr>
<tr>
<td>Java</td>
<td align="right">194,520</td>
<td align="right">165,887</td>
<td align="right">361</td>
<td align="right">332</td>
<td align="right">13.90%</td>
<td align="right">11.54%</td>
</tr>
<tr>
<td>C#</td>
<td align="right">153,469</td>
<td align="right">156,043</td>
<td align="right">263</td>
<td align="right">230</td>
<td align="right">10.97%</td>
<td align="right">10.86%</td>
</tr>
<tr>
<td>Objective C</td>
<td align="right">136,711</td>
<td align="right">141,608</td>
<td align="right">89</td>
<td align="right">51</td>
<td align="right">9.77%</td>
<td align="right">9.85%</td>
</tr>
<tr>
<td>JavaScript</td>
<td align="right">131,850</td>
<td align="right">115,107</td>
<td align="right">169</td>
<td align="right">157</td>
<td align="right">9.42%</td>
<td align="right">8.01%</td>
</tr>
<tr>
<td>PHP</td>
<td align="right">106,952</td>
<td align="right">145,566</td>
<td align="right">163</td>
<td align="right">152</td>
<td align="right">7.64%</td>
<td align="right">10.13%</td>
</tr>
<td>C/C++</td>
<td align="right">94,268</td>
<td align="right">93,067</td>
<td align="right">192</td>
<td align="right">184</td>
<td align="right">6.74%</td>
<td align="right">6.48%</td>
</tr>
<tr>
<td>VBA</td>
<td align="right">61,108</td>
<td align="right">48,507</td>
<td align="right">68</td>
<td align="right">58</td>
<td align="right">4.37%</td>
<td align="right">3.38%</td>
</tr>
<tr>
<td>ActionScript</td>
<td align="right">60,578</td>
<td align="right">83,017</td>
<td align="right">96</td>
<td align="right">85</td>
<td align="right">4.33%</td>
<td align="right">5.78%</td>
</tr>
<tr>
<td>Python</td>
<td align="right">58,905</td>
<td align="right">60,700</td>
<td align="right">94</td>
<td align="right">84</td>
<td align="right">4.21%</td>
<td align="right">4.22%</td>
</tr>
<tr>
<td>SQL</td>
<td align="right">53,584</td>
<td align="right">60,260</td>
<td align="right">95</td>
<td align="right">100</td>
<td align="right">3.83%</td>
<td align="right">4.19%</td>
</tr>
</table>
<p>下面这个表里列出Large组语言中卖得最好的几本书。而且，不管从销量看，还是从码洋看，这几本书的排名都是相同的，只不过按码洋排名，WordPress第5的位置会被Addison-Wesley的PHP and MySQL Web Development取代。</p>
<table border="1">
<tr>
<td>O&#8217;Reilly</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="bit.ly/egQEmN" title="Learning PHP, MySQL, and JavaScript, First Edition">Learning PHP, MySQL, and JavaScript, First Edition</a></span></td>
</tr>
<tr>
<td>O&#8217;Reilly</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://oreil.ly/eTKrN9" title="Head First Java, Second Edition">Head First Java, Second Edition</a></span></td>
</tr>
<tr>
<td>Wrox</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://amzn.to/hAcCfA">Professional Android 2 Application Development</a></span></td>
</tr>
<tr>
<td>Addison-Wesley</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://amzn.to/eP4pmm">Programming in Objective-C 2.0</a></span></td>
</tr>
<tr>
<td>Dummies</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://amzn.to/dVCrAF">WordPress for Dummies (covers PHP)</a></span></td>
</tr>
</table>
<p>在Major语言组中，C、Powershell、ShellScript和VBScript都在增长。总体来看，这些语言的图书2010年比2009年少销售27,000册，相当于Major组语言总体减少量的12%。</p>
<h3>Major组的编程语言（2010年销量在10,000-49,999之间）</h3>
<table border="1">
<tr>
<td align="center"><b>*Major*</b></td>
<td colspan="2" align="center"><b>U N I T S</b></td>
<td colspan="2" align="center"><b>T I T L E S</b></td>
<td colspan="2" align="center"><b>M A R K E T S H A R E</b></td>
</tr>
<tr>
<td align="center"><b>Language</b></td>
<td align="center"><b>2010 Units</b></td>
<td align="center"><b>2009 Units</b></td>
<td align="center"><b>2010 Titles</b></td>
<td align="center"><b>2009 Titles</b></td>
<td align="center"><b>10Mkt Share</b></td>
<td align="center"><b>09Mkt Share</b></td>
</tr>
<tr>
<td>.NET Languages</td>
<td align="right">44,958</td>
<td align="right">57,286</td>
<td align="right">82</td>
<td align="right">78</td>
<td align="right">3.25%</td>
<td align="right">4.02%</td>
</tr>
<tr>
<td>Visual Basic</td>
<td align="right">42,225</td>
<td align="right">55,574</td>
<td align="right">88</td>
<td align="right">94</td>
<td align="right">3.05%</td>
<td align="right">3.90%</td>
</tr>
<tr>
<td>C</td>
<td align="right">36,638</td>
<td align="right">34,820</td>
<td align="right">91</td>
<td align="right">83</td>
<td align="right">2.65%</td>
<td align="right">2.44%</td>
</tr>
<tr>
<td>Ruby</td>
<td align="right">20,004</td>
<td align="right">29,977</td>
<td align="right">48</td>
<td align="right">63</td>
<td align="right">1.44%</td>
<td align="right">2.10%</td>
</tr>
<tr>
<td>Powershell</td>
<td align="right">18,652</td>
<td align="right">12,124</td>
<td align="right">26</td>
<td align="right">19</td>
<td align="right">1.35%</td>
<td align="right">0.85%</td>
</tr>
<tr>
<td>Transact SQL</td>
<td align="right">17,507</td>
<td align="right">17,601</td>
<td align="right">28</td>
<td align="right">29</td>
<td align="right">1.26%</td>
<td align="right">1.23%</td>
</tr>
<tr>
<td>Perl</td>
<td align="right">15,606</td>
<td align="right">20,030</td>
<td align="right">32</td>
<td align="right">34</td>
<td align="right">1.13%</td>
<td align="right">1.40%</td>
</tr>
<tr>
<td>Pl/Sql</td>
<td align="right">10,670</td>
<td align="right">10,974</td>
<td align="right">24</td>
<td align="right">26</td>
<td align="right">0.77%</td>
<td align="right">0.77%</td>
</tr>
<tr>
<td>Shell Script</td>
<td align="right">10,720</td>
<td align="right">7,482</td>
<td align="right">20</td>
<td align="right">17</td>
<td align="right">0.77%</td>
<td align="right">0.52%</td>
</tr>
<tr>
<td>VBScript</td>
<td align="right">10,326</td>
<td align="right">8,719</td>
<td align="right">11</td>
<td align="right">13</td>
<td align="right">0.74%</td>
<td align="right">0.61%</td>
</tr>
</table>
<p>以下是Major组语言中销量前5名的图书。</p>
<table border="1">
<tr>
<td>Prentice Hall</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://amzn.to/dXep8h">C Programming Language</a></span></td>
</tr>
<tr>
<td>Prentice Hall</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://amzn.to/g7mC4r">Practical Guide to Linux Commands, Editors, and Shell Programming</a></span></td>
<tr>
<td>O&#8217;Reilly</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://oreil.ly/iesPCX">Learning Perl, 5th Edition</a></span></td>
</tr>
<tr>
<td>Morgan Kaufman</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://amzn.to/fTMRsp">Programming Massively Parallel Processors: A Hands-on Approach (C language)</a></span></td>
</tr>
<td>Pragmatic</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://oreil.ly/eSQSBP">Agile Web Development with Rails, Third Edition</a></span></td>
</tr>
</table>
<h3>Mid-Major组的编程语言（2010年销量在3,000-9,999之间）</h3>
<p>在这个组中，统计分析语言的表现非常出色。如前所述，这些语言2010年比2009年增长了102.87%。其中，最为突出的是以R in a Nutshell为首的8本R语言图书。</p>
<table border="1">
<tr>
<td align="center"><b>*Mid-Major*</b></td>
<td colspan="2" align="center"><b>U N I T S</b></td>
<td colspan="2" align="center"><b>T I T L E S</b></td>
<td colspan="2" align="center"><b>M A R K E T S H A R E</b></td>
</tr>
<tr class="xl29">
<td align="center"><b>Language</b></td>
<td align="center"><b>2010 Units</b></td>
<td align="center"><b>2009 Units</b></td>
<td align="center"><b>2010 Titles</b></td>
<td align="center"><b>2009 Titles</b></td>
<td align="center"><b>10Mkt Share</b></td>
<td align="center"><b>09Mkt Share</b></td>
</tr>
<tr>
<td>SAS</td>
<td align="right">9,035</td>
<td align="right">7,974</td>
<td align="right">27</td>
<td align="right">21</td>
<td align="right">0.65%</td>
<td align="right">0.56%</td>
<tr>
<td>SPSS</td>
<td align="right">8,973</td>
<td align="right">6,818</td>
<td align="right">16</td>
<td align="right">10</td>
<td align="right">0.65%</td>
<td align="right">0.48%</td>
</tr>
<tr>
<td>MatLab</td>
<td align="right">7,857</td>
<td align="right">6,752</td>
<td align="right">22</td>
<td align="right">17</td>
<td align="right">0.57%</td>
<td align="right">0.47%</td>
</tr>
<tr>
<td>R</td>
<td align="right">7,800</td>
<td align="right">2,817</td>
<td align="right">15</td>
<td align="right">12</td>
<td align="right">0.56%</td>
<td align="right">0.20%</td>
</tr>
<tr>
<td>Processing</td>
<td align="right">6,996</td>
<td align="right">6,038</td>
<td align="right">8</td>
<td align="right">6</td>
<td align="right">.51%</td>
<td align="right">.42%</td>
</tr>
<tr>
<td>Shell Script</td>
<td align="right">6,073</td>
<td align="right">7,116</td>
<td align="right">19</td>
<td align="right">16</td>
<td align="right">.44%</td>
<td align="right">.50%</td>
</tr>
<tr>
<td>Basic</td>
<td align="right">5,540</td>
<td align="right">5,277</td>
<td align="right">7</td>
<td align="right">9</td>
<td align="right">.40%</td>
<td align="right">.37%</td>
</tr>
<tr>
<td>Lua</td>
<td align="right">4,677</td>
<td align="right">5,570</td>
<td align="right">7</td>
<td align="right">6</td>
<td align="right">.34%</td>
<td align="right">.39%</td>
</tr>
<tr>
<td>Assembly</td>
<td align="right">4,391</td>
<td align="right">4,359</td>
<td align="right">18</td>
<td align="right">14</td>
<td align="right">.32%</td>
<td align="right">.31%</td>
</tr>
<tr>
<td>MDX</td>
<td align="right">3,890</td>
<td align="right">4,838</td>
<td align="right">8</td>
<td align="right">8</td>
<td align="right">0.28%</td>
<td align="right">0.34%</td>
</tr>
<tr>
<td>UnrealScript</td>
<td align="right">3,028</td>
<td align="right">2,440</td>
<td align="right">3</td>
<td align="right">3</td>
<td align="right">.22%</td>
<td align="right">.17%</td>
</tr>
</table>
<p>Mid-Major组销量前5名如下。</p>
<table border="1">
<tr>
<td>O&#8217;Reilly</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://oreil.ly/fG6e6X">R in a Nutshell: A Desktop Quick Reference</a></span></td>
</tr>
<tr>
<td>Prentice Hall</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://amzn.to/ieoRUn">Using SPSS for Windows and Macintosh: Analyzing and Understanding Data</a></span></td>
</tr>
<tr>
<td>SAS Press</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://amzn.to/hmOu0D">The Little SAS Book: A Primer, Fourth Edition</a></span></td>
</tr>
<tr>
<td>Open University Press</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://amzn.to/eJieRq">SPSS Survival Manual: A Step by Step Guide to Data Analysis Using SPSS for Windows</a></span></td>
</tr>
<tr>
<td>Sams</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://amzn.to/gYfwfO">Mastering Unreal Technology, Volume I: Introduction to Level Design with Unreal Engine 3</a></span></td>
</tr>
</table>
<h3>Mid-Minor组的编程语言（2010年销量在1,682-2,999之间）</h3>
<p>函数式编程语言是这个组中的亮点，比如F#、Scals和Lisp等。函数式编程语言类图书的年增长率达到了喜人的51.38%，2010年共销售了7,648册，而2009年这个数字只有3,718册。</p>
<table border="1">
<tr>
<td align="center"><b>*Mid-Minor*</b></td>
<td colspan="2" align="center"><b>U N I T S</b></td>
<td colspan="2" align="center"><b>T I T L E S</b></td>
<td colspan="2" align="center"><b>M A R K E T S H A R E</b></td>
</tr>
<tr>
<td align="center"><b>Language</b></td>
<td align="center"><b>2010 Units</b></td>
<td align="center"><b>2009 Units</b></td>
<td align="center"><b>2010 Titles</b></td>
<td align="center"><b>2009 Titles</b></td>
<td align="center"><b>10Mkt Share</b></td>
<td align="center"><b>09Mkt Share</b></td>
</tr>
<tr>
<td>F#</td>
<td align=right>2,905</td>
<td align=right>1,095</td>
<td align=right>6</td>
<td align=right>5</td>
<td align=right>0.21%</td>
<td align=right>0.08%</td>
</tr>
<tr>
<td>Scala</td>
<td align=right>2,531</td>
<td align=right>3,946</td>
<td align=right>5</td>
<td align=right>5</td>
<td align=right>0.18%</td>
<td align=right>0.28%</td>
</tr>
<tr>
<td>Groovy</td>
<td align=right>2,452</td>
<td align=right>3,972</td>
<td align=right>7</td>
<td align=right>8</td>
<td align=right>0.18%</td>
<td align=right>0.28%</td>
</tr>
<tr>
<td>Alice</td>
<td align=right>2,441</td>
<td align=right>2,472</td>
<td align=right>10</td>
<td align=right>9</td>
<td align=right>0.18%</td>
<td align=right>0.17%</td>
</tr>
<tr>
<td>Blitzmax</td>
<td align=right>1,836</td>
<td align=right>2,603</td>
<td align=right>2</td>
<td align=right>2</td>
<td align=right>0.13%</td>
<td align=right>0.18%</td>
</tr>
<tr>
<td>AppleScript</td>
<td align=right>1,787</td>
<td align=right>3,994</td>
<td align=right>4</td>
<td align=right>6</td>
<td align=right>0.13%</td>
<td align=right>0.28%</td>
</tr>
<tr>
<td>VHDL</td>
<td align=right>1,785</td>
<td align=right>1,733</td>
<td align=right>18</td>
<td align=right>15</td>
<td align=right>0.13%</td>
<td align=right>0.12%</td>
</tr>
<tr>
<td>Bash</td>
<td align=right>1,715</td>
<td align=right>183</td>
<td align=right>2</td>
<td align=right>1</td>
<td align=right>0.12%</td>
<td align=right>0.01%</td>
</tr>
<tr>
<td>Lisp</td>
<td align=right>1,684</td>
<td align=right>309</td>
<td align=right>4</td>
<td align=right>6</td>
<td align=right>0.12%</td>
<td align=right>0.02%</td>
</tr>
<tr>
<td>LabView</td>
<td align=right>1,682</td>
<td align=right>658</td>
<td align=right>3</td>
<td align=right>1</td>
<td align=right>0.12%</td>
<td align=right>0.05%</td>
</tr>
</table>
<p>Mid-Minor组中销量前5名如下。</p>
<table border="1">
<tr>
<td>Prentice-Hall</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://amzn.to/hfmOnc">Learning To Program with Alice</a></span></td>
</tr>
<tr>
<td>Artima</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://amzn.to/gWvAii">Programming in Scala: A Comprehensive Step-by-step Guide</a></span></td>
</tr>
<tr>
<td>No Starch Press</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://amzn.to/huBOGn">Land of Lisp: Learn to Program in Lisp, One Game at a Time!</a></span></td>
</tr>
<tr>
<td>Prentice-Hall</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://amzn.to/gzP5tU">LabVIEW 2009 Student Edition</a></span></td>
</tr>
<tr>
<td>Manning</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://amzn.to/gsTu72">Real World Functional Programming: With Examples in F# and C#</a></span></td>
</tr>
</table>
<h3>Minor组的编程语言（2010年销量在1,000-1,680之间）</h3>
<p>这个组10门语言中有6种在2010年的销量减少了。总体来看，销量比上一年下降了约20%。其中，最吸引眼球的是Mathematica，很大程度归功于Mathematica Cookbook这本书。与Mid-Minor组一样，这个组仍然是函数式编程语言的主战场，但它们在这个组里表现平平。</p>
<table border="1">
<tr>
<td align="center"><b>*Minor*</b></td>
<td colspan="2" align="center"><b>U N I T S</b></td>
<td colspan="2" align="center"><b>T I T L E S</b></td>
<td colspan="2" align="center"><b>M A R K E T S H A R E</b></td>
</tr>
<tr>
<td align="center"><b>Language</b></td>
<td align="center"><b>2010 Units</b></td>
<td align="center"><b>2009 Units</b></td>
<td align="center"><b>2010 Titles</b></td>
<td align="center"><b>2009 Titles</b></td>
<td align="center"><b>10Mkt Share</b></td>
<td align="center"><b>09Mkt Share</b></td>
</tr>
<tr>
<td>Mathematica</td>
<td align=right>1,675</td>
<td align=right>900</td>
<td align=right>9</td>
<td align=right>4</td>
<td align=right>0.12%</td>
<td align=right>0.06%</td>
</tr>
<tr>
<td>Erlang</td>
<td align=right>1,513</td>
<td align=right>2,276</td>
<td align=right>3</td>
<td align=right>2</td>
<td align=right>0.11%</td>
<td align=right>0.16%</td>
</tr>
<tr>
<td>Scheme</td>
<td align=right>1,479</td>
<td align=right>1,364</td>
<td align=right>8</td>
<td align=right>7</td>
<td align=right>0.11%</td>
<td align=right>0.10%</td>
</tr>
<tr>
<td>FBML</td>
<td align=right>1,367</td>
<td align=right>2,335</td>
<td align=right>5</td>
<td align=right>4</td>
<td align=right>0.10%</td>
<td align=right>0.16%</td>
</tr>
<tr>
<td>Clojure</td>
<td align=right>1,332</td>
<td align=right>1,460</td>
<td align=right>2</td>
<td align=right>1</td>
<td align=right>0.10%</td>
<td align=right>0.10%</td>
</tr>
<tr>
<td>AWK</td>
<td align=right>1,200</td>
<td align=right>1,642</td>
<td align=right>2</td>
<td align=right>2</td>
<td align=right>0.09%</td>
<td align=right>0.12%</td>
</tr>
<tr>
<td>Nxt-g</td>
<td align=right>1,172</td>
<td align=right>969</td>
<td align=right>4</td>
<td align=right>1</td>
<td align=right>0.08%</td>
<td align=right>0.07%</td>
</tr>
<tr>
<td>Scratch</td>
<td align=right>1,112</td>
<td align=right>674</td>
<td align=right>2</td>
<td align=right>2</td>
<td align=right>0.08%</td>
<td align=right>0.05%</td>
</tr>
<tr>
<td>Latex</td>
<td align=right>1,099</td>
<td align=right>1,623</td>
<td align=right>6</td>
<td align=right>5</td>
<td align=right>0.08%</td>
<td align=right>0.11%</td>
</tr>
<tr>
<td>Haskell</td>
<td align=right>1,051</td>
<td align=right>2,274</td>
<td align=right>5</td>
<td align=right>3</td>
<td align=right>0.08%</td>
<td align=right>0.16%</td>
</tr>
</table>
<p>Minor组语言中销售排名前5的图书如下。</p>
<table border="1">
<tr>
<td>O&#8217;Reilly</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://oreil.ly/hULgvs">Mathematica Cookbook</a></span></td>
</tr>
<tr>
<td>O&#8217;Reilly</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://oreil.ly/eQBjua">ERLANG Programming</a></span></td>
</tr>
<tr>
<td>O&#8217;Reilly</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://oreil.ly/hLGsKr">Real World Haskell</a></span></td>
</tr>
<tr>
<td>Pragmatic</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://oreil.ly/ecRcnT">Programming Clojure</a></span></td>
</tr>
<tr>
<td>O&#8217;Reilly</td>
<td><span style="color: #0000EE; font-style: italic; text-decoration: underline;"><a href="http://oreil.ly/eQwc9L">sed &#038; awk</a></span></td>
</tr>
</table>
<h3>Linelist 组的编程语言（2010年销量在399-999之间）</h3>
<p>虽然销售总量很少，但这个组里的10门语言中仍然有6门在2010年实现了增长。这个组的年销售下降幅度大约为-0.81%。后面并没有列出畅销书的名录，因为这个组整体都还谈不上畅销。</p>
<h3>TheRest组的编程语言（2010年销量少于400）</h3>
<p>最后是2010年销量低于400册的语言。这些语言按降序排列如下：autolisp、unity、x++、cfml、inform、mysql spl、blitz3d、q、nxt、gml、pure data、javafx、rpg、cobol、nxc、minitab、ml、boo、ada、fortran、octave、jcl、racket、jsl、idl、cfscript、abap、verilog、m、smalltalk、mumps、go、windows script、egl、c/al、realbasic、bondi、cl、cs2、eiffel、ocaml、xquery。</p>
<p>接下来，第五部分将关注电子图书销售。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/02/25/2010-book-market-of-usa-4-2265.html/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>2010年美国计算机图书市场报告三：出版商</title>
		<link>http://www.cn-cuckoo.com/2011/02/23/2010-book-market-of-usa-3-2270.html</link>
		<comments>http://www.cn-cuckoo.com/2011/02/23/2010-book-market-of-usa-3-2270.html#comments</comments>
		<pubDate>Wed, 23 Feb 2011 14:46:39 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[出版]]></category>
		<category><![CDATA[编程技术]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2270</guid>
		<description><![CDATA[http://radar.oreilly.com/2011/02/2010-book-market-3.html Mike Hendrickson 2011-2-17 报告内容 第一部分：市场综述 第二部分：分类市场 第三部分：出版商 第四部分：编程语言 第五部分：完结篇及数字出版 下载完整版（PDF） 这一部分主要以2009年作为对比分析2010年出版商的经营情况。下面两张饼图展示了2009年和2010年各大出版商的经营业绩。最值得注意的是，Wiley继续稳坐最大出版商的位置（占图书销售量份额的32%），而Pearson和O&#8217;Reilly各掉了1%，分别被Cengage和McGraw Hill拿走。（后面将会分析收入份额。） 2009 Pub Share 2010 Pub Share 可能有人不太熟悉这些排名靠前的出版商，那是因为这些大型出版集团几年来收购、成立、拆分出了很多小出版公司。而往往这些小出版公司才是读者心目中最熟悉的品牌。比如说，你买了一本Peachpit或Sams出的书，书脊上印的都是Peachpit和Sams，而非Pearson，但后者拥有前两家出版公司。对O&#8217;Relly来说，任何不打“O&#8217;Reilly”标志的出版公司都是他们的发行合作伙伴，而不属于O&#8217;Reilly。至于构成各大出版商的小出版公司的市场份额，也会在本文后面以饼图的形式详细给出。 下面来看一下各大出版商两年的市场表现情况。以下表格中包含了几组有趣的对比性数据。 Publisher 2010 Units 2009 Units 2010 Title Count 2009 Title Count 2010 Efficiency 2009 Efficiency Wiley 1,887,493 1,904,859 1,538 1,468 1.65 1.61 O&#8217;Reilly 1,404,607 1,577,838 1,145 1,185 1.65 1.65 Pearson 1,386,301 1,511,855 1,934 1,936 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://radar.oreilly.com/2011/02/2010-book-market-3.html">http://radar.oreilly.com/2011/02/2010-book-market-3.html</a><br />
Mike Hendrickson<br />
2011-2-17</p>
<div style="float:right; border:1px solid #ddd;border-width:0 0 1px 1px;padding:0 .5em;margin:0 0 0 .5em;">
<p style="font-weight:bold;">报告内容</p>
<ol>
<li><a href="http://www.cn-cuckoo.com/2011/02/26/2010-book-market-of-usa-1-2287.html">第一部分：市场综述</a></li>
<li><a href="http://www.cn-cuckoo.com/2011/02/23/2010-book-market-of-usa-2-2329.html">第二部分：分类市场</a></li>
<li><a href="http://www.cn-cuckoo.com/2011/02/23/2010-book-market-of-usa-3-2270.html">第三部分：出版商</a></li>
<li><a href="http://www.cn-cuckoo.com/2011/02/23/2010-book-market-of-usa-4-2265.html">第四部分：编程语言</a></li>
<li><a href="http://www.cn-cuckoo.com/2011/02/25/2010-book-market-of-usa-5-2279.html">第五部分：完结篇及数字出版</a></li>
</ol>
<div style="text-align:center;">
<a href="http://u.115.com/file/f661fc6f86"><br />
<img class="colorbox-2270"  style="border:1px solid #eee;" src="http://ww1.sinaimg.cn/large/61baa48djw6deqves2ryvj.jpg"/><br />
</a><br />
<a href="http://u.115.com/file/f661fc6f86">下载完整版（PDF）</a>
</div>
</div>
<p>这一部分主要以2009年作为对比分析2010年出版商的经营情况。下面两张饼图展示了2009年和2010年各大出版商的经营业绩。最值得注意的是，Wiley继续稳坐最大出版商的位置（占图书销售量份额的32%），而Pearson和O&#8217;Reilly各掉了1%，分别被Cengage和McGraw Hill拿走。（后面将会分析收入份额。）</p>
<h3>2009 Pub Share</h3>
<p><img class="colorbox-2270"  src="http://radar.oreilly.com/upload/2011/01/Pub2009.png"/></p>
<h3>2010 Pub Share</h3>
<p><img class="colorbox-2270"  src="http://radar.oreilly.com/upload/2011/01/Pub2010.png"/></p>
<p>可能有人不太熟悉这些排名靠前的出版商，那是因为这些大型出版集团几年来收购、成立、拆分出了很多小出版公司。而往往这些小出版公司才是读者心目中最熟悉的品牌。比如说，你买了一本Peachpit或Sams出的书，书脊上印的都是Peachpit和Sams，而非Pearson，但后者拥有前两家出版公司。对O&#8217;Relly来说，任何不打“O&#8217;Reilly”标志的出版公司都是他们的发行合作伙伴，而不属于O&#8217;Reilly。至于构成各大出版商的小出版公司的市场份额，也会在本文后面以饼图的形式详细给出。<br />
<span id="more-2270"></span><br />
下面来看一下各大出版商两年的市场表现情况。以下表格中包含了几组有趣的对比性数据。</p>
<table border="1" cellpadding="1" cellspacing="1">
<tr>
<td align=center><b>Publisher</b></td>
<td align=center><b>2010 Units</b></td>
<td align=center><b>2009 Units</b></td>
<td align=center><b>2010 Title Count</b></td>
<td align=center><b>2009 Title Count</b></td>
<td align=center><b>2010 Efficiency</b></td>
<td align=center><b>2009 Efficiency</b></td>
</tr>
<tr>
<td>Wiley</td>
<td align=right>1,887,493</td>
<td align=right>1,904,859</td>
<td align=right>1,538</td>
<td align=right>1,468</td>
<td align=right>1.65</td>
<td align=right>1.61</td>
</tr>
<tr>
<td>O&#8217;Reilly</td>
<td align=right>1,404,607</td>
<td align=right>1,577,838</td>
<td align=right>1,145</td>
<td align=right>1,185</td>
<td align=right>1.65</td>
<td align=right>1.65</td>
</tr>
<tr>
<td>Pearson</td>
<td align=right>1,386,301</td>
<td align=right>1,511,855</td>
<td align=right>1,934</td>
<td align=right>1,936</td>
<td align=right>0.97</td>
<td align=right>0.97</td>
</tr>
<tr>
<td>McGrawHill</td>
<td align=right>276,439</td>
<td align=right>255,667</td>
<td align=right>466</td>
<td align=right>454</td>
<td align=right>0.80</td>
<td align=right>0.70</td>
</tr>
<tr>
<td>Apress</td>
<td align=right>200,267</td>
<td align=right>212,614</td>
<td align=right>423</td>
<td align=right>389</td>
<td align=right>0.64</td>
<td align=right>0.68</td>
</tr>
<tr>
<td>Cengage</td>
<td align=right>167,020</td>
<td align=right>143,521</td>
<td align=right>676</td>
<td align=right>644</td>
<td align=right>0.33</td>
<td align=right>0.28</td>
</tr>
<tr>
<td>Reed Elsevier</td>
<td align=right>140,708</td>
<td align=right>128,657</td>
<td align=right>384</td>
<td align=right>355</td>
<td align=right>0.49</td>
<td align=right>0.45</td>
</tr>
<tr>
<td>Lightning Source</td>
<td align=right>67,620</td>
<td align=right>61,676</td>
<td align=right>412</td>
<td align=right>325</td>
<td align=right>0.22</td>
<td align=right>0.23</td>
</tr>
<tr>
<td><b>Sum/Avg</b></td>
<td align=right><strong>5,530,455</strong></td>
<td align=right><b>5,796,687</b></td>
<td align=right><b>6,978</b></td>
<td align=right><b>6,756</b></td>
<td align=right><strong>0.84</strong></td>
<td align=right><b>.82</b></td>
</tr>
</table>
<p>这些数据说明什么问题？首先，最大的三家出版商（每年销售册数100万以上）业绩全部下滑。其次，前8名里有4家业绩攀升：McGraw Hill、Cengage、Reed Elsevier和Lightning Source在2010年都有适度增长。总体上看，2010年前8家出版商的出书品种虽然增加了222个，但图书销售量却减少了266,232册。</p>
<h2>关于市场份额与单品效率</h2>
<p>衡量出版商经营水平的一个典型指标，就是图书销售量的市场份额，这也是我们一直在讨论的问题。但是，还有一个更好的度量指标，就是出版商获得的可比较的销售份额是出了多少本书换来的。这个比例是用出书品种份额比上销量份额。解释一下：如果某出版商出版的图书在Bookscan Top 3000中占15%，而该出版商的销量份额也是15%，那么这个比例就是1:1，其单品效率为1.0。如果品种份额为20%，而销量份额是10%，单品效率就是0.5。单品效率1.0代表市场平均水平：100%的出版品种带来了100%的图书销售。以较少的品种实现其销量份额的出版商具有较高的效率。只有两个出版商的效率超过了1：Wiley和O&#8217;Reilly。</p>
<p>单品效率小于1.0的出版商的表现就是在Bookscan监控数据中拥有很多图书品种，但实际卖出的图书却不够多。但需要注意一点，有些出版商拥有不少长销不衰的书，这些书会影响数据。一般来说，老书的销量会逐年递减，但也不是所有书都这样。不少书后续年份的销量并不亚于刚上市的年份。Head First Design Patterns就是一个例子，其销量仍然位居大多数新书之上。为此，可以把单品效率看一种频率比，而不是真正用它去衡量出版效率，毕竟出一本书能卖好几年才是真正有效率。真正的效率指标应该考虑所有出版商出版的所有图书，以及这些图书中有多少进了前3000名。有的出版商还有一些书根本就没有进入过前3000名，数据库里没有这些书的数据，因而我们就无法统计它们（很难说它们对效率的贡献）。</p>
<h2>关于长销书</h2>
<p>下面表格中展示了一些出版公司拥有的长销书比例。我们是怎么统计长销书的呢？我们会按照版权日期给一本书打分，分为16年以上（最高分）、10-16年、5-10年以及5年以内（零分，因为还没有证明其长销）。在为每本书打分之后，就可以统计出2004到2010年每家公司的长销书比例。统计发现，当然也是意料之中的，拥有长销书最多的前三家出版公司（Wiley、Addison-Wesley和Prentice Hall）都有稳定的学术遗产（a strong academic heritage ？）。</p>
<table border="1" cellpadding="1" cellspacing="1">
<tr>
<td><b>Imprint</b></td>
<td><b>% Evergreen</b></td>
</tr>
<tr>
<td>John Wiley</td>
<td align="right">11.47%</td>
</tr>
<tr>
<td>Addison-Wesley</td>
<td align="right">11.07%</td>
</tr>
<tr>
<td>Prentice Hall</td>
<td align="right">10.85%</td>
</tr>
<tr>
<td>O&#8217;Reilly</td>
<td align="right">9.63%</td>
</tr>
<tr>
<td>For Dummies</td>
<td align="right">8.43%</td>
</tr>
<tr>
<td>Sams</td>
<td align="right">7.79%</td>
</tr>
<tr>
<td>Que</td>
<td align="right">7.01%</td>
</tr>
<tr>
<td>Peachpit Press</td>
<td align="right">5.62%</td>
</tr>
<tr>
<td>McGraw-Hill/Osborne</td>
<td align="right">5.50%</td>
</tr>
<tr>
<td>Wrox</td>
<td align="right">3.66%</td>
</tr>
<tr>
<td>APress</td>
<td align="right">2.92%</td>
</tr>
</table>
<p>现在我们对单品效率和长销书的情况有了基本的了解，下面我们就深入分析一下这些出版公司2010年的经营业绩，先从Wiley、Pearson和O&#8217;Reilly这三大出版商入手。这一点很重要，因为你买书的时候通常只会看书上印的出版公司的名字，至少背后的出版商是谁，恐怕你不会在意。（如果想知道出版商是谁，可以翻到版权页找一找，但O&#8217;Reilly除外，因为我们其他出版公司都是发行合作伙伴。换句话说，O&#8217;Reilly会替这些合作伙伴提供一些销售和发行服务，但并不拥有这些公司，不像Pearson和Wiley那样。）</p>
<p>#1 Wiley<br />
<img class="colorbox-2270"  src="http://radar.oreilly.com/upload/2011/01/Wiley2010.jpg"/></p>
<p>#2 O&#8217;Reilly Media<br />
<img class="colorbox-2270"  src="http://radar.oreilly.com/upload/2011/01/ORM2010.jpg"/></p>
<p>#3 Pearson<br />
<img class="colorbox-2270"  src="http://radar.oreilly.com/upload/2011/01/pearson2010.jpg"/></p>
<p>2010年，O&#8217;Reilly Media携所有出版和发行伙伴成为第二大出版商。我们的数据中包含了来自所有合作伙伴的贡献，以及它们加入各自出版集团的大致年份。很大程度上，我们与Microsoft Press达成的协议是让O&#8217;Reilly Media一跃成为第二大技术出版商的根本原因。当然，这个第二名领先第三名Pearson的优势几乎是微不足道的（只有不到15,000册）。Wiley仍然是第一大出版商，而且应对市场下滑的能力好像更强一些，这主要归功于Dummies品牌及其广泛的领域。下面的趋势图展示了三大技术图书出版商几年来各自的增长情况。</p>
<p><img class="colorbox-2270"  src="http://radar.oreilly.com/upload/2011/01/BigThree_Years.jpg"/></p>
<p>了解了构成三大出版商的出版公司之后，我们接下来再看一看所有这些出版公司各自的市场份额情况。下面的柱形图展示了前20家出版公司，以及它们之间的业绩对比。其中前10家2010年的图书销量减少了422,814册，而2009年技术图书的市场表现也并不好。当然，还有一些图中没有列出的中小型出版公司同样占有相当的市场份额。从出版公司的角度来看，O&#8217;Reilly的市场份额居于Dummies之后。</p>
<p><img class="colorbox-2270"  src="http://radar.oreilly.com/upload/2011/01/top20Units.jpg"/></p>
<p>这张图能够说明什么问题呢？第一，处于市场前10的出版公司基本上没变。换句话说，排名在前的出版公司仍然排名在前。实际上，在这前20家出版公司中，只有7家的图书销量比2009年略有增加，只有8家的销售码洋比2009年有所增长（见下面的柱形图）。唯一从前10名中下降的是Apress，它从第10变成了第11。其中，Sybex、Wrox和Course Technology依次是销量增长最多的三家公司，而Wrox、Course Technology和Sybex依次是百分比提高最多的三家公司。应该说，Sybex上一年的基数最大，因此市场份额百分比增长并不突出。而另外两家的码洋规模都少了一半，因此它们的销量增长对百分比增长的拉动更为明显。</p>
<p>在分类剖析各家出版公司之前，我们再从码洋角度看看这些出版公司的业绩。计算数据的公式很简单：销量×定价 = 码洋。就算有折扣、促销及其他因素影响计算结果的精确度，但应该也是相当接近实际的。再不然，你可以把码洋看成零售价值。因此，这一次是从收入角度排名，而且，是从出版公司层面，按照码洋来排序的。显然，与上面按销量排名的图一比，你马上就能发现非常大的变化。Microsoft Press这次成了产值最高的出版公司，其次是O&#8217;Reilly，然后是Dummies。前20名中变动最大的是Addison-Wesley，按码洋计算一下子让它从第8跃升至第4。相反，Wiley的Visual出版公司则从按销量排名的第10跌落至按码洋排名的第17位。</p>
<p><img class="colorbox-2270"  src="http://radar.oreilly.com/upload/2011/01/top20Dollars.jpg"/></p>
<h2>出版门类分析</h2>
<p>在了解了这些出版公司在2010年的经营情况之后，下面我们就来看看这些出版公司涉足的出版门类，以及它们的优势所在。Dummies和O&#8217;Reilly拥有的出版门类是最多样化的，而且他们在涉足的任何门类中都取得了不错的成绩。在商业应用和消费者操作系统类别中，Dummies无疑是王者，而O&#8217;Reilly则在系统与程序设计类别中超越了Microsoft Press。下面这张图也说明，Addison-Wesley基本上只出版系统与程序设计类图书。而这也正是某些出版商的策略：他们自己的某家出版公司会专注于一或两个门类。这一策略是好是坏尚无定论，但Addison-Welsey在2010年码洋的增长可能是要归功于这种专注的。可以得出一个结论，在某个领域没有太多技术拉动的情况下，经营门类不够多样化会导致出版商/出版公司更容易受到市场下滑的冲击。</p>
<p><img class="colorbox-2270"  src="http://radar.oreilly.com/upload/2011/01/CF_Imprint_top10Units.jpg"/></p>
<h3>出版门类及位列第一的出版商</h3>
<p>以下出版门类的数据图都是2010年的，表格中列出了每家出版商的出书品种及总销量。每个门类也分别给出了2010年度最畅销的图书书目。</p>
<h2>门类：系统与程序设计</h2>
<p>在这个门类中，O&#8217;Reilly在各大出版商中占有最多份额，Pearson以微弱差距位居第二。如果按照出版公司再细分一下，就很容易看谁是真正的市场主导者了。排名前6的出版公司分别是O&#8217;Reilly占13.66%、Microsoft Press占10.26%、Addison-Wesley占9.65%、For Dummies占7.04%、Apress占6.67%、Prentice Hall占5.48%。通过这张图看不出来的是，前几大出版商的市场份额都下降了两三个百分点，这说明市场的增长源自排名居中的出版公司。</p>
<p><img class="colorbox-2270"  src="http://radar.oreilly.com/upload/2011/01/2010_SysProg.png"/></p>
<p>从下面的表格中可以看出，O&#8217;Reilly的图书销量最多，单品效率也最高。这两个指标的组合是比较良性的。换句话说，虽然我们出版的图书品种并不少，但我们效率也明显高于市场平均值。</p>
<h3>系统与程序设计类：出版商市场份额 （2010.1.1-2010.12.31）</h3>
<table border="1" cellpadding="1" cellspacing="1">
<tr>
<td><b>Publisher</b></td>
<td><b>Units</b></td>
<td><b>Title Count</b></td>
<td><b>Units/Title</b></td>
<td><b>Efficiency</b></td>
</tr>
<tr>
<td>O&#8217;Reilly</td>
<td align="right">557,876</td>
<td align="right">637</td>
<td align="right">876</td>
<td align="right">1.63</td>
</tr>
<tr>
<td>Pearson</td>
<td align="right">525,897</td>
<td align="right">960</td>
<td align="right">548</td>
<td align="right">1.02</td>
</tr>
<tr>
<td>Wiley</td>
<td align="right">386,809</td>
<td align="right">553</td>
<td align="right">699</td>
<td align="right">1.30</td>
</tr>
<tr>
<td>Apress</td>
<td align="right">114,705</td>
<td align="right">236</td>
<td align="right">512</td>
<td align="right">0.95</td>
</tr>
<tr>
<td>McGraw Hill</td>
<td align="right">111,980</td>
<td align="right">236</td>
<td align="right">474</td>
<td align="right">0.88</td>
</tr>
<tr>
<td>Cengage</td>
<td align="right">64,580</td>
<td align="right">252</td>
<td align="right">256</td>
<td align="right">0.48</td>
</tr>
<tr>
<td>Lightning Source</td>
<td align="right">34,674</td>
<td align="right">188</td>
<td align="right">184</td>
<td align="right">.34</td>
</tr>
<tr>
<td>Reed Elsevier</td>
<td align="right">31,957</td>
<td align="right">188</td>
<td align="right">170</td>
<td align="right">0.32</td>
</tr>
</table>
<p>注意：这个门类中包含“编程语言”和“程序设计”，这两个子类别2010年销量超过了2009年。2010年系统与程序设计类领先的图书及出版商如下：</p>
<ol>
<li><i>PMP Exam Prep: Rita&#8217;s Course in a Book for Passing the PMP Exam</i> （这本书位居榜首已经好几年了)(RMC)</li>
<li><i><a href="http://oreil.ly/e0iDsN">MCTS Self-Paced Training Kit : Configuring Windows 7</a></i>(Microsoft Press)</li>
<li><i>CISSP Certification All-in-One Exam Guide, 5th Ed.</i>(McGraw Hill)</li>
<li><i>CCNA Official Exam Certification Library, 3rd Ed.</i>(Cisco Press)</li>
<li><i><a href="http://oreil.ly/eTKrN9">Head First Java, 2nd Edition</a></i>(O&#8217;Reilly)</li>
</ol>
<h2>门类：Web设计与开发</h2>
<p>在这个门类中，Wiley的市场份额是各家出版商中最大的，Pearson紧随其后。如果再细化到出版公司的层面，这张图的序列会发生一些变化。位于前6名的出版公司变成了O&#8217;Reilly占21.11%、Dummies占13.30%、Sams占6.25%、Wiley占5.92%、New Riders占5.82%、Peachpit占5.40%。</p>
<p><img class="colorbox-2270"  src="http://radar.oreilly.com/upload/2011/01/2010_WebDev.png"/></p>
<p>从下面这张表中可以看出，Pearson出书品种最多，其业绩在这个门类中也相当突出。在Web设计与开发这个类别中，前几大出版商的单品效率通常都高于平均值1.0。但这里只有前三家出版商的效率超过了1.0这个临界值。（这说明还有很多二线出版商的效率低于1.0，但这张表并没有体现出现来。）2010年，这个门类的销量减少了25,000册，但出书品种多了21种。市场下滑也影响了这个门类及相应出版商的效率。</p>
<h3>Web设计与开发：出版商市场份额 （2010.1.1-2010.12.31）</h3>
<table border="1" cellpadding="1" cellspacing="1">
<tr>
<td>Publisher</td>
<td>Units</td>
<td>Title Count</td>
<td>Units/Title</td>
<td>Efficiency</td>
</tr>
<tr>
<td>Wiley</td>
<td align="right">234,853</td>
<td align="right">219</td>
<td align="right">1,072</td>
<td align="right">1.48</td>
</tr>
<tr>
<td>Pearson</td>
<td align="right">232,547</td>
<td align="right">287</td>
<td align="right">810</td>
<td align="right">1.11</td>
</tr>
<tr>
<td>O&#8217;Reilly</td>
<td align="right">221,876</td>
<td align="right">211</td>
<td align="right">1,052</td>
<td align="right">1.45</td>
</tr>
<tr>
<td>Apress</td>
<td align="right">48,812</td>
<td align="right">124</td>
<td align="right">394</td>
<td align="right">0.54</td>
</tr>
<tr>
<td>Lightning Source</td>
<td align="right">16,345</td>
<td align="right">104</td>
<td align="right">157</td>
<td align="right">.22</td>
</tr>
</table>
<p>Web设计与开发类中领先的图书和出版商如下：</p>
<ol>
<li><i>Don&#8217;t Make Me Think: A Common Sense Approach to Web Usability, 2nd Ed.</i>(New Riders&#8217; )</li>
<li><i><a href="http://oreil.ly/hPDptg">Head First HTML with CSS &amp; XHTML</a></i>(O&#8217;Reilly)</li>
<li><i><a href="http://oreil.ly/fE8dpT">CSS: The Missing Manual</a></i>(O&#8217;Reilly)</li>
<li><i>HTML, XHTML, and CSS: Visual Quickstart, 6th Ed.</i>(Peachpit)</li>
<li><i>WordPress For Dummies: 2nd Ed.</i>(Wiley)</li>
</ol>
<h2>门类：商业应用</h2>
<p>在这个类别中，拥有最大市场份额的是Wiley，而O&#8217;Reilly（抱歉，图中没有显示出O&#8217;Reilly的21%）已经超过Pearson，位居第二。从出版公司的层面上看，这张图的排名也会发生变化。前6名的出版公司分别是Dummies占28.34%、Microsoft Press占14.72%、McGraw Hill/Osborne占7.06%、O&#8217;Reilly占6.29、John Wiley占5.74%、Que占4.18%。</p>
<p><img class="colorbox-2270"  src="http://radar.oreilly.com/upload/2011/02/2010_BisApps.png"/></p>
<h3>商业应用：出版商市场份额 （2010.1.1-2010.12.31）</h3>
<table border="1" cellpadding="1" cellspacing="1">
<tr>
<td><b>Publisher</b></td>
<td><b>Units</b></td>
<td><b>Title Count</b></td>
<td><b>Units/Title</b></td>
<td><b>Efficiency</b></td>
</tr>
<tr>
<td>Wiley</td>
<td align="right">566,391</td>
<td align="right">386</td>
<td align="right">1,467</td>
<td align="right">1.74</td>
</tr>
<tr>
<td>O&#8217;Reilly</td>
<td align="right">278,058</td>
<td align="right">162</td>
<td align="right">1,716</td>
<td align="right">2.04</td>
</tr>
<tr>
<td>Pearson</td>
<td align="right">199,261</td>
<td align="right">296</td>
<td align="right">673</td>
<td align="right">0.80</td>
</tr>
<tr>
<td>McGraw Hill</td>
<td align="right">96,806</td>
<td align="right">121</td>
<td align="right">800</td>
<td align="right">0.95</td>
</tr>
<tr>
<td>Cengage</td>
<td align="right">102,034</td>
<td align="right">75</td>
<td align="right">1,360</td>
<td align="right">1.2</td>
</tr>
<tr>
<td>Cengage</td>
<td align="right">35,625</td>
<td align="right">200</td>
<td align="right">178</td>
<td align="right">0.21</td>
</tr>
<tr>
<td>Apress</td>
<td align="right">16,370</td>
<td align="right">38</td>
<td align="right">431</td>
<td align="right">0.51</td>
</tr>
</table>
<p>商业应用类中领先的图书及出版商如下：</p>
<ol>
<li><i>Facebook For Dummies</i>(Wiley)</li>
<li><i>Office 2007 All-in-One Desk Reference For Dummies</i>(Wiley)</li>
<li><i>Excel 2007 for Dummies</i>(Wiley)</li>
<li><i><a href="http://oreil.ly/dSIGDp">Microsoft Office Excel 2007 Step by Step</a></i>(Microsoft)</li>
<li><i>QuickBooks 2010 The Official Guide </i>(McGraw Hill)</li>
<li><i>Excel 2007 All-In-One Desk Reference For Dummies</i>(Wiley)</li>
</ol>
<h2>门类：消费者操作系统</h2>
<p>在这个门类中，我们看到Wiley占有最多的市场份额（达到了46%），其他出版商中，O&#8217;Reilly以22%居第二位，Pearson以17%稳稳坐在第三把交椅上。（抱歉，O&#8217;Reilly的百分比在图中被切掉了一点。）按照出版公司来看，这张图又会有变化。前6名的出版公司分别是Dummies占31.00%、O&#8217;Reilly占13.15%、Que占9.39%、Microsoft Press占8.52%、Wiley的Visual占7.19%。</p>
<p><img class="colorbox-2270"  src="http://radar.oreilly.com/upload/2011/02/ConOps.png"/></p>
<p>从下面表格中可以看出，Wiley出的书最多，单品效率也相对不错。O&#8217;Reilly的单品效率更高。这个门类中最突出的一点是，前6家出版公司中有4家单品销售量超过1,000册。在我看来，它意味着这个门类支撑着很多大销售商的出货量，而绝不仅仅是零售渠道偶然的成功。从下面畅销书的排行可以看出，这个类别的突出表现很大程度上得益于Windows 7，而iPad: The Missing Manual出现在2010年畅销榜中实属意外。</p>
<h3>消费者操作系统：出版商市场份额 （2010.1.1-2010.12.31）</h3>
<table border="1" cellpadding="1" cellspacing="1">
<tr>
<td><b>Publisher</b></td>
<td><b>Units</b></td>
<td><b>Title Count</b></td>
<td><b>Units/Title</b></td>
<td><b>Efficiency</b></td>
</tr>
<tr>
<td>Wiley</td>
<td align="right">490,682</td>
<td align="right">182</td>
<td align="right">2,696</td>
<td align="right">1.48</td>
</tr>
<tr>
<td>O&#8217;Reilly</td>
<td align="right">237,508</td>
<td align="right">62</td>
<td align="right">3,831</td>
<td align="right">2.11</td>
</tr>
<tr>
<td>Pearson</td>
<td align="right">184,497</td>
<td align="right">129</td>
<td align="right">1,430</td>
<td align="right">0.79</td>
</tr>
<tr>
<td>McGraw Hill</td>
<td align="right">48,684</td>
<td align="right">50</td>
<td align="right">974</td>
<td align="right">0.54</td>
</tr>
<tr>
<td>Cengage</td>
<td align="right">37,679</td>
<td align="right">86</td>
<td align="right">438</td>
<td align="right">0.24</td>
</tr>
<tr>
<td>Computer Step </td>
<td align="right">37,528</td>
<td align="right">24</td>
<td align="right">1,564</td>
<td align="right">.86</td>
</tr>
</table>
<p>消费者操作系统领域的畅销图书及其出版商分别是：</p>
<ol>
<li><i>Windows 7 For Dummies</i>(Wiley)</li>
<li><i>Windows 7 For Dummies Book + DVD Bundle</i>(Wiley)</li>
<li><i><a href="http://oreil.ly/fC1foB">Windows 7 Plain &#038; Simple</a></i>(Microsoft Press)</li>
<li><i><a href="http://oreilly.com/catalog/9780596529529/index.html">Mac OS X Leopard: The Missing Manual</a></i>(O&#8217;Reilly) </li>
<li><i><a href="http://oreil.ly/hYuUBK">Windows 7 Step by Step</a></i>(Microsoft Press)</li>
<li><i><a href="http://oreil.ly/hkAXOX">iPad: The Missing Manual</a></i>(O&#8217;Reilly)</li>
</ol>
<h2>门类：数字媒体</h2>
<p>在这个类别中，Pearson跃居第一，Wiley降至第二。而通过后面的表格可以看出，Pearson出版的图书最多，单品效率也相当不错。O&#8217;Reilly的单品效率和平均单品销量也都很高。这一点印证了我前面的说法，少出书多卖书才是出版之道。比如，下面的表格显示Reed Elsevier已经成为第三大出版商，但这个市场地位的获得，完全是建立在其出书量比O&#8217;Reilly高两倍的基础之上的。因此，它的单品效率比O&#8217;Reilly低了很多。如果考虑到Reed Elsvier有一本书的销量占到了其总销量的1/4，那么它的实际单品效率应该会更低。</p>
<p><img class="colorbox-2270"  src="http://radar.oreilly.com/upload/2011/02/DigigalMedia.png"/></p>
<h3>数字媒体：出版商市场份额 （2010.1.1-2010.12.31）</h3>
<table border="1" cellpadding="1" cellspacing="1">
<tr>
<td><b>Publisher</b></td>
<td><b>Units</b></td>
<td><b>Title Count</b></td>
<td><b>Units/Title</b></td>
<td><b>Efficiency</b></td>
</tr>
<tr>
<td>Pearson</td>
<td align="right">228,640</td>
<td align="right">186</td>
<td align="right">1,229</td>
<td align="right">1.27</td>
</tr>
<tr>
<td>Wiley</td>
<td align="right">173,616</td>
<td align="right">157</td>
<td align="right">1,106</td>
<td align="right">1.14</td>
</tr>
<tr>
<td>Reed Elsevier</td>
<td align="right">76,359</td>
<td align="right">110</td>
<td align="right">694</td>
<td align="right">0.72</td>
</tr>
<tr>
<td>O&#8217;Reilly</td>
<td align="right">74,235</td>
<td align="right">36</td>
<td align="right">2,062</td>
<td align="right">2.13</td>
</tr>
<tr>
<td>Cengage</td>
<td align="right">15,027</td>
<td align="right">47</td>
<td align="right">320</td>
<td align="right">0.33</td>
</tr>
</table>
<p>数字媒体领域的畅销图书及其出版商如下：</p>
<ol>
<li><i>Adobe Photoshop CS5 for Photographers</i>(Focal Press)</li>
<li><i>The Adobe Photoshop CS5 Book for Digital Photographers</i>(New Riders)</li>
<li><i>Adobe Photoshop CS4 Classroom in a Book</i>(Adobe Press)</li>
<li><i>Adobe Photoshop CS5 Classroom in a Book </i>(Adobe Press)</li>
<li><i><a href="http://oreil.ly/fSVT96">Photoshop Elements 8 for Windows: The Missing Manual</a></i>(O&#8217;Reilly)</li>
</ol>
<p>接下来，第四部分将详细分析编程语言类图书，而第五部分将重点关注电子图书销售。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/02/23/2010-book-market-of-usa-3-2270.html/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>2010年美国计算机图书市场报告二：分类市场</title>
		<link>http://www.cn-cuckoo.com/2011/02/22/2010-book-market-of-usa-2-2329.html</link>
		<comments>http://www.cn-cuckoo.com/2011/02/22/2010-book-market-of-usa-2-2329.html#comments</comments>
		<pubDate>Tue, 22 Feb 2011 15:27:54 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[出版]]></category>
		<category><![CDATA[原创]]></category>
		<category><![CDATA[移动开发]]></category>
		<category><![CDATA[编程技术]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2329</guid>
		<description><![CDATA[http://radar.oreilly.com/2011/02/2010-book-market-2.html Mike Hendrickson 2011-2-14 报告内容 第一部分：市场综述 第二部分：分类市场 第三部分：出版商 第四部分：编程语言 第五部分：完结篇及数字出版 下载完整版（PDF） 在这一部分，我们按照技术门类来分析一下计算机图书的销售情况。 在上一部分，我们把数据分成六大“门类”：系统与程序设计、Web设计与开发、商业应用、数字媒体应用、消费者操作系统与设备、IT人文（Computer Topics）。 这六大门类下面，是一级分类、二级分类、三级分类、四级分类，一共5层。比如说，系统与程序设计门类下面的一级分类有编程语言、数据库、软件工程、通用程序设计、安全，等等。 本部分将对比2010年与2009年的第四季度，也会将2010年与2009年的情况进行对比。 为了方便起见，下面给出了上一部分中展示过的Treemap，其中包含各个门类与一级门类2010年与2009年第四季度的对比。 这张图中的红、绿、黑色方块基本上反映了市场的波动情况。其中，代表高度增长领域的浅绿色方块非常少。但不要忘了这是2010年第四季度与2009年第四季度的对比。两个最大、最亮的绿色区域是“Android编程”和“Android消费者应用”，这两类图书从2008年微不足道的小方块成长为2010年相当可观的大市场。 下面的两张图可以反映出各图书门类历年的增长情况。第一张图是历年构成Top 3000的图书品种，而第二张图是历年来的图书销量。从中可以看出，“商业应用/人文”和“系统与程序设计”类图书的品种在2010年都增加了，但这两类图书的销量却是双双下跌的。“消费者操作系统与设备”是唯一一个出书品种和销量在2010年双增的门类。“系统与程序设计”是最大的一个门类，但其销售业绩也更加不稳定，2010年经历了最大的一次整体下滑。“系统与程序设计”是计算机图书市场的风向标，计算机（纸质）图书市场整体也是下滑的。在随后关于数字发行的部分中，我们还会展示一些更积极的信息。 历年的图书品种 历年的图书销量 下面这张表格列出了各个门类2009年到2010年的增长情况（YoY）、2009和2010年的排名情况（09Rand/10Rank）以及2009、2010年的市场份额百分比（09Share/10Share）。 门类 YoY Growth 09Rank 10Rank 09Share 10Share 商业应用 -05.10% 2nd 2nd 20.60% 21.00% IT人文及其他 04.09% 6th 6th 02.82% 03.15% 消费者操作系统 04.22% 4th 3rd 15.44% 17.27% 数字媒体 -18.32% 5th 5th 10.66% 09.65% 系统与程序设计 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://radar.oreilly.com/2011/02/2010-book-market-2.html">http://radar.oreilly.com/2011/02/2010-book-market-2.html</a><br />
Mike Hendrickson<br />
2011-2-14</p>
<div style="float:right; border:1px solid #ddd;border-width:0 0 1px 1px;padding:0 .5em;margin:0 0 0 .5em;">
<p style="font-weight:bold;">报告内容</p>
<ol>
<li><a href="http://www.cn-cuckoo.com/2011/02/26/2010-book-market-of-usa-1-2287.html">第一部分：市场综述</a></li>
<li><a href="http://www.cn-cuckoo.com/2011/02/23/2010-book-market-of-usa-2-2329.html">第二部分：分类市场</a></li>
<li><a href="http://www.cn-cuckoo.com/2011/02/23/2010-book-market-of-usa-3-2270.html">第三部分：出版商</a></li>
<li><a href="http://www.cn-cuckoo.com/2011/02/23/2010-book-market-of-usa-4-2265.html">第四部分：编程语言</a></li>
<li><a href="http://www.cn-cuckoo.com/2011/02/25/2010-book-market-of-usa-5-2279.html">第五部分：完结篇及数字出版</a></li>
</ol>
<div style="text-align:center;">
<a href="http://u.115.com/file/f661fc6f86"><br />
<img class="colorbox-2329"  style="border:1px solid #eee;" src="http://ww1.sinaimg.cn/large/61baa48djw6deqves2ryvj.jpg"/><br />
</a><br />
<a href="http://u.115.com/file/f661fc6f86">下载完整版（PDF）</a>
</div>
</div>
<p>在这一部分，我们按照技术门类来分析一下计算机图书的销售情况。</p>
<p>在上一部分，我们把数据分成六大“门类”：系统与程序设计、Web设计与开发、商业应用、数字媒体应用、消费者操作系统与设备、IT人文（Computer Topics）。</p>
<p>这六大门类下面，是一级分类、二级分类、三级分类、四级分类，一共5层。比如说，系统与程序设计门类下面的一级分类有编程语言、数据库、软件工程、通用程序设计、安全，等等。</p>
<p>本部分将对比2010年与2009年的第四季度，也会将2010年与2009年的情况进行对比。</p>
<p>为了方便起见，下面给出了上一部分中展示过的Treemap，其中包含各个门类与一级门类2010年与2009年第四季度的对比。</p>
<p><img class="colorbox-2329"  src="http://radar.oreilly.com/upload/2011/02/cat_yoy_QTR4.jpg"/></p>
<p>这张图中的红、绿、黑色方块基本上反映了市场的波动情况。其中，代表高度增长领域的浅绿色方块非常少。但不要忘了这是2010年第四季度与2009年第四季度的对比。两个最大、最亮的绿色区域是“Android编程”和“Android消费者应用”，这两类图书从2008年微不足道的小方块成长为2010年相当可观的大市场。<br />
<span id="more-2329"></span><br />
下面的两张图可以反映出各图书门类历年的增长情况。第一张图是历年构成Top 3000的图书品种，而第二张图是历年来的图书销量。从中可以看出，“商业应用/人文”和“系统与程序设计”类图书的品种在2010年都增加了，但这两类图书的销量却是双双下跌的。“消费者操作系统与设备”是唯一一个出书品种和销量在2010年双增的门类。“系统与程序设计”是最大的一个门类，但其销售业绩也更加不稳定，2010年经历了最大的一次整体下滑。“系统与程序设计”是计算机图书市场的风向标，计算机（纸质）图书市场整体也是下滑的。在随后关于数字发行的部分中，我们还会展示一些更积极的信息。</p>
<h2>历年的图书品种</h2>
<p><img class="colorbox-2329"  src="http://radar.oreilly.com/upload/2011/01/Cat_family_Titles.jpg"/></p>
<h2>历年的图书销量</h2>
<p><img class="colorbox-2329"  src="http://radar.oreilly.com/upload/2011/01/Cat_family_Units.jpg"/></p>
<p>下面这张表格列出了各个门类2009年到2010年的增长情况（YoY）、2009和2010年的排名情况（09Rand/10Rank）以及2009、2010年的市场份额百分比（09Share/10Share）。</p>
<table border="1">
<tbody>
<tr>
<td align=center><strong>门类</strong></td>
<td><strong>YoY Growth</strong></td>
<td><strong>09Rank</strong></td>
<td><strong>10Rank</strong></td>
<td><strong>09Share</strong></td>
<td><strong>10Share</strong></td>
</tr>
<tr>
<td>商业应用</td>
<td align=right>-05.10%</td>
<td align=right>2nd</td>
<td align=right>2nd</td>
<td align=right>20.60%</td>
<td align=right>21.00%</td>
</tr>
<tr>
<td>IT人文及其他</td>
<td align=right>04.09%</td>
<td align=right>6th</td>
<td align=right>6th</td>
<td align=right>02.82%</td>
<td align=right>03.15%</td>
</tr>
<tr>
<td>消费者操作系统</td>
<td align=right>04.22%</td>
<td align=right>4th</td>
<td align=right>3rd</td>
<td align=right>15.44%</td>
<td align=right>17.27%</td>
</tr>
<tr>
<td>数字媒体</td>
<td align=right>-18.32%</td>
<td align=right>5th</td>
<td align=right>5th</td>
<td align=right>10.66%</td>
<td align=right>09.65%</td>
</tr>
<tr>
<td>系统与程序设计</td>
<td align=right>-03.32%</td>
<td align=right>1st</td>
<td align=right>1st</td>
<td align=right>33.39%</td>
<td align=right>34.62%</td>
</tr>
<tr>
<td>Web 设计与开发</td>
<td align=right>-28.01%</td>
<td align=right>3rd</td>
<td align=right>4th</td>
<td align=right>17.10%</td>
<td align=right>14.32%</td>
</tr>
</tbody>
</table>
<p>在继续深入分析各门类之前，我们先来看看2010年出版的所有计算机图书的书名中出现的关键词。这是一个非常有意思的角度，因为这些关键词会出现在图书封面上、在线搜索中，以及任何相关内容的元数据中。说明一点：我把the、and、it、with等停顿词都过滤掉了。此外，Microsoft这个词因为被用于描述很多种产品，重复次数太多，也被我忽略了。下面就是这张图书市场的“书名关键词”图。</p>
<p><img class="colorbox-2329"  src="http://radar.oreilly.com/upload/2011/01/titles.jpg"/></p>
<p>深入分析各门类图书后，我们发现在排名前10的二级分类中，有7个在2010年销量少于2009年，前20个二级分类销量净减少了244,936册。换句话说，在相对较大而且一般也较为稳定的领域，图书销量在2010年明显下降。2010年上半年，有49个二级分类销量领先于2009年上半年，而其中有6个二级分类下半年增长放缓、优势尽丧，最终导致全年销量下降。结果，2010年有43个二级分类的销量超过2009年。按照销量增长多少排序，这些二级分类分别是：平板电脑、移动编程、Windows应用、安全、硬件、社交网站、计算机与安全、云计算、信息技术和数据处理。其中平板电脑类图书2010年上半年的销量大约为15,000册，而下半年销量猛增至100,000册。图书品种的增多加快了这种增长——2010年上半年版权输出7种，而下半年底达到22种，是上半年的3倍。而图书销量下降幅度最大的领域依次是：网页制作、数字图像、Mac OS、Flash、Web程序设计、网页设计工具、个人电脑、Linux、软件项目管理和个人数据库。最让我吃惊的领域是Web程序设计。2010年上榜的Web程序设计类图书减少了16种，只有7%的图书销量过千，而这个比例在2009年是11%。</p>
<p>在市场持续下滑的同时，很多出版商的反应就是增加出书的数量，希望通过品种增加来获得市场份额。下面两张图显示的分别是Bookscan监控到的图书品种数，以及所有图书的单品平均销量。有一点似乎并不是显而易见：在没有必要多出那么多种书的情况下，居然有那么多新书说出就出了。这一切可能就要归结为上榜的门槛太低了。换句话说，有几周Top 3000中图书的销量都低到了只有6册。这个问题可以相对来看。前两年，低门槛的问题已经显现了，导致打榜的图书品种虽多，但单品的平均销量却不尽人意。如果市场良性发展，门槛自然会提高，因而只有销售业绩真好的图书才能进入Top 3000。低门槛的结果就是所有出版商的单品平均销量都在明显减少。除了22家最大的出版公司之外，2010年榜上有名的另外18家出版公司也增加了出书品种。然而，这18家出版公司中只有6家在多出书的同时也做到了单品平均销量的增长。因此，关键在于，进入Top 3000行列的图书品种可以增加，但如果进入的门槛太低，那么平均销量和总销量照样也会跟着低。</p>
<h2>图书品种</h2>
<p><img class="colorbox-2329"  src="http://radar.oreilly.com/upload/2011/01/TitlesPerYear.jpg"/></p>
<h2>平均销量</h2>
<p><img class="colorbox-2329"  src="http://radar.oreilly.com/upload/2011/01/AvgUnitsYear.jpg"/></p>
<p>下面这张表格显示了市场被稀释的结果。平均最低值意味着给定年度内每周的“低门槛”水平。平均最高值则是给定年度内每周的最高销量。品种数的含义不言自明。数据显示，平均最低值越高，对应的年度图书品种数越少。总而言之，投入市场的图书品种越多，品种多销量少的稀释效应就会越明显。</p>
<table border="1">
<tbody>
<tr>
<td align=center><strong>年份</strong></td>
<td><strong>平均最低值</strong></td>
<td><strong>平均最高值</strong></td>
<td><strong>品种数</strong></td>
</tr>
<tr>
<td>2004</td>
<td align=right>9.2</td>
<td align=right>1,133</td>
<td align=right>7,451</td>
</tr>
<tr>
<td>2005</td>
<td align=right>9.6</td>
<td align=right>1,099</td>
<td align=right>7,123</td>
</tr>
<tr>
<td>2006</td>
<td align=right>9.6</td>
<td align=right>1,315</td>
<td align=right>6,881</td>
</tr>
<tr>
<td>2007</td>
<td align=right>9.4</td>
<td align=right>1,348</td>
<td align=right>7,092</td>
</tr>
<tr>
<td>2008</td>
<td align=right>8.2</td>
<td align=right>1,534</td>
<td align=right>7,310</td>
</tr>
<tr>
<td>2009</td>
<td align=right>7.3</td>
<td align=right>1,057</td>
<td align=right>7,557</td>
</tr>
<tr>
<td>2010</td>
<td align=right>6.7</td>
<td align=right>1,112</td>
<td align=right>7,792</td>
</tr>
</table>
<p>因此，可以说我们现在正处于技术创新的低迷阶段。有什么技术、平台、方法、理论或者什么新点子，能让我们走出这个市场低迷期吗？还是说，出版商只能一味地多出书，而不管码洋是不是受损失，放任既有的市场空间被多出来的书稀释掉，难道真的就只能这样原地打转、束手无策吗？我认为是后一种情况。只能等有一天，突然大量的需求出现，才能把现在的市场托起来。我说不好这股需求到底是来自云计算、移动应用，还是社会化平台，当然也可能来自其他蓄势待发的潜力领域。未来5年哪个领域可能会有大的增长？有没有酝酿已久的将会对技术世界产生巨大影响的事物？</p>
<p>现在，我们来分析一下构成各大门类的细分类别。下面首先给出了一组趋势图，显示了从2009年1月到2010年12月24个月期间各个主要类别的市场表现。以24个月为周期，能够更清楚地看出某个特定领域是否会受到季节性因素的影响，该领域是不是在持续增长，还是持续下跌。大家在看图的时候，别忘记图中的曲线反映的是相对市场规模，因此纵轴上的市场规模绝对值不容忽视。另外，还有一种简便的判断方法，即曲线在方框图中的位置越高，说明其市场规模越大，反之市场规模越小。有意思的是，消费者操作系统、数字媒体、商业应用与设备这些类别在1月份都有一个很高的起点，这很可能是因为不少读者会因为买了新电脑、新设备或新操作系统，需要看一些入门指南类的图书。这其实就是明显的季节性特征。</p>
<table border=0>
<tr>
<td align=right>IT人文</td>
<td align=right>数字媒体</td>
<td align=right>Web开发与设计</td>
<tr>
<td>
<div class="ap_r"><a href="http://radar.oreilly.com/upload/2011/01/CT.png" class="highslide" onclick="return hs.expand(this)"><img class="colorbox-2329"  src="http://radar.oreilly.com/upload/2011/01/CT.png" alt="CT.png"/></a></div>
</td>
<td>
<div class="ap_r"><a href="http://radar.oreilly.com/upload/2011/01/DM.png" class="highslide" onclick="return hs.expand(this)"><img class="colorbox-2329"  src="http://radar.oreilly.com/upload/2011/01/DM.png" alt="DM.png"/></a></div>
</td>
<td>
<div class="ap_r"><a href="http://radar.oreilly.com/upload/2011/01/WD.png" class="highslide" onclick="return hs.expand(this)"><img class="colorbox-2329"  src="http://radar.oreilly.com/upload/2011/01/WD.png" alt="WD.png"/></a></div>
</td>
</tr>
<td align=right>消费者操作系统与设备</td>
<td align=right>商业应用</td>
<td align=right>系统与程序设计</td>
<tr>
<td>
<div class="ap_r"><a href="http://radar.oreilly.com/upload/2011/01/CO.png" class="highslide" onclick="return hs.expand(this)"><img class="colorbox-2329"  src="http://radar.oreilly.com/upload/2011/01/CO.png" alt="CO.png"/></a></div>
</td>
<td>
<div class="ap_r"><a href="http://radar.oreilly.com/upload/2011/01/ba.png" class="highslide" onclick="return hs.expand(this)"><img class="colorbox-2329"  src="http://radar.oreilly.com/upload/2011/01/ba.png" alt="ba.png"/></a></div>
</td>
<td>
<div class="ap_r"><a href="http://radar.oreilly.com/upload/2011/01/SP.png" class="highslide" onclick="return hs.expand(this)"><img class="colorbox-2329"  src="http://radar.oreilly.com/upload/2011/01/SP.png" alt="SP.png"/></a></div>
</td>
</tr>
</table>
<h1>细分门类分析（以24个月为周期，从2009年1月到2010年12月）</h1>
<p>在理解下面给出的细分门类的相关图表时，请参考上面的各大门类的趋势图。通过这些图表，可以更深入地了解细分门类的市场规模以及季节变化规律。</p>
<h2>门类：消费者操作系统与设备</h2>
<p>以下是消费者操作系统与设备门类下的4个细分门类的趋势线。</p>
<p><img class="colorbox-2329"  src="http://radar.oreilly.com/upload/2011/01/CO_1.jpg"/><br />
<img class="colorbox-2329"  src="http://radar.oreilly.com/upload/2011/01/CO_2.jpg"/></p>
<p>这是一个中等规模的门类，也是两个跨年度增长的门类之一。这个门类的增长主要由Windows 7和便携设备（Port Dev）子类别驱动。便携设备子类别2010年由Android领衔，2009年则是iPhone挂帅。前面我们提到过，平板电脑子类别在2010年下半年的表现非常突出，曲线上扬得很快。Andy Rathbone的新书Windows 7 For Dummies名列榜首，另外两本Windows 7的图书排名第二和第三。婵连销售冠军的<a href="http://oreilly.com/catalog/9780596153298"><em>Mac OS X Snow Leopard: The Missing Manual</em></a>下落到第四位，由于Snow Leopard并非苹果公司的一个重要OS版本，因而相关主题的图书没有像往年一样拉动所属类别的增长。</p>
<p>虽然在Mac OS X爆炸性增长的带动下，这个市场也曾经增长过，但仍然还是不能与Windows图书相比，后者一直都稳居畅销排行榜之列，而且近两年也实现了增长。下面这张柱形图显示了Mac OS与Windows图书历年累计销量的对比情况。你使用PC还是Mac？这张图说明，还是使用PC的读者更多！</p>
<p><img class="colorbox-2329"  src="http://radar.oreilly.com/upload/2011/01/MacOSxWindows.jpg"/></p>
<h2>门类：商业/办公应用</h2>
<p>2009与2010年商业应用类图书相比，有8个一级分类的表现好于上一年，有23个表现不如上一年。而这23个表现不佳的分类减少的销量比8个增长的分类多卖的销量还要多，相比之下，净损失67,000册，总体增长率为-5.10%。</p>
<p>两个最健康的一级分类是电子表格（Excel）和社交网络（Facebook），分别实现了2.42%和11.49%的增长率。两个最后进的一级分类是图形应用（Graphics Applications）和电子商务，增长率分别是-1.80%和-47.00%。最让我不理解的是，CMS（Content Management Systems，内容管理系统）没有像我想象得那样增长。为此，我查了几年的数据，发现CMS图书增长最快的时期是2006至2009年。而在过去的两年，这个分类的市场保持稳定，与整体市场下滑相比表现还是不错的。下面就是CMS图书历年的销量柱形图。</p>
<h3>CMS图书历年销量</h3>
<p><img class="colorbox-2329"  src="http://radar.oreilly.com/upload/2011/01/CMS_Units_Years.jpg"/></p>
<p>以下是商业/办公门类中三个主要领域的趋势图。</p>
<p><img class="colorbox-2329"  src="http://radar.oreilly.com/upload/2011/01/BA_1.jpg"/></p>
<p>注意，“办公应用”这个分类的市场规模与另外两个分类（“一般商业应用”和“设计”）相比有多么大。但这个分类的市场表现略有下降，销量从2009年的196,722册下降到2010年的187,968册，增长率为-4.66%。这个增长率（下降率）与计算机整体市场的增长率（-4.54%）相差无几。办公应用类图书的王者是“阿呆系列”（Dummies）。2010年排名前三的都是阿呆系列，而且前10名的位子中阿呆系列占到了7席。想想也难怪，Excel之类的软件又不是什么高端技术，因此阿呆系列图书受到了各类读者的广泛青睐，其中既有闻技术而色变的普通老百姓，也不乏满脑子前沿技术的高端学者。对办公应用这个领域，即使称它为“阿呆帝国”恐怕也不过分。</p>
<h2>门类：Web设计与开发</h2>
<p>2010年与2009年相比，Web设计与开发类图书的销量下降了28.01%，251,000册。但是别忘了，2009年可是整体市场最差的一年了。这个门类中只有两个一级分类实现了增长：JavaScript和社交网站，增长率分别是7.81%和7.18%。我们出的<a href="http://oreil.ly/egQEmN"><em>Learning PHP, MySQL, and JavaScript</em></a>是这个门类中卖得最好的一本书。最令人吃惊的是，网页制作类图书的销量与2009相比，骤减70,000册（别忘了，2009年已经很糟糕了）。是人们的兴趣从HTML转移到PHP、JavaScript和CMS上面去了吗？还是大家都跑去开发能访问自己网页的移动应用了呢？</p>
<p>以下三张趋势图展示的是Web设计与开发门类中三个主要的分类。</p>
<p><img class="colorbox-2329"  src="http://radar.oreilly.com/upload/2011/01/WD_1.jpg"/></p>
<p>显然，最大的子类别是“网站建设”。这个子类别中占主导地位的图书，讨论的都是性能、可扩展性、可靠性以及调优等，都是能在我们的<a href="http://velocityconf.com/velocity2011">Velocity Conference</a>和<a href="http://bit.ly/bundles/mikehatora/3">推荐书目</a>中找到的话题。富Web界面在各子类别中位居第二，但总体是下滑趋势。在这个类别中，Flash和Silverlight的下降幅度最大。Flash下降幅度为-84.43%，Silverligth是-8.29%。不过，Flash的市场规模仍然是Silverlight的4倍。难道是HTML5让这两种技术失宠了吗？</p>
<h2>门类：系统与程序设计</h2>
<p>这是计算机图书市场中最大的一个门类。这个门类囊括了绝大多数编程语言、数据库和软件开发类的图书。这个门类的正常趋势是年初有一个不错的开端，而后到9月份（大学生开学）又会冲到一个高点。这个门类包含67个子类别，2010年有44个领域出现了负增长，只有23个领域是正增长，正负相抵，2010年整个门类的销量净减少72,024册。算下来，下降幅度只有-3.32%，因此这个大门类的实际市场表现还是好于整体市场的。在增长的二级分类中，位列前5的依次是移动编程、安全、云计算、信息技术和数据处理。业绩最差的二级分类中，前5名分别是：Linux、软件项目管理、个人数据库、Visual Basic和SQL Server。在增长率最高的移动编程领域，iPhone编程是2009年主流，而Android编程则是2010年的热门。注意，这些图书谈论的不是怎么玩iPhone或Droid手机，而是怎么开发移动应用。2009年，iOS类图书的市场规模是Android的9倍，而2010年大约是2.5倍。</p>
<p>以下是系统与程序设计门类中9个一级分类的前3名的趋势图。</p>
<p><img class="colorbox-2329"  src="http://radar.oreilly.com/upload/2011/01/SyPro_1.jpg"/></p>
<p>注意一下每个分类的整体规模。编程语言（prog lang）仍然是最大的一级分类，而程序设计（prog）已经从第三跃居第二。算上2010年，数据库已经连续下滑了三年了。如前所述，软件项目管理是2010年最大的失败者，但它仍然还是系统与程序设计门类中的第三大二级分类，前面的两个二级分类是移动编程和安全。不过，与SPM（系统与程序设计市场）的整体下滑相对应，移动编程和安全也都是下滑的。另一个从名不见经传成长为可观的二级分类的是数据处理。这个类别中的很多书与我们<a href="http://bit.ly/bundles/mikehatora/4"> Strata Conference及Data Science 资源</a>中的一些访谈、对话和文章是类似的。</p>
<p>第二组一级分类的趋势图与其他门类的一级分类相比，波动不是那么大。这组曲线的趋势虽然平缓，但都带有明显的季节性销售的特征。</p>
<p><img class="colorbox-2329"  src="http://radar.oreilly.com/upload/2011/01/SyPro_2.jpg"/></p>
<p>对比2009年与2010年全年的数据可以发现，软件工程（sw engr）是这一组中最大的一级分类，经典著作<em>The Mythical Man-Month: Essays on Software Engineering, Anniversary Edition</em>和新经典<em>Coders at Work: Reflections on the Craft of Programming</em>是软件工程类的榜首图书。网络类图书由CompTIA（Computer Technology Industry Association，美国计算机行业协会）的资格认证图书占据，前10名中有5本书都是它们的，包括前2名。</p>
<p>第三组趋势线由CISSP（Certified Information System Security Professional，信息系统安全认证专业人员）、电脑入侵及CompTIA安全类图书主导。</p>
<p><img class="colorbox-2329"  src="http://radar.oreilly.com/upload/2011/01/SyPro_3.jpg"/></p>
<p>接下来的第三部分，将分析出版商，包括赢家和输家。第四部分将对编程语言类图书市场进行更深入的分析。而第五部分将关注数字出版。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/02/22/2010-book-market-of-usa-2-2329.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>2010年美国计算机图书市场报告一：市场综述</title>
		<link>http://www.cn-cuckoo.com/2011/02/21/2010-book-market-of-usa-1-2287.html</link>
		<comments>http://www.cn-cuckoo.com/2011/02/21/2010-book-market-of-usa-1-2287.html#comments</comments>
		<pubDate>Mon, 21 Feb 2011 04:59:35 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[交互设计]]></category>
		<category><![CDATA[出版]]></category>
		<category><![CDATA[编程技术]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2287</guid>
		<description><![CDATA[http://radar.oreilly.com/2011/02/2010-book-market-1.html Mike Hendrickson 2011-2-10 报告内容 第一部分：市场综述 第二部分：分类市场 第三部分：出版商 第四部分：编程语言 第五部分：完结篇及数字出版 下载完整版（PDF） 自从上一次计算机图书市场报告发表之后的两年来，技术图书市场经历了一些重大的变化。恐怕不少读者根据图书市场日益疲软的征兆，已经看到未来发展的某些趋势了。实际上，我们早就断言过计算机图书销售情况预示着技术发展的趋势，大家也可以搜索一下有关计算机图书市场的其他文章。 本报告的数据来自Bookscan每周监控到的Top 3000图书的销售情况。Bookscan计量的是书店收银机的实际销售数据。换句话说，只要你在美国的书店里买过一本技术书，那么你购买这本书的信息十有八九已经进入了Bookscan的数据库里。Borders、Barnes &#038; Noble以及Amazon等零售商实现了绝大多数技术图书的销售。 图书市场业绩综述 在讨论细分的计算机图书市场之前，我们先来了解一下截止到2011年1月2日这个周末，整个图书市场的表现情况。下面这张表涵盖了从The Girl with the Dragon Tatoo and Eat, Pray, Love to Decision Points到The Ugly Truth的所有图书，只要是印刷、装订并以书的形式销售的，都包含在里面。 整体图书市场表现（所有图书，数据截止日期2011年1月2日） 所有图书，所有题材 青少年非虚构 -0.44% 青少年虚构 -3.46% 青少图书整体 -2.88% 成人非虚构 -1.91% &#160;&#160;&#160;&#160;计算机及互联网 -3.99% 成人虚构 -7.20% 其他 -13.12% 整体市场 -4.54% 从表中可以看出，计算机图书市场较上年下滑了4%。需要注意的是，计算机图书的销售量只占实体和在线书店所有图书总销量的1%。下面这张图展示的整体图书市场各门类的业绩增长情况。其中，幽默（Humor）类图书的增长在普遍低迷的市场背景下显得独树一帜（14.45%）。另一个增长的领域是青少年非虚构类中的教材/教辅类（21.55%）。我很奇怪，为什么教材/教辅类图书居然有这么高的增长率。 整体图书市场增长情况 下面言归正传，看看技术图书市场。下面这张柱形图展示的是各年份累计图书销量的对比情况。从图中可以看出，每年的总销量从2007年开始逐年递减。2007年的时候，不少人认为市场会中止2001年以来一路下跌的态势，开始进入恢复期，但2009年较上一年的跌幅达到了历年最大值。 而下面这张折线图展示的是自2004年以来计算机图书市场每周的市场表现情况（根据我们从Bookscan获得的第一手数据生成）。请注意，这个图反映的是所有出版商，而不仅仅是O&#8217;Reilly。图中稍粗一点的红线表示2010年的数据。 从图中可以看出，我们提到过的明显的季节性特征依然存在。换句话说，每年开始都会强势上扬，然后一直到夏季逐步走低，到了秋天“返校”的季节开始止跌回升，到了年底又强势收尾。图中每年的趋势线都与上一年的趋势线非常接近，甚至连每周的涨跌都十分一致。在24个月来乏善可陈的市场表现中，唯一能让人感到一点慰藉的是，2009年每周销量与上一年度比有10-15%是下降的，而这个比例在2010年减少到了3-6%。但这能说明市场已经见底了吗，还是说我们也像读者思考着怎样才能学到新技术一样处于观望状态？如今，销售图书的方式更多了（后面几部分中会介绍），不少出版商通过不同数字格式来销售相同的内容实现了码洋与销量的双增长。而有些出版商纸质书发行量的降低，也通过数字发行和销售得到了补偿。 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://radar.oreilly.com/2011/02/2010-book-market-1.html">http://radar.oreilly.com/2011/02/2010-book-market-1.html</a><br />
Mike Hendrickson<br />
2011-2-10</p>
<div style="float:right; border:1px solid #ddd;border-width:0 0 1px 1px;padding:0 .5em;margin:0 0 0 .5em;">
<p style="font-weight:bold;">报告内容</p>
<ol>
<li><a href="http://www.cn-cuckoo.com/2011/02/26/2010-book-market-of-usa-1-2287.html">第一部分：市场综述</a></li>
<li><a href="http://www.cn-cuckoo.com/2011/02/23/2010-book-market-of-usa-2-2329.html">第二部分：分类市场</a></li>
<li><a href="http://www.cn-cuckoo.com/2011/02/23/2010-book-market-of-usa-3-2270.html">第三部分：出版商</a></li>
<li><a href="http://www.cn-cuckoo.com/2011/02/23/2010-book-market-of-usa-4-2265.html">第四部分：编程语言</a></li>
<li><a href="http://www.cn-cuckoo.com/2011/02/25/2010-book-market-of-usa-5-2279.html">第五部分：完结篇及数字出版</a></li>
</ol>
<div style="text-align:center;">
<a href="http://u.115.com/file/f661fc6f86"><br />
<img class="colorbox-2287"  style="border:1px solid #eee;" src="http://ww1.sinaimg.cn/large/61baa48djw6deqves2ryvj.jpg"/><br />
</a><br />
<a href="http://u.115.com/file/f661fc6f86">下载完整版（PDF）</a>
</div>
</div>
<p>自从上一次计算机图书市场报告发表之后的两年来，技术图书市场经历了一些重大的变化。恐怕不少读者根据图书市场日益疲软的征兆，已经看到未来发展的某些趋势了。实际上，我们早就断言过<a href="http://radar.oreilly.com/archives/2005/04/book_sales_as_a.html">计算机图书销售情况预示着技术发展的趋势</a>，大家也可以搜索一下有关计算机图书市场的其他文章。</p>
<p>本报告的数据来自Bookscan每周监控到的Top 3000图书的销售情况。Bookscan计量的是书店收银机的实际销售数据。换句话说，只要你在美国的书店里买过一本技术书，那么你购买这本书的信息十有八九已经进入了Bookscan的数据库里。Borders、Barnes &#038; Noble以及Amazon等零售商实现了绝大多数技术图书的销售。</p>
<h1>图书市场业绩综述</h1>
<p>在讨论细分的计算机图书市场之前，我们先来了解一下截止到2011年1月2日这个周末，整个图书市场的表现情况。下面这张表涵盖了从<em>The Girl with the Dragon Tatoo and Eat, Pray, Love to Decision Points</em>到<em>The Ugly Truth</em>的所有图书，只要是印刷、装订并以书的形式销售的，都包含在里面。</p>
<p>整体图书市场表现（所有图书，数据截止日期2011年1月2日）</p>
<table border=1 cellpadding=1 cellspacing=3 width=245>
<tr height=13>
<td align=center><strong>所有图书，所有题材</strong></td>
</tr>
</table>
<table border=1 cellpadding=1 cellspacing=3 width=245>
<tr>
<td><strong>青少年非虚构</strong></td>
<td align=right>-0.44%</td>
<tr height=13>
<td height=13  ><strong>青少年虚构<strong></td>
<td align=right>-3.46%</td>
<tr height=13>
<td height=13><strong>青少图书整体</strong></td>
<td align=right>-2.88%</td>
</tr>
<tr height=13>
<td   height=13><strong>成人非虚构</strong></td>
<td align=right>-1.91%</td>
<tr height=13>
<td height=13><font color="red"><strong>&nbsp;&nbsp;&nbsp;&nbsp;计算机及互联网</strong></font></td>
<td align=right>-3.99%</td>
<tr height=13>
<td  ><strong>成人虚构</strong></td>
<td align=right>-7.20%</td>
</tr>
<tr height=13>
<td  ><strong>其他</strong></td>
<td align=right>-13.12%</td>
</tr>
<td align=center><strong>整体市场</strong></td>
<td align=right><strong>-4.54%</strong></td>
</tr>
</table>
<p>从表中可以看出，计算机图书市场较上年下滑了4%。需要注意的是，计算机图书的销售量只占实体和在线书店所有图书总销量的1%。下面这张图展示的整体图书市场各门类的业绩增长情况。其中，幽默（Humor）类图书的增长在普遍低迷的市场背景下显得独树一帜（14.45%）。另一个增长的领域是青少年非虚构类中的教材/教辅类（21.55%）。我很奇怪，为什么教材/教辅类图书居然有这么高的增长率。<br />
<span id="more-2287"></span></p>
<h2>整体图书市场增长情况</h2>
<p><img class="colorbox-2287"  src="http://radar.oreilly.com/WholeMarket.jpg"/></p>
<p>下面言归正传，看看技术图书市场。下面这张柱形图展示的是各年份累计图书销量的对比情况。从图中可以看出，每年的总销量从2007年开始逐年递减。2007年的时候，不少人认为市场会中止2001年以来一路下跌的态势，开始进入恢复期，但2009年较上一年的跌幅达到了历年最大值。</p>
<p><img class="colorbox-2287"  src="http://radar.oreilly.com/upload/2011/02/allYears.jpg"/></p>
<p>而下面这张折线图展示的是自2004年以来计算机图书市场每周的市场表现情况（根据我们从Bookscan获得的第一手数据生成）。请注意，这个图反映的是所有出版商，而不仅仅是O&#8217;Reilly。图中稍粗一点的红线表示2010年的数据。</p>
<p><img class="colorbox-2287"  src="http://radar.oreilly.com/upload/2011/01/sync_2010.jpg"/></p>
<p>从图中可以看出，我们提到过的明显的季节性特征依然存在。换句话说，每年开始都会强势上扬，然后一直到夏季逐步走低，到了秋天“返校”的季节开始止跌回升，到了年底又强势收尾。图中每年的趋势线都与上一年的趋势线非常接近，甚至连每周的涨跌都十分一致。在24个月来乏善可陈的市场表现中，唯一能让人感到一点慰藉的是，2009年每周销量与上一年度比有10-15%是下降的，而这个比例在2010年减少到了3-6%。但这能说明市场已经见底了吗，还是说我们也像读者思考着怎样才能学到新技术一样处于观望状态？如今，销售图书的方式更多了（后面几部分中会介绍），不少出版商通过不同数字格式来销售相同的内容实现了码洋与销量的双增长。而有些出版商纸质书发行量的降低，也通过数字发行和销售得到了补偿。</p>
<p>从上面图中看不来的是，计算机图书市场从2001年开始走下坡路，随后连续3年以20%的比例收缩，直到2004年趋于稳定，规模保持在2000年时的一半左右。（我们手中只有上溯到2004年的可靠数据。）如今，市场从2008年下半年开始又进入下跌通道，一直延续到2010年。前6年的整体市场增长率分别为：2005年1.48%、2006年3.17%、2007年-2.00%、2008年-4.27%、2009年-15.31%、2010年-4.29%。</p>
<p>那么，2010年有什么好消息吗？2010年，有11周的图书销量超过了上一年度。2009年，只有两周的销量超过了上一年度。因此，从这一点来说，似乎能看到市场复苏的某种迹象。2010年最终收关收在了2008年的销量水平上，而且整体市场降速比2009年慢了很多。持乐观态度的人认为，2010年市场已经触底；但持悲观态度的人则认为，这种情况早已有之：看起来好像市场已经跌无可跌了，但随后照样出现了大跌。因此，到底市场会再次走低，还是稳步复苏，都是没有办法确定的。</p>
<p>Treemap工具能够将数据可视化，通过它可以从另一个角度观察市场的表现。Treemap有助于迅速捕捉到市场的趋势信息，即使是几千种图书也不在话下。它的使用方法如下：</p>
<p>图中一个方块表示一个门类的市场份额和相对规模，颜色表示销量变化的速度。红色意味着下降，绿色意味着上升，而颜色的深浅表示变化的幅度（越深越大）。下面这张Treemap的屏幕截图显示了2010年第四季度与2009年第四季度相比，计算机图书市场各门类的损益情况。</p>
<p><img class="colorbox-2287"  src="http://radar.oreilly.com/upload/2011/02/cat_yoy_QTR4.jpg"/></p>
<p>从这些彩色方块中能看出什么来呢？首先别忘了它反映的是2010年第四季度与2009年第四季度的一个对比。这张屏幕截图已经不像去年那张那样“血流成河”了（去年的Treemap到处都是红色），与去年同期相比，2010年第四季度的亮点（浅绿色）不少。位于左上方的Android类图书，与2009年第四季度相比，增长了2,413%。你可能会注意到上部中间还有一个Android方块，呈浅绿色，区别在于中部上方的是面向消费者的书，左上角是Android编程的书。这两类书2010年都比2009年有很大的增长。左上角的iPad图书方块是黑色的，因为2009年还没有iPad图书。不过，方块的大小表明其发展规模一开始就令人印象深刻。</p>
<p>2010年，Windows 7图书增幅最大，其次是iPad，然后是Android（面向消费者的）和Android编程类图书。这是从销量增长来看的，而且这些技术之所以表现如此不俗，很大程度上是因为它们都是相对新的技术，没有大块的市场份额作为比较的基础。对于那些历史较长的技术，安全及网络安全、数字图像类图书的销量增长比较明显。</p>
<p>要看明白图中表示的趋势，可以按照颜色对这些门类加以分组：浅绿色代表“高度增长门类”，深绿及黑色代表“中度增长门类”，所有颜色都是“待观察门类”，红色及浅红色代表“下降门类”。除了“待观察门类”，其他都无须解释。“待观察门类”中包含那些不容易受季节性因素影响的，以及我们O&#8217;Reilly Radar关注的一些门类。您可以把希望添加到我们待观察范围的门类告诉我们。</p>
<p>下面这个表格分析并解释了上面Treemap中的某些数据，数据年份为2010年。其中Share（份额）一栏显示的是相应门类的市场份额，ROC一栏显示的是变化的速度（Rate of Change，RoC = (本期-上期)/上期）。举例来说，Mac OS类图书占整个计算机图书市场的份额为2.95%，收缩速度（RoC）为32.12%。</p>
<table border="1" cellpadding="5" cellspacing="1">
<col />
<col />
<col />
<col />
<tbody>
<tr>
<td><strong>高度增长</strong></td>
<td><strong>Share</strong></td>
<td><strong>ROC</strong></td>
<td><strong>Notes</strong></td>
</tr>
<tr>
<td>Windows 7</td>
<td align="right">05.53%</td>
<td align="right">217.38%</td>
<td>取代了XP和Vista自成一大类。Windows 7是操作系统中的大哥大。</td>
</tr>
<tr>
<td>iPad</td>
<td align="right">01.74%</td>
<td align="right">xx.yy%</td>
<td>这个类别在2009年的时候还没有，但现在已经成为市场份额排名第7的类别了。</td>
</tr>
<tr>
<td>Android编程</td>
<td align="right">00.68%</td>
<td align="right">292.65%</td>
<td>这个类别从2008年开始稳定增长，目前排名第42位，在最快RoC中排名第3位。</td>
</tr>
<tr>
<td>可用性</td>
<td align="right">00.11%</td>
<td align="right">491.50%</td>
<td>这个领域已经不像昔日那么巨大了，但高RoC加速了其增长，使其成为相当大的一个类别。</td>
</tr>
<tr>
<td>Android</td>
<td align="right">00.55%</td>
<td align="right">2493.88%</td>
<td>主要是面向Android消费者的领域，包括用户手册、最佳应用，等等。2008年起从无到有，2009年稳定增长，2010年名列前茅。</td>
</tr>
<tr>
<td><strong>中度增长</strong></td>
<td><strong>Share</strong></td>
<td><strong>ROC</strong></td>
<td><strong>Notes</strong></td>
</tr>
<tr>
<td>jQuery</td>
<td align="right">00.41%</td>
<td align="right">83.79%</td>
<td>规模相当大的一个类别，版权输出从2009年的9本降至2010年的6本，不过销量仍在稳定增长。</td>
</tr>
<tr>
<td>云计算</td>
<td align="right">00.22%</td>
<td align="right">63.58%</td>
<td>一个看涨的门类，2010年8本新书就取得如此成绩。当下出版的主要还是介绍性图书。</td>
</tr>
<tr>
<td>Windows 管理</td>
<td align="right">00.32%</td>
<td align="right">36.29%</td>
<td>中等规模的门类，2010年新书19本，2009年新书16本（2009年出版的图书也含在2010年销售数据中）。</td>
</tr>
<tr>
<td>社交网站</td>
<td align="right">00.21%</td>
<td align="right">30.27%</td>
<td>此类图书在过去两年中翻了一倍，2010年的新书增长了61%，创历年新高。</td>
</tr>
<tr>
<td>网络安全</td>
<td align="right">00.90%</td>
<td align="right">24.25%</td>
<td>安全类图书在2010年表现不错，新书版权稳定输出。</td>
</tr>
<tr>
<td><strong>待观察门类</strong></td>
<td><strong>Share</strong></td>
<td><strong>ROC</strong></td>
<td><strong>Notes</strong></td>
</tr>
<tr>
<td>Office 应用</td>
<td align="right">2.71%</td>
<td align="right">-3.54%</td>
<td>非常大的一个门类，市场一如既往地稳定。即使有所下滑，仍不像整体市场下滑得那样厉害。</td>
</tr>
<tr>
<td>图形图像</td>
<td align="right">05.97%</td>
<td align="right">-17.20%</td>
<td>非常大的一个门类（在Windows之后位居第2），有4本书销量过万；2010年新增图书10本，但销量下降64,581册。</td>
</tr>
<tr>
<td>电子表格</td>
<td align="right">02.99%</td>
<td align="right">-4.66%</td>
<td>第三大门类，有4本书销量过万；2010年新增打榜图书11种，但销量较2009年减少8,754册。</td>
</tr>
<tr>
<td>软件项目管理</td>
<td align="right">02.10%</td>
<td align="right">-15.14%</td>
<td>规模较大也较稳定的一个门类，销量略有下降。PMP及敏捷项目管理类图书最好卖。</td>
</tr>
<tr>
<td><strong>下降门类</strong></td>
<td><strong>Share</strong></td>
<td><strong>ROC</strong></td>
<td><strong>Notes</strong></td>
</tr>
<tr>
<td>Flash</td>
<td align="right">01.12%</td>
<td align="right">-84.43%</td>
<td>在Apple的冲击下，这个门类已经进退维谷，2010年销量比2009年减少59,340册，而2009年销量较2008年减少55,187册。</td>
</tr>
<tr>
<td>Mac OS</td>
<td align="right">02.95%</td>
<td align="right">-32.12%</td>
<td>很大的一个类别，2010年销量减少59,668册。2009年销量比2008年少67,642册。显然是Snow Leopard不给力带来的恶果。</td>
</tr>
<tr>
<td>Web 设计工具</td>
<td align="right">01.37%</td>
<td align="right">-53.20%</td>
<td>这个类别遭受了打击，主要因为Dreamweaver CS5没有随CS4图书的退场而及时跟上。2010年销量减少45,709册。</td>
</tr>
<tr>
<td>Web 程序设计</td>
<td align="right">02.01%</td>
<td align="right">-41.32%</td>
<td>规模较大，2010年新书品种减少了16种。2009年，有56个品种销量过千，而2010年销量过千的品种只有37种。.</td>
</tr>
<tr>
<td>网页制作</td>
<td align="right">04.09%</td>
<td align="right">-27.37%</td>
<td>拥有较大规模，2010年只有4个品种销量过万，而2009年过这个线的有9种。2010年的销量减少了70,492册。.</td>
</tr>
</tbody>
</table>
<p>本报告的第二部分将深入分析这些门类中的各种技术。第三部分将关注出版商，包括赢家和输家。第四部分将主要分析编程语言，第五部分将关注数字销售。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/02/21/2010-book-market-of-usa-1-2287.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>现代浏览器揭秘（草）</title>
		<link>http://www.cn-cuckoo.com/2011/02/18/how-broswers-work-2257.html</link>
		<comments>http://www.cn-cuckoo.com/2011/02/18/how-broswers-work-2257.html#comments</comments>
		<pubDate>Fri, 18 Feb 2011 13:53:46 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[原创]]></category>
		<category><![CDATA[编程技术]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2257</guid>
		<description><![CDATA[原文地址：How browsers work 简介 Web浏览器恐怕是用户最多的软件了。本文将介绍浏览器的工作原理。想知道从你在地址栏中输入“google.com”，到窗口中显示Google主页的过程中都发生了什么？本文会为你揭开这个秘密。 要讨论的浏览器 今天，人们主要使用5种浏览器：Internet Explorer、Firefox、Safari、Chrome和Opera。这篇文章的分析源自开源浏览器——Firefox、Chrome和Safari，Safari是部分开源的。根据W3C对浏览器使用情况的统计信息，当前（2009年10）Firefox、Safari和Chrome共同的市场占有率已接近60%。因此，可以说开源浏览器已经占据了浏览器市场的半壁江山。 浏览器的主要功能 浏览器的主要功能就是呈现你选择的网络资源，换句话说，就是你向服务器请求资源，然后浏览器把它们显示在自己的窗口中。资源的格式通常是HTML，当然也有PDF、图像等等。资源的位置是使用URI（Uniform Resource Indentifier，统一资源标识符）来指定的。与此相关的内容在后面讨论网络的时候还会详细介绍。 浏览器如何解释HTML文件是由HTML和CSS规范规定的。这些规范是由W3C（World Wide Web Consortium，万维网联盟）维护的，W3C是负责制定Web标准的组织。 HTML当前的版本号是4（http://www.w3.org/TR/html401/），HTML5还在制定中。CSS当前的版本号是2（http://www.w3.org/TR/CSS2/），CSS3也正在制定过程中。 多少年来，浏览器厂商各自为战，纷纷埋头开发自己的扩展，对规范的支持始终不给力。结果就给Web开发人员带来了生死攸关的兼容性问题。而今天，大多数浏览器对规范的支持程度仍然参差不齐。 浏览器的用户界面大同小异，其中相同的界面元素包括： 用于输入URI的地址栏 后退和前进按钮 书签选项 用于刷新和停止加载当前文档的刷新及停止按钮 返回主页的主页按钮 说来也怪，并没有哪个正式公布的规范对浏览器的用户界面作出规定，浏览器目前的外观是多年来浏览器厂商之间互相模仿和不断改进的结果。HTML5规范中没有定义浏览器必须具备的UI元素，但列出了一些公共元素，其中就包括地址栏、状态栏和工具栏。当然，有些浏览器还有自己专有的一些功能，如Firefox的下载管理器。相关的更多内容将在后面讨论用户界面时介绍。 浏览器的主要构成 以下是构成浏览器的主要组件（参考1.1）。 1、用户界面——包括地址栏、后退/前进按钮、书签菜单等等，也就是除了显示所请求页面的主窗口之外的其他所有部分。 2、浏览器引擎——用于查询和操作呈现（rendering）引擎的接口。 3、呈现引擎——负责显示请求的内容，例如请求的内容是HTML，它就负责解析HTML和CSS并将解析后的内容显示到屏幕上。 4、网络模块——用于完成网络调用，如HTTP请求。具有平台中立的接口和针对不同平台的底层实现。 5、UI后端——用于绘制基本的组合选择框及对话框之类的基本部件。具有不特定于某个平台的界面样式，在底层使用的是操作系统的用户界面方法。 6、JavaScript解释器——用户解释和执行JavaScript代码。 7、数据存储模块——属于持久层；浏览器需要在硬盘中保存各种数据，如Cookie。HTML5还为客户端存储定义了新的技术。 图1 浏览器的主要组件 需要特别指出的是，Chrome会为每个新建的标签页创建一个新的呈现引擎的实例，并且每个标签页也运行在独立的进程当中，这一点与其他浏览器不一样。对构成浏览器的这些组件，我们会逐一详细讨论。 组件之间的通信 Firefox和Chroem都具有联系各个组件的组件。后面也将讨论这些组件。 呈现引擎 呈现引擎主要负责……呈现，也就是把请求的内容显示到浏览器屏幕上。 默认情况下，呈现引擎可以显示HTML和XML文档以及图像。而借助插件（一种浏览器扩展）它还可以显示其他类型的内容，比如使用PDF阅读器插件可以显示PDF。后面我们还会专门讨论插件和扩展，但这里我们只讨论呈现引擎的主要用途——显示使用CSS格式化之后的HTML及图像。 呈现引擎 前面提到的浏览器（Firefox、Chrome和Safari）是构建在两个呈现引擎之上的。Firefox使用Gecko——Mozilla自己开发的一个呈现引擎；Safari和Chrome都使用Webkit。 Webkit是一个开源的呈现引擎，最早是为Linux平台开发的，后来由苹果公司移植到Mac和Windows平台。有关内容请参考http://webkit.org。 主流程 呈现引擎首先通过网络层取得被请求文档的内容。通常是以8K分块的方式完成。 取得内容之后，呈现引擎的基本工作流如下图所示： 图2 呈现引擎的基本工作流 呈现引擎会开始解析HTML文档，并将HTML标签转换成“内容树”中的DOM节点。然后，它开始解析样式数据，包括外部CSS文件和style元素中的样式。解析后的样式信息，再加上HTML中的视觉指令，将被用于创建另一个树——呈现器树。 呈现器树中包含着各种矩形，每个矩形都有颜色和大小等属性。这些矩形都按照显示在屏幕上的顺序排列好了。 在构建完呈现器树之后，呈现引擎要完成一个“布局”过程。在这个过程中，它会精确地确定每个节点在屏幕上出现时的坐标。紧接着的一个阶段就是绘制——遍历呈现器树，并使用UI后端层将所有节点逐个绘制出来。 上述过程是逐步完成的，认识到这一点很重要。为了获得更好的用户体验，呈现引擎会尽可能早地将内容呈示到屏幕上。换句话说，它不会等到把所有HTML标签都解析完毕之后再去构建和布局呈现器树，而是解析完一部分内容，就显示一部分内容；与此同时，剩余内容可能还在通过网络不断下载的过程中。 主流程示例 [...]]]></description>
			<content:encoded><![CDATA[<p>原文地址：<a href="http://taligarsiel.com/Projects/howbrowserswork1.htm">How browsers work</a></p>
<h2>简介</h2>
<p>Web浏览器恐怕是用户最多的软件了。本文将介绍浏览器的工作原理。想知道从你在地址栏中输入“google.com”，到窗口中显示Google主页的过程中都发生了什么？本文会为你揭开这个秘密。</p>
<h4>要讨论的浏览器</h4>
<p>今天，人们主要使用5种浏览器：Internet Explorer、Firefox、Safari、Chrome和Opera。这篇文章的分析源自开源浏览器——Firefox、Chrome和Safari，Safari是部分开源的。根据W3C对浏览器使用情况的统计信息，当前（2009年10）Firefox、Safari和Chrome共同的市场占有率已接近60%。因此，可以说开源浏览器已经占据了浏览器市场的半壁江山。</p>
<h4>浏览器的主要功能</h4>
<p>浏览器的主要功能就是呈现你选择的网络资源，换句话说，就是你向服务器请求资源，然后浏览器把它们显示在自己的窗口中。资源的格式通常是HTML，当然也有PDF、图像等等。资源的位置是使用URI（Uniform Resource Indentifier，统一资源标识符）来指定的。与此相关的内容在后面讨论网络的时候还会详细介绍。</p>
<p>浏览器如何解释HTML文件是由HTML和CSS规范规定的。这些规范是由W3C（World Wide Web Consortium，万维网联盟）维护的，W3C是负责制定Web标准的组织。</p>
<p>HTML当前的版本号是4（http://www.w3.org/TR/html401/），HTML5还在制定中。CSS当前的版本号是2（http://www.w3.org/TR/CSS2/），CSS3也正在制定过程中。</p>
<p>多少年来，浏览器厂商各自为战，纷纷埋头开发自己的扩展，对规范的支持始终不给力。结果就给Web开发人员带来了生死攸关的兼容性问题。而今天，大多数浏览器对规范的支持程度仍然参差不齐。</p>
<p>浏览器的用户界面大同小异，其中相同的界面元素包括：</p>
<ul>
<li>用于输入URI的地址栏</li>
<li>后退和前进按钮</li>
<li>书签选项</li>
<li>用于刷新和停止加载当前文档的刷新及停止按钮</li>
<li>返回主页的主页按钮</li>
</ul>
<p>说来也怪，并没有哪个正式公布的规范对浏览器的用户界面作出规定，浏览器目前的外观是多年来浏览器厂商之间互相模仿和不断改进的结果。HTML5规范中没有定义浏览器必须具备的UI元素，但列出了一些公共元素，其中就包括地址栏、状态栏和工具栏。当然，有些浏览器还有自己专有的一些功能，如Firefox的下载管理器。相关的更多内容将在后面讨论用户界面时介绍。<br />
<span id="more-2257"></span></p>
<h4>浏览器的主要构成</h4>
<p>以下是构成浏览器的主要组件（参考<a href="#2257-1">1.1</a>）。<br />
1、用户界面——包括地址栏、后退/前进按钮、书签菜单等等，也就是除了显示所请求页面的主窗口之外的其他所有部分。<br />
2、浏览器引擎——用于查询和操作呈现（rendering）引擎的接口。<br />
3、呈现引擎——负责显示请求的内容，例如请求的内容是HTML，它就负责解析HTML和CSS并将解析后的内容显示到屏幕上。<br />
4、网络模块——用于完成网络调用，如HTTP请求。具有平台中立的接口和针对不同平台的底层实现。<br />
5、UI后端——用于绘制基本的组合选择框及对话框之类的基本部件。具有不特定于某个平台的界面样式，在底层使用的是操作系统的用户界面方法。<br />
6、JavaScript解释器——用户解释和执行JavaScript代码。<br />
7、数据存储模块——属于持久层；浏览器需要在硬盘中保存各种数据，如Cookie。HTML5还为客户端存储定义了新的技术。</p>
<p><img class="colorbox-2257"  src="http://cache.cn-cuckoo.com/img/2257_layers.png"/><br />
图1 浏览器的主要组件</p>
<p>需要特别指出的是，Chrome会为每个新建的标签页创建一个新的呈现引擎的实例，并且每个标签页也运行在独立的进程当中，这一点与其他浏览器不一样。对构成浏览器的这些组件，我们会逐一详细讨论。</p>
<h4>组件之间的通信</h4>
<p>Firefox和Chroem都具有联系各个组件的组件。后面也将讨论这些组件。</p>
<h2>呈现引擎</h2>
<p>呈现引擎主要负责……呈现，也就是把请求的内容显示到浏览器屏幕上。</p>
<p>默认情况下，呈现引擎可以显示HTML和XML文档以及图像。而借助插件（一种浏览器扩展）它还可以显示其他类型的内容，比如使用PDF阅读器插件可以显示PDF。后面我们还会专门讨论插件和扩展，但这里我们只讨论呈现引擎的主要用途——显示使用CSS格式化之后的HTML及图像。</p>
<h4>呈现引擎</h4>
<p>前面提到的浏览器（Firefox、Chrome和Safari）是构建在两个呈现引擎之上的。Firefox使用Gecko——Mozilla自己开发的一个呈现引擎；Safari和Chrome都使用Webkit。<br />
Webkit是一个开源的呈现引擎，最早是为Linux平台开发的，后来由苹果公司移植到Mac和Windows平台。有关内容请参考http://webkit.org。</p>
<h4>主流程</h4>
<p>呈现引擎首先通过网络层取得被请求文档的内容。通常是以8K分块的方式完成。</p>
<p>取得内容之后，呈现引擎的基本工作流如下图所示：</p>
<p><img class="colorbox-2257"  src="http://cache.cn-cuckoo.com/img/2257_flow.jpg"/><br />
图2 呈现引擎的基本工作流</p>
<p>呈现引擎会开始解析HTML文档，并将HTML标签转换成“内容树”中的<a href="#dom">DOM</a>节点。然后，它开始解析样式数据，包括外部CSS文件和style元素中的样式。解析后的样式信息，再加上HTML中的视觉指令，将被用于创建另一个树——<a href="render_tree">呈现器树</a>。</p>
<p>呈现器树中包含着各种矩形，每个矩形都有颜色和大小等属性。这些矩形都按照显示在屏幕上的顺序排列好了。</p>
<p>在构建完呈现器树之后，呈现引擎要完成一个“<a href="layout">布局</a>”过程。在这个过程中，它会精确地确定每个节点在屏幕上出现时的坐标。紧接着的一个阶段就是<a href="painting">绘制</a>——遍历呈现器树，并使用UI后端层将所有节点逐个绘制出来。</p>
<p>上述过程是逐步完成的，认识到这一点很重要。为了获得更好的用户体验，呈现引擎会尽可能早地将内容呈示到屏幕上。换句话说，它不会等到把所有HTML标签都解析完毕之后再去构建和布局呈现器树，而是解析完一部分内容，就显示一部分内容；与此同时，剩余内容可能还在通过网络不断下载的过程中。</p>
<h6>主流程示例</h6>
<p><img class="colorbox-2257"  src="http://cache.cn-cuckoo.com/img/2257_webkitflow.png" /><br />
图3　Webkit的主流程</p>
<p><img class="colorbox-2257"  src="http://cache.cn-cuckoo.com/img/2257_geckoflow.jpg" /><br />
图4　Mozilla的Gecko呈现引擎的主流程</p>
<p>从图3和图4可以看出，Webkit和Gecko使用的术语稍有不同，但整个流程基本上是相同的。</p>
<p>Gecko把可见的格式化元素的树叫做“框架树”（Frame tree），每个元素都是一个框架。而Webkit使用的则是“呈现器树”（Render tree），这个树由“呈现器对象”构成。Webkit把排列元素叫做“布局”，而Gecko则称该过程为“重排”（Reflow）。同样，“附加”（Attachment）则是Webkit对连接DOM节点与样式信息以创建呈现器树的称呼。Gecko还有一个与语义无关的小差别，它在HTML与DOM树之间加了一层，叫做“内容渗入”（Content Sink），相当于一个制造DOM元素的工厂。下面我们就来解释流程中的每个阶段。</p>
<h6>基本解析</h6>
<p>由于解析是呈现引擎的一项非常重要的工作，因此我们会讨论得比较深入一些。首先来简单地介绍一下解析。</p>
<p>所谓的解析文档，就是把文档转换成具有某种意义的结构，以便代码能够被理解和使用。解析之后的结果通常是一个节点树，与文档的结构对应。这个节点树叫做解析树或语法树。</p>
<p>举个例子，解析表达式“2+3-1”会返回下面这个树：</p>
<p><img class="colorbox-2257"  src="http://cache.cn-cuckoo.com/img/2257_nodetree.png"/><br />
图5 算术表达式的节点树</p>
<h6>文法</h6>
<p>解析是依据文档所遵循的语法规则进行的，取决于编写文档的语言和格式。每一个要解析的格式都必须具有由词汇表和语法规则构成的文法。这种文法称为<a href="#context_free_grammer">上下文无关的文法</a>。人类语言不具备上下文无关的文法，因此无法使用通常的解析技术来解析。</p>
<h6>解析器——加上词法分析器</h6>
<p>解析可以分为两个步骤：词法分析（lexical analysis）和语法分析（syntax analysis）。</p>
<p>词法分析指的是把输入分解成符号。符号来自语言的词汇表——基本有效单元的集合。对人类语言来说，符号就相当于我们字典中的那些单词。</p>
<p>语法分析就是使用语言的语法规则进行分析。</p>
<p>解析器通常把这两项工作交给两个组件来完成：词法分析器（有时也叫分词器）负责把输入分解成符号，而解析器则负责依据语言的语法规则来分析文档结构，然后构建起解析树。词法分析器知道如何剥离空格、换行等无关字符。</p>
<p><img class="colorbox-2257"  src="http://cache.cn-cuckoo.com/img/2257_parsetree.png"/><br />
图6 从源文档到解析树</p>
<p>解析过程是迭代进行的。解析器通常会要求词法分析器给出一个新的符号，然后使用该符号去匹配某种语法规则。如果匹配成功，则将与该符号对应的节点添加到解析树中，然后继续要求词法分析器再提供另一个符号。</p>
<p>如果匹配不成功，解析器会在内部保存当前符号，然后继续从词法分析器那里获取符号，直到所有内部保存的符号能够匹配一项语法规则为止。如果最终都没有找到匹配的规则，解析器就会抛出异常。这就意味着文档无效，或者说包含语法错误。</p>
<h6>转换</6><br />
（待续2011/2/20）</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/02/18/how-broswers-work-2257.html/feed</wfw:commentRss>
		<slash:comments>29</slash:comments>
		</item>
		<item>
		<title>解构JavaScript库：jQuery、Prototype、Mootools</title>
		<link>http://www.cn-cuckoo.com/2011/01/06/javascript-libraries-deconstructed-2231.html</link>
		<comments>http://www.cn-cuckoo.com/2011/01/06/javascript-libraries-deconstructed-2231.html#comments</comments>
		<pubDate>Thu, 06 Jan 2011 15:25:09 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[编程技术]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2231</guid>
		<description><![CDATA[JavaScript库“解构”系列旨在以可视化和可交互的方式剖析JavaScript库的源代码，包括 jQuery、Prototype 和 MooTools。 通过将 JavaScript 源代码以可见块元素的方式标记出来，可以更方便查找和学习。点开每个块元素，即可查看相应的代码。点击代码中的链接，即可在程序流中纵情畅游。 ——Dave Stewart 这么好的东西，还用多说吗？你懂的。（见下图） 唯一需要说明的是，Dave Stewart原创的这个JavaScript库解构系列不知何故被挡在“墙”外头了，我只是把它搬到了“墙”里面来而已。换句话说，这个解构系列并非出自我手，我只是在自己的站点上提供了它的一个镜像，以方便“墙”内的JavaScript学习者参考。 现在就开始：解构JavaScript库!]]></description>
			<content:encoded><![CDATA[<div style="padding:1em;background:#eee;">JavaScript库“解构”系列旨在以可视化和可交互的方式剖析JavaScript库的源代码，包括 jQuery、Prototype 和 MooTools。<br />
通过将 JavaScript 源代码以可见块元素的方式标记出来，可以更方便查找和学习。点开每个块元素，即可查看相应的代码。点击代码中的链接，即可在程序流中纵情畅游。</p>
<div style="text-align:right;margin-right:2em;font-family:Arial, Helvetica, sans-serif;">——Dave Stewart</div>
</div>
<p>这么好的东西，还用多说吗？你懂的。（见下图）<br />
唯一需要说明的是，Dave Stewart原创的这个JavaScript库解构系列不知何故被挡在“墙”外头了，我只是把它搬到了“墙”里面来而已。换句话说，这个解构系列并非出自我手，我只是在自己的站点上提供了它的一个镜像，以方便“墙”内的JavaScript学习者参考。</p>
<p>现在就开始：<a href="http://www.cn-cuckoo.com/deconstructed/">解构JavaScript库</a>!<br />
<a href="http://www.cn-cuckoo.com/main/wp-content/uploads/2011/01/jquery.png"><img src="http://www.cn-cuckoo.com/main/wp-content/uploads/2011/01/jquery_small.png" alt="" title="jquery" class="aligncenter size-full wp-image-2239 colorbox-2231" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2011/01/06/javascript-libraries-deconstructed-2231.html/feed</wfw:commentRss>
		<slash:comments>37</slash:comments>
		</item>
		<item>
		<title>HTML5设计原理</title>
		<link>http://www.cn-cuckoo.com/2010/10/21/the-design-of-html5-2151.html</link>
		<comments>http://www.cn-cuckoo.com/2010/10/21/the-design-of-html5-2151.html#comments</comments>
		<pubDate>Thu, 21 Oct 2010 15:09:40 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2151</guid>
		<description><![CDATA[Jeremy Keith在 Fronteers 2010 上的主题演讲 特别感谢以下朋友指出翻译错误。 rukey67指出了一个翻译错误（另一个没有翻错）。 梁海指出了一个翻译错误。 小乐指出了一个错别字。 Rui指出了一个错别字。 Gavin指出译文少了一个“是”字。 下载PPT（PDF） 观看视频 今天我想跟大家谈一谈HTML5的设计。主要分两个方面：一方面，当然了，就是HTML5。我可以站在这儿只讲HTML5，但我并不打算这样做，因为如果你想了解HTML5的话，你可以Google，可以看书，甚至可以看规范。 实际上，确实有人会谈到规范的内容。史蒂夫·福克纳（Steve Faulkner）会讲HTML5与可访问性。而保罗·艾里什（Paul Irish）则会讲HTML5提供的各种API。因此，我今天站在这里，不会光讲一讲HTML5就算完事了。 说老实话，在正式开始之前，我想先交待清楚我所说的HTML5到底是什么意思。这话听起来有点搞笑：这会子你一直在说HTML5，难道我们还不知道什么是HTML5吗？大家知道，有一个规范，它的名字叫HTML5。我所说的HTML5，指的就是这个规范。但问题是，有些人所说的HTML5，指的不仅仅是这个规范，还有别的意思。比如说，用HTML5来代指CSS3就是一种常见的叫法。我可不是这样的。我所说的HTML5，不包含CSS3，就是HTML5。 类似的术语问题以前也有过。Ajax本来是一种含义明确的技术，但过了不久，它的含义就变成了“用JavaScript来做一切好玩的东西”。这就是Ajax，对不对？今天，HTML5也面临同样的问题，它本来指的是一个特定的规范，但如今含义却成了“在Web上做一切好玩的事。”我说的不是这种HTML5，不是这种涵盖了最近刚刚出现的各种新东东的HTML5。我说的仅仅是规范本身：HTML5。 刚才已经说了，我今天想要讲的内容不多，也没有打算介绍HTML5都包含什么。今天我要讲的是它的另一方面，即HTML5的设计。换句话说，我要讲的不是规范里都包含什么，而是规范里为什么会包含它们，以及在设计这个规范的时候，设计者们是怎么看待这些东西的。 设计原理 设计原理本质上是一种信念、一种想法、一个概念，是你行动的支柱。不管你是制定规范，还是制造一种有形的物品，或者编写软件，甚至发明编程语言。你都能找到背后的一个或者多个设计原理，多人协作的任何成果都是例证。不仅仅Web开发领域是这样。纵观人类历史，像国家和社会这样大规模的构建活动背后，同样也有设计原理。 就拿美国为例吧，美国的设计原理都写在了《独立宣言》中了。 我们认为这些真理是不言而喻的，人人生而平等，造物主赋予了每个人不可剥夺的权利，包括生存、自由和追求幸福。 这里有一句口号：生存、自由和追求幸福。这是被写进宪法中的核心理念，它关系到我们所有人的一切，也就是我们构建自己社会的原则。 还有一个例子，就是卡尔·马克思（Karl Marx），他的著作在20世纪曾被奉为建设社会主义的圭臬。其基本思想大致可以归结为下面这条设计原理： 各尽所能，各取所需。 这其实就是一种经济体系背后的设计原理。 还有一个例子，比前面两个的历史更久远一些，不过大同小异： 人人为我，我为人人。 这个极为简单的设计原理，是两千年前的拿撒勒犹太人耶稣基督提出来的。而这条原则成为了后来许多宗教的核心教义。原理与实践有时候并不是同步的。 下面是小说中的一个例子。英国小说家乔治·奥威尔（George Orwell）笔下的《动物庄园》，就是在一条设计原理的基础上构建起来的虚拟社会。这条设计原理是： 四条腿的都是好人，两条腿的都是坏蛋！ 《动物庄园》中有意思的是，随着社会的变迁——变得越来越坏，这条设计原理也跟着发生了改变，变成了“四条腿的都是好人，两条腿的就更好了。”最关键的是，即使是在虚构的作品里，设计原理都是存在的。 还有一套虚构的作品是以三条设计原理为基础构建起来的，那就是美国著名小说家艾萨克·阿西莫夫（Issac Asimov）的机器人经典系列。阿西莫夫发明了机器人学这个术语，并提出了机器人学三大法则，然后在这三个简单的设计原理基础上创作了一系列经典作品——大约有50本书。无论作品的情节如何变化，实际上都是从不同的角度来阐释这三大设计原理。我想，在座各位对机器人三大法则都不应该陌生。 机器人不得伤害人类，或袖手旁观人类受伤害。 机器人必须服从人类命令，除非命令违反第一法则。 机器人必须自卫，只要不违背第一和第二法则。 这些恐怕是第一次出现在小说中的针对软件的设计原理了。虽然基于这三个设计原理的软件运行在虚构的机器人的“正电子脑”中，但我想这应该是软件设计原理的事实开端。从此以后，我们才看到大量优秀软件背后的设计原理。 蒂姆·伯纳斯-李（Tim Berners-Lee），Web的发明者，在W3C的网站上发表过一份文档，其中有一个URL给出了他自己的一套设计原理。这些设计原理并不那么容易理解，不仅多，而且随着时时间推移，他还会不断补充、修改和删除。不过我还是觉得把自己认同的设计原理写出来放在某个地方真是个不错的主意。 实际上，CSS的发明人之一伯特·波斯（Bert Bos），也在W3C的网站上放着一份文档，其中讲的都是基本的设计原理，比如怎样设计并构建一种格式，无论是CSS还是其他格式。推荐大家看一看。 只要你在W3C的站点中随便找一找，就可以发现非常多的这种设计原理，包括蒂姆·伯纳斯-李个人的。当然，你还会看到他从软件工程学校里借用的一些口号：分权（decentalisation）、容忍（tolerance）、简易（simplicity）、模块化（modularity）。这些都是在他发明新格式的时候，头脑中无时无刻不在想的那些关键词。 在座各位对蒂姆·伯纳斯-李的贡献都是非常熟悉的，因为大家每天都在用。他发明了Web，与罗伯特·卡里奥（Robert Cailliau）共同发明了Web，而且在发明Web的同时，也发明了我们每天都在Web上使用的语言。当然，这门语言就是HTML：超文本标记语言。 HTML HTML最早是从2.0版开始的。从来就没有1.0版。如果有人告诉你说，他最早是从HTML 1.0开始使用HTML的，那他绝对是在忽悠你。从前确实有一个名叫HTML Tags的文档，其中的部分标签一直用到现在，但那个文档并非官方的规范。 使用标签、尖括号、p或h1，等等，并不是蒂姆·伯纳斯-李首创的想法。当时的SGML里就有了这些概念，而且当时的CERN（Conseil Europeen [...]]]></description>
			<content:encoded><![CDATA[<h2><a href="http://adactio.com/articles/1704/">Jeremy Keith在 Fronteers 2010 上的主题演讲</a></h2>
<div style="background:#eee;border:1px dashed orange;padding:1em 0 0 1em;float:right;margin:0 0em 1em 1em;">
特别感谢以下朋友指出翻译错误。</p>
<ul>
<li><a href="http://www.rukey.cn/" title="rukey67的个人网站">rukey67</a>指出了<a href="http://www.cn-cuckoo.com/2010/10/21/the-design-of-html5-2151.html/comment-page-1#comment-3384">一个翻译错误（另一个没有翻错）</a>。</li>
<li><a href="https://twitter.com/lianghai" title="梁海的Twitter">梁海</a>指出了<a href="http://www.cn-cuckoo.com/2010/10/21/the-design-of-html5-2151.html#comment-3446">一个翻译错误</a>。</li>
<li><a href="#" title="小乐没有留下链接">小乐</a>指出了<a href="http://www.cn-cuckoo.com/2010/10/21/the-design-of-html5-2151.html#comment-3621">一个错别字。</a></li>
<li><a href="#" title="Rui没有留下链接">Rui</a>指出了<a href="http://www.cn-cuckoo.com/2010/10/21/the-design-of-html5-2151.html#comment-3758">一个错别字。</a></li>
<li><a href="#" title="Rui没有留下链接">Gavin</a>指出译文<a href="http://www.cn-cuckoo.com/2010/10/21/the-design-of-html5-2151.html#comment-4450">少了一个“是”字</a>。</li>
</ul>
</div>
<div style="text-align:right;">
<a href="http://adactio.com/extras/slides/designofhtml5.pdf">下载PPT（PDF）</a><br />
<a href="http://fronteers.nl/congres/2010/sessions/the-design-of-html5-jeremy-keith">观看视频</a>
</div>
<p>今天我想跟大家谈一谈HTML5的设计。主要分两个方面：一方面，当然了，就是HTML5。我可以站在这儿只讲HTML5，但我并不打算这样做，因为如果你想了解HTML5的话，你可以Google，可以看书，甚至可以看规范。</p>
<p>实际上，确实有人会谈到规范的内容。史蒂夫·福克纳（Steve Faulkner）会讲HTML5与可访问性。而保罗·艾里什（Paul Irish）则会讲HTML5提供的各种API。因此，我今天站在这里，不会光讲一讲HTML5就算完事了。</p>
<p>说老实话，在正式开始之前，我想先交待清楚我所说的HTML5到底是什么意思。这话听起来有点搞笑：这会子你一直在说HTML5，难道我们还不知道什么是HTML5吗？大家知道，有一个规范，它的名字叫HTML5。我所说的HTML5，指的就是这个规范。但问题是，有些人所说的HTML5，指的不仅仅是这个规范，还有别的意思。比如说，用HTML5来代指CSS3就是一种常见的叫法。我可不是这样的。我所说的HTML5，不包含CSS3，就是HTML5。</p>
<p>类似的术语问题以前也有过。Ajax本来是一种含义明确的技术，但过了不久，它的含义就变成了“用JavaScript来做一切好玩的东西”。这就是Ajax，对不对？今天，HTML5也面临同样的问题，它本来指的是一个特定的规范，但如今含义却成了“在Web上做一切好玩的事。”我说的不是这种HTML5，不是这种涵盖了最近刚刚出现的各种新东东的HTML5。我说的仅仅是规范本身：HTML5。</p>
<p>刚才已经说了，我今天想要讲的内容不多，也没有打算介绍HTML5都包含什么。今天我要讲的是它的另一方面，即HTML5的设计。换句话说，我要讲的不是规范里都包含什么，而是规范里为什么会包含它们，以及在设计这个规范的时候，设计者们是怎么看待这些东西的。</p>
<h2>设计原理</h2>
<p>设计原理本质上是一种信念、一种想法、一个概念，是你行动的支柱。不管你是制定规范，还是制造一种有形的物品，或者编写软件，甚至发明编程语言。你都能找到背后的一个或者多个设计原理，多人协作的任何成果都是例证。不仅仅Web开发领域是这样。纵观人类历史，像国家和社会这样大规模的构建活动背后，同样也有设计原理。</p>
<p>就拿美国为例吧，美国的设计原理都写在了《独立宣言》中了。</p>
<p style="padding:2em;background:#eee;">
我们认为这些真理是不言而喻的，人人生而平等，造物主赋予了每个人不可剥夺的权利，包括生存、自由和追求幸福。
</p>
<p>这里有一句口号：生存、自由和追求幸福。这是被写进宪法中的核心理念，它关系到我们所有人的一切，也就是我们构建自己社会的原则。<br />
<span id="more-2151"></span><br />
还有一个例子，就是卡尔·马克思（Karl Marx），他的著作在20世纪曾被奉为建设社会主义的圭臬。其基本思想大致可以归结为下面这条设计原理：</p>
<p style="padding:2em;background:#eee;">
各尽所能，各取所需。
</p>
<p>这其实就是一种经济体系背后的设计原理。</p>
<p>还有一个例子，比前面两个的历史更久远一些，不过大同小异：</p>
<p style="padding:2em;background:#eee;">
人人为我，我为人人。
</p>
<p>这个极为简单的设计原理，是两千年前的拿撒勒犹太人耶稣基督提出来的。而这条原则成为了后来许多宗教的核心教义。原理与实践有时候并不是同步的。</p>
<p>下面是小说中的一个例子。英国小说家乔治·奥威尔（George Orwell）笔下的《动物庄园》，就是在一条设计原理的基础上构建起来的虚拟社会。这条设计原理是：</p>
<p style="padding:2em;background:#eee;">
四条腿的都是好人，两条腿的都是坏蛋！
</p>
<p>《动物庄园》中有意思的是，随着社会的变迁——变得越来越坏，这条设计原理也跟着发生了改变，变成了“四条腿的都是好人，两条腿的就更好了。”最关键的是，即使是在虚构的作品里，设计原理都是存在的。</p>
<p>还有一套虚构的作品是以三条设计原理为基础构建起来的，那就是美国著名小说家艾萨克·阿西莫夫（Issac Asimov）的机器人经典系列。阿西莫夫发明了机器人学这个术语，并提出了机器人学三大法则，然后在这三个简单的设计原理基础上创作了一系列经典作品——大约有50本书。无论作品的情节如何变化，实际上都是从不同的角度来阐释这三大设计原理。我想，在座各位对机器人三大法则都不应该陌生。</p>
<p style="padding:2em;background:#eee;">
机器人不得伤害人类，或袖手旁观人类受伤害。<br />
机器人必须服从人类命令，除非命令违反第一法则。<br />
机器人必须自卫，只要不违背第一和第二法则。
</p>
<p>这些恐怕是第一次出现在小说中的针对软件的设计原理了。虽然基于这三个设计原理的软件运行在虚构的机器人的“正电子脑”中，但我想这应该是软件设计原理的事实开端。从此以后，我们才看到大量优秀软件背后的设计原理。</p>
<p>蒂姆·伯纳斯-李（Tim Berners-Lee），Web的发明者，在W3C的网站上发表过一份文档，其中有一个URL给出了他自己的一套设计原理。这些设计原理并不那么容易理解，不仅多，而且随着时时间推移，他还会不断补充、修改和删除。不过我还是觉得把自己认同的设计原理写出来放在某个地方真是个不错的主意。</p>
<p>实际上，CSS的发明人之一伯特·波斯（Bert Bos），也在W3C的网站上放着一份文档，其中讲的都是基本的设计原理，比如怎样设计并构建一种格式，无论是CSS还是其他格式。推荐大家看一看。</p>
<p>只要你在W3C的站点中随便找一找，就可以发现非常多的这种设计原理，包括蒂姆·伯纳斯-李个人的。当然，你还会看到他从软件工程学校里借用的一些口号：分权（decentalisation）、容忍（tolerance）、简易（simplicity）、模块化（modularity）。这些都是在他发明新格式的时候，头脑中无时无刻不在想的那些关键词。</p>
<p>在座各位对蒂姆·伯纳斯-李的贡献都是非常熟悉的，因为大家每天都在用。他发明了Web，与罗伯特·卡里奥（Robert Cailliau）共同发明了Web，而且在发明Web的同时，也发明了我们每天都在Web上使用的语言。当然，这门语言就是HTML：超文本标记语言。</p>
<h2>HTML</h2>
<p>HTML最早是从2.0版开始的。从来就没有1.0版。如果有人告诉你说，他最早是从HTML 1.0开始使用HTML的，那他绝对是在忽悠你。从前确实有一个名叫HTML Tags的文档，其中的部分标签一直用到现在，但那个文档并非官方的规范。</p>
<p>使用标签、尖括号、p或h1，等等，并不是蒂姆·伯纳斯-李首创的想法。当时的SGML里就有了这些概念，而且当时的CERN（Conseil Europeen pour la Recherche Nucleaire，欧洲核子研究委员会）也在使用SGML的一个特定的版本。也就是说，即便在那个时代，他也没有白手起家；这一点在HTML后来的发展过程中也体现了出来：继往开来、承前启后，而不是另立门户、从头开始。</p>
<p>换句话说，这篇名为HTML Tags的文档可以算作HTML的第一个版本，但它却不是一个正式的版本。第一个正式版本，HTML 2.0，也不是出自W3C之手。HTML 2.0是由IETF，因特网工程任务组（Internet Engineering Task Force）制定的。在W3C成立之前，IETF已经发布了不少标准。但从第三个版本开始往后，W3C，万维网联盟（World Wide Web Consortium）开始接手，并负责后续版本的制定工作。</p>
<p>20世纪九十年代HTML有过几次快速的发展。众所周知，在那个时代要想构建网站，可是一项十分复杂的工程。浏览器大战曾令人头疼不已。市场竞争的结果就是各家浏览器里都塞满了各种专有的特性，都试图在专有特性上胜人一筹。当时的混乱程度不堪回首，HTML到底还重不重要，或者它作为Web格式的前景如何，谁都说不清楚。</p>
<p>从1997年到1999年，HTML的版本从3.2到4.0到4.01，经历了非常快的发展。问题是到了4.01的时候，W3C的认识发生了倒退，他们说“好了，这个版本就这样了，HTML也就这样了；HTML 4.01是HTML的最后一个版本了，我们用不着HTML工作组了。”</p>
<p>W3C并没有停止开发这门语言，只不过他们对HTML不再感兴趣了。在HTML 4.01之后，他们提出了XHTML 1.0。虽然听起来完全不同，但XHTML 1.0与HTML 4.01其实是一样的。我的意思是说，从字面上看这两个规范的内容是一样的，词汇表是一样的，所有的元素是一样，所有的属性也都是一样的。唯一一点不同之处，就是XHTML 1.0要求使用XML语法。也就是说，所有属性都必须使用小写字母，所有元素也必须使用小写字母，所有属性值都必须加引号，你还得记着使用结束标签，记着对img和br要使用自结束标签。</p>
<p>从规范本身的内容来看，实际上是相同的，没有什么不同。不同之处就是编码风格，因为对浏览器来说，读取符合HTML 4.01、HTML 3.2，或者XHTML 1.0规范的网页都没有问题，对浏览器来说这些网页都是一样的，都会生成相同的DOM树。只不过人们会比较喜欢XHTML 1.0，因为不少人认同它比较严格的编码风格。</p>
<p>到了2000年，Web标准项目（Web Standards Project）的活动开展得如火如荼，开发人员对浏览器里包含的那些乱七八糟的专有特性已经忍无可忍了。大家都很生气，就骂那些浏览器厂商“遵守个规范就他妈的真有那么难吗？”当时CSS有了长足的发展，而且与XHTML 1.0结合得也很紧密，CSS加XHTML 1.0基本上就可以算是“最佳实践”了。虽然在我看来HTML 4.01与XHTML 1.0没有本质上的不同，但大家都接受了。专业的开发人员能做到元素全部小写，属性全部小写，属性值也全部加引号：由于专业人员起到了模范带头作用，越来越多的人也都开始支持这种语法。</p>
<p>我就是一个例子！过去的10年，我一直都使用XHTML 1.0文档类型，原因是这样一来验证器就能给我帮上很大的忙，对不对？只要我写的是XHTML 1.0，然后用验证器测试，它就能告诉我是不是忘了给属性值加引号，是不是没有结束某个标签，等等等等。而如果我写的是HTML 4.01，同样的问题就变成了有效的了，验证器就不一定会提醒我了。</p>
<p>这就是我一直使用XHTML 1.0的原因。我估计很多人都……使用XHTML 1.0的朋友，请把手举起来。好的。HTML 4.01呢？人少多了。一直没有举手的呢，大声点，你们用什么？HTML5，也很好！更早的呢，还有人使用更早的文档类型吗？没有了？</p>
<p>10年来我一直使用XHTML 1.0，就是因为验证器能够真正帮到我。有人用XHTML 1.1吗？你知道有人用吗？请举手，别放下。有人把网页标记为XML文档吗？有吗？那你们使用的就不是XHTML 1.1。</p>
<p>这就是个大问题。XHTML 1.0之后是XHTML 1.1，只是小数点后面的数字加了一个1，而且从词汇表的角度看，规范本身没有什么新东西，元素也都相同，属性也都相同。但对XHTML 1.1来说，唯一的变化是你必须把自己的文档标记为XML文档。在使用XHTML 1.0的时候，还可以把文档标记为HTML，而我们也正是这样做的，否则把文档标记为XML没准真会把人逼疯的。</p>
<p>为什么这么说呢？首先，把文档标记为XML后，Internet Explorer不能处理。当然，IE9是可以处理了。恐怕有人会讲“真是太可爱了”，他们到现在居然都没有忘了这件事。这艘船终于靠岸了！不过那时候，作为全球领先的浏览器，IE无法处理接收到的XML文档类型的文档，而规范又要求你以XML文档类型来发送文档，这不把人逼疯才怪呢。</p>
<p>所以说XHTML 1.1有点脱离现实，而你不想把文档以XML格式发送给那些能够理解XML的浏览器，则是因为XML的错误处理模型。XML的语法，无论是属性小写，元素小写，还是始终要给属性值加引号，这些都没有问题，都很好，事实上我也喜欢这样做，但XML的错误处理模型却是这样的：解析器如果遇到错误，停止解析。规范里就是这么写的。如果你把XHTML 1.1标记为XML文档类型，假设你用Firefox打开这个文档，而文档中有一个和号（&#038;）没有正确编码，就算整个页面中就这一处错误，你看到的也将是黄屏，浏览器死掉了。Firefox会说：“没戏了，页面中有一个错误，你看不到这个网页了。”根据XML规范，这样处理是正确的，对Firefox而言，遇到错误就停止解析，并且不呈现其他任何内容是严格按照XML规范做的。因为它不是HTML，HTML根本就没有错误处理模型，但根据XML规范，这样做没错。</p>
<p>这就是为什么你不会把文档标记为XML的另一个原因。接下来，新的版本是XHTML 2，大家注意后面没有日期，因为这个规范并没有完成。</p>
<p>现在就说说XHTML 2，我很愿意把问题说清楚，XHTML 2实际上真是一个非常非常好的规范，确实非常好……从理论的角度来说。我的意思是说，制定这个规范的人都是非常非常有头脑的。直说吧，领导制定这个规范的家伙是斯蒂芬·彭伯顿（Stephen Pemberton），他应该是本地人，是一个聪明过人的家伙。规范本身也很了不起，如果所有人都同意使用的话，也一定是一个非常好的格式。只不过，还不够实际。</p>
<p>首先，XHTML 2仍然使用XML错误处理模型，你必须保证以XML文档类型发送文档；这一点不言自明：没人愿意这样做。其次，XHTML 2有意不再向后兼容已有的HTML的各个版本。他们甚至曾经讨论过废除img元素，这对每天都在做Web开发的人来说确实有点疯了的味道。但我们知道，他们之所以这样做，理论上确实有充足的理由——使用object元素可能会更好。</p>
<p>因此，无论XHTML 2在理论上是多么完美的一种格式，但却从未有机会付诸实践。而之所以难以将其付诸实践，就是因为像你我这样的开发人员永远不会支持它，它不向后兼容。同样，浏览器厂商也不会，浏览器厂商必须要保证向后兼容。</p>
<p>为什么XHTML 1.1没有像XML那样得到真正广泛地应用，为什么XHTML 2从未落到实处？因为它违反了一条设计原理，这条设计原理就是著名的伯斯塔尔法则（Postel&#8217;s Law）。大家都知道：</p>
<p style="padding:2em;background:#eee;">
发送时要保守；接收时要开放。
</p>
<p>没错，接收的时候要开放，而这也正是Web得以构建的基础。开发浏览器的人必须敞开胸怀，接收所有发送给浏览器的东西，因为它们过去一直都在接收那些不够标准的东西，对不对？Web上的很多文档都不规范，但那正是Web发展的动力。从某种角度讲，Web走的正是一条混沌发展之路，虽然混沌，但却非常美丽诱人。在Web上，格式不规范的文档随处可见，但那又怎样呢？如果所有人都能够写出精准的XML，所有文档的格式都十分正确，那当然好了。可是，那不现实。现实是伯斯塔尔法则。</p>
<p>作为专业人士，在发送文档的时候，我们会尽量保守一些，尽量采用最佳实践，尽量确保文档格式良好。但从浏览器的角度说，它们必须以开放的姿态去接收任何文档。</p>
<p>有人可能会说XML有错误处理模型，XHTML 1.1和XHTML 2都使用该模型，但那个错误处理模型太苛刻了。它绝对不符合接收时开放这个法则，遇到一个错误就停止解析怎么能叫开放呢？我们只能说它与健壮性法则（也就是伯斯塔尔法则）是对立的。</p>
<h2>HTML5</h2>
<p>之后，就到了HTML5，但HTML5并不是由W3C直接制定的。故事的经过是这样的，到20世纪末的时候，还没有HTML工作组，W3C内部的一些人就开始琢磨了，“HTML也许还可以更长寿一点，只要我们对它稍加扩展就行了。只要把我们放在XHTML上的时间和精力拿出一部分来，就可以提升一下HTML中的表单，可以让HTML更接近编程语言，就可以让它更上一层楼。”</p>
<p>于是，在2004年W3C成员内部的一次研讨会上，当时Opera公司的代表伊恩·希克森（Ian Hickson）提出了一个扩展和改进HTML的建议。他建议新任务组可以跟XHTML 2并行，但是在已有HTML的基础上开展工作，目标是对HTML进行扩展。W3C投票表决的结果是——“反对”，因为HTML已经死了，XHTML 2才是未来的方向。然后，Opera、Apple等浏览器厂商，以及其他一些成员说：“那好吧，不指望他们了，我们自已一样可以做这件事，我们脱离W3C。”他们成立了Web Hypertext Applications Technology Working Group（Web超文本应用技术工作组，WHATWG）——可巧的是，他们自称工作组，而不是特别小组（task force），这就为HTML5将来的命运埋下了伏笔。</p>
<p>WHATWG决定完全脱离W3C，在HTML的基础上开展工作，向其中添加一些新东西。这个工作组的成员里有浏览器厂商，因此他们不仅可以说加就加，而且还能够一一实现。结果，大家不断提出一些好点子，并且逐一做到了浏览器中。</p>
<p>WHATWG的工作效率很高，不久就初见成效。在此期间，W3C的XHTML 2没有什么实质性的进展。特别是，如果从实现的角度来说，用原地踏步形容似乎也不为过。</p>
<p>结果，一件有意思的事情发生了。那是在2006年，蒂姆·伯纳斯-李写了一篇博客，说：“你们知道吗？我们错了。我们错在企图一夜之间就让Web跨入XML时代，我们的想法太不切实际了，是的，也许我们应该重新组建HTML工作组了。”善哉斯言，后来的故事情节果真就是这样发展的。W3C在2007年组建了HTML5工作组。这个工作组面临的第一个问题，毫无疑问就是“我们是从头开始做起呢，还是在2004年成立的那个叫WHATWG的工作组既有成果的基础上开始工作呢？”答案是显而易见的，他们当然希望从已经取得的成果着手，以之为基础展开工作。于是他们又投了一次票，同意“在WHATWG工作成果的基础上继续开展工作”。好了，这下他们要跟WHATWG并肩战斗了。</p>
<p>第二个问题就是如何理顺两个工作组之间的关系。W3C这个工作组的编辑应该由谁担任？是不是还让WHATWG的编辑，也就是现在Google的伊恩·希克森来兼任？于是他们又投了一次票，赞成“让伊恩·希克森担任W3C HTML5规范的编辑，同时兼任WHATWG的编辑，更有助于新工作组开展工作。”</p>
<p>这就是他们投票的结果，也就是我们今天看到的局面：一种格式，两个版本。WHATWG的网站上有这个规范，而W3C的站点上同样也有一份。</p>
<p>如果你不了解内情，很可能会产生这样的疑问：“哪个版本才是真正的规范？”当然，这两个版本内容是一样的……基本上相同。实际上，这两个版本将来还会分道扬镳。现在已经有了分道扬镳的迹象了。我的意思是说，W3C最终要制定一个具体的规范，这个规范会成为一个工作草案，定格在某个历史时刻。</p>
<p>而WHATWG呢，他们还在不断地迭代。即使目前我们说的HTML5，也不能完全涵盖WHATWG正在从事的工作。最准确的理解是他们正在开发一项简单的HTML或Web技术，因为这才是他们工作的核心目标。然而，同时存在两个这样的工作组，这两个工作组同时开发一个基本相同的规范，这无论如何也容易让人产生误解。误解就可能造成麻烦。</p>
<p>其实这两个工作组背后各自有各自的流程，因为它们的理念完全不同。在WHATWG，可以说是一种独裁的工作机制。我刚才说了，伊恩·希克森是编辑。他会听取各方意见，在所有成员各抒己见，充分陈述自己的观点之后，他批准自己认为正确的意见。</p>
<p>W3C则截然相反，可以说是一种民主的工作机制。所有成员都可以发表意见，而且每个人都有投票表决的权利。这个流程的关键在于投票表决。从表面上看，WHATWG的工作机制让人不好接受。岂止是不好接受，简直是历史的倒退。相信谁都会认为“运作任何项目都不能采取这种方式！”</p>
<p>W3C的工作机制听起来让人很舒服。至少体现了人人平等嘛。但在实践中，WHATWG的工作机制运行得非常非常好。我认为之所以会这样，主要归功于伊恩·希克森。他的的确确是一个非常称职的编辑。他在听取各方意见时，始终可以做到丝毫不带个人感情色彩。</p>
<p>从原理上讲，W3C的工作机制很公平，而实际上却非常容易在某些流程或环节上卡壳，造成工作停滞不前，一件事情要达成决议往往需要花费很长时间。那到底哪种工作机制最好呢？我认为，最好的工作机制是将二者结合起来。而事实也是两个规范制定主体在共同制定一份相同的规范，我想，这倒是非常有利于两种工作机制相互取长补短。</p>
<p>两个工作组之所以能够同心同德，主要原因是HTML5的设计思想。因为他们从一开始就确定了设计HTML5所要坚持的原则。结果，我们不仅看到了一份规范，也就是W3C站点上公布的那份文档，即HTML5语言规范，还在W3C站点上看到了另一份文档，也就是HTML设计原理。而这份文档的一位编辑今天也来到了我们大会的现场，<del datetime="2011-01-29T15:26:47+00:00" title="感谢 @梁海 指出这个翻译错误">她</del>他就是安妮·奇泰丝（Anne Van Kesteren）。如果大家对这份文档有问题，可以请教安妮。</p>
<p>这份文档非常好，真的非常出色。这份文档，可以说见证了W3C与WHATWG同心协力共谋发展的历程。难道你们不觉得他们像是一对欢喜冤家吗？那他们还怎么同心同德呢？这份文档忠实地记录了他们一道做了什么，他们共同拥护什么。</p>
<p>接下来，我想要讲的就是这份文档。因为，既然他们能就这份文档达成共识，那么我相信，HTML5必将是一个伟大的规范，而他们已经认可这就是他们的共同行动纲领。为此，你才会看到诸如兼容性、实用性、互用性之类的概念。即便W3C与WHATWG之间再有多大的分歧——确实相当多——至少他们还有这份文档中记录的共识。这一点才是至关重要的。正因为他们有了共识，才有了这份基于共识描述设计原理的文档。</p>
<h2>避免不必要的复杂性</h2>
<p>下面我就给大家介绍一些这份文档中记载的设计原理。第一个，非常简单：避免不必要的复杂性。好像很简单吧。我用一个例子来说明。</p>
<p>假设我使用HTML 4.01规范，我打开文档，输入doctype。这里有人记得HTML 4.01的doctype吗？好，没有，我猜没有。除非……我的意思是说，你是傻冒。现场恐怕真有人背过，这就是HTML 4.01的doctype：</p>
<pre class="brush: html; ">

&lt;!DOCTYPE html PUBLIC &quot;-//W3C/DTD HTML 4.01//EN&quot;
&quot;http://www.w3.org/TR/html4/strict.dtd&quot;&gt;
</pre>
<p>我不记这个两行代码，不然还要记事本、要Google、要模板有什么用呢？</p>
<p>要是我使用XHTML 1.0呢，这个规范我都已经用了10年了。有谁记得住这个doctype吗？没错，它的长度跟HTML 4.01的差不太多：</p>
<pre class="brush: html; ">

&lt;!DOCTYPE html PUBLIC &quot;-//W3C/DTD XHTML 1.0 Strict//EN&quot;
&quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;
</pre>
<p>是不是，基本上相同。它要告诉浏览器的是：这个文档是XHTML 1.0的文档。那么在HTML 5中，省掉不必要的复杂性，doctype就简化成了：</p>
<pre class="brush: html; ">

&lt;!DOCTYPE html&gt;
</pre>
<p>仅此而已。好了，就连我也能过目不忘了。我用不着把这几个字符记在记事本里了。我得说，在我第一次看到这个doctype的时候——我当然以为这是一个HTML文档的doctype——被它吓了一跳：“是不是还少一个数字5啊？”我心里想：“这个doctype想告诉浏览器什么呢？就说这个文档是HTML吗？难道这是有史以来唯一一个HTML版本吗，这件事我得首先搞清楚，HTML今后永远不会再有新版本了吗？”好一副唯我独尊的架式！我错了，因为这个doctype并没有这个意思。为此，必须先搞清楚为什么文档一开头就要写doctype。它不是写给浏览器看的。Doctype是写给验证器看的。也就是说，我之所以要在文档一开头写那行XHTML 1.0的doctype，是为了告诉验证器，让验证器按照该doctype来验证我的文档。</p>
<p>浏览器反倒无所谓了。假设我写的是HTML 3.2文档，文档开头写的是HTML 3.2的doctype。而在文档中某个地方，我使用了HTML 4.01中才出现的一个元素。浏览器会怎么处理这种情况？它会因为这个元素出现在比doctype声明的HTML版本更晚的规范中，就不解释呈现该元素吗？不会，当然不会！它照样会解释呈现该元素，别忘了伯斯塔尔法则，别忘了健壮性。浏览器在接收的时候必须要开放。因此，它不会检查任何格式类型，而验证器会，验证器才关心格式类型。这才是存在doctype的真正原因。</p>
<p>而按照HTML5的另一个设计原理，它必须向前向后兼容，兼容未来的HTML版本——不管是HTML6、HTML7，还是其他什么——都要与当前的HTML版本，HTML5，兼容。因此，把一个版本号放在doctype里面没有多大的意义，即使对验器证也一样。</p>
<p>刚才，我说doctype不是为浏览器写的，这样说大多数情况下没有问题。在有一种情况下，你使用的doctype会影响到浏览器，相信在座诸位也都知道。但在这种情况下，Doctype并非真正用得其所，而只是为了达到某种特殊的目的才使用doctype。当初微软在引入CSS的时候，走在了标准的前头，他们率先在浏览器中支持CSS，也推出了自己的盒模型——后来标准发布了，但标准中使用了不一样的盒模型。他们怎么办？他们想支持标准，但也想向后兼容自己过去推出的编码方式。他们怎么知道网页作者想使用标准，还是想使用他们过去的方式？</p>
<p>于是，他们想出了一个非常巧妙的主意。那就是利用doctype，利用有效的doctype来触发标准模式，而不是兼容模型（quiks mode）。这个主意非常巧妙。我们今天也都是这样在做，在我们向文档中加入doctype时，就相当于声明了“我想使用标准模式”，但这并不是发明doctype的本意。这只是为了达到特殊的目的在利用doctype。</p>
<p>下面我出一道有奖抢答题，听好：“一分钟后开始，如果你手快的话，第一个在文档前面写完<span class="inline-code">doctype html</span>，然后我用Internet Explorer打开你的文档，会触发它的标准模式，还是会触发它的兼容模式？”</p>
<p>答案是，这是在Internet Explorer中触发标准模式的最少字符数目。我认为这也说明了HTML5规范的本质：它不追求理论上的完美。HTML5所体现的不是“噢，给作者一个简短好记的doctype不好吗？”，没错，简短好记是很好，但如果这个好记的doctype无法适应现有的浏览器，还不如把它忘了更好。因此，这个平衡把握得非常好，不仅理论上看是个好主意——简短好记的doctype，而且实践中同样也是个好主意——仍然可以触发标准模式。应该说，Doctype是一个非常典型的例子。</p>
<p>还有一个例子，同样可以说明规范是如何省略不必要的复杂性，避免不必要的复杂性的。如果前面的文档使用的是HTML 4.01，假设我要指定文档的字符编码。理想的方式，是通过服务器在头部信息中发送字符编码，不过也可以在文档这个级别上指定：</p>
<pre class="brush: html; ">

&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;&gt;
</pre>
<p>同样，我也不会把这行代码背下来。我还想省下自己的脑细胞去记点别的更有价值的东西呢。不过，如果我想指定文档使用UTF-8编码，只能添加这行代码。这是在HTML 4.01中需要这样做。要是你在XHTML 1.0指定同样的编码，就得多敲一下键盘，因为你还得声明meta元素位于一个开始的XML标签中。</p>
<pre class="brush: html; ">

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
</pre>
<p>在HTML5中，你要敲的字符只有：</p>
<pre class="brush: html; ">

&lt;meta charset=&quot;utf-8&quot;&gt;
</pre>
<p>简短好记。我能背下来。</p>
<p>同样，这样写也是有效的。它不仅适用于最新版本的浏览器，只要是今天还有人在用的浏览器都同样有效。为什么？因为在我们把这些meta元素输入浏览器时，浏览器会这样解释它：“元数据（meta）点点点点点，字符集（charset）utf-8。”这就是浏览器在解释那行字符串时真正看到的内容。它必须看到这些内容，根据就是伯斯塔尔法则，对不对？</p>
<p>我多次提到健壮性原理，但总有人不理解。我们换一种说法，浏览器会想“好，我觉得作者是想要指定一个字符集……看，没错，utf-8。”这些都是规范里明文规定的。如今，不仅那个斜杠可以省了，而且总共只要写<span class="inline-code">meta charset=&#8221;utf-8&#8243;</span>就行了。</p>
<p>关于省略不必要的复杂性，或者说避免不必要的复杂性的例子还有不少。但关键是既能避免不必要的复杂性，还不会妨碍在现有浏览器中使用。比如说，在HTML5中，如果我使用link元素链接到一个样式表，我说了<span class="inline-code">rel=&#8221;stylesheet&#8221;</span>，然后再说<span class="inline-code">type=&#8221;text/css&#8221;</span>，那就是重复自己了。对浏览器而言，我就是在重复自己。浏览器用不着同时看到这两个属性。浏览器只要看到<span class="inline-code">rel=&#8221;stylesheet&#8221;</span>就够了，因为它可以猜出来你要链接的是一个CSS样式表。所以就不用再指定type属性了。你不是已经说了这是一个样式表了嘛；不用再说第二次了。当然，愿意的话，你可以再说；如果你想包含type属性，请便。</p>
<p>同样地，如果你使用了script元素，你说<span class="inline-code">type=&#8221;text/javascript&#8221;</span>，浏览器差不多就知道是怎么回事了。对Web开发而言，你还使用其他的脚本语言吗？如果你真想用其他脚本语言，没人会阻拦你。但我要奉劝你一句，任何浏览器都不会支持你。</p>
<p>愿意的话，你可以添加一个type属性。不过，也可以什么都不写，浏览器自然会假设你在使用JavaScript。避免-不必要的-复杂性。</p>
<h2>支持已有的内容</h2>
<p>支持已有的内容。这一点非常重要，因为很多人都认为HTML5很新，很闪亮；它应该代表着未来发展的方向，应该把Web推向一个新的发展阶段。这就是HTML5，对吗？显然，我们都会考虑让Web的未来发展得更好，但他们则必须考虑过去。别忘了W3C这个工作组中有很多人代表的是浏览器厂商，他们肯定是要考虑支持已有内容的。只要你想构建一款浏览器，就必须记住这个原则：必须支持已有的内容。</p>
<p>下面我们就来看一个HTML5支持已有内容的例子。</p>
<p>这个例子展示了编写同样内容的四种不同方式。上面是一个img元素，下面是带一个属性的段落元素。四种写法唯一的不同点就是语法。把其中任何一段代码交给浏览器，浏览器都会生成相同的DOM树，没有任何问题。从浏览器的角度看，这四种写法没有区别。因而在HTML5中，你可以随意使用下列任何语法。</p>
<pre class="brush: html; ">

&lt;img src=&quot;foo&quot; alt=&quot;bar&quot; /&gt;
&lt;p class=&quot;foo&quot;&gt;Hello world&lt;/p&gt;

&lt;img src=&quot;foo&quot; alt=&quot;bar&quot;&gt;
&lt;p class=&quot;foo&quot;&gt;Hello world

&lt;IMG SRC=&quot;foo&quot; ALT=&quot;bar&quot;&gt;
&lt;P CLASS=&quot;foo&quot;&gt;Hello world&lt;/P&gt;

&lt;img src=foo alt=bar&gt;
&lt;p class=foo&gt;Hello world&lt;/p&gt;
</pre>
<p>好了，看到这几段代码，恐怕有人会说“不对不对不对。其中只有一个是对的，另外三个——说不好。”不对，应该给属性值加引号！拜托，我们可是一直都给属性值加引号的！元素名大写对吗？这种做法10年不是就被抛弃了吗？</p>
<p>看到HTML5同时允许这些写法，我心里忍不住一阵阵想吐。我写了10年的XHTML 1.0，已经非常适应严格的语法了。但你必须明白，站在浏览器的角度上，这些写法实际上都是一样的。确实没有什么问题。</p>
<p>还有谁也感到不舒服了吗？有谁看到这些之后想“噢，这不是乱写嘛，这样做不对”？只有我这样想吗？还有别人吗？</p>
<p>但是，HTML5必须支持已经存在的内容，而已有的内容就是这个样子的。不是吗？根据伯斯塔尔法则，浏览器没有别的选择。</p>
<p>有人可能会说“这样不行。我觉得语言本身应该提供一种开关，让作者能够表明自己想做什么。”比如说，想使用某种特定的语法，像XHTML，而不是使用其他语法。我理解这些人的想法。但我不赞成在语言里设置开关。因为我们讨论的只是编码风格或者写作风格，跟哪种语法正确无关。对于像我们这样的专业人士，我认为可以使用lint工具（一种软件质量保证工具，或者说是一种更加严格的编译器。它不仅可以象普通编译器那样检查出一般的语法错误，还可以检查出那些虽然完全合乎语法要求，但很可能是潜在的、不易发现的错误），对其他技术我们不是也在使用lint工具嘛。</p>
<p>比如说对JavaScript使用lint工具。JavaScript同样也是比较混乱、不严谨的例子，但它非常强大，原因恰恰是它混乱、不严谨，而且有很多不同的编码方式。在JavaScript，你可以在每条语句末尾加上分号，但不是必需的，因为JavaScript会自动插入分号……是不是听起来有点不好接受？</p>
<p>正因为如此，才有了像JSlint这样的工具，在道格拉斯·克劳克福德（Douglas Crockford）的网站jslint.org上面。有个网页上写着“JSlint可能会伤害你的感情。”但这确实是个非常棒的工具，它可以把JavaScript代码变得完美无瑕。如果你通过JSlint运行JavaScript，它会告诉你“好，你的JavaScript代码有效，但写法不妥。你这种编码风格啊，我不喜欢。不赞成你这样写。这样写不好。”特别是对团队，对于要使用统一的编码风格的团队，JSlint是非常方便的工具。</p>
<p>我个人认为，不仅对团队来说，就算是你自己写代码，也要坚持一种语法风格。从浏览器解析的角度讲，不存在哪种语法比另一种更好的问题，但我认为，作为专业人士，我们必须能够自信地讲“这就是我的编码风格。”然而，我不认为语言里应该内置这种开关。你可以使用lint工具来统一编码风格。现在就来说说lint工具。大家可以登录htmllint.com，在其中运行你的HTML5文档，它会帮你检查属性值是否加了引号，元素是否小写，你还可以通过勾选复选框来设置其他检查项。</p>
<p>但这不意味着拒绝粗心大意的标记，做不做清理完全取决于你自己。我说过，因为浏览器必须支持已有的内容，HTML5自然也不能例外。归根结底还是伯斯塔尔法则。我们始终离不开伯斯塔尔法则。</p>
<h2>解决现实的问题</h2>
<p>HTML5的另一个设计原理是解决现实的问题。显而易见的是，解决各种问题的格式和规范已经比比皆是了，<del datetime="2011-04-07T05:12:24+00:00" title="感谢 @rukey67 指出这个翻译错误">因此在我看来，这个原理其实是要解决理论问题，而非解决现实的问题。这条设计原理是要从理论上承认人们普遍存在的问题，消除敏感问题。</del>但是在我看来，那些格式和规范要解决的都是理论问题，而非现实问题。这条设计原理才是真正要解决今天的人们所面临的现实问题、令人头疼的问题。</p>
<p>下面我来举个例子。相信这个例子有不少人都遇到过。假设我使用HTML 4或XHTML 1，页面中已经有了一块内容，我想给整块内容加个链接，怎么办？问题是这块内容里包含一个标题，一个段落，也许还有一张图片。如果我想给它们全部都可以点击，必须使用3个链接元素。于是，我得先把光标放在标题（比如说h2元素）中，写一个链接标签，然后再选中所有要包含到链接里面来的文本。接着，再把光标放在段落里，写一个链接标签，然后把段落中的文本放在链接里……</p>
<pre class="brush: js; ">

&lt;h2&gt;&lt;a href=&quot;/path/to/resource&quot;&gt;Headline text&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;/path/to/resource&quot;&gt;Paragraph text.&lt;/a&gt;&lt;/p&gt;
</pre>
<p>在HTML5中，我只要简单地把所有内容都包装在一个链接元素中就行了。</p>
<pre class="brush: js; ">

&lt;a href=&quot;/path/to/resource&quot;&gt;
&lt;h2&gt;Headline text&lt;/h2&gt;
&lt;p&gt;Paragraph text.&lt;/p&gt;
&lt;/a&gt;
</pre>
<p>没错，链接包含的都是块级元素，但现在我可以用一个元素包含它们。这样太好了。因为我碰到过类似的情形，必须给几个块级元素加上相同的链接，所有能这样写就太好了。为此，我就非常欢迎HTML5这个新标准。</p>
<p>它解决了一个现实的问题。我敢说在座不少朋友都曾遇到过这个问题。</p>
<p>那这到底解决的是什么问题呢？浏览器不必因此重新写代码来支持这种写法。这种写法其实早就已经存在于浏览器中了，因为早就有人这样写了，当然以前这样写是不合乎规范的。所以，说HTML5解决现实的问题，其本质还是“你都这样写了很多年了吧？现在我们把标准改了，允许你这样写了。”<br />
<img class="colorbox-2151"  src="http://fronteers.nl/_img/congres/2009/attendees-2.jpg" alt="Fronteers 2009" /></p>
<h2>求真务实</h2>
<p>在所有设计原理中，这一条恐怕是最响亮的了——求真务实。不知道大家有没有在公司里开会时听到过这种口号：“开拓进取，求真务实。”实际上，除了作为企业的口号，它还是一条非常重要的设计原理，因为求真务实对于HTML的含义是：在解决那些令人头痛的问题之前，先看看人们为应对这些问题都想出了哪些办法。集中精力去理解这些“民间的”解决方案才是当务之急。</p>
<p>HTML5中新的语义元素就是遵循求真务实原理的反映。新增的元素不算多，谈不上无限的扩展性，但却不失为一件好事。尽管数量屈指可数，但意义却非同一般。这些新元素涉及头部（header）、脚部（footer）、分区（section）、文章（article）……，相信大家都不会觉得陌生。我的意思是说，即便你不使用HTML5，也应该熟悉这些称呼，这些都是你曾经使用过的类名，比如<span class="inline-code">class=&#8221;header&#8221;</span>/<span class="inline-code">&#8220;head&#8221;</span>/<span class="inline-code">&#8220;heading&#8221;</span>，或<span class="inline-code">class=&#8221;footer&#8221;</span>/<span class="inline-code">&#8220;foot&#8221;</span>。当然，也可能是ID，<span class="inline-code">id=&#8221;header&#8221;</span>，<span class="inline-code">id=&#8221;footer&#8221;</span>。这些不都是我们已经司空见惯了的嘛。</p>
<p>好，举个例子吧，假设你今天写了下面这个文档。</p>
<pre class="brush: js; ">

&lt;body&gt;
&lt;div id=&quot;header&quot;&gt;...&lt;/div&gt;
&lt;div id=&quot;navigation&quot;&gt;...&lt;/div&gt;
&lt;div id=&quot;main&quot;&gt;...&lt;/div&gt;
&lt;div id=&quot;sidebar&quot;&gt;...&lt;/div&gt;
&lt;div id=&quot;footer&quot;&gt;...&lt;/div&gt;
&lt;/body&gt;
</pre>
<p>这里有一个div使用了<span class="inline-code">id=&#8221;header&#8221;</span>，另一个div使用了<span class="inline-code">id=&#8221;navigation&#8221;</span>，……。怎么样，都轻车熟路了吧？在HTML5中，这些元素都可以换掉。说起新增的语义元素，它们价值的一方面可以这样来体现：“嘿，看啊，这样多好，用HTML5新增的元素可以把这些div都替换掉。”</p>
<pre class="brush: js; ">

&lt;body&gt;
&lt;header&gt;...&lt;/header&gt;
&lt;nav&gt;...&lt;/nav&gt;
&lt;div id=&quot;main&quot;&gt;...&lt;/div&gt;
&lt;aside&gt;...&lt;/aside&gt;
&lt;footer&gt;...&lt;/footer&gt;
&lt;/body&gt;
</pre>
<p>当然了，你可以这样做。在文档级别上使用这些元素没有问题。但是，假如新增这些元素的目的仅仅是为了取代原来的div，那就真有点多此一举了。</p>
<p>虽然在这个文档中，我们用这些新元素来替换的是ID，但在我个人看来，将它们作为类的替代品更有价值。为什么这么说呢？因为这些元素在一个页面中不止可以使用一次，而是可以使用多次。没错，你可以为文档添加一个头部（header），再添加一个脚部（footer）；但文档中的每个分区（section）照样也都可以有一个头部和一个脚部。而每个分区里还可以嵌套另一个分区，被嵌套的分区仍然可以有自己的头部和脚部，是这样吧？</p>
<p>这四个新元素：section、article、aside和nav，之所以说它们强大，原因在于它们代表了一种新的内容模型，一种HTML中前所未有的内容模型——给内容分区。迄今为止，我们一直都在用div来组织页面中的内容，但与其他类似的元素一样，div本身并没有语义。但section、article、aside和nav实际上是在明确地告诉你——这一块就像文档中的另一个文档一样。位于这些元素中的任何内容，都可以拥有自己的概要、标题，自己的脚部。</p>
<p>其中最为通用的section，可以说是与内容最相关的一个。而article则是一种特殊的section。Aside呢，是一种特殊的section。最后，Nav也是一种特殊的section。</p>
<p>好，即便是现在，你照样可以使用div和类来描述页面中不同的部分，就像下面这样：</p>
<pre class="brush: js; ">

&lt;div class=&quot;item&quot;&gt;
&lt;h2&gt;...&lt;/h2&gt;
&lt;div class=&quot;meta&quot;&gt;...&lt;/div&gt;
&lt;div class=&quot;content&quot;&gt;
...
&lt;/div&gt;
&lt;div class=&quot;links&quot;&gt;...&lt;/div&gt;
&lt;/div&gt;
</pre>
<p>其中包含可能是有关内容作者的元数据，而下面会给出一些链接，差不多就这样。在HTML5中，我完全可以说这块内容就是一个文档，通过对内容分区，使用section或article或aside，我可以说“这一块完全是可以独立存在的。”因此，我当然可以使用header和footer。</p>
<pre class="brush: js; ">

&lt;section class=&quot;item&quot;&gt;
&lt;header&gt;&lt;h1&gt;...&lt;/h1&gt;&lt;/header&gt;
&lt;footer class=&quot;meta&quot;&gt;...&lt;/footer&gt;
&lt;div class=&quot;content&quot;&gt;
...
&lt;/div&gt;
&lt;nav class=&quot;links&quot;&gt;...&lt;/nav&gt;
&lt;/section&gt;
</pre>
<p>请注意，即便是footer，也不一定非要出现在下面，不是吗？这几个元素，header、footer、aside、nav，最重要的是它们的语义；跟位置没有关系。一想到footer这个词，我们总会不由自主地想，“噢，应该放在下面。”同样，我们把aside想象成一个侧边栏。可是，如果你看一看规范，就会发现这些元素只跟内容有关。因此，放在footer中的内容也可以是署名，文章作者之类的，它只是你使用的一个元素。这个元素并没有说“必须把我放在文档或者分区的下面。”</p>
<p>这里，请注意，最重要的还不是我用几个新元素替换了原来的div加类，而是我把原来的H2换成了H1——震撼吧，我看到有人发抖了。我碰到过不少职业的Web开发人员，多年来他们一直认为规范里说一个文档中只能有一个H1。还有一些自诩为万能的SEO秘诀同样说要这样。很多SEO的技巧其实是很教条的。所谓教条，意思就是不相信数据。过去，这种教条表现为“不行，页面中包含两个以上的H1，你就会死掉的。”在HTML5中，只要你建立一个新的内容块，不管用section、article、aside、nav，还是别的元素，都可以在其中使用H1，而不必担心这个块里的标题在整个页面中应该排在什么级别；H2、H3，都没有问题。</p>
<p>这个变化太厉害了。想一想吧，这个变化对内容管理是革命性的。因为现在，你可以把每个内容分区想象一个独立的、能够从页面中拿出来的部分。此时，根据上下文不同，这个独立部分中的H1，在整个页面中没准会扮演H2或H3的角色——取决于它在文档中出现的位置。面对这个突如其来的变化，也许有人的脑子会暂时转不过弯来。不要紧，但我可以告诉你，我认为这才是HTML5中这些新语义标记的真正价值所在。换句话说，我们现在有了独立的元素了，这些元素中的标题级别可以重新定义。</p>
<p>我的文档中可能会包含一个分区，这个分区中可能会嵌套另一个分区，或者一篇文章，然后文章再嵌套分区，分区再嵌套文章、嵌套分区，文章再嵌套文章。而且每个分区和文章都可以拥有自己的H1到H6。从这个意义上讲，H元素真可谓“子子孙孙，无穷匮也”了。但是，在你编写内容或者内容管理系统的时候，它们又都是独立的，完全独立的内容块。这才是真正的价值所在。</p>
<p>实际上，这个点子并不是HTML5工作组拍脑门想出来的，也不是W3C最近才提出来的。下面这几句话摘自蒂姆·伯纳斯-李1991年的一封邮件，邮件是发给丹·康纳利（Dan Connolly）的。他在邮件中解释了对HTML的理解，他说：“你知道……知道我的想法，我认为H1、H2这样单调地排下去不好，我希望它成为一种可以嵌套的元素，或者说一个通用的H元素，我们可以在其中嵌套不同的层次。”但后来，我们没有看到通用的H元素，而是一直在使用H1和H2——那是因为我们一直在支持已有的内容。20年后的今天，这个理想终于实现了。</p>
<h2>平稳退化</h2>
<p>下一条原理大家应该都很熟悉了，那就是平稳退化。毕竟，我们已经遵守这条规则好多年了。渐进增强的另一面就是平稳退化。</p>
<p>有关HTML5遵循这条原理的例子，就是使用type属性增强表单。下面列出了可以为type属性指定的新值，有number、search、range，等等。</p>
<pre class="brush: js; ">

input type=&quot;number&quot;
input type=&quot;search&quot;
input type=&quot;range&quot;
input type=&quot;email&quot;
input type=&quot;date&quot;
input type=&quot;url&quot;
</pre>
<p>最关键的问题在于浏览器在看到这些新type值时会如何处理。现有的浏览器，不是将来的浏览器，现有的浏览器是无法理解这些新type值的。但在它们看到自己不理解的type值时，会将type的值解释为text。</p>
<p>无论你写的是<span style="font-family:'Palatino Linotype';">input type=&#8221;foo&#8221;</span>还是<span style="font-family:'Palatino Linotype';">input type=&#8221;bar&#8221;</bar>，现有的任何浏览器都会说：“嗯，也许作者的意思是text。”因而，你从现在开始就可以使用这些新值，而且你也可以放心，那些不理解它们的浏览器会把新值看成<span style="font-family:'Palatino Linotype';">type=&#8221;text&#8221;</span>，而这真是一个浏览器实践平稳退化原理的好例子。</p>
<p>比如说，你现在输入了<span style="font-family:'Palatino Linotype';">type=&#8221;number&#8221;</span>。假设你需要一个输入数值的文本框。那么你可以把这个input的type属性设置为number，然后理解它的浏览器就会呈现一个可爱的小控件，像带小箭头图标的微调控件之类的。对吧？而在不理解它的浏览器中，你会看到一个文本框，一个你再熟悉不过的文本框。既然如此，为什么不能说输入<span style="font-family:'Palatino Linotype';">type=&#8221;number&#8221;</span>就会得到一个带小箭头图标的微调控件呢？</p>
<p>当然，你还可以设置最小和最大值属性，它们同样可以平稳退化。这是问题的关键。</p>
<p>再看<span style="font-family:'Palatino Linotype';">input type=&#8221;search&#8221;</span>。你也可以考虑一下这种输入框，因为这种输入框在Safari中会被呈现为一个系统级的搜索控件，右边还有一个点击即可清除搜索关键词的X。而在其他浏览器中，你得到的则是一个文本框，就像你写的是<span style="font-family:'Palatino Linotype';">input type=&#8221;text&#8221;</span>一样，也就是你已经非常熟悉的文本框。那为什么还不使用<span style="font-family:'Palatino Linotype';">input type=&#8221;search&#8221;</span>呢？它不会有什么副作用，没有，对不对？</p>
<p>HTML5还为输入元素增加了新的属性，比如placeholder（占位符）。有人不知道这个属性的用处吗，没有吧？没错，就是用于在文本框中预先放一些文本。不对，不是标签（label）——占位符和标签完全不是一回事。占位符就是文本框可以接受的示例内容，一般颜色是灰色的。只要你一点击文本框，它就消失了。如果你把已经输入的内容全部删除，然后单击了文本框外部，它又会出现。</p>
<p>使用JavaScript编写一些代码当然也可以实现这个功能，但HTML5只用一个placeholder属性就帮我们解决了问题。</p>
<p>当然，对于不支持这个属性的浏览器，你还是可以使用JavaScript来实现占位符功能。通过JavaScript来测试浏览器支不支持该属性也非常简单。如果支持，后退一步，把路让开，乐享其成即可。如果不支持，可以再让你的JavaScript来模拟这个功能。</p>
<p>现在，我不得不提到另一个话题了：HTML5对Flash。也许你早听说过了，或者在哪里看到了这方面的讨论。说实话，我一点也不明白。我搞不懂人们怎么会仅仅凭自己的推测来展开争论。</p>
<p>首先，他们所说的HTML5对Flash，并不是指的HTML5，也不是指的Flash。而是指HTML5的一个子集和Flash的一个子集。具体来说，他们指的是视频。因此，不管你在哪里听到别人说“HTML5对Flash”，那很可能说的只是HTML5视频对Flash视频。</p>
<p>其次，一说HTML5对Flash，就好像你必须得作出选择一样：你站在哪一边？实际上不是这样的。HTML5规范的设计能够让你做到鱼和熊掌兼得。</p>
<p>好，下面就来看看这个新的video元素；真是非常贴心的一个元素，而且设计又简单，又实用。一个开始的video元素，加一个结束的video元素，中间可以放后备内容。注意，是后备内容，不是保证可访问性的内容，是后备内容。下面就是针对不支持video元素的浏览器写的代码：</p>
<pre class="brush: js; ">

&lt;video src=&quot;movie.mp4&quot;&gt;
&lt;!-- 后备内容 --&gt;
&lt;/video&gt;
</pre>
<p>那么，在后备内容里面放些什么东西呢？好，你可以放Flash影片。这样，HTML5的视频与Flash的视频就可以协同起来了。你不用作出选择。</p>
<pre class="brush: js; ">

&lt;video src=&quot;movie.mp4&quot;&gt;
&lt;object data=&quot;movie.swf&quot;&gt;
&lt;!-- 后备内容 --&gt;
&lt;/object&gt;
&lt;/video&gt;
</pre>
<p>当然，你的代码实际上并没有这么简单。因为这里我使用了H264，部分浏览器支持这种视频格式。但有的浏览器不支持。</p>
<p>对不起，请不要跟我谈视频格式，我一听就心烦。不是因为技术。技术倒无所谓，关键是会牵扯到一大堆专利还有律师、知识产权等等，这些都是Web的天敌，对我建网站一点好处都没有。</p>
<p>可你实际上要做的，仅仅就是把后备内容放在那而已，后备内容可以包含多种视频格式。如果愿意的话，可以使用source元素而非src属性来指定不同的视频格式。</p>
<pre class="brush: js; ">

&lt;video&gt;
&lt;source src=&quot;movie.mp4&quot;&gt;
&lt;source src=&quot;movie.ogv&quot;&gt;
&lt;object data=&quot;movie.swf&quot;&gt;
&lt;a href=&quot;movie.mp4&quot;&gt;download&lt;/a&gt;
&lt;/object&gt;
&lt;/video&gt;
</pre>
<p>上面的代码中包含了4个不同的层次。<br />
1、如果浏览器支持video元素，也支持H264，没什么好说的，用第一个视频。<br />
2、如果浏览器支持video元素，支持Ogg，那么用第二个视频。<br />
3、如果浏览器不支持video元素，那么就要试试Flash影片了。<br />
4、如果浏览器不支持video元素，也不支持Flash，我还给出了下载链接。</p>
<p>不错，一开始就能考虑这么周到很难得啊。有了这几个层次，已经够完善了。</p>
<p>总之，我是建议你各种技术要兼顾，无论是HTML5，还是Flash，一个也不能少。如果只使用video元素提供视频，难免搬起石头砸自己的脚，我个人认为。而如果只提供Flash影片，情况也好不到哪去，性质是一样的。所以还是应该两者兼顾。</p>
<p>为什么要兼顾这两种技术呢？假设你需要面向某些不支持Flash的手持设备——只是举个例子——提供视频，你当然希望手持设备的用户能够看到视频了，不是吗？</p>
<p>至于为什么要使用不同的格式，为什么Flash视频和音频如此成功，我想可以归结为另一个设计原理，即梅特卡夫定律(Metcalfe&#8217;s Law)：</p>
<p style="padding:2em;background:#eee;">
网络价值同网络用户数量的平方成正比。
</p>
<p>梅特卡夫的这个定律虽然是针对电话网提出来的，但在很多领域里也是适用的。使用网络的用户越多，网络的价值也就越大。人人都上Facebook，还不是因为人人都上Facebook嘛。虽然Facebook真正的价值不在于此，但只有人人都上才会让它的变得如此有价值。</p>
<p>梅特卡夫定律也适用于传真机。如果只有一个人购买了传真机，当然没有什么用处。但如果其他人也陆续购买了传真机，那么他的投资会就得到回报。</p>
<p>当然，面对竞争性的视频格式和不同的编码方式，你感觉不到梅特卡夫定律的作用，我也很讨厌以不同的方式来编码视频，但只向浏览器发送用一种方式编码的视频是行不通的。而这也正是Flash在视频/音频领域如此成功的原因。你只要把Flash影片发送给浏览器就好了，然后安装了插件的浏览器都能正常播放。本质上讲，Flash利用了梅特卡夫定律。</p>
<h2>最终用户优先</h2>
<p>今天我要讲的最后一个设计原理，也是我个人最推崇的一个，但没有要展示的代码示例。这个原理更有哲学的味道，即最终用户优先。</p>
<p>这个设计原理本质上是一种解决冲突的机制。换句话说，当你面临一个要解决的问题时，如果W3C给出了一种解决方案，而WHATWG给出了另一种解决方案，一个人这么想，另一个人那么想……这时候，有人站出来说：“对这个问题我们这样来解决。”</p>
<p style="padding:2em;background:#eee;">
一旦遇到冲突，最终用户优先，其次是作者，其次是实现者，其次标准制定者，最后才是理论上的完满。
</p>
<p>理论上的完满，大致是指尽可能创建出最完美的格式。标准制定者，指的是工作组、W3C，等等。实现者，指的是浏览器厂商。作者，就是我们这些开发人员，对吧？看看我们在这个链条里面的位置多靠上啊！我们的地位仅次于最终用户——事情本来就该这个样子。用户是第一位的。而我们的声音在标准制定过程中也同样非常非常重要。</p>
<p>Hixie（即Ian Hickson， Acid2、Acid3的作者及维护者，HTML5、CSS 2.1规范的制定者）经常说，在有人建议了某个特性，而HTML5工作组为此争论不下时，如果有浏览器厂商说“我们不会支持这个特性，不会在我们的浏览器中实现这个特性”，那么这个特性就不会写进规范。因为即使是把特性写进规范，如果没有厂商实现，规范不过是一纸空文，对不对？实现者可以拒绝实现规范。</p>
<p>而根据最终用户优先的原理，我们在链条中的位置高于实现者，假如我们发现了规范中的某些地方有问题，我们想“这样规定我们不能同意，我们不支持实现这个特性”，那么就等于把相应的特性给否定了，规范里就得删除，因为我们的声音具有更高的权重。我觉得这样挺好！本质上是我们拥有了更大的发言权，对吧？我认为开发人员就应该拥有更多的发言权。</p>
<p>我觉得这应该是最重要的一条设计原理了，因为它承认了你的权利，无论是设计一种格式，还是设计软件，这条原理保证了你的发言权。而这条原理也正道出了事物运行的本质。难道还不够明显吗？用户的权利大于作者，作者的权利大于实现者，实现者的权利大于标准制定者。然而，反观其他规范，比如XHTML2，你就会发现完全相反的做法。把追求理论的完满放在第一位，而把用户——需要忍受严格错误处理带来的各种麻烦的用户——放在了链条的最底端。我并没有说这种做法就是错误的，但我认为这是一种完全不同的思维方式。</p>
<p>因此，我认为无论你做什么，不管是构建像HTML5这样的格式，还是构建一个网站，亦或一个内容管理系统，明确你的设计原理都至关重要。</p>
<p style="padding:2em;background:#eee;">
软件，就像所有技术一样，具有天然的政治性。代码必然会反映作者的选择、偏见和期望。
</p>
<p>下面我们讲一个例子。Drupal社区曾联系马克·博尔顿（Mark Boulton）和丽莎·雷贺特（Leisa Reichilt）设计Drupal的界面。他们计划遵循一些设计原理。为此，他们并没有纸上谈兵，而是经过了一段时间的思考和酝酿，提出指导将来工作的4个设计原理：</p>
<p style="padding:2em;background:#eee;">
简化最常见的任务，让不常见的任务不至于太麻烦。<br />
只为80%设计。<br />
给内容创建者最大的权利。<br />
默认设置智能化。
</p>
<p>实际上，我在跟马克谈到这个问题时，马克说主要还是那两个，即“只为80%设计。给内容创建者最大的权利。”这就很不错了，至少它表明了立场，“我们认为内容创建者比这个项目中的任何人都重要。”在制定设计原理时，很多人花了很多时间都抓不住重点，因为他们想取悦所有人。关键在于我们不是要取悦所有人，而是要明确哪些人最重要。他们认为内容创建者是最重要的。</p>
<p>另一条设计原理，只为80%设计，其实是一条常见的设计原理，也是一种通用模式，即帕累托原理（Pareto principle）。</p>
<p>帕累托是意大利经济学家，他提出这个比例，80/20，说的是世界上20%的人口拥有80%的财富。这个比例又暗合了自然界各个领域的幂律分布现象。总之，无论你是编写软件，还是制造什么东西，都是一样的，即20%的努力可以触及80%的用例。最后20%的用例则需要付出80%甚至更多的努力。因此，有时候据此确定只为80%设计是很合理的，因为我们知道为此只要付出20%的努力即可。</p>
<p>再比如，微格式同样也利用了帕累托原理，只处理常见用例，而没有考虑少数情形。他们知道自己不会让所有人都满意；而他们的目标也不是让所有人都满意。他们遵循的设计原理很多，也都非常有价值，但最吸引人的莫过于下面这条了：</p>
<p style="padding:2em;background:#eee;">
首先为人类设计，其次为机器设计。
</p>
<p>同样，你我都会觉得这是一条再明显不过的道理，但现实中仍然有不少例子违反了这条原理：容易让机器理解（解析）比容易让用户理解更重要。</p>
<p>所以，我认为平常多看一看别人推崇的设计原理，有助于做好自己手头的工作。你可以把自己认为有道理的设计原理贴在墙上。当然，你可以维护一个URL，把自己认为有价值的设计原理分享出来，就像Mozilla基金会那样，对不对，以下是Mozilla的设计原理：</p>
<p style="padding:2em;background:#eee;">
Internet作为一种公共资源，其运作效率取决于互通性（协议、数据格式、内容）、变革及全球范围内的协作。<br />
基于透明社区的流程有助于增进协作、义务和信任。
</p>
<p>我觉得像这样的设计原理都非常好。而有了设计原理，我认为才更有希望设计出真正有价值的产品。设计原理是Web发展背后的驱动力，也是通过HTML5反映出来的某种思维方式。我想，下面这条原理你绝对不会陌生：</p>
<p style="padding:2em;background:#eee;">
<a name="html5_1"></a>大多数人的意见和运行的代码。<a href="#html5_1_note">[1]</a>
</p>
<p>对不对？这句话经常在我脑际回响，它囊括了Web的真谛，触及了HTML5的灵魂。</p>
<p>也许我该把这条原理打印出来贴到办公室的墙上，让它时刻提醒我，这就是Web的设计原理：大多数人的意见和运行的代码。</p>
<p>我想，今天的演讲就到这里了。如果大家有什么想法可以在twitter上通过@adactio找到我。有时候我也会在自己的博客，adactio.com上写写有关这个主题的文章。最后，可能还要顺便给我自己做个广告，我刚出了一本书，希望大家关注。</p>
<p>非常感谢大家。</p>
<p>[全文完]</p>
<p><img class="colorbox-2151"  src="http://ss5.sinaimg.cn/orignal/61baa48dx93226ab35934&#038;690" alt="Fronteers 2010" /></p>
<p>————————————<br />
<a name="html5_1_note"></a><a href="#html5_1">[1]</a> 1992年，大卫·克拉克（David Clark）教授在IETF会议上总结了这样一句话“We reject: kings, presidents, and voting. We believe in: rough consensus and running code”（我们拒绝国王、总统和投票，我们相信大多数人的意见和运行的代码）。这就是广为流传的“互联网哲学”（Internet Philosophy）。——译者注</p>
<p>最后编辑于：<br />
2010/11/07 @ 14:29</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2010/10/21/the-design-of-html5-2151.html/feed</wfw:commentRss>
		<slash:comments>184</slash:comments>
		</item>
		<item>
		<title>从HTML 2.0到HTML5</title>
		<link>http://www.cn-cuckoo.com/2010/09/22/a-brief-history-of-markup-2079.html</link>
		<comments>http://www.cn-cuckoo.com/2010/09/22/a-brief-history-of-markup-2079.html#comments</comments>
		<pubDate>Tue, 21 Sep 2010 17:53:01 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[好书]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2079</guid>
		<description><![CDATA[原文链接：A Brief History of Markup 2010年9月23日校毕 HTML是World Wide Web上统一的语言。使用它所提供的标签，人类已经创建了令人惊奇、姿态万千的超链接的文档网络。看看Amazon、eBay和Wikipedia，再看看个人博客和专为猫咪建立的站点，无一不是HTML的杰作。 HTML5是这门通用语言的最新版。虽然这次升级的变化之大史无前例，但HTML更新换代已经不是第一次了。这门语言从诞生之日起一直在发展。 在发明Web的同时，Tim Berners-Lee先生创造了HTML（HyperText Markup Language，超文本标记语言）。1991年，他写了一篇名为“HTML Tags”的文档（另见更早的www-talk上的记录），其中建议人们使用20来个元素编写网页。 说到用尖括号包围文本的标签，并不是Tim先生的首创。更早的SGML（Standard Generalized Markup Language，标准通用标记语言）中就开始使用这种标签了。Tim先生当时并没有发明新语言，而是着眼于利用已经存在的技术——在HTML5的发展过程中，这个倾向依然得到了体现。 从IETF到W3C：HTML 4诞生记 HTML 1？这个版本实际上是不存在的。最早的HTML官方规范，是由IETF（Internet Engineering Task Force，因特网工程任务组）发布的HTML 2.0。这一规范中的许多特性，都是在已有实现的基础上归纳总结出来的。比如说，1994年居于市场领导地位的Mosaic浏览器提供了一个&#60;img&#62;标签，作者可以通过它在自己的文档中嵌入图像。后来，img元素就出现在了HTML 2.0中。 W3C（World Wide Web Consortium，万维网联盟）继IETF之后成为HTML后续标准的制定者，其官方网站是http://www.w3.org。20世纪90年代中期以后，W3C对HTML进行了几次升级，直至1999年发布HTML 4.01。 此时，HTML的发展走到了一个十字路口上。 XHTML 1：符合XML标准的HTML HMLT 4.01之后的一个修订版变成了XHTML 1.0。其中，X表示“eXtreme”（极端）。当时的Web开发人员在提到这个字母的时候，必须双臂交叉，作出一个X的形状来。 谁说的？纯属瞎掰。那个X表示的是“eXtensible”（可扩展），而且也没人要求你必须双臂交叉。 XHTML 1.0规范的内容与HTML 4.01完全相同，没有添加任何新元素或新属性。这两个规范唯一的差别就是对HTML的语法作出了不同的规定。HTML给予了作者最大的自由度，他们可以按照自己的意愿去写元素和属性，但XHTML要求作者遵从XML规则；XML是W3C大多数技术规范的基础，是一种更为严格的标记语言。 语法规则变得更严格了，这本身没有什么坏处。新规范的目的就是让作者按照统一的风格来编写标签。此前的标签和属性可以是大写、小写，或者任意大小写字母的组合，而有效的XHTML 1.0文档则要求所有标签和属性必须一律小写。 XHTML 1.0发布的时候恰逢浏览器普遍开始支持CSS。开发人员意识到了Web标准的出现，特别是在Web标准项目（The Web Standards Project）的倡导下，XHTML规定的这种更严格的语法被看成是写标记的“最佳实践”。 然后，W3C发布了XHTML 1.1。 虽然XHTML 1.0只不过是用XML来重新表示的HTML，但XHTML 1.1却是真正的、纯粹的XML。这意味着不能以text/html这样的MIME类型来提供XHTML [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: right;">原文链接：<a href="http://www.alistapart.com/articles/a-brief-history-of-markup/" target="_blank">A Brief History of Markup</a><br />
2010年9月23日校毕</p>
<p><div class="wp-caption alignleft" style="width: 405px"><a href="http://books.alistapart.com/products/html5-for-web-designers"><img class="colorbox-2079"  title="HTML5 for Web Designers" src="http://bkaprt.com/i/buy-html5-for-web-designers.png" alt="" width="395" height="554" /></a><p class="wp-caption-text">A Book Apart 的第一本书，由Jeremy Keith执笔；本文是该书第1章。</p></div> HTML是World Wide Web上统一的语言。使用它所提供的标签，人类已经创建了令人惊奇、姿态万千的超链接的文档网络。看看<a href="http://www.amazon.com/">Amazon</a>、<a href="http://www.ebay.com/">eBay</a>和<a href="http://en.wikipedia.org/wiki/Main_Page">Wikipedia</a>，再看看个人博客和专为猫咪建立的站点，无一不是HTML的杰作。</p>
<p>HTML5是这门通用语言的最新版。虽然这次升级的变化之大史无前例，但HTML更新换代已经不是第一次了。这门语言从诞生之日起一直在发展。</p>
<p>在发明Web的同时，Tim Berners-Lee先生创造了HTML（HyperText Markup Language，超文本标记语言）。1991年，他写了一篇<a href="http://www.w3.org/History/19921103-hypertext/hypertext/WWW/MarkUp/Tags.html">名为“HTML Tags”的文档</a>（<a href="http://lists.w3.org/Archives/Public/www-talk/1991SepOct/0003.html">另见更早的www-talk上的记录</a>），其中建议人们使用20来个元素编写网页。</p>
<p>说到用尖括号包围文本的标签，并不是Tim先生的首创。更早的<a href="http://www.iso.org/iso/catalogue_detail.htm?csnumber=16387">SGML（Standard Generalized Markup Language，标准通用标记语言）</a>中就开始使用这种标签了。Tim先生当时并没有发明新语言，而是着眼于利用已经存在的技术——在HTML5的发展过程中，这个倾向依然得到了体现。</p>
<h2>从IETF到W3C：HTML 4诞生记</h2>
<p>HTML 1？这个版本实际上是不存在的。最早的HTML官方规范，是<a href="http://www.ietf.org/">由IETF（Internet Engineering Task Force，因特网工程任务组）</a>发布的<a href="http://tools.ietf.org/html/rfc1866">HTML 2.0</a>。这一规范中的许多特性，都是在已有实现的基础上归纳总结出来的。比如说，1994年居于市场领导地位的<a href="http://en.wikipedia.org/wiki/Mosaic_(web_browser)">Mosaic浏览器</a>提供了一个&lt;img&gt;标签，作者可以通过它在自己的文档中嵌入图像。后来，img元素就出现在了HTML 2.0中。</p>
<p>W3C（World Wide Web Consortium，万维网联盟）继IETF之后成为HTML后续标准的制定者，其官方网站是<a href="http://www.w3.org">http://www.w3.org</a>。20世纪90年代中期以后，W3C对HTML进行了几次升级，直至1999年发布<a href="http://www.w3.org/TR/html401/">HTML 4.01</a>。</p>
<p>此时，HTML的发展走到了一个十字路口上。<br />
<span id="more-2079"></span></p>
<h2>XHTML 1：符合XML标准的HTML</h2>
<p>HMLT 4.01之后的一个修订版变成了<a href="http://www.w3.org/TR/xhtml1/">XHTML 1.0</a>。其中，X表示“eXtreme”（极端）。当时的Web开发人员在提到这个字母的时候，必须双臂交叉，作出一个X的形状来。</p>
<p>谁说的？纯属瞎掰。那个X表示的是“eXtensible”（可扩展），而且也没人要求你必须双臂交叉。</p>
<p>XHTML 1.0规范的内容与HTML 4.01完全相同，没有添加任何新元素或新属性。这两个规范唯一的差别就是对HTML的语法作出了不同的规定。HTML给予了作者最大的自由度，他们可以按照自己的意愿去写元素和属性，但XHTML要求作者遵从XML规则；XML是W3C大多数技术规范的基础，是一种更为严格的标记语言。</p>
<p>语法规则变得更严格了，这本身没有什么坏处。新规范的目的就是让作者按照统一的风格来编写标签。此前的标签和属性可以是大写、小写，或者任意大小写字母的组合，而有效的XHTML 1.0文档则要求所有标签和属性必须一律小写。</p>
<p>XHTML 1.0发布的时候恰逢浏览器普遍开始支持CSS。开发人员意识到了Web标准的出现，特别是在<a href="http://www.webstandards.org/">Web标准项目（The Web Standards Project）</a>的倡导下，XHTML规定的这种更严格的语法被看成是写标记的“最佳实践”。</p>
<p>然后，W3C发布了<a href="http://www.w3.org/TR/xhtml11/">XHTML 1.1</a>。</p>
<p>虽然XHTML 1.0只不过是用XML来重新表示的HTML，但XHTML 1.1却是真正的、纯粹的XML。这意味着不能以text/html这样的<a href="http://en.wikipedia.org/wiki/MIME">MIME类型</a>来提供XHTML 1.1文档。可是，如果有作者以XML的MIMI类型（application/xhtml+xml）来发布文档，那么当时世界上最流行的Web浏览器——Internet Explorer，又无法呈现该文档。</p>
<p>看起来W3C好像已经开始与日常的Web发布脱节了。</p>
<h2>XHTML 2：我们不接受！</h2>
<p>如果达斯汀·霍夫曼（Dustin Hoffman）在电影《毕业生》（<em>The Graduate</em>）中的角色是一名Web设计师，那么W3C只会对他说一句话，就一句话：XML。<a name="footref1"></a><a href="#footnotes1">[1]</a></p>
<p>W3C在接管HTML的时候，HTML的版本已经到了4。现在，他们又着手开发<a href="http://www.w3.org/TR/xhtml2/">XHTML 2</a>，旨在把Web引向建立在XML之上的无比光明的美好未来。</p>
<p>虽然XHTML 2的名字听起来与XHTML 1非常类似，但它们的差别却非常之大。与XHTML 1不一样，XHTML 2与既有的Web内容都不兼容，甚至就连以前版本的HTML都不兼容。说白了，XHTML 2就是要成为一门纯粹的语言，与以前规范的邋遢历史没有任何干系。</p>
<p>没想到竟是一场灾难。</p>
<h2>分裂：WHATWG TF？</h2>
<p>一股反抗势力在W3C内部逐步壮大。W3C热衷于从理论角度构建纯净的标准，却无视Web设计人员的需求。来自<a href="http://www.opera.com/">Opera</a>、<a href="http://www.apple.com/">Apple</a>和<a href="http://www.mozilla.org/">Mozilla</a>的代表对这种倾向非常反感。他们希望那些支持创建Web应用的特性能够得到更多的关注。</p>
<p>2004年的一次工作组会议成了矛盾激化的导火索。<a href="http://ian.hixie.ch/">伊恩·希克森（Ian Hickson）</a>——当时还在Opera Software效力——建议以支持创建Web应用为目标来扩展HTML。这个建议被驳回了。</p>
<p>心怀不满的反抗者建立了自己的组织：<a href="http://www.whatwg.org/">Web Hypertext Application Technology Working Group</a>（Web超文本应用技术工作组），简称WHATWG。</p>
<h2>从Web Apps 1.0到HTML5</h2>
<p>从一开始，WHATWG的工作方式就与W3C截然不同。W3C采取基于表决的方式：提出议题、讨论议题，然后投票表决。而在WHATWG，同样会提出和讨论议题，但哪些特性可以写入规范的最终决定权在编辑手中。这个编辑就是伊恩·希克森。</p>
<p>表面上看，W3C的流程更民主也更公平。但实际上，政治博弈加上内部争论，经常会导致流程停滞不前。而在WHATWG，任何人都可以自由地发表意见，但负责拍板的则只有编辑一个人，因此工作效率明显高很多。其实编辑也并非拥有绝对的权力：一个仅由受邀人员组成的指导委员会可以质疑编辑的偏执做法。</p>
<p>最初，WHATWG的大部分工作被分为两个规范：<a href="http://www.whatwg.org/specs/web-forms/current-work/">Web Form 2.0</a>和<a href="http://www.whatwg.org/specs/web-apps/2005-09-01/">Web Apps 1.0</a>。这两个规范都是在HTML的基础上扩展而来的。后来，这两个规范又被合并到一起，简单地称作<a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/">HTML5</a>。</p>
<h2>再次联手</h2>
<p>在WHATWG开发HTML5期间，W3C继续制定XHTML 2规范。如果说XHTML 2规范的制定速度很快那是忽悠人的。实际上，别提有多慢了。</p>
<p>2006年10月，Tim Berners-Lee先生发表了一篇博客，承认将Web从HTML迁移到XML是行不通的。几个月后，W3C签发了新委任状，成立了一个HTML工作组。这个工作组并没有从头开始，而是明智地决定在WHATWG工作成果的基础上开发下一个HTML版本。</p>
<p>一套起步停车的动作做下来以后，局面反倒让人不理解了。<a href="http://www.w3.org/MarkUp/Activity">W3C同时有两个工作组，分别负责制定不同的、互不兼容的标记语言</a>：<a href="http://www.w3.org/2007/03/XHTML2-WG-charter">XHTML 2</a>和<a href="http://www.w3.org/2007/03/HTML-WG-charter.html">HTML 5</a>（注意数字5前面有一个空格）。与此同时，还有一个独立的组织——WHATWG，正在开发HTML5（没有空格）规范，而该规范还将成为上述W3C中一个规范的基础！</p>
<p>每个想稿清楚上述状况的Web设计人员都会发现，还是破解电影《记忆碎片》（<em>Memento</em>）、《雷管》（<em>Primer</em>）中扑朔迷离的故事情节更容易一些，甚至就连摸清大卫·林奇（David Lynch）这样善用颠倒错乱、诡异多变的形象来迷惑人的导演的套路都没有那么复杂。</p>
<h2>XHTML已死，XHTML语法长生</h2>
<p>种种迷团终于在2009年烟消云散。W3C宣布不再续颁<a href="http://www.w3.org/2007/03/XHTML2-WG-charter">XHTML 2工作组的委任状</a>。XHTML 2作为一种格式实际上已经死了好几年了；这次的宣布差不多可以看成是为它补发了一张死亡证明。</p>
<p>奇怪的是，XHTML 2并没有平静地逝去，不少兴灾乐祸的小人跳出来大放厥词。XML反对者趁机奚落使用XHTML 1的人——连XHTML 1和XHTML 2几乎没有共同点这个事实都视而不见。</p>
<p>这时候，那些遵照XHTML 1较为严格规则的作者又担心起来，生怕HTML5又回到支持邋遢标记的老路上去。</p>
<p>其实，这个担心是多余的。HTML5允许邋邋遢遢的标记，也支持严格的标记，到底邋遢还是严格就要看编写标记的人了。</p>
<h2>HTML5的时间线</h2>
<p>HTML5目前的状态已经不似先前那么含含糊糊了，但仍然还是不甚明了。</p>
<p>有两个工作组在围绕HTML5工作。WHATWG正在使用它的“提交后评审”流程创建HTML5规范。而HTML Working Group则把这个规范作为输入，并将其纳入到了自己的“评审后提交”的流程当中。不难想见，这个联盟并不和谐。最后，仍然还需要就类似“要空格还是不要空格？”这样讨厌的问题达成共识才行。</p>
<p>对于刚刚涉足HTML5的Web开发人员来说，最令他们困惑的一个问题莫过于“这个规范什么时候能够完工啊？”</p>
<p>在一次采访中，伊恩·希克森提到HTML5估计要等到2022年才能成为推荐标准。有些Web设计者听他这么一说，立刻就激动起来。他们并不理解所谓的“推荐标准”意味着什么，但他们知道从现在开始数到2022，自己的10个手指头根本就不够用的。</p>
<p>这种激动完全是没有来由的。想一想吧，成为“推荐标准”，意味必须要有两个HTML5的完整实现。考虑到这个规范涵盖的范围之广，这个时间点恐怕都有点仓促了。历史表明，没有哪款浏览器在实现既有标准方面是做得出色的。仅仅支持一个小小的abbr元素，Internet Explorer就用了10多年的时间。</p>
<p>与HTML5真正有关系的日期应该是2012年。这是它预计将会成为“候选标准”的时间。成为“候选标准”，就意味着标准的制定工作结束了。</p>
<p>不过，即便是这个时间对Web开发人员来说也不是特别重要。真正重要的问题是浏览器从什么时候开始支持HTML5的特性。从浏览器一支持<a href="http://www.w3.org/TR/CSS2/">CSS 2.1</a>的部分特性，我们就开始使用那些特性了。要是等到所有浏览器都完全支持CSS 2.1我们才去使用它，那么恐怕现如今我们在痴痴地等呢。</p>
<p>HTML5不也一样嘛。没有人规定这个时间点，说不到这个时间你就不能使用HTML5。只要浏览器支持，我们就先使用那些它们支持的特性就不完了吗。</p>
<p>切记，HTML5并不是一门凭空造出来的新语言。它的标记变化都是革新性的，不是革命性的。无论你现在使用哪个版本的HTML创建网站，你都可以说自己已经在使用HTML5了。</p>
<hr size="1" /><a name="footnotes1"></a> <a href="#footref1">[1]</a> 男主角本杰明是一位以优异成绩毕业的大学生，其父亲的好友麦奎尔先生对他未来职业规划的建议只有一句话：塑料。——译者注</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2010/09/22/a-brief-history-of-markup-2079.html/feed</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>足够好的革命：便宜简单恰到好处</title>
		<link>http://www.cn-cuckoo.com/2010/09/18/the-good-enough-revolution-2062.html</link>
		<comments>http://www.cn-cuckoo.com/2010/09/18/the-good-enough-revolution-2062.html#comments</comments>
		<pubDate>Sat, 18 Sep 2010 08:38:59 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2062</guid>
		<description><![CDATA[原文：The Good Enough Revolution 2001年，Jonathan Kaplan和Ariel Braunstein注意到摄像机市场中一种奇怪的现象。高端数字相机市场增幅最大，但销量最大的仍然是便宜、一次性的胶卷相机。那一年，美国总共卖出了1.81亿台一次性相机，而数字相机只有大约7百万台。瞅准这个机会，Kaplan和Braunstein组建了一家名为Pure Digital Technologies的公司，尝试把昂贵的数字成像的“巧克力”，与走到哪拍到哪的这种大众市场的“花生奶油”混合起来，创造一种新产品。他们给自己第一款产品起的名字叫Single Use Digital Camera（单用途数字相机），然后通过零售商——主要是像CVS这样的大药房——来发售。 这个概念似乎很有前途，但终究还是有不少缺点。Pure Digital创业管理团队成员Simon Fleming-Wood表示，问题在于这个业务模型意味着人们为了得到照片或CD，必须要向商家再返还20美元。还要假设零售商会把二手相机返回给Pure Digital，然后翻新，从而减少生产新相机的数量。但用户不会很快把相机送回来。有人觉得在1.4英寸的小屏幕上浏览照片可以接受，因此就留着相机，打算过一段时间再去打印。还有人解决了把照片下载到PC的问题，这样就更不会送还相机了。 快速地销售却没有快速回笼作保证，导致公司利润急剧下滑，最终导致相机停产。但是，Kaplan和Braunstein因此认识到：为了经济实惠、方便好用，用户可以放弃很多功能。为了把价格降下来，Pure Digital不得不反复权衡：使用便宜的镜头和其他组件，减少图像处理芯片的数量。拍摄的照片可以接受，但画质并不好。不过，Pure Digital还是卖出去三百万台相机。 对于一般相机零售市场，Kaplan和Braunstein也有了全新的认识。这个市场分成两大块：自动对焦、曝光的消费类相机（包括一次性产品）和独立镜头的单反专业相机（SLR，Single-Lens Reflex），后者可以更换镜头，而且要使用其他高端配件。毋庸置疑，当时相机销售量中的主体都是消费类相机（现在也是）；SLR只对业余摄影爱好者和专业人士有吸引力。 然而，奇怪的是，数字摄像机市场却没有即点即拍的消费类产品——这正是他们看到的下一个机会。家用摄像机几乎清一色都是高价货，内置了防抖、夜视模式以及颜色校正之类的复杂功能。而且，即便使用Apple的iMovie，都很难从拍摄的视频中截取一段放到计算机上编辑和共享。在复杂性和价格方面，便携式摄像机市场类似SLR市场，没有低端即点即拍的摄像机。Kaplan和Braunstein预测更便宜、更简单的视频摄像机将是一个新的市场。因此，他们决定推出一款这种摄像机。 经过反复尝试，Pure Digital在2007年发布了Flip Ultra。这种精简版的摄像机——与Single Use Digital Camera类似——有很多缺点。它的拍摄分辨率比较低，单帧画面只有640×480像素。而Sony、Panasonic和Canon推出的摄像机能够达到1080线的高清晰度。Flip Ultra的观察屏幕很小，也没有颜色调整功能，只有最基本的控制装置。甚至连光学变焦功能都没有。但是，它的个头很小（比一包烟都小）、价格便宜（只卖150美元，Sony中端产品都要800美元），而且操作简单——从录像到上传——几乎所有人都能在6、7秒钟内搞定。 几个月里，Pure Digital开足马力生产也刚刚能够满足订单需求。消费者发现Flip是将自己拍摄的视频分享到骤然流行起来的YouTube上的绝佳方式，这款摄像机获得了极大成功，第一年的销量就超过了1百万台。今天，仅仅两年后，Flip Ultra及其后续改进版，已经登上了美国最受欢迎的数码摄像机榜首，占有便携摄像机市场17%的份额。Sony和Canon都在后面奋力追赶。 Flip的成功让业界为之震惊，但这其实又没有什么值得大惊小怪的。Flip只是我们可以称之为“足够好的”技术的一次成功预演。低价、便捷、简单的工具一夜之间就充斥于每个人的生活当中。我们通过博客获知爆炸性新闻、在Skype上进行长距离质量不一的通话、在小小的电脑屏幕而不是电视上看视频，越来越多的人使用纤小、低能耗、正好能满足其上网和收邮件需求的上网本。各种低端产品和服务的消费量与日俱增。 …… 对这一点，没有人比Pure Digital Technologies那些人理解得更透彻了。两年前，Flip Ultra秉赋着三大可访问性横空出世：一是比其他数码摄像机便宜很多，让人感觉买起来都是一种刺激；二是容易使用，不仅拍摄视频易如反掌，而且向Internet上传视频剪辑同样不费吹灰之力；三是便于携带和Web共享的能力，让用户能够随时随地分享视频。Flip完全符合恰到好处的标准。 在问到为什么Flip能够成功，而其他更强大的摄像机——包括Sony等公司对Flip的仿制产品——会失败时，Pure Digital的Fleming-Wood的回答很有意思：“我觉得是我们的产品更好吧。”奇怪的是，Sony和Canon的高管恐怕也会如是说。毕竟，他们的机型拥有更多功能，拍摄的画质也更好。但Fleming-Wood与他们对“更好”的定义不同。他的质量观的核心是容易使用——拍摄与分享视频更容易。“把自己的视频剪辑与别人分享，是每一个人都想要的。”他说。 即使如此也不难想见，有朝一日Flip也将被种种滋生的功能所困。事实上，该公司最新发布了能录制高清视频的HD机型。好了，既然如此，为什么不能期待防抖动、大LCD——甚至：嘿，换成触摸屏如何？“我们将始终优先考虑可访问性，然后考虑的才是功能。”Fleming-Wood强调。像素数提升只不过是关于芯片速度和存储容量提升的摩尔定律作用的结果，并不是Pure Digital要改弦更张的信号。在HD组件不会明显提高成本，也不会导致使用更复杂的情况下，“没有理由不推出HD，”Fleming-Wood说。他指出，Pure Digital还会加入光学变焦、防抖动等功能，他知道人们喜欢Flip就是因为通过它拍摄和分享视频非常简单。“这一点我们永远不会丢弃。” 在谋划Flip未来的产品时，Fleming-Wood打算加入能够使分享视频变得更容易的功能。“嗯，我们可以加上Wi-Fi或单元互联功能，这样在你拍摄孩子的足球比赛时，可以实时将视频上传到Web，而奶奶就可以在家里观战了。”言语间流露出一位幻想家的激情。要实现这么宏伟的目标，恐怕得选牺牲一点HD的品质。没问题，只要足够好就可以了。 附注：2009年3月19日，思科宣布收购数码摄像机制造商Pure Digital，拟加强该公司在消费电子市场的影响力，以使思科成为大众熟知的品牌。]]></description>
			<content:encoded><![CDATA[<p style="text-align: right;">原文：<a title="The Good Enough Revolution: When Cheap and Simple Is Just Fine" href="http://www.wired.com/gadgets/miscellaneous/magazine/17-09/ff_goodenough" target="_blank">The Good Enough Revolution</a></p>
<p>2001年，Jonathan Kaplan和Ariel Braunstein注意到摄像机市场中一种奇怪的现象。高端数字相机市场增幅最大，但销量最大的仍然是便宜、一次性的胶卷相机。那一年，美国总共卖出了1.81亿台一次性相机，而数字相机只有大约7百万台。瞅准这个机会，Kaplan和Braunstein组建了一家名为Pure Digital Technologies的公司，尝试把昂贵的数字成像的“巧克力”，与走到哪拍到哪的这种大众市场的“花生奶油”混合起来，创造一种新产品。他们给自己第一款产品起的名字叫Single Use Digital Camera（单用途数字相机），然后通过零售商——主要是像CVS这样的大药房——来发售。</p>
<p>这个概念似乎很有前途，但终究还是有不少缺点。Pure Digital创业管理团队成员Simon Fleming-Wood表示，问题在于这个业务模型意味着人们为了得到照片或CD，必须要向商家再返还20美元。还要假设零售商会把二手相机返回给Pure Digital，然后翻新，从而减少生产新相机的数量。但用户不会很快把相机送回来。有人觉得在1.4英寸的小屏幕上浏览照片可以接受，因此就留着相机，打算过一段时间再去打印。还有人解决了把照片下载到PC的问题，这样就更不会送还相机了。</p>
<p>快速地销售却没有快速回笼作保证，导致公司利润急剧下滑，最终导致相机停产。但是，Kaplan和Braunstein因此认识到：为了经济实惠、方便好用，用户可以放弃很多功能。为了把价格降下来，Pure Digital不得不反复权衡：使用便宜的镜头和其他组件，减少图像处理芯片的数量。拍摄的照片可以接受，但画质并不好。不过，Pure Digital还是卖出去三百万台相机。</p>
<p>对于一般相机零售市场，Kaplan和Braunstein也有了全新的认识。这个市场分成两大块：自动对焦、曝光的消费类相机（包括一次性产品）和独立镜头的单反专业相机（SLR，Single-Lens Reflex），后者可以更换镜头，而且要使用其他高端配件。毋庸置疑，当时相机销售量中的主体都是消费类相机（现在也是）；SLR只对业余摄影爱好者和专业人士有吸引力。<br />
<span id="more-2062"></span><br />
然而，奇怪的是，数字摄像机市场却没有即点即拍的消费类产品——这正是他们看到的下一个机会。家用摄像机几乎清一色都是高价货，内置了防抖、夜视模式以及颜色校正之类的复杂功能。而且，即便使用Apple的iMovie，都很难从拍摄的视频中截取一段放到计算机上编辑和共享。在复杂性和价格方面，便携式摄像机市场类似SLR市场，没有低端即点即拍的摄像机。Kaplan和Braunstein预测更便宜、更简单的视频摄像机将是一个新的市场。因此，他们决定推出一款这种摄像机。</p>
<p>经过反复尝试，Pure Digital在2007年发布了Flip Ultra。这种精简版的摄像机——与Single Use Digital Camera类似——有很多缺点。它的拍摄分辨率比较低，单帧画面只有640×480像素。而Sony、Panasonic和Canon推出的摄像机能够达到1080线的高清晰度。Flip Ultra的观察屏幕很小，也没有颜色调整功能，只有最基本的控制装置。甚至连光学变焦功能都没有。但是，它的个头很小（比一包烟都小）、价格便宜（只卖150美元，Sony中端产品都要800美元），而且操作简单——从录像到上传——几乎所有人都能在6、7秒钟内搞定。</p>
<p style="text-align: center;"><a href="http://www.theflip.com/en-us/"><img class="aligncenter colorbox-2062" src="http://www.sinaimg.cn/IT/digi/2007-09-14/4028a1d8627365b64610b7fd34ecc7ad.jpg" alt="" width="500" height="333" /></a></p>
<p>几个月里，Pure Digital开足马力生产也刚刚能够满足订单需求。消费者发现Flip是将自己拍摄的视频分享到骤然流行起来的YouTube上的绝佳方式，这款摄像机获得了极大成功，第一年的销量就超过了1百万台。今天，仅仅两年后，Flip Ultra及其后续改进版，已经登上了美国最受欢迎的数码摄像机榜首，占有便携摄像机市场17%的份额。Sony和Canon都在后面奋力追赶。</p>
<p>Flip的成功让业界为之震惊，但这其实又没有什么值得大惊小怪的。Flip只是我们可以称之为“足够好的”技术的一次成功预演。低价、便捷、简单的工具一夜之间就充斥于每个人的生活当中。我们通过博客获知爆炸性新闻、在Skype上进行长距离质量不一的通话、在小小的电脑屏幕而不是电视上看视频，越来越多的人使用纤小、低能耗、正好能满足其上网和收邮件需求的上网本。各种低端产品和服务的消费量与日俱增。</p>
<p>……</p>
<p>对这一点，没有人比Pure Digital Technologies那些人理解得更透彻了。两年前，Flip Ultra秉赋着三大可访问性横空出世：一是比其他数码摄像机便宜很多，让人感觉买起来都是一种刺激；二是容易使用，不仅拍摄视频易如反掌，而且向Internet上传视频剪辑同样不费吹灰之力；三是便于携带和Web共享的能力，让用户能够随时随地分享视频。Flip完全符合恰到好处的标准。</p>
<p>在问到为什么Flip能够成功，而其他更强大的摄像机——包括Sony等公司对Flip的仿制产品——会失败时，Pure Digital的Fleming-Wood的回答很有意思：“我觉得是我们的产品更好吧。”奇怪的是，Sony和Canon的高管恐怕也会如是说。毕竟，他们的机型拥有更多功能，拍摄的画质也更好。但Fleming-Wood与他们对“更好”的定义不同。他的质量观的核心是容易使用——拍摄与分享视频更容易。“把自己的视频剪辑与别人分享，是每一个人都想要的。”他说。</p>
<p>即使如此也不难想见，有朝一日Flip也将被种种滋生的功能所困。事实上，该公司最新发布了能录制高清视频的HD机型。好了，既然如此，为什么不能期待防抖动、大LCD——甚至：嘿，换成触摸屏如何？“我们将始终优先考虑可访问性，然后考虑的才是功能。”Fleming-Wood强调。像素数提升只不过是关于芯片速度和存储容量提升的摩尔定律作用的结果，并不是Pure Digital要改弦更张的信号。在HD组件不会明显提高成本，也不会导致使用更复杂的情况下，“没有理由不推出HD，”Fleming-Wood说。他指出，Pure Digital还会加入光学变焦、防抖动等功能，他知道人们喜欢Flip就是因为通过它拍摄和分享视频非常简单。“这一点我们永远不会丢弃。”</p>
<p>在谋划Flip未来的产品时，Fleming-Wood打算加入能够使分享视频变得更容易的功能。“嗯，我们可以加上Wi-Fi或单元互联功能，这样在你拍摄孩子的足球比赛时，可以实时将视频上传到Web，而奶奶就可以在家里观战了。”言语间流露出一位幻想家的激情。要实现这么宏伟的目标，恐怕得选牺牲一点HD的品质。没问题，只要足够好就可以了。</p>
<div id="_mcePaste"><strong>附注：2009年3月19日，思科宣布收购数码摄像机制造商Pure Digital，拟加强该公司在消费电子市场的影响力，以使思科成为大众熟知的品牌。</strong></div>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2010/09/18/the-good-enough-revolution-2062.html/feed</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>Rich Stevens答读者问</title>
		<link>http://www.cn-cuckoo.com/2010/09/12/rich-stevens-faq-2007.html</link>
		<comments>http://www.cn-cuckoo.com/2010/09/12/rich-stevens-faq-2007.html#comments</comments>
		<pubDate>Sun, 12 Sep 2010 14:00:31 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[好书]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=2007</guid>
		<description><![CDATA[原文链接：http://www.kohala.com/start/rstevensfaq.html 校对时间：2010年9月19日 问题TOC 你怎么想到要写UNIX Network Programming？ 你为什么要写Advanced Programming in the UNIX Environment？ 你为什么要写TCP/IP Illustrated, Volume 1: The Protocols？ 你为什么要写TCP/IP Illustrated, Volume 2: The Implementation？ 你为什么要写TCP/IP Illustrated, Volume 3: TCP for Transactions, HTTP, NNTP, and the Unix Domain Protocols？ 我应该看其中哪本书？ 你跟Doug Comer合作写过书吗？ 写一本书要花多长时间？ 在写这些书的时候你是通过哪些方式来学习的？ 你会回复读者的邮件吗？ 我也想写一本书。我该从何做起呢？ 能谈一谈UNIX Network Programming是怎么出版的吗？ 你并没有使用troff写书，是吗？ 你使用哪种Unix系统？ 你喜欢哪些技术书？ 你名字中的W.表示什么？ 你为什么专门为MTS（Michigan Terminal System）写APUE呢？ [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: right;">原文链接：<a href="http://www.kohala.com/start/rstevensfaq.html">http://www.kohala.com/start/rstevensfaq.html</a><br />
校对时间：2010年9月19日</p>
<h2><a name="Rich_Stevens_FAQ_TOC">问题TOC</a></h2>
<ul style="background:#eee;padding:2em;">
<li><a href="#Rich_Stevens_FAQ_1">你怎么想到要写<em>UNIX Network Programming</em>？</a></li>
<li><a href="#Rich_Stevens_FAQ_2">你为什么要写<em>Advanced Programming in the UNIX Environment</em>？
<li><a href="#Rich_Stevens_FAQ_3">你为什么要写<em>TCP/IP Illustrated, Volume 1: The Protocols</em>？
<li><a href="#Rich_Stevens_FAQ_4">你为什么要写<em>TCP/IP Illustrated, Volume 2: The Implementation</em>？</a></li>
<li><a href="#Rich_Stevens_FAQ_5">你为什么要写<em>TCP/IP Illustrated, Volume 3: TCP for Transactions, HTTP, NNTP, and the Unix Domain Protocols</em>？<br />
</a></li>
<li><a href="#Rich_Stevens_FAQ_6">我应该看其中哪本书？</a></li>
<li><a href="#Rich_Stevens_FAQ_7">你跟Doug Comer合作写过书吗？</a></li>
<li><a href="#Rich_Stevens_FAQ_8">写一本书要花多长时间？</a></li>
<li><a href="#Rich_Stevens_FAQ_9">在写这些书的时候你是通过哪些方式来学习的？</a></li>
<li><a href="#Rich_Stevens_FAQ_10">你会回复读者的邮件吗？</a></li>
<li><a href="#Rich_Stevens_FAQ_11">我也想写一本书。我该从何做起呢？</a></li>
<li><a href="#Rich_Stevens_FAQ_12">能谈一谈UNIX Network Programming是怎么出版的吗？</a></li>
<li><a href="#Rich_Stevens_FAQ_13">你并没有使用troff写书，是吗？</a></li>
<li><a href="#Rich_Stevens_FAQ_14">你使用哪种Unix系统？</a></li>
<li><a href="#Rich_Stevens_FAQ_15">你喜欢哪些技术书？</a></li>
<li><a href="#Rich_Stevens_FAQ_16">你名字中的W.表示什么？</a></li>
<li><a href="#Rich_Stevens_FAQ_17">你为什么专门为MTS（Michigan Terminal System）写APUE呢？</a></li>
<li><a href="#Rich_Stevens_FAQ_18">你编写的程序里为什么会包含goto？</a></li>
</ul>
<p>问：<strong>你怎么想到要写</strong><em><strong>UNIX Network Programming</strong></em><strong>？</strong><a name="Rich_Stevens_FAQ_1" href="#Rich_Stevens_FAQ_TOC">返回TOC</a></p>
<p>1980年代，我在Health Systems International工作，那时候我们先后为很多平台开发过Unix<a name="notes1" href="#footnotes1">[1]</a>软件。我们跟大多数同时代的创业公司一样，经历过一系列硬件的变迁：起先是VAX-11/750<a name="notes2" href="#footnotes2">[2]</a>，运行4.2BSD<a name="notes3" href="#footnotes3">[3]</a>，然后是个头稍大的VAX（785），接着又是多台VAX（又加了一台8500），有几台PC运行着一种风格的操作系统（Venix、Xenix<a name="notes4" href="#footnotes4">[4]</a>、DOS），另外还有一台IBM大型机运行VM。因为有多台VAX运行4.xBSD，所以我们就通过以太网把它们连接起来运行TCP/IP，当然装有Unix系列操作系统的PC和那台大型机也都可以运行TCP/IP。除了使用标准的实用工具（ftp、rlogin），我们还着手使用套接字自己开发工具。当时几乎没有文档可查（我从一堆4.3BSD手册中找到两本Leffler等人编写的文档，但非常破旧），因而在想解决某个问题时，就得查源代码。就这样查了一段时间的源代码之后，我意识到应该把自己发现的东西诉诸文字。1988年我开始写UNP，因为每天都要工作，所以这本书写了两年。</p>
<p>我相信UNP以及我的其他书之所以能够获得成功，是我的背景起了决定性的作用。换句话说，我既不是Berkeley也不是AT&amp;T的开发人员，因此写作中就没有“内存转储”<a name="notes5" href="#footnotes5">[5]</a>的问题。书中的所有内容都是我自己经过深入钻研想明白的。在深入钻研和思考各种原理的过程中，我经常会绕很大的弯子，有时候甚至会走进死胡同。但这个过程对于理解新知识是极为必要的。有很多次我想在书中把某方面的工作原理写出来，自己也觉得很明白，但才刚写了几个测试程序，马上就又碰到了新的、不懂的问题。我在自己的几本书中也尽力传达了这种探索的盲目性，因为我觉得看到某个问题的错误解决方案（并理解它错在哪里），常常要比直接看到正确的解决方案收获更大。</p>
<p>问：<strong>你为什么要写</strong><em><strong>Advanced Programming in the UNIX Environment</strong></em><strong>？</strong><a name="Rich_Stevens_FAQ_2" href="#Rich_Stevens_FAQ_TOC">返回TOC</a></p>
<p>整个1980年代，我翻看最勤的就是Marc Rochkind的<em>Advanced UNIX Programming</em>。但那本书的内容只涵盖了System III<a name="notes6" href="#footnotes6">[6]</a>，我也知道他没有升级那本书的打算。所以，我决定自己写一本高级的Unix图书。</p>
<p>问：<strong>你为什么要写</strong><em><strong>TCP/IP Illustrated, Volume 1: The Protocols</strong></em><strong>？</strong><a name="Rich_Stevens_FAQ_3" href="#Rich_Stevens_FAQ_TOC">返回TOC</a></p>
<p>我对TCP/IP产生兴趣始于1987年夏天在菲尼克斯（Phoenix，美国亚利桑纳州首府）召开的Summer Usenix<a name="notes7" href="#footnotes7">[7]</a>大会，当时我买了一本Doug Comer的<em>Internetworking With Xinu</em><a name="notes8" href="#footnotes8">[8]</a>。（我是在Jim Joyce的书店买的这本书，这个书店开在酒店的一个套间里，他可能也是第一个尝试在Usenix大会上卖书的人。会场上是不允许卖书的。）在回康涅狄格的飞机上，我从头到尾看完了这本书。撰写UNP期间以及1990年代早几年，Doug Comer“卷I”的第1版和第2版先后都被我翻得书脊开了胶。我毕竟是一个业内人士，相对于理论阐述，我更关心对实际工作有指导意义的内容。在翻阅Doug这本教材的过程中，我不断提出一些非常实际但又在书中找不到答案的问题。与此同时，一位在IBM教TCP/IP的朋友也时不时地向我询问一些问题，而这些问题不管是在RFC规范还是其他任何教材中同样也找不到答案。我开始编写一些小测试程序，观察程序运行的结果（参见我这本书的“附录C：sock程序”的开头），冥冥之中感觉到以这种方式来写一本书倒是个不错的主意。我也知道有很多唾手可得的现成工具（大多数都是Van Jacobson写的，了不起！）可以帮我理解这两个协议，这些工具谁都可以拿来用。比如说Tcpdump吧，它不仅仅是一个诊断网络问题的工具，更是一个辅助理解协议原理的无价之宝。最终，在经历了数年的网络编程之后，我慢慢地认识到：80%的网络编程问题根本就不是编程问题，都是对协议运行原理理解不够造成的。</p>
<p>问：<strong>你为什么要写</strong><em><strong>TCP/IP Illustrated, Volume 2: The Implementations</strong></em><strong>？</strong><a name="Rich_Stevens_FAQ_4" href="#Rich_Stevens_FAQ_TOC">返回TOC</a></p>
<p>同样，我是Doug Comer的“卷II”（TCP/IP的Xinu实现）的忠实读者，但在遇到没有实现的功能时总会感到很无助，况且Xinu也不是标准。Berkeley的实现才是事实标准，而且其代码基也“小”（15000行C代码）到可以用1本书——尽管是一本“大”书——来讲完。</p>
<p>问：<strong>你为什么要写</strong><em><strong>TCP/IP Illustrated, Volume 3: TCP for Transactions, HTTP, NNTP, and the Unix Domain Protocols</strong></em><strong>？</strong><a name="Rich_Stevens_FAQ_5" href="#Rich_Stevens_FAQ_TOC">返回TOC</a></p>
<p>这本书实际上是由3本更小的书构成的。第一部分“TCP for Transactions”是对Volume 1第24.7节的重要扩展。这一部分从两个方面讲解了T/TCP：一是通过实例讲解TCP协议扩展（第1至4章，延续了Volume 1的风格），二是分析了4.4BSD-Lite连网代码对T/TCP的实现（第5至13章，延续了Volume 2的风格）。第二部分“HTTP（Hypertext Transfer Protocol） and NNTP（Network News Transfer Protocol）”是对Volume 1的补充，因为这一部分讲解了构建于TCP之上的两个应用层协议。其中有一章详细地解释了繁忙的World Wide Web服务器上实际的数据包，展示了多变的、有时候完全不可思议的TCP行为及实现。这两部分的主题完全取材于Volume 1和Volume 2，而且都是相关领域中重要而流行的实际应用。第三部分“Unix Domain Protocols”是对Volume 2的补充，因为这一部分专注于这些协议在4.4BSD-Lite连网代码中的实现。所以说，最后这一卷其实是对前两卷的一个延伸。</p>
<p>问：<strong>我应该看其中哪本书？</strong><a name="Rich_Stevens_FAQ_6" href="#Rich_Stevens_FAQ_TOC">返回TOC</a></p>
<p>这取决于你对哪个领域感兴趣。UNP是一本网络编程教材：包含15000行C源代码和大量有关网络编程的详细解释。但是，UNP只介绍了基本的Unix和TCP/IP。相对而言，APUE则完全是一本Unix编程教材，没有涉及网络编程。事实上，可以将APUE看作是对UNP第2章的一个重要扩展。TCP/IPIv1纯粹讲协议：这些协议怎么运行，为什么那么运行（是对UNP第5.2节的一个重要扩展）。这本书里连一行C代码都没有。TCP/IPIv2讲的是TCP/IP的实际实现：包含15000行内核中的C源代码。TCP/IPIv3则是由协议（T/TCP、HTTP、NNTP）和实现（大约2200行内核C源代码）构成的。</p>
<p>我自己对网络编程非常感兴趣，但是我发现要做好网络编程，必须理解网络底层的运行系统（APUE）和底层的协议（TCP/IPIv[123]）。</p>
<p>问：<strong>你跟Doug Comer合作写过书吗？</strong><a name="Rich_Stevens_FAQ_7" href="#Rich_Stevens_FAQ_TOC">返回TOC</a></p>
<p>没有，那个人是普渡大学的David L. Stevens。我们不是一个人。</p>
<p>问：<strong>写一本书要花多长时间？</strong><a name="Rich_Stevens_FAQ_8" href="#Rich_Stevens_FAQ_TOC">返回TOC</a></p>
<p>每一面大约要花2小时左右。这个时间包含了为出版商制作可供照排机使用的PostScript<a name="notes9" href="#footnotes9">[9]</a>文件的时间。这样算来，一本600页的书，大约要花1200小时。如果你不制作供照排机使用的文件（例如，让出版商自己排版和做索引），还可以节省一点时间，但我喜欢完全控制最终结果。</p>
<p>问：<strong>在写这些书的时候你是通过哪些方式来学习的？</strong><a name="Rich_Stevens_FAQ_9" href="#Rich_Stevens_FAQ_TOC">返回TOC</a></p>
<p>我阅读了大量源代码。实际上，阅读源代码的技能大学里通常都不会教，但其实要看懂代码也不是一件多难的事。（还记得John Lion在1977年出版的那本完整展示和分析UNIX Version 6源代码的A Commentary on the UNIX Operating System<a name="notes10" href="#footnotes10">[10]</a>吗？我很幸运，读研究生的时候，Dave Hanson就拿这本书当教材给我们上课。）虽然我看不到大多数Unix商业版的源代码，但好在仍有不少系统的源代码可以供我研究，例如：4.4BSD-Lite、FreeBSD、Linux、Minix、GNU，等等。</p>
<p>另外，我还会从一些有用的Usenet新闻组中学习。在新闻组里，可以看到解决相同问题的不同手段，可以学到从来没听说过的新知识，也可以目睹别人遇到的一些问题。我每天在Usenet上面阅读和发帖的时间大约是25分钟。</p>
<p>以下是我经常上的一些新闻组：news.admin.announce、comp.security.announce、comp.protocols.tcp-ip、comp.dcom.sys.cisco、comp.unix.bsd.bsdi.announce、comp.unix.bsd.bsdi.misc、info.bsdi.users、comp.unix.solaris、comp.unix.internals、comp.unix.programmer、comp.protocols.dns.bind、comp.protocols.dns.std、comp.protocols.dns.ops、comp.programming.threads、gnu.groff.bug、gnu.announce、gnu.gcc.announce、gnu.g++.announce、misc.books.technical、comp.protocols.time.ntp、comp.protocols.tcp-ip.domains、comp.org.usenix、comp.mail.mush、comp.protocols.nfs、comp.std.unix、comp.text、alt.sys.sun、comp.sys.sun.announce、comp.sys.sun.hardware、comp.std.announce、comp.os.linux.announce、comp.lang.java.announce和comp.lang.java.programmer。</p>
<p>问：<strong>你会回复读者的邮件吗？</strong><a name="Rich_Stevens_FAQ_10" href="#Rich_Stevens_FAQ_TOC">返回TOC</a></p>
<p>当然。我的电子邮件地址印在了这几本书前言的末尾，我会看收到的每一封邮件。不过，由于邮件的格式混乱，可读性差，这几年我还设计了几种推荐的标准格式。想知道这个标准格式的最简单快捷的方法，就是把你想让我帮你调试的源代码发给我（别笑，要是知道我收到过多少封包含这种请求的邮件，你就不会惊讶了）。其次，可以把构建书中某些源代码期间得到的make输出发给我，并问我怎么解决——出版商好心好意地提供了全部代码下载，但这些代码也只是提供下载而已，并不意味着他们配备了专人来答疑解惑。诸如此类的问题大多数都应该贴到相应Unix版本的新闻组中。</p>
<p>还有不少邮件询问我几年前写过的某篇文章中的某个具体的问题，信不信由你，这些细节我很难一下子都想起来。我的基本原则是，只要我能想出问题的答案，而且不必敲太多次键盘，我就会马上回复。可如果回答问题还需要翻箱倒柜地找书，乃至查阅相关资料，或者需要跟发件人来往通几次信以便了解问题的更多细节，我想我是没有这个时间的。</p>
<p>有很多读者通过邮件问我的编程问题，都应该发到某些Usenet新闻中去——特别是comp.unix.programmer。</p>
<p>问：<strong>我也想写一本书。我该从何做起呢？</strong><a name="Rich_Stevens_FAQ_11" href="#Rich_Stevens_FAQ_TOC">返回TOC</a></p>
<p>技术书市场跟小说市场完全不同。技术出版商无时无刻不在寻找好书，作者有没有名气都没有关系。我建议你先写出来一些东西（比如，书中比较主要的几章），然后再联系出版公司。联系出版公司的最佳途径是参加技术会议（Usenix、Interop，等等），到他们的展台前当面谈。正常情况下，他们都会对你非常热情的。</p>
<p>再给几个简单的建议：</p>
<ul>
<li>不要在太细节的内容上花过多时间。我保证这样写出来的东西90%都要改。</li>
<li>不要在导言那一章（通常是第1章）花太多时间，等写完全书再回过头来写。一般来说，这一章是全书最重要的一章，因为它肩负着向读者介绍其他章节内容的重任。想想看，在写完全书之前，有些内容没准是会变的。</li>
<li>如果承受不了批评就不要写书。以下是UNP第1版征求意见稿反馈回来的一些评论，你听听：“啊！这家伙难道一点语法和表达都不懂吗？”“怎么这个人我从来都没听说过呢？”“把括号里那些废话都删了算了”“术语前后不统一。”UNP第2版也有一些难听的话：“整本书到处都是以……开头的句子，根本没法理解。”</li>
</ul>
<p>另外，要做好重写、重写、再重写的心理准备。<a target="_blank" href="http://www.kohala.com/start/gifs/unprewrite.gif">这是UNIX Network Programming, Second Edition, Volume 1中的一页（280K的GIF图）</a>，看了之后你就知道我说的重写是什么意思了。这是该书第92/93页定稿前的一张照片，愿意的话你可以比较一下。而且，这还只是我自己校正某些表述时所做的修改，是交给其他审稿人审读之前的样子。</p>
<p>问：<strong>能谈一谈UNIX Network Programming是怎么出版的吗？</strong><a name="Rich_Stevens_FAQ_12" href="#Rich_Stevens_FAQ_TOC">返回TOC</a></p>
<p>前面说过，我是1998年开始写UNP的，基本素材是我整理的一些记录Berkeley连网代码工作原理的内部笔记。至于为什么要写这方面的书，我现在好像也没办法说得很清楚，不过倒是有几个小理由。首先，我已经在一家创业公司（HSI）工作了6年，公司发展很快，编程人员也越来越多，我可以多腾出一点时间来去做些别的事情，不用成天写代码和补漏洞了。加之，我取得博士学位也已经有6个年头了，而我在技术方面的著述还是零纪录。最后，我在HSI又招聘到了这个新人（Gray Wright），刚刚走出校门，思维敏捷，我只有在技术上不断进取，才不至被他落下。（UNP的前言里面提到过Gary，他是第一个阅读我写的所有文字的人。）</p>
<p>在决定了写书之后，接着还得决定要写什么。我个人想写一本计算机图形和网络方面的书。1987年我到楠塔基特岛（Nantucket，位于美国马萨诸塞州东南沿海的岛屿，避暑胜地）过感恩节，我记得当时还带着Tanenbaum<a name="notes11" href="#footnotes11">[11]</a>的Computer Networks和Foley与Van Dam合著的Fundamentals of Interactive Computer Graphics。但在我回到家以后，我就决定写一本网络编程方面的书。说写就写，我最早给这本书起的名字叫Network Programming。跟大多数新作者一样，我白天上班，晚上利用“闲暇时间”写我的第一本书。</p>
<p>我至今还保存着1989年1月Usenet上的一个帖子：“我正在找一本关于Unix的好书（难道你们大家不想吗？）。我对Unix以及C和Shell编程都已经非常熟悉了。现在打算学习Unix通信方面的知识，例如：套接字、协议，等等。”一周后，另一个标题为“IPC的问题”的帖子询问了实现IPC（Internet Process Connection，进程间通信）的各种方法的细节，我看那些内容都是Marc Rochkind<a name="notes12" href="#footnotes12">[12]</a>的书里没有讲到的。这些提问让我感觉到自己的决定是正确的。还有一个帖子是Rick Adams在1988年11月23日发的：“终于等到这一天了，不含ATT代码的4.3BSD文件现在人人可用了。”这意味着我可以在这本书里使用Berkeley的代码了。</p>
<p>就这样埋头写了几个月之后，我觉得应该看一看自己写的这些东西有没有出版价值。我跟贝尔实验室一个在Prentice Hall出版社出过书的朋友联系，他给了我那里一位编辑John Wait的电话号码。1988年6月我打了电话，并给他的秘书留了言，然后他竟然给我回了电话！他说话很有意思，想看看我写的东西，告诉我他会参加那一年在旧金山举行的USENIX大会。我注册了这次会议，但最后是让Gary Wright替我去的；他戴我的胸牌。Gary把我的手稿（278页）交给了John。（Gray不久后又在Unix Expo大会上遇见了John，同样还是挂着写着我的名字胸牌。为此，John甚至怀疑书稿其实都是Gray写的，他只是假托是别人写的而已。如果你在哪一届Unix大会上遇见一个人，他的胸牌上写着“Rich Stevens”，你可以这么跟他打招呼：“噢，想必你一定是Gary Wright。”）John说他需要把我写的这几章发出去审校，然后他要么（1）立即开车到纽黑文跟我签合同，要么（2）把合同寄给我，否则（3）跟我说干脆死了这条心去干点别的吧，不要继续写了。随后，我就去夏威夷去度假了，一个月之后我回来了，发现有一条找John的电话留言。我提前并不知情，原来审稿人里面还有Brian Kernighan<a name="notes13" href="#footnotes13">[13]</a>，Brian对书稿的评价是：“相当不错，值得出版。……总之，具备一本好书的潜质。……不管怎么说，都很有必要继续写下去。”John把合同寄给了我，于是我接着往下写。</p>
<p>问：<strong>你并没有使用troff写书，是吗？</strong><a name="Rich_Stevens_FAQ_13" href="#Rich_Stevens_FAQ_TOC">返回TOC</a></p>
<p>当然用了。还有其他软件吗？troff在业内是首屈一指的，我花了好几年功夫学习它。我在写书的时候用的是-ms宏的一个修改版。在通过troff格式化页面之前，我在输入中添加了很多“微调”指令，很难想象如果用Frame这些细节上的调整怎么做到。我还使用pic制作了所有插图。我用键盘比用鼠标熟练得多，所以使用依赖菜单的绘图软件很耽误时间，也很难受。之所以没有使用TeX，是因为那几年TeX和PostScript不能很好地协同。要是书里数学方面的东西多一些，可能会考虑TeX。</p>
<p>关于生成供照排机使用的文件，我想多说一点。1989年，在我写完UNP的时候，出版商还没有条件处理供照排机使用的文件，当时只有类似贝尔实验室这样的机构才有自己的排字机。因此在写完UNP之后，我又写了15页的PostScript文件，保存在6张1.2MB的MS-DOC磁盘里，并亲自开车把这几张盘从纽黑文送到罗得岛州府普罗维登斯<a name="notes14" href="#footnotes14">[14]</a>的Typesetting Service Corp.。两天后，他们通过联邦快递（FedEx）把排版后的页面送到Prentice Hall，排版费也是我刷的Visa卡（781页，每页4美元，共3124美元），Prentice Hall后来又把这些钱补给了我。今天，作者只要把最终的PostScript文件通过ftp传给出版商，出版商就可以排版了。</p>
<p>问：<strong>你使用哪种Unix系统？</strong><a name="Rich_Stevens_FAQ_14" href="#Rich_Stevens_FAQ_TOC">返回TOC</a></p>
<p>我每天都在使用的是运行在Sparc Ultra 5上的Solaris。原因很简单：1990年我在买第一台工作站时，只有SparcStation SLC的价格低于5000美元。那几年，大多数工作站厂商都瞧不上低端市场（有些厂商到现在还是如此）。后来我把SLC升级到ELC，然后又将ELC升级到SparcStation4，最后又换成了现在的Ultra 5。（我大约每3年就升级或更换一次硬件。）我的机器里也安装了很多可自由使用软件（GNU C、GNU troff，等等），而且我发现大多数这类软件都会率先被移植到Sun平台上来，因此感觉还是很舒服的。</p>
<p>运行我这个kohala.com域名的服务器中安装的是BSD/OS（HTTP、匿名FTP、电子邮件、DNS，等等）。BSD/OS是非常优秀的系统，非常可靠，它可以一直运行下去不出任何问题。我喜欢它还因为它的源代码是开放的，平常可以时不时地看一看，偶尔也会自己动手解决一点问题。不过我也买了他们的服务，让他们自己来发现和修复一些bug。（对Sun和BSDI的所有产品，我都是照单付钱的，因此以上所说都是非常客观的。）</p>
<p>我的办公室里还有很多其他计算机，运行着各种风格的Unix（在写UNP第2版时是9种；参见该书原版第21页）。我主要用它们来编译和测试我在其他系统上写的代码，同时也可以方便地在不同的主机环境下运行客户端和服务器。</p>
<p>这些系统和Cisco路由器的管理工作完全由我自己负责，要是连这些都做不了，还怎么写Unix网络和编程的书呢。</p>
<p>问：<strong>你喜欢哪些技术书？</strong><a name="Rich_Stevens_FAQ_15" href="#Rich_Stevens_FAQ_TOC">返回TOC</a></p>
<p>以下是一个书单，排名没有先后之分。</p>
<ul>
<li><em><a href="http://www.amazon.com/exec/obidos/ISBN=0131103628/">The C Programming Language</a></em>（Kernighan与Ritchie合著）。我始终很纳闷，为什么有人说这本书太复杂或者太粗糙。这本书简洁、明确，还配有很多示例。</li>
<li><em><a href="http://www.amazon.com/exec/obidos/ISBN=020103669X/">Software Tools</a></em>（Kernighan与Plauger合著）。这本书展示了如何设计然后实现许多简单版的Unix工具：grep、sort、ed等。（没错，连ed都有，这可是每个系统管理员都应该知道怎么使用的编辑器啊。我自己每年都要用很多次，经常在单用户模式下使用，编辑一些基本的配置文件。）我最喜欢引用这本书第250页中的那句话：“同样，如果你打算构建一些东西，一定要保证它们概念上的完整性——不要把一堆无关的‘功能’撺在一起。而且要以增量方式来构建，不要一下子全弄出来。” </li>
<li><em><a href="http://www.amazon.com/exec/obidos/ISBN=013937681X/">The UNIX Programming Environment</a></em>（Kernighan与Pike合著）。经典，在我看来现在仍然“没有过时”。这本书介绍了一些标准Unix命令行工具的用途（以及一些C编程知识），而<em>Software Tools</em>则是一本讲编程的书。</li>
<li><em><a href="http://www.amazon.com/exec/obidos/ISBN=0201134470/">The TeXbook</a></em>（Knuth）。我不用TeX，但我在排版时经常参考这本书。</li>
<li><em><a href="http://www.amazon.com/exec/obidos/ISBN=0201134470/">The AWK Programming Language</a></em>（Aho、Kernighan和Weinberger）。我经常用AWK，主要是编写小程序。不，我不用Perl——我认为它是一种只适合写不适合读的语言。</li>
<li><em><a href="http://www.amazon.com/exec/obidos/ISBN=0070342075/">The Elements of Programming Style</a></em>（Kernighan与Plauger合著）。这本书仍然是所有程序员的必读。</li>
<li><em><a href="http://www.amazon.com/exec/obidos/ISBN=0062735233/">On Writing Well</a></em>（Zinsser）。教你写作的一本好书。</li>
<li><em><a href="http://www.amazon.com/exec/obidos/ISBN=0139478213/">Webster&#8217;s New World Guide to Current American Usage</a></em>（Randall）。告诉你怎么克服高中英语课上灌输给你的那些不良表达习惯。</li>
</ul>
<p>时刻放在我桌子上的两本书分别是<em><a href="http://www.amazon.com/exec/obidos/ISBN=0877797099/">Merriam Webster&#8217;s Collegiate Dictionary</a></em>和<em><a href="http://www.amazon.com/exec/obidos/ISBN=0226103897/">The Chicago Manual of Style</a></em>。</p>
<p>你也知道，我不只看技术书，我喜欢的小说作者（或者说，他们书的精装本一上市我就出手的那些作者）有：David Baldacci、Patricia Cornwell、Michael Crichton、Patrick Davis、Nelson DeMille、Joseph Finder、Frederick Forsyth、Stephen Frey、John Grisham、Payne Harrison、Greg Isles、Douglas Kennedy、Phillip Margolin、Steve Martini、Douglas Preston和Lincoln Child, 以及Stuart Woods。不过，只有坐飞机的时候看这些书才是为了解闷的。</p>
<p>问：<strong>你名字中的W.表示什么？</strong><a name="Rich_Stevens_FAQ_16" href="#Rich_Stevens_FAQ_TOC">返回TOC</a></p>
<p>William。我父母想用我舅舅（叔叔）Bill的名字，但又想叫我Richard。他们觉得“William Richard”叫起来要比“Richard William”更顺口。</p>
<p>问：<strong>为什么专门为MTS（Michigan Terminal System）写APUE呢？</strong><a name="Rich_Stevens_FAQ_17" href="#Rich_Stevens_FAQ_TOC">返回TOC</a></p>
<p>我是1968～1973年在Michigan上的大学，我用的第一台计算机是运行MTS的IBM 360/67，作为未来的工程师，每个人都要上机学习Fortran编程语言。我们使用的课本是Brice Carnahan和James Wilkes自己编写的，Elliot Organick的那本Fortran IV是补充教材。MTS系统本身非常不可思议，包含了很多巧妙的想法，而且差不多是与Unix同时被开发出来的。与Unix一样，MTS蕴含的思想也领先于它的时代，这一点与其他IBM大型机操作系统相比尤其明显。只不过MTS运行在昂贵的IBM大型机上，而Unix则运行在便宜的PDP-11系列上。结果呢，也就不言自明了。</p>
<p>问：<strong>你编写的程序里为什么会包含goto？</strong><a name="Rich_Stevens_FAQ_18" href="#Rich_Stevens_FAQ_TOC">返回TOC</a></p>
<p>请参考高德纳1974年12月发表在ACM Computing Surveys, Vol. 6, No. 4上的论文，题目叫 Structured Programming with go to Statements。（事实上，那一期的Computing Surveys完全堪称经典。）我想给绝不使用goto的程序员出一道题，就是请在不使用任何goto语句的情况下重新编写tcp_input()（TCP/IPIv2第27章和第28章），注意不要造成任何性能损失（这道题看似简单，实际上可不好解）。</p>
<hr size="1" /><a name="footnotes1" href="#notes1">[1]</a> Unix操作系统（官方商标是UNIX，有时候也写作U<span style="font-variant: small-caps;">nix</span> ）最早是1969年由美国AT&amp;T公司贝尔实验室的员工肯·汤普逊（<a title="Ken Thompson (computer programmer)" href="http://en.wikipedia.org/wiki/Ken_Thompson_(computer_programmer)">Ken Thompson</a>）、丹尼斯·里奇（ <a title="Dennis Ritchie" href="http://en.wikipedia.org/wiki/Dennis_Ritchie">Dennis Ritchie</a>）、布赖恩·凯尔尼汗（<a title="Brian Kernighan" href="http://en.wikipedia.org/wiki/Brian_Kernighan">Brian Kernighan</a>）、道格拉斯·麦克伊罗（<a title="Douglas McIlroy" href="http://en.wikipedia.org/wiki/Douglas_McIlroy">Douglas McIlroy</a>）和 <a title="Joe Ossanna" href="http://en.wikipedia.org/wiki/Joe_Ossanna">Joe Ossanna</a>开发的。Unix是1971年最早在在PDP-11（PDP，Programmed Data Processor；PDP-11由DEC公司制造）上运行的操作系统，具有多用户、多任务的特点，支持多种处理器架构。AT&amp;T公司以低廉甚至免费的许可将Unix源码授权给学术机构做研究或教学之用，许多机构在此源码基础上加以扩充和改进，形成了所谓的“Unix变体”，这些变体反过来也促进了Unix的发展，其中最著名的变体之一是由加州大学柏克利分校开发的BSD产品。后来AT&amp;T意识到了Unix的商业价值，不再将Unix源码授权给学术机构，并对之前的Unix及其变体声明了版权权利。结果，导致了一场旷日持久的版权官司。这场官司一直打到AT&amp;T将自己的Unix系统实验室卖掉——同时也为Linux的诞生创造了难得的条件，新接手的Novell公司采取了一种比较开明的做法，允许柏克利分校自由发布自己的BSD，但是前提是必须将来自于AT&amp;T的代码完全删除，于是诞生了4.4 BSD Lite版，由于这个版本不存在法律问题，4.4BSD Lite成为了现代BSD系统的基础版本。要了解完整的Unix及其变体的时间线，请参考：<a href="http://www.levenez.com/unix/">http://www.levenez.com/unix/</a>。——译者注</p>
<p><a name="footnotes2" href="#notes2">[2]</a> VAX（Virtual Address eXtension）是一种可以支持机器语言和虚拟地址的32位小型计算机。VAX最初由DEC（Digital Equipment Corporation）公司在20世纪70年代初发明，是原来16位PDP-11的扩展产品。DEC公司1998年1月26日被Compaq（康柏）公司收购，后者2001年9月4日又被HP（惠普）公司收购。VAX被誉为最成功的小型机，其设计师、DEC技术灵魂、小型机之父戈登·贝尔（Gordon Bell）的个人主页为：http://research.microsoft.com/en-us/um/people/gbell/。——译者注</p>
<p><a name="footnotes3" href="#notes3">[3]</a>]1974年，伯克利加州大学（University of California, Berkeley）从AT&amp;T公司获得修改UNIX的许可，并在此基础上发布BSD（Berkeley Software Distribution，伯克利软件套件）；换句话说，BSD是Unix的衍生系统。1BSD（first Berkeley Software Distribution）是1977年由伯克利的研究生比尔·乔伊（Bill Joy，Sun公司的联合创办人）整理开发出来的。1978年、1979年和1980年，Joy分别发布了2BSD、3BSD和4BSD。4BSD以后的版本由1980年成立的CSRG（Computer System Research Group，计算机系统研究小组）负责发行。该小组于1981年6月发行了称之为4.1BSD的新版本——不是5BSD。由于AT&amp;T觉得5BSD会使用户将它和AT&amp;T Unix System V混淆，Berkely同意改变BSD将来版本的命名规则，将版本号仅保留在4BSD上，以后只增加4后面的小版本号。到1995年CSRG解散时，BSD的最高版本是4.4。1990年代初、中期，NetBSD、FreeBSD以及OpenBSD（从NetBSD小组中分离出来）小组相继成立，它们努力的结晶成为BSD的三个主要变体。BSD的另外两个主要变体NeXTSTEP和Darwin（Mac OS X的核心， 由FreeBSD 4.5和NeXTSTEP混合派生）如今已经演变成苹果公司Mac OS X及iPhone OS的核心。BSD对Unix最重要的贡献之一是TCP/IP。BSD有8个主要的发行版中包含了TCP/IP：4.1c、4.2、4.3、4.3-Tahoe、4.3-Reno、Net2、4.4以及4.4-lite。这些发行版中的TCP/IP代码几乎是现在所有系统中TCP/IP实现的前身，包括AT&amp;T System V 和Microsoft Windows。——译者注</p>
<p><a name="footnotes4" href="#notes4">[4]</a> Xenix是微软为微型计算机推出的Unix版本。由于微软购买的授权无法直接让该操作系统以“UNIX”为名，便命名该系统为Xenix。微软在1979年从美国电话电报公司购买了 Version 7 Unix 的授权，并于1980年8月25日发布面向16位系统的版本，由SCO公司将该系统移植至英特尔8086/8088架构。在Unix V7的基础上，Xenix整合了BSD的技术，再加上当时x86处理器的价格低廉，很快便成为当时最受欢迎的Unix发行版。据The Design and Implementation of the 4.3BSD UNIX Operating System（Samuel J. Leffler、Marshall Kirk McKusick，Addison-Wesley，1991.3）称：“如果就运行它的机器数量而言，Xenix可能是发行量最大的一个Unix版本了。”——译者注</p>
<p><a name="footnotes5" href="#notes5">[5]</a> “内存转储”原指把内存中的二进制数据以原来的表达方式转存成文件，用于对内存的运行状态进行事后分析。在这里指的是作者不会照搬开发文档，因此书的内容框架和语言表达自然更接近一般读者。——译者注</p>
<p><a name="footnotes6" href="#notes6">[6]</a> UNIX System III （有时也称System 3）是由AT&#038;T的Unix Support Group（USG）于1982年发布了一个Unix版本，也是第一个面向贝尔实验室之外发布的版本。UNIX System III综合了多个AT&#038;T版本： PWB/UNIX 2.0、CB UNIX 3.0、UNIX/TS 3.0.1和UNIX/32V。System III支持DEC PDP-11和VAX计算机。之所以将这个版本称为System III，是因为它是UNIX/TS 3.0.1和CB UNIX 3这两个由贝尔实验室内部支持的Unix系统的对外发行版。这个版本的文档叫做UNIX Edition 3.0。之前，根本没有System I和System II这两个Unix版本。而且也没有官方发布的UNIX/TS 4.0（否则，就会有System IV了）。换句话说，System III之后就是基于UNIX/TS 5.0System V了。——译者注</p>
<p><a name="footnotes7" href="#notes7">[7]</a> USENIX协会（USENIX Association）是一个高级计算技术协会。其前身是成立于1975年的Unix Users Group（Unix用户组），主要致力于Unix及类似系统的研发。1977年，AT&#038;T的律师通知这个小组不能使用UNIX这个词，因为它是Western Electric（截止到1995年一直是AT&#038;T的生产部门）的注册商标。于是，该小组遂更名为USENIX。这个协会受到了计算机操作系统领域的众多业内人士、开发人员和研究人员的推崇。这个协会每年都会举办一些会议和研讨会，最著名的是OSDI（USENIX Symposium on Operating Systems Design and Implementation ，USENIX操作系统设计与实现研讨会）、USENIX Annual Technical Conference（USENIX年度技术大会）、 USENIX Security Symposium（USENIX安全研讨会）、 FAST（USENIX Conference on File and Storage Technologies，USENIX文件及存储技术大会），以及SAGE（The USENIX Special Interest Group for Sysadmins，USENIX系统管理员特别兴趣小组——非盈利的专业系统管理员的国际性协会）主办的LISA（Large Installation System Administration Conference，大型系统管理员大会）。——译者注</p>
<p><a name="footnotes8" href="#notes8">[8]</a> Xinu是一种类Unix操作系统，1980年代由Douglas Comer为教学在普渡大学（Purdue University）开发。Xinu这外名字既是递归缩写（Xinu Is Not Unix），又是“Unix”的反向拼写形式。这个系统曾被移植到很多硬件平台，包括DEC LSI-11和VAX系统、 Sun-2 and Sun-3工作站、Intel x86、PowerPC G3 和MIPS等。——译者注</p>
<p><a name="footnotes9" href="#notes9">[9]</a> PostScript是1982年由John Warnock和Charles Geschke专门为打印图形和文字而设计的一种页面描述语言和编程语言，它与打印的介质无关，不管是在纸上、胶片上打印，还是在屏幕显示都没有问题。PostScript的主要目标是提供一种独立于设备的能够方便地描述图像的语言。独立于设备意味着，不需要借助任何具体设备的特性（例如，打印机的分辨率）来描述图像，因而这个描述不需要经过任何修改即可在其他的PostScript打印机上进行打印。PostScript作为一种语言，自己有语法和格式规范，这种语言描述的页面由PostScript文件表示。PostScript文件本身只是用PostScript语言描述了所要显示或者打印的文本及图像有哪些特征、参数，在显示或者打印PostScript文件的时候，再由PostScript解释器解释并打印或者显示。PostScript不仅与设备无关，而且与操作系统无关。无论是Windows操作系统，还是Unix操作系统，都可以阅读和打印PostScript文件。由于PostScript文件是以文本形式存储，因而文件比较小，适合在Internet上传输。（1982年12月，John Warnock和Charles Geschke离开施乐公司创建Adobe，以开发和销售PostScript为生。后来成就了Adobe“帝国”。）——译者注</p>
<p><a name="footnotes10" href="#notes10">[10]</a> 完整的书名是<em>Lions&#8217; Commentary on UNIX 6th Edition, with Source Code</em>，据说有中文版，暂时没找到。——译者注</p>
<p><a name="footnotes11" href="#notes11">[11]</a>Andrew S．Tanenbaum获得过美国麻省理工学院的理学学士学位和加利福尼亚大学伯克利分校的哲学博士学位，目前是荷兰阿姆斯特丹Vrije大学的计算机科学系的教授。还出版过《分布式操作系统》（Distributed Operating Systems）、《分布式系统：原理与范型》（Distributed Systems: Principles and Paradigms）、《计算机组成：结构化方法》（Structured Computer Organization）、《现代操作系统》（Modern Operating Systems）和《操作系统：设计及实现》（Operating Systems: Design and Implementation）等计算机专著。其中，《操作系统：设计及实现》一书和书中示例的Minix操作系统（也是Tanenbaum领导开发的一个免费用于教学目的的类Unix操作系统）给予了林纳斯·托瓦兹创造Linux操作系统内核的灵感。在他的自传《Just For Fun》（英文意为“只是为了有趣”）中，托瓦兹把这本书描述为“引领我到达新高度的一本书籍”。Tanenbaum是ACM会员，IEEE资深会员，荷兰皇家艺术和科学学院院士，获得过1994年度ACM KarlV．Karlstrom杰出教育家奖。根据Pearson官方网站公布的信息（http://www.pearsonhighered.com/tanenbaum/），Computer Networks, Fifh Edition将于2010年10月出版。</p>
<p><a name="footnotes12" href="#notes12">[12]</a>最早的Unix编程专著Advanced UNIX Programming（Addison-Wesley，1985）一书的作者，该书第1版出版19年后，作者推出了“升级版”——第2版，在自己的网站里（http://basepath.com/aup/），作者戏言：“说升级也许有点不恰当了。新版的篇幅达到750页，而旧版中差不多只有20段话没有改过，上一版介绍了70个系统调用，而这一版则达到了300个。”</p>
<p><a name="footnotes13" href="#notes13">[13]</a>Brian W．Kernighan，贝尔实验室计算科学研究中心高级研究人员，著名的计算机科学家。他参加了UNIX系统、C语言、AWK语言和许多其他系统的开发，同时出版了许多在计算机领域具有影响的著作，包括The Elements of Programming Style、The Practice of Programming、The UNIX Programming Environment、The AWK Language、Software Tools等。</p>
<p><a name="footnotes14" href="#notes14">[14]</a>从康涅狄格州纽黑文到罗得岛州府普罗维登斯大约105英里，约168公里。——译者注</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2010/09/12/rich-stevens-faq-2007.html/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>在Windows平台的Apache中配置Python</title>
		<link>http://www.cn-cuckoo.com/2010/08/19/run-python-in-apache-by-use-mod_python-1960.html</link>
		<comments>http://www.cn-cuckoo.com/2010/08/19/run-python-in-apache-by-use-mod_python-1960.html#comments</comments>
		<pubDate>Thu, 19 Aug 2010 11:25:35 +0000</pubDate>
		<dc:creator>为之漫笔</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[编程技术]]></category>

		<guid isPermaLink="false">http://www.cn-cuckoo.com/?p=1960</guid>
		<description><![CDATA[要在Windows平台的Apache中使用Python，当然必须得先安装Apache和Python。Apache我使用的是XAMPP，而Python则随便一搜，就可以找到下载链接。由于这个解决方案要通过安装Apache模块mod_python来实现，而mod_python的当前版本3.3.1只支持Apache 2.2和Python 2.5，所以不得不先缷载已经装好的Python 3.0，重新下载安装了Python 2.5。mod_python是一个Apache模块，它可以将Python解释器嵌入到Apache服务器中（详情可以看这里）。 让Apache支持Python的过程很简单，只要3步。 下载mod_python模块安装程序（注意文件名后面Python和Apache的版本号要与自己已经安装的版本一致；文件名前面的版本号则是mod_python的，文件名示例：mod_python-3.3.1.win32-py2.5-Apache2.2.exe），然后安装，安装向导会自动找到Python路径，但可能需要我们手工指定Apache路径，安装到最后，向导还会提示你如何修改Apache配置文件（参见下一步）并给出了后续步骤的英文说明。 让Apache加载mod_python模块。在Apache安装目录下找到其配置文件apache\conf\httpd.conf，打开，搜“LoadModule”，找到加载模块的地方，然后添加一条语句：LoadModule python_module modules/mod_python.so，重新启动Apache。 在htdocs目录下新建一个目录，如：“py”。进入py目录，新建一个文本文件，并命名为“.htaccess”，加入下列3条指令： AddHandler mod_python .py PythonHandler mptest PythonDebug On 这里第一条指令是将所有URL末尾为.py的请求转发给mod_python处理程序，mod_python接收到请求之后再寻找适当的PythonHandler处理程序。第二条指令只定义了一个mptest处理程序。最后一条是启用Python代码调试功能，以便在代码运行出错时输出Python解释器返回的错误。 完成以上3步之后，就可以编写Python文件并进行测试了。在py目录下新建 mptest.py 文件，打开后添加如下代码： from mod_python import apache def handler(req): req.content_type = &#039;text/plain&#039; req.write(&#34;Hello World!&#34;) return apache.OK 保存。打开浏览器，输入http://localhost/py/mptest.py，回车。看到“Hello World！”了吗？ 实际上，由于前面只明确将mptest设置为处理程序，所以无论浏览器URL中的.py文件名是什么（如：login.py、default.py），都将被转发给mptest.py文件来处理，都会返回“Hello World！”。怎么办呢？长话短说，可以将上面第3步中的代码替换成如下所示： AddHandler mod_python .py PythonHandler mod_python.publisher PythonDebug On 更多内容，参见Mod_python Manual和Introducing mod_python。]]></description>
			<content:encoded><![CDATA[<p>要在Windows平台的Apache中使用Python，当然必须得先安装Apache和Python。Apache我使用的是<a title="下载XAMPP" href="http://www.apachefriends.org/zh_cn/xampp.html" target="_blank">XAMPP</a>，而Python则随便一搜，就可以找到下载链接。由于这个解决方案要通过安装Apache模块mod_python来实现，而mod_python的当前版本3.3.1只支持Apache 2.2和Python 2.5，所以不得不先缷载已经装好的Python 3.0，重新下载安装了Python 2.5。mod_python是一个Apache模块，它可以将Python解释器嵌入到Apache服务器中（<a title="http://www.modpython.org/" href="http://www.modpython.org/" target="_blank">详情可以看这里</a>）。</p>
<p>让Apache支持Python的过程很简单，只要3步。</p>
<ol>
<li><a title="下载mod_python安装文件" href="http://www.apache.org/dist/httpd/modpython/win/" target="_blank">下载mod_python模块安装程序</a>（注意文件名后面Python和Apache的版本号要与自己已经安装的版本一致；文件名前面的版本号则是mod_python的，文件名示例：<strong>mod_python-3.3.1</strong>.win32-<strong>py2.5</strong>-<strong>Apache2.2</strong>.exe），然后安装，安装向导会自动找到Python路径，但可能需要我们手工指定Apache路径，安装到最后，向导还会提示你如何修改Apache配置文件（参见下一步）并给出了<a title="修改完Apache配置文件（httpd.conf）后，看这个链接。" href="http://www.modpython.org/live/current/doc-html/inst-testing.html" target="_blank">后续步骤的英文说明</a>。</li>
<li>让Apache加载mod_python模块。在Apache安装目录下找到其配置文件apache\conf\httpd.conf，打开，搜“LoadModule”，找到加载模块的地方，然后添加一条语句：<strong>LoadModule python_module modules/mod_python.so</strong>，重新启动Apache。</li>
<li>在htdocs目录下新建一个目录，如：“py”。进入py目录，新建一个文本文件，并命名为“.htaccess”，加入下列3条指令：
<pre class="brush: py; ">

AddHandler mod_python .py
PythonHandler mptest
PythonDebug On
</pre>
<p>这里第一条指令是将所有URL末尾为.py的请求转发给mod_python处理程序，mod_python接收到请求之后再寻找适当的PythonHandler处理程序。第二条指令只定义了一个mptest处理程序。最后一条是启用Python代码调试功能，以便在代码运行出错时输出Python解释器返回的错误。</li>
</ol>
<p>完成以上3步之后，就可以编写Python文件并进行测试了。在py目录下新建 mptest.py 文件，打开后添加如下代码：</p>
<pre class="brush: py; ">

from mod_python import apache

def handler(req):
	req.content_type = &#039;text/plain&#039;
	req.write(&quot;Hello World!&quot;)
	return apache.OK
</pre>
<p>保存。打开浏览器，输入http://localhost/py/mptest.py，回车。看到“Hello World！”了吗？</p>
<p>实际上，由于前面只明确将mptest设置为处理程序，所以无论浏览器URL中的.py文件名是什么（如：login.py、default.py），都将被转发给mptest.py文件来处理，都会返回“Hello World！”。怎么办呢？长话短说，可以将上面第3步中的代码替换成如下所示：</p>
<pre class="brush: py; ">

AddHandler mod_python .py
PythonHandler mod_python.publisher
PythonDebug On
</pre>
<p>更多内容，参见<a href="http://www.modpython.org/live/current/doc-html/modpython.html"><em>Mod_python Manual</em></a>和<a href="http://onlamp.com/pub/a/python/2003/10/02/mod_python.html"><em>Introducing mod_python</em></a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cn-cuckoo.com/2010/08/19/run-python-in-apache-by-use-mod_python-1960.html/feed</wfw:commentRss>
		<slash:comments>37</slash:comments>
		</item>
	</channel>
</rss>

