﻿<?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://blog.jobbole.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.jobbole.com</link>
	<description>伯乐在线 博客</description>
	<lastBuildDate>Thu, 17 May 2012 09:40:59 +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>Zen Coding: 一种快速编写HTML/CSS代码的方法</title>
		<link>http://blog.jobbole.com/19714/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=zen-coding-%25e4%25b8%2580%25e7%25a7%258d%25e5%25bf%25ab%25e9%2580%259f%25e7%25bc%2596%25e5%2586%2599htmlcss%25e4%25bb%25a3%25e7%25a0%2581%25e7%259a%2584%25e6%2596%25b9%25e6%25b3%2595</link>
		<comments>http://blog.jobbole.com/19714/#comments</comments>
		<pubDate>Thu, 17 May 2012 02:31:28 +0000</pubDate>
		<dc:creator>齐哲</dc:creator>
				<category><![CDATA[IT技术]]></category>
		<category><![CDATA[设计]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>

		<guid isPermaLink="false">http://blog.jobbole.com/?p=19714</guid>
		<description><![CDATA[在本文中我们将展示一种新的使用仿CSS选择器的语法来快速开发HTML和CSS的方法。它由<a href="http://www.smashingmagazine.com/author/sergey-chikuyonok/">Sergey Chikuyonok</a>开发。

你在写HTML代码(包括所有标签、属性、引用、大括号等)上花费多少时间？如果你的编辑器有代码提示功能，你编写的时候就会容易些，但即便如此你还是要手动敲入很多代码。

在JavaScript方面，当我们想要在一个页面上获取某个特定的元素时，我们就会遇到同样的问题，我们必须写很多代码，这就变得难于维护和重 用。JavaScript框架应运而生，它们同时引入了CSS选择器引擎。现在，你可以使用简单的CSS表达式来获取DOM元素，这相当酷。

但是，如果你不仅仅可以用CSS的选择器布局和定位元素，还能<strong>生成代码</strong>会怎么样？比如，如果你这样写：
<pre class="brush: css; gutter: true"> div#content&#62;h1+p</pre>
…然后就可以看到这样的输出：
<pre class="brush: html; gutter: true">&#60;div id=&#34;content&#34;&#62;
&#60;h1&#62;&#60;/h1&#62;
&#60;p&#62;&#60;/p&#62;
&#60;/div&#62;</pre>
有些迷惑吧？今天，我将向你介绍<a href="http://code.google.com/p/zen-coding/">Zen Coding</a>，一组用于快速HTML和CSS编码的工具。最初由<a href="http://pepelsbey.net/2009/04/zen-coding-concept/">Vadim Makeev在2009年4月提出</a>(文章为俄语)，由鄙人(也就是我)开发了数月并最终达到比较成熟的状态。Zen Coding由两个核心组件组成：一个缩写扩展器(缩写为像CSS一样的选择器)和上下文无关的HTML标签对匹配器。看一下这个演示视频来看一下它们能为你做些什么。

[youku id="XMTM4NDQwNzgw"]

<strong>注意：</strong>该视频原版位于Vimeo，但是要看的话需要翻[和谐]墙先，地址在这里：<a href="http://vimeo.com/7405114" target="_blank">http://vimeo.com/7405114</a>，上面的视频是我费尽周折从Vimeo上下载下来上传到优酷的，上传后质量竟被大打折扣了，囧。youtube上也有一份视频，是基于Aptana的演示，一样很精彩：<a href="http://www.youtube.com/watch?v=ug84Ypwqfzk" target="_blank">http://www.youtube.com/watch?v=ug84Ypwqfzk</a>。PS:貌似youtube要比Vimeo翻[和谐]墙容易些，不过如何翻[和谐]墙不在本站讨论范围。

如果你想跳转到详细介绍和使用指南，请看一下演示页面并立刻下载你适用的插件：

<strong>Demo</strong>

●<a href="http://zen-coding.ru/demo/">Demo</a> (使用 <em>Ctrl + ,</em> 展开缩写，需要JavaScript支持)

●<a href="http://labs.qianduan.net/zencoding/">中文版演示</a>

<strong>下载(完全支持)</strong>

●<a href="http://code.google.com/p/zen-coding/downloads/detail?name=Zen.Coding-Aptana.v0.5.zip">Aptana</a> (跨平台);

●Coda, via <a href="http://github.com/sergeche/tea-for-coda/downloads">TEA for Coda</a> (Mac);

●Espresso, via <a href="http://github.com/sergeche/tea-for-espresso/downloads">TEA for Espresso</a> (Mac);

<strong>下载(部分支持，只支持“展开缩写”)</strong>

<a href="http://code.google.com/p/zen-coding/downloads/detail?name=Zen%20Coding%20for%20TextMate%20v0.3.1.zip">TextMate</a>(只能用于Mac机,Windows可以使用E-text编辑器替代);

●<a href="http://code.google.com/p/zen-coding/downloads/detail?name=TopStyle.Zen.Coding.1.0.zip">TopStyle</a>;

●<a href="http://code.google.com/p/zen-coding/downloads/detail?name=Sublime.Zen.Coding.1.1.3.zip">Sublime Text</a>;

●<a href="http://www.kryogenix.org/days/2009/09/21/zen-coding-for-gedit">GEdit</a>;

●<a href="http://zen-coding.googlecode.com/files/Zen.Coding-Dreamweaver.v0.4.zip">Dreamweaver CS4</a>

●<a href="http://zen-coding.ru/demo/">editArea在线编辑器</a>;

●<a href="http://labs.qianduan.net/zencoding/">Zen Coding在线编辑器中文版</a>

现在让我们看一下这些工具是如何工作的吧。

<strong>展开缩写</strong>

展开缩写功能将类似CSS的选择器转换为XHTML代码。术语“缩写”可能会有点儿难以理解。为什么不直接称之为“CSS选择器”呢？嗯，首要原因是语义化：“选择器”意为<em>选择</em>一些东西，但是在这里我们事实上是<em>生成</em> 一些东西，<strong>是写一个长代码的较短的替代</strong>。其次，它只是使用真实的CSS选择器语法的一个小的子集，并添加了一些新的操作符。

这里是一个支持的属性和操作符的列表：

●E

元素名称(div, p);

●E#id

使用id的元素(div#content, p#intro, span#error);

●E.class

使用类的元素(div.header, p.error.critial). 你也可以联合使用class和idID: div#content.column.width;

●E&#62;N

子代元素(div&#62;p, div#footer&#62;p&#62;span);

●E+N

兄弟元素(h1+p, div#header+div#content+div#footer);

●E*N

元素倍增(ul#nav&#62;li*5&#62;a);

●E$*N

条目编号 (ul#nav&#62;li.item-$*5);

正如你能看到的，你已经知道如何使用Zen Coding了：只是些一个简单的仿CSS选择器(呃，“缩写”抱歉)，就像这样…

…然后调用”展开缩写”行为。

这里有两个新增的操作符：元素倍增和条目编号。比如，如果你想生成5个&#60;li&#62;元素，你可以简单的写位li*5。它也将同样重写全部子 代元素。如果你想写4个&#60;li&#62;元素，每个里面都有一个&#60;a&#62;标签，你就可以简单的写为li*4&#62;a，这样会生成以下 HTML代码：
<pre class="brush: html; gutter: true">&#60;li&#62;&#60;a href=&#34;&#34;&#62;&#60;/a&#62;&#60;/li&#62;
&#60;li&#62;&#60;a href=&#34;&#34;&#62;&#60;/a&#62;&#60;/li&#62;
&#60;li&#62;&#60;a href=&#34;&#34;&#62;&#60;/a&#62;&#60;/li&#62;
&#60;li&#62;&#60;a href=&#34;&#34;&#62;&#60;/a&#62;&#60;/li&#62;</pre>
最后一个——条目编号用于当你想用索引标记重复的元素的情况。假设你想生成class为item1、item2和item3的3个&#60;div&#62;元素。你可以写成这样的缩写，div.item$*3:
<pre class="brush: html; gutter: true">&#60;div&#62;&#60;/div&#62;
&#60;div&#62;&#60;/div&#62;
&#60;div&#62;&#60;/div&#62;</pre>
只需在你想要索引出现的任何class或id属性上添加一个美元符号即可，而且想要多少都可以。那么，这样…
<pre class="brush: html; gutter: true">div#i$-test.class$$$*5</pre>
会被转换成为:
<pre class="brush: html; gutter: true">&#60;div id=&#34;i1-test&#34;&#62;&#60;/div&#62;
&#60;div id=&#34;i2-test&#34;&#62;&#60;/div&#62;
&#60;div id=&#34;i3-test&#34;&#62;&#60;/div&#62;
&#60;div id=&#34;i4-test&#34;&#62;&#60;/div&#62;
&#60;div id=&#34;i5-test&#34;&#62;&#60;/div&#62;</pre>
你会看到，当你写a的缩写的时候，输出是&#60;a href=”"&#62;&#60;/a&#62;。或者，如果你写img，输出就是&#60;img src=”" alt=”" /&#62;。

Zen Coding是如何知道什么时候应该为生成的标签添加默认的属性或者跳过关闭标签的？有一个专门的文件，名为<em><a href="http://code.google.com/p/zen-coding/source/browse/branches/serge.che/aptana/zen_settings.js">zen_settings.js</a></em>描述了输出元素。这是一个简单的JSON文件，描述每种语言的缩写(是的，你可以为不同的句法定义缩写，比如HTML、XSL、CSS等)。通用的语言缩写定义看起来就像这样：
<pre class="brush: javascript; gutter: true">&#039;html&#039;: { &#039;snippets&#039;: { &#039;cc:ie6&#039;: &#039;&#60;!--[if lte IE 6]&#62;\n\t${child}&#124;\n&#60;![endif]--&#62;&#039;,
            ...
            },
              &#039;abbreviations&#039;: { &#039;a&#039;: &#039;&#60;a href=&#34;&#34;&#62;&#60;/a&#62;&#039;, &#039;img&#039;: &#039;&#60;img src=&#34;&#34; alt=&#34;&#34; /&#62;&#039;,
            ...
            }
            }</pre>
<strong>元素类型</strong>

Zen Coding有两个主要的元素类型：<strong>“片段(snippets)” 和 “缩写(abbreviations)”。</strong>片 段就是随意的代码碎片，而缩写是标签定义。通过片段，你可以写出你想要的任何代码，它也会照你写的格式输出；但是你必须手动的格式化它(使用\n 和\t实现换行和缩进) 并将${child}变量放到你想要输出子元素的地方，就像这样：cc:ie6&#62;style。如果你不使用${child}变量，子元素将会输出于 代码片段的<strong>后面</strong>。

有了缩写，您必须编写标记定义，而且语法是非常重要的。通常，你必须写一个简单的带有所有默认的属性的标签，比如: &#60;a href=”"&#62;&#60;/a&#62;。当Zen Coding被加载后，它会解析一个标签定义到一个描述该标签的名字、属性(包括它们的顺序)以及该标签是否为空的特定的对象中。所以，如果你 写&#60;img src=”" alt=”" /&#62;，你会告诉Zen Coding这个标签必须是空的，然后“扩展缩写”行为就会在输出之前为它使用特定的规则。

对于片段和缩写，你可以添加一个管道符号，它告诉Zen Coding当缩写被展开的时候光标会被定位到哪里。默认的，Zen Coding 将光标放在空属性的引号中间以及开始和关闭标签的中间。

<strong>例子</strong>

那么，这里解释一下当你写了一个缩写并召唤“展开缩写”行动时发生的事情。首先，它将一个完整的缩写分开为独立的元素：这样div&#62;a 会被分成div 和a 元素，当然也会维持他们的关系。然后，每个元素，解析器先在代码片段内而后在缩写中寻找定义。如果它找不到，将会使用元素的名字作为新的标签，并为其添加 缩写中定义的id和class。比如，如果你写mytag#example，解析器在片段或缩写中找不到mytag定义，它就会输出&#60;mytag id=”example”&#62;&#60;mytag&#62;。

我们制作了很多<a href="http://code.google.com/p/zen-coding/wiki/ZenCSSPropertiesEn">默认的CSS</a>和<a href="http://code.google.com/p/zen-coding/wiki/ZenHTMLElementsEn">HTML缩写和片段</a>。你会发现学习使用Zen Coding可以增加你的生产力。

<strong>HTML 标签对匹配器</strong>

对于HTML编码者的另一个非常常见的任务是寻找一个元素的标签对。例如你想选择整个&#60;div id=”content”&#62;标签并将其移动到其它地方或者删除它。或者有可能你在寻找一个关闭标签并想知道它属于那个开始标签。

不幸的是，很多现代开发工具在该功能方面有所欠缺。那么我就决定写一个我自己的标签对匹配器作为Zen Coding的一部分。不过它依然在beta阶段并尚存一些问题，但它可以工作的很不错并很快。不是浏览整个文档(像通常的那种HTML标签对匹配器的做 法)，它从光标的当前位置开始寻找相关的标签。这使得它非常快并且<em>上下文无关</em>：它甚至可以用于这段<strong>JavaScript代码片段</strong>：
<pre class="brush: javascript; gutter: true">var table = &#039;&#60;table&#62;&#039;; for (var i = 0; i &#60; 3; i++) {
    table += &#039;&#60;tr&#62;&#039;; for (var j = 0; j &#60; 5; j++) {
        table += &#039;&#60;td&#62;&#039; + j + &#039;&#60;/td&#62;&#039;;
    }
    table += &#039;&#60;/tr&#62;&#039;;
}
table += &#039;&#60;/table&#62;&#039;;</pre>
<strong>使用缩写包裹</strong>

这真的是一个很酷的特性，它将缩写和标签对匹配器的功能合并到一起了。你有多少才发现你需要<strong>添加一个包裹元素以修正一个浏览器bug</strong>？或者你需要添加一个装饰，比如一个背景图片或者边框到一个块级内容？你必须写开始标签，临时打断你的代码，找到相关的点然后关闭标签。这就是“使用缩写包裹”能帮助你的地方。

该功能相当简单：它要求你输入缩写，然后执行适当的“展开缩写”行动并将你期望的文本放到你缩写的<em>最后一个元素里面</em>。如果你没有选择任何文本，它就会启动标签对匹配器并使用结果。它同样能搞清楚你的光标的位置：标签的内容里面或者是开始和关闭标签中间。依赖于它的位置，它会包裹标签的内容或标签本身。

缩写包裹为包裹个别行引入了一个特定的缩写句法。简单跳转到倍增操作符后面的数字，比如：ul#nav&#62;li*&#62;a。当Zen Coding 发现一个使用未定义的倍增数的时候，它会将它作为一个<em>重复元素</em>：你的章节中有多少行，它就会输出多少次，并将每行的内容放到重复元素的<em>最后一个子元素</em>里面。

如果你在这段文本外面包裹这段缩写div#header&#62;ul#navigation&#62;li.item$*&#62;a&#62;span：
<pre class="brush: html; gutter: true">About Us
Products
News
Blog
Contact Up</pre>
你将会得到以下结果：
<pre class="brush: html; gutter: true">&#60;div id=&#34;header&#34;&#62;
    &#60;ul id=&#34;navigation&#34;&#62;
        &#60;li&#62;&#60;a href=&#34;&#34;&#62;&#60;span&#62;About Us&#60;/span&#62;&#60;/a&#62;&#60;/li&#62;
        &#60;li&#62;&#60;a href=&#34;&#34;&#62;&#60;span&#62;Products&#60;/span&#62;&#60;/a&#62;&#60;/li&#62;
        &#60;li&#62;&#60;a href=&#34;&#34;&#62;&#60;span&#62;News&#60;/span&#62;&#60;/a&#62;&#60;/li&#62;
        &#60;li&#62;&#60;a href=&#34;&#34;&#62;&#60;span&#62;Blog&#60;/span&#62;&#60;/a&#62;&#60;/li&#62;
        &#60;li&#62;&#60;a href=&#34;&#34;&#62;&#60;span&#62;Contact Up&#60;/span&#62;&#60;/a&#62;&#60;/li&#62;
    &#60;/ul&#62;
&#60;/div&#62;</pre>
你可以看到，Zen Coding是一个强大的文本处理工具。

<strong>快捷键</strong>

●Ctrl+,

展开缩写

●Ctrl+M

匹配对

●Ctrl+H

使用缩写包括

●Shift+Ctrl+M

合并行

●Ctrl+Shift+?

上一个编辑点

●Ctrl+Shift+?

下一个编辑点

●Ctrl+Shift+?

定位匹配对

这些快捷键是可以自定义的。

<strong>在线演示</strong>

你已经学到很多关于Zen Coding如何工作以及它是如何使你的编码更容易了。现在为什么不自己尝试一下呢？因为Zen Coding是用纯JavaScript开发并迁移到Python，它甚至可以用于浏览器内部，这令它成为引入到CMS的首选。

●<a href="http://zen-coding.ru/demo/">Demo</a> (使用 <em>Ctrl + ,</em> 展开缩写，需要JavaScript支持)

●<a href="http://labs.qianduan.net/zencoding/">中文版演示</a>

<strong>支持的编辑器</strong>

Zen Coding并不依赖某个特定的编辑器。它是一个只处理文本的出色的组件：它获取文本、做一些处理并放回新的文本(或索引，用于标签匹配)。Zen Coding由JavaScript和Python编写，所以它实际上可以运行于任何平台。在Windows，你可以运行JavaScript版本，而 Mac和Linux 分支可以使用Python版。

如果让你的编辑器支持Zen Coding，你需要写一个特定的可以在你的编辑器和Zen Coding之间转换数据的插件。问题是一个编辑器可能不会完整的支持Zen Coding因为它本身的插件系统。比如，<a href="http://macromates.com/">TextMate</a>通过使用脚本输出替换当前行很容的就支持了“展开缩写”功能，但是它不能处理标签对匹配因为没有标准的方法请求TextMate来选择内容。

<strong>完全支持</strong>

●<a href="http://code.google.com/p/zen-coding/downloads/detail?name=Zen.Coding-Aptana.v0.5.zip">Aptana</a> (跨平台);

●Coda, via <a href="http://github.com/sergeche/tea-for-coda/downloads">TEA for Coda</a> (Mac);

●Espresso, via <a href="http://github.com/sergeche/tea-for-espresso/downloads">TEA for Espresso</a> (Mac);

<strong>部分支持(只支持“展开缩写”)</strong>

●<a href="http://code.google.com/p/zen-coding/downloads/detail?name=Zen%20Coding%20for%20TextMate%20v0.3.1.zip">TextMate</a> (只能用于Mac机,Windows可以使用E-text编辑器替代);

●<a href="http://code.google.com/p/zen-coding/downloads/detail?name=TopStyle.Zen.Coding.1.0.zip">TopStyle</a>;

●<a href="http://code.google.com/p/zen-coding/downloads/detail?name=Sublime.Zen.Coding.1.1.3.zip">Sublime Text</a>;

●<a href="http://www.kryogenix.org/days/2009/09/21/zen-coding-for-gedit">GEdit</a>;

●<a href="http://zen-coding.googlecode.com/files/Zen.Coding-Dreamweaver.v0.4.zip">Dreamweaver CS4</a>

●<a href="http://zen-coding.ru/demo/">editArea在线编辑器</a>;

●<a href="http://labs.qianduan.net/zencoding/">Zen Coding在线编辑器中文版</a>

Aptana是我主要的开发环境，它使用一个JavaScript版本的Zen Coding。它也包含很多其它的我用于日常工作的工具，所以任何一个新的Zen Coding版本都将会首先对Aptana可用，然后部署到Python并兼容其它的编辑器。

Coda和Espresso 插件被杰出的<a href="http://onecrayon.com/tea/">Text Editor Actions</a> (TEA) 平台支持，由<a href="http://beckism.com/">Ian Beck</a>开发。原始的源代码<a href="http://github.com/onecrayon">在GitHub上</a>，但我还是制作了<a href="http://github.com/sergeche/">我自己的分支</a>以整合Zen Coding的特性。

<strong>总结</strong>

很多尝试过Zen Coding的人都说它改变了他们写页面的方式。当然还有很多事情要做，还有很多的编辑器需要被支持以及一些文档要写。请浏览<a href="http://code.google.com/p/zen-coding/w/list">现在的文档</a> 以及<a href="http://code.google.com/p/zen-coding/source/browse/#svn/branches/serge.che">源代码</a>以寻找你的问题的答案。希望你喜欢Zen Coding!

<strong>附：Zen coding的具体用法</strong>

遗憾的是， 本文原作者并没有说明zen coding的具体用法，神飞认为有必要做以下简要的说明。这里就以Aptana/Eclipse和Dreamweaver为例，其它编辑器平台暂不描述，如有疑问可以在评论中与前端观察的网友交流。

<strong>Aptana/Eclipse</strong>

由于Aptana本身就是基于Eclipse的，所以，Zen Coding也是支持Eclipse的，只是需要一个EclipseMonkey插件的支持，Aptana已经封装了这个插件，所以如果你使用Aptana，下面的第一步可以跳过。

1、通过更新网站安装EclipseMonkey: <a href="http://download.eclipse.org/technology/dash/update" rel="nofollow">http://download.eclipse.org/technology/dash/update</a>(如果你使用Aptana，可跳过这一步)

2、在你的当前工作去创建一个顶级的项目，给它命名，比如，就叫<strong>zencoding</strong>&#60;

3、在新创建的项目中创建<strong>scripts</strong>文件夹

4、解压缩下载的ZIP插件包到该文件夹。项目结构看起来就像这样:

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/A-Speedy-Way-To-Write-Code.png"><img class="aligncenter size-full wp-image-19715" title="Zen Coding: 一种快速编写HTML/CSS代码的方法 " src="http://blog.jobbole.com/wp-content/uploads/2012/05/A-Speedy-Way-To-Write-Code.png" alt="Zen Coding: 一种快速编写HTML/CSS代码的方法 " width="405" height="293" /></a>

5、安装之后，Aptana的菜单栏中的“脚本(Script)”菜单中将会出现Zen coding相关子菜单

注意事项：

●Aptana版的官方插件是基于MAC机的，如果你用的是Windows，需要手动更改快捷键(在每个文件头部的注释片段中更改)

●官方的文件编码有点儿乱，修改官方js的时候，请注意<strong>编码问题</strong>，修改不当会造成相关功能的丢失；

<strong>DreamWeaver</strong>

好消息是，现在已经有了Zen coding for DreamWeaver插件，坏消息是，该插件支持的功能很少，只支持展开缩写功能。而且默认的快捷键是无效的。只能在“命令”菜单中点击操作。另外，没 有测试该插件是不是只支持CS4版本。不过比较好的是，作者将本插件的源码也放出了，你可以自定义一个Dreamweaver的插件。

<del>事实上，官方的DW插件在Windows下有点儿bug，就是会出现空白的行，我简单的修正了下，重新编译了个包，在本机测试没问题，感兴趣的童鞋可以下载尝试：<a href="http://www.boxcn.net/shared/c71z7x7sfe" target="_blank">http://www.boxcn.net/shared/c71z7x7sfe</a></del>

PS:官方的DW插件已经更新，<strong>推荐</strong><a href="http://zen-coding.googlecode.com/files/Zen%20Coding.mxp" target="_blank">到官方去下载</a>。新的插件添加了更多的功能支持。UPDATE @ 12-23-2009

<strong>特别推荐</strong>：豪情同学将缩写给实践了一番，总结出了很多很棒的用例，推荐大家<a href="http://www.cnblogs.com/jikey/archive/2009/12/19/1628002.html" target="_blank">前去学习</a>。

<strong>原作者介绍：</strong>

Sergey Chikuyonok是一位俄罗斯的前端开发工程师和作者，他在优化方面有很大的热情：从图片、JavaScript效果到工作流程和节省时间的编码。访问<a href="http://chikuyonok.ru/" target="_blank">他的主页</a>和<a href="http://twitter.com/chikuyonok" target="_blank">他的Twitter</a>。

英文原文：<a href="http://www.smashingmagazine.com/2009/11/21/zen-coding-a-new-way-to-write-html-code/">Smashing Magazine</a>]]></description>
			<content:encoded><![CDATA[<p>在本文中我们将展示一种新的使用仿CSS选择器的语法来快速开发HTML和CSS的方法。它由<a href="http://www.smashingmagazine.com/author/sergey-chikuyonok/">Sergey Chikuyonok</a>开发。</p>
<p>你在写HTML代码(包括所有标签、属性、引用、大括号等)上花费多少时间？如果你的编辑器有代码提示功能，你编写的时候就会容易些，但即便如此你还是要手动敲入很多代码。</p>
<p>在JavaScript方面，当我们想要在一个页面上获取某个特定的元素时，我们就会遇到同样的问题，我们必须写很多代码，这就变得难于维护和重 用。JavaScript框架应运而生，它们同时引入了CSS选择器引擎。现在，你可以使用简单的CSS表达式来获取DOM元素，这相当酷。</p>
<p>但是，如果你不仅仅可以用CSS的选择器布局和定位元素，还能<strong>生成代码</strong>会怎么样？比如，如果你这样写：</p>
<pre class="brush: css; gutter: true"> div#content&gt;h1+p</pre>
<p>…然后就可以看到这样的输出：</p>
<pre class="brush: html; gutter: true">&lt;div id=&quot;content&quot;&gt;
&lt;h1&gt;&lt;/h1&gt;
&lt;p&gt;&lt;/p&gt;
&lt;/div&gt;</pre>
<p>有些迷惑吧？今天，我将向你介绍<a href="http://code.google.com/p/zen-coding/">Zen Coding</a>，一组用于快速HTML和CSS编码的工具。最初由<a href="http://pepelsbey.net/2009/04/zen-coding-concept/">Vadim Makeev在2009年4月提出</a>(文章为俄语)，由鄙人(也就是我)开发了数月并最终达到比较成熟的状态。Zen Coding由两个核心组件组成：一个缩写扩展器(缩写为像CSS一样的选择器)和上下文无关的HTML标签对匹配器。看一下这个演示视频来看一下它们能为你做些什么。</p>
<object width="480" height="400"><param name="movie" value="http://player.youku.com/player.php/sid/XMTM4NDQwNzgw/v.swf"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="never"></param><param name="allownetworking" value="internal"></param><param name="flashvars" value="isShowRelatedVideo=false&showAd=0&show_pre=1&show_next=1&isAutoPlay=false&isDebug=false&UserID=&winType=interior&playMovie=true&MMControl=false&MMout=false&RecordCode=1001,1002,1003,1004,1005,1006,2001,3001,3002,3003,3004,3005,3007,3008,9999" /><embed src="http://player.youku.com/player.php/sid/XMTM4NDQwNzgw/v.swf" type="application/x-shockwave-flash" allowscriptaccess="never" allownetworking="internal" allowfullscreen="true" width="480" height="400" flashvars="isShowRelatedVideo=false&showAd=0&show_pre=1&show_next=1&isAutoPlay=false&isDebug=false&UserID=&winType=interior&playMovie=true&MMControl=false&MMout=false&RecordCode=1001,1002,1003,1004,1005,1006,2001,3001,3002,3003,3004,3005,3007,3008,9999"></embed></object>
<p><strong>注意：</strong>该视频原版位于Vimeo，但是要看的话需要翻[和谐]墙先，地址在这里：<a href="http://vimeo.com/7405114" target="_blank">http://vimeo.com/7405114</a>，上面的视频是我费尽周折从Vimeo上下载下来上传到优酷的，上传后质量竟被大打折扣了，囧。youtube上也有一份视频，是基于Aptana的演示，一样很精彩：<a href="http://www.youtube.com/watch?v=ug84Ypwqfzk" target="_blank">http://www.youtube.com/watch?v=ug84Ypwqfzk</a>。PS:貌似youtube要比Vimeo翻[和谐]墙容易些，不过如何翻[和谐]墙不在本站讨论范围。</p>
<p>如果你想跳转到详细介绍和使用指南，请看一下演示页面并立刻下载你适用的插件：</p>
<p><strong>Demo</strong></p>
<p>●<a href="http://zen-coding.ru/demo/">Demo</a> (使用 <em>Ctrl + ,</em> 展开缩写，需要JavaScript支持)</p>
<p>●<a href="http://labs.qianduan.net/zencoding/">中文版演示</a></p>
<p><strong>下载(完全支持)</strong></p>
<p>●<a href="http://code.google.com/p/zen-coding/downloads/detail?name=Zen.Coding-Aptana.v0.5.zip">Aptana</a> (跨平台);</p>
<p>●Coda, via <a href="http://github.com/sergeche/tea-for-coda/downloads">TEA for Coda</a> (Mac);</p>
<p>●Espresso, via <a href="http://github.com/sergeche/tea-for-espresso/downloads">TEA for Espresso</a> (Mac);</p>
<p><strong>下载(部分支持，只支持“展开缩写”)</strong></p>
<p><a href="http://code.google.com/p/zen-coding/downloads/detail?name=Zen%20Coding%20for%20TextMate%20v0.3.1.zip">TextMate</a>(只能用于Mac机,Windows可以使用E-text编辑器替代);</p>
<p>●<a href="http://code.google.com/p/zen-coding/downloads/detail?name=TopStyle.Zen.Coding.1.0.zip">TopStyle</a>;</p>
<p>●<a href="http://code.google.com/p/zen-coding/downloads/detail?name=Sublime.Zen.Coding.1.1.3.zip">Sublime Text</a>;</p>
<p>●<a href="http://www.kryogenix.org/days/2009/09/21/zen-coding-for-gedit">GEdit</a>;</p>
<p>●<a href="http://zen-coding.googlecode.com/files/Zen.Coding-Dreamweaver.v0.4.zip">Dreamweaver CS4</a></p>
<p>●<a href="http://zen-coding.ru/demo/">editArea在线编辑器</a>;</p>
<p>●<a href="http://labs.qianduan.net/zencoding/">Zen Coding在线编辑器中文版</a></p>
<p>现在让我们看一下这些工具是如何工作的吧。</p>
<p><strong>展开缩写</strong></p>
<p>展开缩写功能将类似CSS的选择器转换为XHTML代码。术语“缩写”可能会有点儿难以理解。为什么不直接称之为“CSS选择器”呢？嗯，首要原因是语义化：“选择器”意为<em>选择</em>一些东西，但是在这里我们事实上是<em>生成</em> 一些东西，<strong>是写一个长代码的较短的替代</strong>。其次，它只是使用真实的CSS选择器语法的一个小的子集，并添加了一些新的操作符。</p>
<p>这里是一个支持的属性和操作符的列表：</p>
<p>●E</p>
<p>元素名称(div, p);</p>
<p>●E#id</p>
<p>使用id的元素(div#content, p#intro, span#error);</p>
<p>●E.class</p>
<p>使用类的元素(div.header, p.error.critial). 你也可以联合使用class和idID: div#content.column.width;</p>
<p>●E&gt;N</p>
<p>子代元素(div&gt;p, div#footer&gt;p&gt;span);</p>
<p>●E+N</p>
<p>兄弟元素(h1+p, div#header+div#content+div#footer);</p>
<p>●E*N</p>
<p>元素倍增(ul#nav&gt;li*5&gt;a);</p>
<p>●E$*N</p>
<p>条目编号 (ul#nav&gt;li.item-$*5);</p>
<p>正如你能看到的，你已经知道如何使用Zen Coding了：只是些一个简单的仿CSS选择器(呃，“缩写”抱歉)，就像这样…</p>
<p>…然后调用”展开缩写”行为。</p>
<p>这里有两个新增的操作符：元素倍增和条目编号。比如，如果你想生成5个&lt;li&gt;元素，你可以简单的写位li*5。它也将同样重写全部子 代元素。如果你想写4个&lt;li&gt;元素，每个里面都有一个&lt;a&gt;标签，你就可以简单的写为li*4&gt;a，这样会生成以下 HTML代码：</p>
<pre class="brush: html; gutter: true">&lt;li&gt;&lt;a href=&quot;&quot;&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;&quot;&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;&quot;&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;&quot;&gt;&lt;/a&gt;&lt;/li&gt;</pre>
<p>最后一个——条目编号用于当你想用索引标记重复的元素的情况。假设你想生成class为item1、item2和item3的3个&lt;div&gt;元素。你可以写成这样的缩写，div.item$*3:</p>
<pre class="brush: html; gutter: true">&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;</pre>
<p>只需在你想要索引出现的任何class或id属性上添加一个美元符号即可，而且想要多少都可以。那么，这样…</p>
<pre class="brush: html; gutter: true">div#i$-test.class$$$*5</pre>
<p>会被转换成为:</p>
<pre class="brush: html; gutter: true">&lt;div id=&quot;i1-test&quot;&gt;&lt;/div&gt;
&lt;div id=&quot;i2-test&quot;&gt;&lt;/div&gt;
&lt;div id=&quot;i3-test&quot;&gt;&lt;/div&gt;
&lt;div id=&quot;i4-test&quot;&gt;&lt;/div&gt;
&lt;div id=&quot;i5-test&quot;&gt;&lt;/div&gt;</pre>
<p>你会看到，当你写a的缩写的时候，输出是&lt;a href=”&#8221;&gt;&lt;/a&gt;。或者，如果你写img，输出就是&lt;img src=”&#8221; alt=”&#8221; /&gt;。</p>
<p>Zen Coding是如何知道什么时候应该为生成的标签添加默认的属性或者跳过关闭标签的？有一个专门的文件，名为<em><a href="http://code.google.com/p/zen-coding/source/browse/branches/serge.che/aptana/zen_settings.js">zen_settings.js</a></em>描述了输出元素。这是一个简单的JSON文件，描述每种语言的缩写(是的，你可以为不同的句法定义缩写，比如HTML、XSL、CSS等)。通用的语言缩写定义看起来就像这样：</p>
<pre class="brush: javascript; gutter: true">&#039;html&#039;: { &#039;snippets&#039;: { &#039;cc:ie6&#039;: &#039;&lt;!--[if lte IE 6]&gt;\n\t${child}|\n&lt;![endif]--&gt;&#039;,
            ...
            },
              &#039;abbreviations&#039;: { &#039;a&#039;: &#039;&lt;a href=&quot;&quot;&gt;&lt;/a&gt;&#039;, &#039;img&#039;: &#039;&lt;img src=&quot;&quot; alt=&quot;&quot; /&gt;&#039;,
            ...
            }
            }</pre>
<p><strong>元素类型</strong></p>
<p>Zen Coding有两个主要的元素类型：<strong>“片段(snippets)” 和 “缩写(abbreviations)”。</strong>片 段就是随意的代码碎片，而缩写是标签定义。通过片段，你可以写出你想要的任何代码，它也会照你写的格式输出；但是你必须手动的格式化它(使用\n 和\t实现换行和缩进) 并将${child}变量放到你想要输出子元素的地方，就像这样：cc:ie6&gt;style。如果你不使用${child}变量，子元素将会输出于 代码片段的<strong>后面</strong>。</p>
<p>有了缩写，您必须编写标记定义，而且语法是非常重要的。通常，你必须写一个简单的带有所有默认的属性的标签，比如: &lt;a href=”&#8221;&gt;&lt;/a&gt;。当Zen Coding被加载后，它会解析一个标签定义到一个描述该标签的名字、属性(包括它们的顺序)以及该标签是否为空的特定的对象中。所以，如果你 写&lt;img src=”&#8221; alt=”&#8221; /&gt;，你会告诉Zen Coding这个标签必须是空的，然后“扩展缩写”行为就会在输出之前为它使用特定的规则。</p>
<p>对于片段和缩写，你可以添加一个管道符号，它告诉Zen Coding当缩写被展开的时候光标会被定位到哪里。默认的，Zen Coding 将光标放在空属性的引号中间以及开始和关闭标签的中间。</p>
<p><strong>例子</strong></p>
<p>那么，这里解释一下当你写了一个缩写并召唤“展开缩写”行动时发生的事情。首先，它将一个完整的缩写分开为独立的元素：这样div&gt;a 会被分成div 和a 元素，当然也会维持他们的关系。然后，每个元素，解析器先在代码片段内而后在缩写中寻找定义。如果它找不到，将会使用元素的名字作为新的标签，并为其添加 缩写中定义的id和class。比如，如果你写mytag#example，解析器在片段或缩写中找不到mytag定义，它就会输出&lt;mytag id=”example”&gt;&lt;mytag&gt;。</p>
<p>我们制作了很多<a href="http://code.google.com/p/zen-coding/wiki/ZenCSSPropertiesEn">默认的CSS</a>和<a href="http://code.google.com/p/zen-coding/wiki/ZenHTMLElementsEn">HTML缩写和片段</a>。你会发现学习使用Zen Coding可以增加你的生产力。</p>
<p><strong>HTML 标签对匹配器</strong></p>
<p>对于HTML编码者的另一个非常常见的任务是寻找一个元素的标签对。例如你想选择整个&lt;div id=”content”&gt;标签并将其移动到其它地方或者删除它。或者有可能你在寻找一个关闭标签并想知道它属于那个开始标签。</p>
<p>不幸的是，很多现代开发工具在该功能方面有所欠缺。那么我就决定写一个我自己的标签对匹配器作为Zen Coding的一部分。不过它依然在beta阶段并尚存一些问题，但它可以工作的很不错并很快。不是浏览整个文档(像通常的那种HTML标签对匹配器的做 法)，它从光标的当前位置开始寻找相关的标签。这使得它非常快并且<em>上下文无关</em>：它甚至可以用于这段<strong>JavaScript代码片段</strong>：</p>
<pre class="brush: javascript; gutter: true">var table = &#039;&lt;table&gt;&#039;; for (var i = 0; i &lt; 3; i++) {
    table += &#039;&lt;tr&gt;&#039;; for (var j = 0; j &lt; 5; j++) {
        table += &#039;&lt;td&gt;&#039; + j + &#039;&lt;/td&gt;&#039;;
    }
    table += &#039;&lt;/tr&gt;&#039;;
}
table += &#039;&lt;/table&gt;&#039;;</pre>
<p><strong>使用缩写包裹</strong></p>
<p>这真的是一个很酷的特性，它将缩写和标签对匹配器的功能合并到一起了。你有多少才发现你需要<strong>添加一个包裹元素以修正一个<span class='wp_keywordlink'><a href="http://blog.jobbole.com/12749/" title="浏览器">浏览器</a></span>bug</strong>？或者你需要添加一个装饰，比如一个背景图片或者边框到一个块级内容？你必须写开始标签，临时打断你的代码，找到相关的点然后关闭标签。这就是“使用缩写包裹”能帮助你的地方。</p>
<p>该功能相当简单：它要求你输入缩写，然后执行适当的“展开缩写”行动并将你期望的文本放到你缩写的<em>最后一个元素里面</em>。如果你没有选择任何文本，它就会启动标签对匹配器并使用结果。它同样能搞清楚你的光标的位置：标签的内容里面或者是开始和关闭标签中间。依赖于它的位置，它会包裹标签的内容或标签本身。</p>
<p>缩写包裹为包裹个别行引入了一个特定的缩写句法。简单跳转到倍增操作符后面的数字，比如：ul#nav&gt;li*&gt;a。当Zen Coding 发现一个使用未定义的倍增数的时候，它会将它作为一个<em>重复元素</em>：你的章节中有多少行，它就会输出多少次，并将每行的内容放到重复元素的<em>最后一个子元素</em>里面。</p>
<p>如果你在这段文本外面包裹这段缩写div#header&gt;ul#navigation&gt;li.item$*&gt;a&gt;span：</p>
<pre class="brush: html; gutter: true">About Us
Products
News
Blog
Contact Up</pre>
<p>你将会得到以下结果：</p>
<pre class="brush: html; gutter: true">&lt;div id=&quot;header&quot;&gt;
    &lt;ul id=&quot;navigation&quot;&gt;
        &lt;li&gt;&lt;a href=&quot;&quot;&gt;&lt;span&gt;About Us&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&quot;&quot;&gt;&lt;span&gt;Products&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&quot;&quot;&gt;&lt;span&gt;News&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&quot;&quot;&gt;&lt;span&gt;Blog&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&quot;&quot;&gt;&lt;span&gt;Contact Up&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
&lt;/div&gt;</pre>
<p>你可以看到，Zen Coding是一个强大的文本处理工具。</p>
<p><strong>快捷键</strong></p>
<p>●Ctrl+,</p>
<p>展开缩写</p>
<p>●Ctrl+M</p>
<p>匹配对</p>
<p>●Ctrl+H</p>
<p>使用缩写包括</p>
<p>●Shift+Ctrl+M</p>
<p>合并行</p>
<p>●Ctrl+Shift+?</p>
<p>上一个编辑点</p>
<p>●Ctrl+Shift+?</p>
<p>下一个编辑点</p>
<p>●Ctrl+Shift+?</p>
<p>定位匹配对</p>
<p>这些快捷键是可以自定义的。</p>
<p><strong>在线演示</strong></p>
<p>你已经学到很多关于Zen Coding如何工作以及它是如何使你的编码更容易了。现在为什么不自己尝试一下呢？因为Zen Coding是用纯JavaScript开发并迁移到Python，它甚至可以用于浏览器内部，这令它成为引入到CMS的首选。</p>
<p>●<a href="http://zen-coding.ru/demo/">Demo</a> (使用 <em>Ctrl + ,</em> 展开缩写，需要JavaScript支持)</p>
<p>●<a href="http://labs.qianduan.net/zencoding/">中文版演示</a></p>
<p><strong>支持的编辑器</strong></p>
<p>Zen Coding并不依赖某个特定的编辑器。它是一个只处理文本的出色的组件：它获取文本、做一些处理并放回新的文本(或索引，用于标签匹配)。Zen Coding由JavaScript和Python编写，所以它实际上可以运行于任何平台。在Windows，你可以运行JavaScript版本，而 Mac和Linux 分支可以使用Python版。</p>
<p>如果让你的编辑器支持Zen Coding，你需要写一个特定的可以在你的编辑器和Zen Coding之间转换数据的插件。问题是一个编辑器可能不会完整的支持Zen Coding因为它本身的插件系统。比如，<a href="http://macromates.com/">TextMate</a>通过使用脚本输出替换当前行很容的就支持了“展开缩写”功能，但是它不能处理标签对匹配因为没有标准的方法请求TextMate来选择内容。</p>
<p><strong>完全支持</strong></p>
<p>●<a href="http://code.google.com/p/zen-coding/downloads/detail?name=Zen.Coding-Aptana.v0.5.zip">Aptana</a> (跨平台);</p>
<p>●Coda, via <a href="http://github.com/sergeche/tea-for-coda/downloads">TEA for Coda</a> (Mac);</p>
<p>●Espresso, via <a href="http://github.com/sergeche/tea-for-espresso/downloads">TEA for Espresso</a> (Mac);</p>
<p><strong>部分支持(只支持“展开缩写”)</strong></p>
<p>●<a href="http://code.google.com/p/zen-coding/downloads/detail?name=Zen%20Coding%20for%20TextMate%20v0.3.1.zip">TextMate</a> (只能用于Mac机,Windows可以使用E-text编辑器替代);</p>
<p>●<a href="http://code.google.com/p/zen-coding/downloads/detail?name=TopStyle.Zen.Coding.1.0.zip">TopStyle</a>;</p>
<p>●<a href="http://code.google.com/p/zen-coding/downloads/detail?name=Sublime.Zen.Coding.1.1.3.zip">Sublime Text</a>;</p>
<p>●<a href="http://www.kryogenix.org/days/2009/09/21/zen-coding-for-gedit">GEdit</a>;</p>
<p>●<a href="http://zen-coding.googlecode.com/files/Zen.Coding-Dreamweaver.v0.4.zip">Dreamweaver CS4</a></p>
<p>●<a href="http://zen-coding.ru/demo/">editArea在线编辑器</a>;</p>
<p>●<a href="http://labs.qianduan.net/zencoding/">Zen Coding在线编辑器中文版</a></p>
<p>Aptana是我主要的开发环境，它使用一个JavaScript版本的Zen Coding。它也包含很多其它的我用于日常工作的工具，所以任何一个新的Zen Coding版本都将会首先对Aptana可用，然后部署到Python并兼容其它的编辑器。</p>
<p>Coda和Espresso 插件被杰出的<a href="http://onecrayon.com/tea/">Text Editor Actions</a> (TEA) 平台支持，由<a href="http://beckism.com/">Ian Beck</a>开发。原始的源代码<a href="http://github.com/onecrayon">在GitHub上</a>，但我还是制作了<a href="http://github.com/sergeche/">我自己的分支</a>以整合Zen Coding的特性。</p>
<p><strong>总结</strong></p>
<p>很多尝试过Zen Coding的人都说它改变了他们写页面的方式。当然还有很多事情要做，还有很多的编辑器需要被支持以及一些文档要写。请浏览<a href="http://code.google.com/p/zen-coding/w/list">现在的文档</a> 以及<a href="http://code.google.com/p/zen-coding/source/browse/#svn/branches/serge.che">源代码</a>以寻找你的问题的答案。希望你喜欢Zen Coding!</p>
<p><strong>附：Zen coding的具体用法</strong></p>
<p>遗憾的是， 本文原作者并没有说明zen coding的具体用法，神飞认为有必要做以下简要的说明。这里就以Aptana/Eclipse和Dreamweaver为例，其它编辑器平台暂不描述，如有疑问可以在评论中与前端观察的网友交流。</p>
<p><strong>Aptana/Eclipse</strong></p>
<p>由于Aptana本身就是基于Eclipse的，所以，Zen Coding也是支持Eclipse的，只是需要一个EclipseMonkey插件的支持，Aptana已经封装了这个插件，所以如果你使用Aptana，下面的第一步可以跳过。</p>
<p>1、通过更新网站安装EclipseMonkey: <a href="http://download.eclipse.org/technology/dash/update" rel="nofollow">http://download.eclipse.org/technology/dash/update</a>(如果你使用Aptana，可跳过这一步)</p>
<p>2、在你的当前工作去创建一个顶级的项目，给它命名，比如，就叫<strong>zencoding</strong>&lt;</p>
<p>3、在新创建的项目中创建<strong>scripts</strong>文件夹</p>
<p>4、解压缩下载的ZIP插件包到该文件夹。项目结构看起来就像这样:</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/A-Speedy-Way-To-Write-Code.png" rel="lightbox[19714]" title="Zen Coding: 一种快速编写HTML/CSS代码的方法 "><img class="aligncenter size-full wp-image-19715" title="Zen Coding: 一种快速编写HTML/CSS代码的方法 " src="http://blog.jobbole.com/wp-content/uploads/2012/05/A-Speedy-Way-To-Write-Code.png" alt="Zen Coding: 一种快速编写HTML/CSS代码的方法 " width="405" height="293" /></a></p>
<p>5、安装之后，Aptana的菜单栏中的“脚本(Script)”菜单中将会出现Zen coding相关子菜单</p>
<p>注意事项：</p>
<p>●Aptana版的官方插件是基于MAC机的，如果你用的是Windows，需要手动更改快捷键(在每个文件头部的注释片段中更改)</p>
<p>●官方的文件编码有点儿乱，修改官方js的时候，请注意<strong>编码问题</strong>，修改不当会造成相关功能的丢失；</p>
<p><strong>DreamWeaver</strong></p>
<p>好消息是，现在已经有了Zen coding for DreamWeaver插件，坏消息是，该插件支持的功能很少，只支持展开缩写功能。而且默认的快捷键是无效的。只能在“命令”菜单中点击操作。另外，没 有测试该插件是不是只支持CS4版本。不过比较好的是，作者将本插件的源码也放出了，你可以自定义一个Dreamweaver的插件。</p>
<p><del>事实上，官方的DW插件在Windows下有点儿bug，就是会出现空白的行，我简单的修正了下，重新编译了个包，在本机测试没问题，感兴趣的童鞋可以下载尝试：<a href="http://www.boxcn.net/shared/c71z7x7sfe" target="_blank">http://www.boxcn.net/shared/c71z7x7sfe</a></del></p>
<p>PS:官方的DW插件已经更新，<strong>推荐</strong><a href="http://zen-coding.googlecode.com/files/Zen%20Coding.mxp" target="_blank">到官方去下载</a>。新的插件添加了更多的功能支持。UPDATE @ 12-23-2009</p>
<p><strong>特别推荐</strong>：豪情同学将缩写给实践了一番，总结出了很多很棒的用例，推荐大家<a href="http://www.cnblogs.com/jikey/archive/2009/12/19/1628002.html" target="_blank">前去学习</a>。</p>
<p><strong>原作者介绍：</strong></p>
<p>Sergey Chikuyonok是一位俄罗斯的前端开发工程师和作者，他在优化方面有很大的热情：从图片、JavaScript效果到工作流程和节省时间的编码。访问<a href="http://chikuyonok.ru/" target="_blank">他的主页</a>和<a href="http://twitter.com/chikuyonok" target="_blank">他的Twitter</a>。</p>
<p>英文原文：<a href="http://www.smashingmagazine.com/2009/11/21/zen-coding-a-new-way-to-write-html-code/">Smashing Magazine</a></p>
<h2  class="related_post_title">相关文章</h2><ul class="related_post"><li><a target="_blank" href="http://blog.jobbole.com/16668/" title="Codecademy为编程初学者新增HTML和CSS两门课程">Codecademy为编程初学者新增HTML和CSS两门课程</a></li><li><a target="_blank" href="http://blog.jobbole.com/10408/" title="如何将页脚固定在页面底部">如何将页脚固定在页面底部</a></li><li><a target="_blank" href="http://blog.jobbole.com/854/" title="6种编写HTML和CSS的最有效的方法">6种编写HTML和CSS的最有效的方法</a></li><li><a target="_blank" href="http://blog.jobbole.com/19701/" title="谈谈CSS Sprites技术及其优化">谈谈CSS Sprites技术及其优化</a></li><li><a target="_blank" href="http://blog.jobbole.com/19592/" title="HTML特殊字符大全">HTML特殊字符大全</a></li><li><a target="_blank" href="http://blog.jobbole.com/19322/" title="HTML的15个最佳实践">HTML的15个最佳实践</a></li><li><a target="_blank" href="http://blog.jobbole.com/16375/" title="10个便利的CSS代码在线生成器">10个便利的CSS代码在线生成器</a></li><li><a target="_blank" href="http://blog.jobbole.com/14681/" title="前端是否应该将CSS和JS分开设置两个不同岗位">前端是否应该将CSS和JS分开设置两个不同岗位</a></li><li><a target="_blank" href="http://blog.jobbole.com/13758/" title="10 款实用的 CSS 开发助手推荐">10 款实用的 CSS 开发助手推荐</a></li><li><a target="_blank" href="http://blog.jobbole.com/10011/" title="前端开发人员需要了解的CSS原理 ">前端开发人员需要了解的CSS原理 </a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.jobbole.com/19714/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>代码审查中的暴力冲突</title>
		<link>http://blog.jobbole.com/19709/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25e4%25bb%25a3%25e7%25a0%2581%25e5%25ae%25a1%25e6%259f%25a5%25e4%25b8%25ad%25e7%259a%2584%25e6%259a%25b4%25e5%258a%259b%25e5%2586%25b2%25e7%25aa%2581</link>
		<comments>http://blog.jobbole.com/19709/#comments</comments>
		<pubDate>Thu, 17 May 2012 01:56:33 +0000</pubDate>
		<dc:creator>齐哲</dc:creator>
				<category><![CDATA[程序员]]></category>
		<category><![CDATA[Code Review]]></category>
		<category><![CDATA[代码审查]]></category>

		<guid isPermaLink="false">http://blog.jobbole.com/?p=19709</guid>
		<description><![CDATA[“你好，麦克

我想为昨天在代码审查中发生的事情向你道歉。我做了和说了一些非常不体面的事。

首先，我不应该坚持用逻辑语(Lojban)进行这次审查。我本以为这样可以使审查过程更有逻辑次序，但事实很显然不是这样。而且，我还错误的认为你用逻辑语(Lojban)交流(很不流利)是对我的冒犯。

第二，我承认，我因为你使用Java而称你为“<em>公司娼妓</em>”是完全没必要的，而且是很过分的。我知道，虽然这是一种有深度缺陷的语言，只有神经错乱的精神病或居心叵测的公司奸细才会想使用它，但这是部门的规定，应该遵守。

还有，试图通过向你注射“<em>依赖果汁(dependency juice)</em>”来演示依赖注入的重要性的方式是非常欠考虑的。不过你可以放宽心，据我所知，依赖果汁(dependency juice)的化学组成成分是非常适合人体消化吸收的。

既然说到这里，我再说一点，我真的很后悔我是如何解释正确的抛异常的方式的。我现在知道了，在办公室里抛物体(或人)是很不受大家赞同的。还有，我惊讶的发现，在人的脑门上写画，特别是用永久墨水，不管你写的是什么，人们都不会接受。

但是，这里我最想(在法律上也是有义务)要道歉的事情，也许应该是我们的代码审查结束的方式。特别是，我真的后悔把不顺眼的类代码打印出来，并以祭祀的形式的当着你的面把它烧掉。这几乎是没必要的，虽然我后来发现其实不会引起火灾。

感谢你花时间理解我的歉意。

你真诚的，

鲍勃”
<p id="page-note">[本文英文原文链接：<a href="http://tatiyants.com/code-review-gone-bad/">Code Review Gone Bad</a> ]</p>]]></description>
			<content:encoded><![CDATA[<p>“你好，麦克</p>
<p>我想为昨天在代码审查中发生的事情向你道歉。我做了和说了一些非常不体面的事。</p>
<p>首先，我不应该坚持用逻辑语(Lojban)进行这次审查。我本以为这样可以使审查过程更有逻辑次序，但事实很显然不是这样。而且，我还错误的认为你用逻辑语(Lojban)交流(很不流利)是对我的冒犯。</p>
<p>第二，我承认，我因为你使用Java而称你为“<em>公司娼妓</em>”是完全没必要的，而且是很过分的。我知道，虽然这是一种有深度缺陷的语言，只有神经错乱的精神病或居心叵测的公司奸细才会想使用它，但这是部门的规定，应该遵守。</p>
<p>还有，试图通过向你注射“<em>依赖果汁(dependency juice)</em>”来演示依赖注入的重要性的方式是非常欠考虑的。不过你可以放宽心，据我所知，依赖果汁(dependency juice)的化学组成成分是非常适合人体消化吸收的。</p>
<p>既然说到这里，我再说一点，我真的很后悔我是如何解释正确的抛异常的方式的。我现在知道了，在办公室里抛物体(或人)是很不受大家赞同的。还有，我惊讶的发现，在人的脑门上写画，特别是用永久墨水，不管你写的是什么，人们都不会接受。</p>
<p>但是，这里我最想(在法律上也是有义务)要道歉的事情，也许应该是我们的代码审查结束的方式。特别是，我真的后悔把不顺眼的类代码打印出来，并以祭祀的形式的当着你的面把它烧掉。这几乎是没必要的，虽然我后来发现其实不会引起火灾。</p>
<p>感谢你花时间理解我的歉意。</p>
<p>你真诚的，</p>
<p>鲍勃”</p>
<p id="page-note">[本文英文原文链接：<a href="http://tatiyants.com/code-review-gone-bad/">Code Review Gone Bad</a> ]</p>
<h2  class="related_post_title">相关文章</h2><ul class="related_post"><li><a target="_blank" href="http://blog.jobbole.com/17630/" title="敏捷代码审查指南">敏捷代码审查指南</a></li><li><a target="_blank" href="http://blog.jobbole.com/16416/" title="开发人员抵触代码审查的4个原因 ">开发人员抵触代码审查的4个原因 </a></li><li><a target="_blank" href="http://blog.jobbole.com/1252/" title="编码规范：大家都应该做的事情">编码规范：大家都应该做的事情</a></li><li><a target="_blank" href="http://blog.jobbole.com/1243/" title="开发人员需做代码复查的5个原因">开发人员需做代码复查的5个原因</a></li><li><a target="_blank" href="http://blog.jobbole.com/1171/" title="代码审查：大家都应该做的事情">代码审查：大家都应该做的事情</a></li><li><a target="_blank" href="http://blog.jobbole.com/282/" title="成为一名优秀程序员所需要知道的15件事">成为一名优秀程序员所需要知道的15件事</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.jobbole.com/19709/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>谈谈CSS Sprites技术及其优化</title>
		<link>http://blog.jobbole.com/19701/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25e8%25b0%2588%25e8%25b0%2588css-sprites%25e6%258a%2580%25e6%259c%25af%25e5%258f%258a%25e5%2585%25b6%25e4%25bc%2598%25e5%258c%2596</link>
		<comments>http://blog.jobbole.com/19701/#comments</comments>
		<pubDate>Thu, 17 May 2012 01:52:28 +0000</pubDate>
		<dc:creator>齐哲</dc:creator>
				<category><![CDATA[设计]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[CSS Sprites]]></category>
		<category><![CDATA[前端]]></category>

		<guid isPermaLink="false">http://blog.jobbole.com/?p=19701</guid>
		<description><![CDATA[CSS Sprites 技术对于广大的前端工程师来说应该是一点也不陌生。这个被国内开发者昵称为“CSS精灵”。 CSS雪碧的家伙到底解决了什么问题，我们又怎样合理使用这个技术呢？下面让我们详细的聊聊。

在大家还在拨号上网的“远古时期”，由于网速的限制，页面开发者都喜欢把网页里面的图片字节数控制的非常小，往往在一个图片文件夹里散落着n多的小 碎图。随着网络技术的发展，网速的提升，大家越来越重视页面的加载速度，页面效率问题，过去的那些小图便成为了前端开发者的眼中钉，因为每加载一张图片都 会产生一次浏览器请求数，发起的请求数越多那么页面加载的速度也越慢。还有当页面加载时，图片一个个的零星显示，鼠标经过时候背景闪白等也都是我们不能忍 受的。于是乎将页面中的背景图整合到一起，利用“background- image”，“background- repeat”，“background-position”的组合进行背景定位的技术被广泛使用与了页面构建 中，这就是CSS Sprites。当然CSS Sprites技术也存在着维护不便，内存占用大等等的缺点。

好了，如果我只说这些，那么这篇文章就有点太水了。前面那些只是对CSS Sprites技术的一个普及。作为一个开发者我们应该对它有一个更全面的认识，挖掘深度内容，这样才能有利于我们效率开发，团队协作。

<strong>头疼的多人拼图游戏</strong>

使用CSS Sprites，就好像玩拼图游戏一样。一张白画布，那么多图怎么放到里面去才会完美？这是个让人纠结的事。而且在实际在工作场景中， 我们面临着项目开发时间紧张，UI设计图要分期提供，多人协同开发一个项目等等问题。这些问题非常容易让我们在大项目中迷失，造成CSS拼图混乱，维护及 其困难的情况。

定好规则，其实拼图也挺好玩的

<strong>先期的准备工作</strong>

应对一个项目后期维护成本大的问题，我们最好的解决方案就是在开始前制定一系列的规范来限制问题的产品。好的开始是成功的一半。对于 CSS Sprites，在项目开始前，我们要充分认识一个产品，同UI设计师做好良好的沟通，对我们未来组成我们Sprites图的各个元素有个大体的 概念，比如我们的背景拼图可能包括什么。

<strong>一个好的Sprite画布是必须的</strong>

网页设计里面，Grid系统是必不可少的，好的Grid能解决我们很多排版问题。Grid系统同样适用于CSS Sprites。我们需要创建好一个优秀的画板，剩下的工作就是将元素合理的置于画板中了。

这张是我准备的一张CSS Sprites画布，我们将在这个PSD里面组合项目中的图片。

这张画布是由20px*20px像素的格子组成。这个格子基本上由项目决定的，当我们同UI设计师沟通了解这个项目最多的为16px*16px 图标时。我们就可以采用这种Grid尺寸为画布了。

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Talk-about-the-CSS-Sprites-technique-and-its-optimization1.png"><img class="aligncenter size-full wp-image-19703" title="谈谈CSS Sprites技术及其优化 " src="http://blog.jobbole.com/wp-content/uploads/2012/05/Talk-about-the-CSS-Sprites-technique-and-its-optimization1.png" alt="谈谈CSS Sprites技术及其优化 " width="488" height="262" /></a>

<strong>Sprites画布有了，接下来就是对图标进行分组了</strong>

对于信息的归纳总结、分类是一个有意思的事情。就拿图标来说，我们就可以根据图标功能，尺寸等等作为信息维度进行归纳。其实无论怎么归纳，都是可以的，只是记得我们以一个方向作为标准就可以了。

下图是根据微博站外某组件完成的CSS Sprites

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Talk-about-the-CSS-Sprites-technique-and-its-optimization2.png"><img class="aligncenter size-full wp-image-19704" title="谈谈CSS Sprites技术及其优化 " src="http://blog.jobbole.com/wp-content/uploads/2012/05/Talk-about-the-CSS-Sprites-technique-and-its-optimization2.png" alt="谈谈CSS Sprites技术及其优化 " width="488" height="262" /></a>

根据设计，我们了解在这个页面，需要将图片元素根据功能分为4个维度，即微博品牌展示元素、提交按钮、操作类小按钮、提示类ICON。于是我将画布 X轴坐标方向每5个格（其实完全可以10个格或者更多）划分为一个区域，每个这样一个区域的Y轴方向不再划分区域，这样做的目的是为了以后增加图标的扩展 性。于是我们可以非常快速得到一个图标的坐标了。比如不可用的灰色的分享按钮 X坐标=5*20px=100px Y坐 标=7*20px=140px; 那么我们就取得了这个图标的位置即background-position: -100px -140px。如果抽象成 为公式的话，我们设置一个单元格的宽度为变量n。X坐标值Gx,Y坐标值Gy。那么画布中的元素css背景即为：background- position:-Gx*npx –Gy*npx 了。

<strong>现在图有了，怎么取图也是关键</strong>

因为图片尽可能的被整合到一张拼图，所以我们需要在页面使用图片的位置使用空标签定位的方式将拼图所需展现的部分展示到页面中。

&#160;
<pre class="brush: html; gutter: true">&#60;span class=”iconA”&#62;&#60;/span&#62;
.iconA { display:inline-block; height:16px; width:16px; background:url(icons.png) -20px -20px no-repeat }</pre>
&#160;

<strong>项目出现二期需求了，需要增加图标？</strong>

需求总是不能控制，我们要尽可能的为未来增加图片做好打算。在刚才的例子的项目里后期产品需要增加图标，于是：

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Talk-about-the-CSS-Sprites-technique-and-its-optimization3.png"><img class="aligncenter size-full wp-image-19705" title="谈谈CSS Sprites技术及其优化 " src="http://blog.jobbole.com/wp-content/uploads/2012/05/Talk-about-the-CSS-Sprites-technique-and-its-optimization3.png" alt="谈谈CSS Sprites技术及其优化 " width="488" height="262" /></a>

我们可以继续在对应的图区内增加对应的图标。但是这个例子同样暴露了一个缺陷，如果新增一个按钮区域大于5n(100px)，我们的图区不足以承 载。这时候我们可以同产品，设计师沟通协调，商议是否可以取消过大的按钮设计。如果需求一定，那我们只能沿着X轴方向继续扩展画布。不过，我们也需要注意 无限的放大一张画布，同样会造成对页面效率的影响。

及时的制定好规范，记录好修改日志

可能在项目的初期，我们还来不及制定合图的具体规范，在项目中我们会遇到各种各样的问题。及时的总结，维护整张CSS拼图，在拼图的PSD或者PNG（使用Fireworks）做好注释，方便他人开发。拼合好的图片提交到svn时也写明log内容，这样便日后查询。

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Talk-about-the-CSS-Sprites-technique-and-its-optimization5.png"><img class="aligncenter size-full wp-image-19702" title="谈谈CSS Sprites技术及其优化 " src="http://blog.jobbole.com/wp-content/uploads/2012/05/Talk-about-the-CSS-Sprites-technique-and-its-optimization5.png" alt="谈谈CSS Sprites技术及其优化 " width="577" height="201" /></a>

<strong>我们最终的目的</strong>

其实CSS Sprites经过了那么多年的演变，前端开发者不断的优化，都是为了提升页面效率，提升团队开发效率，减少开发维护成本而努力。配合 最近非常流行的将CSS动态语言化（如SASS LESS等），增加入变量， 继承， 运算， 函数等。CSS Sprites会变的更好玩，会减少更多 的开发维护成本。甚至我们在“面向对象”的模块开发方式中，还可以使用一个类的的同一个backgroud-position：（x y）值，在不同的页 面通过引用不同的图片（background属性）实现将一个页面内图片请求量进一步减少的目的。随着高级浏览器的普及我们还可以多使用CSS3属性，减 少渐变背景图的使用，将纯色ICON制作成字体取代拼图等我们能更大程度上减少图片的使用量。这篇文章只是抛砖引玉。实际上还有很多关于 CSS Sprites的方法，还有众多的拼图生成工具。

说了那么多，我们如果在日常的开发中，只要我们多注意总结，敢于创新，敢于制定规范，那么再小的事也能干的很漂亮，对于CSS Sprites的优化就是这么一个例子，你说不是么？]]></description>
			<content:encoded><![CDATA[<p>CSS Sprites 技术对于广大的前端工程师来说应该是一点也不陌生。这个被国内开发者昵称为“CSS精灵”。 CSS雪碧的家伙到底解决了什么问题，我们又怎样合理使用这个技术呢？下面让我们详细的聊聊。</p>
<p>在大家还在拨号上网的“远古时期”，由于网速的限制，页面开发者都喜欢把网页里面的图片字节数控制的非常小，往往在一个图片文件夹里散落着n多的小 碎图。随着网络技术的发展，网速的提升，大家越来越重视页面的加载速度，页面效率问题，过去的那些小图便成为了前端开发者的眼中钉，因为每加载一张图片都 会产生一次<span class='wp_keywordlink'><a href="http://blog.jobbole.com/12749/" title="浏览器">浏览器</a></span>请求数，发起的请求数越多那么页面加载的速度也越慢。还有当页面加载时，图片一个个的零星显示，鼠标经过时候背景闪白等也都是我们不能忍 受的。于是乎将页面中的背景图整合到一起，利用“background- image”，“background- repeat”，“background-position”的组合进行背景定位的技术被广泛使用与了页面构建 中，这就是CSS Sprites。当然CSS Sprites技术也存在着维护不便，内存占用大等等的缺点。</p>
<p>好了，如果我只说这些，那么这篇文章就有点太水了。前面那些只是对CSS Sprites技术的一个普及。作为一个开发者我们应该对它有一个更全面的认识，挖掘深度内容，这样才能有利于我们效率开发，团队协作。</p>
<p><strong>头疼的多人拼图游戏</strong></p>
<p>使用CSS Sprites，就好像玩拼图游戏一样。一张白画布，那么多图怎么放到里面去才会完美？这是个让人纠结的事。而且在实际在工作场景中， 我们面临着项目开发时间紧张，UI设计图要分期提供，多人协同开发一个项目等等问题。这些问题非常容易让我们在大项目中迷失，造成CSS拼图混乱，维护及 其困难的情况。</p>
<p>定好规则，其实拼图也挺好玩的</p>
<p><strong>先期的准备工作</strong></p>
<p>应对一个项目后期维护成本大的问题，我们最好的解决方案就是在开始前制定一系列的规范来限制问题的产品。好的开始是成功的一半。对于 CSS Sprites，在项目开始前，我们要充分认识一个产品，同UI设计师做好良好的沟通，对我们未来组成我们Sprites图的各个元素有个大体的 概念，比如我们的背景拼图可能包括什么。</p>
<p><strong>一个好的Sprite画布是必须的</strong></p>
<p>网页设计里面，Grid系统是必不可少的，好的Grid能解决我们很多排版问题。Grid系统同样适用于CSS Sprites。我们需要创建好一个优秀的画板，剩下的工作就是将元素合理的置于画板中了。</p>
<p>这张是我准备的一张CSS Sprites画布，我们将在这个PSD里面组合项目中的图片。</p>
<p>这张画布是由20px*20px像素的格子组成。这个格子基本上由项目决定的，当我们同UI设计师沟通了解这个项目最多的为16px*16px 图标时。我们就可以采用这种Grid尺寸为画布了。</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Talk-about-the-CSS-Sprites-technique-and-its-optimization1.png" rel="lightbox[19701]" title="谈谈CSS Sprites技术及其优化 "><img class="aligncenter size-full wp-image-19703" title="谈谈CSS Sprites技术及其优化 " src="http://blog.jobbole.com/wp-content/uploads/2012/05/Talk-about-the-CSS-Sprites-technique-and-its-optimization1.png" alt="谈谈CSS Sprites技术及其优化 " width="488" height="262" /></a></p>
<p><strong>Sprites画布有了，接下来就是对图标进行分组了</strong></p>
<p>对于信息的归纳总结、分类是一个有意思的事情。就拿图标来说，我们就可以根据图标功能，尺寸等等作为信息维度进行归纳。其实无论怎么归纳，都是可以的，只是记得我们以一个方向作为标准就可以了。</p>
<p>下图是根据微博站外某组件完成的CSS Sprites</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Talk-about-the-CSS-Sprites-technique-and-its-optimization2.png" rel="lightbox[19701]" title="谈谈CSS Sprites技术及其优化 "><img class="aligncenter size-full wp-image-19704" title="谈谈CSS Sprites技术及其优化 " src="http://blog.jobbole.com/wp-content/uploads/2012/05/Talk-about-the-CSS-Sprites-technique-and-its-optimization2.png" alt="谈谈CSS Sprites技术及其优化 " width="488" height="262" /></a></p>
<p>根据设计，我们了解在这个页面，需要将图片元素根据功能分为4个维度，即微博品牌展示元素、提交按钮、操作类小按钮、提示类ICON。于是我将画布 X轴坐标方向每5个格（其实完全可以10个格或者更多）划分为一个区域，每个这样一个区域的Y轴方向不再划分区域，这样做的目的是为了以后增加图标的扩展 性。于是我们可以非常快速得到一个图标的坐标了。比如不可用的灰色的分享按钮 X坐标=5*20px=100px Y坐 标=7*20px=140px; 那么我们就取得了这个图标的位置即background-position: -100px -140px。如果抽象成 为公式的话，我们设置一个单元格的宽度为变量n。X坐标值Gx,Y坐标值Gy。那么画布中的元素css背景即为：background- position:-Gx*npx –Gy*npx 了。</p>
<p><strong>现在图有了，怎么取图也是关键</strong></p>
<p>因为图片尽可能的被整合到一张拼图，所以我们需要在页面使用图片的位置使用空标签定位的方式将拼图所需展现的部分展示到页面中。</p>
<p>&nbsp;</p>
<pre class="brush: html; gutter: true">&lt;span class=”iconA”&gt;&lt;/span&gt;
.iconA { display:inline-block; height:16px; width:16px; background:url(icons.png) -20px -20px no-repeat }</pre>
<p>&nbsp;</p>
<p><strong>项目出现二期需求了，需要增加图标？</strong></p>
<p>需求总是不能控制，我们要尽可能的为未来增加图片做好打算。在刚才的例子的项目里后期产品需要增加图标，于是：</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Talk-about-the-CSS-Sprites-technique-and-its-optimization3.png" rel="lightbox[19701]" title="谈谈CSS Sprites技术及其优化 "><img class="aligncenter size-full wp-image-19705" title="谈谈CSS Sprites技术及其优化 " src="http://blog.jobbole.com/wp-content/uploads/2012/05/Talk-about-the-CSS-Sprites-technique-and-its-optimization3.png" alt="谈谈CSS Sprites技术及其优化 " width="488" height="262" /></a></p>
<p>我们可以继续在对应的图区内增加对应的图标。但是这个例子同样暴露了一个缺陷，如果新增一个按钮区域大于5n(100px)，我们的图区不足以承 载。这时候我们可以同产品，设计师沟通协调，商议是否可以取消过大的按钮设计。如果需求一定，那我们只能沿着X轴方向继续扩展画布。不过，我们也需要注意 无限的放大一张画布，同样会造成对页面效率的影响。</p>
<p>及时的制定好规范，记录好修改日志</p>
<p>可能在项目的初期，我们还来不及制定合图的具体规范，在项目中我们会遇到各种各样的问题。及时的总结，维护整张CSS拼图，在拼图的PSD或者PNG（使用Fireworks）做好注释，方便他人开发。拼合好的图片提交到svn时也写明log内容，这样便日后查询。</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Talk-about-the-CSS-Sprites-technique-and-its-optimization5.png" rel="lightbox[19701]" title="谈谈CSS Sprites技术及其优化 "><img class="aligncenter size-full wp-image-19702" title="谈谈CSS Sprites技术及其优化 " src="http://blog.jobbole.com/wp-content/uploads/2012/05/Talk-about-the-CSS-Sprites-technique-and-its-optimization5.png" alt="谈谈CSS Sprites技术及其优化 " width="577" height="201" /></a></p>
<p><strong>我们最终的目的</strong></p>
<p>其实CSS Sprites经过了那么多年的演变，前端开发者不断的优化，都是为了提升页面效率，提升团队开发效率，减少开发维护成本而努力。配合 最近非常流行的将CSS动态语言化（如SASS LESS等），增加入变量， 继承， 运算， 函数等。CSS Sprites会变的更好玩，会减少更多 的开发维护成本。甚至我们在“面向对象”的模块开发方式中，还可以使用一个类的的同一个backgroud-position：（x y）值，在不同的页 面通过引用不同的图片（background属性）实现将一个页面内图片请求量进一步减少的目的。随着高级浏览器的普及我们还可以多使用CSS3属性，减 少渐变背景图的使用，将纯色ICON制作成字体取代拼图等我们能更大程度上减少图片的使用量。这篇文章只是抛砖引玉。实际上还有很多关于 CSS Sprites的方法，还有众多的拼图生成工具。</p>
<p>说了那么多，我们如果在日常的开发中，只要我们多注意总结，敢于创新，敢于制定规范，那么再小的事也能干的很漂亮，对于CSS Sprites的优化就是这么一个例子，你说不是么？</p>
<h2  class="related_post_title">相关文章</h2><ul class="related_post"><li><a target="_blank" href="http://blog.jobbole.com/14681/" title="前端是否应该将CSS和JS分开设置两个不同岗位">前端是否应该将CSS和JS分开设置两个不同岗位</a></li><li><a target="_blank" href="http://blog.jobbole.com/8966/" title="编写出色CSS代码的13个建议">编写出色CSS代码的13个建议</a></li><li><a target="_blank" href="http://blog.jobbole.com/8350/" title="CSS模块化编码让开发事半功倍 ">CSS模块化编码让开发事半功倍 </a></li><li><a target="_blank" href="http://blog.jobbole.com/19714/" title="Zen Coding: 一种快速编写HTML/CSS代码的方法 ">Zen Coding: 一种快速编写HTML/CSS代码的方法 </a></li><li><a target="_blank" href="http://blog.jobbole.com/19321/" title="HTML5+CSS3+jQuery制作视频播放器完全指南">HTML5+CSS3+jQuery制作视频播放器完全指南</a></li><li><a target="_blank" href="http://blog.jobbole.com/19262/" title="浅谈PHP代码设计结构">浅谈PHP代码设计结构</a></li><li><a target="_blank" href="http://blog.jobbole.com/19203/" title="网易邮箱前端Javascript编码规范：类规范">网易邮箱前端Javascript编码规范：类规范</a></li><li><a target="_blank" href="http://blog.jobbole.com/19197/" title="网易邮箱前端Javascript编码规范：基础规范">网易邮箱前端Javascript编码规范：基础规范</a></li><li><a target="_blank" href="http://blog.jobbole.com/18758/" title="前端工程师的编码遭遇战">前端工程师的编码遭遇战</a></li><li><a target="_blank" href="http://blog.jobbole.com/16668/" title="Codecademy为编程初学者新增HTML和CSS两门课程">Codecademy为编程初学者新增HTML和CSS两门课程</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.jobbole.com/19701/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>谈谈对程序员的培养</title>
		<link>http://blog.jobbole.com/19697/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25e8%25b0%2588%25e8%25b0%2588%25e5%25af%25b9%25e7%25a8%258b%25e5%25ba%258f%25e5%2591%2598%25e7%259a%2584%25e5%259f%25b9%25e5%2585%25bb</link>
		<comments>http://blog.jobbole.com/19697/#comments</comments>
		<pubDate>Thu, 17 May 2012 00:19:35 +0000</pubDate>
		<dc:creator>齐哲</dc:creator>
				<category><![CDATA[程序员]]></category>
		<category><![CDATA[职场]]></category>

		<guid isPermaLink="false">http://blog.jobbole.com/?p=19697</guid>
		<description><![CDATA[这篇文字是我好久以来的想法，有一些感悟，有一些激烈的言辞，我很自豪我就是一名程序员，我希望给程序员或者前程序员们带来一点启发。也许你认可我的言辞，也许你不屑我的观点，无论如何，欢迎谈谈你的看法。

<strong>让程序员做更多种类的事<!--more--></strong>

为什么有人说小公司锻炼人？在小公司，条件并不那么齐备，很多事情都需要程序员自己做，自己去澄清需求、自己做设计、自己搭建环境、自己测试，甚至自己上线、自己维护（这件事情在我们团队被称为“自己吃自己狗食”）。

然而到了某些公司，在一些正规的流程下，“人”反而显得不那么重要了：一个完、整的流程被切分成若干环节，程序员只能负责那小小的一环，更严重的是，他们显示出消极和片面的情绪，他们称自己码农，自嘲并且觉得在总做一些低级和毫无技术含量的事情。

关于“码农”——这似乎是一件很悲哀的事情，在美国，程序员是一个相当值得尊敬的行业，<a href="http://www.phperz.com/php-news/b/1/20120118692.html" target="_blank">去年硅谷的技术员工年薪平均已经超过10万美元</a>；在中国，教师的行业起码获得了人们口头上的尊敬（虽然实质上也许并没有获得应有的待遇），而程序员，往往只能看到自己给自己呐喊。

这里没有绝对的对错之分，但我一直在博客中强调软件开发实质是一种创造性的劳动，只是在一个流程严格控制的公司内，这样的创造的火花可能被扼杀，换来的好处是人员的流动中，代价最小化：谁都可以走、谁都可以代替谁，所有问题都被认为只是时间问题……那么，程序员，你的自我价值何在呢？

<strong>关于测试</strong>

我听到很多真实的声音，都在抱怨测试工作乏味、加班辛苦。我认为，国内大部分的测试，其实完全是程序员扭曲的工作形态导致的。

专职的测试人员去做专项测试、整个系统的集成测试等等，我都能理解，但是绝对不应当深入模块内部去测试开发人员的代码，绝对不应该去考虑所谓的代码覆盖率——因为这些，比如白盒测试，本都是程序员自己该完成的事情。程序员自己开发的程序，当然要自己验证功能，很多软件公司在一些项目流程里就是没有专职测试介入测试执行，原因很简单，难道自己拉了稀，让别人给你擦屁股？

另一方面，测试该掌握哪些技能？

我见过许多测试人员，他们抱怨工作总是被轻视，没有说话的分量，但是每天的工作就是了解开发的流程，根据流程完成用例的编写，然后执行那些用例，发现bug并填写bug report。如果一名测试只需要做这些事情，那么确实太没有技术含量了、太没有入门门槛了，太单调乏味了。

测试需要成长，既为自己考虑，也为团队中的程序员考虑。

做一名优秀的测试，除了要有分析能力、辨识能力等等软实力以外，基础技能如通信协议、脚本、编译原理、操作系统等等，亦视情况掌握，只有这样，才能和程序员从并不清晰的需求开始，一起去分析、设计、实现和质量保证、去和上上下下的环节做沟通、论证。微软的测试（SDET）都把算法和编码视为基础要求，敢问国内一些公司的测试人员，有几个敢这么说？

<strong>让程序员远离浮躁</strong>

去看看国内几家知名博客和论坛，多少浮躁的博文和帖子四处乱飞？多少人在骂公司狗血，在自嘲薪水，甚至在人身攻击？

浮躁的心态可能是造成这种现象的罪魁祸首，有一位同事说得好，很多具体的技术都可以学，但是执着的心和对技术的热爱是不容易学得的。

整个社会都在日益浮躁，ITEye本来也是一个有技术深度、氛围浓厚的网站，现在看起来有些鱼龙混杂；微博的流行正验证了社会浮躁的趋势，很多人没有时间和耐心去写完整的文章，但是两三句感慨、甚至一词半句的惊叹却容易得多；程序员像寻找速配男女一样，在这个概念翻飞的时代，茫然地寻找自己应该进入的领域，应该了解的技术，于是，很容易看到许多所谓的架构师和咨询师可以把这些东西讲得海阔天空、天花乱坠，这个概念、那个素语，但是——给他一个具体问题吧，要他写写实际代码吧，你会要了他的命。

<strong>给程序员一点宽松和鼓励</strong>

都在说国内的IT环境不如欧美，大量劳动力的富余让人力成本变得无比廉价，能<a href="http://www.douban.com/group/topic/23278439/" target="_blank">让青年付出卖肾代价</a>以购买大部分配件都“Made In China”的iPhone，<a href="http://tech.ifeng.com/telecom/detail_2011_12/01/11035727_0.shtml" target="_blank">中国却只获得了1.8%的利润</a>，这些都让人感叹，为什么中国做不出苹果系列这样的产品？为什么中国始终要给别人套上“廉价劳动力”的帽子？中国的程序员，你们的创造力呢？你们精彩的点子呢？

好吧，我听到有人在说是教育体制的问题。<a href="http://www.goodbuzz.org/blog/conversation/programmers-high-social-status/" target="_blank">对于程序员的地位的思考有很多</a>，可惜我们不是教育工作者，我们也没有那么大的影响力，不过，在团队中间，我们应当多给予这些脆弱的程序员们一点鼓励，让他们表达出自己的想法，特别是在设计上、实现上的想法，不要嘲笑任何人弱智，不要咒骂评审的代码狗屁，多一点沟通，把眼光放长远一些。

这些能表达出想法的人起码可以证明两点：有思考、有勇气，仅这两点，仅足以让旁观的人鼓掌。

一名优秀的Team Leader，不应该整天陶醉在跟踪项目进度和获取程序员工作反馈上。我们都明白，所谓一张一弛，在工作压力恰当的时候，是最适宜工作的，程序员的工作本来就需要创造性，没有适度宽松的环境，就没有思维的火花。

让程序员自己去布置工作台，给他们创造机会聊聊天，把各个团队、各个角色放到一起说说话，组织分享一些有趣的话题，做一些有意思的研究（最初程序员都很腼腆，得劳烦您多牵线搭桥了），Team Leader的工作，绝不仅仅是说“行”或“不行”。

<strong>程序员的理想</strong>

1983年，乔布斯对百事可乐的CEO John Sculley说：“Do you want to sell sugar water for the rest of your life, or do you want to change the world?”（<a href="http://www.edibleapple.com/2010/11/21/the-story-behind-steve-jobs-1985-resignation-from-apple/" target="_blank">你想卖一辈子糖水，还是改变世界？</a>）就这样，一段传奇的合作开始了。

我们已经不在战火纷飞的年代，有多少程序员还愿意怀抱那些原始的理想，还能说出“做互联网的弄潮儿”、“用技术改变世界”这样的话来？

这个世界执着的人并不多，用这样的理念去吸引程序员的公司，则更少。

<strong>关于技术</strong>

我始终觉得，做软件的公司是需要依赖于技术的，当然国内可以称得上是“技术公司”的并不多，但是，优秀的技术能让程序员脱颖而出，也作为一种谋生的手段，为其觅得不错的回报。

做技术能不能一直有饭吃？我想答案是肯定的，有许多公司声称技术路线可以一直有发展的可行性，但是技术牛人还是转了管理或者一走了之，有一种粗暴但是易行的鉴别技术公司的办法，就是寻找里面又没有40岁，甚至50岁以上还在做实际设计和编码的人（不是那些脱离了具体实现向客户吹嘘的角色）。

世界上有两种最赚钱的人，一种是真正的生产者，他们用自己独一无二的聪慧、灵感和劳动创造了价值；一种是极其老道的投机者，专门从别人口袋里把钱掏出来放到自己口袋里。他们都受人尊敬、受人瞩目，后一种让自己的生活变得更美好，但是前一种，让整个世界更美好。

如果你不能在技术的道路上坚决地走下去，在大部分公司做市场、做管理、做咨询，顺便鄙视一下别的辛苦工作的程序员，那么也可以混得很好——毕竟，生活的解总是有很多种。]]></description>
			<content:encoded><![CDATA[<p>这篇文字是我好久以来的想法，有一些感悟，有一些激烈的言辞，我很自豪我就是一名<span class='wp_keywordlink'><a href="http://blog.jobbole.com/821/" title="程序员的本质">程序员</a></span>，我希望给程序员或者前程序员们带来一点启发。也许你认可我的言辞，也许你不屑我的观点，无论如何，欢迎谈谈你的看法。</p>
<p><strong>让程序员做更多种类的事<span id="more-19697"></span></strong></p>
<p>为什么有人说小公司锻炼人？在小公司，条件并不那么齐备，很多事情都需要程序员自己做，自己去澄清需求、自己做设计、自己搭建环境、自己测试，甚至自己上线、自己维护（这件事情在我们团队被称为“自己吃自己狗食”）。</p>
<p>然而到了某些公司，在一些正规的流程下，“人”反而显得不那么重要了：一个完、整的流程被切分成若干环节，程序员只能负责那小小的一环，更严重的是，他们显示出消极和片面的情绪，他们称自己码农，自嘲并且觉得在总做一些低级和毫无技术含量的事情。</p>
<p>关于“码农”——这似乎是一件很悲哀的事情，在美国，程序员是一个相当值得尊敬的行业，<a href="http://www.phperz.com/php-news/b/1/20120118692.html" target="_blank">去年硅谷的技术员工年薪平均已经超过10万美元</a>；在中国，教师的行业起码获得了人们口头上的尊敬（虽然实质上也许并没有获得应有的待遇），而程序员，往往只能看到自己给自己呐喊。</p>
<p>这里没有绝对的对错之分，但我一直在博客中强调软件开发实质是一种创造性的劳动，只是在一个流程严格控制的公司内，这样的创造的火花可能被扼杀，换来的好处是人员的流动中，代价最小化：谁都可以走、谁都可以代替谁，所有问题都被认为只是时间问题……那么，程序员，你的自我价值何在呢？</p>
<p><strong>关于测试</strong></p>
<p>我听到很多真实的声音，都在抱怨测试工作乏味、加班辛苦。我认为，国内大部分的测试，其实完全是程序员扭曲的工作形态导致的。</p>
<p>专职的测试人员去做专项测试、整个系统的集成测试等等，我都能理解，但是绝对不应当深入模块内部去测试开发人员的代码，绝对不应该去考虑所谓的代码覆盖率——因为这些，比如白盒测试，本都是程序员自己该完成的事情。程序员自己开发的程序，当然要自己验证功能，很多软件公司在一些项目流程里就是没有专职测试介入测试执行，原因很简单，难道自己拉了稀，让别人给你擦屁股？</p>
<p>另一方面，测试该掌握哪些技能？</p>
<p>我见过许多测试人员，他们抱怨工作总是被轻视，没有说话的分量，但是每天的工作就是了解开发的流程，根据流程完成用例的编写，然后执行那些用例，发现bug并填写bug report。如果一名测试只需要做这些事情，那么确实太没有技术含量了、太没有入门门槛了，太单调乏味了。</p>
<p>测试需要成长，既为自己考虑，也为团队中的程序员考虑。</p>
<p>做一名优秀的测试，除了要有分析能力、辨识能力等等软实力以外，基础技能如通信协议、脚本、<span class='wp_keywordlink'><a href="http://www.amazon.cn/gp/product/B001NGO85I/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=vastwork-23&linkCode=as2&camp=536&creative=3200&creativeASIN=B001NGO85I" title="编译原理" rel="nofollow" target="_blank">编译原理</a></span>、操作系统等等，亦视情况掌握，只有这样，才能和程序员从并不清晰的需求开始，一起去分析、设计、实现和质量保证、去和上上下下的环节做沟通、论证。微软的测试（SDET）都把算法和编码视为基础要求，敢问国内一些公司的测试人员，有几个敢这么说？</p>
<p><strong>让程序员远离浮躁</strong></p>
<p>去看看国内几家知名博客和论坛，多少浮躁的博文和帖子四处乱飞？多少人在骂公司狗血，在自嘲薪水，甚至在人身攻击？</p>
<p>浮躁的心态可能是造成这种现象的罪魁祸首，有一位同事说得好，很多具体的技术都可以学，但是执着的心和对技术的热爱是不容易学得的。</p>
<p>整个社会都在日益浮躁，ITEye本来也是一个有技术深度、氛围浓厚的网站，现在看起来有些鱼龙混杂；微博的流行正验证了社会浮躁的趋势，很多人没有时间和耐心去写完整的文章，但是两三句感慨、甚至一词半句的惊叹却容易得多；程序员像寻找速配男女一样，在这个概念翻飞的时代，茫然地寻找自己应该进入的领域，应该了解的技术，于是，很容易看到许多所谓的架构师和咨询师可以把这些东西讲得海阔天空、天花乱坠，这个概念、那个素语，但是——给他一个具体问题吧，要他写写实际代码吧，你会要了他的命。</p>
<p><strong>给程序员一点宽松和鼓励</strong></p>
<p>都在说国内的IT环境不如欧美，大量劳动力的富余让人力成本变得无比廉价，能<a href="http://www.douban.com/group/topic/23278439/" target="_blank">让青年付出卖肾代价</a>以购买大部分配件都“Made In China”的iPhone，<a href="http://tech.ifeng.com/telecom/detail_2011_12/01/11035727_0.shtml" target="_blank">中国却只获得了1.8%的利润</a>，这些都让人感叹，为什么中国做不出苹果系列这样的产品？为什么中国始终要给别人套上“廉价劳动力”的帽子？中国的程序员，你们的创造力呢？你们精彩的点子呢？</p>
<p>好吧，我听到有人在说是教育体制的问题。<a href="http://www.goodbuzz.org/blog/conversation/programmers-high-social-status/" target="_blank">对于程序员的地位的思考有很多</a>，可惜我们不是教育工作者，我们也没有那么大的<span class='wp_keywordlink'><a href="http://www.amazon.cn/gp/product/B0044KME2E/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=vastwork-23&linkCode=as2&camp=536&creative=3200&creativeASIN=B0044KME2E" title="影响力" rel="nofollow" target="_blank">影响力</a></span>，不过，在团队中间，我们应当多给予这些脆弱的程序员们一点鼓励，让他们表达出自己的想法，特别是在设计上、实现上的想法，不要嘲笑任何人弱智，不要咒骂评审的代码狗屁，多一点沟通，把眼光放长远一些。</p>
<p>这些能表达出想法的人起码可以证明两点：有思考、有勇气，仅这两点，仅足以让旁观的人鼓掌。</p>
<p>一名优秀的Team Leader，不应该整天陶醉在跟踪项目进度和获取程序员工作反馈上。我们都明白，所谓一张一弛，在工作压力恰当的时候，是最适宜工作的，程序员的工作本来就需要创造性，没有适度宽松的环境，就没有思维的火花。</p>
<p>让程序员自己去布置工作台，给他们创造机会聊聊天，把各个团队、各个角色放到一起说说话，组织分享一些有趣的话题，做一些有意思的研究（最初程序员都很腼腆，得劳烦您多牵线搭桥了），Team Leader的工作，绝不仅仅是说“行”或“不行”。</p>
<p><strong>程序员的理想</strong></p>
<p>1983年，<span class='wp_keywordlink'><a href="http://blog.jobbole.com/191/" title="史蒂文·乔布斯的青春岁月">乔布斯</a></span>对百事可乐的CEO John Sculley说：“Do you want to sell sugar water for the rest of your life, or do you want to change the world?”（<a href="http://www.edibleapple.com/2010/11/21/the-story-behind-steve-jobs-1985-resignation-from-apple/" target="_blank">你想卖一辈子糖水，还是改变世界？</a>）就这样，一段传奇的合作开始了。</p>
<p>我们已经不在战火纷飞的年代，有多少程序员还愿意怀抱那些原始的理想，还能说出“做互联网的弄潮儿”、“用技术改变世界”这样的话来？</p>
<p>这个世界执着的人并不多，用这样的理念去吸引程序员的公司，则更少。</p>
<p><strong>关于技术</strong></p>
<p>我始终觉得，做软件的公司是需要依赖于技术的，当然国内可以称得上是“技术公司”的并不多，但是，优秀的技术能让程序员脱颖而出，也作为一种谋生的手段，为其觅得不错的回报。</p>
<p>做技术能不能一直有饭吃？我想答案是肯定的，有许多公司声称技术路线可以一直有发展的可行性，但是技术牛人还是转了管理或者一走了之，有一种粗暴但是易行的鉴别技术公司的办法，就是寻找里面又没有40岁，甚至50岁以上还在做实际设计和编码的人（不是那些脱离了具体实现向客户吹嘘的角色）。</p>
<p>世界上有两种最赚钱的人，一种是真正的生产者，他们用自己独一无二的聪慧、灵感和劳动创造了价值；一种是极其老道的投机者，专门从别人口袋里把钱掏出来放到自己口袋里。他们都受人尊敬、受人瞩目，后一种让自己的生活变得更美好，但是前一种，让整个世界更美好。</p>
<p>如果你不能在技术的道路上坚决地走下去，在大部分公司做市场、做管理、做咨询，顺便鄙视一下别的辛苦工作的程序员，那么也可以混得很好——毕竟，生活的解总是有很多种。</p>
<h2  class="related_post_title">相关文章</h2><ul class="related_post"><li><a target="_blank" href="http://blog.jobbole.com/15688/" title="程序员真的很懒">程序员真的很懒</a></li><li><a target="_blank" href="http://blog.jobbole.com/14486/" title="工作满意度评估程序员版">工作满意度评估程序员版</a></li><li><a target="_blank" href="http://blog.jobbole.com/13264/" title="朱云翔：程序员不要做沙和尚 ">朱云翔：程序员不要做沙和尚 </a></li><li><a target="_blank" href="http://blog.jobbole.com/11592/" title="2012最受企业欢迎的开发技能Top10">2012最受企业欢迎的开发技能Top10</a></li><li><a target="_blank" href="http://blog.jobbole.com/10624/" title="年终工作总结：给新手程序员的几个建议">年终工作总结：给新手程序员的几个建议</a></li><li><a target="_blank" href="http://blog.jobbole.com/8170/" title="程序员都应该挖一口属于自己的井">程序员都应该挖一口属于自己的井</a></li><li><a target="_blank" href="http://blog.jobbole.com/19416/" title="5种迹象显示你应该当场聘用程序员">5种迹象显示你应该当场聘用程序员</a></li><li><a target="_blank" href="http://blog.jobbole.com/19227/" title="计算机科学不等于数学">计算机科学不等于数学</a></li><li><a target="_blank" href="http://blog.jobbole.com/19188/" title="我猜我不是 “501” 程序员 ">我猜我不是 “501” 程序员 </a></li><li><a target="_blank" href="http://blog.jobbole.com/19124/" title="想招优秀的程序员，给他们付足够的钱吧！">想招优秀的程序员，给他们付足够的钱吧！</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.jobbole.com/19697/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>测试转开发，一个女孩子短短的工作心得</title>
		<link>http://blog.jobbole.com/19692/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25e6%25b5%258b%25e8%25af%2595%25e8%25bd%25ac%25e5%25bc%2580%25e5%258f%2591%25ef%25bc%258c%25e4%25b8%2580%25e4%25b8%25aa%25e5%25a5%25b3%25e5%25ad%25a9%25e5%25ad%2590%25e7%259f%25ad%25e7%259f%25ad%25e7%259a%2584%25e5%25b7%25a5%25e4%25bd%259c%25e5%25bf%2583%25e5%25be%2597</link>
		<comments>http://blog.jobbole.com/19692/#comments</comments>
		<pubDate>Thu, 17 May 2012 00:11:09 +0000</pubDate>
		<dc:creator>齐哲</dc:creator>
				<category><![CDATA[程序员]]></category>
		<category><![CDATA[女程序员]]></category>
		<category><![CDATA[测试]]></category>
		<category><![CDATA[测试人员]]></category>

		<guid isPermaLink="false">http://blog.jobbole.com/?p=19692</guid>
		<description><![CDATA[在讲述我的经历之前，我先分享下工作不到2年时间得到的几个重要的结论：

一、坚持梦想没有理由

二、世界不断在变化，该行动就要行动

三、人需要通过一些事情不断证明自己

下面就开始讲述我短短的工作心得吧~<!--more-->

<strong> 一、在XF的测试之路</strong>

2010年大学毕业，非计算机专业，大学期间本来打算好好自学编程以后做个程序员，但因为懒惰以及恋爱，没什么时间学习，只能退而求其次，找门槛低点的，就通过校招找了一份软件测试的工作。

2010年四月进入XF（我的第一家公司）实习，实习期间我的表现并不好，什么工作流程都不懂，每天把手头工作完成下班到点走人当时我认为是理所当然的事情，却惹的那个项目组的人都对我有意见，然后实习了一个月我就结束了实习，回学校逍遥自在到毕业。

2010年七月毕业后进入XF做软件测试，入职后进行了为期一个月的培训，30号新入职测试员工一周六天从早上9点到晚上9点在科大南区的培训，培训老师（其实就是测试部门的同事）装13的苛刻教学方式，以及租房子等等事情，一下子让刚出校园的我压力大的透不过气来。依稀记得那年夏天出奇的热，租的房子在顶楼，天晴晚上睡觉热死，下雨墙体漏水停电，人累的跟鬼一样，学到的都是一些没有意义的形式主义的东西。结束一个月的培训后进入项目组，项目组还是以前实习的项目组，可是3天后我就得知我被调出项目组。我知道这个项目在事业部属于核心型项目，在这个项目组的人基本都很自傲，我觉得当时我的自尊心被严重的打击了，我很好强，培训期间我的表现并不差，数一数二，大概还是因为实习期间的表现吧，人家不愿意要我了。

其实一切都是因缘际会，因为被一个组抛弃，而进入另一个组，再到后来得到大家的肯定，拿到年终优秀新员工，结交了一群一生的朋友，只要自己努力了，自然大家都看得见。

2011年三四月的时候，来了一个实习生华仔，领导分配我作为他的指导人。华仔很亲切的一口一个小师父的喊着，他不算是一个聪明的孩子，但他却有着别人没有的执着与努力，他的进步很快，同时也分担了我的很大一部分工作，这时候我开始思考我的人生。。

我热切的渴望做技术，而现在我做的测试是什么，无非是重复的执行一些用例，甚至是不断的点点页面，写写测试短信，我需要找回自己，我需要学习，需要改变。

因为项目组用的是C#，我开始学习C#，其实很多事情都是贵在坚持，很幸运的是我坚持下来了。我开始写一些测试工具帮助自己在测试工作中进行自动化，不断的优化自己的代码，不断的积累。

花花是我们项目组的PM，后来搬家我和她住到了一起，我们相处的很好，我也愿意和她说我的事情，某次交流中我说我以后想转开发，她说我更适合做产品经理，说哪有傻瓜愿意从测试转开发哦，人家都说嫌开发累转测试。

后来我思考了很久，我还是坚持我的梦想，一生总要一次跟着自己走，傻也好，笨也好，否则多遗憾啊~

后面的日子我闷着头不断的学习，不断的做一些小的东西并应用于工作上。

&#160;

<strong>二、离职</strong>

2012年2月14日，我办完了离职手续，走出公司大楼，站在等候公交的站台，仰头看着21层的楼，我有太多感慨。

我要感谢这家公司，让我在毕业找工作的彷徨季给了我一个机会，让我结交了一群好友，让我在找下一份工作给了我一个很重要的筹码。。。

&#160;
<p style="text-align: center;"> <a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Test-switch-to-development-a-girl-a-short-period-of-work-experience.jpg"><img class="aligncenter size-full wp-image-19693" title="测试转开发，一个女孩子短短的工作心得" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Test-switch-to-development-a-girl-a-short-period-of-work-experience.jpg" alt="测试转开发，一个女孩子短短的工作心得" width="618" height="819" /></a></p>
&#160;

&#160;

<strong>三、求职</strong>

离职后第一趟去上海2天面试了2家公司，一家是测试的一家是测试开发，两家都是外包公司。

第一家公司面试很简单，因为我有测试基础又有开发基础，很容易就通过，当天就给了offer，工资也是按期望薪资给的；第二家公司笔试面试稍微偏技术点，但也不难，后来通知也拿下来了，但工资砍了价，后来谈了几次涨了一些，基本就打算入职。

后来又面了一家公司TD打电话给我，招软件工程师，也是做voice方面的，和我第一家公司是竞争对手。笔试面试都不涉及技术，全是智力题，我感觉我做的蛮好的，笔试面试后一周才通知。几经周折我选择了TD。

<strong>四、在TD的两个月</strong>

TD是一家台资公司的研发中心，在网上看评价说这家公司工作环境是难得的那种较单纯的。入职后发现voice部门在台湾，内地这边加上我才招了2个人，另一个是男孩子比我大2岁。

进入公司后前半个月时间，基本没事情，就做点杂事，自己学习也没人管。后来台湾那边的主管过来出差陆续也见过几个领导，人都蛮好的。大致了解到这边用的是java，可是我并没有做过java，人家说没关系，边做边学。

后来开始做项目，因为我没有java开发的基础，分配给我的是报表开发。

我开始学习iReport，不断钻研做到最好，两周后台湾那边的PM来到这边，Elina，三十多岁的女人，未婚，我们很谈得来，有很多共同的语言，我也很庆幸在哪里都能交到一些知心朋友。

现在我开始往web开发方向发展，人们总说笨鸟先飞，既然我已经后飞了，就要花费多一些的努力和辛勤去跟上。

<strong>后记：</strong>

有人说我傻，说我脑子有问题，好好的跑来做什么开发，我想说的是：每个人的信念不同，何必在乎别人的看法。

另外现在拿着比以前翻了一番的工资的时候，想想家里的父母，又想到微博上流传的一句话“我们之所以努力赚钱，是为了让父母为自己买东西时能像给我们买东西时一样大方”，这也是一种安慰吧。

妈妈我爱你！母亲节快乐！]]></description>
			<content:encoded><![CDATA[<p>在讲述我的经历之前，我先分享下工作不到2年时间得到的几个重要的结论：</p>
<p>一、坚持梦想没有理由</p>
<p>二、世界不断在变化，该行动就要行动</p>
<p>三、人需要通过一些事情不断证明自己</p>
<p>下面就开始讲述我短短的工作心得吧~<span id="more-19692"></span></p>
<p><strong> 一、在XF的测试之路</strong></p>
<p>2010年大学毕业，非计算机专业，大学期间本来打算好好自学编程以后做个<span class='wp_keywordlink'><a href="http://blog.jobbole.com/821/" title="程序员的本质">程序员</a></span>，但因为懒惰以及恋爱，没什么时间学习，只能退而求其次，找门槛低点的，就通过校招找了一份软件测试的工作。</p>
<p>2010年四月进入XF（我的第一家公司）实习，实习期间我的表现并不好，什么工作流程都不懂，每天把手头工作完成下班到点走人当时我认为是理所当然的事情，却惹的那个项目组的人都对我有意见，然后实习了一个月我就结束了实习，回学校逍遥自在到毕业。</p>
<p>2010年七月毕业后进入XF做软件测试，入职后进行了为期一个月的培训，30号新入职测试员工一周六天从早上9点到晚上9点在科大南区的培训，培训老师（其实就是测试部门的同事）装13的苛刻教学方式，以及租房子等等事情，一下子让刚出校园的我压力大的透不过气来。依稀记得那年夏天出奇的热，租的房子在顶楼，天晴晚上睡觉热死，下雨墙体漏水停电，人累的跟鬼一样，学到的都是一些没有意义的形式主义的东西。结束一个月的培训后进入项目组，项目组还是以前实习的项目组，可是3天后我就得知我被调出项目组。我知道这个项目在事业部属于核心型项目，在这个项目组的人基本都很自傲，我觉得当时我的自尊心被严重的打击了，我很好强，培训期间我的表现并不差，数一数二，大概还是因为实习期间的表现吧，人家不愿意要我了。</p>
<p>其实一切都是因缘际会，因为被一个组抛弃，而进入另一个组，再到后来得到大家的肯定，拿到年终优秀新员工，结交了一群一生的朋友，只要自己努力了，自然大家都看得见。</p>
<p>2011年三四月的时候，来了一个实习生华仔，领导分配我作为他的指导人。华仔很亲切的一口一个小师父的喊着，他不算是一个聪明的孩子，但他却有着别人没有的执着与努力，他的进步很快，同时也分担了我的很大一部分工作，这时候我开始思考我的人生。。</p>
<p>我热切的渴望做技术，而现在我做的测试是什么，无非是重复的执行一些用例，甚至是不断的点点页面，写写测试短信，我需要找回自己，我需要学习，需要改变。</p>
<p>因为项目组用的是C#，我开始学习C#，其实很多事情都是贵在坚持，很幸运的是我坚持下来了。我开始写一些测试工具帮助自己在测试工作中进行自动化，不断的优化自己的代码，不断的积累。</p>
<p>花花是我们项目组的PM，后来搬家我和她住到了一起，我们相处的很好，我也愿意和她说我的事情，某次交流中我说我以后想转开发，她说我更适合做产品经理，说哪有傻瓜愿意从测试转开发哦，人家都说嫌开发累转测试。</p>
<p>后来我思考了很久，我还是坚持我的梦想，一生总要一次跟着自己走，傻也好，笨也好，否则多遗憾啊~</p>
<p>后面的日子我闷着头不断的学习，不断的做一些小的东西并应用于工作上。</p>
<p>&nbsp;</p>
<p><strong>二、离职</strong></p>
<p>2012年2月14日，我办完了离职手续，走出公司大楼，站在等候公交的站台，仰头看着21层的楼，我有太多感慨。</p>
<p>我要感谢这家公司，让我在毕业找工作的彷徨季给了我一个机会，让我结交了一群好友，让我在找下一份工作给了我一个很重要的筹码。。。</p>
<p>&nbsp;</p>
<p style="text-align: center;"> <a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Test-switch-to-development-a-girl-a-short-period-of-work-experience.jpg" rel="lightbox[19692]" title="测试转开发，一个女孩子短短的工作心得"><img class="aligncenter size-full wp-image-19693" title="测试转开发，一个女孩子短短的工作心得" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Test-switch-to-development-a-girl-a-short-period-of-work-experience.jpg" alt="测试转开发，一个女孩子短短的工作心得" width="618" height="819" /></a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><strong>三、求职</strong></p>
<p>离职后第一趟去上海2天面试了2家公司，一家是测试的一家是测试开发，两家都是外包公司。</p>
<p>第一家公司面试很简单，因为我有测试基础又有开发基础，很容易就通过，当天就给了offer，工资也是按期望薪资给的；第二家公司笔试面试稍微偏技术点，但也不难，后来通知也拿下来了，但工资砍了价，后来谈了几次涨了一些，基本就打算入职。</p>
<p>后来又面了一家公司TD打电话给我，招<span class='wp_keywordlink'><a href="http://blog.jobbole.com/344/" title="明星软件工程师的10种特质">软件工程师</a></span>，也是做voice方面的，和我第一家公司是竞争对手。笔试面试都不涉及技术，全是智力题，我感觉我做的蛮好的，笔试面试后一周才通知。几经周折我选择了TD。</p>
<p><strong>四、在TD的两个月</strong></p>
<p>TD是一家台资公司的研发中心，在网上看评价说这家公司工作环境是难得的那种较单纯的。入职后发现voice部门在台湾，内地这边加上我才招了2个人，另一个是男孩子比我大2岁。</p>
<p>进入公司后前半个月时间，基本没事情，就做点杂事，自己学习也没人管。后来台湾那边的主管过来出差陆续也见过几个领导，人都蛮好的。大致了解到这边用的是java，可是我并没有做过java，人家说没关系，边做边学。</p>
<p>后来开始做项目，因为我没有java开发的基础，分配给我的是报表开发。</p>
<p>我开始学习iReport，不断钻研做到最好，两周后台湾那边的PM来到这边，Elina，三十多岁的女人，未婚，我们很谈得来，有很多共同的语言，我也很庆幸在哪里都能交到一些知心朋友。</p>
<p>现在我开始往web开发方向发展，人们总说笨鸟先飞，既然我已经后飞了，就要花费多一些的努力和辛勤去跟上。</p>
<p><strong>后记：</strong></p>
<p>有人说我傻，说我脑子有问题，好好的跑来做什么开发，我想说的是：每个人的信念不同，何必在乎别人的看法。</p>
<p>另外现在拿着比以前翻了一番的工资的时候，想想家里的父母，又想到微博上流传的一句话“我们之所以努力赚钱，是为了让父母为自己买东西时能像给我们买东西时一样大方”，这也是一种安慰吧。</p>
<p>妈妈我爱你！母亲节快乐！</p>
<h2  class="related_post_title">相关文章</h2><ul class="related_post"><li><a target="_blank" href="http://blog.jobbole.com/19048/" title="软件测试转型之路">软件测试转型之路</a></li><li><a target="_blank" href="http://blog.jobbole.com/18954/" title="反测试无用论之四：不做庸俗测试人员">反测试无用论之四：不做庸俗测试人员</a></li><li><a target="_blank" href="http://blog.jobbole.com/18104/" title="进入测试行业的六年感悟">进入测试行业的六年感悟</a></li><li><a target="_blank" href="http://blog.jobbole.com/17722/" title="反测试无用论之三：牛逼公司的模式就一定对吗？">反测试无用论之三：牛逼公司的模式就一定对吗？</a></li><li><a target="_blank" href="http://blog.jobbole.com/17714/" title="反测试无用论之二：帮你接盘子的人">反测试无用论之二：帮你接盘子的人</a></li><li><a target="_blank" href="http://blog.jobbole.com/17615/" title="陈晔：致所有测试人员的信">陈晔：致所有测试人员的信</a></li><li><a target="_blank" href="http://blog.jobbole.com/14736/" title="测试人员是…">测试人员是…</a></li><li><a target="_blank" href="http://blog.jobbole.com/18749/" title="开发人员与测试人员的划分">开发人员与测试人员的划分</a></li><li><a target="_blank" href="http://blog.jobbole.com/16907/" title="为何本地化测试如此重要">为何本地化测试如此重要</a></li><li><a target="_blank" href="http://blog.jobbole.com/18542/" title="软件质量控制实践――Microsoft 篇 (1)">软件质量控制实践――Microsoft 篇 (1)</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.jobbole.com/19692/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Michael Abrash：我是如何加入Valve公司的</title>
		<link>http://blog.jobbole.com/19390/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=michael-abrash%25ef%25bc%259a%25e6%2588%2591%25e6%2598%25af%25e5%25a6%2582%25e4%25bd%2595%25e5%258a%25a0%25e5%2585%25a5valve%25e5%2585%25ac%25e5%258f%25b8%25e7%259a%2584</link>
		<comments>http://blog.jobbole.com/19390/#comments</comments>
		<pubDate>Wed, 16 May 2012 19:31:40 +0000</pubDate>
		<dc:creator>黄小非</dc:creator>
				<category><![CDATA[程序员]]></category>
		<category><![CDATA[Michael Abrash]]></category>
		<category><![CDATA[Valve]]></category>
		<category><![CDATA[可穿戴式计算]]></category>
		<category><![CDATA[游戏开发]]></category>
		<category><![CDATA[管理]]></category>

		<guid isPermaLink="false">http://blog.jobbole.com/?p=19390</guid>
		<description><![CDATA[<strong>译注：</strong>本文的作者是Michael Abrash（迈克尔·亚伯拉什），他是计算机图形领域首屈一指的大师！ 他是著名的计算机图形编程书籍《Graphics Programming Black Book》的作者，同时也是一位拥有高超编程技巧的开发者。Michale Abrash的职业经历非常丰富，他所效力过的公司包括微软、Id Software、Intel等，参与过的项目涉及操作系统开发、游戏开发、人工智能项目、处理器设计项目等多个领域，同时他当然也是一位杰出的软件顾问和技术专栏作者。Michael Abrash于2011年加入Valve公司，从事游戏相关的研究项目。本文就是他在加入Valve后，对自己的职业生涯的回顾，以及对自己在Valve公司的工作情况的介绍，同时，此文也是一个为Valve招兵买马的招聘贴！（以下是全文）
<div class="mceTemp mceIEcenter" style="text-align: center;"><dl id="attachment_19400" class="wp-caption aligncenter" style="width: 554px;"><dt class="wp-caption-dt"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Michael-Abrash-Valve-GDC.jpg"><img class="size-full wp-image-19400" title="Michael-Abrash-Valve-GDC" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Michael-Abrash-Valve-GDC.jpg" alt="Michael Abrash" width="544" height="368" /></a></dt><dd class="wp-caption-dd">Michael Abrash</dd></dl></div>
&#160;

一切都是从Snow Crash开始的。

如果我没有了解到Metaverse(虚拟世界)，如果我没有被Metaverse(虚拟世界)的构想深深吸引，如果我没有意识到3D网络化离现实是如此地接近，如果我不够自信能有所作为，更重要的是，如果我不是发自内心地想去做，那我就永远不可能有机会来到Valve工作。

那是1994年，我当时已经为微软工作了几年。那年的某天晚上，我的女儿正在Sammamish Plateau的小教授书店翻看各种书籍，我偶尔就注意到了书架上的一本书：《<a href="http://www.amazon.cn/gp/product/0553380958/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&#38;tag=vastwork-23&#38;linkCode=as2&#38;camp=536&#38;creative=3200&#38;creativeASIN=0553380958" target="_blank">Snow Crash</a>》。我拿起这本书，翻开就读，然后就决定要买下，接下来，只用了一个晚上，我就狼吞虎咽地读完了。看完书以后，我自己开始意识到，书中80%的内容都非常可行，我能在电脑上实现他们！我的心情是如此迫切，对于与做电脑相关的事情，我的急切一如既往。我是个职业科幻迷，这次，我有一个绝佳的机会去自己实现一把科幻！于是，在微软公司，我就着手开始实现一个基于网络的3D引擎项目。
<div class="mceTemp mceIEcenter" style="text-align: center;"><dl id="attachment_19399" class="wp-caption aligncenter" style="width: 296px;"><dt class="wp-caption-dt"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/stephenson_b.jpg"><img class="size-full wp-image-19399" title="stephenson_b" src="http://blog.jobbole.com/wp-content/uploads/2012/05/stephenson_b.jpg" alt="科幻小说《Snow Crash》" width="286" height="432" /></a></dt><dd class="wp-caption-dd">科幻小说《<a href="http://www.amazon.cn/gp/product/0553380958/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&#38;tag=vastwork-23&#38;linkCode=as2&#38;camp=536&#38;creative=3200&#38;creativeASIN=0553380958" target="_blank">Snow Crash</a>》</dd></dl></div>
&#160;

就在我心血来潮的时候，我也开始清醒地认识到，自己绝对不会有机会去启动这么一个项目。John Carmack到西雅图来探望他的母亲，当时他刚刚在Id Software搞出了Doom，我趁此机会约他见面一起吃个饭，就在当地的泰国餐厅。我以前只见过Carmack一次，但是他之前就认识我，是因为他在刚开始学PC编程的时候，在《PC Magazine》上读到过我的文章，几年前，我们还在M&#38;T BBS上有过几回文字交流。上一次我和他见面的时候，他问我是否考虑加入Id Software, 这个邀请让我觉得有点惊讶，因为我当时正在忙于Windows NT的交付工作，况且微软在职工优先认证股权方面的待遇也非常地慷慨，所以我拒绝了他。这一次见面，我知道他还是想邀请我加盟，但是我觉得我还是会拒绝他，因为我目前在微软的根基已经挺牢固了，况且微软目前在股权方面的待遇更加优厚了。出乎意料的是，John Carmack跟我聊了两个多小时，却对邀请我加盟的事情只字未提。他只是谈到了些关于可持续性的Internet游戏服务器，以及玩家自己设计关卡，并在他们自己的服务器上运行，还有就是如何把众多的玩家都聚集起来，让他们在一个共同的虚拟空间共同成长等等事情。我意识到了，他所说的正是Metaverse，虽然没有Neal(科幻小说《<a href="http://www.amazon.cn/gp/product/0553380958/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&#38;tag=vastwork-23&#38;linkCode=as2&#38;camp=536&#38;creative=3200&#38;creativeASIN=0553380958" target="_blank">Snow Crash</a>》的作者——译者著)在书中描写的那么迷人，但是却真实得令人难以置信。有了这个铺垫，当他最后摊牌邀请我加盟的时候，我无法再拒绝了，我不能错过创造未来的机会。
<div class="mceTemp mceIEcenter" style="text-align: center;"><dl id="attachment_19402" class="wp-caption aligncenter" style="width: 360px;"><dt class="wp-caption-dt"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/jcint350.jpg"><img class="size-full wp-image-19402" title="jcint350" src="http://blog.jobbole.com/wp-content/uploads/2012/05/jcint350.jpg" alt="John Carmack, 游戏编程领域的奇才" width="350" height="263" /></a></dt><dd class="wp-caption-dd">John Carmack, 游戏编程领域的奇才</dd></dl></div>
&#160;

与John一起工作，就仿佛是《黑客帝国》里的Neo一样，把一种又一种武术技能灌入大脑。我曾经每天晚上都蹒跚走到Id Software的停车场，对我一天的工作感到震惊和不知所措。我每天都在试图跟上John Carmack的节奏，我们在创建一个全新的编程领域：3D,基于Internet的客户端/服务器多人游戏系统，模组，脚本，所有的这些，都只有我们两个程序员负责完成！当然，思考了这些以后，我还要挤出半小时时间，开车回Plano. 所有的事情都以光速前进，根本没有时间停歇和回味。在我到公司的16个月后，Quake就正式完成并交付发售了。不过这一切都是值得的，不仅仅是因为我在编程方面的突飞猛进，Quake开创了一个时代，它可不是什么“最好的游戏之一”，它是一个突破性的技术（对此，需要说明一下，Carmack是杰出的创新家，也是创新的源动力）。该游戏创建了全新的流派，拥有了自己的社区，并且时至今日仍然非常火爆。举个例子，当我后来在Valve工作的时候，我发现有不少的员工，他们的职业生涯是从给Quake做模组，或者在Quake引擎的基础上开发而开始的。像这些员工一样，我也给我自己创造了未来15年的工作机会。
<div class="mceTemp mceIEcenter" style="text-align: center;"><dl id="attachment_19403" class="wp-caption aligncenter" style="width: 370px;"><dt class="wp-caption-dt"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/600full-quake-cover.jpg"><img class="size-full wp-image-19403 " title="600full-quake-cover" src="http://blog.jobbole.com/wp-content/uploads/2012/05/600full-quake-cover.jpg" alt="轰动一时的第一人称3D在线对战游戏《Quake》" width="360" height="425" /></a></dt><dd class="wp-caption-dd">轰动一时的第一人称3D在线对战游戏《Quake》</dd></dl></div>
&#160;

1996年，Id Software迎来了两位客人，Mike Harrington和Gabe Newell，这两个人刚刚离开微软公司，并创办了一家叫做Valve的游戏公司。他们想购买Quake引擎的源代码，来构建他们自己的第一个游戏。当时，整个Id Software上下没有一个人对源代码授权这种事情感兴趣，甚至大家都懒得理这两个人。鉴于这种尴尬的局面，我出面帮他们搞定了源代码授权的问题。因为我和Mike以及Gabe在微软的时候就互相认识，而且当我刚到微软工作的时候，Mike做了很多他份外的事情来帮助我，因此我才得以在微软生存下来，所以我觉得我现在也应该帮助他们。事实上，源代码授权这件事情后来演变成了双赢的局面，Id Software从授权中赚了很多钱，Valve也在这个源代码的基础上开发了他们的成名作《半条命》（也就是完全不用再多介绍的网络对战游戏《反恐精英》的单机版——译者注），不过，我本人并没有从这件事情中获得经济利益（希望以后会），因为不久之后我就决定从Id Software离职了。我当时的计划是，离职后返回微软工作，不过Mike和Gabe向我伸出了橄榄枝，问我是否愿意加盟Valve，成为第三联合创始人。经过很长时间的思考，我认为自己在小规模的游戏公司待的时间已经足够长了，所以最后我决定返回微软，加入微软自然语言处理组（NLP Group）,并在那里工作了一到两年。我在自然语言处理组的时光非常愉快，但是我也意识到，自然语言处理这个课题不是在我有生之年能够彻底解决的。

从Id Software离职后回到微软工作，这个决定既不是我职业生涯中做出的最好选择，当然也不是最糟糕的。Valve的眼光则更加长远，他们一直与我保持着联系，并时不时地询问我，是否做好准备加盟了？14年之后(14年！你知道Valve多有远见和耐心了吧)，我结束了我在英特尔Larrabee项目的工作，此时我已经知道Valve推出过很多很酷也很成功的游戏，并且有很多我很喜欢也很尊重的朋友在Valve工作。单凭这些理由，就足以让我放手一试了。所以，在我毫不了解Value的企业文化和组织机构的前提下，我加入了Valve，我只是希望这家公司多少能和我以前工作过的公司一样，不至于让我非常不适应。
<div class="mceTemp mceIEcenter" style="text-align: center;"><dl id="attachment_19404" class="wp-caption aligncenter" style="width: 260px;"><dt class="wp-caption-dt"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/GabeNewell.gif"><img class="size-full wp-image-19404" title="GabeNewell" src="http://blog.jobbole.com/wp-content/uploads/2012/05/GabeNewell.gif" alt="Valve公司的联合创始人之一 Gabe Newell" width="250" height="221" /></a></dt><dd class="wp-caption-dd">Valve公司的联合创始人之一 Gabe Newell</dd></dl></div>
&#160;

<strong>Valve</strong><strong>是如此与众不同</strong>

<strong></strong>我的职业生涯已经接近30年，其中我经历了不同的公司和不同的工作环境。我当过软件顾问，也做过技术专栏作家。我曾经在不同的公司独立开发程序，也曾经与人合作一起开发游戏。我曾经参与的项目包括：操作系统，驱动程序，固件开发，自然语言处理，控制终端以及处理器设计。我曾经为一系列的小型创业公司做过技术顾问，其业务涉及软件和硬件。我曾经为微软工作，也曾经为Id Software工作，还曾经为RAD Game Tools工作。这些公司都很有趣，对于我来说，都给我带来了宝贵的经验，其中的某些经验对我来说至关重要。总的来讲，在技术的领域，我几乎已经涉及过所有可能的领域。

但是Valve却如此与众不同。
<div class="mceTemp mceIEcenter" style="text-align: center;"><dl id="attachment_19405" class="wp-caption aligncenter" style="width: 505px;"><dt class="wp-caption-dt"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/img20120413346257800.jpg"><img class="size-full wp-image-19405" title="Valve公司著名的Logo" src="http://blog.jobbole.com/wp-content/uploads/2012/05/img20120413346257800.jpg" alt="Valve公司著名的Logo" width="495" height="375" /></a></dt><dd class="wp-caption-dd">Valve公司著名的Logo</dd></dl></div>
&#160;

Gabe跟我说过这么一件事：当他20世纪90年代在微软工作的时候，他曾经做过一次调查，在用户的个人电脑上究竟哪些软件安装得最多。当时排名第二的软件是，Windows操作系统。

排名第一的是：Id Software开发的游戏Doom

一个来自于德克萨斯Mesquite的10至20人的小公司，他们的创意所产生的软件居然能够超越当时世界上最牛的软件公司（微软）生产的产品，成为最受用户欢迎的软件。这一事实让Gabe对软件生产力的本质理解发生了改变。他从历史的角度审视了组织结构这个问题，他发现，层级式的管理制度最早是从军队中衍生出来的，最早的军队利用这种体系来进行管理，以便让一个1000人的队伍能够机械地翻山越岭，向敌人开枪。当工业革命发生以后，层级式的管理依然有效，因为工业化生产的精髓，就是把每个人看作一个机器的零件，然后确保每个零件准确无误地重复自己的工作。
Doom所造就的成功则完全不属于上述的管理学范畴。因为在Id Software的案例里面，重复的工作几乎没有任何价值。Id Software的所有价值都体现在了如何创造新的事物上。Doom推出以后，会有成千上万的程序员和艺术家会照着Doom的模式推出类似的产品（确实很多人这么做），但是没人能够企及Doom的高度。同样，作为一个程序员，你可以完美地重现Facebook或者Google搜索引擎或者Twitter或者浏览器，或者你可以再次开发类似于《俄罗斯方块》、《愤怒的小鸟》或者《猜字游戏》、《开心农场》等等这些已经大红大紫的应用。但是这样做有什么意义呢？我的观点是：在Internet时代，复制一个软件和大面积传播软件的代价几乎为零，因此，只有软件的首创者才能真正获得所谓的良性循环。

鉴于Valve现在多数的工作都是创新，传统的那种层级式的管理模式就很难适用了。传统的层级管理模式强调的是重复设计和制造同样的产品，然后在不停重复的过程中一点一点地创新（也许就是腾讯说的“微创新”吧——译者注）。如果你想从起步就通过持续地创新进入所谓的“良性循环”，那么层级式的管理模式确实帮不了什么忙。因为在层级式的管理模式下，公司的高层往往是创新的瓶颈，因为你很难指望这帮高层人士能够去提出开发什么与现有产品大相径庭的创新产品，他们的思路往往正好相反，他们更信任现有的产品。实际上，Valve能够吸引那种热爱原创的人们，给他们提供自由的创新平台，这也是他们能留在Valve专心工作的主要原因。所以，在Valve没有正式的管理人员，也完全没有什么分层级的公司结构。

现在，我可以负责任地告诉你，事实就是这样。也许你不太相信刚才我说的话。是的，我一开始也不信。一个300人规模的公司，怎么可以没有正式的管理层呢？但实际上，根据我的观察，新人入职Valve以后，需要6个月的时间才能融入整个团队，其间没有人会告诉他们应该做什么事情，也没有所谓的管理层对其进行复核，在公司里也没有什么升职这种事情，甚至没有固定头衔和职位（不过奖金和分红不会少哦，如果公司合伙人发现公司市值上升的话）。新人自己对自己负责，也只有他们自己对自己负责，来安排他们自己的时间（这也正是公司最宝贵的资源）去找出为公司做出贡献的方法，然后加以实现。如果他们想做一些与众不同的事情，也不需要经过什么管理层的首肯；他们需要做的仅仅是，把办公桌移动到新的项目组所在的位置（办公桌都是带滑轮的，开发用的电脑就放在桌上），然后就开始开发新项目了。（显然他们要自行判断坐在哪个位置比较有利于开展工作，以及便于与他人沟通，但这些都是基于他们的常识判断，没有硬性规定他们必须要怎么做）。项目中的每个人都是独立的贡献者，他们每个人都需要负责编码、美工、关卡设计、音乐等等，甚至包括部分管理工作。这里没有纯管理或者纯构架或者纯设计的职位。公司的任何一个部分都能够随时快速转型，因为没有管理层和职位的束缚，也就不用考虑什么重组计划，重组预算什么的。Gabe其实挺想让公司有个专职管理层的，以处理那些管理方面的事情，但是没有员工愿意签约成为专职的管理人员。

Valve最令人难以置信的就是信任的程度。信任无处不在。Valve所有的源代码毫无疑问地可以被所有员工访问，任何员工都有权限对代码提交修改。任何员工都有权做他们认为值得的事情。Steam工作室就是能够体现这一点的最近的例子。公司的所有员工都能了解到公司是如何运作的，以及公司目前的状况。公司对于员工来说就是透明的。与其他的很多组织机构不同，Valve打心眼儿里就不想让行政因素成为员工与公司的壁垒。公司充分相信员工自己的知道该干什么，以及如何体现自己的价值。

需要澄清的是，Valve并不曾回避软件产品需要开发和交互的事实。我们也是人，团队内部也会对开发什么产品和如何开发产品产生争吵（有的时候争吵还相当激烈），但是大家都是互相尊重的，并且最后一定能够达成一致。当产品接近交货时，也会面临很大的压力和繁重的工作流程，尤其是应付那些主机游戏厂商的产品认证期限（PC游戏的交付会相对灵活很多，多亏了Steam）.有时开发团队或者开发人员甚至会徘徊不前，做很多无用功，此时就要靠其他的同事们及时出手把他们拉回正轨。

其次需要说明的是，不要认为在Valve，员工是想来就来想走就走，而且能够为所欲为。在工作时间，如果一个程序员自己决定要搬到一个独立办公室，然后开始织毛线帽，这当然是不OK的(除非这个程序员是想开发一款程序，能够帮助玩家织虚拟的毛线帽，并且成功地卖掉这个产品赚钱，这样就OK了)。员工提交了项目以后，这些项目就由员工自己负责。项目会有项目负责人，但是这些负责人不是正式任命的，也不涉及到什么荣誉或者奖金什么的。负责人是暂时的，当项目更换时，前一个项目的负责人在新项目里也许就仅仅是新项目的一个普通参与者。负责人需要得到项目组的全体人员的认可，认同挑选这个负责人做协调工作对项目最有利。每个项目组内部会自己制定项目测试、代码检入规则、开会的频率（当然不会很频繁），以及项目的开发目标和开发途径。综上所述，各个项目组之间的情况会大相径庭。

你很难想象这样的组织形式居然能够维持正常工作，但实际上我们确实正常地在工作。我想这多少有点儿“进化”的意思。一方面，我们看上去混乱无序，貌似低效，大的IT公司决然不会容忍如此的工作作风；另一方面，我们却开发出无与伦比的产品，达到伟大的成绩，这些业绩也不是靠传统的层级式模式管理的大公司能够做到的。我们让游戏为自己说话，于是有了Steam项目（当然，Steam项目也没有正式的管理层）。Valve的一系列成功，甚至是很多突破性的壮举，都无不证明了这样一个假设的正确性：唯有具有创造力的人才，才是获得成功的关键因素。所以，以这些创新型人才为中心建立起来的松散的公司结构取得了很大的成功！

显然，就像我们定义的那样。Valve是创新人才最适合的聚居地!

&#160;

<strong>我的工作</strong>

<strong></strong>那么，我个人的在公司的经历如何呢？

像我刚才提到的那样，我刚来到公司的时候，对公司知之甚少。别人告诉我关于这个公司的信息，多少和公司的实际情况有所差异。我原以为我来了以后，就应当有一大堆技术工作要做，比如Source 3D引擎中的可见性探测，或者DotA2中的战场雾化计算等等（实际上这些工作我也做了，只是它们并不是主要工作，而只是一些有趣的小优化，日后我会写写这些方面的内容）

除了做技术，我从公司的这些人身上得到的一些建议让我觉得非常新奇，没有人会告诉我应当怎么做，没有直接的指示！我记得最近一次有人给我指示，是我在Source 3D引擎小组工作时，那时整个Source 3D引擎小组都正在为游戏Portal 2做优化工作。我当时已经为这款游戏做了很多优化工作，对该游戏的各项细节也非常熟悉了，所以我建议Jay Stelly，是不是让我也加入Portal 2开发小组，为该游戏贡献自己的力量。Jay回复我说：“好啊！没问题！但是你要知道，我们最终还是要把这个游戏卖出去的。” 当时我不太明白他的意思，但是经过几次类似的讨论后，我意识到了，他的意思是要让我弄清楚，什么才是我能做的最有价值的事情。目前已经有很多有经验有才华的人在为Portal 2做优化了，而我，应该把精力放到更有影响力的产品上去，我需要做别人都做不到的事情。就是因为这段对话，再加上我和公司其他人交流之后，促使我彻底改变了思维模式，并最终将我领入了一个美妙的领域：可穿戴计算技术

所谓的“可穿戴计算技术”，是一种移动计算技术，该技术能够将计算机产生的图像和真实世界的场景融合起来，并一同呈现在用户的眼前（想象《终结者》里面施瓦辛格扮演的终结者的视角吧，就像那样。此外，Google最新启动的Google Glass项目，应该就是可穿戴计算技术的典型例子——译者注）。我们已经潜移默化地从台式机电脑转移到了笔记本电脑，并从笔记本电脑转移到了上网本和平板电脑，这是一个计算设备往随处、随时特性发展的趋势。逻辑计算终端无时不在，无处不在，这就是可穿戴式计算，我很有信心地预计，在未来20年内，该技术就会建立起工业标准，通过眼镜或者接触，或者其他我所知的更直接的神经连接的形式加以实现。我也非常有信心，平台迁移的速度将远远低于20年，最慢10年，最快3-5年。因为该领域最核心的部分：输入、处理/功率/电子器件尺寸，以及输出，这些推进可穿戴计算的关键技术都在顺利发展，尽管目前还有差距，但是前景乐观。
<div class="mceTemp mceIEcenter" style="text-align: center;"><dl id="attachment_19406" class="wp-caption aligncenter" style="width: 527px;"><dt class="wp-caption-dt"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/t1-a2.jpg"><img class="size-full wp-image-19406  " title="终结者的视角" src="http://blog.jobbole.com/wp-content/uploads/2012/05/t1-a2.jpg" alt="终结者的视角" width="517" height="284" /></a></dt><dd class="wp-caption-dd">终结者的视角</dd></dl></div>
&#160;

当然，硬件只是作为软件运行的基础。目前仍有像蜘蛛网一样错综复杂的各种疑问和矛盾亟待解决。例如，如何让软件和硬件能配合工作，可穿戴式的UI如何设计，如何与可穿戴式输入设备进行交互，计算机如何判断用户的位置，以及用户视点的方向，当人类的视觉系统发现一对叠加的物体，其中一个是真实物体，一个是虚拟物体，计算机将如何判断接受哪一个拒绝哪一个？如何界定扩展现实的范围，使之有效？需要什么样性能的硬件设备来驱动软件？诸如此类，种类繁多。每一个问题都非常深奥，值得你不惜一切代价去解决（我希望我能再以后把所有的问题都列举出来）。实际上，我需要提到的是，从广义上来说，通过Quake，我们弄懂了3D图形学，C/S互联网络通信，文件格式，等等，一切都是白手起家做出来的。事实上，我认为可穿戴式计算技术，就像Quake一样，很有潜力成为一个技术转折点，从而改变以往的一切。

实际上，当年我试图开发的Snow Crash科幻游戏，该技术可被看做是我追求的方向上的潜在的巨大的进步。因果轮回，如果我当初没有因为试图开发Snow Crash游戏，从而加入Id Software，那我今天也就不会在Valve做这些事情，甚至Valve也不会开展这些方面的研究。

在我经历了这么多事情，并完成了大量的研究课题后，我决定花些时间评估一下“可穿戴式计算”是否可以作为Valve公司的一个开发领域，这样做对公司会有好处。我把我的研究和结论展示给公司里很多我尊重的人看，结果他们都一致反映，说“可穿戴式计算”是项目值得一试。其主要的理由是，“可穿戴式计算”应该先构建出一套真正的原型，以供搜集信息，然后才评判项目是否能够成功。除此之外，大家就没有其他的意见和建议了，并且我也不需要获得什么“官方认可”。一旦我搜集到了足够的反馈，并达到了我满意的程度，我就直接启动了项目。

停下了来想一想我刚才说的，然后在琢磨琢磨你自己的工作。在Valve,只要我觉得这个事情是有意义有价值的，不出一个晚上，我就可以开启这个项目！酷不酷？

特别说一下，这个项目现在还是“研发”阶段，目前还不到形成产品的程度，而且很可能在很长一段时间里都无法形成最终的产品。所以，拜托不要再传什么“在E3上会推出Steam眼镜”这种谣言了。目前我正在对这个有趣且有前景的项目开展研发工作，并且在研究上的比例要多于开发。在Valve做事的方法就是，动手实践，然后观察结果。实验失败并不是灾难，关键是我们要如何才能快速发现问题，从中吸取教训，并继续向前，开展下一次的实验。这个过程一旦开始，其推进是快速的，并且是迭代的。实验能进行到什么程度，发展到多远，这需要取决于我们从实验中得到的经验和教训。

这同时也取决于谁来做这些实验。团队不停地成长，朝好的方向发展，但是需要实验的问题也种类繁多，我们需要更多的天才加盟。大量的聪明人，硬件工程师，软件工程师，固件工程师，游戏设计师，UI设计师，或者是优秀的程序员和解决问题的高手，工业设计师，机械工程师，电气工程师，系统程序员，电脑视觉工程师，光学工程师，无论什么类型的工程师，我们都很需要。

也许就是你！

如果你有兴趣深入到“可穿戴式计算”课题中去，那么你就是我们需要的人，我写这篇帖子正是为了你！我们需要你，我觉得你也有可能乐意加入我们。不信的话，再读一读这个帖子你就知道了。给我发email吧，我们就可以共同战斗了！

就算我的项目无法吸引你，你也应该仔细考虑一下是不是要加入Valve。我们是一家杰出的游戏公司，也是一家优秀的数字化发行和传媒公司，并且还有很多优秀的特点！我们这里开展各种各样的项目（事实上，你单从我开展的“穿戴式计算”项目，就可以看出我们公司的项目范围有多广），需要各种各样的技能，我们需要动画师，艺术家，关卡设计师，音乐和音效设计师，编剧，网络应用程序员，数据库程序员，其他领域程序员，研究型心理学家，数据挖掘和机器学习专家，统计学家，用户体验工程师，会计，开发者相关人员，各种硬件工程师等等，我们需要的人才甚至不止上述这些。如果你是一流的经济学家，请研究一下我们吧，你会有一个包含四千万用户的沙箱，我保证你绝不会对这个规模的案例感到缺乏挑战。

如果Valve让你觉得还算对胃口（未来我会发一篇帖子，专门讨论Vavle在招聘时如何招人的细节），那么就赶快飞奔来联系我们吧（记住要跑过来，不要散步散过来哦）！

我们已经迫不及待地要跟你交谈了！

&#160;

英文原文：<a href="http://blogs.valvesoftware.com/abrash/valve-how-i-got-here-what-its-like-and-what-im-doing-2/" target="_blank">MAbrash</a>   编译：<a href="http://www.jobbole.com" target="_blank">伯乐</a>在线 - <a href="http://blog.jobbole.com/19390/" target="_blank">黄小非</a>

<span style="color: red;">【如需转载，请标注并保留原文链接、译文链接和译者等信息，谢谢合作！】</span>

&#160;]]></description>
			<content:encoded><![CDATA[<p><strong>译注：</strong>本文的作者是Michael Abrash（迈克尔·亚伯拉什），他是计算机图形领域首屈一指的大师！ 他是著名的计算机图形编程书籍《<span class='wp_keywordlink'><a href="http://www.amazon.com/gp/product/1576101746/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=job0ae-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=1576101746" title="Graphics Programming Black Book" rel="nofollow" target="_blank">Graphics Programming Black Book</a></span>》的作者，同时也是一位拥有高超编程技巧的开发者。Michale Abrash的职业经历非常丰富，他所效力过的公司包括微软、Id Software、Intel等，参与过的项目涉及操作系统开发、游戏开发、人工智能项目、处理器设计项目等多个领域，同时他当然也是一位杰出的软件顾问和技术专栏作者。Michael Abrash于2011年加入Valve公司，从事游戏相关的研究项目。本文就是他在加入Valve后，对自己的职业生涯的回顾，以及对自己在Valve公司的工作情况的介绍，同时，此文也是一个为Valve招兵买马的招聘贴！（以下是全文）</p>
<div class="mceTemp mceIEcenter" style="text-align: center;">
<dl id="attachment_19400" class="wp-caption aligncenter" style="width: 554px;">
<dt class="wp-caption-dt"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Michael-Abrash-Valve-GDC.jpg" rel="lightbox[19390]" title="Michael-Abrash-Valve-GDC"><img class="size-full wp-image-19400" title="Michael-Abrash-Valve-GDC" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Michael-Abrash-Valve-GDC.jpg" alt="Michael Abrash" width="544" height="368" /></a></dt>
<dd class="wp-caption-dd">Michael Abrash</dd>
</dl>
</div>
<p>&nbsp;</p>
<p>一切都是从<span class='wp_keywordlink'><a href="http://www.amazon.cn/gp/product/0553380958/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=vastwork-23&linkCode=as2&camp=536&creative=3200&creativeASIN=0553380958" title="Snow Crash" rel="nofollow" target="_blank">Snow Crash</a></span>开始的。</p>
<p>如果我没有了解到Metaverse(虚拟世界)，如果我没有被Metaverse(虚拟世界)的构想深深吸引，如果我没有意识到3D网络化离现实是如此地接近，如果我不够自信能有所作为，更重要的是，如果我不是发自内心地想去做，那我就永远不可能有机会来到Valve工作。</p>
<p>那是1994年，我当时已经为微软工作了几年。那年的某天晚上，我的女儿正在Sammamish Plateau的小教授书店翻看各种书籍，我偶尔就注意到了书架上的一本书：《<a href="http://www.amazon.cn/gp/product/0553380958/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&amp;tag=vastwork-23&amp;linkCode=as2&amp;camp=536&amp;creative=3200&amp;creativeASIN=0553380958" target="_blank">Snow Crash</a>》。我拿起这本书，翻开就读，然后就决定要买下，接下来，只用了一个晚上，我就狼吞虎咽地读完了。看完书以后，我自己开始意识到，书中80%的内容都非常可行，我能在电脑上实现他们！我的心情是如此迫切，对于与做电脑相关的事情，我的急切一如既往。我是个职业科幻迷，这次，我有一个绝佳的机会去自己实现一把科幻！于是，在微软公司，我就着手开始实现一个基于网络的3D引擎项目。</p>
<div class="mceTemp mceIEcenter" style="text-align: center;">
<dl id="attachment_19399" class="wp-caption aligncenter" style="width: 296px;">
<dt class="wp-caption-dt"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/stephenson_b.jpg" rel="lightbox[19390]" title="stephenson_b"><img class="size-full wp-image-19399" title="stephenson_b" src="http://blog.jobbole.com/wp-content/uploads/2012/05/stephenson_b.jpg" alt="科幻小说《Snow Crash》" width="286" height="432" /></a></dt>
<dd class="wp-caption-dd">科幻小说《<a href="http://www.amazon.cn/gp/product/0553380958/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&amp;tag=vastwork-23&amp;linkCode=as2&amp;camp=536&amp;creative=3200&amp;creativeASIN=0553380958" target="_blank">Snow Crash</a>》</dd>
</dl>
</div>
<p>&nbsp;</p>
<p>就在我心血来潮的时候，我也开始清醒地认识到，自己绝对不会有机会去启动这么一个项目。John Carmack到西雅图来探望他的母亲，当时他刚刚在Id Software搞出了Doom，我趁此机会约他见面一起吃个饭，就在当地的泰国餐厅。我以前只见过Carmack一次，但是他之前就认识我，是因为他在刚开始学PC编程的时候，在《PC Magazine》上读到过我的文章，几年前，我们还在M&amp;T BBS上有过几回文字交流。上一次我和他见面的时候，他问我是否考虑加入Id Software, 这个邀请让我觉得有点惊讶，因为我当时正在忙于Windows NT的交付工作，况且微软在职工优先认证股权方面的待遇也非常地慷慨，所以我拒绝了他。这一次见面，我知道他还是想邀请我加盟，但是我觉得我还是会拒绝他，因为我目前在微软的根基已经挺牢固了，况且微软目前在股权方面的待遇更加优厚了。出乎意料的是，John Carmack跟我聊了两个多小时，却对邀请我加盟的事情只字未提。他只是谈到了些关于可持续性的Internet游戏服务器，以及玩家自己设计关卡，并在他们自己的服务器上运行，还有就是如何把众多的玩家都聚集起来，让他们在一个共同的虚拟空间共同成长等等事情。我意识到了，他所说的正是Metaverse，虽然没有Neal(科幻小说《<a href="http://www.amazon.cn/gp/product/0553380958/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&amp;tag=vastwork-23&amp;linkCode=as2&amp;camp=536&amp;creative=3200&amp;creativeASIN=0553380958" target="_blank">Snow Crash</a>》的作者——译者著)在书中描写的那么迷人，但是却真实得令人难以置信。有了这个铺垫，当他最后摊牌邀请我加盟的时候，我无法再拒绝了，我不能错过创造未来的机会。</p>
<div class="mceTemp mceIEcenter" style="text-align: center;">
<dl id="attachment_19402" class="wp-caption aligncenter" style="width: 360px;">
<dt class="wp-caption-dt"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/jcint350.jpg" rel="lightbox[19390]" title="jcint350"><img class="size-full wp-image-19402" title="jcint350" src="http://blog.jobbole.com/wp-content/uploads/2012/05/jcint350.jpg" alt="John Carmack, 游戏编程领域的奇才" width="350" height="263" /></a></dt>
<dd class="wp-caption-dd">John Carmack, 游戏编程领域的奇才</dd>
</dl>
</div>
<p>&nbsp;</p>
<p>与John一起工作，就仿佛是《黑客帝国》里的Neo一样，把一种又一种武术技能灌入大脑。我曾经每天晚上都蹒跚走到Id Software的停车场，对我一天的工作感到震惊和不知所措。我每天都在试图跟上John Carmack的节奏，我们在创建一个全新的编程领域：3D,基于Internet的客户端/服务器多人游戏系统，模组，脚本，所有的这些，都只有我们两个<span class='wp_keywordlink'><a href="http://blog.jobbole.com/821/" title="程序员的本质">程序员</a></span>负责完成！当然，思考了这些以后，我还要挤出半小时时间，开车回Plano. 所有的事情都以光速前进，根本没有时间停歇和回味。在我到公司的16个月后，Quake就正式完成并交付发售了。不过这一切都是值得的，不仅仅是因为我在编程方面的突飞猛进，Quake开创了一个时代，它可不是什么“最好的游戏之一”，它是一个突破性的技术（对此，需要说明一下，Carmack是杰出的创新家，也是创新的源动力）。该游戏创建了全新的流派，拥有了自己的社区，并且时至今日仍然非常火爆。举个例子，当我后来在Valve工作的时候，我发现有不少的员工，他们的职业生涯是从给Quake做模组，或者在Quake引擎的基础上开发而开始的。像这些员工一样，我也给我自己创造了未来15年的工作机会。</p>
<div class="mceTemp mceIEcenter" style="text-align: center;">
<dl id="attachment_19403" class="wp-caption aligncenter" style="width: 370px;">
<dt class="wp-caption-dt"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/600full-quake-cover.jpg" rel="lightbox[19390]" title="600full-quake-cover"><img class="size-full wp-image-19403" title="600full-quake-cover" src="http://blog.jobbole.com/wp-content/uploads/2012/05/600full-quake-cover.jpg" alt="轰动一时的第一人称3D在线对战游戏《Quake》" width="360" height="425" /></a></dt>
<dd class="wp-caption-dd">轰动一时的第一人称3D在线对战游戏《Quake》</dd>
</dl>
</div>
<p>&nbsp;</p>
<p>1996年，Id Software迎来了两位客人，Mike Harrington和Gabe Newell，这两个人刚刚离开微软公司，并创办了一家叫做Valve的游戏公司。他们想购买Quake引擎的源代码，来构建他们自己的第一个游戏。当时，整个Id Software上下没有一个人对源代码授权这种事情感兴趣，甚至大家都懒得理这两个人。鉴于这种尴尬的局面，我出面帮他们搞定了源代码授权的问题。因为我和Mike以及Gabe在微软的时候就互相认识，而且当我刚到微软工作的时候，Mike做了很多他份外的事情来帮助我，因此我才得以在微软生存下来，所以我觉得我现在也应该帮助他们。事实上，源代码授权这件事情后来演变成了双赢的局面，Id Software从授权中赚了很多钱，Valve也在这个源代码的基础上开发了他们的成名作《半条命》（也就是完全不用再多介绍的网络对战游戏《反恐精英》的单机版——译者注），不过，我本人并没有从这件事情中获得经济利益（希望以后会），因为不久之后我就决定从Id Software离职了。我当时的计划是，离职后返回微软工作，不过Mike和Gabe向我伸出了橄榄枝，问我是否愿意加盟Valve，成为第三联合创始人。经过很长时间的思考，我认为自己在小规模的游戏公司待的时间已经足够长了，所以最后我决定返回微软，加入微软自然语言处理组（NLP Group）,并在那里工作了一到两年。我在自然语言处理组的时光非常愉快，但是我也意识到，自然语言处理这个课题不是在我有生之年能够彻底解决的。</p>
<p>从Id Software离职后回到微软工作，这个决定既不是我职业生涯中做出的最好选择，当然也不是最糟糕的。Valve的眼光则更加长远，他们一直与我保持着联系，并时不时地询问我，是否做好准备加盟了？14年之后(14年！你知道Valve多有远见和耐心了吧)，我结束了我在英特尔Larrabee项目的工作，此时我已经知道Valve推出过很多很酷也很成功的游戏，并且有很多我很喜欢也很尊重的朋友在Valve工作。单凭这些理由，就足以让我放手一试了。所以，在我毫不了解Value的企业文化和组织机构的前提下，我加入了Valve，我只是希望这家公司多少能和我以前工作过的公司一样，不至于让我非常不适应。</p>
<div class="mceTemp mceIEcenter" style="text-align: center;">
<dl id="attachment_19404" class="wp-caption aligncenter" style="width: 260px;">
<dt class="wp-caption-dt"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/GabeNewell.gif" rel="lightbox[19390]" title="GabeNewell"><img class="size-full wp-image-19404" title="GabeNewell" src="http://blog.jobbole.com/wp-content/uploads/2012/05/GabeNewell.gif" alt="Valve公司的联合创始人之一 Gabe Newell" width="250" height="221" /></a></dt>
<dd class="wp-caption-dd">Valve公司的联合创始人之一 Gabe Newell</dd>
</dl>
</div>
<p>&nbsp;</p>
<p><strong>Valve</strong><strong>是如此与众不同</strong></p>
<p><strong></strong>我的职业生涯已经接近30年，其中我经历了不同的公司和不同的工作环境。我当过软件顾问，也做过技术专栏作家。我曾经在不同的公司独立开发程序，也曾经与人合作一起开发游戏。我曾经参与的项目包括：操作系统，驱动程序，固件开发，自然语言处理，控制终端以及处理器设计。我曾经为一系列的小型创业公司做过技术顾问，其业务涉及软件和硬件。我曾经为微软工作，也曾经为Id Software工作，还曾经为RAD Game Tools工作。这些公司都很有趣，对于我来说，都给我带来了宝贵的经验，其中的某些经验对我来说至关重要。总的来讲，在技术的领域，我几乎已经涉及过所有可能的领域。</p>
<p>但是Valve却如此与众不同。</p>
<div class="mceTemp mceIEcenter" style="text-align: center;">
<dl id="attachment_19405" class="wp-caption aligncenter" style="width: 505px;">
<dt class="wp-caption-dt"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/img20120413346257800.jpg" rel="lightbox[19390]" title="Valve公司著名的Logo"><img class="size-full wp-image-19405" title="Valve公司著名的Logo" src="http://blog.jobbole.com/wp-content/uploads/2012/05/img20120413346257800.jpg" alt="Valve公司著名的Logo" width="495" height="375" /></a></dt>
<dd class="wp-caption-dd">Valve公司著名的Logo</dd>
</dl>
</div>
<p>&nbsp;</p>
<p>Gabe跟我说过这么一件事：当他20世纪90年代在微软工作的时候，他曾经做过一次调查，在用户的个人电脑上究竟哪些软件安装得最多。当时排名第二的软件是，Windows操作系统。</p>
<p>排名第一的是：Id Software开发的游戏Doom</p>
<p>一个来自于德克萨斯Mesquite的10至20人的小公司，他们的创意所产生的软件居然能够超越当时世界上最牛的软件公司（微软）生产的产品，成为最受用户欢迎的软件。这一事实让Gabe对软件生产力的本质理解发生了改变。他从历史的角度审视了组织结构这个问题，他发现，层级式的管理制度最早是从军队中衍生出来的，最早的军队利用这种体系来进行管理，以便让一个1000人的队伍能够机械地翻山越岭，向敌人开枪。当工业革命发生以后，层级式的管理依然有效，因为工业化生产的精髓，就是把每个人看作一个机器的零件，然后确保每个零件准确无误地重复自己的工作。<br />
Doom所造就的成功则完全不属于上述的管理学范畴。因为在Id Software的案例里面，重复的工作几乎没有任何价值。Id Software的所有价值都体现在了如何创造新的事物上。Doom推出以后，会有成千上万的程序员和艺术家会照着Doom的模式推出类似的产品（确实很多人这么做），但是没人能够企及Doom的高度。同样，作为一个程序员，你可以完美地重现Facebook或者Google搜索引擎或者Twitter或者<span class='wp_keywordlink'><a href="http://blog.jobbole.com/12749/" title="浏览器">浏览器</a></span>，或者你可以再次开发类似于《俄罗斯方块》、《愤怒的小鸟》或者《猜字游戏》、《开心农场》等等这些已经大红大紫的应用。但是这样做有什么意义呢？我的观点是：在Internet时代，复制一个软件和大面积传播软件的代价几乎为零，因此，只有软件的首创者才能真正获得所谓的良性循环。</p>
<p>鉴于Valve现在多数的工作都是创新，传统的那种层级式的管理模式就很难适用了。传统的层级管理模式强调的是重复设计和制造同样的产品，然后在不停重复的过程中一点一点地创新（也许就是腾讯说的“微创新”吧——译者注）。如果你想从起步就通过持续地创新进入所谓的“良性循环”，那么层级式的管理模式确实帮不了什么忙。因为在层级式的管理模式下，公司的高层往往是创新的瓶颈，因为你很难指望这帮高层人士能够去提出开发什么与现有产品大相径庭的创新产品，他们的思路往往正好相反，他们更信任现有的产品。实际上，Valve能够吸引那种热爱原创的人们，给他们提供自由的创新平台，这也是他们能留在Valve专心工作的主要原因。所以，在Valve没有正式的管理人员，也完全没有什么分层级的公司结构。</p>
<p>现在，我可以负责任地告诉你，事实就是这样。也许你不太相信刚才我说的话。是的，我一开始也不信。一个300人规模的公司，怎么可以没有正式的管理层呢？但实际上，根据我的观察，新人入职Valve以后，需要6个月的时间才能融入整个团队，其间没有人会告诉他们应该做什么事情，也没有所谓的管理层对其进行复核，在公司里也没有什么升职这种事情，甚至没有固定头衔和职位（不过奖金和分红不会少哦，如果公司合伙人发现公司市值上升的话）。新人自己对自己负责，也只有他们自己对自己负责，来安排他们自己的时间（这也正是公司最宝贵的资源）去找出为公司做出贡献的方法，然后加以实现。如果他们想做一些与众不同的事情，也不需要经过什么管理层的首肯；他们需要做的仅仅是，把办公桌移动到新的项目组所在的位置（办公桌都是带滑轮的，开发用的电脑就放在桌上），然后就开始开发新项目了。（显然他们要自行判断坐在哪个位置比较有利于开展工作，以及便于与他人沟通，但这些都是基于他们的常识判断，没有硬性规定他们必须要怎么做）。项目中的每个人都是独立的贡献者，他们每个人都需要负责编码、美工、关卡设计、音乐等等，甚至包括部分管理工作。这里没有纯管理或者纯构架或者纯设计的职位。公司的任何一个部分都能够随时快速转型，因为没有管理层和职位的束缚，也就不用考虑什么重组计划，重组预算什么的。Gabe其实挺想让公司有个专职管理层的，以处理那些管理方面的事情，但是没有员工愿意签约成为专职的管理人员。</p>
<p>Valve最令人难以置信的就是信任的程度。信任无处不在。Valve所有的源代码毫无疑问地可以被所有员工访问，任何员工都有权限对代码提交修改。任何员工都有权做他们认为值得的事情。Steam工作室就是能够体现这一点的最近的例子。公司的所有员工都能了解到公司是如何运作的，以及公司目前的状况。公司对于员工来说就是透明的。与其他的很多组织机构不同，Valve打心眼儿里就不想让行政因素成为员工与公司的壁垒。公司充分相信员工自己的知道该干什么，以及如何体现自己的价值。</p>
<p>需要澄清的是，Valve并不曾回避软件产品需要开发和交互的事实。我们也是人，团队内部也会对开发什么产品和如何开发产品产生争吵（有的时候争吵还相当激烈），但是大家都是互相尊重的，并且最后一定能够达成一致。当产品接近交货时，也会面临很大的压力和繁重的工作流程，尤其是应付那些主机游戏厂商的产品认证期限（PC游戏的交付会相对灵活很多，多亏了Steam）.有时开发团队或者开发人员甚至会徘徊不前，做很多无用功，此时就要靠其他的同事们及时出手把他们拉回正轨。</p>
<p>其次需要说明的是，不要认为在Valve，员工是想来就来想走就走，而且能够为所欲为。在工作时间，如果一个程序员自己决定要搬到一个独立办公室，然后开始织毛线帽，这当然是不OK的(除非这个程序员是想开发一款程序，能够帮助玩家织虚拟的毛线帽，并且成功地卖掉这个产品赚钱，这样就OK了)。员工提交了项目以后，这些项目就由员工自己负责。项目会有项目负责人，但是这些负责人不是正式任命的，也不涉及到什么荣誉或者奖金什么的。负责人是暂时的，当项目更换时，前一个项目的负责人在新项目里也许就仅仅是新项目的一个普通参与者。负责人需要得到项目组的全体人员的认可，认同挑选这个负责人做协调工作对项目最有利。每个项目组内部会自己制定项目测试、代码检入规则、开会的频率（当然不会很频繁），以及项目的开发目标和开发途径。综上所述，各个项目组之间的情况会大相径庭。</p>
<p>你很难想象这样的组织形式居然能够维持正常工作，但实际上我们确实正常地在工作。我想这多少有点儿“进化”的意思。一方面，我们看上去混乱无序，貌似低效，大的IT公司决然不会容忍如此的工作作风；另一方面，我们却开发出无与伦比的产品，达到伟大的成绩，这些业绩也不是靠传统的层级式模式管理的大公司能够做到的。我们让游戏为自己说话，于是有了Steam项目（当然，Steam项目也没有正式的管理层）。Valve的一系列成功，甚至是很多突破性的壮举，都无不证明了这样一个假设的正确性：唯有具有创造力的人才，才是获得成功的关键因素。所以，以这些创新型人才为中心建立起来的松散的公司结构取得了很大的成功！</p>
<p>显然，就像我们定义的那样。Valve是创新人才最适合的聚居地!</p>
<p>&nbsp;</p>
<p><strong>我的工作</strong></p>
<p><strong></strong>那么，我个人的在公司的经历如何呢？</p>
<p>像我刚才提到的那样，我刚来到公司的时候，对公司知之甚少。别人告诉我关于这个公司的信息，多少和公司的实际情况有所差异。我原以为我来了以后，就应当有一大堆技术工作要做，比如Source 3D引擎中的可见性探测，或者DotA2中的战场雾化计算等等（实际上这些工作我也做了，只是它们并不是主要工作，而只是一些有趣的小优化，日后我会写写这些方面的内容）</p>
<p>除了做技术，我从公司的这些人身上得到的一些建议让我觉得非常新奇，没有人会告诉我应当怎么做，没有直接的指示！我记得最近一次有人给我指示，是我在Source 3D引擎小组工作时，那时整个Source 3D引擎小组都正在为游戏Portal 2做优化工作。我当时已经为这款游戏做了很多优化工作，对该游戏的各项细节也非常熟悉了，所以我建议Jay Stelly，是不是让我也加入Portal 2开发小组，为该游戏贡献自己的力量。Jay回复我说：“好啊！没问题！但是你要知道，我们最终还是要把这个游戏卖出去的。” 当时我不太明白他的意思，但是经过几次类似的讨论后，我意识到了，他的意思是要让我弄清楚，什么才是我能做的最有价值的事情。目前已经有很多有经验有才华的人在为Portal 2做优化了，而我，应该把精力放到更有<span class='wp_keywordlink'><a href="http://www.amazon.cn/gp/product/B0044KME2E/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=vastwork-23&linkCode=as2&camp=536&creative=3200&creativeASIN=B0044KME2E" title="影响力" rel="nofollow" target="_blank">影响力</a></span>的产品上去，我需要做别人都做不到的事情。就是因为这段对话，再加上我和公司其他人交流之后，促使我彻底改变了思维模式，并最终将我领入了一个美妙的领域：可穿戴计算技术</p>
<p>所谓的“可穿戴计算技术”，是一种移动计算技术，该技术能够将计算机产生的图像和真实世界的场景融合起来，并一同呈现在用户的眼前（想象《终结者》里面施瓦辛格扮演的终结者的视角吧，就像那样。此外，Google最新启动的Google Glass项目，应该就是可穿戴计算技术的典型例子——译者注）。我们已经潜移默化地从台式机电脑转移到了笔记本电脑，并从笔记本电脑转移到了上网本和平板电脑，这是一个计算设备往随处、随时特性发展的趋势。逻辑计算终端无时不在，无处不在，这就是可穿戴式计算，我很有信心地预计，在未来20年内，该技术就会建立起工业标准，通过眼镜或者接触，或者其他我所知的更直接的神经连接的形式加以实现。我也非常有信心，平台迁移的速度将远远低于20年，最慢10年，最快3-5年。因为该领域最核心的部分：输入、处理/功率/电子器件尺寸，以及输出，这些推进可穿戴计算的关键技术都在顺利发展，尽管目前还有差距，但是前景乐观。</p>
<div class="mceTemp mceIEcenter" style="text-align: center;">
<dl id="attachment_19406" class="wp-caption aligncenter" style="width: 527px;">
<dt class="wp-caption-dt"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/t1-a2.jpg" rel="lightbox[19390]" title="终结者的视角"><img class="size-full wp-image-19406" title="终结者的视角" src="http://blog.jobbole.com/wp-content/uploads/2012/05/t1-a2.jpg" alt="终结者的视角" width="517" height="284" /></a></dt>
<dd class="wp-caption-dd">终结者的视角</dd>
</dl>
</div>
<p>&nbsp;</p>
<p>当然，硬件只是作为软件运行的基础。目前仍有像蜘蛛网一样错综复杂的各种疑问和矛盾亟待解决。例如，如何让软件和硬件能配合工作，可穿戴式的UI如何设计，如何与可穿戴式输入设备进行交互，计算机如何判断用户的位置，以及用户视点的方向，当人类的视觉系统发现一对叠加的物体，其中一个是真实物体，一个是虚拟物体，计算机将如何判断接受哪一个拒绝哪一个？如何界定扩展现实的范围，使之有效？需要什么样性能的硬件设备来驱动软件？诸如此类，种类繁多。每一个问题都非常深奥，值得你不惜一切代价去解决（我希望我能再以后把所有的问题都列举出来）。实际上，我需要提到的是，从广义上来说，通过Quake，我们弄懂了3D图形学，C/S互联网络通信，文件格式，等等，一切都是白手起家做出来的。事实上，我认为可穿戴式计算技术，就像Quake一样，很有潜力成为一个技术转折点，从而改变以往的一切。</p>
<p>实际上，当年我试图开发的Snow Crash科幻游戏，该技术可被看做是我追求的方向上的潜在的巨大的进步。因果轮回，如果我当初没有因为试图开发Snow Crash游戏，从而加入Id Software，那我今天也就不会在Valve做这些事情，甚至Valve也不会开展这些方面的研究。</p>
<p>在我经历了这么多事情，并完成了大量的研究课题后，我决定花些时间评估一下“可穿戴式计算”是否可以作为Valve公司的一个开发领域，这样做对公司会有好处。我把我的研究和结论展示给公司里很多我尊重的人看，结果他们都一致反映，说“可穿戴式计算”是项目值得一试。其主要的理由是，“可穿戴式计算”应该先构建出一套真正的原型，以供搜集信息，然后才评判项目是否能够成功。除此之外，大家就没有其他的意见和建议了，并且我也不需要获得什么“官方认可”。一旦我搜集到了足够的反馈，并达到了我满意的程度，我就直接启动了项目。</p>
<p>停下了来想一想我刚才说的，然后在琢磨琢磨你自己的工作。在Valve,只要我觉得这个事情是有意义有价值的，不出一个晚上，我就可以开启这个项目！酷不酷？</p>
<p>特别说一下，这个项目现在还是“研发”阶段，目前还不到形成产品的程度，而且很可能在很长一段时间里都无法形成最终的产品。所以，拜托不要再传什么“在E3上会推出Steam眼镜”这种谣言了。目前我正在对这个有趣且有前景的项目开展研发工作，并且在研究上的比例要多于开发。在Valve做事的方法就是，动手实践，然后观察结果。实验失败并不是灾难，关键是我们要如何才能快速发现问题，从中吸取教训，并继续向前，开展下一次的实验。这个过程一旦开始，其推进是快速的，并且是迭代的。实验能进行到什么程度，发展到多远，这需要取决于我们从实验中得到的经验和教训。</p>
<p>这同时也取决于谁来做这些实验。团队不停地成长，朝好的方向发展，但是需要实验的问题也种类繁多，我们需要更多的天才加盟。大量的聪明人，硬件工程师，<span class='wp_keywordlink'><a href="http://blog.jobbole.com/344/" title="明星软件工程师的10种特质">软件工程师</a></span>，固件工程师，游戏设计师，UI设计师，或者是优秀的程序员和解决问题的高手，工业设计师，机械工程师，电气工程师，系统程序员，电脑视觉工程师，光学工程师，无论什么类型的工程师，我们都很需要。</p>
<p>也许就是你！</p>
<p>如果你有兴趣深入到“可穿戴式计算”课题中去，那么你就是我们需要的人，我写这篇帖子正是为了你！我们需要你，我觉得你也有可能乐意加入我们。不信的话，再读一读这个帖子你就知道了。给我发email吧，我们就可以共同战斗了！</p>
<p>就算我的项目无法吸引你，你也应该仔细考虑一下是不是要加入Valve。我们是一家杰出的游戏公司，也是一家优秀的数字化发行和传媒公司，并且还有很多优秀的特点！我们这里开展各种各样的项目（事实上，你单从我开展的“穿戴式计算”项目，就可以看出我们公司的项目范围有多广），需要各种各样的技能，我们需要动画师，艺术家，关卡设计师，音乐和音效设计师，编剧，网络应用程序员，数据库程序员，其他领域程序员，研究型心理学家，数据挖掘和机器学习专家，统计学家，用户体验工程师，会计，开发者相关人员，各种硬件工程师等等，我们需要的人才甚至不止上述这些。如果你是一流的经济学家，请研究一下我们吧，你会有一个包含四千万用户的沙箱，我保证你绝不会对这个规模的案例感到缺乏挑战。</p>
<p>如果Valve让你觉得还算对胃口（未来我会发一篇帖子，专门讨论Vavle在招聘时如何招人的细节），那么就赶快飞奔来联系我们吧（记住要跑过来，不要散步散过来哦）！</p>
<p>我们已经迫不及待地要跟你交谈了！</p>
<p>&nbsp;</p>
<p>英文原文：<a href="http://blogs.valvesoftware.com/abrash/valve-how-i-got-here-what-its-like-and-what-im-doing-2/" target="_blank">MAbrash</a>   编译：<a href="http://www.jobbole.com" target="_blank">伯乐</a>在线 &#8211; <a href="http://blog.jobbole.com/19390/" target="_blank">黄小非</a></p>
<p><span style="color: red;">【如需转载，请标注并保留原文链接、译文链接和译者等信息，谢谢合作！】</span></p>
<p>&nbsp;</p>
<h2  class="related_post_title">相关文章</h2><ul class="related_post"><li><a target="_blank" href="http://blog.jobbole.com/17536/" title="PM如何突破工程师心防">PM如何突破工程师心防</a></li><li><a target="_blank" href="http://blog.jobbole.com/17529/" title="工程师如何不被PM欺负">工程师如何不被PM欺负</a></li><li><a target="_blank" href="http://blog.jobbole.com/17035/" title="专注的艺术：致管理者的三大建议">专注的艺术：致管理者的三大建议</a></li><li><a target="_blank" href="http://blog.jobbole.com/12689/" title="张子阳：如何在30岁前年薪超过30万">张子阳：如何在30岁前年薪超过30万</a></li><li><a target="_blank" href="http://blog.jobbole.com/9124/" title="当ios游戏开发像做份沙拉那么简单">当ios游戏开发像做份沙拉那么简单</a></li><li><a target="_blank" href="http://blog.jobbole.com/8903/" title="从一个程序员笑话看软件开发管理 ">从一个程序员笑话看软件开发管理 </a></li><li><a target="_blank" href="http://blog.jobbole.com/6997/" title="如何才能做好技术团队管理">如何才能做好技术团队管理</a></li><li><a target="_blank" href="http://blog.jobbole.com/6492/" title="GitHub如何运作：时间并不决定一切">GitHub如何运作：时间并不决定一切</a></li><li><a target="_blank" href="http://blog.jobbole.com/4608/" title="有关技术管理的一些思考">有关技术管理的一些思考</a></li><li><a target="_blank" href="http://blog.jobbole.com/1385/" title="乔布斯的10条管理诫律">乔布斯的10条管理诫律</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.jobbole.com/19390/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>UNIX 系统中的文本操作简介</title>
		<link>http://blog.jobbole.com/19641/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=unix-%25e7%25b3%25bb%25e7%25bb%259f%25e4%25b8%25ad%25e7%259a%2584%25e6%2596%2587%25e6%259c%25ac%25e6%2593%258d%25e4%25bd%259c%25e7%25ae%2580%25e4%25bb%258b</link>
		<comments>http://blog.jobbole.com/19641/#comments</comments>
		<pubDate>Wed, 16 May 2012 02:51:46 +0000</pubDate>
		<dc:creator>齐哲</dc:creator>
				<category><![CDATA[IT技术]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Unix]]></category>

		<guid isPermaLink="false">http://blog.jobbole.com/?p=19641</guid>
		<description><![CDATA[<strong>简介</strong>

UNIX 的基本哲学之一就是创建只做一件事并将这一件事做好的程序（或进程）。这一哲学要求认真考虑接口以及结合这些更小（有望更简单）流程的方法，以产生有用的 结果。文本数据通常是在这些接口之间流动。多年以来，越来越高级的文本处理工具和语言已经开发出来。从语言上来讲，早期专门处理文本的语言有 perl，后来又出现了 python 和 ruby。虽然这些语言以及其他语言都是非常强大的文本处理器，但这些工具并不是一直可行的，在生产环境下尤其如此。本文将介绍一些基本的 UNIX 文本处理命令，这些命令既可单独使用也可结合使用，可用来解决需要更新的语言才能解决的问题。对许多人来说，与长篇大论的解释相比，实例能够提供更多的信 息。请注意，由于有多种可用的 UNIX 和 UNIX 类系统，因此不同实现之间的命令标志、程序行为和输出结果会略有不同。

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Banni%C3%A8re-Unix-linux.jpg"><img class="aligncenter size-full wp-image-18798" title="Bannière Unix linux" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Banni%C3%A8re-Unix-linux.jpg" alt="" width="640" height="247" /></a>

<strong>使用 cat</strong>

cat 命令是最基本的命令之一。这个命令用来创建、追加、显示以及合并文本文件。

我们可以使用 cat 命令创建文件，方法是：使用 ‘&#62;’ 将标准输入 (stdin) 重定向到文件。使用 ‘&#62;’ 操作符会缩短指定输出文件的内容。在此之后输入的文本会重定向到 ‘&#62;’ 操作符右侧指定的文件。control-d 表示文件结束，将控制权返回给 shell。

<strong>使用 cat 创建文件的示例</strong>
<pre class="brush: shell; gutter: true">  $ cat &#62; grocery.list
  apples
  bananas
  plums
  &#60;ctrl-d&#62;
  $</pre>
使用 ‘&#62;&#62;’ 操作符将标准输入追加到现有文件。

<strong>使用 cat 追加文件的示例</strong>
<pre class="brush: shell; gutter: true">$ cat &#62;&#62; grocery.list
 carrots</pre>
使用 cat 命令不加标志，可查看 grocery.list 文件的内容。请注意文件的内容如何包含来自重定向的输入以及追加操作符的示例。

<strong>使用无标志 cat 的示例</strong>
<pre class="brush: shell; gutter: true">$ cat grocery.list
 apples
 bananas
 plums
 carrots</pre>
可以使用 cat 命令对文件行进行编号。

<strong>使用 cat 计算行的示例：</strong>
<pre class="brush: shell; gutter: true">$ cat -n grocery.list
 1 apples
 2 bananas
 3 plums
 4 carrots</pre>
<strong>使用 nl</strong>

nl 过滤器会从 stdin 或指定文件读取行。输出则会写入 stdout 并重定向到文件，或传到另一个进程中。nl 的行为是由不同命令行选项控制的。

在默认情况下，nl 会计算行数，与 cat -n 的功能类似。

<strong>nl 默认用法示例：</strong>
<pre class="brush: shell; gutter: true">$nl grocery.list
 1 apples
 2 bananas
 3 plums
 4 carrots</pre>
使用 -b 标志指定要进行编号的行。此标志将参数作为 “类型”。该类型告诉 nl 需要给哪些行编号，使用 ‘a’ 给所有行编号，‘t’ 告诉 nl 不对空行和只有空格的行进行编号，‘n’ 指定不编号行。在示例中显示针对模式的类型 ‘p’。nl 给正则表达式模式指定的行编号，在本用例中，是以字母 ‘a’ 或 ‘b’ 开始的行。

<strong>使用 nl 对符合正则表达式的行进行编号的示例</strong>
<pre class="brush: shell; gutter: true">$ nl -b p^[ba]grocery.list
 1 apples
 2 bananas
 plums
 carrots</pre>
在默认情况下，nl 行号和文本之间使用制表符进行分隔。使用 -s 指定其他分隔符，例如 ‘=’ 号。

<strong>使用 nl 指定其他分隔符的示例</strong>
<pre class="brush: shell; gutter: true">$nl -s= grocery.list
 1=apples
 2=bananas
 3=plums
 4=carrots</pre>
<strong>使用 wc</strong>

wc (wordcount) 命令计算指定文件或来自 stdin 的行数、单词数（由空格分隔）和字符数。

<strong>wc 用法示例</strong>
<pre class="brush: shell; gutter: true">$wc grocery.list
 4 4 29 grocery.list
 $wc -l grocery.list
 4 grocery.list
 $wc -w grocery.list
 4 grocery.list
 $wc -c grocery.list
 29 grocery.list</pre>
<strong>使用 grep</strong>

grep 命令在指定文件或 stdin 中搜索与给定表达式相匹配的模式。grep 的输出由多个选项标志控制。

为了演示，这里新创建了一个文件，与 grocery.list 配合使用。
<pre class="brush: shell; gutter: true">$cat grocery.list2
 Apple Sauce
 wild rice
 black beans
 kidney beans
 dry apples</pre>
<strong>grep 基本用法示例</strong>
<pre class="brush: shell; gutter: true">$ grep apple grocery.list grocery.list2
 grocery.list:apples
 grocery.list2:dry apples</pre>
grep 拥有相当可观的选项标志。下面的示例将演示其中几个选项的用法。

要显示文件名（处理多个文件的情况下）以及发现模式匹配的行数，在本用例中使用的模式是计算每个文件中出现单词 ‘apple’ 的行数。

<strong>grep 示例：计算文件中匹配数</strong>
<pre class="brush: shell; gutter: true">$ grep -c apple grocery.list grocery.list2
 grocery.list:1
 grocery.list2:1</pre>
在搜索多个文件时，可以使用 -h 选项取消在输出中显示文件名。

<strong>grep 示例：取消在输出中显示文件名</strong>
<pre class="brush: shell; gutter: true">$ grep -h apple grocery.list grocery.list2
 apples
 dry apples</pre>
在很多情况下，需要进行不区分大小写的搜索。grep 命令的 -i 选项可以在搜索时忽略大小写。

<strong>grep 示例：不区分大小写</strong>

&#160;
<pre class="brush: shell; gutter: true">$ grep -i apple grocery.list grocery.list2
grocery.list:apples
 grocery.list2:Apple Sauce
 grocery.list2:dry apples</pre>
&#160;

有些时候，只需要输出文件名，不需要输出模式匹配的行。grep 提供 -l 选项，用于只输出包含匹配模式行的文件名。

<strong>grep 示例：只输出文件名</strong>
<pre class="brush: shell; gutter: true">$ grep -l carrot grocery.list grocery.list2
 grocery.list</pre>
行号可以显示在输出中。使用 -n 选项来包含行号。

<strong>grep 示例：包含行号</strong>
<pre class="brush: shell; gutter: true">$ grep -n carrot grocery.list grocery.list2
 grocery.list:4:carrots</pre>
有时期望输出与模式不匹配的行。这时就要使用 -v 选项。

<strong>grep 示例：输出不匹配行</strong>
<pre class="brush: shell; gutter: true">$ grep -v beans grocery.list2
 Apple Sauce
 wild rice
 dry apples</pre>
有时，需要的模式是一个单词，两边被空格或其他字符（例如连字符或括号）包围。grep 的多数版本都提供了 -w 选项，能方便地编写此类模式的搜索。

<strong>grep 示例：单词匹配</strong>
<pre class="brush: shell; gutter: true">$ grep -w apples grocery.list grocery.list2
 grocery.list:apples
 grocery.list2:dry apples</pre>
<strong>流、管道、重定向、tee 和 here docs</strong>

在 UNIX 中，一个终端默认包含三个流，一个输入流，两个基于输出的流。输入流称为 stdin，通常映射到键盘（也可使用其他输入设备，或从其他进程中传入）。标准输出流称为 stdout，并通常输出到终端上，输出也可供其他进程使用（就像 stdin 一样）。另一个输出流 stderr 主要用作状态报告，通常输出到终端，如 stdout。这三个流都有各自的文件描述符，每一个流都可以从其他流中传入或重定向，即使是它们全都连接到终端。每个流的文件描述符分别是：

●stdin = 0

●stdout = 1

●stderr = 2

这三个流可以传送或重定向到文件或其他进程。这个构造通常称为 “构建一个管道”。例如，程序员可能想将 stdout 流和 stderr 流合并，然后在终端上显示它们，再将结果保存到文件中以便检查版本问题。使用 2&#62;&#38;1，stderr 流以及文件描述符 2 会被重定向到 &#38;1（指向 stdout 流）。这样就能有效地将 stderr 合并到 stdout。使用 ‘&#124;’ 符号表示管道。管道连接左侧进程 (make) 的 stdout 和右侧进程 (tee) 的 stdin。tee 命令会复制（合并）将数据发送到终端以及文件的 stdout 流，在本示例中，称为 build.log。

<strong>合并和拆分标准流的示例</strong>
<pre class="brush: shell; gutter: true">$ make –f build_example.mk 2&#62;&#38;1 &#124; tee build.log</pre>
另一个重定向示例，使用 cat 命令和一些流重定向制作文本文件副本。

<strong>使用重定向制作备份文件的示例</strong>
<pre class="brush: shell; gutter: true">$ cat &#60; grocery.list &#62; grocery.list.bak</pre>
前面使用 nl 命令为在 stdout 中显示的文件加行号。管道可用于将 stdout 流（来自 cat grocery.list）发送到另外一个进程，在本用例中，是 nl 命令。

<strong>简单管道传送到 nl 的示例</strong>
<pre class="brush: shell; gutter: true">$ cat grocery.list &#124; nl
 1 apples
 2 bananas
 3 plums
 4 carrots</pre>
先前显示的另一个示例是针对模式执行不区分大小写的搜索。这也可以使用重定向来实现（在这本用例中为来自 stdin 或使用管道，与上述简单管道示例相似）。

<strong>grep 示例：通过 stdin 重定向和管道</strong>
<pre class="brush: actionscript3; gutter: true">$ grep -i apple &#60; grocery.list2
 Apple Sauce
 dry apples
 $cat grocery.list2 &#124; grep -i apple
 Apple Sauce
 dry apples</pre>
在某些情况下，要将文本块重定向到某个命令或文件中作为脚本的一部分。实现此操作的机制是使用 ‘here document’（或 ‘here-doc’）。要将 here-doc 嵌入到脚本，需要使用 ‘&#60;

<strong>示例：命令行上的基本 here-doc</strong>
<pre class="brush: shell; gutter: true">$ cat &#60;&#60; EOF 3 &#62; oranges
 &#62; mangos
 &#62; pinapples
 &#62; EOF
 oranges
 mangos
 pinapples</pre>
可将此输出重定向到文件，在本示例中，分隔符 ‘EOF’ 改为 ‘!’。然后使用 tr 命令（稍后说明）将 here-doc 中的字母全部变成大写。

<strong>示例：将基本 here-doc 重定向到文件</strong>
<pre class="brush: shell; gutter: true">cat &#60;&#60; ! &#62; grocery.list3
 oranges
 mangos
 pinapples
 !
 $ cat grocery.list3
 oranges
 mangos
 pinapples
 $tr [:lower:] [:upper:] &#60;&#60; ! 12 &#62; onions
 &#62; !
 ONIONS</pre>
<strong>使用 head 和 tail</strong>

head 和 tail 命令用来查看文件的顶部 (head) 或底部 (tail)。要显示文件顶部两行和底部两行，请分别使用这两个命令加 -n 选项标志。相同地，-c 选项显示文件中的前几个或最后几个字符。

<strong>示例：head 和 tail 命令的基本用法</strong>
<pre class="brush: shell; gutter: true">$ head -n2 grocery.list
 apples
 bananas
 $ tail -n2 grocery.list
 plums
 carrots
 $ head -c12 grocery.list
 apples
 banan
 $ tail -c12 grocery.list
 ums
 carrots</pre>
tail 命令的常见用途就是观察日志文件或者正在运行的进程输出，查看其中是否有问题，或者关注进程何时结束。-f (tail –f) 选项使 tail 持续观察流，即使是到达文件结束标记也继续观察，并在流包含更多数据时，持续显示输出。

使用 tr

tr 命令用来转换来自 stdin 的字符，在 stdout 中显示。tr 一般接受两个字符集合，用第二个集合中的字符替换第一个集合中的字符。有许多预定义的字符类（集合）可供 tr 使用，还有其他命令可用。

这些预定义的字符类是：

●alnum：字母数字字符

●alpha：字母字符

●blank：空白字符

●cntrl：控制字符

●digit：数字字符

●graph：图形字符

●lower：小写字母字符

●print：可打印字符

●punct：标点字符

●space：空间字符

●upper：大写字符

●xdigit：16 进制字符

tr 命令够将字符串中的小写字符转换成大写。

<strong>tr 示例：将字符串转换成大写</strong>
<pre class="brush: shell; gutter: true">$ echo &#34;Who is the standard text editor?&#34; &#124;tr [:lower:] [:upper:]
 WHO IS THE STANDARD TEXT EDITOR?</pre>
tr 可以用来从字符串中删除指定字符。

<strong>tr 示例：从字符串中删除指定字符</strong>
<pre class="brush: shell; gutter: true">$ echo &#039;ed, of course!&#039; &#124;tr -d aeiou
 d, f crs!</pre>
使用 tr 将字符串中任何指定字符转换成空格。在序列中遇到多个指定字符时，它们会转换成一个空格。

-s 选项标志的行为在不同系统中表现不同。

<strong>tr 示例：将字符转变成空格</strong>
<pre class="brush: shell; gutter: true">$ echo &#039;The ed utility is the standard text editor.&#039; &#124;tr -s astu &#039; &#039;
 The ed ili y i he nd rd ex edi or.</pre>
-s 选项标志可以用来取消字符串中多余的空格。
<pre class="brush: shell; gutter: true">$ echo &#039;extra spaces – 5’ &#124; tr -s [:blank:]
 extra spaces - 5
 $ echo ‘extra tabs – 2’ &#124; tr -s [:blank:]
 extra tabs – 2</pre>
在基于 UNIX 和 Windows 系统之间转换文件时发生的常见问题就是行分隔符 (line delimiters)。在 UNIX 系统中，行分隔符为一个换行符，而在 Windows 系统中，则是用两个字符（即一个回车符和一个换行符）。使用 tr 配合某种重定向，可以解决这个格式问题。

<strong>tr 示例：消除回车符</strong>
<pre class="brush: shell; gutter: true">$ tr -d &#039;\r&#039; &#60; dosfile.txt &#62; unixfile.txt</pre>
<strong>使用 colrm</strong>

使用 colrm，可以从流中剪切出文本列。在第一个示例中，使用 colrm 命令从管道的每行文本中剪切出第 4 列到行尾。然后，将同一个文件发送至 colrm，以删除第 4 列到第 5 列。

<strong>使用 colrm 删除列的示例</strong>
<pre class="brush: shell; gutter: true">$ cat grocery.list &#124;colrm 4
 app
 ban
 plu
 car
 $ cat grocery.list &#124;colrm 4 5
 apps
 banas
 plu
 carts</pre>
<strong>使用 expand 和 unexpand</strong>

expand 命令将制表符变成空格，而 unexpand 将空格变成制表符。这两个命令都接受 stdin 输入以及命令行指定文件的输入。使用 -t 选项可以设置一个或多个制表符停止位。

<strong>expand 和 unexpand 示例：</strong>
<pre class="brush: shell; gutter: true">$ cat grocery.list&#124;head -2&#124;nl&#124;nl
 1 1 apples
 2 2 bananas
 $ cat grocery.list&#124;head -2&#124;nl&#124;nl&#124;expand -t 5
 1 1 apples
 2 2 bananas
 $ cat grocery.list&#124;head -2&#124;nl&#124;nl&#124;expand -t 5,20
 1 1 apples
 2 2 bananas
 $ cat grocery.list&#124;head -2&#124;nl&#124;nl&#124;expand -t 5,20&#124;unexpand -t 1,5
 1 1 apples
 2 2 bananas</pre>
<strong>使用 comm、cmp 和 diff</strong>

为了演示这些命令，要新建两个文件。

<strong>新建演示文件：</strong>
<pre class="brush: shell; gutter: true">cat &#60;&#60; EOF &#62; dummy_file1.dat
 011 IBM 174.99
 012 INTC 22.69
 013 SAP 59.37
 014 VMW 102.92
 EOF
 cat &#60;&#60; EOF &#62; dummy_file2.dat
 011 IBM 174.99
 012 INTC 22.78
 013 SAP 59.37
 014 vmw 102.92
 EOF</pre>
diff 命令会对两个文件进行比较，报告两者之间的不同之处。diff 可接受多种选项标志。在下面示例中，首先显示默认的 diff，然后是使用 -w 选项的 diff 忽略空格，并以使用 -i 选项标志在比较中忽略大小写区别而结束。

<strong>diff 命令的示例</strong>

&#160;
<pre class="brush: shell; gutter: true">$ diff dummy_file1.dat dummy_file2.dat
 1,2c1,2
 &#60; 011 IBM 174.99
 &#60; 012 INTC 22.69 06 --- 07 &#62; 011 IBM 174.99
 &#62; 012 INTC 22.78
 4c4
 &#60; 014 VMW 102.92 11 --- 12 &#62; 014 vmw 102.92
$ diff -w dummy_file1.dat dummy_file2.dat
 2c2
 &#60; 012 INTC 22.69 17 --- 18 &#62; 012 INTC 22.78
 4c4
 &#60; 014 VMW 102.92 21 --- 22 &#62; 014 vmw 102.92
$ diff -i dummy_file1.dat dummy_file2.dat
 1,2c1,2
 &#60; 011 IBM 174.99
 &#60; 012 INTC 22.69 28 --- 29 &#62; 011 IBM 174.99
 &#62; 012 INTC 22.78</pre>
&#160;

comm 命令会对两个文件进行比较，但比较的方式与 diff 差别很大。comm 产生三列输出，仅出现在第 1 个文件（第 1 列）的行，仅出现在第 2 个文件（第 2 列）的行，两个文件中都有的常见行（第 3 列）。可使用选项标志来取消输出列。此命令可能在取消第 1 列和第 2 列时最有用，只显示两个文件中常见的行，如下所示。

<strong>comm 命令示例</strong>

&#160;
<pre class="brush: shell; gutter: true">$ comm dummy_file1.dat dummy_file2.dat
 011 IBM 174.99
 011 IBM 174.99
 012 INTC 22.69
 012 INTC 22.78
 013 SAP 59.37
 014 VMW 102.92
 014 vmw 102.92
$ comm -12 dummy_file1.dat dummy_file2.dat
 013 SAP 59.37</pre>
&#160;

cmp 命令也会对这两个文件进行比较。但是，与 comm 或 diff 不同，cmp 命令（默认）报告这两个文件刚开始不同的字节和行号。

<strong>cmp 命令示例</strong>
<pre class="brush: shell; gutter: true">$ cmp dummy_file1.dat dummy_file2.dat
 dummy_file1.dat dummy_file2.dat differ: char 5, line 1</pre>
<strong>使用 fold</strong>

使用 fold 命令可以将行拆分为指定的宽度。这个命令最初是用来对无法支持换行的定宽输出设备进行文本格式化。-w 选项标志允许使用指定行宽，而不是只使用默认的 80 列。

<strong>使用 fold 示例</strong>
<pre class="brush: shell; gutter: true">$ fold -w8 dummy_file1.dat
 011 IBM
 174.99
 012 INTC
 22.69
 013 SAP
 59.37
 014 VMW
 102.92</pre>
<strong>使用 paste</strong>

paste 命令用来合并文件，将每个文件的记录逐一合并。利用重定向，可以通过将一个文件中的每个记录与另一个文件的记录合并，来新建文件。

<strong>新建演示文件：</strong>
<pre class="brush: shell; gutter: true">cat &#60;&#60; EOF &#62; dummy1.txt
 IBM
 INTC
 SAP
 VMW
 EOF
 cat &#60;&#60; EOF &#62; dummy2.txt
 174.99
 22.69
 59.37
 102.92
 EOF</pre>
<strong>paste 示例：来自多文件的行</strong>
<pre class="brush: shell; gutter: true">$ paste dummy1.txt dummy2.txt grocery.list
 IBM 174.99 apples
 INTC 22.69 bananas
 SAP 59.37 plums
 VMW 102.92 carrots</pre>
-s 选项标志用来一次处理多个文件（连续地），而不是并行处理。请注意，下面的列与上面示例中的行合并。

<strong>paste 示例 2：来自多文件的行</strong>
<pre class="brush: shell; gutter: true">$ paste -s dummy1.txt dummy2.txt grocery.list
 IBM INTC SAP VMW
 174.99 22.69 59.37 102.92
 apples bananas plums carrots</pre>
如果只指定一个文件，或者 paste 正处理 stdin，输入会默认显示在一个列中。使用 -s 选项标志，输出会显示在一个行中。由于输出缩减到一行，所以使用分隔符来分隔返回的域（默认的分隔符是制表符）。在本示例中，使用 find 命令寻找 64 位库所在的目录，然后构建一个合适的路径，附加到变量 $LD_LIBRARY_PATH 中。

<strong>paste 示例：使用分隔符</strong>

&#160;
<pre class="brush: shell; gutter: true">$ find /usr -name lib64 -type d&#124;paste -s -d:
 /usr/lib/qt3/lib64:/usr/lib/debug/usr/lib64:/usr/X11R6/lib/X11/locale/lib64:/usr/X11R6/
 lib64:/usr/lib64:/usr/local/ibm/gsk7_64/lib64:/usr/local/lib64
$ paste -d, dummy1.txt dummy2.txt
 IBM,174.99
 INTC,22.69
 SAP,59.37
 VMW,102.92</pre>
&#160;

<strong>使用 bc</strong>

在 Shell 上进行算术计算的简易方法是使用 bc（“basic calculator” 或 “bench calculator”）。有些 shell 自带了算术计算功能，有些则依靠 expr 对表达式进行运算。使用 bc，计算可以在不同的 Shell 和 UNIX 系统间移植，只要注意不同厂商的扩展即可。

<strong>bc 示例：简单计算</strong>

&#160;
<pre class="brush: shell; gutter: true">$ echo 2+3&#124;bc
 5
$ echo 3*3+2&#124;bc
 11
$ VAR1=$(echo 2^8&#124;bc)
 $ echo $VAR1
 256
$ echo &#34;(1+1)^8&#34;&#124;bc
 256</pre>
&#160;

bc 不仅可以执行这些简单计算。它是一个解释器，有自己内部的和用户自定义的函数、语法和流程控制，就像编程语言一样。在默认情况下，bc 在小数点右侧不包含任何数字。要提高输出的精度，需要使用特殊的 scale 变量。如示例所示，bc 支持大数字，可实现更长的精度。使用 obase 或 ibase 可以控制输入和输出数字的转换基础。在下面的示例中：

●obase 改变默认的输入基（10 进制），将结果转变成 16 进制

●对于 2 的平方根，scale 指定了小数点右侧的数字个数

●求 2 的 128 次方演示了对大数字的支持

●调用内部函数 sqrt() 计算 2 的平方根

●在 ksh 中，计算和输出百分比

<strong>bc 示例：更多计算</strong>

&#160;
<pre class="brush: shell; gutter: true">$ echo &#34;obase=16; 2^8-1&#34;&#124;bc
 FF
$ echo &#34;99/70&#34;&#124;bc
 1
$ echo &#34;scale=20; 99/70&#34;&#124;bc
 1.41428571428571428571
$ echo &#34;scale=20;sqrt(2)&#34;&#124;bc
 1.41421356237309504880
$ echo 2^128&#124;bc
 340282366920938463463374607431768211456
$ printf &#34;Percentage: %2.2f%%\n&#34; $(echo .9963*100&#124;bc)
 Percentage: 99.63%</pre>
&#160;

的手册页面中有详细说明，并有相关示例。

<strong>使用 split</strong>

split 命令的一大作途就是将大型数据文件分解成小的文件以方便处理。在本示例中，BigFile.dat 经 wc 命令统计有 165782 行。-l 选项标志规定了 split 为每个输出文件生成的最大行数。split 支持为输出文件名指定前缀，例如下面的示例指定 BigFile_ 为前缀。其他选项支持后缀控制，在 BSD 系统上的 -p 选项标志支持按正则表达式进行拆分，就像 csplit（上下文拆分）命令一样。更多信息请参阅手册页面。

<strong>split 示例:</strong>

&#160;
<pre class="brush: shell; gutter: true">$ wc BigFile.dat
 165782 973580 42557440 BigFile.dat
$ split -l 15000 BigFile.dat BigFile_
$ wc BigFile*
 165782 973580 42557440 BigFile.dat
 15000 87835 3816746 BigFile_aa
 15000 88483 3837494 BigFile_ab
 15000 89071 3871589 BigFile_ac
 15000 88563 3877480 BigFile_ad
 15000 88229 3855486 BigFile_ae
 7514 43817 1908914 BigFile_af
 248296 1459578 63725149 total</pre>
&#160;

<strong>使用 cut</strong>

cut 命令用来 "裁剪" 文件中以列为基础小节或从 stdin 传送而来的数据。它可按字节 (-b)、字符 (-c) 和列表指定的域 (-f) 进行修剪。使用逗号分隔列表和连字符指定域列表或字节/字符位置。如果只需要输出一个位置或域，则直接指定位置或域即可。可以使用连字符指定一系列域，例 如 1-3 输出 1-3 域（或位置），-2 从行开始前两个域（或字节/字符）开始输出，3- 则让 cut 从域（或位置）3 开始输出到行尾。多个域之间以逗号分隔。其他有用的标志有：-d 指定域分隔符，-s 取消没有分隔符的行。

<strong>cut 示例</strong>

&#160;
<pre class="brush: shell; gutter: true">$ cat &#60;&#60; EOF &#62; dummy_cut.dat
 # this is a data file
 ID,Name,Score
 13BA,John Smith,100
 24BC,Mary Jones,95
 34BR,Larry Jones,94
 36FT,Joe Ruiz,93
 40RM,Kay Smith,91
 EOF
$ cat dummy_cut.dat &#124;cut -d, -f1,3
 # this is a data file
 ID,Score
 13BA,100
 24BC,95
 34BR,94
 36FT,93
 40RM,91
$ cat dummy_cut.dat &#124;cut -b6-
 s is a data file
 me,Score
 John Smith,100
 Mary Jones,95
 Larry Jones,94
 Joe Ruiz,93
 Kay Smith,91
$ cat dummy_cut.dat &#124;cut -f1- -d, -s
 ID,Name,Score
 13BA,John Smith,100
 24BC,Mary Jones,95
 34BR,Larry Jones,94
 36FT,Joe Ruiz,93
 40RM,Kay Smith,91</pre>
&#160;

<strong>使用 uniq</strong>

uniq 命令通常用来惟一地列出输入源（通常是文件或 stdin）中的行。要正确操作，重复的行必须连续放置于输入中。uniq 命令的输入通常会进行排序，因此重复的行会进行合并。与 uniq 命令搭配使用的两个常用标志是：-c 输出每行出现的次数，-d 用来显示重复行的一个实例。

<strong>uniq 示例</strong>

&#160;
<pre class="brush: shell; gutter: true">$ cat &#60;&#60; EOF &#62; dummy_uniq.dat
13BAR Smith John 100
 13BAR Smith John 100
 24BC Jone Mary 95
 34BRR Jones Larry 94
 36FT Ruiz Joe 93
 40REM Smith Kay 91
 13BAR Smith John 100
 99BAR Smith John 100
 13XIV Smith Cindy 91
EOF
$ cat dummy_uniq.dat &#124; uniq
13BAR Smith John 100
 24BC Jone Mary 95
 34BRR Jones Larry 94
 36FT Ruiz Joe 93
 40REM Smith Kay 91
 13BAR Smith John 100
 99BAR Smith John 100
 13XIV Smith Cindy 91
$ cat dummy_uniq.dat &#124; sort &#124;uniq
13BAR Smith John 100
 13XIV Smith Cindy 91
 24BC Jone Mary 95
 34BRR Jones Larry 94
 36FT Ruiz Joe 93
 40REM Smith Kay 91
 99BAR Smith John 100
$ cat dummy_uniq.dat &#124; sort &#124;uniq -d
13BAR Smith John 100
$ cat dummy_uniq.dat &#124; sort &#124;uniq -c
 3
 3 13BAR Smith John 100
 1 13XIV Smith Cindy 91
 1 24BC Jone Mary 95
 1 34BRR Jones Larry 94
 1 36FT Ruiz Joe 93
 1 40REM Smith Kay 91
 1 99BAR Smith John 100</pre>
&#160;

<strong>使用 sort</strong>

要按指定顺序对 stdin 或文件的内容排序，例如按字母顺序或数字顺序，则可以使用 sort 命令。在默认情况下，sort 的输出写在 stdout 中。LC_ALL、LC_COLLATE 和 LANG 等环境变量可以影响 sort 及其他命令的输出。请注意，示例文件显示了 2 个分离的重复记录，一个重复是 IBM，另一个重复是空行。

<strong>sort 示例：默认行为</strong>

&#160;
<pre class="brush: shell; gutter: true">$ cat &#60;&#60; EOF &#62; dummy_sort1.dat
014 VMW, 102.92
 013 INTC, 22.69
 012 sap, 59.37
 011 IBM, 174.99
 011 IBM, 174.99
EOF
$ sort dummy_sort1.dat
011 IBM, 174.99
 011 IBM, 174.99
 012 sap, 59.37
 013 INTC, 22.69
 014 VMW, 102.92</pre>
&#160;

sort 有一个非常强大的标志，在多数情况下可以代替 uniq 命令。-u 选项标志对文件进行排序，删除重复行，以生成一个只包含惟一行的输出清单。

<strong>sort 示例：惟一排序</strong>

&#160;
<pre class="brush: shell; gutter: true">$ sort -u dummy_sort1.dat
011 IBM, 174.99
 012 sap, 59.37
 013 INTC, 22.69
 014 VMW, 102.92</pre>
&#160;

有时，希望将输入倒序输出。在默认情况下，sort 按从小到大（数字）和字符数据的字母顺序排序。使用 -r 选项标志可以将默认排序倒过来。

<strong>sort 示例：倒序排序</strong>
<pre class="brush: shell; gutter: true">$ sort -ru dummy_sort1.dat
 014 VMW, 102.92
 013 INTC, 22.69
 012 sap, 59.37
 011 IBM, 174.99</pre>
不同情况下，可能要求根据某种域或 “键” 对文件进行排序。幸运的是，sort 的 -k 选项标志支持按位置指定排序键。域之间默认以空格分隔。

<strong>sort 示例：按键排序</strong>

&#160;
<pre class="brush: shell; gutter: true">$ sort -k2 -u dummy_sort1.dat
011 IBM, 174.99
 013 INTC, 22.69
 014 VMW, 102.92
 012 sap, 59.37</pre>
&#160;

如果需要区分大小写，sort 的 -f 选项标志可以在进行比较时忽略大小写。在结合如下所示的多个标志时，有些版本的 UNIX 需要用不同的顺序指定这些标志。
<strong></strong>

<strong>sort 示例：不区分大小写排序</strong>

&#160;
<pre class="brush: shell; gutter: true">$ sort -k2 -f -u dummy_sort1.dat
011 IBM, 174.99
 013 INTC, 22.69
 012 sap, 59.37
 014 VMW, 102.92</pre>
&#160;

以上的排序均是对字母的排序。如果需要按数字顺序对数据排序，则要使用 -n 选项标志。

<strong>sort 示例：按数字排序</strong>

&#160;
<pre class="brush: shell; gutter: true">$ sort -n -k3 -u dummy_sort1.dat
013 INTC, 22.69
 012 sap, 59.37
 014 VMW, 102.92
 011 IBM, 174.99</pre>
&#160;

有些输入可能不使用空格而是使用字符在行中区分域。使用 -t 选项标志指定非默认分隔符，例如逗号。

<strong>sort 示例：使用非默认分隔符对域排序</strong>

&#160;
<pre class="brush: shell; gutter: true">$ sort -k2 -t&#34;,&#34; -un dummy_sort1.dat
013 INTC, 22.69
 012 sap, 59.37
 014 VMW, 102.92
 011 IBM, 174.99</pre>
&#160;

<strong>使用 join</strong>

凡是熟悉数据库查询编写的人，都认得 join 命令这个实用工具。与多数 UNIX 命令一样，这个命令的输出也显示在 stdout 中。要将文件连接 (“join”) 在一起，请逐行比较来自两个文件中指定的域。如果没有指定域，join 则会从每一行的开始进行域区匹配。默认域分隔符是空格（有些系统使用一个空格，有的则使用相邻多个空格）。找到域匹配后，会根据域匹配的两行输出一行结果。要得到合理的结果，每个文件都应该按照匹配的域进行排序。各个系统实现 join 的方式略有不同。

本示例使用 -t 指定域分隔符，并演示了在逗号分隔的第一个域（默认）上对两个文件进行连接。数据库操作人员将其看作是内部连接，只显示匹配的行。

<strong>join 示例：使用非默认域分隔符</strong>

&#160;
<pre class="brush: shell; gutter: true">cat &#60;&#60; EOF &#62; dummy_join1.dat
 011,IBM,Palmisano
 012,INTC,Otellini
 013,SAP,Snabe
 014,VMW,Maritz
 015,ORCL,Ellison
 017,RHT,Whitehurst
 EOF
cat &#60;&#60; EOF &#62; dummy_join2.dat
 011,174.99,14.6
 012,22.69,10.4
 013,59.37,26.4
 014,102.92,106.1
 016,27.77,31.2
 EOF
cat &#60;&#60; EOF &#62; dummy_join3.dat
 IBM,Armonk
 INTC,Santa Clara
 SAP,Walldorf
 VMW,Palo Alto
 ORCL,Redwood City
 EMC,Hopkinton
 EOF
$ join -t, dummy_join1.dat dummy_join2.dat
 011,IBM,Palmisano,174.99,14.6
 012,INTC,Otellini,22.69,10.4
 013,SAP,Snabe,59.37,26.4
 014,VMW,Maritz,102.92,106.1</pre>
&#160;

要指定在每个文件中 “连接” 哪个域，可以使用 -j[1,2] x 选项标志（或者只使用 -1 x 或 -2 x）。选项标志 -j1 2 或 -1 2 指定第 1 个文件的第 2 个域，第 1 个文件是命令中列出的第一个文件。本示例将演示如何根据第 1 个文件的第 1 个域和第 2 个文件的第 2 个域连接文件，这个连接也是内部连接，只连接匹配的行。

<strong>join 示例：指定域</strong>
<pre class="brush: shell; gutter: true">$ join -t, -j1 1 -j2 2 dummy_join3.dat dummy_join1.dat
 IBM,Armonk,011,Palmisano
 INTC,Santa Clara,012,Otellini
 SAP,Walldorf,013,Snabe
 VMW,Palo Alto,014,Maritz
 ORCL,Redwood City,015,Ellison</pre>
与数据库相关示例概念一致，可以用标志实现一个左外连接 (left outer join)。左外连接包含左侧第一个文件或表中的所有行以及第二个文件或表中的匹配行。使用 -a 可以包含指定文件中的所有行。

<strong>join 示例：左外连接</strong>
<pre class="brush: shell; gutter: true">$ join -t, -a1 dummy_join1.dat dummy_join2.dat
 011,IBM,Palmisano,174.99,14.6
 012,INTC,Otellini,22.69,10.4
 013,SAP,Snabe,59.37,26.4
 014,VMW,Maritz,102.92,106.1
 015,ORCL,Ellison
 017,RHT,Whitehurst</pre>
全外连接包含两个文件或表中的所有行，并不关心域是否匹配。可以使用 -a 选项标志指定两个文件来实现全外连接。

<strong>join 示例：全外连接</strong>
<pre class="brush: shell; gutter: true">$ join -t, -a1 -a2 -j1 2 -j2 1 dummy_join1.dat dummy_join3.dat
 IBM,011,Palmisano,Armonk
 INTC,012,Otellini,Santa Clara
 SAP,013,Snabe,Walldorf
 VMW,014,Maritz,Palo Alto
 ORCL,015,Ellison,Redwood City
 EMC,Hopkinton
 017,RHT,Whitehurst</pre>
<strong>使用 sed</strong>

sed 流编辑器 (stream editor) 是个有用的文本解析和操作实用工具，可以方便地进行文件或数据流的转换。它一次一行地读取文本，在文本行中应用指定的命令。默认输出到 stdout。sed 使用的命令可以执行多种操作，如删除缓冲区的文本、将文本附加或插入到缓冲区、写入到一个文件中，以及根据正则表达式转换文本等。

sed 替换的基本示例显示使用 -e 选项标志来指定表达式或编辑文本。在一个 sed 执行中可以指定多个表达式或编辑文本。请注意 sed 文本编辑的组件。文本编辑开始的 “s” 代表这是个替换命令。使用 “/” 作为分隔符，先指明要替换的 “IBM”。接下来，替换模式出现在两个 “/” 分隔符之间。最后，“g” 指明在当前文本缓冲区中进行全局修改。本示例的第三个演示解释了三个文本编辑的组合：用斜杠代替反斜杠，用下划线代替空格，以及删除冒号（请注意其中反斜 杠 “\” 字符的转义表示方式）。

sed 示例：基本替换/多个编辑文本

&#160;
<pre class="brush: shell; gutter: true">$ echo &#34;IBM 174.99&#34; &#124;sed –e &#039;s/IBM/International Business Machines/g&#039;
 International Business Machines 174.99
$ echo &#34;Oracle DB&#34;&#124;sed -e &#039;s/Oracle/IBM/g&#039; -e &#039;s/DB/DB2/g&#039;
 IBM DB2
$ echo &#34;C:\Program Files\PuTTY\putty.exe&#34;&#124; sed -e &#039;s/\\/\//g&#039; -e &#039;s/ /_/g&#039; -e &#039;s/://g&#039;
 C/Program_Files/PuTTY/putty.exe</pre>
&#160;

在下面的示例中，将创建一个文件来演示 sed 的另外一个特性。除了替换之外，筛选也是 sed 常用的功能。UNIX 的 grep 命令是常用的筛选器，在命令行上发现多种文本操作方式很常见。本示例将演示如何使用 sed 删除命令删除以 “#” 或以空格加 “#” 开始的行。同时还列出了采用相同模式的 grep 示例以作参考。

<strong>sed 示例：筛选</strong>

&#160;
<pre class="brush: shell; gutter: true">cat &#60;&#60; EOF &#62; dummy_sed.txt
 # top of file
 # the next line here
 # Last Name, Phone
 Smith, 555-1212
 Jones, 555-5555 # last number
 EOF
$ sed &#039;/^[[:space:]]*#/d&#039; dummy_sed.txt
 Smith, 555-1212
 Jones, 555-5555 # last number
$ grep -v ^[[:space:]]*# dummy_sed.txt
 Smith, 555-1212
 Jones, 555-5555 # last number</pre>
&#160;

为了更好地理解 sed 行为，这里要多演示几个模式。为了让这些模式有文本可处理，还新建了一个文件。第一个 sed 模式显示了如何从文件列出的字符串（文件名）中删除最后 4 个字符。接着，该模式删除圆点 (“.”) 右侧的全部字符，即文件扩展名。还列出一个删除空行的模式。特殊字符 “&#38;” 允许在输出中使用搜索模式。在本示例中，IBM 是输入模式的一部分，并使用 “&#38;” 将其指定为输出的一部分。本系列最后展示的一个模式显示了如何使用 sed 删除从基于 Windows 系统上传输过来的文本文件的回车符。 要在命令行向脚本中输入 “^M”，请先按 control-v，再按 control-m。请注意，终端的特征可能影响 control-v、control-m 组合的输入。

<strong>sed 示例：更多模式</strong>

&#160;
<pre class="brush: shell; gutter: true">cat &#60;&#60; EOF &#62; filelist.txt
 PuTTY.exe
sftp.exe
 netstat.exe
 servernames.list
 EOF
$ sed &#039;s/....$//&#039; filelist.txt
 PuTTY
sftp
 netstat
 servernames.
$ sed &#039;s/\..*$//g&#039; filelist.txt
 PuTTY
sftp
 netstat
 servernames
$ sed &#039;/^$/d&#039; filelist.txt
 PuTTY.exe
 sftp.exe
 netstat.exe
 servernames.list
$ echo &#34;IBM 174.99&#34; &#124;sed &#039;s/IBM/&#38;-International Business Machines/g&#039;
 IBM-International Business Machines 174.99
$ cat dosfile.txt &#124; sed &#039;s/^M//&#039; &#62; unixfile.txt</pre>
&#160;

sed 命令可以在指定的地址范围内操作。下面的示例显示了一些 sed 可以控制的寻址方式。“-n” 选项标志取消 sed 将每行输入显示在输出的默认行为。在第一个示例中，sed 在文件第 4 行到第 7 行上操作。请注意其中如何只显示文件最先列出的表行（行 4 到 7）。接下来，sed 只显示文件中的第一行和最后一行。有些版本的 sed 支持使用模式来指定在命令上应用地址范围。请注意在输出中，只是从表中删除了逗号，并未在注释中删除。

<strong>sed 示例：地址范围</strong>
<pre class="brush: shell; gutter: true">cat &#60;&#60; EOF &#62; dummy_table.frag
    &#60;!--This, is a comment. --&#62;
    &#60;p&#62;This, is a paragraph.&#60;/p&#62;
    &#60;table border=&#34;1&#34;&#62;
    &#60;tr&#62;
    &#60;td&#62;row 1, 1st cell&#60;/td&#62;
    &#60;td&#62;row 1, 2nd cell&#60;/td&#62;
    &#60;/tr&#62;
    &#60;tr&#62;
    &#60;td&#62;row 2, 1st cell&#60;/td&#62;
    &#60;td&#62;row 2, 2nd cell&#60;/td&#62;
    &#60;/tr&#62;
    &#60;/table&#62;
    &#60;!--This, is another comment. --&#62;
    EOF
     
    $ sed -n 4,7p dummy_table.frag
    &#60;tr&#62;
    &#60;td&#62;row 1, 1st cell&#60;/td&#62;
    &#60;td&#62;row 1, 2nd cell&#60;/td&#62;
    &#60;/tr&#62;
     
    $ sed -n -e 1p -e \$p dummy_table.frag
    &#60;!--This, is a comment. --&#62;
    &#60;!--This, is another comment. --&#62;
     
    $ sed &#039;/^&#60;table/,/^&#60;\/table/s/,//g&#039; dummy_table.frag
    &#60;!--This, is a comment. --&#62;
    &#60;p&#62;This, is a paragraph.&#60;/p&#62;
    &#60;table border=&#34;1&#34;&#62;
    &#60;tr&#62;
    &#60;td&#62;row 1 1st cell&#60;/td&#62;
    &#60;td&#62;row 1 2nd cell&#60;/td&#62;
    &#60;/tr&#62;
    &#60;tr&#62;
    &#60;td&#62;row 2 1st cell&#60;/td&#62;
    &#60;td&#62;row 2 2nd cell&#60;/td&#62;
    &#60;/tr&#62;
    &#60;/table&#62;
    &#60;!--This, is another comment. --&#62;</pre>
表达式内的模式可以进行分组，并引用在输出中。在许多环境中，这种做法很有用，例如在进行值交换或使用位置变量时。括号用来在表达式中标记出 模式，必须用反斜杠 \ 转义（模式 \）。在表达式其他地方使用 \n 引用模式，其中 n 是模式在标记模式中的顺序号。将表达式分解后，可以更容易理解它的工作方式：
<strong>模式</strong>                                                              <strong>注解</strong>
/^#.*$/d                                                   从输出中删除以 # 开始的行

/^$/d                                                          从输出中删除空行

s/\([:a-z:]*\):\(.*\) /\2:\1 /             这个语句标记着以冒号结尾的第一串小写字母，然后标记紧接冒号后的字符串。在输出时，这些标记的字符串会交换位置。


<strong>sed 示例：分组模式</strong>
<pre class="brush: shell; gutter: true">cat &#60;&#60; EOF &#62; sed_chown_example.txt
    # use sed to swap the group:owner to owner:group
     
    sudo chown dba:jdoe oraenv.ksh
    sudo chown staff:jdoe sysenv.ksh
    ...
    EOF
     
    $ sed &#039;/^#.*$/d;/^$/d;s/\([:a-z:]*\):\(.*\) /\2:\1 /&#039; sed_chown_example.txt
    sudo chown jdoe:dba oraenv.ksh
    sudo chown jdoe:staff sysenv.ksh
    ...</pre>
<strong>使用 awk</strong>

awk 程序是个方便的文本操作工具，执行的工作包括文本的解析、筛选和简易格式化。它的输入来自 stdin 或文件，默认在 stdout 上显示输出。awk 有不同的发行版，并使用不同的名称，例如 nawk 和 gawk。不同版本和供应商提供的 awk 其行为也各不相同。awk 与本文介绍的其他命令不同，因为它是一个编程语言。该语言内置算术、字符串操作、流程控制以及文本格式化的函数。程序员也可以自己定义函数，创建用户自定义函数库或独立脚本。因为 awk 包含的特性如此之多，所以这里只演示少量的示例。欲了解更多信息，请参阅 参考资料 小节或手册页面。

在本示例中，首先将 awk 作为筛选器，只输出 Linux 系统上的完整文件系统。在默认情况下，awk 使用空白来识别各个列。该示例检查了第 5 列，因为此列显示的是磁盘已用空间百分比。如果磁盘利用率是 100%，则第一个示例会在 stdout 中输出记录。接下来的语句对第一个示例做了扩展，对消息进行格式化，可能要在电子邮件中发送，或者放在消息中写入日志文件。接下来的示例显示如何创建一个使用数值比较的匹配。

<strong>awk 示例：筛选器</strong>
<pre class="brush: shell; gutter: true">   $ df –k
    Filesystem           1K-blocks      Used Available Use% Mounted on
    /dev/sda1             61438632  61381272     57360 100% /
    udev                    255788       148    255640   1% /dev
    /dev/mapper/datavg     6713132   3584984   3128148  54% /data
    rmthost1:/archives/backup    -         -         -   -  /backups
    rmthost1:/archives/          -         -         -   -  /amc
    rmthost1:/archives/data2     -         -         -   -  /data2
     
    $ df -k &#124;awk &#039;$5 ~ /100%/ {print $0}&#039;
    /dev/sda1             61438632  61381272     57360 100% /
     
    $ df -k &#124;awk &#039;$5 ~ /100%/ {printf(&#34;full filesystem: %s, mountpoint: %s\n&#34;,$6,$1)}&#039;
    full filesystem: /, mountpoint: /dev/sda1
     
    $ df -k &#124;awk &#039;$4 &#62; 3000000  {print $0}&#039;
    Filesystem           1K-blocks      Used Available Use% Mounted on
    /dev/mapper/datavg     6713132   3584984   3128148  54% /data</pre>
有时，数据不是用空白分隔的。例如 /etc/passwd 文件就是用冒号 “:” 分隔的。本示例显示了 awk 如何使用 -F 标志输出 /etc/passwd 中前 5 个条目的用户名和 UID。接下来，将通过输出 /etc/passwd 文件中第 1 列的前 3 个字符来展示 awk 的 substr() 函数。

<strong>awk 示例：域分隔符/字符串函数</strong>
<pre class="brush: shell; gutter: true">  $ cat /etc/passwd &#124;awk -F: &#039;{printf(&#34;%s %s\n&#34;, $1,$3)}&#039; &#124;head -5
  root 0
 daemon 1
  bin 2
  sys 3
  adm 4

  cat /etc/passwd &#124;awk -F: &#039;{printf(&#34;%s \n&#34;, substr($1,1,3))}&#039;&#124;head -5
  roo
  dae
  bin
  sys
  adm</pre>
很多时候，系统管理员或程序员会编写自己的 awk 脚本来执行某种作业。下面示例为 awk 程序求文件中第 3 列中发现的数字的平均值。这个计算是通过手动将第 3 列数据添加到汇总变量中。NR 是一个特殊的内部变量，awk 用它来跟踪已经处理的记录数量。将总汇变量除以 NR，就得到了第 3 列的平均值。该程序会显示中间结果和数据，所以很容易理解其中的逻辑。

<strong>awk 示例：程序/算术</strong>
<pre class="brush: shell; gutter: true">  cat &#60;&#60; EOF &#62; dummy_file2.dat
  011 IBM 174.99
  012 INTC 22.78
  013 SAP 59.37
  014 vmw 102.92
  EOF

  $ cat avg.awk
  awk &#039;BEGIN {total=0;}
  {printf(&#34;tot: %.2f arg3: %.2f NR: %d\n&#34;,total, $3, NR); total+=$3;}
  END {printf &#34;Total:%.3f Average:%.3f \n&#34;,total,total/NR}&#039;

  $ cat dummy_file2.dat &#124; avg.awk
 tot: 0.00 arg3: 174.99 NR: 1
  tot: 174.99 arg3: 22.78 NR: 2
  tot: 197.77 arg3: 59.37 NR: 3
  tot: 257.14 arg3: 102.92 NR: 4
  Total:360.060 Average:90.015</pre>
<strong>基于 Shell 的字符串操作</strong>

Shell 可以是强大的编程语言。与 awk 一样，Shell 提供了丰富的选项来执行字符串操作、算术功能、数组、流程控制，以及文件操作。下面的几个示例将显示如何从某一方提取字符串的各个部分。此操作并不改变字 符串的值，只是提取出需要的结果，通常用来对变量赋值。使用百分号 “%” 截断模式的右侧，并用 “#” 号截断模式的左侧。

<strong>Shell 脚本的示例：字符串提取</strong>
<pre class="brush: shell; gutter: true">  $ cat string_example1.sh
  #!/bin/sh
  FILEPATH=/home/w/wyoes/samples/ksh_samples-v1.0.ksh
  echo &#039;${FILEPATH} =&#039; ${FILEPATH} &#34; # the full filepath&#34;
  echo &#039;${#FILEPATH} =&#039; ${#FILEPATH} &#34; # length of the string&#34;
  echo &#039;${FILEPATH%.*} =&#039; ${FILEPATH%.*} &#34; # truncate right of the last dot&#34;
  echo &#039;${FILEPATH%%.*} =&#039; ${FILEPATH%%.*} &#34; # truncate right of the first dot&#34;
  echo &#039;${FILEPATH%%/w*} =&#039; ${FILEPATH%%/w*} &#34; # truncate right of the first /w&#34;
  echo &#039;${FILEPATH#/*/*/} =&#039; ${FILEPATH#/*/*/} &#34; # truncate left of the third slash&#34;
  echo &#039;${FILEPATH##/*/} =&#039; ${FILEPATH##/*/} &#34; # truncate left of the last slash&#34;

   $ ./string_example1.sh
  ${FILEPATH}=/home/w/wyoes/samples/ksh_samples-v1.0.ksh # the full filepath
  ${#FILEPATH} = 42 # length of the string
  ${FILEPATH%.*}=/home/w/wyoes/samples/ksh_samples-v1.0 # truncate right of the last dot
  ${FILEPATH%%.*}=/home/w/wyoes/samples/ksh_samples-v1 # truncate right of the first dot
  ${FILEPATH%%/w*}=/home # truncate right of the first /w
  ${FILEPATH#/*/*/}=wyoes/samples/ksh_samples-v1.0.ksh # truncate left of the third slash
  ${FILEPATH##/*/}=ksh_samples-v1.0.ksh # truncate left of the last slash</pre>
例如，系统管理员可能需要将一批 .jpg 文件的扩展名全部修改成小写字母。因为 UNIX 服务器区分大小写，而有些应用程序可能要求小写扩展名，也有可能管理员只是想将文件扩展名标准化。手动或通过 GUI 界面修改大量文件可能需要几小时才能完成。下面的 shell 样例脚本显示了解决这一问题办法。该示例由两个文件组成。第一个是 setup_files.ksh，用来创建样例目录树并使用一些文件填充树。它还创建了需要修改扩展名的文件列表。第二个脚本 fix_extension.ksh 读取该文件列表，修改文件的扩展名。作为 mv 命令的一部分，% 字符串操作符用来截断文件名最后一个圆点 “.” 右侧的字符（截断扩展名）。在运行之后，两个脚本还使用 find 命令显示成果。

<strong>Shell 脚本示例：修改文件扩展名</strong>
<pre class="brush: shell; gutter: true">  $ cat setup_files.ksh
  mkdir /tmp/mv_demo
  [ ! -d /tmp/mv_demo ] &#38;&#38; exit

  cd /tmp/mv_demo
  mkdir tmp JPG &#039;pictures 1&#039;
 touch a.JPG b.jpg c.Jpg d.jPg M.jpG P.jpg JPG_file.JPG JPG.file2.jPg file1.JPG.Jpg &#039;tmp/
  pic 2.Jpg&#039; 10.JPG.bak &#039;pictures 1/photo.JPG&#039; JPG/readme.txt JPG/sos.JPG

  find . -type f&#124;grep -i &#34;\.jpg$&#34; &#124;sort&#124; tee file_list.txt

  $ ./setup_files.ksh
  ./JPG.file2.jPg
  ./JPG/sos.JPG
  ./JPG_file.JPG
  ./M.jpG
  ./P.jpg
  ./a.JPG
  ./b.jpg
  ./c.Jpg
  ./d.jPg
  ./file1.JPG.Jpg
  ./pictures 1/photo.JPG
  ./tmp/pic 2.Jpg

  $ cd /tmp/mv_demo
  $ cat /tmp/fix_extension.ksh
  while read f ; do
  mv &#34;${f}&#34; &#34;${f%.*}.jpg&#34;
  done &#60; file_list.txt

  find . -type f&#124;grep -i &#34;\.jpg$&#34; &#124;sort

  $ /tmp/fix_extension.ksh
  ./JPG.file2.jpg
  ./JPG/sos.jpg
  ./JPG_file.jpg
  ./M.jpg
  ./P.jpg
  ./a.jpg
  ./b.jpg
  ./c.jpg
  ./d.jpg
 ./file1.JPG.jpg
 ./pictures 1/photo.jpg
  ./tmp/pic 2.jpg</pre>
本着创建有用可重用工具的精神，应该将修改文件扩展名的示例做得更通用。想到的一些改进有：传递进要修改的文件名称流，例如通过管道传递。可 添加选项标志来指定要修改的文件扩展名（例如 .mp3 或 .mov），并指定如何格式化文件扩展名（例如大写、小写，或大小写混合）。可能性只受程序员的想象力和时间的限制。

<strong>结束语</strong>

UNIX 提供了各种以本机方式进行文本解析的工具，在很多情况下，不需要依赖那些系统上可能没有安装的特殊解释器。本文只是宽泛地介绍了各种命令，并未对其用途进 行深入探讨。本文中只对命令进行了部分演示，各个系统上实现的标志或行为可能会各有所异。UNIX 提供了更多命令和方式来实现这些相同的任务，“有不止一种的方式来完成任务”。]]></description>
			<content:encoded><![CDATA[<p><strong>简介</strong></p>
<p>UNIX 的基本哲学之一就是创建只做一件事并将这一件事做好的程序（或进程）。这一哲学要求认真考虑接口以及结合这些更小（有望更简单）流程的方法，以产生有用的 结果。文本数据通常是在这些接口之间流动。多年以来，越来越高级的文本处理工具和语言已经开发出来。从语言上来讲，早期专门处理文本的语言有 perl，后来又出现了 python 和 ruby。虽然这些语言以及其他语言都是非常强大的文本处理器，但这些工具并不是一直可行的，在生产环境下尤其如此。本文将介绍一些基本的 UNIX 文本处理命令，这些命令既可单独使用也可结合使用，可用来解决需要更新的语言才能解决的问题。对许多人来说，与长篇大论的解释相比，实例能够提供更多的信 息。请注意，由于有多种可用的 UNIX 和 UNIX 类系统，因此不同实现之间的命令标志、程序行为和输出结果会略有不同。</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Banni%C3%A8re-Unix-linux.jpg" rel="lightbox[19641]" title="Bannière Unix linux"><img class="aligncenter size-full wp-image-18798" title="Bannière Unix linux" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Banni%C3%A8re-Unix-linux.jpg" alt="" width="640" height="247" /></a></p>
<p><strong>使用 cat</strong></p>
<p>cat 命令是最基本的命令之一。这个命令用来创建、追加、显示以及合并文本文件。</p>
<p>我们可以使用 cat 命令创建文件，方法是：使用 ‘&gt;’ 将标准输入 (stdin) 重定向到文件。使用 ‘&gt;’ 操作符会缩短指定输出文件的内容。在此之后输入的文本会重定向到 ‘&gt;’ 操作符右侧指定的文件。control-d 表示文件结束，将控制权返回给 shell。</p>
<p><strong>使用 cat 创建文件的示例</strong></p>
<pre class="brush: shell; gutter: true">  $ cat &gt; grocery.list
  apples
  bananas
  plums
  &lt;ctrl-d&gt;
  $</pre>
<p>使用 ‘&gt;&gt;’ 操作符将标准输入追加到现有文件。</p>
<p><strong>使用 cat 追加文件的示例</strong></p>
<pre class="brush: shell; gutter: true">$ cat &gt;&gt; grocery.list
 carrots</pre>
<p>使用 cat 命令不加标志，可查看 grocery.list 文件的内容。请注意文件的内容如何包含来自重定向的输入以及追加操作符的示例。</p>
<p><strong>使用无标志 cat 的示例</strong></p>
<pre class="brush: shell; gutter: true">$ cat grocery.list
 apples
 bananas
 plums
 carrots</pre>
<p>可以使用 cat 命令对文件行进行编号。</p>
<p><strong>使用 cat 计算行的示例：</strong></p>
<pre class="brush: shell; gutter: true">$ cat -n grocery.list
 1 apples
 2 bananas
 3 plums
 4 carrots</pre>
<p><strong>使用 nl</strong></p>
<p>nl 过滤器会从 stdin 或指定文件读取行。输出则会写入 stdout 并重定向到文件，或传到另一个进程中。nl 的行为是由不同命令行选项控制的。</p>
<p>在默认情况下，nl 会计算行数，与 cat -n 的功能类似。</p>
<p><strong>nl 默认用法示例：</strong></p>
<pre class="brush: shell; gutter: true">$nl grocery.list
 1 apples
 2 bananas
 3 plums
 4 carrots</pre>
<p>使用 -b 标志指定要进行编号的行。此标志将参数作为 “类型”。该类型告诉 nl 需要给哪些行编号，使用 ‘a’ 给所有行编号，‘t’ 告诉 nl 不对空行和只有空格的行进行编号，‘n’ 指定不编号行。在示例中显示针对模式的类型 ‘p’。nl 给正则表达式模式指定的行编号，在本用例中，是以字母 ‘a’ 或 ‘b’ 开始的行。</p>
<p><strong>使用 nl 对符合正则表达式的行进行编号的示例</strong></p>
<pre class="brush: shell; gutter: true">$ nl -b p^[ba]grocery.list
 1 apples
 2 bananas
 plums
 carrots</pre>
<p>在默认情况下，nl 行号和文本之间使用制表符进行分隔。使用 -s 指定其他分隔符，例如 ‘=’ 号。</p>
<p><strong>使用 nl 指定其他分隔符的示例</strong></p>
<pre class="brush: shell; gutter: true">$nl -s= grocery.list
 1=apples
 2=bananas
 3=plums
 4=carrots</pre>
<p><strong>使用 wc</strong></p>
<p>wc (wordcount) 命令计算指定文件或来自 stdin 的行数、单词数（由空格分隔）和字符数。</p>
<p><strong>wc 用法示例</strong></p>
<pre class="brush: shell; gutter: true">$wc grocery.list
 4 4 29 grocery.list
 $wc -l grocery.list
 4 grocery.list
 $wc -w grocery.list
 4 grocery.list
 $wc -c grocery.list
 29 grocery.list</pre>
<p><strong>使用 grep</strong></p>
<p>grep 命令在指定文件或 stdin 中搜索与给定表达式相匹配的模式。grep 的输出由多个选项标志控制。</p>
<p>为了演示，这里新创建了一个文件，与 grocery.list 配合使用。</p>
<pre class="brush: shell; gutter: true">$cat grocery.list2
 Apple Sauce
 wild rice
 black beans
 kidney beans
 dry apples</pre>
<p><strong>grep 基本用法示例</strong></p>
<pre class="brush: shell; gutter: true">$ grep apple grocery.list grocery.list2
 grocery.list:apples
 grocery.list2:dry apples</pre>
<p>grep 拥有相当可观的选项标志。下面的示例将演示其中几个选项的用法。</p>
<p>要显示文件名（处理多个文件的情况下）以及发现模式匹配的行数，在本用例中使用的模式是计算每个文件中出现单词 ‘apple’ 的行数。</p>
<p><strong>grep 示例：计算文件中匹配数</strong></p>
<pre class="brush: shell; gutter: true">$ grep -c apple grocery.list grocery.list2
 grocery.list:1
 grocery.list2:1</pre>
<p>在搜索多个文件时，可以使用 -h 选项取消在输出中显示文件名。</p>
<p><strong>grep 示例：取消在输出中显示文件名</strong></p>
<pre class="brush: shell; gutter: true">$ grep -h apple grocery.list grocery.list2
 apples
 dry apples</pre>
<p>在很多情况下，需要进行不区分大小写的搜索。grep 命令的 -i 选项可以在搜索时忽略大小写。</p>
<p><strong>grep 示例：不区分大小写</strong></p>
<p>&nbsp;</p>
<pre class="brush: shell; gutter: true">$ grep -i apple grocery.list grocery.list2
grocery.list:apples
 grocery.list2:Apple Sauce
 grocery.list2:dry apples</pre>
<p>&nbsp;</p>
<p>有些时候，只需要输出文件名，不需要输出模式匹配的行。grep 提供 -l 选项，用于只输出包含匹配模式行的文件名。</p>
<p><strong>grep 示例：只输出文件名</strong></p>
<pre class="brush: shell; gutter: true">$ grep -l carrot grocery.list grocery.list2
 grocery.list</pre>
<p>行号可以显示在输出中。使用 -n 选项来包含行号。</p>
<p><strong>grep 示例：包含行号</strong></p>
<pre class="brush: shell; gutter: true">$ grep -n carrot grocery.list grocery.list2
 grocery.list:4:carrots</pre>
<p>有时期望输出与模式不匹配的行。这时就要使用 -v 选项。</p>
<p><strong>grep 示例：输出不匹配行</strong></p>
<pre class="brush: shell; gutter: true">$ grep -v beans grocery.list2
 Apple Sauce
 wild rice
 dry apples</pre>
<p>有时，需要的模式是一个单词，两边被空格或其他字符（例如连字符或括号）包围。grep 的多数版本都提供了 -w 选项，能方便地编写此类模式的搜索。</p>
<p><strong>grep 示例：单词匹配</strong></p>
<pre class="brush: shell; gutter: true">$ grep -w apples grocery.list grocery.list2
 grocery.list:apples
 grocery.list2:dry apples</pre>
<p><strong>流、管道、重定向、tee 和 here docs</strong></p>
<p>在 UNIX 中，一个终端默认包含三个流，一个输入流，两个基于输出的流。输入流称为 stdin，通常映射到键盘（也可使用其他输入设备，或从其他进程中传入）。标准输出流称为 stdout，并通常输出到终端上，输出也可供其他进程使用（就像 stdin 一样）。另一个输出流 stderr 主要用作状态报告，通常输出到终端，如 stdout。这三个流都有各自的文件描述符，每一个流都可以从其他流中传入或重定向，即使是它们全都连接到终端。每个流的文件描述符分别是：</p>
<p>●stdin = 0</p>
<p>●stdout = 1</p>
<p>●stderr = 2</p>
<p>这三个流可以传送或重定向到文件或其他进程。这个构造通常称为 “构建一个管道”。例如，<span class='wp_keywordlink'><a href="http://blog.jobbole.com/821/" title="程序员的本质">程序员</a></span>可能想将 stdout 流和 stderr 流合并，然后在终端上显示它们，再将结果保存到文件中以便检查版本问题。使用 2&gt;&amp;1，stderr 流以及文件描述符 2 会被重定向到 &amp;1（指向 stdout 流）。这样就能有效地将 stderr 合并到 stdout。使用 ‘|’ 符号表示管道。管道连接左侧进程 (make) 的 stdout 和右侧进程 (tee) 的 stdin。tee 命令会复制（合并）将数据发送到终端以及文件的 stdout 流，在本示例中，称为 build.log。</p>
<p><strong>合并和拆分标准流的示例</strong></p>
<pre class="brush: shell; gutter: true">$ make –f build_example.mk 2&gt;&amp;1 | tee build.log</pre>
<p>另一个重定向示例，使用 cat 命令和一些流重定向制作文本文件副本。</p>
<p><strong>使用重定向制作备份文件的示例</strong></p>
<pre class="brush: shell; gutter: true">$ cat &lt; grocery.list &gt; grocery.list.bak</pre>
<p>前面使用 nl 命令为在 stdout 中显示的文件加行号。管道可用于将 stdout 流（来自 cat grocery.list）发送到另外一个进程，在本用例中，是 nl 命令。</p>
<p><strong>简单管道传送到 nl 的示例</strong></p>
<pre class="brush: shell; gutter: true">$ cat grocery.list | nl
 1 apples
 2 bananas
 3 plums
 4 carrots</pre>
<p>先前显示的另一个示例是针对模式执行不区分大小写的搜索。这也可以使用重定向来实现（在这本用例中为来自 stdin 或使用管道，与上述简单管道示例相似）。</p>
<p><strong>grep 示例：通过 stdin 重定向和管道</strong></p>
<pre class="brush: actionscript3; gutter: true">$ grep -i apple &lt; grocery.list2
 Apple Sauce
 dry apples
 $cat grocery.list2 | grep -i apple
 Apple Sauce
 dry apples</pre>
<p>在某些情况下，要将文本块重定向到某个命令或文件中作为脚本的一部分。实现此操作的机制是使用 ‘here document’（或 ‘here-doc’）。要将 here-doc 嵌入到脚本，需要使用 ‘&lt;</p>
<p><strong>示例：命令行上的基本 here-doc</strong></p>
<pre class="brush: shell; gutter: true">$ cat &lt;&lt; EOF 3 &gt; oranges
 &gt; mangos
 &gt; pinapples
 &gt; EOF
 oranges
 mangos
 pinapples</pre>
<p>可将此输出重定向到文件，在本示例中，分隔符 ‘EOF’ 改为 ‘!’。然后使用 tr 命令（稍后说明）将 here-doc 中的字母全部变成大写。</p>
<p><strong>示例：将基本 here-doc 重定向到文件</strong></p>
<pre class="brush: shell; gutter: true">cat &lt;&lt; ! &gt; grocery.list3
 oranges
 mangos
 pinapples
 !
 $ cat grocery.list3
 oranges
 mangos
 pinapples
 $tr [:lower:] [:upper:] &lt;&lt; ! 12 &gt; onions
 &gt; !
 ONIONS</pre>
<p><strong>使用 head 和 tail</strong></p>
<p>head 和 tail 命令用来查看文件的顶部 (head) 或底部 (tail)。要显示文件顶部两行和底部两行，请分别使用这两个命令加 -n 选项标志。相同地，-c 选项显示文件中的前几个或最后几个字符。</p>
<p><strong>示例：head 和 tail 命令的基本用法</strong></p>
<pre class="brush: shell; gutter: true">$ head -n2 grocery.list
 apples
 bananas
 $ tail -n2 grocery.list
 plums
 carrots
 $ head -c12 grocery.list
 apples
 banan
 $ tail -c12 grocery.list
 ums
 carrots</pre>
<p>tail 命令的常见用途就是观察日志文件或者正在运行的进程输出，查看其中是否有问题，或者关注进程何时结束。-f (tail –f) 选项使 tail 持续观察流，即使是到达文件结束标记也继续观察，并在流包含更多数据时，持续显示输出。</p>
<p>使用 tr</p>
<p>tr 命令用来转换来自 stdin 的字符，在 stdout 中显示。tr 一般接受两个字符集合，用第二个集合中的字符替换第一个集合中的字符。有许多预定义的字符类（集合）可供 tr 使用，还有其他命令可用。</p>
<p>这些预定义的字符类是：</p>
<p>●alnum：字母数字字符</p>
<p>●alpha：字母字符</p>
<p>●blank：空白字符</p>
<p>●cntrl：控制字符</p>
<p>●digit：数字字符</p>
<p>●graph：图形字符</p>
<p>●lower：小写字母字符</p>
<p>●print：可打印字符</p>
<p>●punct：标点字符</p>
<p>●space：空间字符</p>
<p>●upper：大写字符</p>
<p>●xdigit：16 进制字符</p>
<p>tr 命令够将字符串中的小写字符转换成大写。</p>
<p><strong>tr 示例：将字符串转换成大写</strong></p>
<pre class="brush: shell; gutter: true">$ echo &quot;Who is the standard text editor?&quot; |tr [:lower:] [:upper:]
 WHO IS THE STANDARD TEXT EDITOR?</pre>
<p>tr 可以用来从字符串中删除指定字符。</p>
<p><strong>tr 示例：从字符串中删除指定字符</strong></p>
<pre class="brush: shell; gutter: true">$ echo &#039;ed, of course!&#039; |tr -d aeiou
 d, f crs!</pre>
<p>使用 tr 将字符串中任何指定字符转换成空格。在序列中遇到多个指定字符时，它们会转换成一个空格。</p>
<p>-s 选项标志的行为在不同系统中表现不同。</p>
<p><strong>tr 示例：将字符转变成空格</strong></p>
<pre class="brush: shell; gutter: true">$ echo &#039;The ed utility is the standard text editor.&#039; |tr -s astu &#039; &#039;
 The ed ili y i he nd rd ex edi or.</pre>
<p>-s 选项标志可以用来取消字符串中多余的空格。</p>
<pre class="brush: shell; gutter: true">$ echo &#039;extra spaces – 5’ | tr -s [:blank:]
 extra spaces - 5
 $ echo ‘extra tabs – 2’ | tr -s [:blank:]
 extra tabs – 2</pre>
<p>在基于 UNIX 和 Windows 系统之间转换文件时发生的常见问题就是行分隔符 (line delimiters)。在 UNIX 系统中，行分隔符为一个换行符，而在 Windows 系统中，则是用两个字符（即一个回车符和一个换行符）。使用 tr 配合某种重定向，可以解决这个格式问题。</p>
<p><strong>tr 示例：消除回车符</strong></p>
<pre class="brush: shell; gutter: true">$ tr -d &#039;\r&#039; &lt; dosfile.txt &gt; unixfile.txt</pre>
<p><strong>使用 colrm</strong></p>
<p>使用 colrm，可以从流中剪切出文本列。在第一个示例中，使用 colrm 命令从管道的每行文本中剪切出第 4 列到行尾。然后，将同一个文件发送至 colrm，以删除第 4 列到第 5 列。</p>
<p><strong>使用 colrm 删除列的示例</strong></p>
<pre class="brush: shell; gutter: true">$ cat grocery.list |colrm 4
 app
 ban
 plu
 car
 $ cat grocery.list |colrm 4 5
 apps
 banas
 plu
 carts</pre>
<p><strong>使用 expand 和 unexpand</strong></p>
<p>expand 命令将制表符变成空格，而 unexpand 将空格变成制表符。这两个命令都接受 stdin 输入以及命令行指定文件的输入。使用 -t 选项可以设置一个或多个制表符停止位。</p>
<p><strong>expand 和 unexpand 示例：</strong></p>
<pre class="brush: shell; gutter: true">$ cat grocery.list|head -2|nl|nl
 1 1 apples
 2 2 bananas
 $ cat grocery.list|head -2|nl|nl|expand -t 5
 1 1 apples
 2 2 bananas
 $ cat grocery.list|head -2|nl|nl|expand -t 5,20
 1 1 apples
 2 2 bananas
 $ cat grocery.list|head -2|nl|nl|expand -t 5,20|unexpand -t 1,5
 1 1 apples
 2 2 bananas</pre>
<p><strong>使用 comm、cmp 和 diff</strong></p>
<p>为了演示这些命令，要新建两个文件。</p>
<p><strong>新建演示文件：</strong></p>
<pre class="brush: shell; gutter: true">cat &lt;&lt; EOF &gt; dummy_file1.dat
 011 IBM 174.99
 012 INTC 22.69
 013 SAP 59.37
 014 VMW 102.92
 EOF
 cat &lt;&lt; EOF &gt; dummy_file2.dat
 011 IBM 174.99
 012 INTC 22.78
 013 SAP 59.37
 014 vmw 102.92
 EOF</pre>
<p>diff 命令会对两个文件进行比较，报告两者之间的不同之处。diff 可接受多种选项标志。在下面示例中，首先显示默认的 diff，然后是使用 -w 选项的 diff 忽略空格，并以使用 -i 选项标志在比较中忽略大小写区别而结束。</p>
<p><strong>diff 命令的示例</strong></p>
<p>&nbsp;</p>
<pre class="brush: shell; gutter: true">$ diff dummy_file1.dat dummy_file2.dat
 1,2c1,2
 &lt; 011 IBM 174.99
 &lt; 012 INTC 22.69 06 --- 07 &gt; 011 IBM 174.99
 &gt; 012 INTC 22.78
 4c4
 &lt; 014 VMW 102.92 11 --- 12 &gt; 014 vmw 102.92
$ diff -w dummy_file1.dat dummy_file2.dat
 2c2
 &lt; 012 INTC 22.69 17 --- 18 &gt; 012 INTC 22.78
 4c4
 &lt; 014 VMW 102.92 21 --- 22 &gt; 014 vmw 102.92
$ diff -i dummy_file1.dat dummy_file2.dat
 1,2c1,2
 &lt; 011 IBM 174.99
 &lt; 012 INTC 22.69 28 --- 29 &gt; 011 IBM 174.99
 &gt; 012 INTC 22.78</pre>
<p>&nbsp;</p>
<p>comm 命令会对两个文件进行比较，但比较的方式与 diff 差别很大。comm 产生三列输出，仅出现在第 1 个文件（第 1 列）的行，仅出现在第 2 个文件（第 2 列）的行，两个文件中都有的常见行（第 3 列）。可使用选项标志来取消输出列。此命令可能在取消第 1 列和第 2 列时最有用，只显示两个文件中常见的行，如下所示。</p>
<p><strong>comm 命令示例</strong></p>
<p>&nbsp;</p>
<pre class="brush: shell; gutter: true">$ comm dummy_file1.dat dummy_file2.dat
 011 IBM 174.99
 011 IBM 174.99
 012 INTC 22.69
 012 INTC 22.78
 013 SAP 59.37
 014 VMW 102.92
 014 vmw 102.92
$ comm -12 dummy_file1.dat dummy_file2.dat
 013 SAP 59.37</pre>
<p>&nbsp;</p>
<p>cmp 命令也会对这两个文件进行比较。但是，与 comm 或 diff 不同，cmp 命令（默认）报告这两个文件刚开始不同的字节和行号。</p>
<p><strong>cmp 命令示例</strong></p>
<pre class="brush: shell; gutter: true">$ cmp dummy_file1.dat dummy_file2.dat
 dummy_file1.dat dummy_file2.dat differ: char 5, line 1</pre>
<p><strong>使用 fold</strong></p>
<p>使用 fold 命令可以将行拆分为指定的宽度。这个命令最初是用来对无法支持换行的定宽输出设备进行文本格式化。-w 选项标志允许使用指定行宽，而不是只使用默认的 80 列。</p>
<p><strong>使用 fold 示例</strong></p>
<pre class="brush: shell; gutter: true">$ fold -w8 dummy_file1.dat
 011 IBM
 174.99
 012 INTC
 22.69
 013 SAP
 59.37
 014 VMW
 102.92</pre>
<p><strong>使用 paste</strong></p>
<p>paste 命令用来合并文件，将每个文件的记录逐一合并。利用重定向，可以通过将一个文件中的每个记录与另一个文件的记录合并，来新建文件。</p>
<p><strong>新建演示文件：</strong></p>
<pre class="brush: shell; gutter: true">cat &lt;&lt; EOF &gt; dummy1.txt
 IBM
 INTC
 SAP
 VMW
 EOF
 cat &lt;&lt; EOF &gt; dummy2.txt
 174.99
 22.69
 59.37
 102.92
 EOF</pre>
<p><strong>paste 示例：来自多文件的行</strong></p>
<pre class="brush: shell; gutter: true">$ paste dummy1.txt dummy2.txt grocery.list
 IBM 174.99 apples
 INTC 22.69 bananas
 SAP 59.37 plums
 VMW 102.92 carrots</pre>
<p>-s 选项标志用来一次处理多个文件（连续地），而不是并行处理。请注意，下面的列与上面示例中的行合并。</p>
<p><strong>paste 示例 2：来自多文件的行</strong></p>
<pre class="brush: shell; gutter: true">$ paste -s dummy1.txt dummy2.txt grocery.list
 IBM INTC SAP VMW
 174.99 22.69 59.37 102.92
 apples bananas plums carrots</pre>
<p>如果只指定一个文件，或者 paste 正处理 stdin，输入会默认显示在一个列中。使用 -s 选项标志，输出会显示在一个行中。由于输出缩减到一行，所以使用分隔符来分隔返回的域（默认的分隔符是制表符）。在本示例中，使用 find 命令寻找 64 位库所在的目录，然后构建一个合适的路径，附加到变量 $LD_LIBRARY_PATH 中。</p>
<p><strong>paste 示例：使用分隔符</strong></p>
<p>&nbsp;</p>
<pre class="brush: shell; gutter: true">$ find /usr -name lib64 -type d|paste -s -d:
 /usr/lib/qt3/lib64:/usr/lib/debug/usr/lib64:/usr/X11R6/lib/X11/locale/lib64:/usr/X11R6/
 lib64:/usr/lib64:/usr/local/ibm/gsk7_64/lib64:/usr/local/lib64
$ paste -d, dummy1.txt dummy2.txt
 IBM,174.99
 INTC,22.69
 SAP,59.37
 VMW,102.92</pre>
<p>&nbsp;</p>
<p><strong>使用 bc</strong></p>
<p>在 Shell 上进行算术计算的简易方法是使用 bc（“basic calculator” 或 “bench calculator”）。有些 shell 自带了算术计算功能，有些则依靠 expr 对表达式进行运算。使用 bc，计算可以在不同的 Shell 和 UNIX 系统间移植，只要注意不同厂商的扩展即可。</p>
<p><strong>bc 示例：简单计算</strong></p>
<p>&nbsp;</p>
<pre class="brush: shell; gutter: true">$ echo 2+3|bc
 5
$ echo 3*3+2|bc
 11
$ VAR1=$(echo 2^8|bc)
 $ echo $VAR1
 256
$ echo &quot;(1+1)^8&quot;|bc
 256</pre>
<p>&nbsp;</p>
<p>bc 不仅可以执行这些简单计算。它是一个解释器，有自己内部的和用户自定义的函数、语法和流程控制，就像<span class='wp_keywordlink'><a href="http://blog.jobbole.com/tag/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/" title="如何选择语言和编程语言排名相关文章">编程语言</a></span>一样。在默认情况下，bc 在小数点右侧不包含任何数字。要提高输出的精度，需要使用特殊的 scale 变量。如示例所示，bc 支持大数字，可实现更长的精度。使用 obase 或 ibase 可以控制输入和输出数字的转换基础。在下面的示例中：</p>
<p>●obase 改变默认的输入基（10 进制），将结果转变成 16 进制</p>
<p>●对于 2 的平方根，scale 指定了小数点右侧的数字个数</p>
<p>●求 2 的 128 次方演示了对大数字的支持</p>
<p>●调用内部函数 sqrt() 计算 2 的平方根</p>
<p>●在 ksh 中，计算和输出百分比</p>
<p><strong>bc 示例：更多计算</strong></p>
<p>&nbsp;</p>
<pre class="brush: shell; gutter: true">$ echo &quot;obase=16; 2^8-1&quot;|bc
 FF
$ echo &quot;99/70&quot;|bc
 1
$ echo &quot;scale=20; 99/70&quot;|bc
 1.41428571428571428571
$ echo &quot;scale=20;sqrt(2)&quot;|bc
 1.41421356237309504880
$ echo 2^128|bc
 340282366920938463463374607431768211456
$ printf &quot;Percentage: %2.2f%%\n&quot; $(echo .9963*100|bc)
 Percentage: 99.63%</pre>
<p>&nbsp;</p>
<p>的手册页面中有详细说明，并有相关示例。</p>
<p><strong>使用 split</strong></p>
<p>split 命令的一大作途就是将大型数据文件分解成小的文件以方便处理。在本示例中，BigFile.dat 经 wc 命令统计有 165782 行。-l 选项标志规定了 split 为每个输出文件生成的最大行数。split 支持为输出文件名指定前缀，例如下面的示例指定 BigFile_ 为前缀。其他选项支持后缀控制，在 BSD 系统上的 -p 选项标志支持按正则表达式进行拆分，就像 csplit（上下文拆分）命令一样。更多信息请参阅手册页面。</p>
<p><strong>split 示例:</strong></p>
<p>&nbsp;</p>
<pre class="brush: shell; gutter: true">$ wc BigFile.dat
 165782 973580 42557440 BigFile.dat
$ split -l 15000 BigFile.dat BigFile_
$ wc BigFile*
 165782 973580 42557440 BigFile.dat
 15000 87835 3816746 BigFile_aa
 15000 88483 3837494 BigFile_ab
 15000 89071 3871589 BigFile_ac
 15000 88563 3877480 BigFile_ad
 15000 88229 3855486 BigFile_ae
 7514 43817 1908914 BigFile_af
 248296 1459578 63725149 total</pre>
<p>&nbsp;</p>
<p><strong>使用 cut</strong></p>
<p>cut 命令用来 &#8220;裁剪&#8221; 文件中以列为基础小节或从 stdin 传送而来的数据。它可按字节 (-b)、字符 (-c) 和列表指定的域 (-f) 进行修剪。使用逗号分隔列表和连字符指定域列表或字节/字符位置。如果只需要输出一个位置或域，则直接指定位置或域即可。可以使用连字符指定一系列域，例 如 1-3 输出 1-3 域（或位置），-2 从行开始前两个域（或字节/字符）开始输出，3- 则让 cut 从域（或位置）3 开始输出到行尾。多个域之间以逗号分隔。其他有用的标志有：-d 指定域分隔符，-s 取消没有分隔符的行。</p>
<p><strong>cut 示例</strong></p>
<p>&nbsp;</p>
<pre class="brush: shell; gutter: true">$ cat &lt;&lt; EOF &gt; dummy_cut.dat
 # this is a data file
 ID,Name,Score
 13BA,John Smith,100
 24BC,Mary Jones,95
 34BR,Larry Jones,94
 36FT,Joe Ruiz,93
 40RM,Kay Smith,91
 EOF
$ cat dummy_cut.dat |cut -d, -f1,3
 # this is a data file
 ID,Score
 13BA,100
 24BC,95
 34BR,94
 36FT,93
 40RM,91
$ cat dummy_cut.dat |cut -b6-
 s is a data file
 me,Score
 John Smith,100
 Mary Jones,95
 Larry Jones,94
 Joe Ruiz,93
 Kay Smith,91
$ cat dummy_cut.dat |cut -f1- -d, -s
 ID,Name,Score
 13BA,John Smith,100
 24BC,Mary Jones,95
 34BR,Larry Jones,94
 36FT,Joe Ruiz,93
 40RM,Kay Smith,91</pre>
<p>&nbsp;</p>
<p><strong>使用 uniq</strong></p>
<p>uniq 命令通常用来惟一地列出输入源（通常是文件或 stdin）中的行。要正确操作，重复的行必须连续放置于输入中。uniq 命令的输入通常会进行排序，因此重复的行会进行合并。与 uniq 命令搭配使用的两个常用标志是：-c 输出每行出现的次数，-d 用来显示重复行的一个实例。</p>
<p><strong>uniq 示例</strong></p>
<p>&nbsp;</p>
<pre class="brush: shell; gutter: true">$ cat &lt;&lt; EOF &gt; dummy_uniq.dat
13BAR Smith John 100
 13BAR Smith John 100
 24BC Jone Mary 95
 34BRR Jones Larry 94
 36FT Ruiz Joe 93
 40REM Smith Kay 91
 13BAR Smith John 100
 99BAR Smith John 100
 13XIV Smith Cindy 91
EOF
$ cat dummy_uniq.dat | uniq
13BAR Smith John 100
 24BC Jone Mary 95
 34BRR Jones Larry 94
 36FT Ruiz Joe 93
 40REM Smith Kay 91
 13BAR Smith John 100
 99BAR Smith John 100
 13XIV Smith Cindy 91
$ cat dummy_uniq.dat | sort |uniq
13BAR Smith John 100
 13XIV Smith Cindy 91
 24BC Jone Mary 95
 34BRR Jones Larry 94
 36FT Ruiz Joe 93
 40REM Smith Kay 91
 99BAR Smith John 100
$ cat dummy_uniq.dat | sort |uniq -d
13BAR Smith John 100
$ cat dummy_uniq.dat | sort |uniq -c
 3
 3 13BAR Smith John 100
 1 13XIV Smith Cindy 91
 1 24BC Jone Mary 95
 1 34BRR Jones Larry 94
 1 36FT Ruiz Joe 93
 1 40REM Smith Kay 91
 1 99BAR Smith John 100</pre>
<p>&nbsp;</p>
<p><strong>使用 sort</strong></p>
<p>要按指定顺序对 stdin 或文件的内容排序，例如按字母顺序或数字顺序，则可以使用 sort 命令。在默认情况下，sort 的输出写在 stdout 中。LC_ALL、LC_COLLATE 和 LANG 等环境变量可以影响 sort 及其他命令的输出。请注意，示例文件显示了 2 个分离的重复记录，一个重复是 IBM，另一个重复是空行。</p>
<p><strong>sort 示例：默认行为</strong></p>
<p>&nbsp;</p>
<pre class="brush: shell; gutter: true">$ cat &lt;&lt; EOF &gt; dummy_sort1.dat
014 VMW, 102.92
 013 INTC, 22.69
 012 sap, 59.37
 011 IBM, 174.99
 011 IBM, 174.99
EOF
$ sort dummy_sort1.dat
011 IBM, 174.99
 011 IBM, 174.99
 012 sap, 59.37
 013 INTC, 22.69
 014 VMW, 102.92</pre>
<p>&nbsp;</p>
<p>sort 有一个非常强大的标志，在多数情况下可以代替 uniq 命令。-u 选项标志对文件进行排序，删除重复行，以生成一个只包含惟一行的输出清单。</p>
<p><strong>sort 示例：惟一排序</strong></p>
<p>&nbsp;</p>
<pre class="brush: shell; gutter: true">$ sort -u dummy_sort1.dat
011 IBM, 174.99
 012 sap, 59.37
 013 INTC, 22.69
 014 VMW, 102.92</pre>
<p>&nbsp;</p>
<p>有时，希望将输入倒序输出。在默认情况下，sort 按从小到大（数字）和字符数据的字母顺序排序。使用 -r 选项标志可以将默认排序倒过来。</p>
<p><strong>sort 示例：倒序排序</strong></p>
<pre class="brush: shell; gutter: true">$ sort -ru dummy_sort1.dat
 014 VMW, 102.92
 013 INTC, 22.69
 012 sap, 59.37
 011 IBM, 174.99</pre>
<p>不同情况下，可能要求根据某种域或 “键” 对文件进行排序。幸运的是，sort 的 -k 选项标志支持按位置指定排序键。域之间默认以空格分隔。</p>
<p><strong>sort 示例：按键排序</strong></p>
<p>&nbsp;</p>
<pre class="brush: shell; gutter: true">$ sort -k2 -u dummy_sort1.dat
011 IBM, 174.99
 013 INTC, 22.69
 014 VMW, 102.92
 012 sap, 59.37</pre>
<p>&nbsp;</p>
<p>如果需要区分大小写，sort 的 -f 选项标志可以在进行比较时忽略大小写。在结合如下所示的多个标志时，有些版本的 UNIX 需要用不同的顺序指定这些标志。<br />
<strong></strong></p>
<p><strong>sort 示例：不区分大小写排序</strong></p>
<p>&nbsp;</p>
<pre class="brush: shell; gutter: true">$ sort -k2 -f -u dummy_sort1.dat
011 IBM, 174.99
 013 INTC, 22.69
 012 sap, 59.37
 014 VMW, 102.92</pre>
<p>&nbsp;</p>
<p>以上的排序均是对字母的排序。如果需要按数字顺序对数据排序，则要使用 -n 选项标志。</p>
<p><strong>sort 示例：按数字排序</strong></p>
<p>&nbsp;</p>
<pre class="brush: shell; gutter: true">$ sort -n -k3 -u dummy_sort1.dat
013 INTC, 22.69
 012 sap, 59.37
 014 VMW, 102.92
 011 IBM, 174.99</pre>
<p>&nbsp;</p>
<p>有些输入可能不使用空格而是使用字符在行中区分域。使用 -t 选项标志指定非默认分隔符，例如逗号。</p>
<p><strong>sort 示例：使用非默认分隔符对域排序</strong></p>
<p>&nbsp;</p>
<pre class="brush: shell; gutter: true">$ sort -k2 -t&quot;,&quot; -un dummy_sort1.dat
013 INTC, 22.69
 012 sap, 59.37
 014 VMW, 102.92
 011 IBM, 174.99</pre>
<p>&nbsp;</p>
<p><strong>使用 join</strong></p>
<p>凡是熟悉数据库查询编写的人，都认得 join 命令这个实用工具。与多数 UNIX 命令一样，这个命令的输出也显示在 stdout 中。要将文件连接 (“join”) 在一起，请逐行比较来自两个文件中指定的域。如果没有指定域，join 则会从每一行的开始进行域区匹配。默认域分隔符是空格（有些系统使用一个空格，有的则使用相邻多个空格）。找到域匹配后，会根据域匹配的两行输出一行结果。要得到合理的结果，每个文件都应该按照匹配的域进行排序。各个系统实现 join 的方式略有不同。</p>
<p>本示例使用 -t 指定域分隔符，并演示了在逗号分隔的第一个域（默认）上对两个文件进行连接。数据库操作人员将其看作是内部连接，只显示匹配的行。</p>
<p><strong>join 示例：使用非默认域分隔符</strong></p>
<p>&nbsp;</p>
<pre class="brush: shell; gutter: true">cat &lt;&lt; EOF &gt; dummy_join1.dat
 011,IBM,Palmisano
 012,INTC,Otellini
 013,SAP,Snabe
 014,VMW,Maritz
 015,ORCL,Ellison
 017,RHT,Whitehurst
 EOF
cat &lt;&lt; EOF &gt; dummy_join2.dat
 011,174.99,14.6
 012,22.69,10.4
 013,59.37,26.4
 014,102.92,106.1
 016,27.77,31.2
 EOF
cat &lt;&lt; EOF &gt; dummy_join3.dat
 IBM,Armonk
 INTC,Santa Clara
 SAP,Walldorf
 VMW,Palo Alto
 ORCL,Redwood City
 EMC,Hopkinton
 EOF
$ join -t, dummy_join1.dat dummy_join2.dat
 011,IBM,Palmisano,174.99,14.6
 012,INTC,Otellini,22.69,10.4
 013,SAP,Snabe,59.37,26.4
 014,VMW,Maritz,102.92,106.1</pre>
<p>&nbsp;</p>
<p>要指定在每个文件中 “连接” 哪个域，可以使用 -j[1,2] x 选项标志（或者只使用 -1 x 或 -2 x）。选项标志 -j1 2 或 -1 2 指定第 1 个文件的第 2 个域，第 1 个文件是命令中列出的第一个文件。本示例将演示如何根据第 1 个文件的第 1 个域和第 2 个文件的第 2 个域连接文件，这个连接也是内部连接，只连接匹配的行。</p>
<p><strong>join 示例：指定域</strong></p>
<pre class="brush: shell; gutter: true">$ join -t, -j1 1 -j2 2 dummy_join3.dat dummy_join1.dat
 IBM,Armonk,011,Palmisano
 INTC,Santa Clara,012,Otellini
 SAP,Walldorf,013,Snabe
 VMW,Palo Alto,014,Maritz
 ORCL,Redwood City,015,Ellison</pre>
<p>与数据库相关示例概念一致，可以用标志实现一个左外连接 (left outer join)。左外连接包含左侧第一个文件或表中的所有行以及第二个文件或表中的匹配行。使用 -a 可以包含指定文件中的所有行。</p>
<p><strong>join 示例：左外连接</strong></p>
<pre class="brush: shell; gutter: true">$ join -t, -a1 dummy_join1.dat dummy_join2.dat
 011,IBM,Palmisano,174.99,14.6
 012,INTC,Otellini,22.69,10.4
 013,SAP,Snabe,59.37,26.4
 014,VMW,Maritz,102.92,106.1
 015,ORCL,Ellison
 017,RHT,Whitehurst</pre>
<p>全外连接包含两个文件或表中的所有行，并不关心域是否匹配。可以使用 -a 选项标志指定两个文件来实现全外连接。</p>
<p><strong>join 示例：全外连接</strong></p>
<pre class="brush: shell; gutter: true">$ join -t, -a1 -a2 -j1 2 -j2 1 dummy_join1.dat dummy_join3.dat
 IBM,011,Palmisano,Armonk
 INTC,012,Otellini,Santa Clara
 SAP,013,Snabe,Walldorf
 VMW,014,Maritz,Palo Alto
 ORCL,015,Ellison,Redwood City
 EMC,Hopkinton
 017,RHT,Whitehurst</pre>
<p><strong>使用 sed</strong></p>
<p>sed 流编辑器 (stream editor) 是个有用的文本解析和操作实用工具，可以方便地进行文件或数据流的转换。它一次一行地读取文本，在文本行中应用指定的命令。默认输出到 stdout。sed 使用的命令可以执行多种操作，如删除缓冲区的文本、将文本附加或插入到缓冲区、写入到一个文件中，以及根据正则表达式转换文本等。</p>
<p>sed 替换的基本示例显示使用 -e 选项标志来指定表达式或编辑文本。在一个 sed 执行中可以指定多个表达式或编辑文本。请注意 sed 文本编辑的组件。文本编辑开始的 “s” 代表这是个替换命令。使用 “/” 作为分隔符，先指明要替换的 “IBM”。接下来，替换模式出现在两个 “/” 分隔符之间。最后，“g” 指明在当前文本缓冲区中进行全局修改。本示例的第三个演示解释了三个文本编辑的组合：用斜杠代替反斜杠，用下划线代替空格，以及删除冒号（请注意其中反斜 杠 “\” 字符的转义表示方式）。</p>
<p>sed 示例：基本替换/多个编辑文本</p>
<p>&nbsp;</p>
<pre class="brush: shell; gutter: true">$ echo &quot;IBM 174.99&quot; |sed –e &#039;s/IBM/International Business Machines/g&#039;
 International Business Machines 174.99
$ echo &quot;Oracle DB&quot;|sed -e &#039;s/Oracle/IBM/g&#039; -e &#039;s/DB/DB2/g&#039;
 IBM DB2
$ echo &quot;C:\Program Files\PuTTY\putty.exe&quot;| sed -e &#039;s/\\/\//g&#039; -e &#039;s/ /_/g&#039; -e &#039;s/://g&#039;
 C/Program_Files/PuTTY/putty.exe</pre>
<p>&nbsp;</p>
<p>在下面的示例中，将创建一个文件来演示 sed 的另外一个特性。除了替换之外，筛选也是 sed 常用的功能。UNIX 的 grep 命令是常用的筛选器，在命令行上发现多种文本操作方式很常见。本示例将演示如何使用 sed 删除命令删除以 “#” 或以空格加 “#” 开始的行。同时还列出了采用相同模式的 grep 示例以作参考。</p>
<p><strong>sed 示例：筛选</strong></p>
<p>&nbsp;</p>
<pre class="brush: shell; gutter: true">cat &lt;&lt; EOF &gt; dummy_sed.txt
 # top of file
 # the next line here
 # Last Name, Phone
 Smith, 555-1212
 Jones, 555-5555 # last number
 EOF
$ sed &#039;/^[[:space:]]*#/d&#039; dummy_sed.txt
 Smith, 555-1212
 Jones, 555-5555 # last number
$ grep -v ^[[:space:]]*# dummy_sed.txt
 Smith, 555-1212
 Jones, 555-5555 # last number</pre>
<p>&nbsp;</p>
<p>为了更好地理解 sed 行为，这里要多演示几个模式。为了让这些模式有文本可处理，还新建了一个文件。第一个 sed 模式显示了如何从文件列出的字符串（文件名）中删除最后 4 个字符。接着，该模式删除圆点 (“.”) 右侧的全部字符，即文件扩展名。还列出一个删除空行的模式。特殊字符 “&amp;” 允许在输出中使用搜索模式。在本示例中，IBM 是输入模式的一部分，并使用 “&amp;” 将其指定为输出的一部分。本系列最后展示的一个模式显示了如何使用 sed 删除从基于 Windows 系统上传输过来的文本文件的回车符。 要在命令行向脚本中输入 “^M”，请先按 control-v，再按 control-m。请注意，终端的特征可能影响 control-v、control-m 组合的输入。</p>
<p><strong>sed 示例：更多模式</strong></p>
<p>&nbsp;</p>
<pre class="brush: shell; gutter: true">cat &lt;&lt; EOF &gt; filelist.txt
 PuTTY.exe
sftp.exe
 netstat.exe
 servernames.list
 EOF
$ sed &#039;s/....$//&#039; filelist.txt
 PuTTY
sftp
 netstat
 servernames.
$ sed &#039;s/\..*$//g&#039; filelist.txt
 PuTTY
sftp
 netstat
 servernames
$ sed &#039;/^$/d&#039; filelist.txt
 PuTTY.exe
 sftp.exe
 netstat.exe
 servernames.list
$ echo &quot;IBM 174.99&quot; |sed &#039;s/IBM/&amp;-International Business Machines/g&#039;
 IBM-International Business Machines 174.99
$ cat dosfile.txt | sed &#039;s/^M//&#039; &gt; unixfile.txt</pre>
<p>&nbsp;</p>
<p>sed 命令可以在指定的地址范围内操作。下面的示例显示了一些 sed 可以控制的寻址方式。“-n” 选项标志取消 sed 将每行输入显示在输出的默认行为。在第一个示例中，sed 在文件第 4 行到第 7 行上操作。请注意其中如何只显示文件最先列出的表行（行 4 到 7）。接下来，sed 只显示文件中的第一行和最后一行。有些版本的 sed 支持使用模式来指定在命令上应用地址范围。请注意在输出中，只是从表中删除了逗号，并未在注释中删除。</p>
<p><strong>sed 示例：地址范围</strong></p>
<pre class="brush: shell; gutter: true">cat &lt;&lt; EOF &gt; dummy_table.frag
    &lt;!--This, is a comment. --&gt;
    &lt;p&gt;This, is a paragraph.&lt;/p&gt;
    &lt;table border=&quot;1&quot;&gt;
    &lt;tr&gt;
    &lt;td&gt;row 1, 1st cell&lt;/td&gt;
    &lt;td&gt;row 1, 2nd cell&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
    &lt;td&gt;row 2, 1st cell&lt;/td&gt;
    &lt;td&gt;row 2, 2nd cell&lt;/td&gt;
    &lt;/tr&gt;
    &lt;/table&gt;
    &lt;!--This, is another comment. --&gt;
    EOF
    
    $ sed -n 4,7p dummy_table.frag
    &lt;tr&gt;
    &lt;td&gt;row 1, 1st cell&lt;/td&gt;
    &lt;td&gt;row 1, 2nd cell&lt;/td&gt;
    &lt;/tr&gt;
    
    $ sed -n -e 1p -e \$p dummy_table.frag
    &lt;!--This, is a comment. --&gt;
    &lt;!--This, is another comment. --&gt;
    
    $ sed &#039;/^&lt;table/,/^&lt;\/table/s/,//g&#039; dummy_table.frag
    &lt;!--This, is a comment. --&gt;
    &lt;p&gt;This, is a paragraph.&lt;/p&gt;
    &lt;table border=&quot;1&quot;&gt;
    &lt;tr&gt;
    &lt;td&gt;row 1 1st cell&lt;/td&gt;
    &lt;td&gt;row 1 2nd cell&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
    &lt;td&gt;row 2 1st cell&lt;/td&gt;
    &lt;td&gt;row 2 2nd cell&lt;/td&gt;
    &lt;/tr&gt;
    &lt;/table&gt;
    &lt;!--This, is another comment. --&gt;</pre>
<p>表达式内的模式可以进行分组，并引用在输出中。在许多环境中，这种做法很有用，例如在进行值交换或使用位置变量时。括号用来在表达式中标记出 模式，必须用反斜杠 \ 转义（模式 \）。在表达式其他地方使用 \n 引用模式，其中 n 是模式在标记模式中的顺序号。将表达式分解后，可以更容易理解它的工作方式：<br />
<strong>模式</strong>                                                              <strong>注解</strong><br />
/^#.*$/d                                                   从输出中删除以 # 开始的行</p>
<p>/^$/d                                                          从输出中删除空行</p>
<p>s/\([:a-z:]*\):\(.*\) /\2:\1 /             这个语句标记着以冒号结尾的第一串小写字母，然后标记紧接冒号后的字符串。在输出时，这些标记的字符串会交换位置。</p>
<p><strong>sed 示例：分组模式</strong></p>
<pre class="brush: shell; gutter: true">cat &lt;&lt; EOF &gt; sed_chown_example.txt
    # use sed to swap the group:owner to owner:group
    
    sudo chown dba:jdoe oraenv.ksh
    sudo chown staff:jdoe sysenv.ksh
    ...
    EOF
    
    $ sed &#039;/^#.*$/d;/^$/d;s/\([:a-z:]*\):\(.*\) /\2:\1 /&#039; sed_chown_example.txt
    sudo chown jdoe:dba oraenv.ksh
    sudo chown jdoe:staff sysenv.ksh
    ...</pre>
<p><strong>使用 awk</strong></p>
<p>awk 程序是个方便的文本操作工具，执行的工作包括文本的解析、筛选和简易格式化。它的输入来自 stdin 或文件，默认在 stdout 上显示输出。awk 有不同的发行版，并使用不同的名称，例如 nawk 和 gawk。不同版本和供应商提供的 awk 其行为也各不相同。awk 与本文介绍的其他命令不同，因为它是一个编程语言。该语言内置算术、字符串操作、流程控制以及文本格式化的函数。程序员也可以自己定义函数，创建用户自定义函数库或独立脚本。因为 awk 包含的特性如此之多，所以这里只演示少量的示例。欲了解更多信息，请参阅 参考资料 小节或手册页面。</p>
<p>在本示例中，首先将 awk 作为筛选器，只输出 Linux 系统上的完整文件系统。在默认情况下，awk 使用空白来识别各个列。该示例检查了第 5 列，因为此列显示的是磁盘已用空间百分比。如果磁盘利用率是 100%，则第一个示例会在 stdout 中输出记录。接下来的语句对第一个示例做了扩展，对消息进行格式化，可能要在电子邮件中发送，或者放在消息中写入日志文件。接下来的示例显示如何创建一个使用数值比较的匹配。</p>
<p><strong>awk 示例：筛选器</strong></p>
<pre class="brush: shell; gutter: true">   $ df –k
    Filesystem           1K-blocks      Used Available Use% Mounted on
    /dev/sda1             61438632  61381272     57360 100% /
    udev                    255788       148    255640   1% /dev
    /dev/mapper/datavg     6713132   3584984   3128148  54% /data
    rmthost1:/archives/backup    -         -         -   -  /backups
    rmthost1:/archives/          -         -         -   -  /amc
    rmthost1:/archives/data2     -         -         -   -  /data2
    
    $ df -k |awk &#039;$5 ~ /100%/ {print $0}&#039;
    /dev/sda1             61438632  61381272     57360 100% /
    
    $ df -k |awk &#039;$5 ~ /100%/ {printf(&quot;full filesystem: %s, mountpoint: %s\n&quot;,$6,$1)}&#039;
    full filesystem: /, mountpoint: /dev/sda1
    
    $ df -k |awk &#039;$4 &gt; 3000000  {print $0}&#039;
    Filesystem           1K-blocks      Used Available Use% Mounted on
    /dev/mapper/datavg     6713132   3584984   3128148  54% /data</pre>
<p>有时，数据不是用空白分隔的。例如 /etc/passwd 文件就是用冒号 “:” 分隔的。本示例显示了 awk 如何使用 -F 标志输出 /etc/passwd 中前 5 个条目的用户名和 UID。接下来，将通过输出 /etc/passwd 文件中第 1 列的前 3 个字符来展示 awk 的 substr() 函数。</p>
<p><strong>awk 示例：域分隔符/字符串函数</strong></p>
<pre class="brush: shell; gutter: true">  $ cat /etc/passwd |awk -F: &#039;{printf(&quot;%s %s\n&quot;, $1,$3)}&#039; |head -5
  root 0
 daemon 1
  bin 2
  sys 3
  adm 4

  cat /etc/passwd |awk -F: &#039;{printf(&quot;%s \n&quot;, substr($1,1,3))}&#039;|head -5
  roo
  dae
  bin
  sys
  adm</pre>
<p>很多时候，系统管理员或程序员会编写自己的 awk 脚本来执行某种作业。下面示例为 awk 程序求文件中第 3 列中发现的数字的平均值。这个计算是通过手动将第 3 列数据添加到汇总变量中。NR 是一个特殊的内部变量，awk 用它来跟踪已经处理的记录数量。将总汇变量除以 NR，就得到了第 3 列的平均值。该程序会显示中间结果和数据，所以很容易理解其中的逻辑。</p>
<p><strong>awk 示例：程序/算术</strong></p>
<pre class="brush: shell; gutter: true">  cat &lt;&lt; EOF &gt; dummy_file2.dat
  011 IBM 174.99
  012 INTC 22.78
  013 SAP 59.37
  014 vmw 102.92
  EOF

  $ cat avg.awk
  awk &#039;BEGIN {total=0;}
  {printf(&quot;tot: %.2f arg3: %.2f NR: %d\n&quot;,total, $3, NR); total+=$3;}
  END {printf &quot;Total:%.3f Average:%.3f \n&quot;,total,total/NR}&#039;

  $ cat dummy_file2.dat | avg.awk
 tot: 0.00 arg3: 174.99 NR: 1
  tot: 174.99 arg3: 22.78 NR: 2
  tot: 197.77 arg3: 59.37 NR: 3
  tot: 257.14 arg3: 102.92 NR: 4
  Total:360.060 Average:90.015</pre>
<p><strong>基于 Shell 的字符串操作</strong></p>
<p>Shell 可以是强大的编程语言。与 awk 一样，Shell 提供了丰富的选项来执行字符串操作、算术功能、数组、流程控制，以及文件操作。下面的几个示例将显示如何从某一方提取字符串的各个部分。此操作并不改变字 符串的值，只是提取出需要的结果，通常用来对变量赋值。使用百分号 “%” 截断模式的右侧，并用 “#” 号截断模式的左侧。</p>
<p><strong>Shell 脚本的示例：字符串提取</strong></p>
<pre class="brush: shell; gutter: true">  $ cat string_example1.sh
  #!/bin/sh
  FILEPATH=/home/w/wyoes/samples/ksh_samples-v1.0.ksh
  echo &#039;${FILEPATH} =&#039; ${FILEPATH} &quot; # the full filepath&quot;
  echo &#039;${#FILEPATH} =&#039; ${#FILEPATH} &quot; # length of the string&quot;
  echo &#039;${FILEPATH%.*} =&#039; ${FILEPATH%.*} &quot; # truncate right of the last dot&quot;
  echo &#039;${FILEPATH%%.*} =&#039; ${FILEPATH%%.*} &quot; # truncate right of the first dot&quot;
  echo &#039;${FILEPATH%%/w*} =&#039; ${FILEPATH%%/w*} &quot; # truncate right of the first /w&quot;
  echo &#039;${FILEPATH#/*/*/} =&#039; ${FILEPATH#/*/*/} &quot; # truncate left of the third slash&quot;
  echo &#039;${FILEPATH##/*/} =&#039; ${FILEPATH##/*/} &quot; # truncate left of the last slash&quot;

   $ ./string_example1.sh
  ${FILEPATH}=/home/w/wyoes/samples/ksh_samples-v1.0.ksh # the full filepath
  ${#FILEPATH} = 42 # length of the string
  ${FILEPATH%.*}=/home/w/wyoes/samples/ksh_samples-v1.0 # truncate right of the last dot
  ${FILEPATH%%.*}=/home/w/wyoes/samples/ksh_samples-v1 # truncate right of the first dot
  ${FILEPATH%%/w*}=/home # truncate right of the first /w
  ${FILEPATH#/*/*/}=wyoes/samples/ksh_samples-v1.0.ksh # truncate left of the third slash
  ${FILEPATH##/*/}=ksh_samples-v1.0.ksh # truncate left of the last slash</pre>
<p>例如，系统管理员可能需要将一批 .jpg 文件的扩展名全部修改成小写字母。因为 UNIX 服务器区分大小写，而有些应用程序可能要求小写扩展名，也有可能管理员只是想将文件扩展名标准化。手动或通过 GUI 界面修改大量文件可能需要几小时才能完成。下面的 shell 样例脚本显示了解决这一问题办法。该示例由两个文件组成。第一个是 setup_files.ksh，用来创建样例目录树并使用一些文件填充树。它还创建了需要修改扩展名的文件列表。第二个脚本 fix_extension.ksh 读取该文件列表，修改文件的扩展名。作为 mv 命令的一部分，% 字符串操作符用来截断文件名最后一个圆点 “.” 右侧的字符（截断扩展名）。在运行之后，两个脚本还使用 find 命令显示成果。</p>
<p><strong>Shell 脚本示例：修改文件扩展名</strong></p>
<pre class="brush: shell; gutter: true">  $ cat setup_files.ksh
  mkdir /tmp/mv_demo
  [ ! -d /tmp/mv_demo ] &amp;&amp; exit

  cd /tmp/mv_demo
  mkdir tmp JPG &#039;pictures 1&#039;
 touch a.JPG b.jpg c.Jpg d.jPg M.jpG P.jpg JPG_file.JPG JPG.file2.jPg file1.JPG.Jpg &#039;tmp/
  pic 2.Jpg&#039; 10.JPG.bak &#039;pictures 1/photo.JPG&#039; JPG/readme.txt JPG/sos.JPG

  find . -type f|grep -i &quot;\.jpg$&quot; |sort| tee file_list.txt

  $ ./setup_files.ksh
  ./JPG.file2.jPg
  ./JPG/sos.JPG
  ./JPG_file.JPG
  ./M.jpG
  ./P.jpg
  ./a.JPG
  ./b.jpg
  ./c.Jpg
  ./d.jPg
  ./file1.JPG.Jpg
  ./pictures 1/photo.JPG
  ./tmp/pic 2.Jpg

  $ cd /tmp/mv_demo
  $ cat /tmp/fix_extension.ksh
  while read f ; do
  mv &quot;${f}&quot; &quot;${f%.*}.jpg&quot;
  done &lt; file_list.txt

  find . -type f|grep -i &quot;\.jpg$&quot; |sort

  $ /tmp/fix_extension.ksh
  ./JPG.file2.jpg
  ./JPG/sos.jpg
  ./JPG_file.jpg
  ./M.jpg
  ./P.jpg
  ./a.jpg
  ./b.jpg
  ./c.jpg
  ./d.jpg
 ./file1.JPG.jpg
 ./pictures 1/photo.jpg
  ./tmp/pic 2.jpg</pre>
<p>本着创建有用可重用工具的精神，应该将修改文件扩展名的示例做得更通用。想到的一些改进有：传递进要修改的文件名称流，例如通过管道传递。可 添加选项标志来指定要修改的文件扩展名（例如 .mp3 或 .mov），并指定如何格式化文件扩展名（例如大写、小写，或大小写混合）。可能性只受程序员的想象力和时间的限制。</p>
<p><strong>结束语</strong></p>
<p>UNIX 提供了各种以本机方式进行文本解析的工具，在很多情况下，不需要依赖那些系统上可能没有安装的特殊解释器。本文只是宽泛地介绍了各种命令，并未对其用途进 行深入探讨。本文中只对命令进行了部分演示，各个系统上实现的标志或行为可能会各有所异。UNIX 提供了更多命令和方式来实现这些相同的任务，“有不止一种的方式来完成任务”。</p>
<h2  class="related_post_title">相关文章</h2><ul class="related_post"><li><a target="_blank" href="http://blog.jobbole.com/18797/" title="陈皓：用Unix的设计思想来应对多变的需求">陈皓：用Unix的设计思想来应对多变的需求</a></li><li><a target="_blank" href="http://blog.jobbole.com/18131/" title="8 个实用的 Linux netcat 命令示例">8 个实用的 Linux netcat 命令示例</a></li><li><a target="_blank" href="http://blog.jobbole.com/16882/" title="Linux中的两种文件锁&#8212;协同锁与强制锁">Linux中的两种文件锁&#8212;协同锁与强制锁</a></li><li><a target="_blank" href="http://blog.jobbole.com/15342/" title="JVM程序员的阅读清单">JVM程序员的阅读清单</a></li><li><a target="_blank" href="http://blog.jobbole.com/8139/" title="10本Linux免费电子书">10本Linux免费电子书</a></li><li><a target="_blank" href="http://blog.jobbole.com/16604/" title="关于 shell 脚本编程的10 个最佳实践">关于 shell 脚本编程的10 个最佳实践</a></li><li><a target="_blank" href="http://blog.jobbole.com/16102/" title="Linux下五个流行的Webmail">Linux下五个流行的Webmail</a></li><li><a target="_blank" href="http://blog.jobbole.com/15493/" title="传说中的开源 vs 现实中的开源 ">传说中的开源 vs 现实中的开源 </a></li><li><a target="_blank" href="http://blog.jobbole.com/15430/" title="你需要知道的16个Linux服务器监控命令">你需要知道的16个Linux服务器监控命令</a></li><li><a target="_blank" href="http://blog.jobbole.com/13219/" title="报告称当前Linux人才抢手 高薪也难觅">报告称当前Linux人才抢手 高薪也难觅</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.jobbole.com/19641/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>22 个免费的图表、流程图工具</title>
		<link>http://blog.jobbole.com/19601/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=22-%25e4%25b8%25aa%25e5%2585%258d%25e8%25b4%25b9%25e7%259a%2584%25e5%259b%25be%25e8%25a1%25a8%25e3%2580%2581%25e6%25b5%2581%25e7%25a8%258b%25e5%259b%25be%25e5%25b7%25a5%25e5%2585%25b7</link>
		<comments>http://blog.jobbole.com/19601/#comments</comments>
		<pubDate>Wed, 16 May 2012 01:40:21 +0000</pubDate>
		<dc:creator>齐哲</dc:creator>
				<category><![CDATA[设计]]></category>
		<category><![CDATA[资源]]></category>
		<category><![CDATA[Web开发]]></category>
		<category><![CDATA[图表]]></category>
		<category><![CDATA[工具]]></category>
		<category><![CDATA[流程图]]></category>

		<guid isPermaLink="false">http://blog.jobbole.com/?p=19601</guid>
		<description><![CDATA[饼图、柱状图、线图和许多其他的图形是非常重要的用来表示数据和沟通的信息，并可展示两个实体之间的关系。而这些图形如果用在 Web 上则有助于吸引访客的注意力，并有效地解释相关数据。 在这里我们推荐一些很棒的工具，你可以通过点击创建非常直观的设计流程图和图表。

<strong><a href="http://www.gliffy.com/" target="_blank">Gliffy<!--more--></a></strong>

使用 Gliffy 可创建非常漂亮的各种图表、流程图、平面图和技术图纸等等。

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts1.jpg"><img class="aligncenter size-full wp-image-19602" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts1.jpg" alt="22 个免费的图表、流程图工具" width="550" height="399" /></a>

<strong><a href="http://www.highcharts.com/" target="_blank">Highcharts</a></strong>

Highcharts是一个制作图表的纯Javascript类库，主要特性如下：

●兼容性：兼容当今所有的浏览器，包括iPhone、IE和火狐等等；

●对个人用户完全免费；

●纯JS，无BS；

●支持大部分的图表类型：直线图，曲线图、区域图、区域曲线图、柱状图、饼装图、散布图；

●跨语言：不管是PHP、Asp.net还是Java都可以使用，它只需要三个文件：一个是Highcharts的核心文件highcharts.js，还有a canvas

●emulator for IE和Jquery类库或者MooTools类库；

●提示功能：鼠标移动到图表的某一点上有提示信息；

●放大功能：选中图表部分放大，近距离观察图表；

●易用性：无需要特殊的开发技能，只需要设置一下选项就可以制作适合自己的图表；

●时间轴：可以精确到毫秒；

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts2.jpg"><img class="aligncenter size-full wp-image-19603" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts2.jpg" alt="22 个免费的图表、流程图工具" width="550" height="432" /></a>

<strong><a href="http://www.barchart.be/index.jsp" target="_blank">Barchart</a></strong>

这是一个用来创建柱状图的工具。

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts3.jpg"><img class="aligncenter size-full wp-image-19604" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts3.jpg" alt="22 个免费的图表、流程图工具" width="550" height="222" /></a>

<strong><a href="http://www.artviper.net/css-chart-generator/create-css-chart.php" target="_blank">CSS Chart Generator</a></strong>

完全使用 Flash 和 XML 构建的图表生成工具。

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts4.jpg"><img class="aligncenter size-full wp-image-19605" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts4.jpg" alt="22 个免费的图表、流程图工具" width="550" height="291" /></a>

<strong><a href="http://www.amblesideprimary.com/ambleweb/mentalmaths/grapher.html" target="_blank">Grapher</a></strong>

非常易用，可点击箭头来创建列，点击标题和数字来修改标题和单位，可右键打印图表。

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts5.jpg"><img class="aligncenter size-full wp-image-19606" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts5.jpg" alt="22 个免费的图表、流程图工具" width="550" height="443" /></a>

<strong><a href="http://charts.hohli.com/#cht=p3&#38;chs=320x240&#38;chd=s:&#38;chf=bg,s,FFFFFF%7Cc,s,FFFFFF&#38;max=100&#38;agent=hohli.com" target="_blank">Hohli Charts</a></strong>

生成动态图表

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts6.jpg"><img class="aligncenter size-full wp-image-19607" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts6.jpg" alt="22 个免费的图表、流程图工具" width="550" height="417" /></a>

<strong><a href="http://dragan.yourtree.org/blog/en/2007/03/31/ajax-mgraph/" target="_blank">MGraph</a></strong>

Ajax MGraph 基于 Prototype.js 的 Ajax 图表库，纯 XHTML 和 CSS 实现。

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts7.jpg"><img class="aligncenter size-full wp-image-19608" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts7.jpg" alt="22 个免费的图表、流程图工具" width="550" height="377" /></a>

<strong><a href="http://flowchart.com/" target="_blank">Flowchart</a></strong>

Flowchart.com 是一个在线多用户、实时协作的流程图服务

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts8.jpg"><img class="aligncenter size-full wp-image-19609" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts8.jpg" alt="22 个免费的图表、流程图工具" width="550" height="315" /></a>

<strong><a href="http://chartgen.blogspot.com/" target="_blank">Online Chart Generator</a></strong>

这是一个最棒的在线图表生成工具，支持三维的图表

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts9.jpg"><img class="aligncenter size-full wp-image-19610" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts9.jpg" alt="22 个免费的图表、流程图工具" width="550" height="211" /></a>

<strong><a href="http://www.diychart.com/" target="_blank">DIY Chart</a></strong>

DIY (Do it yourself) Chart 是一个基于 Web 的简单但强大的在线工具，用来创建交互式的 Web 图表。

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts10.jpg"><img class="aligncenter size-full wp-image-19611" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts10.jpg" alt="22 个免费的图表、流程图工具" width="550" height="338" /></a>

<strong><a href="http://www.maani.us/xml_charts/index.php?menu=Gallery&#38;submenu=Composite" target="_blank">Xml/Swf Charts</a></strong>

XML/SWF Charts 是一个简单但很强大的创建各种吸引人的图表的工具，使用 XML 作为数据传输，使用 Flash 做图表展示。

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts11.jpg"><img class="aligncenter size-full wp-image-19612" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts11.jpg" alt="22 个免费的图表、流程图工具" width="550" height="413" /></a>

<strong><a href="https://cacoo.com/" target="_blank">Cacoo</a></strong>

Cacoo 是一个用户友好的在线图形绘制工具，可创建各种 UML、线框以及网络图。可免费使用！

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts12.jpg"><img class="aligncenter size-full wp-image-19613" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts12.jpg" alt="22 个免费的图表、流程图工具" width="550" height="307" /></a>

<strong><a href="http://webfx.eae.net/dhtml/chart/demo.html" target="_blank">ChartDemo</a></strong>

这里包含很多种形式的图表，无需附加插件，无需图片支持。

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts13.jpg"><img class="aligncenter size-full wp-image-19614" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts13.jpg" alt="22 个免费的图表、流程图工具" width="550" height="323" /></a>

<strong><a href="http://chartgizmo.com/" target="_blank">ChartGizmo</a></strong>

你可通过 ChartGizmo 的免费帐号为网站创建各种图表。

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts14.jpg"><img class="aligncenter size-full wp-image-19615" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts14.jpg" alt="22 个免费的图表、流程图工具" width="550" height="312" /></a>

<strong><a href="http://nces.ed.gov/nceskids/CreateAGraph/default.aspx" target="_blank">CreateAGraph</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts15.jpg"><img class="aligncenter size-full wp-image-19616" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts15.jpg" alt="22 个免费的图表、流程图工具" width="550" height="229" /></a><strong></strong>

&#160;

<strong><a href="http://www.drawanywhere.com/" target="_blank">DrawAnywhere</a></strong>

Draw Anywhere 提供在线的组织结构图、调度和展示图的绘制工具

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts16.jpg"><img class="aligncenter size-full wp-image-19617" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts16.jpg" alt="22 个免费的图表、流程图工具" width="550" height="328" /></a>

<strong><a href="http://piecolor.com/" target="_blank">Piecolor</a></strong>

一个简单的工具用来创建各种效果的饼图

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts17.jpg"><img class="aligncenter size-full wp-image-19618" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts17.jpg" alt="22 个免费的图表、流程图工具" width="550" height="271" /></a>

<strong><a href="http://www.onlinecharttool.com/" target="_blank">Online chart tool</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts18.jpg"><img class="aligncenter size-full wp-image-19619" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts18.jpg" alt="22 个免费的图表、流程图工具" width="550" height="239" /></a>

<strong><a href="http://www.oschina.net/p/yed" target="_blank">YEd Graph Editor</a></strong>

yed 是一个画流程图的工具,不是开源软件，但是可以让你摆脱 Microsoft Office Visio  ,也有linux下的版本，整个程序是java开发的，确实比较强大。

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts19.jpg"><img class="aligncenter size-full wp-image-19620" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts19.jpg" alt="22 个免费的图表、流程图工具" width="550" height="299" /></a>

<strong><a href="http://chartmaker.mathwarehouse.com/create-pie-chart/" target="_blank">Pie Chart Maker</a></strong>

Pie Chart Maker 是一个免费的构建饼图的工具

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts20.jpg"><img class="aligncenter size-full wp-image-19621" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts20.jpg" alt="22 个免费的图表、流程图工具" width="550" height="338" /></a>

<strong><a href="http://fooplot.com/index.php" target="_blank">Fooplot</a></strong>

Plot and graph equations online; lines, circles, parabolas, cubics.

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts21.jpg"><img class="aligncenter size-full wp-image-19622" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts21.jpg" alt="22 个免费的图表、流程图工具" width="550" height="322" /></a>

<strong><a href="http://www.smartdraw.com/specials/smartdraw-charts-graphs-vs-excel.htm?id=330845&#38;gclid=CIqal8bAtp8CFSddagod33e10g" target="_blank">SmartDraw</a></strong>

SmartDraw 是一个桌面软件用来绘制各种图表、UML图等。

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts22.jpg"><img class="aligncenter size-full wp-image-19623" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts22.jpg" alt="22 个免费的图表、流程图工具" width="550" height="240" /></a>

via <a href="http://smashinghub.com/22-useful-free-tools-for-creating-charts-diagrams-and-flowcharts.htm" target="_blank">smashinghub</a>]]></description>
			<content:encoded><![CDATA[<p>饼图、柱状图、线图和许多其他的图形是非常重要的用来表示数据和沟通的信息，并可展示两个实体之间的关系。而这些图形如果用在 Web 上则有助于吸引访客的注意力，并有效地解释相关数据。 在这里我们推荐一些很棒的工具，你可以通过点击创建非常直观的设计流程图和图表。</p>
<p><strong><a href="http://www.gliffy.com/" target="_blank">Gliffy<span id="more-19601"></span></a></strong></p>
<p>使用 Gliffy 可创建非常漂亮的各种图表、流程图、平面图和技术图纸等等。</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts1.jpg" rel="lightbox[19601]" title="22 个免费的图表、流程图工具"><img class="aligncenter size-full wp-image-19602" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts1.jpg" alt="22 个免费的图表、流程图工具" width="550" height="399" /></a></p>
<p><strong><a href="http://www.highcharts.com/" target="_blank">Highcharts</a></strong></p>
<p>Highcharts是一个制作图表的纯Javascript类库，主要特性如下：</p>
<p>●兼容性：兼容当今所有的<span class='wp_keywordlink'><a href="http://blog.jobbole.com/12749/" title="浏览器">浏览器</a></span>，包括iPhone、IE和火狐等等；</p>
<p>●对个人用户完全免费；</p>
<p>●纯JS，无BS；</p>
<p>●支持大部分的图表类型：直线图，曲线图、区域图、区域曲线图、柱状图、饼装图、散布图；</p>
<p>●跨语言：不管是PHP、Asp.net还是Java都可以使用，它只需要三个文件：一个是Highcharts的核心文件highcharts.js，还有a canvas</p>
<p>●emulator for IE和Jquery类库或者MooTools类库；</p>
<p>●提示功能：鼠标移动到图表的某一点上有提示信息；</p>
<p>●放大功能：选中图表部分放大，近距离观察图表；</p>
<p>●易用性：无需要特殊的开发技能，只需要设置一下选项就可以制作适合自己的图表；</p>
<p>●时间轴：可以精确到毫秒；</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts2.jpg" rel="lightbox[19601]" title="22 个免费的图表、流程图工具"><img class="aligncenter size-full wp-image-19603" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts2.jpg" alt="22 个免费的图表、流程图工具" width="550" height="432" /></a></p>
<p><strong><a href="http://www.barchart.be/index.jsp" target="_blank">Barchart</a></strong></p>
<p>这是一个用来创建柱状图的工具。</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts3.jpg" rel="lightbox[19601]" title="22 个免费的图表、流程图工具"><img class="aligncenter size-full wp-image-19604" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts3.jpg" alt="22 个免费的图表、流程图工具" width="550" height="222" /></a></p>
<p><strong><a href="http://www.artviper.net/css-chart-generator/create-css-chart.php" target="_blank">CSS Chart Generator</a></strong></p>
<p>完全使用 Flash 和 XML 构建的图表生成工具。</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts4.jpg" rel="lightbox[19601]" title="22 个免费的图表、流程图工具"><img class="aligncenter size-full wp-image-19605" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts4.jpg" alt="22 个免费的图表、流程图工具" width="550" height="291" /></a></p>
<p><strong><a href="http://www.amblesideprimary.com/ambleweb/mentalmaths/grapher.html" target="_blank">Grapher</a></strong></p>
<p>非常易用，可点击箭头来创建列，点击标题和数字来修改标题和单位，可右键打印图表。</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts5.jpg" rel="lightbox[19601]" title="22 个免费的图表、流程图工具"><img class="aligncenter size-full wp-image-19606" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts5.jpg" alt="22 个免费的图表、流程图工具" width="550" height="443" /></a></p>
<p><strong><a href="http://charts.hohli.com/#cht=p3&amp;chs=320x240&amp;chd=s:&amp;chf=bg,s,FFFFFF%7Cc,s,FFFFFF&amp;max=100&amp;agent=hohli.com" target="_blank">Hohli Charts</a></strong></p>
<p>生成动态图表</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts6.jpg" rel="lightbox[19601]" title="22 个免费的图表、流程图工具"><img class="aligncenter size-full wp-image-19607" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts6.jpg" alt="22 个免费的图表、流程图工具" width="550" height="417" /></a></p>
<p><strong><a href="http://dragan.yourtree.org/blog/en/2007/03/31/ajax-mgraph/" target="_blank">MGraph</a></strong></p>
<p>Ajax MGraph 基于 Prototype.js 的 Ajax 图表库，纯 XHTML 和 CSS 实现。</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts7.jpg" rel="lightbox[19601]" title="22 个免费的图表、流程图工具"><img class="aligncenter size-full wp-image-19608" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts7.jpg" alt="22 个免费的图表、流程图工具" width="550" height="377" /></a></p>
<p><strong><a href="http://flowchart.com/" target="_blank">Flowchart</a></strong></p>
<p>Flowchart.com 是一个在线多用户、实时协作的流程图服务</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts8.jpg" rel="lightbox[19601]" title="22 个免费的图表、流程图工具"><img class="aligncenter size-full wp-image-19609" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts8.jpg" alt="22 个免费的图表、流程图工具" width="550" height="315" /></a></p>
<p><strong><a href="http://chartgen.blogspot.com/" target="_blank">Online Chart Generator</a></strong></p>
<p>这是一个最棒的在线图表生成工具，支持三维的图表</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts9.jpg" rel="lightbox[19601]" title="22 个免费的图表、流程图工具"><img class="aligncenter size-full wp-image-19610" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts9.jpg" alt="22 个免费的图表、流程图工具" width="550" height="211" /></a></p>
<p><strong><a href="http://www.diychart.com/" target="_blank">DIY Chart</a></strong></p>
<p>DIY (Do it yourself) Chart 是一个基于 Web 的简单但强大的在线工具，用来创建交互式的 Web 图表。</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts10.jpg" rel="lightbox[19601]" title="22 个免费的图表、流程图工具"><img class="aligncenter size-full wp-image-19611" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts10.jpg" alt="22 个免费的图表、流程图工具" width="550" height="338" /></a></p>
<p><strong><a href="http://www.maani.us/xml_charts/index.php?menu=Gallery&amp;submenu=Composite" target="_blank">Xml/Swf Charts</a></strong></p>
<p>XML/SWF Charts 是一个简单但很强大的创建各种吸引人的图表的工具，使用 XML 作为数据传输，使用 Flash 做图表展示。</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts11.jpg" rel="lightbox[19601]" title="22 个免费的图表、流程图工具"><img class="aligncenter size-full wp-image-19612" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts11.jpg" alt="22 个免费的图表、流程图工具" width="550" height="413" /></a></p>
<p><strong><a href="https://cacoo.com/" target="_blank">Cacoo</a></strong></p>
<p>Cacoo 是一个用户友好的在线图形绘制工具，可创建各种 UML、线框以及网络图。可免费使用！</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts12.jpg" rel="lightbox[19601]" title="22 个免费的图表、流程图工具"><img class="aligncenter size-full wp-image-19613" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts12.jpg" alt="22 个免费的图表、流程图工具" width="550" height="307" /></a></p>
<p><strong><a href="http://webfx.eae.net/dhtml/chart/demo.html" target="_blank">ChartDemo</a></strong></p>
<p>这里包含很多种形式的图表，无需附加插件，无需图片支持。</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts13.jpg" rel="lightbox[19601]" title="22 个免费的图表、流程图工具"><img class="aligncenter size-full wp-image-19614" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts13.jpg" alt="22 个免费的图表、流程图工具" width="550" height="323" /></a></p>
<p><strong><a href="http://chartgizmo.com/" target="_blank">ChartGizmo</a></strong></p>
<p>你可通过 ChartGizmo 的免费帐号为网站创建各种图表。</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts14.jpg" rel="lightbox[19601]" title="22 个免费的图表、流程图工具"><img class="aligncenter size-full wp-image-19615" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts14.jpg" alt="22 个免费的图表、流程图工具" width="550" height="312" /></a></p>
<p><strong><a href="http://nces.ed.gov/nceskids/CreateAGraph/default.aspx" target="_blank">CreateAGraph</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts15.jpg" rel="lightbox[19601]" title="22 个免费的图表、流程图工具"><img class="aligncenter size-full wp-image-19616" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts15.jpg" alt="22 个免费的图表、流程图工具" width="550" height="229" /></a><strong></strong></p>
<p>&nbsp;</p>
<p><strong><a href="http://www.drawanywhere.com/" target="_blank">DrawAnywhere</a></strong></p>
<p>Draw Anywhere 提供在线的组织结构图、调度和展示图的绘制工具</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts16.jpg" rel="lightbox[19601]" title="22 个免费的图表、流程图工具"><img class="aligncenter size-full wp-image-19617" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts16.jpg" alt="22 个免费的图表、流程图工具" width="550" height="328" /></a></p>
<p><strong><a href="http://piecolor.com/" target="_blank">Piecolor</a></strong></p>
<p>一个简单的工具用来创建各种效果的饼图</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts17.jpg" rel="lightbox[19601]" title="22 个免费的图表、流程图工具"><img class="aligncenter size-full wp-image-19618" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts17.jpg" alt="22 个免费的图表、流程图工具" width="550" height="271" /></a></p>
<p><strong><a href="http://www.onlinecharttool.com/" target="_blank">Online chart tool</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts18.jpg" rel="lightbox[19601]" title="22 个免费的图表、流程图工具"><img class="aligncenter size-full wp-image-19619" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts18.jpg" alt="22 个免费的图表、流程图工具" width="550" height="239" /></a></p>
<p><strong><a href="http://www.oschina.net/p/yed" target="_blank">YEd Graph Editor</a></strong></p>
<p>yed 是一个画流程图的工具,不是开源软件，但是可以让你摆脱 Microsoft Office Visio  ,也有linux下的版本，整个程序是java开发的，确实比较强大。</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts19.jpg" rel="lightbox[19601]" title="22 个免费的图表、流程图工具"><img class="aligncenter size-full wp-image-19620" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts19.jpg" alt="22 个免费的图表、流程图工具" width="550" height="299" /></a></p>
<p><strong><a href="http://chartmaker.mathwarehouse.com/create-pie-chart/" target="_blank">Pie Chart Maker</a></strong></p>
<p>Pie Chart Maker 是一个免费的构建饼图的工具</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts20.jpg" rel="lightbox[19601]" title="22 个免费的图表、流程图工具"><img class="aligncenter size-full wp-image-19621" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts20.jpg" alt="22 个免费的图表、流程图工具" width="550" height="338" /></a></p>
<p><strong><a href="http://fooplot.com/index.php" target="_blank">Fooplot</a></strong></p>
<p>Plot and graph equations online; lines, circles, parabolas, cubics.</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts21.jpg" rel="lightbox[19601]" title="22 个免费的图表、流程图工具"><img class="aligncenter size-full wp-image-19622" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts21.jpg" alt="22 个免费的图表、流程图工具" width="550" height="322" /></a></p>
<p><strong><a href="http://www.smartdraw.com/specials/smartdraw-charts-graphs-vs-excel.htm?id=330845&amp;gclid=CIqal8bAtp8CFSddagod33e10g" target="_blank">SmartDraw</a></strong></p>
<p>SmartDraw 是一个桌面软件用来绘制各种图表、UML图等。</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts22.jpg" rel="lightbox[19601]" title="22 个免费的图表、流程图工具"><img class="aligncenter size-full wp-image-19623" title="22 个免费的图表、流程图工具" src="http://blog.jobbole.com/wp-content/uploads/2012/05/22-Useful-Free-Tools-For-Creating-Charts-Diagrams-and-Flowcharts22.jpg" alt="22 个免费的图表、流程图工具" width="550" height="240" /></a></p>
<p>via <a href="http://smashinghub.com/22-useful-free-tools-for-creating-charts-diagrams-and-flowcharts.htm" target="_blank">smashinghub</a></p>
<h2  class="related_post_title">相关文章</h2><ul class="related_post"><li><a target="_blank" href="http://blog.jobbole.com/1356/" title="45+免费在线工具来创建图表和流程图">45+免费在线工具来创建图表和流程图</a></li><li><a target="_blank" href="http://blog.jobbole.com/17787/" title="对Web开发人员和设计师有用的10个流程图">对Web开发人员和设计师有用的10个流程图</a></li><li><a target="_blank" href="http://blog.jobbole.com/14996/" title="如何选择优秀的Web开发工具/IDE？">如何选择优秀的Web开发工具/IDE？</a></li><li><a target="_blank" href="http://blog.jobbole.com/1355/" title="5个基于Web的建模工具">5个基于Web的建模工具</a></li><li><a target="_blank" href="http://blog.jobbole.com/1282/" title="给设计师推荐16个免费在线工具">给设计师推荐16个免费在线工具</a></li><li><a target="_blank" href="http://blog.jobbole.com/1204/" title="20个云端web开发工具">20个云端web开发工具</a></li><li><a target="_blank" href="http://blog.jobbole.com/848/" title="推荐20款Web设计和开发工具">推荐20款Web设计和开发工具</a></li><li><a target="_blank" href="http://blog.jobbole.com/800/" title="11个完全免费的线框图工具">11个完全免费的线框图工具</a></li><li><a target="_blank" href="http://blog.jobbole.com/732/" title="Diagramly：轻松在网页上绘制流程图">Diagramly：轻松在网页上绘制流程图</a></li><li><a target="_blank" href="http://blog.jobbole.com/16979/" title="省时利器：代码美化与格式化工具">省时利器：代码美化与格式化工具</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.jobbole.com/19601/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adobe、标准和HTML5</title>
		<link>http://blog.jobbole.com/19598/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=adobe%25e3%2580%2581%25e6%25a0%2587%25e5%2587%2586%25e5%2592%258chtml5</link>
		<comments>http://blog.jobbole.com/19598/#comments</comments>
		<pubDate>Tue, 15 May 2012 23:50:41 +0000</pubDate>
		<dc:creator>齐哲</dc:creator>
				<category><![CDATA[IT技术]]></category>
		<category><![CDATA[资讯]]></category>
		<category><![CDATA[adobe]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[浏览器]]></category>

		<guid isPermaLink="false">http://blog.jobbole.com/?p=19598</guid>
		<description><![CDATA[<span style="color: #888888;">“[提供商之间的]最激烈的竞争将与标准密切相关。大部分聪明人的眼睛将紧盯着技术标准。但在计算机行业，新标准既可能是无限财富的源泉，也可能导致企业帝国的毁灭。尽管存在着如此多的风险，标准仍然点燃了无限激情”</span>

<span style="color: #888888;">—The Economist, 1993年2月23日</span>

在编写这段有关标准化的话时，计算领域的主要争议是Unix是否是一个可行的操作系统（以及是否为IBM、DEC和HP的更多专用操作系统带来了挑战），以及哪个视窗平台（SUN/AT&#38;T还是IBM/DEC/HP）将成为标准。Internet已存在标准，但万维网没有。浏览器的标准化甚至还未起步。

我们现在知道，与最近5年相比，作者在1993年看到的行业和他描述的“无限激情”是一个更加稳定和友好（甚至可能和谐）的时期。

但是，作者表达的观点是，标准（尽管平凡且无趣）是将信息和通信技术（ICT）行业凝聚在一起的黏合剂。标准的关键是互操作性和用户效用——它们现在的主要功能是使复杂、异构的系统可行且可满足用户需要。标准化领域现在比以往更加复杂，这在很大程度上离不开万维网的普遍性，这既提高市场的技术复杂性，也提高用户需要和期望。

万维网基本上基于两种标准——HTML和HTTP。HTML是万维网联盟（W3C）的建议标准，HTTP由Internet工程任务组（IETF）提出。

在这两种标准中，HTML更容易在各种消息中看到，因为它在Web内容的创建上占据主导地位。它是定义网络的基本标记语言的规则。使用HTML，异构系统、供应商和产品之间可以进行互操作。HTML4（HTML5的上一版）在HTML3.2推出之后不久推出，保留了自2000年以来主要的HTML形式。正是在这个时间段（2000年以来），网络发生了显著的商业增长。

但是，与ICT行业的方方面面一样，变化发生了。用户开始期望更复杂的功能，各种工具被创建来响应用户的期望和需求。举例而言，在动画领域出现了各种替代方案，到2005年，Macromedia Flash平台成为了用户所期望的和生产商所提供的交互性事实标准（广告、品牌网站、下拉菜单等）。

在市场的不断变化之中，多家浏览器开发商对复兴和改造HTML提供了一种推动力——自上一个HTML版本发布至今已近5年，整个市场也已改变。新产品包括针对多种平台和屏幕尺寸的开源浏览器和移动浏览器，电子发布和电子媒体变得愈加重要，对视觉增强的需要已然凸显出来。

为了响应此需要，多家浏览器开发商启动了一项创建一个更新的HTML版本（称为HTML5）的工作。该工作在W3C外部启动，但最终会转移到W3C内形成更正式的标准化和知识产权保护。（W3C强制要求W3C建议中包含的所有知识产权免费。通过将规范引入W3C，创建者和他们的赞助公司可确保所有他们（以及所有其他贡献者）无法在以后声明版权或创建一个以IP为围墙的花园）。此工作已创建了最新的HTML规范修订版（HTML5）。因为网络是对我们的客户至关重要的平台，所以Adobe向W3C标准化组织同时提供了HTML5的技术资源和知识产权。

但是，因为Adobe是一家工具开发商，而不是浏览器开发商，我们必须像所有工具开发商一样采用一种不同的方法来实现HTML5。浏览器使用HTML5——也就是说，Web浏览器读取HTML文档，然后将文档组合到一个看得见或听得见的显示界面上。Adobe的主要工作是检查HTML5是否“适合工具”。对于Adobe等工具开发商而言，重要的是规范是明确和无歧义的，所有各种实现都是兼容的，减少了创建针对浏览器呈现差异提供了具体调整的HTML5内容的需要。

作为工具开发商，Adobe专注于编写HTML页面的人和这个人在创建内容时的需要，或者专注于生成HTML页面的流程（服务器、工具）。我们收到的客户和用户反馈表明，用户已认识到行业正处于一个重要的过渡期，因为正在创造“新型网络”。旧知识正在被重新审视，新创意正在经历测试。在网络上生成发布质量输出的用户，习惯于像素特定的设计的用户，必须以不同的方式进行思考。现在他们必须创建自适应且可缩放的内容。所以他们会问自己（和Adobe）：您如何控制体验而不控制像素？我们没有听到太多表明该模型是错误的反馈。我们在密切关注着这样一群人，他们尝试获取新工具来执行他们实现富有创意的表达所需的操作。

理想情况下，工具会使创造工作变得更轻松；在这个不断演化的市场中，Adobe面临的一部分挑战是理解用户想从工具中得到什么。用户想要让他们专注于以更快、更轻松、更好或更廉价的方式（或者可预测地，所有上述优势）实现他们的目标的工具。作为工具开发商，Adobe必须高瞻远瞩，摆脱对W3C规范的基本支持。举例而言，性能（包括工具的性能和输出内容的质量）是许多用户的关键考虑因素。如果性能配置文件在不同设备和浏览器之间差别巨大，这可能是与缺乏功能互操作一样巨大的壁垒。随着移动访问变得更加普遍，性能成为了一个尤其重要的问题。

创建Web内容的群体已发展地非常多样性，新标准需要广泛、深入地支持这种多样性。这样做，使Adobe的客户能够拥有生成他们想要的高质量和强大的网站所需的一致性和互操作性。标准所提供的一致通信至关重要，这在它缺乏时非常明显。每个人都还记得（或应该记得）二十世纪90年代中期的Netscape-Microsoft浏览器大战。这是浏览器开发商蓄意添加不兼容竞争对手浏览器的功能的一个事例。这个时代已在一般用户和开发商的抗议中结束。所以，Adobe用户的第一个需求是在这些无处不在的浏览器之间一致的HTML5呈现，一种“编写一次，随处良好运行”模型。

但是，要实现此目标，Adobe在修改和专门化我们的Web产品以利用新功能之前，一直在等待标准的稳定化。我们在开发HTML5工具的过程，还使用了我们跨不同平台（PDF、Flash、HTML、多媒体）的广泛的工具开发经验。与此同时，Adobe的用户可能主要是内容生成者，他们并不真正关心技术规范——他们希望Adobe关注规范，然后开发出最佳的工具供他们表达自己的想法和创造力。他们的问题是，“我们如何使用不断变化的标准所带来的能力表达我们想要什么，我们如何将它们整合到工作流中？”以及，“您能够多快提供这些工具？”

用户需要和需求变得日渐复杂，尤其是在所有一切（比如视频、杂志和电视）变得数字化时。此外，交互式设备的种类比桌面和笔记本时代多得多。现在，屏幕尺寸和文本可见性，以及交互性机制在不同设备上表明应用程序和内容必须采取的形式的方式上各不相同。最近，Adobe展开了一些有趣的讨论，而杂志出版商反馈，他们希望在平板电脑和其他设备上复制他们的高质量印刷出版物。具有类似尺寸的设备类别已然出现。目前，Adobe已开始认识到布局模式可适用于不同的类别。在创建者从一种类别进入另一种时，比如从小型手持设备尺寸进入平板电脑尺寸，再到台式机时，存在一些“断点”。这些设备还有不同的交互模式。用户喜欢与设备独立地创作的想法，但也希望放大每种设备的能力。

与此同时，用户注意到，用户熟悉的丰富的印刷品还未使用HTML5。HTML5/CSS布局标准并不像他们在印刷环境中所熟悉的标准那么完善。为了响应这一区域的用户需要（以及帮助行业创建更丰富的显示效果），Adobe最近向W3C CSS工作组提议了一个CSS3区域模块。另外，由于Adobe客户群的多样性，移动创作在目前对几乎所有客户都至关重要。这已成为了他们的一个重要出路，并且这一趋势正在迅猛地增长（在智能电话和平板电脑上）。例如，Adobe的工具集被出版商用于创作杂志（使用InDesign），我们将为他们提供一种使用标准导出内容并在移动设备上显示的方式。这一切创建满足用户需要的工具紧密相关，而工具离不开稳定的标准。

Adobe用户也关注不断出现的大量规范。再一次，其中一些规范并不仅仅关系到部分客户。它们影响到我们支持什么和不支持什么。作为工具制造商，我们需要满足对有用和适用的工具的需求。我们需要理解用户需求，然后需要确定如何和何时将规范结合起来，使它们变得更强大。当处理CSS区域时，Adobe认识到您可使用它执行有趣的布局，但在与JavaScript结合时能实现更有趣的操作。

Adobe也已开始向WebKit工作做出贡献。上面已经提到，与其说HTML5规范引起了用户的兴趣，倒不如说它们能够实现和运行在HTML5上构建的代码。因此，我们在工具中使用了WebKit，向WebKit引擎贡献了我们的错误修复程序。再次说明，我们旨在通过多种方式使HTML5工具对我们的用户有用。作为我们工作的一个示例，在8月中旬的WebKit提交期间，Adobe的Alexandru Chiculita被得到了如下表彰“……为浮动元素查找添加了 一种新的性能测试 ，它带来了一种优化，在查找浮动元素上带来了大约150%的性能改进。”再次说明，我们旨在通过多种方式使HTML5工具对我们的用户有用。

类似地，借助所有主流浏览器中对SVG的支持，我们注意到我们的用户现在要求Adobe恢复对在已存在多年的Adobe Illustrator中创建SVG的支持。他们还希望我们的所有产品为SVG提供更多支持。此外，来自Adobe实验室的工具Wallaby可从Flash中导出HTML，并同样利用SVG。

矢量图形是构建高保真Web平台的一个重要部分，也是Adobe在网络上实现高保真度呈现的目标的一部分：布局控制、丰富的动画和高质量排印都是缩小差距的重要元素。HTML5有望从“80%的份额”提升到为网络创建富应用程序和内容而“唯一需要的平台”。作为这一推动力量的一部分，有一种使用HTML和CSS创建动画的需要，我们正在开发工具来提供浏览器支持但工具中缺乏的HTML5功能。我们知道我们有能力提供优秀的工具——请访问Adobe Edge，查看来自Adobe的最新示例。

与此同时，我们还开发了The Expressive Web作为供HTML5和CSS开发人员使用的一种资源。因为不是所有浏览器都一致地采用了HTML5的所有功能，我们发现在主流浏览器都认可它们想要使用的大部分功能之前，表明何种功能适用于何处和兼容何种功能（在不兼容时如何做），有助于开发人员实际熟悉HTML5和它的功能，以及它将拥有的缺点。为了帮助用户，Adobe提供了Adobe BrowserLab工具，它允许用户在不同的浏览器和配置上测试Web内容。我们会呈现您的内容，并向您发回图像以显示有效和无效的功能。

在您在浏览器中实现的功能方面，桌面与移动设备之间仍然存在着差距。在设备功能集成或访问上，我们还没有达到相同的丰富程度，但这种差距正在缩小：浏览器中添加了新功能，JavaScript引擎的性能改进了不少。前途是光明的，差距终会消除，但我们还需努力。

我们的传统软件产品拥有悠久的历史，但我们正在努力改进产品来与如今互联的时间更紧密地整合。我们提供了一些试验工作来判断客户反馈，比如在Photoshop Express中，允许通过浏览器和在移动设备上管理图像。您一定会看到我们在此领域的更多成就。

Adobe的意图始终是使用户能够最大化他们的信息和内容的价值和流行。我们不断在开发使对内容的访问更轻松、更迅速、更富表现力和更有价值的工具。因为即使细微的技术更改，对开发工具以及依靠它们的设计人员和开发人员也有巨大的影响，所以Adobe选择比提供试验性呈现器的厂商更缓慢地发展。我们的客户需要摆脱试验，它们希望使用Adobe工具实现此目标。因为我们通过工具来代表我们的用户，所以我们对HTML5的全景拥有与此领域的其他许多厂商不同的独特视角。而且正因为这种不同的、基于工具的视角，我们现在专注于来自W3C的更加成熟和稳定的HTML5建议。
<div class="mceTemp mceIEcenter" style="text-align: center;"><dl id="attachment_19642" class="wp-caption aligncenter" style="width: 170px;"><dt class="wp-caption-dt"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/carl-cargill.png"><img class="size-full wp-image-19642" title="carl cargill" src="http://blog.jobbole.com/wp-content/uploads/2012/05/carl-cargill.png" alt="carl cargill" width="160" height="160" /></a></dt><dd class="wp-caption-dd">作者：Carl Cargill</dd></dl></div>
&#160;

英文原文：<a href="http://www.adobe.com/devnet/html5/articles/adobe-standards-html5.html">http://www.adobe.com/devnet/html5/articles/adobe-standards-html5.html</a>

&#160;]]></description>
			<content:encoded><![CDATA[<p><span style="color: #888888;">“[提供商之间的]最激烈的竞争将与标准密切相关。大部分聪明人的眼睛将紧盯着技术标准。但在计算机行业，新标准既可能是无限财富的源泉，也可能导致企业帝国的毁灭。尽管存在着如此多的风险，标准仍然点燃了无限激情”</span></p>
<p><span style="color: #888888;">—The Economist, 1993年2月23日</span></p>
<p>在编写这段有关标准化的话时，计算领域的主要争议是Unix是否是一个可行的操作系统（以及是否为IBM、DEC和HP的更多专用操作系统带来了挑战），以及哪个视窗平台（SUN/AT&amp;T还是IBM/DEC/HP）将成为标准。Internet已存在标准，但万维网没有。<span class='wp_keywordlink'><a href="http://blog.jobbole.com/12749/" title="浏览器">浏览器</a></span>的标准化甚至还未起步。</p>
<p>我们现在知道，与最近5年相比，作者在1993年看到的行业和他描述的“无限激情”是一个更加稳定和友好（甚至可能和谐）的时期。</p>
<p>但是，作者表达的观点是，标准（尽管平凡且无趣）是将信息和通信技术（ICT）行业凝聚在一起的黏合剂。标准的关键是互操作性和用户效用——它们现在的主要功能是使复杂、异构的系统可行且可满足用户需要。标准化领域现在比以往更加复杂，这在很大程度上离不开万维网的普遍性，这既提高市场的技术复杂性，也提高用户需要和期望。</p>
<p>万维网基本上基于两种标准——HTML和HTTP。HTML是万维网联盟（W3C）的建议标准，HTTP由Internet工程任务组（IETF）提出。</p>
<p>在这两种标准中，HTML更容易在各种消息中看到，因为它在Web内容的创建上占据主导地位。它是定义网络的基本标记语言的规则。使用HTML，异构系统、供应商和产品之间可以进行互操作。HTML4（HTML5的上一版）在HTML3.2推出之后不久推出，保留了自2000年以来主要的HTML形式。正是在这个时间段（2000年以来），网络发生了显著的商业增长。</p>
<p>但是，与ICT行业的方方面面一样，变化发生了。用户开始期望更复杂的功能，各种工具被创建来响应用户的期望和需求。举例而言，在动画领域出现了各种替代方案，到2005年，Macromedia Flash平台成为了用户所期望的和生产商所提供的交互性事实标准（广告、品牌网站、下拉菜单等）。</p>
<p>在市场的不断变化之中，多家浏览器开发商对复兴和改造HTML提供了一种推动力——自上一个HTML版本发布至今已近5年，整个市场也已改变。新产品包括针对多种平台和屏幕尺寸的开源浏览器和移动浏览器，电子发布和电子媒体变得愈加重要，对视觉增强的需要已然凸显出来。</p>
<p>为了响应此需要，多家浏览器开发商启动了一项创建一个更新的HTML版本（称为HTML5）的工作。该工作在W3C外部启动，但最终会转移到W3C内形成更正式的标准化和知识产权保护。（W3C强制要求W3C建议中包含的所有知识产权免费。通过将规范引入W3C，创建者和他们的赞助公司可确保所有他们（以及所有其他贡献者）无法在以后声明版权或创建一个以IP为围墙的花园）。此工作已创建了最新的HTML规范修订版（HTML5）。因为网络是对我们的客户至关重要的平台，所以Adobe向W3C标准化组织同时提供了HTML5的技术资源和知识产权。</p>
<p>但是，因为Adobe是一家工具开发商，而不是浏览器开发商，我们必须像所有工具开发商一样采用一种不同的方法来实现HTML5。浏览器使用HTML5——也就是说，Web浏览器读取HTML文档，然后将文档组合到一个看得见或听得见的显示界面上。Adobe的主要工作是检查HTML5是否“适合工具”。对于Adobe等工具开发商而言，重要的是规范是明确和无歧义的，所有各种实现都是兼容的，减少了创建针对浏览器呈现差异提供了具体调整的HTML5内容的需要。</p>
<p>作为工具开发商，Adobe专注于编写HTML页面的人和这个人在创建内容时的需要，或者专注于生成HTML页面的流程（服务器、工具）。我们收到的客户和用户反馈表明，用户已认识到行业正处于一个重要的过渡期，因为正在创造“新型网络”。旧知识正在被重新审视，新创意正在经历测试。在网络上生成发布质量输出的用户，习惯于像素特定的设计的用户，必须以不同的方式进行思考。现在他们必须创建自适应且可缩放的内容。所以他们会问自己（和Adobe）：您如何控制体验而不控制像素？我们没有听到太多表明该模型是错误的反馈。我们在密切关注着这样一群人，他们尝试获取新工具来执行他们实现富有创意的表达所需的操作。</p>
<p>理想情况下，工具会使创造工作变得更轻松；在这个不断演化的市场中，Adobe面临的一部分挑战是理解用户想从工具中得到什么。用户想要让他们专注于以更快、更轻松、更好或更廉价的方式（或者可预测地，所有上述优势）实现他们的目标的工具。作为工具开发商，Adobe必须高瞻远瞩，摆脱对W3C规范的基本支持。举例而言，性能（包括工具的性能和输出内容的质量）是许多用户的关键考虑因素。如果性能配置文件在不同设备和浏览器之间差别巨大，这可能是与缺乏功能互操作一样巨大的壁垒。随着移动访问变得更加普遍，性能成为了一个尤其重要的问题。</p>
<p>创建Web内容的群体已发展地非常多样性，新标准需要广泛、深入地支持这种多样性。这样做，使Adobe的客户能够拥有生成他们想要的高质量和强大的网站所需的一致性和互操作性。标准所提供的一致通信至关重要，这在它缺乏时非常明显。每个人都还记得（或应该记得）二十世纪90年代中期的Netscape-Microsoft浏览器大战。这是浏览器开发商蓄意添加不兼容竞争对手浏览器的功能的一个事例。这个时代已在一般用户和开发商的抗议中结束。所以，Adobe用户的第一个需求是在这些无处不在的浏览器之间一致的HTML5呈现，一种“编写一次，随处良好运行”模型。</p>
<p>但是，要实现此目标，Adobe在修改和专门化我们的Web产品以利用新功能之前，一直在等待标准的稳定化。我们在开发HTML5工具的过程，还使用了我们跨不同平台（PDF、Flash、HTML、多媒体）的广泛的工具开发经验。与此同时，Adobe的用户可能主要是内容生成者，他们并不真正关心技术规范——他们希望Adobe关注规范，然后开发出最佳的工具供他们表达自己的想法和创造力。他们的问题是，“我们如何使用不断变化的标准所带来的能力表达我们想要什么，我们如何将它们整合到工作流中？”以及，“您能够多快提供这些工具？”</p>
<p>用户需要和需求变得日渐复杂，尤其是在所有一切（比如视频、杂志和电视）变得数字化时。此外，交互式设备的种类比桌面和笔记本时代多得多。现在，屏幕尺寸和文本可见性，以及交互性机制在不同设备上表明应用程序和内容必须采取的形式的方式上各不相同。最近，Adobe展开了一些有趣的讨论，而杂志出版商反馈，他们希望在平板电脑和其他设备上复制他们的高质量印刷出版物。具有类似尺寸的设备类别已然出现。目前，Adobe已开始认识到布局模式可适用于不同的类别。在创建者从一种类别进入另一种时，比如从小型手持设备尺寸进入平板电脑尺寸，再到台式机时，存在一些“断点”。这些设备还有不同的交互模式。用户喜欢与设备独立地创作的想法，但也希望放大每种设备的能力。</p>
<p>与此同时，用户注意到，用户熟悉的丰富的印刷品还未使用HTML5。HTML5/CSS布局标准并不像他们在印刷环境中所熟悉的标准那么完善。为了响应这一区域的用户需要（以及帮助行业创建更丰富的显示效果），Adobe最近向W3C CSS工作组提议了一个CSS3区域模块。另外，由于Adobe客户群的多样性，移动创作在目前对几乎所有客户都至关重要。这已成为了他们的一个重要出路，并且这一趋势正在迅猛地增长（在智能电话和平板电脑上）。例如，Adobe的工具集被出版商用于创作杂志（使用InDesign），我们将为他们提供一种使用标准导出内容并在移动设备上显示的方式。这一切创建满足用户需要的工具紧密相关，而工具离不开稳定的标准。</p>
<p>Adobe用户也关注不断出现的大量规范。再一次，其中一些规范并不仅仅关系到部分客户。它们影响到我们支持什么和不支持什么。作为工具制造商，我们需要满足对有用和适用的工具的需求。我们需要理解用户需求，然后需要确定如何和何时将规范结合起来，使它们变得更强大。当处理CSS区域时，Adobe认识到您可使用它执行有趣的布局，但在与JavaScript结合时能实现更有趣的操作。</p>
<p>Adobe也已开始向WebKit工作做出贡献。上面已经提到，与其说HTML5规范引起了用户的兴趣，倒不如说它们能够实现和运行在HTML5上构建的代码。因此，我们在工具中使用了WebKit，向WebKit引擎贡献了我们的错误修复程序。再次说明，我们旨在通过多种方式使HTML5工具对我们的用户有用。作为我们工作的一个示例，在8月中旬的WebKit提交期间，Adobe的Alexandru Chiculita被得到了如下表彰“……为浮动元素查找添加了 一种新的性能测试 ，它带来了一种优化，在查找浮动元素上带来了大约150%的性能改进。”再次说明，我们旨在通过多种方式使HTML5工具对我们的用户有用。</p>
<p>类似地，借助所有主流浏览器中对SVG的支持，我们注意到我们的用户现在要求Adobe恢复对在已存在多年的Adobe Illustrator中创建SVG的支持。他们还希望我们的所有产品为SVG提供更多支持。此外，来自Adobe实验室的工具Wallaby可从Flash中导出HTML，并同样利用SVG。</p>
<p>矢量图形是构建高保真Web平台的一个重要部分，也是Adobe在网络上实现高保真度呈现的目标的一部分：布局控制、丰富的动画和高质量排印都是缩小差距的重要元素。HTML5有望从“80%的份额”提升到为网络创建富应用程序和内容而“唯一需要的平台”。作为这一推动力量的一部分，有一种使用HTML和CSS创建动画的需要，我们正在开发工具来提供浏览器支持但工具中缺乏的HTML5功能。我们知道我们有能力提供优秀的工具——请访问Adobe Edge，查看来自Adobe的最新示例。</p>
<p>与此同时，我们还开发了The Expressive Web作为供HTML5和CSS开发人员使用的一种资源。因为不是所有浏览器都一致地采用了HTML5的所有功能，我们发现在主流浏览器都认可它们想要使用的大部分功能之前，表明何种功能适用于何处和兼容何种功能（在不兼容时如何做），有助于开发人员实际熟悉HTML5和它的功能，以及它将拥有的缺点。为了帮助用户，Adobe提供了Adobe BrowserLab工具，它允许用户在不同的浏览器和配置上测试Web内容。我们会呈现您的内容，并向您发回图像以显示有效和无效的功能。</p>
<p>在您在浏览器中实现的功能方面，桌面与移动设备之间仍然存在着差距。在设备功能集成或访问上，我们还没有达到相同的丰富程度，但这种差距正在缩小：浏览器中添加了新功能，JavaScript引擎的性能改进了不少。前途是光明的，差距终会消除，但我们还需努力。</p>
<p>我们的传统软件产品拥有悠久的历史，但我们正在努力改进产品来与如今互联的时间更紧密地整合。我们提供了一些试验工作来判断客户反馈，比如在Photoshop Express中，允许通过浏览器和在移动设备上管理图像。您一定会看到我们在此领域的更多成就。</p>
<p>Adobe的意图始终是使用户能够最大化他们的信息和内容的价值和流行。我们不断在开发使对内容的访问更轻松、更迅速、更富表现力和更有价值的工具。因为即使细微的技术更改，对开发工具以及依靠它们的设计人员和开发人员也有巨大的影响，所以Adobe选择比提供试验性呈现器的厂商更缓慢地发展。我们的客户需要摆脱试验，它们希望使用Adobe工具实现此目标。因为我们通过工具来代表我们的用户，所以我们对HTML5的全景拥有与此领域的其他许多厂商不同的独特视角。而且正因为这种不同的、基于工具的视角，我们现在专注于来自W3C的更加成熟和稳定的HTML5建议。</p>
<div class="mceTemp mceIEcenter" style="text-align: center;">
<dl id="attachment_19642" class="wp-caption aligncenter" style="width: 170px;">
<dt class="wp-caption-dt"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/carl-cargill.png" rel="lightbox[19598]" title="carl cargill"><img class="size-full wp-image-19642" title="carl cargill" src="http://blog.jobbole.com/wp-content/uploads/2012/05/carl-cargill.png" alt="carl cargill" width="160" height="160" /></a></dt>
<dd class="wp-caption-dd">作者：Carl Cargill</dd>
</dl>
</div>
<p>&nbsp;</p>
<p>英文原文：<a href="http://www.adobe.com/devnet/html5/articles/adobe-standards-html5.html">http://www.adobe.com/devnet/html5/articles/adobe-standards-html5.html</a></p>
<p>&nbsp;</p>
<h2  class="related_post_title">相关文章</h2><ul class="related_post"><li><a target="_blank" href="http://blog.jobbole.com/1285/" title="Flash播放器：从开创者到“被革命者”">Flash播放器：从开创者到“被革命者”</a></li><li><a target="_blank" href="http://blog.jobbole.com/10132/" title="8款浏览器对HTML5支持评测">8款浏览器对HTML5支持评测</a></li><li><a target="_blank" href="http://blog.jobbole.com/1183/" title="HTML5网页动画工具：Adobe Edge">HTML5网页动画工具：Adobe Edge</a></li><li><a target="_blank" href="http://blog.jobbole.com/19321/" title="HTML5+CSS3+jQuery制作视频播放器完全指南">HTML5+CSS3+jQuery制作视频播放器完全指南</a></li><li><a target="_blank" href="http://blog.jobbole.com/16670/" title="Chromium团队的安全开发核心准则">Chromium团队的安全开发核心准则</a></li><li><a target="_blank" href="http://blog.jobbole.com/17368/" title="PhoneGap开发不可或缺的五件装备">PhoneGap开发不可或缺的五件装备</a></li><li><a target="_blank" href="http://blog.jobbole.com/14146/" title="适合网页设计师的11个不错的Chrome插件 ">适合网页设计师的11个不错的Chrome插件 </a></li><li><a target="_blank" href="http://blog.jobbole.com/13612/" title="开发者须知 HTML5 的15个新特性">开发者须知 HTML5 的15个新特性</a></li><li><a target="_blank" href="http://blog.jobbole.com/13522/" title="Google Web应用开发指南第一章：什么是Web应用？">Google Web应用开发指南第一章：什么是Web应用？</a></li><li><a target="_blank" href="http://blog.jobbole.com/13278/" title="10个出色的HTML5画布示例">10个出色的HTML5画布示例</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.jobbole.com/19598/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HTML特殊字符大全</title>
		<link>http://blog.jobbole.com/19592/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=html%25e7%2589%25b9%25e6%25ae%258a%25e5%25ad%2597%25e7%25ac%25a6%25e5%25a4%25a7%25e5%2585%25a8</link>
		<comments>http://blog.jobbole.com/19592/#comments</comments>
		<pubDate>Tue, 15 May 2012 23:45:36 +0000</pubDate>
		<dc:creator>齐哲</dc:creator>
				<category><![CDATA[设计]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[特殊字符]]></category>

		<guid isPermaLink="false">http://blog.jobbole.com/?p=19592</guid>
		<description><![CDATA[HTML的特殊字符我们并不常用，但是有的时候却要在页面中用到这些字符，甚至有时候还需要用这些字符来实现某种特殊的视觉效果。现在，国外的设计师<a href="http://ikwebdesigner.com/special-characters/">Neal Chester</a>整理了一份很全的特殊字符集，共享出来供大家查阅。

<strong>使用方法：<!--more--></strong>

●这些字符属于unicode字符集，所以，你的文档需要声明为UTF-8；

●下面符号列表的后面有两列编号，它们并不太一样，第一列是用于HTML的，你需要在前面加上&#38;#符号；

●第二列可以用于CSS文件中，但是需要用反斜杠\转义；

●第二列也可以用于JavaScript，和CSS用法一样，不过要用\u来转义。

<strong>需要主意的是：</strong>

●有的字符在不同的浏览器下表现不太一样；比如小雪人 ☃ 在Firefox和Chrome下不太一样，钻石 ◆ 在IE下要比Chrome下要大一点儿；

●有的字符在某个浏览器下不会显示；当然原因并不是字符代码的问题，而是浏览器的bug，比如，–在Chrome下。。。

●但是，98%的字符都能在所有浏览器下正常显示的，不过如果你真的要使用，最好仔细在各个浏览器下验证一番。

●经测试这些字符在Android/iOS等智能终端的识别度比较差，所以，使用的时候要特别注意移动浏览器～～

<strong>各种箭头</strong>

●     ⇠     8672 21E0

●     ⇢     8674 21E2

●    ⇡        8673 21E1

●    ⇣        8675 21E3

●   ↞       8606 219E

●   ↠       8608 21A0

●    ↟        8607 219F

●    ↡        8609 21A1

●    ←      8592 2190

●    →      8594 2192

●     ↑       8593 2191

●     ↓       8595 2193

●    ↔      8596 2194

●      ↕      8597 2195

●     ⇄     8644 21C4

●     ⇅      8645 21C5

●     ↢     8610 21A2

●    ↣      8611 21A3

●    ⇞        8670 21DE

●     ⇟      8671 21DF

●     ↫      8619 21AB

●     ↬      8620 21AC

●     ⇜      8668 21DC

●     ⇝      8669 21DD

●     ↚      8602 219A

●     ↛      8603 219B

●     ↮      8622 21AE

●     ↭      8621 21AD

<strong>形状</strong>

●     ⇦      8678 21E6

●     ⇨      8680 21E8

●     ⇧      8679 21E7

●     ⇩      8681 21E9

●     ↷      8631 21B7

●     ↶      8630 21B6

●     ↻      8635 21BB

●     ↺      8634 21BA

●     ⟳      10227 27F3

●     ⟲      10226 27F2

●     ⟰      10224 27F0

●     ⟱      10225 27F1

●     ↵      8629 21B5

●     ↯      8623 21AF

●     ⇵      8693 21F5

<strong>向右的箭头</strong>

●     ➔      10132 2794

●     ➙      10137 2799

●     ➨      10152 27A8

●     ➲      10162 27B2

●     ➜      10140 279C

●     ➞      10142 279E

●     ➟      10143 279F

●     ➠      10144 27A0

●     ➤      10148 27A4

●     ➥      10149 27A5

●     ➦      10150 27A6

●     ➧      10151 27A7

●     ➵      10165 27B5

●     ➸      10168 27B8

●     ➼      10172 27BC

●     ➽      10173 27BD

●     ➺      10170 27BA

●     ➳      10163 27B3

●     ➾      10174 27BE

<strong>基本形状</strong>

●     ▲      9650 25B2

●     ►      9658 25BA

●     ▼      9660 25BC

●     ◄      9668 25C4

●     ❤      10084 2764

●     ✈      9992 2708

●     ★      9733 2605

●     ✦      10022 2726

●     ☀      9728 2600

●     ◆      9670 25C6

●     ◈      9672 25C8

●     ▣      9635 25A3

<strong>标点</strong>

●     «      171 00AB

●     »      187 00BB

●     ‹      139 008B

●     ›      155 009B

●     “      8220 201C

●     ”      8221 201D

●     ‘      8216 2018

●     ’      8217 2019

●     •      8226 2022

●     ◦      9702 25E6

●     ¡      161 00A1

●     ¿      191 00BF

●     ℅      8453 2105

●     №      8470 2116

●     &#38;      38 0026

●     @      64 0040

●     ℞      8478 211E

●     ℃      8451 2103

●     ℉      8457 2109

●     °      176 00B0

●     &#124;      124 007C

●     ¦      166 00A6

●     –      8211 2013

●     —      8212 2014

●     …      8230 2026

●     ¶      182 00B6

●     ∼      8764 223C

●     ≠      8800 2260

<strong>法律符号</strong>

●     ®      174 00AE

●     ©      169 00A9

●     ℗      8471 2117

●     ™      153 0099

●     ℠      8480 2120

<strong>货币</strong>

●     $      36 0024

●     ¢      162 00A2

●     £      163 00A3

●     ¤      164 00A4

●     €      8364 20AC

●     ¥      165 00A5

●     ₱      8369 20B1

●     ₹      8377 20B9

<strong>数学</strong>

●     ½      189 00BD

●     ¼      188 00BC

●     ¾      190 00BE

●     ⅓      8531 2153

●     ⅔      8532 2154

●     ⅛      8539 215B

●     ⅜      8540 215C

●     ⅝      8541 215D

●     ‰      8240 2030

●     %      37 0025

●     &#60;      60 003C

●     &#62;      62 003E

<strong>音乐符号</strong>

●     ♩      9833 2669

●     ♪      9834 266A

●     ♫      9835 266B

●     ♬      9836 266C

●     ♭      9837 266D

●     ♯      9839 266F

<strong>对号、错号</strong>

●               160 00A0

●     ☐      9744 2610

●     ☑      9745 2611

●     ☒      9746 2612

●     ✓      10003 2713

●     ✔      10004 2714

●     ✕      10005 10005

●     ✖      10006 2716

●     ✗      10007 2717

●     ✘      10008 2718

<strong>十字</strong>

●     ☨      9768 2628

●     ☩      9769 2629

●     ✝      10013 271D

●     ✞      10014 271E

●     ✟      10015 271F

●     ✠      10016 2720

●     ✚      10010 271A

●     †      8224 2020

●     ✢      10018 2722

●     ✤      10020 2724

●     ✣      10019 2723

●     ✥      10021 2725

<strong>星星、星号、雪花</strong>

●     ★      9733 2605

●     ✭      10029 272D

●     ✮      10030 272E

●     ☆      9734 2606

●     ✪      10026 272A

●     ✡      10017 2721

●     ✯      10031 272F

●     ✵      10037 2735

●     ✶      10038 2736

●     ✸      10040 2738

●     ✹      10041 2739

●     ✺      10042 273A

●     ✱      10033 2731

●     ✲      10034 2732

●     ✴      10036 2734

●     ✳      10035 2733

●     ✻      10043 273B

●     ✽      10045 273D

●     ❋      10059 274B

●     ❆      10054 2746

●     ❄      10052 2744

●     ❅      10053 2745

<strong>杂项</strong>

●     ☻      9787 263B

●     ☺      9786 263A

●     ☹      9785 2639

●     ✉      9993 2709

●     ☎      9742 260E

●     ☏      9743 260F

●     ✆      9990 2706

●     �      65533 FFFD

●     ☁      9729 2601

●     ☂      9730 2602

●     ❄      10052 2744

●     ☃      9731 2603

●     ❈      10056 2748

●     ✿      10047 273F

●     ❀      10048 2740

●     ❁      10049 2741

●     ☘      9752 2618

●     ❦      10086 2766

●     ☕      9749 9749

●     ❂      10050 2742

●     ☥      9765 2625

●     ☮      9774 262E

●     ☯      9775 262F

●     ☪      9770 262A

●     ☤      9764 2624

●     ✄      9988 2704

●     ✂      9986 2702

●     ☸      9784 2638

●     ⚓      9875 2693

●     ☣      9763 2623

●     ⚠      9888 26A0

●     ⚡      9889 26A1

●     ☢      9762 2622

●     ♻      9851 267B

●     ♿      9855 267F

●     ☠      9760 2620

<strong>手型、铅笔、笔</strong>

●     ☜      9756 261C

●     ☞      9758 261E

●     ☝      9757 261D

●     ☟      9759 261F

●     ✌      9996 270C

●     ✍      9997 270D

●     ✎      9998 270E

●     ✐      10000 2710

●     ✏      9999 270F

●     ✑      10001 2711

●     ✒      10002 2712

<strong>天空、植物</strong>

●     ☽      9789 263D

●     ☾      9790 263E

●     ♂      9794 2642

●     ♀      9792 2640

●     ☿      9791 263F

●     ♁      9793 2641

●     ♃      9795 2643

●     ♄      9796 2644

●     ♅      9797 2645

●     ♆      9798 2646

●     ♇      9799 2647

<strong>星座</strong>

●     ♈      9800 2648

●     ♉      9801 2649

●     ♊      9802 264A

●     ♋      9803 264B

●     ♌      9804 264C

●     ♍      9805 264D

●     ♎      9806 264E

●     ♏      9807 264F

●     ♑      9809 2651

●     ♒      9810 2652

●     ♓      9811 2653

<strong>象棋，扑克牌</strong>

●     ♚      9818 265A

●     ♛      9819 265B

●     ♜      9820 265C

●     ♝      9821 265D

●     ♞      9822 265E

●     ♟      9823 265F

●     ♔      9812 2654

●     ♕      9813 2655

●     ♖      9814 2656

●     ♗      9815 2657

●     ♘      9816 2658

●     ♙      9817 2659

●     ♠      9824 2660

●     ♣      9827 2663

●     ♥      9829 2665

●     ♦      9830 2666

●     ♤      9828 2664

●     ♧      9831 2667

●     ♡      9825 2661

●     ♢      9826 2662

<strong>希腊字母</strong>

●     Α      913 0391

●     Β      914 0392

●     Γ      915 0393

●     Δ      916 0394

●     Ε      917 0395

●     Ζ      918 0396

●     Η      919 0397

●     Θ      920 0398

●     Ι      921 0399

●     Κ      922 039A

●     Λ      923 039B

●     Μ      924 039C

●     Ν      925 039D

●     Ξ      926 039E

●     Ο      927 039F

●     Π      928 03A0

●     Ρ      929 03A1

●     Σ      931 03A3

●     Τ      932 03A4

●     Υ      933 03A5

●     Φ      934 03A6

●     Χ      935 03A7

●     Ψ      936 03A8

●     Ω      937 03A9]]></description>
			<content:encoded><![CDATA[<p>HTML的特殊字符我们并不常用，但是有的时候却要在页面中用到这些字符，甚至有时候还需要用这些字符来实现某种特殊的视觉效果。现在，国外的设计师<a href="http://ikwebdesigner.com/special-characters/">Neal Chester</a>整理了一份很全的特殊字符集，共享出来供大家查阅。</p>
<p><strong>使用方法：<span id="more-19592"></span></strong></p>
<p>●这些字符属于unicode字符集，所以，你的文档需要声明为UTF-8；</p>
<p>●下面符号列表的后面有两列编号，它们并不太一样，第一列是用于HTML的，你需要在前面加上&amp;#符号；</p>
<p>●第二列可以用于CSS文件中，但是需要用反斜杠\转义；</p>
<p>●第二列也可以用于JavaScript，和CSS用法一样，不过要用\u来转义。</p>
<p><strong>需要主意的是：</strong></p>
<p>●有的字符在不同的<span class='wp_keywordlink'><a href="http://blog.jobbole.com/12749/" title="浏览器">浏览器</a></span>下表现不太一样；比如小雪人 ☃ 在Firefox和Chrome下不太一样，钻石 ◆ 在IE下要比Chrome下要大一点儿；</p>
<p>●有的字符在某个浏览器下不会显示；当然原因并不是字符代码的问题，而是浏览器的bug，比如，–在Chrome下。。。</p>
<p>●但是，98%的字符都能在所有浏览器下正常显示的，不过如果你真的要使用，最好仔细在各个浏览器下验证一番。</p>
<p>●经测试这些字符在Android/iOS等智能终端的识别度比较差，所以，使用的时候要特别注意移动浏览器～～</p>
<p><strong>各种箭头</strong></p>
<p>●     ⇠     8672 21E0</p>
<p>●     ⇢     8674 21E2</p>
<p>●    ⇡        8673 21E1</p>
<p>●    ⇣        8675 21E3</p>
<p>●   ↞       8606 219E</p>
<p>●   ↠       8608 21A0</p>
<p>●    ↟        8607 219F</p>
<p>●    ↡        8609 21A1</p>
<p>●    ←      8592 2190</p>
<p>●    →      8594 2192</p>
<p>●     ↑       8593 2191</p>
<p>●     ↓       8595 2193</p>
<p>●    ↔      8596 2194</p>
<p>●      ↕      8597 2195</p>
<p>●     ⇄     8644 21C4</p>
<p>●     ⇅      8645 21C5</p>
<p>●     ↢     8610 21A2</p>
<p>●    ↣      8611 21A3</p>
<p>●    ⇞        8670 21DE</p>
<p>●     ⇟      8671 21DF</p>
<p>●     ↫      8619 21AB</p>
<p>●     ↬      8620 21AC</p>
<p>●     ⇜      8668 21DC</p>
<p>●     ⇝      8669 21DD</p>
<p>●     ↚      8602 219A</p>
<p>●     ↛      8603 219B</p>
<p>●     ↮      8622 21AE</p>
<p>●     ↭      8621 21AD</p>
<p><strong>形状</strong></p>
<p>●     ⇦      8678 21E6</p>
<p>●     ⇨      8680 21E8</p>
<p>●     ⇧      8679 21E7</p>
<p>●     ⇩      8681 21E9</p>
<p>●     ↷      8631 21B7</p>
<p>●     ↶      8630 21B6</p>
<p>●     ↻      8635 21BB</p>
<p>●     ↺      8634 21BA</p>
<p>●     ⟳      10227 27F3</p>
<p>●     ⟲      10226 27F2</p>
<p>●     ⟰      10224 27F0</p>
<p>●     ⟱      10225 27F1</p>
<p>●     ↵      8629 21B5</p>
<p>●     ↯      8623 21AF</p>
<p>●     ⇵      8693 21F5</p>
<p><strong>向右的箭头</strong></p>
<p>●     ➔      10132 2794</p>
<p>●     ➙      10137 2799</p>
<p>●     ➨      10152 27A8</p>
<p>●     ➲      10162 27B2</p>
<p>●     ➜      10140 279C</p>
<p>●     ➞      10142 279E</p>
<p>●     ➟      10143 279F</p>
<p>●     ➠      10144 27A0</p>
<p>●     ➤      10148 27A4</p>
<p>●     ➥      10149 27A5</p>
<p>●     ➦      10150 27A6</p>
<p>●     ➧      10151 27A7</p>
<p>●     ➵      10165 27B5</p>
<p>●     ➸      10168 27B8</p>
<p>●     ➼      10172 27BC</p>
<p>●     ➽      10173 27BD</p>
<p>●     ➺      10170 27BA</p>
<p>●     ➳      10163 27B3</p>
<p>●     ➾      10174 27BE</p>
<p><strong>基本形状</strong></p>
<p>●     ▲      9650 25B2</p>
<p>●     ►      9658 25BA</p>
<p>●     ▼      9660 25BC</p>
<p>●     ◄      9668 25C4</p>
<p>●     ❤      10084 2764</p>
<p>●     ✈      9992 2708</p>
<p>●     ★      9733 2605</p>
<p>●     ✦      10022 2726</p>
<p>●     ☀      9728 2600</p>
<p>●     ◆      9670 25C6</p>
<p>●     ◈      9672 25C8</p>
<p>●     ▣      9635 25A3</p>
<p><strong>标点</strong></p>
<p>●     «      171 00AB</p>
<p>●     »      187 00BB</p>
<p>●     ‹      139 008B</p>
<p>●     ›      155 009B</p>
<p>●     “      8220 201C</p>
<p>●     ”      8221 201D</p>
<p>●     ‘      8216 2018</p>
<p>●     ’      8217 2019</p>
<p>●     •      8226 2022</p>
<p>●     ◦      9702 25E6</p>
<p>●     ¡      161 00A1</p>
<p>●     ¿      191 00BF</p>
<p>●     ℅      8453 2105</p>
<p>●     №      8470 2116</p>
<p>●     &amp;      38 0026</p>
<p>●     @      64 0040</p>
<p>●     ℞      8478 211E</p>
<p>●     ℃      8451 2103</p>
<p>●     ℉      8457 2109</p>
<p>●     °      176 00B0</p>
<p>●     |      124 007C</p>
<p>●     ¦      166 00A6</p>
<p>●     –      8211 2013</p>
<p>●     —      8212 2014</p>
<p>●     …      8230 2026</p>
<p>●     ¶      182 00B6</p>
<p>●     ∼      8764 223C</p>
<p>●     ≠      8800 2260</p>
<p><strong>法律符号</strong></p>
<p>●     ®      174 00AE</p>
<p>●     ©      169 00A9</p>
<p>●     ℗      8471 2117</p>
<p>●     ™      153 0099</p>
<p>●     ℠      8480 2120</p>
<p><strong>货币</strong></p>
<p>●     $      36 0024</p>
<p>●     ¢      162 00A2</p>
<p>●     £      163 00A3</p>
<p>●     ¤      164 00A4</p>
<p>●     €      8364 20AC</p>
<p>●     ¥      165 00A5</p>
<p>●     ₱      8369 20B1</p>
<p>●     ₹      8377 20B9</p>
<p><strong>数学</strong></p>
<p>●     ½      189 00BD</p>
<p>●     ¼      188 00BC</p>
<p>●     ¾      190 00BE</p>
<p>●     ⅓      8531 2153</p>
<p>●     ⅔      8532 2154</p>
<p>●     ⅛      8539 215B</p>
<p>●     ⅜      8540 215C</p>
<p>●     ⅝      8541 215D</p>
<p>●     ‰      8240 2030</p>
<p>●     %      37 0025</p>
<p>●     &lt;      60 003C</p>
<p>●     &gt;      62 003E</p>
<p><strong>音乐符号</strong></p>
<p>●     ♩      9833 2669</p>
<p>●     ♪      9834 266A</p>
<p>●     ♫      9835 266B</p>
<p>●     ♬      9836 266C</p>
<p>●     ♭      9837 266D</p>
<p>●     ♯      9839 266F</p>
<p><strong>对号、错号</strong></p>
<p>●               160 00A0</p>
<p>●     ☐      9744 2610</p>
<p>●     ☑      9745 2611</p>
<p>●     ☒      9746 2612</p>
<p>●     ✓      10003 2713</p>
<p>●     ✔      10004 2714</p>
<p>●     ✕      10005 10005</p>
<p>●     ✖      10006 2716</p>
<p>●     ✗      10007 2717</p>
<p>●     ✘      10008 2718</p>
<p><strong>十字</strong></p>
<p>●     ☨      9768 2628</p>
<p>●     ☩      9769 2629</p>
<p>●     ✝      10013 271D</p>
<p>●     ✞      10014 271E</p>
<p>●     ✟      10015 271F</p>
<p>●     ✠      10016 2720</p>
<p>●     ✚      10010 271A</p>
<p>●     †      8224 2020</p>
<p>●     ✢      10018 2722</p>
<p>●     ✤      10020 2724</p>
<p>●     ✣      10019 2723</p>
<p>●     ✥      10021 2725</p>
<p><strong>星星、星号、雪花</strong></p>
<p>●     ★      9733 2605</p>
<p>●     ✭      10029 272D</p>
<p>●     ✮      10030 272E</p>
<p>●     ☆      9734 2606</p>
<p>●     ✪      10026 272A</p>
<p>●     ✡      10017 2721</p>
<p>●     ✯      10031 272F</p>
<p>●     ✵      10037 2735</p>
<p>●     ✶      10038 2736</p>
<p>●     ✸      10040 2738</p>
<p>●     ✹      10041 2739</p>
<p>●     ✺      10042 273A</p>
<p>●     ✱      10033 2731</p>
<p>●     ✲      10034 2732</p>
<p>●     ✴      10036 2734</p>
<p>●     ✳      10035 2733</p>
<p>●     ✻      10043 273B</p>
<p>●     ✽      10045 273D</p>
<p>●     ❋      10059 274B</p>
<p>●     ❆      10054 2746</p>
<p>●     ❄      10052 2744</p>
<p>●     ❅      10053 2745</p>
<p><strong>杂项</strong></p>
<p>●     ☻      9787 263B</p>
<p>●     ☺      9786 263A</p>
<p>●     ☹      9785 2639</p>
<p>●     ✉      9993 2709</p>
<p>●     ☎      9742 260E</p>
<p>●     ☏      9743 260F</p>
<p>●     ✆      9990 2706</p>
<p>●     �      65533 FFFD</p>
<p>●     ☁      9729 2601</p>
<p>●     ☂      9730 2602</p>
<p>●     ❄      10052 2744</p>
<p>●     ☃      9731 2603</p>
<p>●     ❈      10056 2748</p>
<p>●     ✿      10047 273F</p>
<p>●     ❀      10048 2740</p>
<p>●     ❁      10049 2741</p>
<p>●     ☘      9752 2618</p>
<p>●     ❦      10086 2766</p>
<p>●     ☕      9749 9749</p>
<p>●     ❂      10050 2742</p>
<p>●     ☥      9765 2625</p>
<p>●     ☮      9774 262E</p>
<p>●     ☯      9775 262F</p>
<p>●     ☪      9770 262A</p>
<p>●     ☤      9764 2624</p>
<p>●     ✄      9988 2704</p>
<p>●     ✂      9986 2702</p>
<p>●     ☸      9784 2638</p>
<p>●     ⚓      9875 2693</p>
<p>●     ☣      9763 2623</p>
<p>●     ⚠      9888 26A0</p>
<p>●     ⚡      9889 26A1</p>
<p>●     ☢      9762 2622</p>
<p>●     ♻      9851 267B</p>
<p>●     ♿      9855 267F</p>
<p>●     ☠      9760 2620</p>
<p><strong>手型、铅笔、笔</strong></p>
<p>●     ☜      9756 261C</p>
<p>●     ☞      9758 261E</p>
<p>●     ☝      9757 261D</p>
<p>●     ☟      9759 261F</p>
<p>●     ✌      9996 270C</p>
<p>●     ✍      9997 270D</p>
<p>●     ✎      9998 270E</p>
<p>●     ✐      10000 2710</p>
<p>●     ✏      9999 270F</p>
<p>●     ✑      10001 2711</p>
<p>●     ✒      10002 2712</p>
<p><strong>天空、植物</strong></p>
<p>●     ☽      9789 263D</p>
<p>●     ☾      9790 263E</p>
<p>●     ♂      9794 2642</p>
<p>●     ♀      9792 2640</p>
<p>●     ☿      9791 263F</p>
<p>●     ♁      9793 2641</p>
<p>●     ♃      9795 2643</p>
<p>●     ♄      9796 2644</p>
<p>●     ♅      9797 2645</p>
<p>●     ♆      9798 2646</p>
<p>●     ♇      9799 2647</p>
<p><strong>星座</strong></p>
<p>●     ♈      9800 2648</p>
<p>●     ♉      9801 2649</p>
<p>●     ♊      9802 264A</p>
<p>●     ♋      9803 264B</p>
<p>●     ♌      9804 264C</p>
<p>●     ♍      9805 264D</p>
<p>●     ♎      9806 264E</p>
<p>●     ♏      9807 264F</p>
<p>●     ♑      9809 2651</p>
<p>●     ♒      9810 2652</p>
<p>●     ♓      9811 2653</p>
<p><strong>象棋，扑克牌</strong></p>
<p>●     ♚      9818 265A</p>
<p>●     ♛      9819 265B</p>
<p>●     ♜      9820 265C</p>
<p>●     ♝      9821 265D</p>
<p>●     ♞      9822 265E</p>
<p>●     ♟      9823 265F</p>
<p>●     ♔      9812 2654</p>
<p>●     ♕      9813 2655</p>
<p>●     ♖      9814 2656</p>
<p>●     ♗      9815 2657</p>
<p>●     ♘      9816 2658</p>
<p>●     ♙      9817 2659</p>
<p>●     ♠      9824 2660</p>
<p>●     ♣      9827 2663</p>
<p>●     ♥      9829 2665</p>
<p>●     ♦      9830 2666</p>
<p>●     ♤      9828 2664</p>
<p>●     ♧      9831 2667</p>
<p>●     ♡      9825 2661</p>
<p>●     ♢      9826 2662</p>
<p><strong>希腊字母</strong></p>
<p>●     Α      913 0391</p>
<p>●     Β      914 0392</p>
<p>●     Γ      915 0393</p>
<p>●     Δ      916 0394</p>
<p>●     Ε      917 0395</p>
<p>●     Ζ      918 0396</p>
<p>●     Η      919 0397</p>
<p>●     Θ      920 0398</p>
<p>●     Ι      921 0399</p>
<p>●     Κ      922 039A</p>
<p>●     Λ      923 039B</p>
<p>●     Μ      924 039C</p>
<p>●     Ν      925 039D</p>
<p>●     Ξ      926 039E</p>
<p>●     Ο      927 039F</p>
<p>●     Π      928 03A0</p>
<p>●     Ρ      929 03A1</p>
<p>●     Σ      931 03A3</p>
<p>●     Τ      932 03A4</p>
<p>●     Υ      933 03A5</p>
<p>●     Φ      934 03A6</p>
<p>●     Χ      935 03A7</p>
<p>●     Ψ      936 03A8</p>
<p>●     Ω      937 03A9</p>
<h2  class="related_post_title">相关文章</h2><ul class="related_post"><li><a target="_blank" href="http://blog.jobbole.com/19714/" title="Zen Coding: 一种快速编写HTML/CSS代码的方法 ">Zen Coding: 一种快速编写HTML/CSS代码的方法 </a></li><li><a target="_blank" href="http://blog.jobbole.com/19322/" title="HTML的15个最佳实践">HTML的15个最佳实践</a></li><li><a target="_blank" href="http://blog.jobbole.com/16668/" title="Codecademy为编程初学者新增HTML和CSS两门课程">Codecademy为编程初学者新增HTML和CSS两门课程</a></li><li><a target="_blank" href="http://blog.jobbole.com/10408/" title="如何将页脚固定在页面底部">如何将页脚固定在页面底部</a></li><li><a target="_blank" href="http://blog.jobbole.com/1519/" title="HTML4 和 HTML5的10个关键区别">HTML4 和 HTML5的10个关键区别</a></li><li><a target="_blank" href="http://blog.jobbole.com/854/" title="6种编写HTML和CSS的最有效的方法">6种编写HTML和CSS的最有效的方法</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.jobbole.com/19592/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>省时利器：代码美化与格式化工具</title>
		<link>http://blog.jobbole.com/16979/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25e7%259c%2581%25e6%2597%25b6%25e5%2588%25a9%25e5%2599%25a8%25ef%25bc%259a%25e4%25bb%25a3%25e7%25a0%2581%25e7%25be%258e%25e5%258c%2596%25e4%25b8%258e%25e6%25a0%25bc%25e5%25bc%258f%25e5%258c%2596%25e5%25b7%25a5%25e5%2585%25b7</link>
		<comments>http://blog.jobbole.com/16979/#comments</comments>
		<pubDate>Tue, 15 May 2012 19:18:00 +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://blog.jobbole.com/?p=16979</guid>
		<description><![CDATA[<p align="left"><strong>导读：</strong>有统计表明，缩进良好的代码可以提高代码阅读效率40%以上，70%开发工作是维护前任工程师所编写的代码，因此代码的格式美化往往是系统重构的第一步，工欲善其事必先利其器，下面就来看看那些不错的工具吧。</p>
<p align="left">文档齐全、易读的源代码是每一个合作开发项目所必备的，逻辑结构清晰的、组织良好的、格式标准的代码能够更快地发现bug，精简代码而不失功能性，这些要求在一个协同开发的团队里显得尤为重要，在那样的环境中，一个统一的源代码展示风格更是不可或缺。事实上，你不需要手工的做任何事，不少相关的工具能为我们节省大量的时间。</p>
<p align="left">需要提醒的是：收集的以下工具，作者并没有做相关的验证。除了格式化和美化代码之外，部分工具甚至能把冗余的元素去除。使用它们的时候记得备份代码，那样随时可以恢复数据。</p>
<p align="left"><strong>0、 <a href="http://quickhighlighter.com/">Quick Highlighter</a></strong></p>
<p align="left">Quick Highlighter 支持的语言超过85种，如：C++, PHP, Ruby, HTML, JavaScript, Perl, Python, Smarty, XML等等，它能格式化源码以及高亮内建的关键字和数据类型等。</p>
<p align="left"><a href="http://quickhighlighter.com/"><img class="aligncenter size-full wp-image-16980" title="timer-saver0" src="http://blog.jobbole.com/wp-content/uploads/2012/04/timer-saver0.gif" alt="" width="450" height="277" /></a></p>
<p align="left"><strong>1、  <a href="http://www.prettyprinter.de/">PrettyPrinter</a></strong></p>
<p align="left">PrettyPrinter适用于 PHP, Java, C++, C, Perl, JavaScript, CSS。提供了大量格式化选项，可以按照你喜欢的方式来展示代码。</p>
<p align="center"><a href="http://www.prettyprinter.de/"><img class="aligncenter size-full wp-image-16981" title="timer-saver1" src="http://blog.jobbole.com/wp-content/uploads/2012/04/timer-saver1.gif" alt="" width="379" height="449" /></a></p>
<p align="left"><strong>2、  <a href="http://www.waterproof.fr/products/phpCodeBeautifier/">PHP Code Beautifier</a></strong></p>
<p align="left">PHP Code Beautifier旨在美化PHP代码，它运用了大量PHP延伸及扩充程式库(PEAR)，甚至可以准确地处理杂乱的脚本，例如：所有代码在一行中，它能够把代码转换成可读性更好的格式。设置缺省的换行而不会移除任何额外的换行符，那样你可以把相关的东西聚拢在一起，根据嵌套的花括弧来修正错误的缩进。</p>

<pre class="brush: php; gutter: true">&#60;?php

if($code == BAD){$action = REWRITE;}else{$action = KEEP;}

for($i=0; $i&#60;10;$i++){while($j&#62;0){$j++;doCall($i+$j);if($k){$k/=10;}}}

?&#62;</pre>
转换成
<div>
<pre class="brush: php; gutter: true">&#60;?php
if ($code == BAD) {
    $action = REWRITE;
} else {
    $action = KEEP;
}
for($i = 0; $i &#60; 10;$i++) {
    while ($j &#62; 0) {
        $j++;
        doCall($i + $j);
        if ($k) {
            $k /= 10;
        }
    }
}
?&#62;</pre>
</div>
<strong>3、  <a href="http://www.arachnoid.com/ruby/rubyBeautifier.html">Ruby Script Beautifier</a></strong>

Ruby 美化工具以命令行的形式接受文件名列表，为每一个指定的文件创建一个副本然后对源文件进行美化。如果有缩进错误，脚本程序会打印错误消息，但总会对其修改的结果进行保存。

<strong>4、  <a href="http://tools.arantius.com/tabifier">Tabifier</a></strong>

Tabifier 是一个代码缩进工具，目前Tabifier支持CSS，HTML，JSON，以及C语言风格的代码。

<a href="http://tools.arantius.com/tabifier"><img class="aligncenter size-full wp-image-16982" title="timer-saver2" src="http://blog.jobbole.com/wp-content/uploads/2012/04/timer-saver2.gif" alt="" width="450" height="311" /></a>

<strong>5、  <a href="http://www.lonniebest.com/FormatCSS/">CSS Beautifier</a></strong>

CSS Beautifier提供了多种选项，包括按字母排序和大写转换小写等特性。

<a href="http://www.lonniebest.com/FormatCSS/"><img class="aligncenter size-full wp-image-16983" title="timer-saver3" src="http://blog.jobbole.com/wp-content/uploads/2012/04/timer-saver3.png" alt="" width="611" height="529" /></a>
<p style="text-align: left;" align="center"><strong>6、  <a href="http://cdburnerxp.se/cssparse/css_optimiser.php?lang=de">CSS Formatierer und Optimierer</a></strong></p>
<p style="text-align: left;" align="center">该工具有多种压缩设计，你可以对选择器、属性进行排序，重新组合选择器，精简颜色、字体的粗细属性(font-weight)，摒弃无效的属性以及添加时间戳，同时你还可以自定义模板系统用于格式化代码。生成结果能够当做文件输出保存，你可以在<a href="http://www.cleancss.com/?lang=de">cleancss.com</a>找到一个与之对应的副本。</p>
<p style="text-align: left;" align="center"><a href="http://cdburnerxp.se/cssparse/css_optimiser.php?lang=de"><img class="aligncenter size-full wp-image-16984" title="timer-saver4" src="http://blog.jobbole.com/wp-content/uploads/2012/04/timer-saver4.gif" alt="" width="450" height="400" /></a><strong>7、<a href="http://softwaremaniacs.org/soft/highlight/en/">Highlight.js</a></strong></p>
Highlight.js用于博客、论坛等任何web页面上作为代码示例的语法高亮工具。查找代码块，检测语言，高亮处理的自动化机制让操作者易于使用，它同样能够作为WordPress的插进和Firefox的扩展程序，所支持的语言有Python, Ruby, Perl, PHP, HTML, CSS, Django, JavaScript, VBScript, Delphi, Java, C++, SQL，与之类似的工具有由Google提供的 <a href="http://google-code-prettify.googlecode.com/svn/trunk/README.html">Googles Javascript Code Prettifier</a>.
<p align="center"><a href="http://softwaremaniacs.org/soft/highlight/en/"><img class="aligncenter size-full wp-image-16985" title="timer-saver5" src="http://blog.jobbole.com/wp-content/uploads/2012/04/timer-saver5.png" alt="" width="270" height="290" /></a><a href="http://softwaremaniacs.org/soft/highlight/en/"><img class="aligncenter size-full wp-image-16986" title="timer-saver6" src="http://blog.jobbole.com/wp-content/uploads/2012/04/timer-saver6.gif" alt="" width="363" height="131" /></a></p>
<strong>8、<a href="http://pluszone.net/blog/projects/beautifierPlus/index.php">Code Beautifier Plus</a></strong>

Code Beautifier Plus支持Java、C#和ActionScript<a href="http://blog.jobbole.com/wp-content/uploads/2012/04/iphone-ipad-webmaster-apps.png"><img class="aligncenter size-thumbnail wp-image-16993" title="iphone-ipad-webmaster-apps" src="http://blog.jobbole.com/wp-content/uploads/2012/04/iphone-ipad-webmaster-apps-150x150.png" alt="" width="150" height="150" /></a>
<p align="center"><a href="http://blog.jobbole.com/wp-content/uploads/2012/04/timer-saver7.gif"><img class="aligncenter size-full wp-image-16987" title="timer-saver7" src="http://blog.jobbole.com/wp-content/uploads/2012/04/timer-saver7.gif" alt="" width="399" height="420" /></a></p>
<strong>9、 <a href="http://formatter.gerbenvv.nl/version3/index.php?lang=en">PHP Formatter</a></strong>

PHP Formatter可以在控制结构体后添加注释，输出文件高亮处理，通过内联函数链接到php手册，移除注释和空行。它包含5种预定义的风格，同时你也可以定义自己的样式。

<a href="http://formatter.gerbenvv.nl/version3/index.php?lang=en"><img class="aligncenter size-full wp-image-16988" title="timer-saver8" src="http://blog.jobbole.com/wp-content/uploads/2012/04/timer-saver8.gif" alt="" width="324" height="155" /></a>
<p style="text-align: left;"><strong>10、<a href="http://beautifyphp.sourceforge.net/docs/">PHP_Beautifier </a></strong></p>
<p style="text-align: left;">一个美化PHP4和PHP5源代码工具，能够运行在你自己的服务器，但需要PHP5的支持。</p>
<p style="text-align: left;"><strong>11、 <a href="http://jsbeautifier.org/">JSBeautifier</a></strong></p>
<p style="text-align: left;">此工具能够美化JavaScript、HTML，提高JSON/JSONP的可读性。</p>
<strong>商业版本</strong>

<strong>12、 <a href="http://www.polystyle.com/">Polystyle</a></strong>

Polystyle 能按照你自己代码风格来自动格式化代码，它能通过检测你的代码样例来学习如何格式化，该工具支持Actionscript, ASP, C/C++, C#, CMAC, CSS, HTML, Java, Javascript, JSP, PHP, Pascal/Delphi, Perl, Python and Visual Basic.等等，价格是79$，有命令行的窗口两种模式

&#160;

原文：<a title="Posts by Sven Lennartz" href="http://coding.smashingmagazine.com/author/sven-lennartz/" rel="author">Sven Lennartz</a>   编译：<a href="http://www.jobbole.com/" target="_blank">伯乐</a>在线 – <a href="http://blog.jobbole.com/16979">刘志军</a>

<span style="color: #ff0000;">【如需转载，请标注并保留原文链接、译文链接和译者等信息，谢谢合作！】</span>

&#160;]]></description>
			<content:encoded><![CDATA[<p align="left"><strong>导读：</strong>有统计表明，缩进良好的代码可以提高代码阅读效率40%以上，70%开发工作是维护前任工程师所编写的代码，因此代码的格式美化往往是系统<span class='wp_keywordlink'><a href="http://www.amazon.cn/gp/product/B003BY6PLK/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=vastwork-23&linkCode=as2&camp=536&creative=3200&creativeASIN=B003BY6PLK" title="重构" rel="nofollow" target="_blank">重构</a></span>的第一步，工欲善其事必先利其器，下面就来看看那些不错的工具吧。</p>
<p align="left">文档齐全、易读的源代码是每一个合作开发项目所必备的，逻辑结构清晰的、组织良好的、格式标准的代码能够更快地发现bug，精简代码而不失功能性，这些要求在一个协同开发的团队里显得尤为重要，在那样的环境中，一个统一的源代码展示风格更是不可或缺。事实上，你不需要手工的做任何事，不少相关的工具能为我们节省大量的时间。</p>
<p align="left">需要提醒的是：收集的以下工具，作者并没有做相关的验证。除了格式化和美化代码之外，部分工具甚至能把冗余的元素去除。使用它们的时候记得备份代码，那样随时可以恢复数据。</p>
<p align="left"><strong>0、 <a href="http://quickhighlighter.com/">Quick Highlighter</a></strong></p>
<p align="left">Quick Highlighter 支持的语言超过85种，如：C++, PHP, Ruby, HTML, JavaScript, Perl, Python, Smarty, XML等等，它能格式化源码以及高亮内建的关键字和数据类型等。</p>
<p align="left"><a href="http://quickhighlighter.com/"><img class="aligncenter size-full wp-image-16980" title="timer-saver0" src="http://blog.jobbole.com/wp-content/uploads/2012/04/timer-saver0.gif" alt="" width="450" height="277" /></a></p>
<p align="left"><strong>1、  <a href="http://www.prettyprinter.de/">PrettyPrinter</a></strong></p>
<p align="left">PrettyPrinter适用于 PHP, Java, C++, C, Perl, JavaScript, CSS。提供了大量格式化选项，可以按照你喜欢的方式来展示代码。</p>
<p align="center"><a href="http://www.prettyprinter.de/"><img class="aligncenter size-full wp-image-16981" title="timer-saver1" src="http://blog.jobbole.com/wp-content/uploads/2012/04/timer-saver1.gif" alt="" width="379" height="449" /></a></p>
<p align="left"><strong>2、  <a href="http://www.waterproof.fr/products/phpCodeBeautifier/">PHP Code Beautifier</a></strong></p>
<p align="left">PHP Code Beautifier旨在美化PHP代码，它运用了大量PHP延伸及扩充程式库(PEAR)，甚至可以准确地处理杂乱的脚本，例如：所有代码在一行中，它能够把代码转换成可读性更好的格式。设置缺省的换行而不会移除任何额外的换行符，那样你可以把相关的东西聚拢在一起，根据嵌套的花括弧来修正错误的缩进。</p>
<pre class="brush: php; gutter: true">&lt;?php

if($code == BAD){$action = REWRITE;}else{$action = KEEP;}

for($i=0; $i&lt;10;$i++){while($j&gt;0){$j++;doCall($i+$j);if($k){$k/=10;}}}

?&gt;</pre>
<p>转换成</p>
<div>
<pre class="brush: php; gutter: true">&lt;?php
if ($code == BAD) {
    $action = REWRITE;
} else {
    $action = KEEP;
}
for($i = 0; $i &lt; 10;$i++) {
    while ($j &gt; 0) {
        $j++;
        doCall($i + $j);
        if ($k) {
            $k /= 10;
        }
    }
}
?&gt;</pre>
</div>
<p><strong>3、  <a href="http://www.arachnoid.com/ruby/rubyBeautifier.html">Ruby Script Beautifier</a></strong></p>
<p>Ruby 美化工具以命令行的形式接受文件名列表，为每一个指定的文件创建一个副本然后对源文件进行美化。如果有缩进错误，脚本程序会打印错误消息，但总会对其修改的结果进行保存。</p>
<p><strong>4、  <a href="http://tools.arantius.com/tabifier">Tabifier</a></strong></p>
<p>Tabifier 是一个代码缩进工具，目前Tabifier支持CSS，HTML，JSON，以及C语言风格的代码。</p>
<p><a href="http://tools.arantius.com/tabifier"><img class="aligncenter size-full wp-image-16982" title="timer-saver2" src="http://blog.jobbole.com/wp-content/uploads/2012/04/timer-saver2.gif" alt="" width="450" height="311" /></a></p>
<p><strong>5、  <a href="http://www.lonniebest.com/FormatCSS/">CSS Beautifier</a></strong></p>
<p>CSS Beautifier提供了多种选项，包括按字母排序和大写转换小写等特性。</p>
<p><a href="http://www.lonniebest.com/FormatCSS/"><img class="aligncenter size-full wp-image-16983" title="timer-saver3" src="http://blog.jobbole.com/wp-content/uploads/2012/04/timer-saver3.png" alt="" width="611" height="529" /></a></p>
<p style="text-align: left;" align="center"><strong>6、  <a href="http://cdburnerxp.se/cssparse/css_optimiser.php?lang=de">CSS Formatierer und Optimierer</a></strong></p>
<p style="text-align: left;" align="center">该工具有多种压缩设计，你可以对选择器、属性进行排序，重新组合选择器，精简颜色、字体的粗细属性(font-weight)，摒弃无效的属性以及添加时间戳，同时你还可以自定义模板系统用于格式化代码。生成结果能够当做文件输出保存，你可以在<a href="http://www.cleancss.com/?lang=de">cleancss.com</a>找到一个与之对应的副本。</p>
<p style="text-align: left;" align="center"><a href="http://cdburnerxp.se/cssparse/css_optimiser.php?lang=de"><img class="aligncenter size-full wp-image-16984" title="timer-saver4" src="http://blog.jobbole.com/wp-content/uploads/2012/04/timer-saver4.gif" alt="" width="450" height="400" /></a><strong>7、<a href="http://softwaremaniacs.org/soft/highlight/en/">Highlight.js</a></strong></p>
<p>Highlight.js用于博客、论坛等任何web页面上作为代码示例的语法高亮工具。查找代码块，检测语言，高亮处理的自动化机制让操作者易于使用，它同样能够作为WordPress的插进和Firefox的扩展程序，所支持的语言有Python, Ruby, Perl, PHP, HTML, CSS, Django, JavaScript, VBScript, Delphi, Java, C++, SQL，与之类似的工具有由Google提供的 <a href="http://google-code-prettify.googlecode.com/svn/trunk/README.html">Googles Javascript Code Prettifier</a>.</p>
<p align="center"><a href="http://softwaremaniacs.org/soft/highlight/en/"><img class="aligncenter size-full wp-image-16985" title="timer-saver5" src="http://blog.jobbole.com/wp-content/uploads/2012/04/timer-saver5.png" alt="" width="270" height="290" /></a><a href="http://softwaremaniacs.org/soft/highlight/en/"><img class="aligncenter size-full wp-image-16986" title="timer-saver6" src="http://blog.jobbole.com/wp-content/uploads/2012/04/timer-saver6.gif" alt="" width="363" height="131" /></a></p>
<p><strong>8、<a href="http://pluszone.net/blog/projects/beautifierPlus/index.php">Code Beautifier Plus</a></strong></p>
<p>Code Beautifier Plus支持Java、C#和ActionScript<a href="http://blog.jobbole.com/wp-content/uploads/2012/04/iphone-ipad-webmaster-apps.png" rel="lightbox[16979]" title="iphone-ipad-webmaster-apps"><img class="aligncenter size-thumbnail wp-image-16993" title="iphone-ipad-webmaster-apps" src="http://blog.jobbole.com/wp-content/uploads/2012/04/iphone-ipad-webmaster-apps-150x150.png" alt="" width="150" height="150" /></a></p>
<p align="center"><a href="http://blog.jobbole.com/wp-content/uploads/2012/04/timer-saver7.gif" rel="lightbox[16979]" title="timer-saver7"><img class="aligncenter size-full wp-image-16987" title="timer-saver7" src="http://blog.jobbole.com/wp-content/uploads/2012/04/timer-saver7.gif" alt="" width="399" height="420" /></a></p>
<p><strong>9、 <a href="http://formatter.gerbenvv.nl/version3/index.php?lang=en">PHP Formatter</a></strong></p>
<p>PHP Formatter可以在控制结构体后添加注释，输出文件高亮处理，通过内联函数链接到php手册，移除注释和空行。它包含5种预定义的风格，同时你也可以定义自己的样式。</p>
<p><a href="http://formatter.gerbenvv.nl/version3/index.php?lang=en"><img class="aligncenter size-full wp-image-16988" title="timer-saver8" src="http://blog.jobbole.com/wp-content/uploads/2012/04/timer-saver8.gif" alt="" width="324" height="155" /></a></p>
<p style="text-align: left;"><strong>10、<a href="http://beautifyphp.sourceforge.net/docs/">PHP_Beautifier </a></strong></p>
<p style="text-align: left;">一个美化PHP4和PHP5源代码工具，能够运行在你自己的服务器，但需要PHP5的支持。</p>
<p style="text-align: left;"><strong>11、 <a href="http://jsbeautifier.org/">JSBeautifier</a></strong></p>
<p style="text-align: left;">此工具能够美化JavaScript、HTML，提高JSON/JSONP的可读性。</p>
<p><strong>商业版本</strong></p>
<p><strong>12、 <a href="http://www.polystyle.com/">Polystyle</a></strong></p>
<p>Polystyle 能按照你自己代码风格来自动格式化代码，它能通过检测你的代码样例来学习如何格式化，该工具支持Actionscript, ASP, C/C++, C#, CMAC, CSS, HTML, Java, Javascript, JSP, PHP, Pascal/Delphi, Perl, Python and Visual Basic.等等，价格是79$，有命令行的窗口两种模式</p>
<p>&nbsp;</p>
<p>原文：<a title="Posts by Sven Lennartz" href="http://coding.smashingmagazine.com/author/sven-lennartz/" rel="author">Sven Lennartz</a>   编译：<a href="http://www.jobbole.com/" target="_blank">伯乐</a>在线 – <a href="http://blog.jobbole.com/16979">刘志军</a></p>
<p><span style="color: #ff0000;">【如需转载，请标注并保留原文链接、译文链接和译者等信息，谢谢合作！】</span></p>
<p>&nbsp;</p>
<h2  class="related_post_title">相关文章</h2><ul class="related_post"><li><a target="_blank" href="http://blog.jobbole.com/1180/" title="11个源码优化和分析的Java工具">11个源码优化和分析的Java工具</a></li><li><a target="_blank" href="http://blog.jobbole.com/19601/" title="22 个免费的图表、流程图工具">22 个免费的图表、流程图工具</a></li><li><a target="_blank" href="http://blog.jobbole.com/18304/" title="史上最糟糕的两个变量名">史上最糟糕的两个变量名</a></li><li><a target="_blank" href="http://blog.jobbole.com/19371/" title="什么是重构，什么不是重构 ">什么是重构，什么不是重构 </a></li><li><a target="_blank" href="http://blog.jobbole.com/19016/" title="重构：代码异味">重构：代码异味</a></li><li><a target="_blank" href="http://blog.jobbole.com/18714/" title="13个超棒的代码资源网站推荐  ">13个超棒的代码资源网站推荐  </a></li><li><a target="_blank" href="http://blog.jobbole.com/18662/" title="16个不错的Visual Studio插件">16个不错的Visual Studio插件</a></li><li><a target="_blank" href="http://blog.jobbole.com/18232/" title=".Net 开发者必备的11款开发工具">.Net 开发者必备的11款开发工具</a></li><li><a target="_blank" href="http://blog.jobbole.com/18144/" title="张砷镓：我所信奉的编程哲学 ">张砷镓：我所信奉的编程哲学 </a></li><li><a target="_blank" href="http://blog.jobbole.com/17814/" title="简化PHP开发的11个工具 ">简化PHP开发的11个工具 </a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.jobbole.com/16979/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>熊子川：体验设计师可以改进的5个习惯</title>
		<link>http://blog.jobbole.com/19561/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25e7%2586%258a%25e5%25ad%2590%25e5%25b7%259d%25ef%25bc%259a%25e4%25bd%2593%25e9%25aa%258c%25e8%25ae%25be%25e8%25ae%25a1%25e5%25b8%2588%25e5%258f%25af%25e4%25bb%25a5%25e6%2594%25b9%25e8%25bf%259b%25e7%259a%25845%25e4%25b8%25aa%25e4%25b9%25a0%25e6%2583%25af</link>
		<comments>http://blog.jobbole.com/19561/#comments</comments>
		<pubDate>Tue, 15 May 2012 05:01:25 +0000</pubDate>
		<dc:creator>童海波</dc:creator>
				<category><![CDATA[设计]]></category>
		<category><![CDATA[用户体验]]></category>

		<guid isPermaLink="false">http://blog.jobbole.com/?p=19561</guid>
		<description><![CDATA[<p id="">周末参加了<a href="http://www.techyizu.org/events/designing_shanghai_2012/">UXDAY2012</a>的活动即Designing Shanghai2012，活动的过程是去中山公园观察公园里的老人，以及探访老人之家，寻找到可以设计可以帮助老人建立更好生活体验的地方。活动很精彩，在整个过程中我也发现5个体验设计师可以改进的习惯，这里我总结一些我的方法和经验，希望给大家帮助。<!--more--></p>
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/20120400_194344.jpg"><img class="aligncenter size-full wp-image-19562" title="熊子川：体验设计师可以改进的5个习惯" src="http://blog.jobbole.com/wp-content/uploads/2012/05/20120400_194344.jpg" alt="熊子川：体验设计师可以改进的5个习惯" width="560" height="420" /></a></p>
<strong>用户情境观察的结果是感受或结论，而不是事实</strong>

活动第一个环节是去中山公园和老人之家观察老人的行为，回来以后我们将收集的信息展示在黑板上。我看到了诸如“消极和悲观”、“孤独”、“希望社交”、“热衷于被关注”的信息，而在我看来这些信息都不足以成为建立情境所需要的高质量的信息。

体验设计的第一步是建立一个尽可能真实的情境，在这样的情境中才可能产生尽可能真实的问题（problem），于是一个真实的情境需要真实的素材来构建。当你说“老人们热衷于被关注”的时候，你是基于什么有这样的结论──我们需要一个真实发生的故事。

对于“热衷于被关注”这一点，我也有类似发现，而我更多是表达一个“故事”：领头的老人会把报道他们的报纸叠成豆腐块，随时揣在口袋里，拿出来说给关注他们的年轻人看。这是一个“故事”，而不是一个“推断”。

情境应该基于“故事”，而不应该基于一个武断的“推断”，有足够多这样真实的故事，就可以让我们的情境变得更加丰满，因此而发现的问题或机会，就会变得贴和用户的需要。

如果可能的话，把这些小故事用草绘的形式（或照片）表达出来，贴在墙上，布置一个情境房间，在房间里进行设计。
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/IMG_1898-e1336908340115-764x1024.jpg"><img class="aligncenter size-full wp-image-19563" title="熊子川：体验设计师可以改进的5个习惯" src="http://blog.jobbole.com/wp-content/uploads/2012/05/IMG_1898-e1336908340115-764x1024.jpg" alt="熊子川：体验设计师可以改进的5个习惯" width="535" height="717" /></a>
<small>这是一个在参加<a href="http://www.uxaustralia.com.au/servicedesign-2012/">Service Design 2012 Melbourne</a>看到的案例，把所有拍摄到的“故事”贴在一个模特的周围，布置一个情境房间。</small></p>
<strong>用自己的感官感觉替代用户的感官感觉</strong>

在老人院的时候，作为有优越生活的一群人，我们不自然地对整个环境有了一个先入为主的判断，在头脑风暴时，很多人的发现是“缺乏幸福感的环境”、“潮湿阴暗无助”、“缺乏对社交的帮助”等等。
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/IMG_1959-e1336908628295-764x1024.jpg"><img class="aligncenter size-full wp-image-19564" title="熊子川：体验设计师可以改进的5个习惯" src="http://blog.jobbole.com/wp-content/uploads/2012/05/IMG_1959-e1336908628295-764x1024.jpg" alt="熊子川：体验设计师可以改进的5个习惯" width="535" height="717" /></a>
<small>很多对环境的感官感觉是主观的结论而非基于一个真实的故事（insights）</small></p>
也许有老人也是这么想，但是作为用户和情境的研究者，我们不能用自己的感官感受来代替使用者的感官感受，在这里，我们同样需要各种各样的故事去支持这些感官的评价。

人对情境的感官感觉来自于对周边每次互动时的反馈。于是我们需要思考的是老人与整个环境的互动，例如：走道的扶手；洗手间的扶手；灯的开关；床；轮椅；门以及门的扶手；座椅等等，这些就是交互触点（touchpoint），对所有触点的整体体会才构成了对整体情境的评价。

而我们作为设计师，第一次来到这个环境，对整体情境的评价只来自于视觉、嗅觉、以及与以往经历的比较，而没有亲身体会那些老人们每天都在接触的交互触点，那么我们的感官判断是不准确的。

<strong>对现在的解决方案不敏感</strong>

发掘用户问题最好的方法是去研究现有的解决方案，因为绝大部分情况，只要还在使用的解决方案，背后一定有一个被解决或解决不好的问题，研究他们，自然能够挖掘出真实存在的问题。

而我观察到我们很多人的方案更多还是与老人们直接沟通，问他们有什么问题，感觉怎样，而对现有的解决方案并不敏感。并不是说这种直接沟通不重要，而在于对于现有解决方案的了解有助于理解用户当前真正的需要，有意思的是，用户大部分情况会因为习以为常而忘记他周围常用的工具到底解决什么问题。

因为时间有限，我观察了一个老人身边现有的一些解决方案，例如，健身器材，我看到因为在户外，健身器锈迹斑斑，有一个老人来锻炼的时候，还需要另外一个人帮助她抓住有些高的把手，注意，这些都是观察结果，要做的只是忠实记录，而不是做判断；其他的解决方案还包括报警器、每日的药盒、电视机和遥控机、纱门等。
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/20120400_195311.jpg"><img class="aligncenter size-full wp-image-19565" title="熊子川：体验设计师可以改进的5个习惯" src="http://blog.jobbole.com/wp-content/uploads/2012/05/20120400_195311.jpg" alt="熊子川：体验设计师可以改进的5个习惯" width="560" height="420" /></a>
<small>这些是我拍摄的部分解决方案，每个现有的解决方案背后一定有真实存在的问题正在被不同程度地解决。</small></p>
如果时间充裕，我们应该对老人周围所有用到的解决方案进行一个完整的分析，分析结果应该包含每个解决方案应该解决的问题，有什么使用困难（改进点），各个解决方案之间有没有联系（创新点）等。

这个解决方案图谱完成之后，相信你就会对目标用户有一个完整的认识，当然，了解解决方案的最佳方式是亲自体验。

<strong>还没想清楚为什么这样，就开始想为什么不那样</strong>

我看到最严重的问题是对解决方案的痴迷。在我看来，有创造力的含义是发现和定义一个用户真实存在问题，甚至不是解决了这个问题──发现和定义问题是一切设计的核心，当你发现了问题，最有本事的事情是用一个现有的东西去解决而非重新创造。

这种痴迷体现在还没想清楚为什么是现在这个样子，就开始想为什么不那样。当我们谈老人院的时候，在我们还没有想清楚，这个我们看来“阴暗无助充满社交阻隔的地方”为什么是现在的样子前，我们马上就开始思考如何把这个地方变得“幸福活力阳光充满欢乐”。

这件事的核心在于还没确定这是个问题就开始尝试解决问题，那么在我看来，这是承担巨大假设风险的。在进入解决方案的讨论前，应该明确的是两个问题：一是这是不是一个问题？二这个问题是不是我们应该最先解决的？如果这两个问题没有被很好的回答，除非运气极好，最后的结果无非是解决了个根本不是问题的问题，或者解决了不该现在解决的问题。

<strong>不愿意做小</strong>

很多人热衷于颠覆性的设计，而不愿意做小的改进，把创造等同于创意。我对这个问题的理解是，当你没有很好定义出典型用户、场景、和他们在场景中遇到的具体问题，而是用一个宽泛的断言代替设计方向，那么设计就会变得巨大。

如果你的设计挑战是如何让老人变得快乐，你设计很可能变得漫无边际；而如果你的设计挑战是如何让在中山公园组织老人活动的老王更好地宣传他们的社团使得更多人参加，你的设计就可能变得实际和具体。

也许有人说，那么你设计的东西就会变得狭隘，这是限制创新，其实并不是，当你深入到老人的情境中，梳理出更多基于真实故事的设计挑战，例如：如何让老人院的张爷爷记住自己喜欢的电视节目；如何让他锻炼自己的手指头；如何鼓励中山公园的社团参与者更多资助社团活动等等，这一系列小的设计挑战被解决以后，自然是整个体验的提升，自然是一件大的事情。

体验设计中把设计环节需要的心智模型（mentality）定义为“可实现”（rationality），而把发现问题环节定义为“创造力”（creativity）确实不无道理，创造力应该体现在发现具体问题并转化成具体设计挑战的过程中，而设计过程应是切中要害，最忌天马行空，没有商业和技术支持的设计不产生任何价值。

<strong>说多过于画</strong>

在表达解决方案的时候，我仿佛回到了H公司的需求讨论现场，要么所有人都在说，要么只听一个人说，其他人不敢说，没有人使用任何可视化的工具引导讨论，后来我画了几张关于解决方案的草图才让无休止的讨论回到正轨。

这就是为什么我们更加注重视觉引导的能力──如果可能事先把设计过程的框架用视觉化的方式搭建好；尽可能地使用白板，持续不断地把已经达成一致的东西写在白板上；更好使用贴纸的颜色，及时对信息进行组织和验证；对同一个设计挑战分组进行草图设计并展示，避免<strong>设计被那些口才好，强势有气场的人绑架</strong>。
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/20120400_193740.jpg"><img class="aligncenter size-full wp-image-19566" title="熊子川：体验设计师可以改进的5个习惯" src="http://blog.jobbole.com/wp-content/uploads/2012/05/20120400_193740.jpg" alt="熊子川：体验设计师可以改进的5个习惯" width="560" height="420" /></a>
<small>图中右下角是我们最后的故事板，添加了一些草图后使得沟通更加有效率，其他两副图展示了我们做workshop的时候推崇的过程可视化的场景，大量使用草图、白板、并随时将过程产物贴在墙上。</small></p>
<strong>写在最后</strong>

我能理解这样的活动不需要太多条条框框的设计方法进行限制，这只是我的一些思考和经验分享，并不代表大家是不够格的设计师。
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/20120400_200355.jpg"><img class="aligncenter size-full wp-image-19567" title="熊子川：体验设计师可以改进的5个习惯" src="http://blog.jobbole.com/wp-content/uploads/2012/05/20120400_200355.jpg" alt="熊子川：体验设计师可以改进的5个习惯" width="560" height="420" /></a></p>
&#160;

另外非常感谢<a href="http://www.techyizu.org/">techyizu</a>组织这么好的活动，我曾经在<a href="http://www.tuzei8.com/?p=267">牛津参加Design Jam</a>，组织形式类似，它有个环节是在报名时每个人需要提供一个角色：例如designer, developer, 或者strategist等，以保证每个设计团队有足够平衡，供参考。但这个全球性的活动当时并没有用户研究的环节，而正是这个深入用户进行研究的活动真正让我学习到了很多东西，谢谢大家的努力，也希望不久的将来能在北京看到类似的活动。
<p id="aeaoofnhgocdbnbeljkmbjdmhbcokfdb-mousedown"><strong>最后的最后</strong></p>
如果你发现这篇文章实际上是六个习惯而不是五个习惯，那么你真的没有除了上面五个习惯之外，设计师应该改进的第六个习惯：不会数数。无论如何，至少你仔细看了，应该谢谢你。]]></description>
			<content:encoded><![CDATA[<p id="">周末参加了<a href="http://www.techyizu.org/events/designing_shanghai_2012/">UXDAY2012</a>的活动即Designing Shanghai2012，活动的过程是去中山公园观察公园里的老人，以及探访老人之家，寻找到可以设计可以帮助老人建立更好生活体验的地方。活动很精彩，在整个过程中我也发现5个体验设计师可以改进的习惯，这里我总结一些我的方法和经验，希望给大家帮助。<span id="more-19561"></span></p>
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/20120400_194344.jpg" rel="lightbox[19561]" title="熊子川：体验设计师可以改进的5个习惯"><img class="aligncenter size-full wp-image-19562" title="熊子川：体验设计师可以改进的5个习惯" src="http://blog.jobbole.com/wp-content/uploads/2012/05/20120400_194344.jpg" alt="熊子川：体验设计师可以改进的5个习惯" width="560" height="420" /></a></p>
<p><strong>用户情境观察的结果是感受或结论，而不是事实</strong></p>
<p>活动第一个环节是去中山公园和老人之家观察老人的行为，回来以后我们将收集的信息展示在黑板上。我看到了诸如“消极和悲观”、“孤独”、“希望社交”、“热衷于被关注”的信息，而在我看来这些信息都不足以成为建立情境所需要的高质量的信息。</p>
<p>体验设计的第一步是建立一个尽可能真实的情境，在这样的情境中才可能产生尽可能真实的问题（problem），于是一个真实的情境需要真实的素材来构建。当你说“老人们热衷于被关注”的时候，你是基于什么有这样的结论──我们需要一个真实发生的故事。</p>
<p>对于“热衷于被关注”这一点，我也有类似发现，而我更多是表达一个“故事”：领头的老人会把报道他们的报纸叠成豆腐块，随时揣在口袋里，拿出来说给关注他们的年轻人看。这是一个“故事”，而不是一个“推断”。</p>
<p>情境应该基于“故事”，而不应该基于一个武断的“推断”，有足够多这样真实的故事，就可以让我们的情境变得更加丰满，因此而发现的问题或机会，就会变得贴和用户的需要。</p>
<p>如果可能的话，把这些小故事用草绘的形式（或照片）表达出来，贴在墙上，布置一个情境房间，在房间里进行设计。</p>
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/IMG_1898-e1336908340115-764x1024.jpg" rel="lightbox[19561]" title="熊子川：体验设计师可以改进的5个习惯"><img class="aligncenter size-full wp-image-19563" title="熊子川：体验设计师可以改进的5个习惯" src="http://blog.jobbole.com/wp-content/uploads/2012/05/IMG_1898-e1336908340115-764x1024.jpg" alt="熊子川：体验设计师可以改进的5个习惯" width="535" height="717" /></a><br />
<small>这是一个在参加<a href="http://www.uxaustralia.com.au/servicedesign-2012/">Service Design 2012 Melbourne</a>看到的案例，把所有拍摄到的“故事”贴在一个模特的周围，布置一个情境房间。</small></p>
<p><strong>用自己的感官感觉替代用户的感官感觉</strong></p>
<p>在老人院的时候，作为有优越生活的一群人，我们不自然地对整个环境有了一个先入为主的判断，在头脑风暴时，很多人的发现是“缺乏幸福感的环境”、“潮湿阴暗无助”、“缺乏对社交的帮助”等等。</p>
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/IMG_1959-e1336908628295-764x1024.jpg" rel="lightbox[19561]" title="熊子川：体验设计师可以改进的5个习惯"><img class="aligncenter size-full wp-image-19564" title="熊子川：体验设计师可以改进的5个习惯" src="http://blog.jobbole.com/wp-content/uploads/2012/05/IMG_1959-e1336908628295-764x1024.jpg" alt="熊子川：体验设计师可以改进的5个习惯" width="535" height="717" /></a><br />
<small>很多对环境的感官感觉是主观的结论而非基于一个真实的故事（insights）</small></p>
<p>也许有老人也是这么想，但是作为用户和情境的研究者，我们不能用自己的感官感受来代替使用者的感官感受，在这里，我们同样需要各种各样的故事去支持这些感官的评价。</p>
<p>人对情境的感官感觉来自于对周边每次互动时的反馈。于是我们需要思考的是老人与整个环境的互动，例如：走道的扶手；洗手间的扶手；灯的开关；床；轮椅；门以及门的扶手；座椅等等，这些就是交互触点（touchpoint），对所有触点的整体体会才构成了对整体情境的评价。</p>
<p>而我们作为设计师，第一次来到这个环境，对整体情境的评价只来自于视觉、嗅觉、以及与以往经历的比较，而没有亲身体会那些老人们每天都在接触的交互触点，那么我们的感官判断是不准确的。</p>
<p><strong>对现在的解决方案不敏感</strong></p>
<p>发掘用户问题最好的方法是去研究现有的解决方案，因为绝大部分情况，只要还在使用的解决方案，背后一定有一个被解决或解决不好的问题，研究他们，自然能够挖掘出真实存在的问题。</p>
<p>而我观察到我们很多人的方案更多还是与老人们直接沟通，问他们有什么问题，感觉怎样，而对现有的解决方案并不敏感。并不是说这种直接沟通不重要，而在于对于现有解决方案的了解有助于理解用户当前真正的需要，有意思的是，用户大部分情况会因为习以为常而忘记他周围常用的工具到底解决什么问题。</p>
<p>因为时间有限，我观察了一个老人身边现有的一些解决方案，例如，健身器材，我看到因为在户外，健身器锈迹斑斑，有一个老人来锻炼的时候，还需要另外一个人帮助她抓住有些高的把手，注意，这些都是观察结果，要做的只是忠实记录，而不是做判断；其他的解决方案还包括报警器、每日的药盒、电视机和遥控机、纱门等。</p>
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/20120400_195311.jpg" rel="lightbox[19561]" title="熊子川：体验设计师可以改进的5个习惯"><img class="aligncenter size-full wp-image-19565" title="熊子川：体验设计师可以改进的5个习惯" src="http://blog.jobbole.com/wp-content/uploads/2012/05/20120400_195311.jpg" alt="熊子川：体验设计师可以改进的5个习惯" width="560" height="420" /></a><br />
<small>这些是我拍摄的部分解决方案，每个现有的解决方案背后一定有真实存在的问题正在被不同程度地解决。</small></p>
<p>如果时间充裕，我们应该对老人周围所有用到的解决方案进行一个完整的分析，分析结果应该包含每个解决方案应该解决的问题，有什么使用困难（改进点），各个解决方案之间有没有联系（创新点）等。</p>
<p>这个解决方案图谱完成之后，相信你就会对目标用户有一个完整的认识，当然，了解解决方案的最佳方式是亲自体验。</p>
<p><strong>还没想清楚为什么这样，就开始想为什么不那样</strong></p>
<p>我看到最严重的问题是对解决方案的痴迷。在我看来，有创造力的含义是发现和定义一个用户真实存在问题，甚至不是解决了这个问题──发现和定义问题是一切设计的核心，当你发现了问题，最有本事的事情是用一个现有的东西去解决而非重新创造。</p>
<p>这种痴迷体现在还没想清楚为什么是现在这个样子，就开始想为什么不那样。当我们谈老人院的时候，在我们还没有想清楚，这个我们看来“阴暗无助充满社交阻隔的地方”为什么是现在的样子前，我们马上就开始思考如何把这个地方变得“幸福活力阳光充满欢乐”。</p>
<p>这件事的核心在于还没确定这是个问题就开始尝试解决问题，那么在我看来，这是承担巨大假设风险的。在进入解决方案的讨论前，应该明确的是两个问题：一是这是不是一个问题？二这个问题是不是我们应该最先解决的？如果这两个问题没有被很好的回答，除非运气极好，最后的结果无非是解决了个根本不是问题的问题，或者解决了不该现在解决的问题。</p>
<p><strong>不愿意做小</strong></p>
<p>很多人热衷于颠覆性的设计，而不愿意做小的改进，把创造等同于创意。我对这个问题的理解是，当你没有很好定义出典型用户、场景、和他们在场景中遇到的具体问题，而是用一个宽泛的断言代替设计方向，那么设计就会变得巨大。</p>
<p>如果你的设计挑战是如何让老人变得快乐，你设计很可能变得漫无边际；而如果你的设计挑战是如何让在中山公园组织老人活动的老王更好地宣传他们的社团使得更多人参加，你的设计就可能变得实际和具体。</p>
<p>也许有人说，那么你设计的东西就会变得狭隘，这是限制创新，其实并不是，当你深入到老人的情境中，梳理出更多基于真实故事的设计挑战，例如：如何让老人院的张爷爷记住自己喜欢的电视节目；如何让他锻炼自己的手指头；如何鼓励中山公园的社团参与者更多资助社团活动等等，这一系列小的设计挑战被解决以后，自然是整个体验的提升，自然是一件大的事情。</p>
<p>体验设计中把设计环节需要的心智模型（mentality）定义为“可实现”（rationality），而把发现问题环节定义为“创造力”（creativity）确实不无道理，创造力应该体现在发现具体问题并转化成具体设计挑战的过程中，而设计过程应是切中要害，最忌天马行空，没有商业和技术支持的设计不产生任何价值。</p>
<p><strong>说多过于画</strong></p>
<p>在表达解决方案的时候，我仿佛回到了H公司的需求讨论现场，要么所有人都在说，要么只听一个人说，其他人不敢说，没有人使用任何可视化的工具引导讨论，后来我画了几张关于解决方案的草图才让无休止的讨论回到正轨。</p>
<p>这就是为什么我们更加注重视觉引导的能力──如果可能事先把设计过程的框架用视觉化的方式搭建好；尽可能地使用白板，持续不断地把已经达成一致的东西写在白板上；更好使用贴纸的颜色，及时对信息进行组织和验证；对同一个设计挑战分组进行草图设计并展示，避免<strong>设计被那些口才好，强势有气场的人绑架</strong>。</p>
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/20120400_193740.jpg" rel="lightbox[19561]" title="熊子川：体验设计师可以改进的5个习惯"><img class="aligncenter size-full wp-image-19566" title="熊子川：体验设计师可以改进的5个习惯" src="http://blog.jobbole.com/wp-content/uploads/2012/05/20120400_193740.jpg" alt="熊子川：体验设计师可以改进的5个习惯" width="560" height="420" /></a><br />
<small>图中右下角是我们最后的故事板，添加了一些草图后使得沟通更加有效率，其他两副图展示了我们做workshop的时候推崇的过程可视化的场景，大量使用草图、白板、并随时将过程产物贴在墙上。</small></p>
<p><strong>写在最后</strong></p>
<p>我能理解这样的活动不需要太多条条框框的设计方法进行限制，这只是我的一些思考和经验分享，并不代表大家是不够格的设计师。</p>
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/20120400_200355.jpg" rel="lightbox[19561]" title="熊子川：体验设计师可以改进的5个习惯"><img class="aligncenter size-full wp-image-19567" title="熊子川：体验设计师可以改进的5个习惯" src="http://blog.jobbole.com/wp-content/uploads/2012/05/20120400_200355.jpg" alt="熊子川：体验设计师可以改进的5个习惯" width="560" height="420" /></a></p>
<p>&nbsp;</p>
<p>另外非常感谢<a href="http://www.techyizu.org/">techyizu</a>组织这么好的活动，我曾经在<a href="http://www.tuzei8.com/?p=267">牛津参加Design Jam</a>，组织形式类似，它有个环节是在报名时每个人需要提供一个角色：例如designer, developer, 或者strategist等，以保证每个设计团队有足够平衡，供参考。但这个全球性的活动当时并没有用户研究的环节，而正是这个深入用户进行研究的活动真正让我学习到了很多东西，谢谢大家的努力，也希望不久的将来能在北京看到类似的活动。</p>
<p id="aeaoofnhgocdbnbeljkmbjdmhbcokfdb-mousedown"><strong>最后的最后</strong></p>
<p>如果你发现这篇文章实际上是六个习惯而不是五个习惯，那么你真的没有除了上面五个习惯之外，设计师应该改进的第六个习惯：不会数数。无论如何，至少你仔细看了，应该谢谢你。</p>
<h2  class="related_post_title">相关文章</h2><ul class="related_post"><li><a target="_blank" href="http://blog.jobbole.com/18440/" title="如何创造出优秀的用户体验">如何创造出优秀的用户体验</a></li><li><a target="_blank" href="http://blog.jobbole.com/18214/" title="敏捷体验设计师应该具备的12项技能">敏捷体验设计师应该具备的12项技能</a></li><li><a target="_blank" href="http://blog.jobbole.com/17889/" title="韩峰：谁之错？">韩峰：谁之错？</a></li><li><a target="_blank" href="http://blog.jobbole.com/15458/" title="程杰：技术文章如何才能有较好的阅读体验">程杰：技术文章如何才能有较好的阅读体验</a></li><li><a target="_blank" href="http://blog.jobbole.com/14198/" title="对话设计师专家：我们是如何招聘UX设计师的">对话设计师专家：我们是如何招聘UX设计师的</a></li><li><a target="_blank" href="http://blog.jobbole.com/13788/" title="为用户设计舒适的姿势">为用户设计舒适的姿势</a></li><li><a target="_blank" href="http://blog.jobbole.com/13438/" title="一个页面重构工程师眼中的“用户体验” ">一个页面重构工程师眼中的“用户体验” </a></li><li><a target="_blank" href="http://blog.jobbole.com/12999/" title="向Google学习打造灵动的web体验">向Google学习打造灵动的web体验</a></li><li><a target="_blank" href="http://blog.jobbole.com/12934/" title="优秀用户体验的五点提示">优秀用户体验的五点提示</a></li><li><a target="_blank" href="http://blog.jobbole.com/10049/" title="怎样通过更好的用户体验促进网站转化率的提升">怎样通过更好的用户体验促进网站转化率的提升</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.jobbole.com/19561/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NoSQL 数据建模技术</title>
		<link>http://blog.jobbole.com/19533/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=nosql-%25e6%2595%25b0%25e6%258d%25ae%25e5%25bb%25ba%25e6%25a8%25a1%25e6%258a%2580%25e6%259c%25af</link>
		<comments>http://blog.jobbole.com/19533/#comments</comments>
		<pubDate>Tue, 15 May 2012 03:36:20 +0000</pubDate>
		<dc:creator>童海波</dc:creator>
				<category><![CDATA[IT技术]]></category>
		<category><![CDATA[NoSQL]]></category>

		<guid isPermaLink="false">http://blog.jobbole.com/?p=19533</guid>
		<description><![CDATA[<p id="">全文译自墙外文章“<a href="http://highlyscalable.wordpress.com/2012/03/01/nosql-data-modeling-techniques/" target="_blank">NoSQL Data Modeling Techniques</a>”，译得不好，还请见谅。这篇文章看完之后，你可能会对NoSQL的数据结构会有些感觉。我的感觉是，关系型数据库想把一致性，完整性，索引，CRUD都干好，NoSQL只干某一种事，但是牺牲了很多别的东西。总体来说，我觉得NoSQL更适合做Cache。下面是正文——</p>
<p id="">NoSQL 数据库经常被用作很多非功能性的地方，如，扩展性，性能和一致性的地方。这些NoSQL的特性在理论和实践中都正在被大众广泛地研究着，研究的热点正是那些和性能分布式相关的非功能性的东西，我们都知道 <a href="http://en.wikipedia.org/wiki/CAP_theorem">CAP 理论</a>被很好地应用于了 NoSQL 系统中（陈皓注：CAP即，一致性(Consistency)， 可用性(Availability)， 分区容忍性(Partition tolerance)，在分布式系统中，这三个要素最多只能同时实现两个，而NoSQL一般放弃的是一致性）。但在另一方面，NoSQL的数据建模技术却因为缺乏像关系型数据库那样的基础理论没有被世人很好地研究。这篇文章从数据建模方面对NoSQL家族进行了比较，并讨论几个常见的数据建模技术。</p>
要开始讨论数据建模技术，我们不得不或多或少地先系统地看一下NoSQL数据模型的成长的趋势，以此我们可以了解一些他们内在的联系。下图是NoSQL家族的进化图，我们可以看到这样的进化：Key-Value时代，BigTable时代，Document时代，全文搜索时代，和Graph数据库时代：（陈皓注：注意图中SQL说的那句话，NoSQL再这样发展下去就是SQL了，哈哈。）
<div id="attachment_310">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/overview2.png"><img class="aligncenter size-full wp-image-19535" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/overview2.png" alt="NoSQL 数据建模技术" width="594" height="699" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/overview2.png">
</a>NoSQL Data Models</p>

</div>
首先，我们需要注意的是SQL和关系型数据模型已存在了很长的时间，这种面向用户的自然性意味着：

● 最终用户一般更感兴趣于数据的聚合显示，而不是分离的数据，这主要通过SQL来完成。

● 我们无法通过人手工控制数据的并发性，完整性，一致性，或是数据类型校验这些东西的。这就是为什么SQL需要在事务，二维表结构（schema）和外表联合上做很多事。

另一方面，SQL可以让软件应用程序在很多情况下不需要关心数据库的数据聚合，和数据完整性和有效性进行控制。而如果我们去除了数据一致性，完整性这些东西，会对性能和分布存储有着重的帮助。正因为如此，我们才有数据模型的进化：

<strong>● Key-Value 键值对存储</strong>是非常简单而强大的。下面的很多技术基本上都是基于这个技术开始发展的。但是，Key-Value有一个非常致命的问题，那就是如果我们需要查找一段范围内的key。（陈皓注：学过hash-table数据结构的人都应该知道，hash-table是非序列容器，其并不像数组，链接，队列这些有序容器，我们可以控制数据存储的顺序）。于是，有序键值 （Ordered Key-Value） 数据模型被设计出来解决这一限制，来从根本上提高数据集的问题。

<strong>● Ordered Key-Value 有序键值</strong>模型也非常强大，但是，其也没有对Value提供某种数据模型。通常来说，Value的模型可以由应用负责解析和存取。这种很不方便，于是出现了 BigTable类型的数据库，这个数据模型其实就是map里有map，map里再套map，一层一层套下去，也就是层层嵌套的key-value（value里又是一个key-value），这种数据库的Value主要通过“列族”（column families），列，和时间戳来控制版本。（陈皓注：关于时间戳来对数据的版本控制主要是解决数据存储并发问题，也就是所谓的乐观锁，详见《<a title="多版本并发控制(MVCC)在分布式系统中的应用" href="http://coolshell.cn/articles/6790.html" target="_blank">多版本并发控制(MVCC)在分布式系统中的应用</a>》）

<strong>● Document databases 文档数据库</strong> 改进了 BigTable 模型，并提供了两个有意义的改善。第一个是允许Value中有主观的模式（scheme），而不是map套map。第二个是索引。 <strong>Full Text Search Engines 全文搜索引擎</strong>可以被看作是文档数据库的一个变种，他们可以提供灵活的可变的数据模式（scheme）以及自动索引。他们之间的不同点主要是，文档数据库用字段名做索引，而全文搜索引擎用字段值做索引。

<strong>● Graph data models 图式数据库</strong> 可以被认为是这个进化过程中从 Ordered Key-Value 数据库发展过来的一个分支。图式数据库允许构建议图结构的数据模型。它和文档数据库有关系的原因是，它的很多实现允许value可以是一个map或是一个document。

<strong>NoSQL 数据模型摘要</strong>

本文剩下的章节将向你介绍数据建模的技术实现和相关模式。但是，在介绍这些技术之前，先来一段序言：

● NoSQL 数据模型设计一般从业务应用的具体数据查询入手，而不是数据间的关系：
<p style="padding-left: 30px;">● 关系型的数据模型基本上是分析数据间的结构和关系。其设计理念是： ”<strong>What answers do I have?”</strong></p>
<p style="padding-left: 30px;"><strong></strong>● NoSQL 数据模型基本上是从应用对数据的存取方式入手，如：我需要支持某种数据查询。其设计理念是<strong> ”What questions do I have?”</strong></p>
<strong></strong>● NoSQL 数据模型设计比关系型数据库需要对数据结构和算法的更深的了解。在这篇文章中我会和大家说那些尽人皆知的数据结构，这些数据结构并不只是被NoSQL使用，但是对于NoSQL的数据模型却非常有帮助。

● 数据冗余和反规格化是一等公民。

● 关系型数据库对于处理层级数据和图式数据非常的不方便。NoSQL用来解决图式数据明显是一个非常好的解决方案，几乎所有的NoSQL数据库可以很强地解决此类问题。这就是为什么这篇文章专门拿出一章来说明层级数据模型。

下面是NoSQL的分类表，也是我用来写这篇文章时做实践的产品：

● Key-Value 存储: Oracle Coherence, Redis, Kyoto Cabinet

● 类BigTable存储: Apache HBase, Apache Cassandra

● 文档数据库: MongoDB, CouchDB

● 全文索引: Apache Lucene, Apache Solr

● 图数据库: neo4j, FlockDB

<strong>概念技术 Conceptual Techniques</strong>

这一节主要介绍NoSQL数据模型的基本原则。

<strong>(1) 反规格化 Denormalization</strong>

反规格化 Denormalization 可以被认为是把相同的数据拷贝到不同的文档或是表中，这样就可以简化和优化查询，或是正好适合用户的某中特别的数据模型。这篇文章中所说的绝大多数技术都或多或少地导向了这一技术。

总体来说，反规格化需要权衡下面这些东西：

<strong><em>● 查询数据量 /查询IO </em></strong> VS  <strong><em>总数据量</em></strong>。使用反规格化，一方面可以把一条查询语句所需要的所有数据组合起来放到一个地方存储。这意味着，其它不同不同查询所需要的相同的数据，需要放在别不同的地方。因此，这产生了很多冗余的数据，从而导致了数据量的增大。

<strong><em>● 处理复杂度 </em></strong> VS <strong><em>总数据量</em></strong>. 在符合范式的数据模式上进行表连接的查询，很显然会增加了查询处理的复杂度，尤其对于分布式系统来说更是。反规格化的数据模型允许我们以方便查询的方式来存构造数据结构以简化查询复杂度。

<strong>适用性</strong>: Key-Value Store 键值对数据库， Document Databases文档数据库， BigTable风格的数据库。

<strong>(2) 聚合 Aggregates</strong>

所有类型的NoSQL数据库都会提供灵活的Schema（数据结构，对数据格式的限制）：

● Key-Value Stores 和 Graph Databases 基本上来说不会Value的形式，所以Value可以是任意格式。这样一来，这使得我们可以任意组合一个业务实体的keys。比如，我们有一个用户帐号的业务实体，其可以被如下这些key组合起来： <em>UserID_name, UserID_email, UserID_messages</em> 等等。如果一个用户没有email或message，那么相应也不会有这样的记录。

● BigTable 模型通过列集合来支持灵活的Schema，我们称之为列族（<em>column family</em>）。BigTable还可以在同一记录上出现不同的版本（通过时间戳）。

● Document databases 文档数据库是一种层级式的“去Schema”的存储，虽然有些这样的数据库允许检验需要保存的数据是否满足某种Schema。

灵活的Schema允许你可以用一种嵌套式的内部数据方式来存储一组有关联的业务实体（陈皓注：类似于JSON这样的数据封装格式）。这样可以为我们带来两个好处。

● 最小化“一对多”关系——可以通过嵌套式的方式来存储实体，这样可以少一些表联结。

● 可以让内部技术上的数据存储更接近于业务实体，特别是那种混合式的业务实体。可能存于一个文档集或是一张表中。

下图示意了这两种好处。图中描给了电子商务中的商品模型（陈皓注：我记得我在“<a title="挑战无处不在" href="http://coolshell.cn/articles/7048.html" target="_blank">挑战无处不在</a>”一文中说到过电商中产品分类数据库设计的挑战）

● 首先，所有的商品Product都会有一个ID，Price 和 Description。

● 然后，我们可以知道不同的类型的商品会有不同的属性。比如，作者是书的属性，长度是牛仔裤的属性。其些属性可能是“一对多”或是“多对多”的关系，如：唱片中的曲目。

● 接下来，我们知道，某些业务实体不可能使用固定的类型。如：牛仔裤的属性并不是所有的牌子都有的，而且，有些名牌还会搞非常特别的属性。
<div>

对于关系型数据库来说，要设计这样的数据模型并不简单，而且设计出来的绝对离优雅很远很远。而我们NoSQL中灵活的Schema允许你使用一个聚合 Aggregate (product) 可以建出所有不同种类的商品和他们的不同的属性：

</div>
<div>
<div id="attachment_404">

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/soft-schema2.png"><img class="aligncenter size-full wp-image-19536" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/soft-schema2.png" alt="NoSQL 数据建模技术" width="594" height="439" /></a>
<p style="text-align: center;">Entity Aggregation</p>

</div>
</div>
<div>

上图中我们可以比较关系型数据库和NoSQL的差别。<strong>但是我们可以看到在数据更新上，非规格化的数据存储在性能和一致性上会有很大的影响，这就是我们需要重点注意和不得不牺牲的地方</strong>。

</div>
<strong>适用性</strong>: Key-Value Store 键值对数据库， Document Databases文档数据库， BigTable风格的数据库。

<strong>(3) 应用层联结 Application Side Joins</strong>

表联结基本上不被NoSQL支持。正如我们前面所说的，NoSQL是“面向问题”而不是“面向答案”的，不支持表联结就是“面向问题”的后果。表的联结是在设计时被构造出来的，而不是在执行时建造出来的。所以，表联结在运行时是有很大开销的（陈皓注：搞过SQL表联结的都知道笛卡尔积是什么东西，大可以在参看以前酷壳的“<a title="图解SQL的Join" href="http://coolshell.cn/articles/3463.html" target="_blank">图解数据库表Joins</a>”），但是在使用了 Denormalization 和 Aggregates 技术后，我们基本不用进行表联结，如：你们使用嵌套式的数据实体。当然，如果你需要联结数据，你需要在应用层完成这个事。下面是几个主要的Use Case：

● 多对多的数据实体关系——经常需要被连接或联结。

● 聚合 Aggregates 并不适用于数据字段经常被改变的情况。对此，我们需要把那些经常被改变的字段分到另外的表中，而在查询时我们需要联结数据。例如，我们有个Message系统可以有一个User实体，其包括了一个内嵌的Message实体。但是，如果用户不断在附加 message，那么，最好把message拆分到另一个独立的实体，但在查询时联结这User和Message这两个实体。如下图：

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/aggregates-joins.png"><img class="aligncenter size-full wp-image-19556" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/aggregates-joins.png" alt="NoSQL 数据建模技术" width="495" height="327" /></a>

<strong>适用性</strong>: Key-Value Store 键值对数据库， Document Databases文档数据库， BigTable风格的数据库， Graph Databases 图数据库。
<h4>通用建模技术 General Modeling Techniques</h4>
在本书中，我们将讨论NoSQL中各种不同的通用的数据建模技术。

<strong>(4) 原子聚合 Atomic Aggregates</strong>

很多NoSQL的数据库（并不是所有）在事务处理上都是短板。在某些情况下，他们可以通过分布式锁技术或是<a title="Implementation of MVCC Transactions for Key-Value Stores" href="http://highlyscalable.wordpress.com/2012/01/07/mvcc-transactions-key-value/" target="_blank">应用层管理的MVCC技术</a>来实现其事务性（陈皓注：可参看本站的“<a title="多版本并发控制(MVCC)在分布式系统中的应用" href="http://coolshell.cn/articles/6790.html">多版本并发控制(MVCC)在分布式系统中的应用</a>”）但是，通常来说只能使用聚合Aggregates技术来保证一些ACID原则。

这就是为什么我们的关系型数据库需要有强大的事务处理机制——因为关系型数据库的数据是被规格化存放在了不同的地方。所以，Aggregates聚合允许我们把一个业务实体存成一个文档、存成一行，存成一个key-value，这样就可以原子式的更新了：
<div id="attachment_409">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/atomic-aggregate1.png"><img class="aligncenter size-full wp-image-19537" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/atomic-aggregate1.png" alt="NoSQL 数据建模技术" width="533" height="373" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/atomic-aggregate1.png">
</a>Atomic Aggregates</p>

</div>
当然，原子聚合 Atomic Aggregates 这种数据模型并不能实现完全意义上的事务处理，但是如果支持原子性，锁，或 test-and-set 指令，那么， Atomic Aggregates 是可以适用的。

<strong><strong>适用性</strong>: </strong>Key-Value Store 键值对数据库， Document Databases文档数据库， BigTable风格的数据库。

<strong>(5) 可枚举键 Enumerable Keys</strong>

也许，对于无顺序的Key-Value最大的好处是业务实体可以被容易地hash以分区在多个服务器上。而排序了的key会把事情搞复杂，但是有些时候，一个应用能从排序key中获得很多好处，就算是数据库本身不提供这个功能。让我们来思考下email消息的数据模型：

1. 一些NoSQL的数据库提供原子计数器以允许生一些连续的ID。在这种情况下，我们可以使用 <em>userID_messageID</em> 来做为一个组合key。如果我们知道最新的message ID，就可以知道前一个message，也可能知道再前面和后面的Message。

2. Messages可以被打包。比如，每天的邮件包。这样，我们就可以对邮件按指定的时间段来遍历。

<strong><strong><strong>适用性</strong>: </strong></strong>Key-Value Store 键值对数据库<strong>。</strong>

<strong>(6) 降维 Dimensionality Reduction</strong>

Dimensionality Reduction 降维是一种技术可以允许把一个多维的数据映射成一个Key-Value或是其它非多给的数据模型。

传统的地理位置信息系统使用一些如“四分树<a href="http://en.wikipedia.org/wiki/Quadtree" target="_blank">QuadTree</a>” 或 “<a href="http://en.wikipedia.org/wiki/R-tree" target="_blank">R-Tree</a>” 来做地理位置索引。这些数据结构的内容需要被在适当的位置更新，并且，如果数据量很大的话，操作成本会很高。另一个方法是我们可以遍历一个二维的数据结构并把其扁平化成一个列表。一个众所周知的例子是<a href="http://en.wikipedia.org/wiki/Geohash" target="_blank">Geohash</a>（地理哈希）。一个Geohash使用“之字形”的路线扫描一个2维的空间，而且遍历中的移动可以被简单地用0和1来表示其方向，然后在移动的过程中产生0/1串。下图展示了这一算法：（陈皓注：先把地图分成四份，经度为第一位，纬度为第二位，于是左边的经度是0，右边的是1，纬度也一样，上面是为1，下面的为0，这样，经纬度就可以组合成01，11，00，10这四个值，其标识了四块区域，我们可以如此不断的递归地对每个区域进行四分，然后可以得到一串1和0组成的字串，然后使用0-9，b-z 去掉（去掉a, i, l, o）这32个字母进行base32编码得到一个8个长度的编码，这就是Geohash的算法）
<div id="attachment_398">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/geohash-traversal1.png"><img class="aligncenter size-full wp-image-19538" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/geohash-traversal1.png" alt="NoSQL 数据建模技术" width="384" height="500" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/geohash-traversal1.png">
</a>Geohash Index</p>

</div>
Geohash的最强大的功能是使用简单的位操作就可以知道两个区域间的距离，就像图中所示（陈皓：proximity框着的那两个，这个很像IP地址了）。Geohash把一个二维的坐标生生地变成了一个一维的数据模型，这就是降维技术。BigTable的降维技术参看到文章后面的 [6.1]。更多的关于Geohash和其它技术可以参看 [6.2] 和 [6.3]。

<strong><strong><strong>适用性</strong>:</strong></strong> Key-Value Store 键值对数据库， Document Databases文档数据库， BigTable风格的数据库。

<strong>(7) 索引表 Index Table</strong>

Index Table 索引表是一个非常直白的技术，其可以你在不支持索引的数据库中得到索引的好处。BigTable是这类最重要的数据库。这需要我们维护一个有相应存取模式的特别表。例如，我们有一个主表存着用户帐号，其可以被UserID存取。某查询需要查出某个城市里所有的用户，于是我们可以加入一张表，这张表用城市做主键，所有和这个城市相关的UserID是其Value，如下所示：
<div id="attachment_399">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/index-table.png"><img class="aligncenter size-full wp-image-19539" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/index-table.png" alt="NoSQL 数据建模技术" width="438" height="304" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/index-table.png">
</a>Index Table Example</p>

</div>
可见，城市索引表的需要和对主表用户表保持一致性，因此，主表的每一个更新可能需要对索引表进行更新，不然就是一个批处理更新。无论哪个方式，这都会损伤一些性能，因为需要保持一致性。

Index Table 索引表可以被认为是关系型数据库中的视图的等价物。

<strong>适用性</strong>: BigTable 数据库。

<strong>(8) 键组合索引 Composite Key Index</strong>

Composite key 键组合是一个很常用的技术，对此，当我们的数据库支持键排序时能得到极大的好处。Composite key组合键的拼接成为第二排序字段可以让你构建出一种多维索引，这很像我们之前说过的 Dimensionality Reduction 降维技术。例如，我们需要存取用户统计。如果我们需要根据不同的地区来统计用户的分布情况，我们可以把Key设计成这样的格式 <em>(State:City:UserID)</em>，这样一来，就使得我们可以通过State到City来按组遍历用户，特别是我们的NoSQL数据库支持在key上按区查询（如：BigTable类的系统）：
<pre class="brush: sql; gutter: true">SELECT Values WHERE state=&#34;CA:*&#34;
SELECT Values WHERE city=&#34;CA:San Francisco*&#34;</pre>
&#160;
<div id="attachment_477">

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/composite-key-index.png"><img class="aligncenter size-full wp-image-19557" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/composite-key-index.png" alt="NoSQL 数据建模技术" width="397" height="297" /></a>
<p style="text-align: center;">Composite Key Index</p>

</div>
<strong><strong>适用性</strong>: </strong>BigTable 数据库。

<strong>(9) 键组合聚合 Aggregation with Composite Keys</strong>

Composite keys  键组合技术并不仅仅可以用来做索引，同样可以用来区分不用的类型的数据以支持数据分组。考虑一个例子，我们有一个海量的日志数组，这个日志记录了互联网上的用户的访问来源。我们需要计算从某一网站过来的独立访客的数量，在关系型数据库中，我们可能需要下面这样的SQL查询语句：
<pre class="brush: sql; gutter: true">SELECT count(distinct(user_id)) FROM clicks GROUP BY site</pre>
我们可以在NoSQL中建立如下的数据模型：
<div id="attachment_383">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/composite-key-collating1.png"><img class="aligncenter size-full wp-image-19540" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/composite-key-collating1.png" alt="NoSQL 数据建模技术" width="575" height="256" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/composite-key-collating1.png">
</a>Counting Unique Users using Composite Keys</p>

</div>
这样，我们就可以把数据按UserID来排序，我们就可以很容易把同一个用户的数据（一个用户并不会产生太多的event）进行处理，去掉那些重复的站点（使用hash table或是别的什么）。另一个可选的技术是，我们可以对每一个用户建立一个数据实体，然后把其站点来源追加到这个数据实体中，当然，这样一来，数据的更新在性能相比之下会有一定损失。

<strong><strong>适用性</strong>:</strong> Ordered Key-Value Store 排序键值对数据库， BigTable风格的数据库。

<strong>
</strong>

<strong>(10) 反转搜索 Inverted Search – 直接聚合 Direct Aggregation</strong>

这个技术更多的是数据处理技术，而不是数据建模技术。尽管如此，这个技术还是会影响数据模型。这个技术最主要的想法是使用一个索引来找到满足某条件的数据，但是把数据聚合起需要使用全文搜索。还是让我们来说一个示例。还是用上面那个例子，我们有很多的日志，其中包括互联网用户和他们的访问来源。让我们假定每条记录都有一个UserID，还有用户的种类 (Men, Women, Bloggers, 等)，以及用户所在的城市，和访问过的站点。我们要干的事是，为每个用户种类找到满足某些条件（访问源，所在城市，等）的的独立用户。

很明显，我们需要搜索那些满足条件的用户，如果我们使用反转搜索，这会让我们把这事干得很容易，如： <em>{Category -&#62; [user IDs]}</em> 或 <em>{Site -&#62; [user IDs]}</em>。使用这样的索引， 我们可以取两个或多个UserID要的交集或并集（这个事很容易干，而且可以干得很快，如果这些UserID是排好序的）。但是，我们要按用户种类来生成报表会变得有点麻烦，因为我们用语句可能会像下面这样
<pre class="brush: sql; gutter: true">SELECT count(distinct(user_id)) ... GROUP BY category</pre>
但这样的SQL很没有效率，因为category数据太多了。为了应对这个问题，我们可以建立一个直接索引 <em>{UserID -&#62; [Categories]}</em> 然后我们用它来生成报表：
<div id="attachment_388">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/invert-direct1.png"><img class="aligncenter size-full wp-image-19541" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/invert-direct1.png" alt="NoSQL 数据建模技术" width="594" height="438" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/invert-direct1.png">
</a>Counting Unique Users using Inverse and Direct Indexes</p>

</div>
最后，我们需要明白，对每个UserID的随机查询是很没有效率的。我们可以通过批查询处理来解决这个问题。这意味着，对于一些用户集，我们可以进行预处理（不同的查询条件）。

<strong>适用性</strong>: Key-Value Store 键值对数据库， Document Databases文档数据库， BigTable风格的数据库。
<h4>层级式模型 Hierarchy Modeling Techniques</h4>
<strong>(11) 树形聚合Tree Aggregation</strong>

树形或是任意的图（需反规格化）可以被直接打成一条记录或文档存放。

● 当树形结构被一次性取出时这会非常有效率（如：我们需要展示一个blog的树形评论）

● 搜索和任何存取这个实体都会存在问题。

● 对于大多数NoSQL的实现来说，更新数据都是很不经济的（相比起独立结点来说）
<div id="attachment_381">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/tree-aggregation.png"><img class="aligncenter size-full wp-image-19542" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/tree-aggregation.png" alt="NoSQL 数据建模技术" width="442" height="504" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/tree-aggregation.png">
</a>Tree Aggregation</p>

</div>
<strong>适用性</strong>: Key-Value 键值对数据库, Document Databases 文档数据库

<strong>(12) 邻接列表 Adjacency Lists</strong>

Adjacency Lists 邻接列表是一种图 – 每一个结点都是一个独立的记录，其包含了 所有的父结点或子结点。这样，我们就可以通过给定的父或子结点来进行搜索。当然，我们需要通过hop查询遍历图。这个技术在广度和深度查询，以及得到某个结点的子树上没有效率。

<strong>适用性</strong>: Key-Value 键值对数据库, Document Databases 文档数据库

<strong>(13) Materialized Paths</strong>

Materialized Paths 可以帮助避免递归遍历（如：树形结构）。这个技术也可以被认为是反规格化的一种变种。其想法是为每个结点加上父结点或子结点的标识属性，这样就可以不需要遍历就知道所有的后裔结点和祖先结点了：
<div id="attachment_372">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/materialized-paths2.png"><img class="aligncenter size-full wp-image-19543" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/materialized-paths2.png" alt="NoSQL 数据建模技术" width="588" height="330" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/materialized-paths2.png">
</a>Materialized Paths for eShop Category Hierarchy</p>

</div>
这个技术对于全文搜索引擎来说非常有帮助，因为其可以允许把一个层级结构转成一个文档。上面的示图中我们可以看到所有的商品或<em>Men’s Shoes</em>下的子分类可以被一条很短的查询语句处理——只需要给定个分类名。

Materialized Paths 可以存储一个ID的集合，或是一堆ID拼出的字符串。后者允许你通过一个正则表达式来搜索一个特定的分支路径。下图展示了这个技术（分支的路径包括了结点本身）：
<div id="attachment_377">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/materialized-paths-2.png"><img class="aligncenter size-full wp-image-19544" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/materialized-paths-2.png" alt="NoSQL 数据建模技术" width="415" height="300" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/materialized-paths-2.png">
</a>Query Materialized Paths using RegExp</p>

</div>
<strong>适用性</strong>: Key-Value 键值对数据库, Document Databases 文档数据, Search Engines 搜索引擎

<strong>(14) 嵌套集 Nested Sets</strong>

<a href="http://en.wikipedia.org/wiki/Nested_set_model">Nested sets</a> 嵌套集是树形结构的标准技术。它被广泛地用在了关系性数据库中，它完全地适用于 Key-Value 键值对数据库 和 Document Databases 文档数据库。这个技术的想法是把叶子结点存储成一个数组，并通过使用索引的开始和结束来映射每一个非叶子结点到一个叶子结点集，就如下图所示一样：
<div id="attachment_360">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/nested-sets.png"><img class="aligncenter size-full wp-image-19545" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/nested-sets.png" alt="NoSQL 数据建模技术" width="522" height="522" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/nested-sets.png">
</a>Modeling of eCommerce Catalog using Nested Sets</p>

</div>
这样的数据结构对于immutable data不变的数据 有非常不错的效率，因为其点内存空间小，并且可以很快地找出所有的叶子结点而不需要树的遍历。尽管如此，在插入和更新上需要很高的性能成本，因为新的叶子结点需要大规模地更新索引。

<strong>适用性</strong>: Key-Value Stores 键值数据库, Document Databases 文档数据库

<strong>(15) 嵌套文档扁平化：有限的字段名 Nested Documents Flattening: Numbered Field Names</strong>

搜索引擎基本上来说和扁平文档一同工作，如：每一个文档是一个扁平的字段和值的例表。这种数据模型的用来把业务实体映射到一个文本文档上，如果你的业务实体有很复杂的内部结构，这可能会变得很有挑战。一个典型的挑战是把一个有层级的文档映映射出来。例如，文档中嵌套另一个文档。让我们看看下面的示例：
<div id="attachment_363">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/nested-documents-1.png"><img class="aligncenter size-full wp-image-19546" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/nested-documents-1.png" alt="NoSQL 数据建模技术" width="489" height="216" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/nested-documents-1.png">
</a>Nested Documents Problem</p>

</div>
上面的每一个业务实体代码一种简历。其包括了人名和一个技能列表。我把这个层级文档映射成一个文本文档，一种方法是创建 <em>Skill</em> 和 <em>Level</em> 字段。这个模型可以通过技术或是等级来搜索一个人，而上图标注的那样的组合查询则会失败。（陈皓注：因为分不清Excellent是否是Math还是Poetry上的）

在引用中的 [4.6] 给出了一种解决方案。其为每个字段都标上数字 <em>Skill_i</em> 和 <em>Level_i</em>，这样就可以分开搜索每一个对（下图中使用了OR来遍历查找所有可能的字段）:
<div id="attachment_365">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/nested-documents-3.png"><img class="aligncenter size-full wp-image-19547" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/nested-documents-3.png" alt="NoSQL 数据建模技术" width="540" height="273" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/nested-documents-3.png">
</a>Nested Document Modeling using Numbered Field Names</p>

</div>
这样的方式根本没有扩展性，对于一些复杂的问题来说只会让代码复杂度和维护工作变大。

<strong>适用性</strong>: Search Engines 全文搜索

<strong>(16)嵌套文档扁平化：邻近查询 Nested Documents Flattening: Proximity Queries</strong>

在附录 [4.6]中给出了这个技术用来解决扁平层次文档。它用邻近的查询来限制可被查询的单词的范围。下图中，所有的技能和等级被放在一个字段中，叫 SkillAndLevel，查询中出现的 “Excellent” 和 “Poetry” 必需一个紧跟另一个：
<div id="attachment_364">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/nested-documents-2.png"><img class="aligncenter size-full wp-image-19548" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/nested-documents-2.png" alt="NoSQL 数据建模技术" width="584" height="218" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/nested-documents-2.png">
</a>Nested Document Modeling using Proximity Queries</p>

</div>
附录 [4.3] 中讲述了这个技术被用在Solr中的一个成功案例。

<strong>适用性</strong>: Search Engines 全文搜索

<strong>(17) 图结构批处理 Batch Graph Processing</strong>

Graph databases 图数据库，如 neo4j 是一个出众的图数据库，尤其是使用一个结点来探索邻居结点，或是探索两个或少量结点前的关系。但是处理大量的图数据是很没有效率的，因为图数据库的性能和扩展性并不是其目的。分布式的图数据处理可以被 MapReduce 和 Message Passing pattern 来处理。如： <a title="MapReduce Patterns, Algorithms, and Use Cases" href="http://highlyscalable.wordpress.com/2012/02/01/mapreduce-patterns/">在我前一篇的文章中的那个示例</a>。这个方法可以让 Key-Value stores, Document databases, 和 BigTable-style databases 适合于处理大图。

<strong>Applicability</strong>: Key-Value Stores, Document Databases, BigTable-style Databases
<h4>参考</h4>
Finally, I provide a list of useful links related to NoSQL data modeling:

1. Key-Value Stores:
<p style="padding-left: 30px;">1. <a href="http://www.devshed.com/c/a/MySQL/Database-Design-Using-KeyValue-Tables/">http://www.devshed.com/c/a/MySQL/Database-Design-Using-KeyValue-Tables/</a></p>
<p style="padding-left: 30px;">2. <a href="http://antirez.com/post/Sorting-in-key-value-data-model.html">http://antirez.com/post/Sorting-in-key-value-data-model.htm</a>l</p>
<p style="padding-left: 30px;">3. <a href="http://stackoverflow.com/questions/3554169/difference-between-document-based-and-key-value-based-databases">http://stackoverflow.com/questions/3554169/difference-between-document-based-and-key-value-based-databases</a></p>
<p style="padding-left: 30px;">4. <a href="http://dbmsmusings.blogspot.com/2010/03/distinguishing-two-major-types-of_29.html">http://dbmsmusings.blogspot.com/2010/03/distinguishing-two-major-types-of_29.html</a></p>
2. BigTable-style Databases:
<p style="padding-left: 30px;">1. <a href="http://www.slideshare.net/ebenhewitt/cassandra-datamodel-4985524">http://www.slideshare.net/ebenhewitt/cassandra-datamodel-4985524</a></p>
<p style="padding-left: 30px;">2. <a href="http://www.slideshare.net/mattdennis/cassandra-data-modeling">http://www.slideshare.net/mattdennis/cassandra-data-modeling</a></p>
<p style="padding-left: 30px;">3. <a href="http://nosql.mypopescu.com/post/17419074362/cassandra-data-modeling-examples-with-matthew-f-dennis">http://nosql.mypopescu.com/post/17419074362/cassandra-data-modeling-examples-with-matthew-f-dennis</a></p>
<p style="padding-left: 30px;">4. <a href="http://s-expressions.com/2009/03/08/hbase-on-designing-schemas-for-column-oriented-data-stores/">http://s-expressions.com/2009/03/08/hbase-on-designing-schemas-for-column-oriented-data-stores/</a></p>
<p style="padding-left: 30px;">5. <a href="http://jimbojw.com/wiki/index.php?title=Understanding_Hbase_and_BigTable">http://jimbojw.com/wiki/index.php?title=Understanding_Hbase_and_BigTable</a></p>
3. Document Databases:
<p style="padding-left: 30px;">1. <a href="http://www.slideshare.net/mongodb/mongodb-schema-design-richard-kreuters-mongo-berlin-preso">http://www.slideshare.net/mongodb/mongodb-schema-design-richard-kreuters-mongo-berlin-preso</a></p>
<p style="padding-left: 30px;">2. <a href="http://www.michaelhamrah.com/blog/2011/08/data-modeling-at-scale-mongodb-mongoid-callbacks-and-denormalizing-data-for-efficiency/">http://www.michaelhamrah.com/blog/2011/08/data-modeling-at-scale-mongodb-mongoid-callbacks-and-denormalizing-data-for-efficiency/</a></p>
<p style="padding-left: 30px;">3. <a href="http://seancribbs.com/tech/2009/09/28/modeling-a-tree-in-a-document-database/">http://seancribbs.com/tech/2009/09/28/modeling-a-tree-in-a-document-database/</a></p>
<p style="padding-left: 30px;">4. <a href="http://www.mongodb.org/display/DOCS/Schema+Design">http://www.mongodb.org/display/DOCS/Schema+Design</a></p>
<p style="padding-left: 30px;">5. <a href="http://www.mongodb.org/display/DOCS/Trees+in+MongoDB">http://www.mongodb.org/display/DOCS/Trees+in+MongoDB</a></p>
<p style="padding-left: 30px;">6. <a href="http://blog.fiesta.cc/post/11319522700/walkthrough-mongodb-data-modeling">http://blog.fiesta.cc/post/11319522700/walkthrough-mongodb-data-modeling</a></p>
4. Full Text Search Engines:
<p style="padding-left: 30px;">1. <a href="http://www.searchworkings.org/blog/-/blogs/query-time-joining-in-lucene">http://www.searchworkings.org/blog/-/blogs/query-time-joining-in-lucene</a></p>
<p style="padding-left: 30px;">2. <a href="http://www.lucidimagination.com/devzone/technical-articles/solr-and-rdbms-basics-designing-your-application-best-both">http://www.lucidimagination.com/devzone/technical-articles/solr-and-rdbms-basics-designing-your-application-best-both</a></p>
<p style="padding-left: 30px;">3. <a href="http://blog.griddynamics.com/2011/07/solr-experience-search-parent-child.html">http://blog.griddynamics.com/2011/07/solr-experience-search-parent-child.html</a></p>
<p style="padding-left: 30px;">4. <a href="http://www.lucidimagination.com/blog/2009/07/18/the-spanquery/">http://www.lucidimagination.com/blog/2009/07/18/the-spanquery/</a></p>
<p style="padding-left: 30px;">5. <a href="http://blog.mgm-tp.com/2011/03/non-standard-ways-of-using-lucene/">http://blog.mgm-tp.com/2011/03/non-standard-ways-of-using-lucene/</a></p>
<p style="padding-left: 30px;">6. <a href="http://www.slideshare.net/MarkHarwood/proposal-for-nested-document-support-in-lucene">http://www.slideshare.net/MarkHarwood/proposal-for-nested-document-support-in-lucene</a></p>
<p style="padding-left: 30px;">7. <a href="http://mysolr.com/tips/denormalized-data-structure/">http://mysolr.com/tips/denormalized-data-structure/</a></p>
<p style="padding-left: 30px;">8. <a href="http://sujitpal.blogspot.com/2010/10/denormalizing-maps-with-lucene-payloads.html">http://sujitpal.blogspot.com/2010/10/denormalizing-maps-with-lucene-payloads.html</a></p>
<p style="padding-left: 30px;">9. <a href="http://java.dzone.com/articles/hibernate-search-mapping-entit">http://java.dzone.com/articles/hibernate-search-mapping-entit</a></p>
5. Graph Databases:
<p style="padding-left: 30px;">1. <a href="http://docs.neo4j.org/chunked/stable/tutorial-comparing-models.html">http://docs.neo4j.org/chunked/stable/tutorial-comparing-models.html</a></p>
<p style="padding-left: 30px;">2. <a href="http://blog.neo4j.org/2010/03/modeling-categories-in-graph-database.html">http://blog.neo4j.org/2010/03/modeling-categories-in-graph-database.html</a></p>
<p style="padding-left: 30px;">3. <a href="http://skillsmatter.com/podcast/nosql/graph-modelling">http://skillsmatter.com/podcast/nosql/graph-modelling</a></p>
<p style="padding-left: 30px;">4. <a href="http://www.umiacs.umd.edu/~jimmylin/publications/Lin_Schatz_MLG2010.pdf">http://www.umiacs.umd.edu/~jimmylin/publications/Lin_Schatz_MLG2010.pdf</a></p>
6. Demensionality Reduction:
<p style="padding-left: 30px;">1. <a href="http://www.slideshare.net/mmalone/scaling-gis-data-in-nonrelational-data-stores">http://www.slideshare.net/mmalone/scaling-gis-data-in-nonrelational-data-stores</a></p>
<p style="padding-left: 30px;">2. <a href="http://blog.notdot.net/2009/11/Damn-Cool-Algorithms-Spatial-indexing-with-Quadtrees-and-Hilbert-Curves">http://blog.notdot.net/2009/11/Damn-Cool-Algorithms-Spatial-indexing-with-Quadtrees-and-Hilbert-Curves</a></p>
<p style="padding-left: 30px;">3. <a href="http://www.trisis.co.uk/blog/?p=1287">http://www.trisis.co.uk/blog/?p=1287</a></p>
（全文完）]]></description>
			<content:encoded><![CDATA[<p id="">全文译自墙外文章“<a href="http://highlyscalable.wordpress.com/2012/03/01/nosql-data-modeling-techniques/" target="_blank">NoSQL Data Modeling Techniques</a>”，译得不好，还请见谅。这篇文章看完之后，你可能会对NoSQL的数据结构会有些感觉。我的感觉是，关系型数据库想把一致性，完整性，索引，CRUD都干好，NoSQL只干某一种事，但是牺牲了很多别的东西。总体来说，我觉得NoSQL更适合做Cache。下面是正文——</p>
<p id="">NoSQL 数据库经常被用作很多非功能性的地方，如，扩展性，性能和一致性的地方。这些NoSQL的特性在理论和实践中都正在被大众广泛地研究着，研究的热点正是那些和性能分布式相关的非功能性的东西，我们都知道 <a href="http://en.wikipedia.org/wiki/CAP_theorem">CAP 理论</a>被很好地应用于了 NoSQL 系统中（陈皓注：CAP即，一致性(Consistency)， 可用性(Availability)， 分区容忍性(Partition tolerance)，在分布式系统中，这三个要素最多只能同时实现两个，而NoSQL一般放弃的是一致性）。但在另一方面，NoSQL的数据建模技术却因为缺乏像关系型数据库那样的基础理论没有被世人很好地研究。这篇文章从数据建模方面对NoSQL家族进行了比较，并讨论几个常见的数据建模技术。</p>
<p>要开始讨论数据建模技术，我们不得不或多或少地先系统地看一下NoSQL数据模型的成长的趋势，以此我们可以了解一些他们内在的联系。下图是NoSQL家族的进化图，我们可以看到这样的进化：Key-Value时代，BigTable时代，Document时代，全文搜索时代，和Graph数据库时代：（陈皓注：注意图中SQL说的那句话，NoSQL再这样发展下去就是SQL了，哈哈。）</p>
<div id="attachment_310">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/overview2.png" rel="lightbox[19533]" title="NoSQL 数据建模技术"><img class="aligncenter size-full wp-image-19535" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/overview2.png" alt="NoSQL 数据建模技术" width="594" height="699" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/overview2.png"><br />
</a>NoSQL Data Models</p>
</div>
<p>首先，我们需要注意的是SQL和关系型数据模型已存在了很长的时间，这种面向用户的自然性意味着：</p>
<p>● 最终用户一般更感兴趣于数据的聚合显示，而不是分离的数据，这主要通过SQL来完成。</p>
<p>● 我们无法通过人手工控制数据的并发性，完整性，一致性，或是数据类型校验这些东西的。这就是为什么SQL需要在事务，二维表结构（schema）和外表联合上做很多事。</p>
<p>另一方面，SQL可以让软件应用程序在很多情况下不需要关心数据库的数据聚合，和数据完整性和有效性进行控制。而如果我们去除了数据一致性，完整性这些东西，会对性能和分布存储有着重的帮助。正因为如此，我们才有数据模型的进化：</p>
<p><strong>● Key-Value 键值对存储</strong>是非常简单而强大的。下面的很多技术基本上都是基于这个技术开始发展的。但是，Key-Value有一个非常致命的问题，那就是如果我们需要查找一段范围内的key。（陈皓注：学过hash-table数据结构的人都应该知道，hash-table是非序列容器，其并不像数组，链接，队列这些有序容器，我们可以控制数据存储的顺序）。于是，有序键值 （Ordered Key-Value） 数据模型被设计出来解决这一限制，来从根本上提高数据集的问题。</p>
<p><strong>● Ordered Key-Value 有序键值</strong>模型也非常强大，但是，其也没有对Value提供某种数据模型。通常来说，Value的模型可以由应用负责解析和存取。这种很不方便，于是出现了 BigTable类型的数据库，这个数据模型其实就是map里有map，map里再套map，一层一层套下去，也就是层层嵌套的key-value（value里又是一个key-value），这种数据库的Value主要通过“列族”（column families），列，和时间戳来控制版本。（陈皓注：关于时间戳来对数据的版本控制主要是解决数据存储并发问题，也就是所谓的乐观锁，详见《<a title="多版本并发控制(MVCC)在分布式系统中的应用" href="http://coolshell.cn/articles/6790.html" target="_blank">多版本并发控制(MVCC)在分布式系统中的应用</a>》）</p>
<p><strong>● Document databases 文档数据库</strong> 改进了 BigTable 模型，并提供了两个有意义的改善。第一个是允许Value中有主观的模式（scheme），而不是map套map。第二个是索引。 <strong>Full Text Search Engines 全文搜索引擎</strong>可以被看作是文档数据库的一个变种，他们可以提供灵活的可变的数据模式（scheme）以及自动索引。他们之间的不同点主要是，文档数据库用字段名做索引，而全文搜索引擎用字段值做索引。</p>
<p><strong>● Graph data models 图式数据库</strong> 可以被认为是这个进化过程中从 Ordered Key-Value 数据库发展过来的一个分支。图式数据库允许构建议图结构的数据模型。它和文档数据库有关系的原因是，它的很多实现允许value可以是一个map或是一个document。</p>
<p><strong>NoSQL 数据模型摘要</strong></p>
<p>本文剩下的章节将向你介绍数据建模的技术实现和相关模式。但是，在介绍这些技术之前，先来一段序言：</p>
<p>● NoSQL 数据模型设计一般从业务应用的具体数据查询入手，而不是数据间的关系：</p>
<p style="padding-left: 30px;">● 关系型的数据模型基本上是分析数据间的结构和关系。其设计理念是： ”<strong>What answers do I have?”</strong></p>
<p style="padding-left: 30px;"><strong></strong>● NoSQL 数据模型基本上是从应用对数据的存取方式入手，如：我需要支持某种数据查询。其设计理念是<strong> ”What questions do I have?”</strong></p>
<p><strong></strong>● NoSQL 数据模型设计比关系型数据库需要对数据结构和算法的更深的了解。在这篇文章中我会和大家说那些尽人皆知的数据结构，这些数据结构并不只是被NoSQL使用，但是对于NoSQL的数据模型却非常有帮助。</p>
<p>● 数据冗余和反规格化是一等公民。</p>
<p>● 关系型数据库对于处理层级数据和图式数据非常的不方便。NoSQL用来解决图式数据明显是一个非常好的解决方案，几乎所有的<span class='wp_keywordlink'><a href="http://blog.jobbole.com/1344/" title="8种Nosql数据库系统对比">nosql数据库</a></span>可以很强地解决此类问题。这就是为什么这篇文章专门拿出一章来说明层级数据模型。</p>
<p>下面是NoSQL的分类表，也是我用来写这篇文章时做实践的产品：</p>
<p>● Key-Value 存储: Oracle Coherence, Redis, Kyoto Cabinet</p>
<p>● 类BigTable存储: Apache HBase, Apache Cassandra</p>
<p>● 文档数据库: MongoDB, CouchDB</p>
<p>● 全文索引: Apache Lucene, Apache Solr</p>
<p>● 图数据库: neo4j, FlockDB</p>
<p><strong>概念技术 Conceptual Techniques</strong></p>
<p>这一节主要介绍NoSQL数据模型的基本原则。</p>
<p><strong>(1) 反规格化 Denormalization</strong></p>
<p>反规格化 Denormalization 可以被认为是把相同的数据拷贝到不同的文档或是表中，这样就可以简化和优化查询，或是正好适合用户的某中特别的数据模型。这篇文章中所说的绝大多数技术都或多或少地导向了这一技术。</p>
<p>总体来说，反规格化需要权衡下面这些东西：</p>
<p><strong><em>● 查询数据量 /查询IO </em></strong> VS  <strong><em>总数据量</em></strong>。使用反规格化，一方面可以把一条查询语句所需要的所有数据组合起来放到一个地方存储。这意味着，其它不同不同查询所需要的相同的数据，需要放在别不同的地方。因此，这产生了很多冗余的数据，从而导致了数据量的增大。</p>
<p><strong><em>● 处理复杂度 </em></strong> VS <strong><em>总数据量</em></strong>. 在符合范式的数据模式上进行表连接的查询，很显然会增加了查询处理的复杂度，尤其对于分布式系统来说更是。反规格化的数据模型允许我们以方便查询的方式来存构造数据结构以简化查询复杂度。</p>
<p><strong>适用性</strong>: Key-Value Store 键值对数据库， Document Databases文档数据库， BigTable风格的数据库。</p>
<p><strong>(2) 聚合 Aggregates</strong></p>
<p>所有类型的NoSQL数据库都会提供灵活的Schema（数据结构，对数据格式的限制）：</p>
<p>● Key-Value Stores 和 Graph Databases 基本上来说不会Value的形式，所以Value可以是任意格式。这样一来，这使得我们可以任意组合一个业务实体的keys。比如，我们有一个用户帐号的业务实体，其可以被如下这些key组合起来： <em>UserID_name, UserID_email, UserID_messages</em> 等等。如果一个用户没有email或message，那么相应也不会有这样的记录。</p>
<p>● BigTable 模型通过列集合来支持灵活的Schema，我们称之为列族（<em>column family</em>）。BigTable还可以在同一记录上出现不同的版本（通过时间戳）。</p>
<p>● Document databases 文档数据库是一种层级式的“去Schema”的存储，虽然有些这样的数据库允许检验需要保存的数据是否满足某种Schema。</p>
<p>灵活的Schema允许你可以用一种嵌套式的内部数据方式来存储一组有关联的业务实体（陈皓注：类似于JSON这样的数据封装格式）。这样可以为我们带来两个好处。</p>
<p>● 最小化“一对多”关系——可以通过嵌套式的方式来存储实体，这样可以少一些表联结。</p>
<p>● 可以让内部技术上的数据存储更接近于业务实体，特别是那种混合式的业务实体。可能存于一个文档集或是一张表中。</p>
<p>下图示意了这两种好处。图中描给了电子商务中的商品模型（陈皓注：我记得我在“<a title="挑战无处不在" href="http://coolshell.cn/articles/7048.html" target="_blank">挑战无处不在</a>”一文中说到过电商中产品分类数据库设计的挑战）</p>
<p>● 首先，所有的商品Product都会有一个ID，Price 和 Description。</p>
<p>● 然后，我们可以知道不同的类型的商品会有不同的属性。比如，作者是书的属性，长度是牛仔裤的属性。其些属性可能是“一对多”或是“多对多”的关系，如：唱片中的曲目。</p>
<p>● 接下来，我们知道，某些业务实体不可能使用固定的类型。如：牛仔裤的属性并不是所有的牌子都有的，而且，有些名牌还会搞非常特别的属性。</p>
<div>
<p>对于关系型数据库来说，要设计这样的数据模型并不简单，而且设计出来的绝对离优雅很远很远。而我们NoSQL中灵活的Schema允许你使用一个聚合 Aggregate (product) 可以建出所有不同种类的商品和他们的不同的属性：</p>
</div>
<div>
<div id="attachment_404">
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/soft-schema2.png" rel="lightbox[19533]" title="NoSQL 数据建模技术"><img class="aligncenter size-full wp-image-19536" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/soft-schema2.png" alt="NoSQL 数据建模技术" width="594" height="439" /></a></p>
<p style="text-align: center;">Entity Aggregation</p>
</div>
</div>
<div>
<p>上图中我们可以比较关系型数据库和NoSQL的差别。<strong>但是我们可以看到在数据更新上，非规格化的数据存储在性能和一致性上会有很大的影响，这就是我们需要重点注意和不得不牺牲的地方</strong>。</p>
</div>
<p><strong>适用性</strong>: Key-Value Store 键值对数据库， Document Databases文档数据库， BigTable风格的数据库。</p>
<p><strong>(3) 应用层联结 Application Side Joins</strong></p>
<p>表联结基本上不被NoSQL支持。正如我们前面所说的，NoSQL是“面向问题”而不是“面向答案”的，不支持表联结就是“面向问题”的后果。表的联结是在设计时被构造出来的，而不是在执行时建造出来的。所以，表联结在运行时是有很大开销的（陈皓注：搞过SQL表联结的都知道笛卡尔积是什么东西，大可以在参看以前酷壳的“<a title="图解SQL的Join" href="http://coolshell.cn/articles/3463.html" target="_blank">图解数据库表Joins</a>”），但是在使用了 Denormalization 和 Aggregates 技术后，我们基本不用进行表联结，如：你们使用嵌套式的数据实体。当然，如果你需要联结数据，你需要在应用层完成这个事。下面是几个主要的Use Case：</p>
<p>● 多对多的数据实体关系——经常需要被连接或联结。</p>
<p>● 聚合 Aggregates 并不适用于数据字段经常被改变的情况。对此，我们需要把那些经常被改变的字段分到另外的表中，而在查询时我们需要联结数据。例如，我们有个Message系统可以有一个User实体，其包括了一个内嵌的Message实体。但是，如果用户不断在附加 message，那么，最好把message拆分到另一个独立的实体，但在查询时联结这User和Message这两个实体。如下图：</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/aggregates-joins.png" rel="lightbox[19533]" title="NoSQL 数据建模技术"><img class="aligncenter size-full wp-image-19556" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/aggregates-joins.png" alt="NoSQL 数据建模技术" width="495" height="327" /></a></p>
<p><strong>适用性</strong>: Key-Value Store 键值对数据库， Document Databases文档数据库， BigTable风格的数据库， Graph Databases 图数据库。</p>
<h4>通用建模技术 General Modeling Techniques</h4>
<p>在本书中，我们将讨论NoSQL中各种不同的通用的数据建模技术。</p>
<p><strong>(4) 原子聚合 Atomic Aggregates</strong></p>
<p>很多NoSQL的数据库（并不是所有）在事务处理上都是短板。在某些情况下，他们可以通过分布式锁技术或是<a title="Implementation of MVCC Transactions for Key-Value Stores" href="http://highlyscalable.wordpress.com/2012/01/07/mvcc-transactions-key-value/" target="_blank">应用层管理的MVCC技术</a>来实现其事务性（陈皓注：可参看本站的“<a title="多版本并发控制(MVCC)在分布式系统中的应用" href="http://coolshell.cn/articles/6790.html">多版本并发控制(MVCC)在分布式系统中的应用</a>”）但是，通常来说只能使用聚合Aggregates技术来保证一些ACID原则。</p>
<p>这就是为什么我们的关系型数据库需要有强大的事务处理机制——因为关系型数据库的数据是被规格化存放在了不同的地方。所以，Aggregates聚合允许我们把一个业务实体存成一个文档、存成一行，存成一个key-value，这样就可以原子式的更新了：</p>
<div id="attachment_409">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/atomic-aggregate1.png" rel="lightbox[19533]" title="NoSQL 数据建模技术"><img class="aligncenter size-full wp-image-19537" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/atomic-aggregate1.png" alt="NoSQL 数据建模技术" width="533" height="373" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/atomic-aggregate1.png"><br />
</a>Atomic Aggregates</p>
</div>
<p>当然，原子聚合 Atomic Aggregates 这种数据模型并不能实现完全意义上的事务处理，但是如果支持原子性，锁，或 test-and-set 指令，那么， Atomic Aggregates 是可以适用的。</p>
<p><strong><strong>适用性</strong>: </strong>Key-Value Store 键值对数据库， Document Databases文档数据库， BigTable风格的数据库。</p>
<p><strong>(5) 可枚举键 Enumerable Keys</strong></p>
<p>也许，对于无顺序的Key-Value最大的好处是业务实体可以被容易地hash以分区在多个服务器上。而排序了的key会把事情搞复杂，但是有些时候，一个应用能从排序key中获得很多好处，就算是数据库本身不提供这个功能。让我们来思考下email消息的数据模型：</p>
<p>1. 一些NoSQL的数据库提供原子计数器以允许生一些连续的ID。在这种情况下，我们可以使用 <em>userID_messageID</em> 来做为一个组合key。如果我们知道最新的message ID，就可以知道前一个message，也可能知道再前面和后面的Message。</p>
<p>2. Messages可以被打包。比如，每天的邮件包。这样，我们就可以对邮件按指定的时间段来遍历。</p>
<p><strong><strong><strong>适用性</strong>: </strong></strong>Key-Value Store 键值对数据库<strong>。</strong></p>
<p><strong>(6) 降维 Dimensionality Reduction</strong></p>
<p>Dimensionality Reduction 降维是一种技术可以允许把一个多维的数据映射成一个Key-Value或是其它非多给的数据模型。</p>
<p>传统的地理位置信息系统使用一些如“四分树<a href="http://en.wikipedia.org/wiki/Quadtree" target="_blank">QuadTree</a>” 或 “<a href="http://en.wikipedia.org/wiki/R-tree" target="_blank">R-Tree</a>” 来做地理位置索引。这些数据结构的内容需要被在适当的位置更新，并且，如果数据量很大的话，操作成本会很高。另一个方法是我们可以遍历一个二维的数据结构并把其扁平化成一个列表。一个众所周知的例子是<a href="http://en.wikipedia.org/wiki/Geohash" target="_blank">Geohash</a>（地理哈希）。一个Geohash使用“之字形”的路线扫描一个2维的空间，而且遍历中的移动可以被简单地用0和1来表示其方向，然后在移动的过程中产生0/1串。下图展示了这一算法：（陈皓注：先把地图分成四份，经度为第一位，纬度为第二位，于是左边的经度是0，右边的是1，纬度也一样，上面是为1，下面的为0，这样，经纬度就可以组合成01，11，00，10这四个值，其标识了四块区域，我们可以如此不断的递归地对每个区域进行四分，然后可以得到一串1和0组成的字串，然后使用0-9，b-z 去掉（去掉a, i, l, o）这32个字母进行base32编码得到一个8个长度的编码，这就是Geohash的算法）</p>
<div id="attachment_398">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/geohash-traversal1.png" rel="lightbox[19533]" title="NoSQL 数据建模技术"><img class="aligncenter size-full wp-image-19538" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/geohash-traversal1.png" alt="NoSQL 数据建模技术" width="384" height="500" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/geohash-traversal1.png"><br />
</a>Geohash Index</p>
</div>
<p>Geohash的最强大的功能是使用简单的位操作就可以知道两个区域间的距离，就像图中所示（陈皓：proximity框着的那两个，这个很像IP地址了）。Geohash把一个二维的坐标生生地变成了一个一维的数据模型，这就是降维技术。BigTable的降维技术参看到文章后面的 [6.1]。更多的关于Geohash和其它技术可以参看 [6.2] 和 [6.3]。</p>
<p><strong><strong><strong>适用性</strong>:</strong></strong> Key-Value Store 键值对数据库， Document Databases文档数据库， BigTable风格的数据库。</p>
<p><strong>(7) 索引表 Index Table</strong></p>
<p>Index Table 索引表是一个非常直白的技术，其可以你在不支持索引的数据库中得到索引的好处。BigTable是这类最重要的数据库。这需要我们维护一个有相应存取模式的特别表。例如，我们有一个主表存着用户帐号，其可以被UserID存取。某查询需要查出某个城市里所有的用户，于是我们可以加入一张表，这张表用城市做主键，所有和这个城市相关的UserID是其Value，如下所示：</p>
<div id="attachment_399">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/index-table.png" rel="lightbox[19533]" title="NoSQL 数据建模技术"><img class="aligncenter size-full wp-image-19539" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/index-table.png" alt="NoSQL 数据建模技术" width="438" height="304" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/index-table.png"><br />
</a>Index Table Example</p>
</div>
<p>可见，城市索引表的需要和对主表用户表保持一致性，因此，主表的每一个更新可能需要对索引表进行更新，不然就是一个批处理更新。无论哪个方式，这都会损伤一些性能，因为需要保持一致性。</p>
<p>Index Table 索引表可以被认为是关系型数据库中的视图的等价物。</p>
<p><strong>适用性</strong>: BigTable 数据库。</p>
<p><strong>(8) 键组合索引 Composite Key Index</strong></p>
<p>Composite key 键组合是一个很常用的技术，对此，当我们的数据库支持键排序时能得到极大的好处。Composite key组合键的拼接成为第二排序字段可以让你构建出一种多维索引，这很像我们之前说过的 Dimensionality Reduction 降维技术。例如，我们需要存取用户统计。如果我们需要根据不同的地区来统计用户的分布情况，我们可以把Key设计成这样的格式 <em>(State:City:UserID)</em>，这样一来，就使得我们可以通过State到City来按组遍历用户，特别是我们的NoSQL数据库支持在key上按区查询（如：BigTable类的系统）：</p>
<pre class="brush: sql; gutter: true">SELECT Values WHERE state=&quot;CA:*&quot;
SELECT Values WHERE city=&quot;CA:San Francisco*&quot;</pre>
<p>&nbsp;</p>
<div id="attachment_477">
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/composite-key-index.png" rel="lightbox[19533]" title="NoSQL 数据建模技术"><img class="aligncenter size-full wp-image-19557" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/composite-key-index.png" alt="NoSQL 数据建模技术" width="397" height="297" /></a></p>
<p style="text-align: center;">Composite Key Index</p>
</div>
<p><strong><strong>适用性</strong>: </strong>BigTable 数据库。</p>
<p><strong>(9) 键组合聚合 Aggregation with Composite Keys</strong></p>
<p>Composite keys  键组合技术并不仅仅可以用来做索引，同样可以用来区分不用的类型的数据以支持数据分组。考虑一个例子，我们有一个海量的日志数组，这个日志记录了互联网上的用户的访问来源。我们需要计算从某一网站过来的独立访客的数量，在关系型数据库中，我们可能需要下面这样的SQL查询语句：</p>
<pre class="brush: sql; gutter: true">SELECT count(distinct(user_id)) FROM clicks GROUP BY site</pre>
<p>我们可以在NoSQL中建立如下的数据模型：</p>
<div id="attachment_383">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/composite-key-collating1.png" rel="lightbox[19533]" title="NoSQL 数据建模技术"><img class="aligncenter size-full wp-image-19540" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/composite-key-collating1.png" alt="NoSQL 数据建模技术" width="575" height="256" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/composite-key-collating1.png"><br />
</a>Counting Unique Users using Composite Keys</p>
</div>
<p>这样，我们就可以把数据按UserID来排序，我们就可以很容易把同一个用户的数据（一个用户并不会产生太多的event）进行处理，去掉那些重复的站点（使用hash table或是别的什么）。另一个可选的技术是，我们可以对每一个用户建立一个数据实体，然后把其站点来源追加到这个数据实体中，当然，这样一来，数据的更新在性能相比之下会有一定损失。</p>
<p><strong><strong>适用性</strong>:</strong> Ordered Key-Value Store 排序键值对数据库， BigTable风格的数据库。</p>
<p><strong><br />
</strong></p>
<p><strong>(10) 反转搜索 Inverted Search – 直接聚合 Direct Aggregation</strong></p>
<p>这个技术更多的是数据处理技术，而不是数据建模技术。尽管如此，这个技术还是会影响数据模型。这个技术最主要的想法是使用一个索引来找到满足某条件的数据，但是把数据聚合起需要使用全文搜索。还是让我们来说一个示例。还是用上面那个例子，我们有很多的日志，其中包括互联网用户和他们的访问来源。让我们假定每条记录都有一个UserID，还有用户的种类 (Men, Women, Bloggers, 等)，以及用户所在的城市，和访问过的站点。我们要干的事是，为每个用户种类找到满足某些条件（访问源，所在城市，等）的的独立用户。</p>
<p>很明显，我们需要搜索那些满足条件的用户，如果我们使用反转搜索，这会让我们把这事干得很容易，如： <em>{Category -&gt; [user IDs]}</em> 或 <em>{Site -&gt; [user IDs]}</em>。使用这样的索引， 我们可以取两个或多个UserID要的交集或并集（这个事很容易干，而且可以干得很快，如果这些UserID是排好序的）。但是，我们要按用户种类来生成报表会变得有点麻烦，因为我们用语句可能会像下面这样</p>
<pre class="brush: sql; gutter: true">SELECT count(distinct(user_id)) ... GROUP BY category</pre>
<p>但这样的SQL很没有效率，因为category数据太多了。为了应对这个问题，我们可以建立一个直接索引 <em>{UserID -&gt; [Categories]}</em> 然后我们用它来生成报表：</p>
<div id="attachment_388">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/invert-direct1.png" rel="lightbox[19533]" title="NoSQL 数据建模技术"><img class="aligncenter size-full wp-image-19541" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/invert-direct1.png" alt="NoSQL 数据建模技术" width="594" height="438" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/invert-direct1.png"><br />
</a>Counting Unique Users using Inverse and Direct Indexes</p>
</div>
<p>最后，我们需要明白，对每个UserID的随机查询是很没有效率的。我们可以通过批查询处理来解决这个问题。这意味着，对于一些用户集，我们可以进行预处理（不同的查询条件）。</p>
<p><strong>适用性</strong>: Key-Value Store 键值对数据库， Document Databases文档数据库， BigTable风格的数据库。</p>
<h4>层级式模型 Hierarchy Modeling Techniques</h4>
<p><strong>(11) 树形聚合Tree Aggregation</strong></p>
<p>树形或是任意的图（需反规格化）可以被直接打成一条记录或文档存放。</p>
<p>● 当树形结构被一次性取出时这会非常有效率（如：我们需要展示一个blog的树形评论）</p>
<p>● 搜索和任何存取这个实体都会存在问题。</p>
<p>● 对于大多数NoSQL的实现来说，更新数据都是很不经济的（相比起独立结点来说）</p>
<div id="attachment_381">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/tree-aggregation.png" rel="lightbox[19533]" title="NoSQL 数据建模技术"><img class="aligncenter size-full wp-image-19542" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/tree-aggregation.png" alt="NoSQL 数据建模技术" width="442" height="504" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/tree-aggregation.png"><br />
</a>Tree Aggregation</p>
</div>
<p><strong>适用性</strong>: Key-Value 键值对数据库, Document Databases 文档数据库</p>
<p><strong>(12) 邻接列表 Adjacency Lists</strong></p>
<p>Adjacency Lists 邻接列表是一种图 – 每一个结点都是一个独立的记录，其包含了 所有的父结点或子结点。这样，我们就可以通过给定的父或子结点来进行搜索。当然，我们需要通过hop查询遍历图。这个技术在广度和深度查询，以及得到某个结点的子树上没有效率。</p>
<p><strong>适用性</strong>: Key-Value 键值对数据库, Document Databases 文档数据库</p>
<p><strong>(13) Materialized Paths</strong></p>
<p>Materialized Paths 可以帮助避免递归遍历（如：树形结构）。这个技术也可以被认为是反规格化的一种变种。其想法是为每个结点加上父结点或子结点的标识属性，这样就可以不需要遍历就知道所有的后裔结点和祖先结点了：</p>
<div id="attachment_372">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/materialized-paths2.png" rel="lightbox[19533]" title="NoSQL 数据建模技术"><img class="aligncenter size-full wp-image-19543" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/materialized-paths2.png" alt="NoSQL 数据建模技术" width="588" height="330" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/materialized-paths2.png"><br />
</a>Materialized Paths for eShop Category Hierarchy</p>
</div>
<p>这个技术对于全文搜索引擎来说非常有帮助，因为其可以允许把一个层级结构转成一个文档。上面的示图中我们可以看到所有的商品或<em>Men’s Shoes</em>下的子分类可以被一条很短的查询语句处理——只需要给定个分类名。</p>
<p>Materialized Paths 可以存储一个ID的集合，或是一堆ID拼出的字符串。后者允许你通过一个正则表达式来搜索一个特定的分支路径。下图展示了这个技术（分支的路径包括了结点本身）：</p>
<div id="attachment_377">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/materialized-paths-2.png" rel="lightbox[19533]" title="NoSQL 数据建模技术"><img class="aligncenter size-full wp-image-19544" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/materialized-paths-2.png" alt="NoSQL 数据建模技术" width="415" height="300" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/materialized-paths-2.png"><br />
</a>Query Materialized Paths using RegExp</p>
</div>
<p><strong>适用性</strong>: Key-Value 键值对数据库, Document Databases 文档数据, Search Engines 搜索引擎</p>
<p><strong>(14) 嵌套集 Nested Sets</strong></p>
<p><a href="http://en.wikipedia.org/wiki/Nested_set_model">Nested sets</a> 嵌套集是树形结构的标准技术。它被广泛地用在了关系性数据库中，它完全地适用于 Key-Value 键值对数据库 和 Document Databases 文档数据库。这个技术的想法是把叶子结点存储成一个数组，并通过使用索引的开始和结束来映射每一个非叶子结点到一个叶子结点集，就如下图所示一样：</p>
<div id="attachment_360">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/nested-sets.png" rel="lightbox[19533]" title="NoSQL 数据建模技术"><img class="aligncenter size-full wp-image-19545" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/nested-sets.png" alt="NoSQL 数据建模技术" width="522" height="522" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/nested-sets.png"><br />
</a>Modeling of eCommerce Catalog using Nested Sets</p>
</div>
<p>这样的数据结构对于immutable data不变的数据 有非常不错的效率，因为其点内存空间小，并且可以很快地找出所有的叶子结点而不需要树的遍历。尽管如此，在插入和更新上需要很高的性能成本，因为新的叶子结点需要大规模地更新索引。</p>
<p><strong>适用性</strong>: Key-Value Stores 键值数据库, Document Databases 文档数据库</p>
<p><strong>(15) 嵌套文档扁平化：有限的字段名 Nested Documents Flattening: Numbered Field Names</strong></p>
<p>搜索引擎基本上来说和扁平文档一同工作，如：每一个文档是一个扁平的字段和值的例表。这种数据模型的用来把业务实体映射到一个文本文档上，如果你的业务实体有很复杂的内部结构，这可能会变得很有挑战。一个典型的挑战是把一个有层级的文档映映射出来。例如，文档中嵌套另一个文档。让我们看看下面的示例：</p>
<div id="attachment_363">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/nested-documents-1.png" rel="lightbox[19533]" title="NoSQL 数据建模技术"><img class="aligncenter size-full wp-image-19546" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/nested-documents-1.png" alt="NoSQL 数据建模技术" width="489" height="216" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/nested-documents-1.png"><br />
</a>Nested Documents Problem</p>
</div>
<p>上面的每一个业务实体代码一种简历。其包括了人名和一个技能列表。我把这个层级文档映射成一个文本文档，一种方法是创建 <em>Skill</em> 和 <em>Level</em> 字段。这个模型可以通过技术或是等级来搜索一个人，而上图标注的那样的组合查询则会失败。（陈皓注：因为分不清Excellent是否是Math还是Poetry上的）</p>
<p>在引用中的 [4.6] 给出了一种解决方案。其为每个字段都标上数字 <em>Skill_i</em> 和 <em>Level_i</em>，这样就可以分开搜索每一个对（下图中使用了OR来遍历查找所有可能的字段）:</p>
<div id="attachment_365">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/nested-documents-3.png" rel="lightbox[19533]" title="NoSQL 数据建模技术"><img class="aligncenter size-full wp-image-19547" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/nested-documents-3.png" alt="NoSQL 数据建模技术" width="540" height="273" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/nested-documents-3.png"><br />
</a>Nested Document Modeling using Numbered Field Names</p>
</div>
<p>这样的方式根本没有扩展性，对于一些复杂的问题来说只会让代码复杂度和维护工作变大。</p>
<p><strong>适用性</strong>: Search Engines 全文搜索</p>
<p><strong>(16)嵌套文档扁平化：邻近查询 Nested Documents Flattening: Proximity Queries</strong></p>
<p>在附录 [4.6]中给出了这个技术用来解决扁平层次文档。它用邻近的查询来限制可被查询的单词的范围。下图中，所有的技能和等级被放在一个字段中，叫 SkillAndLevel，查询中出现的 “Excellent” 和 “Poetry” 必需一个紧跟另一个：</p>
<div id="attachment_364">
<p style="text-align: center;"><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/nested-documents-2.png" rel="lightbox[19533]" title="NoSQL 数据建模技术"><img class="aligncenter size-full wp-image-19548" title="NoSQL 数据建模技术" src="http://blog.jobbole.com/wp-content/uploads/2012/05/nested-documents-2.png" alt="NoSQL 数据建模技术" width="584" height="218" /></a><a href="http://coolshell.cn/wp-content/uploads/2012/05/nested-documents-2.png"><br />
</a>Nested Document Modeling using Proximity Queries</p>
</div>
<p>附录 [4.3] 中讲述了这个技术被用在Solr中的一个成功案例。</p>
<p><strong>适用性</strong>: Search Engines 全文搜索</p>
<p><strong>(17) 图结构批处理 Batch Graph Processing</strong></p>
<p>Graph databases 图数据库，如 neo4j 是一个出众的图数据库，尤其是使用一个结点来探索邻居结点，或是探索两个或少量结点前的关系。但是处理大量的图数据是很没有效率的，因为图数据库的性能和扩展性并不是其目的。分布式的图数据处理可以被 MapReduce 和 Message Passing pattern 来处理。如： <a title="MapReduce Patterns, Algorithms, and Use Cases" href="http://highlyscalable.wordpress.com/2012/02/01/mapreduce-patterns/">在我前一篇的文章中的那个示例</a>。这个方法可以让 Key-Value stores, Document databases, 和 BigTable-style databases 适合于处理大图。</p>
<p><strong>Applicability</strong>: Key-Value Stores, Document Databases, BigTable-style Databases</p>
<h4>参考</h4>
<p>Finally, I provide a list of useful links related to NoSQL data modeling:</p>
<p>1. Key-Value Stores:</p>
<p style="padding-left: 30px;">1. <a href="http://www.devshed.com/c/a/MySQL/Database-Design-Using-KeyValue-Tables/">http://www.devshed.com/c/a/MySQL/Database-Design-Using-KeyValue-Tables/</a></p>
<p style="padding-left: 30px;">2. <a href="http://antirez.com/post/Sorting-in-key-value-data-model.html">http://antirez.com/post/Sorting-in-key-value-data-model.htm</a>l</p>
<p style="padding-left: 30px;">3. <a href="http://stackoverflow.com/questions/3554169/difference-between-document-based-and-key-value-based-databases">http://stackoverflow.com/questions/3554169/difference-between-document-based-and-key-value-based-databases</a></p>
<p style="padding-left: 30px;">4. <a href="http://dbmsmusings.blogspot.com/2010/03/distinguishing-two-major-types-of_29.html">http://dbmsmusings.blogspot.com/2010/03/distinguishing-two-major-types-of_29.html</a></p>
<p>2. BigTable-style Databases:</p>
<p style="padding-left: 30px;">1. <a href="http://www.slideshare.net/ebenhewitt/cassandra-datamodel-4985524">http://www.slideshare.net/ebenhewitt/cassandra-datamodel-4985524</a></p>
<p style="padding-left: 30px;">2. <a href="http://www.slideshare.net/mattdennis/cassandra-data-modeling">http://www.slideshare.net/mattdennis/cassandra-data-modeling</a></p>
<p style="padding-left: 30px;">3. <a href="http://nosql.mypopescu.com/post/17419074362/cassandra-data-modeling-examples-with-matthew-f-dennis">http://nosql.mypopescu.com/post/17419074362/cassandra-data-modeling-examples-with-matthew-f-dennis</a></p>
<p style="padding-left: 30px;">4. <a href="http://s-expressions.com/2009/03/08/hbase-on-designing-schemas-for-column-oriented-data-stores/">http://s-expressions.com/2009/03/08/hbase-on-designing-schemas-for-column-oriented-data-stores/</a></p>
<p style="padding-left: 30px;">5. <a href="http://jimbojw.com/wiki/index.php?title=Understanding_Hbase_and_BigTable">http://jimbojw.com/wiki/index.php?title=Understanding_Hbase_and_BigTable</a></p>
<p>3. Document Databases:</p>
<p style="padding-left: 30px;">1. <a href="http://www.slideshare.net/mongodb/mongodb-schema-design-richard-kreuters-mongo-berlin-preso">http://www.slideshare.net/mongodb/mongodb-schema-design-richard-kreuters-mongo-berlin-preso</a></p>
<p style="padding-left: 30px;">2. <a href="http://www.michaelhamrah.com/blog/2011/08/data-modeling-at-scale-mongodb-mongoid-callbacks-and-denormalizing-data-for-efficiency/">http://www.michaelhamrah.com/blog/2011/08/data-modeling-at-scale-mongodb-mongoid-callbacks-and-denormalizing-data-for-efficiency/</a></p>
<p style="padding-left: 30px;">3. <a href="http://seancribbs.com/tech/2009/09/28/modeling-a-tree-in-a-document-database/">http://seancribbs.com/tech/2009/09/28/modeling-a-tree-in-a-document-database/</a></p>
<p style="padding-left: 30px;">4. <a href="http://www.mongodb.org/display/DOCS/Schema+Design">http://www.mongodb.org/display/DOCS/Schema+Design</a></p>
<p style="padding-left: 30px;">5. <a href="http://www.mongodb.org/display/DOCS/Trees+in+MongoDB">http://www.mongodb.org/display/DOCS/Trees+in+MongoDB</a></p>
<p style="padding-left: 30px;">6. <a href="http://blog.fiesta.cc/post/11319522700/walkthrough-mongodb-data-modeling">http://blog.fiesta.cc/post/11319522700/walkthrough-mongodb-data-modeling</a></p>
<p>4. Full Text Search Engines:</p>
<p style="padding-left: 30px;">1. <a href="http://www.searchworkings.org/blog/-/blogs/query-time-joining-in-lucene">http://www.searchworkings.org/blog/-/blogs/query-time-joining-in-lucene</a></p>
<p style="padding-left: 30px;">2. <a href="http://www.lucidimagination.com/devzone/technical-articles/solr-and-rdbms-basics-designing-your-application-best-both">http://www.lucidimagination.com/devzone/technical-articles/solr-and-rdbms-basics-designing-your-application-best-both</a></p>
<p style="padding-left: 30px;">3. <a href="http://blog.griddynamics.com/2011/07/solr-experience-search-parent-child.html">http://blog.griddynamics.com/2011/07/solr-experience-search-parent-child.html</a></p>
<p style="padding-left: 30px;">4. <a href="http://www.lucidimagination.com/blog/2009/07/18/the-spanquery/">http://www.lucidimagination.com/blog/2009/07/18/the-spanquery/</a></p>
<p style="padding-left: 30px;">5. <a href="http://blog.mgm-tp.com/2011/03/non-standard-ways-of-using-lucene/">http://blog.mgm-tp.com/2011/03/non-standard-ways-of-using-lucene/</a></p>
<p style="padding-left: 30px;">6. <a href="http://www.slideshare.net/MarkHarwood/proposal-for-nested-document-support-in-lucene">http://www.slideshare.net/MarkHarwood/proposal-for-nested-document-support-in-lucene</a></p>
<p style="padding-left: 30px;">7. <a href="http://mysolr.com/tips/denormalized-data-structure/">http://mysolr.com/tips/denormalized-data-structure/</a></p>
<p style="padding-left: 30px;">8. <a href="http://sujitpal.blogspot.com/2010/10/denormalizing-maps-with-lucene-payloads.html">http://sujitpal.blogspot.com/2010/10/denormalizing-maps-with-lucene-payloads.html</a></p>
<p style="padding-left: 30px;">9. <a href="http://java.dzone.com/articles/hibernate-search-mapping-entit">http://java.dzone.com/articles/hibernate-search-mapping-entit</a></p>
<p>5. Graph Databases:</p>
<p style="padding-left: 30px;">1. <a href="http://docs.neo4j.org/chunked/stable/tutorial-comparing-models.html">http://docs.neo4j.org/chunked/stable/tutorial-comparing-models.html</a></p>
<p style="padding-left: 30px;">2. <a href="http://blog.neo4j.org/2010/03/modeling-categories-in-graph-database.html">http://blog.neo4j.org/2010/03/modeling-categories-in-graph-database.html</a></p>
<p style="padding-left: 30px;">3. <a href="http://skillsmatter.com/podcast/nosql/graph-modelling">http://skillsmatter.com/podcast/nosql/graph-modelling</a></p>
<p style="padding-left: 30px;">4. <a href="http://www.umiacs.umd.edu/~jimmylin/publications/Lin_Schatz_MLG2010.pdf">http://www.umiacs.umd.edu/~jimmylin/publications/Lin_Schatz_MLG2010.pdf</a></p>
<p>6. Demensionality Reduction:</p>
<p style="padding-left: 30px;">1. <a href="http://www.slideshare.net/mmalone/scaling-gis-data-in-nonrelational-data-stores">http://www.slideshare.net/mmalone/scaling-gis-data-in-nonrelational-data-stores</a></p>
<p style="padding-left: 30px;">2. <a href="http://blog.notdot.net/2009/11/Damn-Cool-Algorithms-Spatial-indexing-with-Quadtrees-and-Hilbert-Curves">http://blog.notdot.net/2009/11/Damn-Cool-Algorithms-Spatial-indexing-with-Quadtrees-and-Hilbert-Curves</a></p>
<p style="padding-left: 30px;">3. <a href="http://www.trisis.co.uk/blog/?p=1287">http://www.trisis.co.uk/blog/?p=1287</a></p>
<p>（全文完）</p>
<h2  class="related_post_title">相关文章</h2><ul class="related_post"><li><a target="_blank" href="http://blog.jobbole.com/19125/" title="MongoDB、Java与对象关系映射">MongoDB、Java与对象关系映射</a></li><li><a target="_blank" href="http://blog.jobbole.com/16390/" title="告别编程5年再次回归，我注意到很多变化">告别编程5年再次回归，我注意到很多变化</a></li><li><a target="_blank" href="http://blog.jobbole.com/14164/" title="2012年 NoSQL 就业趋势">2012年 NoSQL 就业趋势</a></li><li><a target="_blank" href="http://blog.jobbole.com/13081/" title="CouchDB 入门指南">CouchDB 入门指南</a></li><li><a target="_blank" href="http://blog.jobbole.com/12924/" title="MongoDB最佳实践">MongoDB最佳实践</a></li><li><a target="_blank" href="http://blog.jobbole.com/10084/" title="系统设计中最重要的概念">系统设计中最重要的概念</a></li><li><a target="_blank" href="http://blog.jobbole.com/9469/" title="NoSQL生态系统">NoSQL生态系统</a></li><li><a target="_blank" href="http://blog.jobbole.com/9426/" title="11个面向文档的开源NoSQL数据库">11个面向文档的开源NoSQL数据库</a></li><li><a target="_blank" href="http://blog.jobbole.com/5701/" title="千万别用MongoDB？真的吗？">千万别用MongoDB？真的吗？</a></li><li><a target="_blank" href="http://blog.jobbole.com/4902/" title="Oracle发布NoSQL数据库 ">Oracle发布NoSQL数据库 </a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.jobbole.com/19533/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>世界上首个“不可见”的广告</title>
		<link>http://blog.jobbole.com/19482/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25e4%25b8%2596%25e7%2595%258c%25e4%25b8%258a%25e9%25a6%2596%25e4%25b8%25aa%25e2%2580%259c%25e4%25b8%258d%25e5%258f%25af%25e8%25a7%2581%25e2%2580%259d%25e7%259a%2584%25e5%25b9%25bf%25e5%2591%258a</link>
		<comments>http://blog.jobbole.com/19482/#comments</comments>
		<pubDate>Tue, 15 May 2012 03:07:30 +0000</pubDate>
		<dc:creator>黄余粮</dc:creator>
				<category><![CDATA[营销]]></category>
		<category><![CDATA[视频营销]]></category>

		<guid isPermaLink="false">http://blog.jobbole.com/?p=19482</guid>
		<description><![CDATA[澳大利亚悉尼推出了首个（肉眼）不可见的广告。把多块特殊的LCD安放在一栋房子的6个窗户，然后播放视频。每个LCD播放的视频不同，其中有小狗游泳、猴子、一对恋人在浴室...，还有一对恋人在卧室...。其特别之处是肉眼看上去就像普通有灯的窗户，只有带着偏光太阳镜才可以看到播放的画面，而且很多人都会误以为这些是透过窗户所看到的真实情景。现场有很多人驻足观看这6个窗户。那些没有戴着偏光太阳镜的人一脸的疑惑，不知道发生了什么有趣的事；那些戴上偏光太阳镜的人则非常惊讶的在旁边大笑。而广告商则将这些一一拍摄下来，制作成视频，然后通过Youtube,Facebook和Twitter等进行传播。当然了，这个广告最终目的是为了宣传某个品牌的偏光太阳镜！

有兴趣的童鞋可以看看视频下面虚构的旁白和文章末尾的反思。
<p style="text-align: center;">[youku id="XMzk2NzcwOTc2" w="500" h="400"]</p>
片头

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/片头.png"><img class="alignnone size-full wp-image-19483" title="片头" src="http://blog.jobbole.com/wp-content/uploads/2012/05/片头.png" alt="" width="556" height="337" /></a>

布景，一所很平常的建筑

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/布景.png"><img class="alignnone size-full wp-image-19486" title="布景" src="http://blog.jobbole.com/wp-content/uploads/2012/05/布景.png" alt="" width="555" height="335" /></a>

夜幕降临，路过的人们肉眼看不出什么特别之处

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/夜幕降临.png"><img class="alignnone size-full wp-image-19487" title="夜幕降临" src="http://blog.jobbole.com/wp-content/uploads/2012/05/夜幕降临.png" alt="" width="553" height="332" /></a>

因为肉眼只能看到像是6扇点着灯的窗户

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/6扇点着灯的窗户.png"><img class="alignnone size-full wp-image-19488" title="6扇点着灯的窗户" src="http://blog.jobbole.com/wp-content/uploads/2012/05/6扇点着灯的窗户.png" alt="" width="553" height="336" /></a>

靓女把眼镜戴上

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/靓女把眼镜戴上.png"><img class="alignnone size-full wp-image-19498" title="靓女把眼镜戴上" src="http://blog.jobbole.com/wp-content/uploads/2012/05/靓女把眼镜戴上.png" alt="" width="553" height="338" /></a>

帅哥你也瞧瞧，特有意思～

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/帅哥你也瞧瞧.png"><img class="alignnone size-full wp-image-19493" title="帅哥你也瞧瞧" src="http://blog.jobbole.com/wp-content/uploads/2012/05/帅哥你也瞧瞧.png" alt="" width="549" height="334" /></a>

正在看的美眉非常惊叹，另外一个赶忙戴上，其他两位排队等候～

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/正在看的美眉非常惊叹.png"><img class="alignnone size-full wp-image-19494" title="正在看的美眉非常惊叹" src="http://blog.jobbole.com/wp-content/uploads/2012/05/正在看的美眉非常惊叹.png" alt="" width="553" height="338" /></a>

靠近点看～

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/靠近点看.png"><img class="alignnone size-full wp-image-19489" title="靠近点看" src="http://blog.jobbole.com/wp-content/uploads/2012/05/靠近点看.png" alt="" width="554" height="337" /></a>

“老大”们也来看了？

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/“老大”们也来看了.png"><img class="alignnone size-full wp-image-19500" title="“老大”们也来看了" src="http://blog.jobbole.com/wp-content/uploads/2012/05/“老大”们也来看了.png" alt="" width="552" height="336" /></a>

帅哥也有戴粉红色的？为何大家笑得如此High?

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/帅哥也有戴粉红色的.png"><img class="alignnone size-full wp-image-19492" title="帅哥也有戴粉红色的" src="http://blog.jobbole.com/wp-content/uploads/2012/05/帅哥也有戴粉红色的.png" alt="" width="552" height="336" /></a>

哦，原来有几个窗口少儿不宜！

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/原来有几个窗口少儿不宜.png"><img class="alignnone size-full wp-image-19491" title="原来有几个窗口少儿不宜" src="http://blog.jobbole.com/wp-content/uploads/2012/05/原来有几个窗口少儿不宜.png" alt="" width="556" height="339" /></a>

六个窗口的全景图

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/六个窗口的全景图.png"><img class="alignnone size-full wp-image-19490" title="六个窗口的全景图" src="http://blog.jobbole.com/wp-content/uploads/2012/05/六个窗口的全景图.png" alt="" width="555" height="336" /></a>

靓女都喜欢戴粉红色的太阳镜？

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/靓女都喜欢戴粉红色的太阳镜.png"><img class="alignnone size-full wp-image-19499" title="靓女都喜欢戴粉红色的太阳镜" src="http://blog.jobbole.com/wp-content/uploads/2012/05/靓女都喜欢戴粉红色的太阳镜.png" alt="" width="554" height="337" /></a>

警察叔叔也来看了～ Hey，禁止停车的指示牌下竟然有辆车？旁边还有警察？！

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/警察叔叔也来看了.png"><img class="alignnone size-full wp-image-19497" title="警察叔叔也来看了" src="http://blog.jobbole.com/wp-content/uploads/2012/05/警察叔叔也来看了.png" alt="" width="555" height="337" /></a>

给小狗狗也开开眼～ 不知道这只小狗喜欢看哪扇窗户？:)

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/给小狗狗也开开眼.png"><img class="alignnone size-full wp-image-19496" title="给小狗狗也开开眼" src="http://blog.jobbole.com/wp-content/uploads/2012/05/给小狗狗也开开眼.png" alt="" width="553" height="337" /></a>

片尾，“主角”现身了～

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/片尾.png"><img class="alignnone size-full wp-image-19495" title="片尾" src="http://blog.jobbole.com/wp-content/uploads/2012/05/片尾.png" alt="" width="555" height="335" /></a>

喻学于乐。看过这么一个有趣的营销案例，不妨反思一下我们学到了什么。我看过不少有创意的营销案例。比如：5月12日，<a href="http://www.weibo.com/u/2133846777">@营销的那些事</a> 分享了一个《<a href="http://www.weibo.com/2133846777/yiNQnFzhC">放胆干杯，你有胆量坐下吗？</a>》的营销视频。个人认为这类创新营销有一定的内在模式。简单地概括就是：结合需要推广的产品或者服务，策划出极具个性的营销方案，再拍摄并制作成视频，上传至Youtube等视频分享网站，然后通过Facebook, Twitter等社交媒体进行传播。

几点反思：

1. 该视频主要拍摄与晚上。谁会在晚上带太阳镜呢？猜想这是营销团队现场发放的太阳镜；

2. 为什么这个推广活动没有选在白天，而是晚上？

&#160;

对于这个“不可见”的广告，你认为还有哪些值得思考的地方？欢迎在评论中和我们一起分享～

大家的观点：

新浪微博 <a href="http://weibo.com/holom">@HolomJEWISH鄭</a> ："非常帅气的创意广告！香水的核心价值，用了它你可以得到不一样的东西！广告视频突出疑似产品内涵、夜生活、时尚、目标客户群。"

新浪微博 <a href="http://weibo.com/u/2133846777">@营销的那些事</a> ：这个视频广告把目标用户定位的很清晰。什么样的目标用户，就有什么样的广告表达。所以，我们不必过于去抱怨类似脑白金那样的广告。因为，即使脑白金的广告能做得像这个视频一样有创意，其结果只是：看得懂的人不会去买，可能会购买的人又看不懂。

&#160;

原文出处：<a href="http://blog.jobbole.com/19482">http://blog.jobbole.com/19482</a> 作者：<a href="http://www.jobbole.com/" target="_blank">伯乐</a>在线 – 黄余粮

【如需转载，请标注并保留原文链接、作者等信息，谢谢合作！】

&#160;]]></description>
			<content:encoded><![CDATA[<p>澳大利亚悉尼推出了首个（肉眼）不可见的广告。把多块特殊的LCD安放在一栋房子的6个窗户，然后播放视频。每个LCD播放的视频不同，其中有小狗游泳、猴子、一对恋人在浴室&#8230;，还有一对恋人在卧室&#8230;。其特别之处是肉眼看上去就像普通有灯的窗户，只有带着偏光太阳镜才可以看到播放的画面，而且很多人都会误以为这些是透过窗户所看到的真实情景。现场有很多人驻足观看这6个窗户。那些没有戴着偏光太阳镜的人一脸的疑惑，不知道发生了什么有趣的事；那些戴上偏光太阳镜的人则非常惊讶的在旁边大笑。而广告商则将这些一一拍摄下来，制作成视频，然后通过Youtube,Facebook和Twitter等进行传播。当然了，这个广告最终目的是为了宣传某个品牌的偏光太阳镜！</p>
<p>有兴趣的童鞋可以看看视频下面虚构的旁白和文章末尾的反思。</p>
<p style="text-align: center;"><object width="500" height="400"><param name="movie" value="http://player.youku.com/player.php/sid/XMzk2NzcwOTc2/v.swf"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="never"></param><param name="allownetworking" value="internal"></param><param name="flashvars" value="isShowRelatedVideo=false&showAd=0&show_pre=1&show_next=1&isAutoPlay=false&isDebug=false&UserID=&winType=interior&playMovie=true&MMControl=false&MMout=false&RecordCode=1001,1002,1003,1004,1005,1006,2001,3001,3002,3003,3004,3005,3007,3008,9999" /><embed src="http://player.youku.com/player.php/sid/XMzk2NzcwOTc2/v.swf" type="application/x-shockwave-flash" allowscriptaccess="never" allownetworking="internal" allowfullscreen="true" width="500" height="400" flashvars="isShowRelatedVideo=false&showAd=0&show_pre=1&show_next=1&isAutoPlay=false&isDebug=false&UserID=&winType=interior&playMovie=true&MMControl=false&MMout=false&RecordCode=1001,1002,1003,1004,1005,1006,2001,3001,3002,3003,3004,3005,3007,3008,9999"></embed></object></p>
<p>片头</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/片头.png" rel="lightbox[19482]" title="片头"><img class="alignnone size-full wp-image-19483" title="片头" src="http://blog.jobbole.com/wp-content/uploads/2012/05/片头.png" alt="" width="556" height="337" /></a></p>
<p>布景，一所很平常的建筑</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/布景.png" rel="lightbox[19482]" title="布景"><img class="alignnone size-full wp-image-19486" title="布景" src="http://blog.jobbole.com/wp-content/uploads/2012/05/布景.png" alt="" width="555" height="335" /></a></p>
<p>夜幕降临，路过的人们肉眼看不出什么特别之处</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/夜幕降临.png" rel="lightbox[19482]" title="夜幕降临"><img class="alignnone size-full wp-image-19487" title="夜幕降临" src="http://blog.jobbole.com/wp-content/uploads/2012/05/夜幕降临.png" alt="" width="553" height="332" /></a></p>
<p>因为肉眼只能看到像是6扇点着灯的窗户</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/6扇点着灯的窗户.png" rel="lightbox[19482]" title="6扇点着灯的窗户"><img class="alignnone size-full wp-image-19488" title="6扇点着灯的窗户" src="http://blog.jobbole.com/wp-content/uploads/2012/05/6扇点着灯的窗户.png" alt="" width="553" height="336" /></a></p>
<p>靓女把眼镜戴上</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/靓女把眼镜戴上.png" rel="lightbox[19482]" title="靓女把眼镜戴上"><img class="alignnone size-full wp-image-19498" title="靓女把眼镜戴上" src="http://blog.jobbole.com/wp-content/uploads/2012/05/靓女把眼镜戴上.png" alt="" width="553" height="338" /></a></p>
<p>帅哥你也瞧瞧，特有意思～</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/帅哥你也瞧瞧.png" rel="lightbox[19482]" title="帅哥你也瞧瞧"><img class="alignnone size-full wp-image-19493" title="帅哥你也瞧瞧" src="http://blog.jobbole.com/wp-content/uploads/2012/05/帅哥你也瞧瞧.png" alt="" width="549" height="334" /></a></p>
<p>正在看的美眉非常惊叹，另外一个赶忙戴上，其他两位排队等候～</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/正在看的美眉非常惊叹.png" rel="lightbox[19482]" title="正在看的美眉非常惊叹"><img class="alignnone size-full wp-image-19494" title="正在看的美眉非常惊叹" src="http://blog.jobbole.com/wp-content/uploads/2012/05/正在看的美眉非常惊叹.png" alt="" width="553" height="338" /></a></p>
<p>靠近点看～</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/靠近点看.png" rel="lightbox[19482]" title="靠近点看"><img class="alignnone size-full wp-image-19489" title="靠近点看" src="http://blog.jobbole.com/wp-content/uploads/2012/05/靠近点看.png" alt="" width="554" height="337" /></a></p>
<p>“老大”们也来看了？</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/“老大”们也来看了.png" rel="lightbox[19482]" title="“老大”们也来看了"><img class="alignnone size-full wp-image-19500" title="“老大”们也来看了" src="http://blog.jobbole.com/wp-content/uploads/2012/05/“老大”们也来看了.png" alt="" width="552" height="336" /></a></p>
<p>帅哥也有戴粉红色的？为何大家笑得如此High?</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/帅哥也有戴粉红色的.png" rel="lightbox[19482]" title="帅哥也有戴粉红色的"><img class="alignnone size-full wp-image-19492" title="帅哥也有戴粉红色的" src="http://blog.jobbole.com/wp-content/uploads/2012/05/帅哥也有戴粉红色的.png" alt="" width="552" height="336" /></a></p>
<p>哦，原来有几个窗口少儿不宜！</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/原来有几个窗口少儿不宜.png" rel="lightbox[19482]" title="原来有几个窗口少儿不宜"><img class="alignnone size-full wp-image-19491" title="原来有几个窗口少儿不宜" src="http://blog.jobbole.com/wp-content/uploads/2012/05/原来有几个窗口少儿不宜.png" alt="" width="556" height="339" /></a></p>
<p>六个窗口的全景图</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/六个窗口的全景图.png" rel="lightbox[19482]" title="六个窗口的全景图"><img class="alignnone size-full wp-image-19490" title="六个窗口的全景图" src="http://blog.jobbole.com/wp-content/uploads/2012/05/六个窗口的全景图.png" alt="" width="555" height="336" /></a></p>
<p>靓女都喜欢戴粉红色的太阳镜？</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/靓女都喜欢戴粉红色的太阳镜.png" rel="lightbox[19482]" title="靓女都喜欢戴粉红色的太阳镜"><img class="alignnone size-full wp-image-19499" title="靓女都喜欢戴粉红色的太阳镜" src="http://blog.jobbole.com/wp-content/uploads/2012/05/靓女都喜欢戴粉红色的太阳镜.png" alt="" width="554" height="337" /></a></p>
<p>警察叔叔也来看了～ Hey，禁止停车的指示牌下竟然有辆车？旁边还有警察？！</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/警察叔叔也来看了.png" rel="lightbox[19482]" title="警察叔叔也来看了"><img class="alignnone size-full wp-image-19497" title="警察叔叔也来看了" src="http://blog.jobbole.com/wp-content/uploads/2012/05/警察叔叔也来看了.png" alt="" width="555" height="337" /></a></p>
<p>给小狗狗也开开眼～ 不知道这只小狗喜欢看哪扇窗户？:)</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/给小狗狗也开开眼.png" rel="lightbox[19482]" title="给小狗狗也开开眼"><img class="alignnone size-full wp-image-19496" title="给小狗狗也开开眼" src="http://blog.jobbole.com/wp-content/uploads/2012/05/给小狗狗也开开眼.png" alt="" width="553" height="337" /></a></p>
<p>片尾，“主角”现身了～</p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/片尾.png" rel="lightbox[19482]" title="片尾"><img class="alignnone size-full wp-image-19495" title="片尾" src="http://blog.jobbole.com/wp-content/uploads/2012/05/片尾.png" alt="" width="555" height="335" /></a></p>
<p>喻学于乐。看过这么一个有趣的营销案例，不妨反思一下我们学到了什么。我看过不少有创意的营销案例。比如：5月12日，<a href="http://www.weibo.com/u/2133846777">@营销的那些事</a> 分享了一个《<a href="http://www.weibo.com/2133846777/yiNQnFzhC">放胆干杯，你有胆量坐下吗？</a>》的营销视频。个人认为这类创新营销有一定的内在模式。简单地概括就是：结合需要推广的产品或者服务，策划出极具个性的营销方案，再拍摄并制作成视频，上传至Youtube等视频分享网站，然后通过Facebook, Twitter等社交媒体进行传播。</p>
<p>几点反思：</p>
<p>1. 该视频主要拍摄与晚上。谁会在晚上带太阳镜呢？猜想这是营销团队现场发放的太阳镜；</p>
<p>2. 为什么这个推广活动没有选在白天，而是晚上？</p>
<p>&nbsp;</p>
<p>对于这个“不可见”的广告，你认为还有哪些值得思考的地方？欢迎在评论中和我们一起分享～</p>
<p>大家的观点：</p>
<p>新浪微博 <a href="http://weibo.com/holom">@HolomJEWISH鄭</a> ：&#8221;非常帅气的创意广告！香水的核心价值，用了它你可以得到不一样的东西！广告视频突出疑似产品内涵、夜生活、时尚、目标客户群。&#8221;</p>
<p>新浪微博 <a href="http://weibo.com/u/2133846777">@营销的那些事</a> ：这个视频广告把目标用户定位的很清晰。什么样的目标用户，就有什么样的广告表达。所以，我们不必过于去抱怨类似脑白金那样的广告。因为，即使脑白金的广告能做得像这个视频一样有创意，其结果只是：看得懂的人不会去买，可能会购买的人又看不懂。</p>
<p>&nbsp;</p>
<p>原文出处：<a href="http://blog.jobbole.com/19482">http://blog.jobbole.com/19482</a> 作者：<a href="http://www.jobbole.com/" target="_blank">伯乐</a>在线 – 黄余粮</p>
<p>【如需转载，请标注并保留原文链接、作者等信息，谢谢合作！】</p>
<p>&nbsp;</p>
<h2  class="related_post_title">相关文章</h2><ul class="related_post"><li><a target="_blank" href="http://blog.jobbole.com/11396/" title="向上营销、交叉营销与关联推荐 ">向上营销、交叉营销与关联推荐 </a></li><li><a target="_blank" href="http://blog.jobbole.com/8068/" title="走出搜索引擎营销的3个误区">走出搜索引擎营销的3个误区</a></li><li><a target="_blank" href="http://blog.jobbole.com/7914/" title="EDM营销解读">EDM营销解读</a></li><li><a target="_blank" href="http://blog.jobbole.com/5416/" title="病毒式营销案例；小企鹅的毛衣">病毒式营销案例；小企鹅的毛衣</a></li><li><a target="_blank" href="http://blog.jobbole.com/1554/" title="你不得不知的微博营销4大价值">你不得不知的微博营销4大价值</a></li><li><a target="_blank" href="http://blog.jobbole.com/1450/" title="魏武挥：微博营销的第一步测量问题">魏武挥：微博营销的第一步测量问题</a></li><li><a target="_blank" href="http://blog.jobbole.com/1195/" title="选择的艺术：转换率提高10倍，你能做到吗？">选择的艺术：转换率提高10倍，你能做到吗？</a></li><li><a target="_blank" href="http://blog.jobbole.com/1146/" title="你不可不知的社会化营销战略矩阵10字法则">你不可不知的社会化营销战略矩阵10字法则</a></li><li><a target="_blank" href="http://blog.jobbole.com/1121/" title="墨瞿：网络营销漫谈">墨瞿：网络营销漫谈</a></li><li><a target="_blank" href="http://blog.jobbole.com/1103/" title="看广告？男人和女人的关注重点不同">看广告？男人和女人的关注重点不同</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.jobbole.com/19482/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>十个有争议的编程观点</title>
		<link>http://blog.jobbole.com/19511/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25e5%258d%2581%25e4%25b8%25aa%25e6%259c%2589%25e4%25ba%2589%25e8%25ae%25ae%25e7%259a%2584%25e7%25bc%2596%25e7%25a8%258b%25e8%25a7%2582%25e7%2582%25b9</link>
		<comments>http://blog.jobbole.com/19511/#comments</comments>
		<pubDate>Tue, 15 May 2012 01:02:47 +0000</pubDate>
		<dc:creator>齐哲</dc:creator>
				<category><![CDATA[程序员]]></category>
		<category><![CDATA[编程]]></category>

		<guid isPermaLink="false">http://blog.jobbole.com/?p=19511</guid>
		<description><![CDATA[在Stack Overflow上有这样的一个贴子《<a href="http://stackoverflow.com/questions/406760/whats-your-most-controversial-programming-opinion" target="_blank">What’s your most controversial programming opinion?</a>》，翻译成中文就是“你认为最有争议的编程观点是什么？”，不过，在400多个主回贴，以及千把个子回贴中，好像并不是很有争议，而是令人相当的茅塞顿开，下面罗列一些，并通过我自己的经历和理解发挥了一些，希望对你有帮助。

<strong>0. The only “best practice” you should be using all the time is “Use Your Brain”.</strong>

唯一的“Best Practice”并不是使用各种各样被前人总结过的各种设计方法、模式，框架，那些著名的方法、模式、框架只代码赞同他们的人多，并不代表他们适合你，你应该更多的去使用你的大脑，独立地思考那些方法、模式、框架出现的原因和其背后的想法和思想，那才是“best practice”。事实上来说，那些所谓的“Best Practice”只不过是限制那些<a href="http://coolshell.cn/articles/1081.html" target="_blank">糟糕的程序员们</a>的破坏力。

<strong>1. Programmers who don’t code in their spare time for fun will never become as good as those that do.</strong>

如果你对编程没有感到一种快乐，没有在你空闲的时候去以一种的娱乐方式去生活，无论是编程，还是运动，还是去旅游，那么你只不过是在应付你的工作，无时无刻不扎在程序堆中，这样下来，就算是你是一个非常聪明，非常有才华的人，你也不会成为一个优秀的编程员，要么只会平平凡凡，要么只会整天扎在技术中成为书呆子。当然，这个观点是有争议，热情和能力的差距也是很大的。不过我们可以从中汲取其正面的观点。

<strong>2. M</strong><strong>ost comments in code are in fact a pernicious form of code duplication.</strong>

注释应该是注释Why，而不是How和What，参看《<a href="http://blog.jobbole.com/1342/" rel="bookmark" target="_blank">惹恼程序员的十件事</a>》，代码告诉你How，而注释应该告诉你Why。但大多数的程序并不知道什么是好的注释，那些注释其实和code是重复的，毫无意义。

<strong>3. XML is highly overrated</strong>

XML可能被高估了。XML对于Web上的应用是不错的，但是我们把其用到了各种地方，好像没有XML，我们都不会编程了。

<strong>4. Not all programmers are created equal</strong>

这是那些junior经理或是流程爱犯的错，他们总是认为，DeveloperA == DeveloperB，只要他们的title一样，他们以为他们的能力、工作速度、解决问题的方法，掌握的技能等等都是一样的。呵呵。更扯的是，在某些时候，就算是最差的程序员，他们也会认为其比别人强十倍，这就是现代的SB管理。

<strong>5. “Googling it” is okay!</strong>

Google只会给你知识，并不会教给你技能。那里只有“鱼”，没有“渔”，过度的使用Google，只会让你越来越离不开他，你越来越去要去立马告诉你答案，而你越来越不会自己去思考，自己去探索，去专研。如果KFC快餐是垃圾食品对我们的身体没有好处，那么使用Google也一种快餐文化对我们的智力发展大大的没有好处。

<strong>6.  </strong><strong>If you only know one language, no matter how well you know it, you’re not a great programmer.</strong>

如果你只懂一种语言，准确的说，如果你只懂一类语类，如：Java和C#，PHP和Perl，那么，你将会被局限起来，只有了解了各种各样的语言，了解了不同语言的不同方法 ，你才会有比较，只有了比较，你才会明白各种语言的长处和短处，才会让你有更为成熟的观点，而且不整天和别的程序在网上斗嘴争论是Windows好还是Unix好，是C好还是C++好，有这点工夫能干好多事了。世界因为不同而精彩，只知道事物的一面是有害的。

<strong>7. Your job is to put yourself out of work.</strong>

你的工作不是保守，那种教会徒弟，饿死师父的想法，不但是相当短浅的，而且还是相当脑残的。因为，在计算机世界里，你掌握的老技术越多，你就越没用，因为技术更新的太快。你对工作越保守，这个工作就越来越离不开你，你就越不越不能抽身去学新的东西，你也就越来越OUT了。记住：If you can’t be replaced then you can’t be promoted!

<strong>8. <strong>Design patterns are hurting good design more than they’re helping it.</strong></strong>

很多程序员把设计模式奉为天神，他们过度的追求设计模式以至都都忘了需求是什么，结果整个系统设计被设计模式搞得乱七八糟，我们叫这种编程为“<a href="http://blog.jobbole.com/1276/" target="_blank">设计模式驱动编程</a>”，正如第一点所说，如果你不懂得用自己的大脑思考的话，知其然，不知所以然的话，那么你不但得不到其好处，反而受其所累。

<strong>9. </strong><strong>Unit Testing won’t help you write good code</strong>

准确地说，我们可以认为这是Test-Driven开发，其实，这种开发就是先写unit test case，这样的开发方式的主要目的是，为了防止你不会因为一个改动而引入Bug，但这并不会让你能写出更好的代码。这只会让你写出不会出错的代码。同第一点，这样的方法，只不过是防止糟糕的程序员，而并不是让程序员或代码质量更有长进。反而，通过Unit Test会为程序员的为自己代码做辩解的一种托辞。

最后，顺便说一下，以前去那个敏捷的公司面试，发现那个公司的某些技术人员中毒不浅，具体表现在上述的0、8、9 观点上。

&#160;]]></description>
			<content:encoded><![CDATA[<p>在Stack Overflow上有这样的一个贴子《<a href="http://stackoverflow.com/questions/406760/whats-your-most-controversial-programming-opinion" target="_blank">What’s your most controversial programming opinion?</a>》，翻译成中文就是“你认为最有争议的编程观点是什么？”，不过，在400多个主回贴，以及千把个子回贴中，好像并不是很有争议，而是令人相当的茅塞顿开，下面罗列一些，并通过我自己的经历和理解发挥了一些，希望对你有帮助。</p>
<p><strong>0. The only “best practice” you should be using all the time is “Use Your Brain”.</strong></p>
<p>唯一的“Best Practice”并不是使用各种各样被前人总结过的各种设计方法、模式，框架，那些著名的方法、模式、框架只代码赞同他们的人多，并不代表他们适合你，你应该更多的去使用你的大脑，独立地思考那些方法、模式、框架出现的原因和其背后的想法和思想，那才是“best practice”。事实上来说，那些所谓的“Best Practice”只不过是限制那些<a href="http://coolshell.cn/articles/1081.html" target="_blank">糟糕的程序员们</a>的破坏力。</p>
<p><strong>1. Programmers who don’t code in their spare time for fun will never become as good as those that do.</strong></p>
<p>如果你对编程没有感到一种快乐，没有在你空闲的时候去以一种的娱乐方式去生活，无论是编程，还是运动，还是去旅游，那么你只不过是在应付你的工作，无时无刻不扎在程序堆中，这样下来，就算是你是一个非常聪明，非常有才华的人，你也不会成为一个优秀的编程员，要么只会平平凡凡，要么只会整天扎在技术中成为书呆子。当然，这个观点是有争议，热情和能力的差距也是很大的。不过我们可以从中汲取其正面的观点。</p>
<p><strong>2. M</strong><strong>ost comments in code are in fact a pernicious form of code duplication.</strong></p>
<p>注释应该是注释Why，而不是How和What，参看《<a href="http://blog.jobbole.com/1342/" rel="bookmark" target="_blank">惹恼程序员的十件事</a>》，代码告诉你How，而注释应该告诉你Why。但大多数的程序并不知道什么是好的注释，那些注释其实和code是重复的，毫无意义。</p>
<p><strong>3. XML is highly overrated</strong></p>
<p>XML可能被高估了。XML对于Web上的应用是不错的，但是我们把其用到了各种地方，好像没有XML，我们都不会编程了。</p>
<p><strong>4. Not all programmers are created equal</strong></p>
<p>这是那些junior经理或是流程爱犯的错，他们总是认为，DeveloperA == DeveloperB，只要他们的title一样，他们以为他们的能力、工作速度、解决问题的方法，掌握的技能等等都是一样的。呵呵。更扯的是，在某些时候，就算是最差的<span class='wp_keywordlink'><a href="http://blog.jobbole.com/821/" title="程序员的本质">程序员</a></span>，他们也会认为其比别人强十倍，这就是现代的SB管理。</p>
<p><strong>5. “Googling it” is okay!</strong></p>
<p>Google只会给你知识，并不会教给你技能。那里只有“鱼”，没有“渔”，过度的使用Google，只会让你越来越离不开他，你越来越去要去立马告诉你答案，而你越来越不会自己去思考，自己去探索，去专研。如果KFC快餐是垃圾食品对我们的身体没有好处，那么使用Google也一种快餐文化对我们的智力发展大大的没有好处。</p>
<p><strong>6.  </strong><strong>If you only know one language, no matter how well you know it, you’re not a great programmer.</strong></p>
<p>如果你只懂一种语言，准确的说，如果你只懂一类语类，如：Java和C#，PHP和Perl，那么，你将会被局限起来，只有了解了各种各样的语言，了解了不同语言的不同方法 ，你才会有比较，只有了比较，你才会明白各种语言的长处和短处，才会让你有更为成熟的观点，而且不整天和别的程序在网上斗嘴争论是Windows好还是Unix好，是C好还是C++好，有这点工夫能干好多事了。世界因为不同而精彩，只知道事物的一面是有害的。</p>
<p><strong>7. Your job is to put yourself out of work.</strong></p>
<p>你的工作不是保守，那种教会徒弟，饿死师父的想法，不但是相当短浅的，而且还是相当脑残的。因为，在计算机世界里，你掌握的老技术越多，你就越没用，因为技术更新的太快。你对工作越保守，这个工作就越来越离不开你，你就越不越不能抽身去学新的东西，你也就越来越OUT了。记住：If you can’t be replaced then you can’t be promoted!</p>
<p><strong>8. <strong>Design patterns are hurting good design more than they’re helping it.</strong></strong></p>
<p>很多程序员把<span class='wp_keywordlink'><a href="http://www.amazon.cn/gp/product/B001130JN8/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=vastwork-23&linkCode=as2&camp=536&creative=3200&creativeASIN=B001130JN8" title="设计模式" rel="nofollow" target="_blank">设计模式</a></span>奉为天神，他们过度的追求设计模式以至都都忘了需求是什么，结果整个系统设计被设计模式搞得乱七八糟，我们叫这种编程为“<a href="http://blog.jobbole.com/1276/" target="_blank">设计模式驱动编程</a>”，正如第一点所说，如果你不懂得用自己的大脑思考的话，知其然，不知所以然的话，那么你不但得不到其好处，反而受其所累。</p>
<p><strong>9. </strong><strong>Unit Testing won’t help you write good code</strong></p>
<p>准确地说，我们可以认为这是Test-Driven开发，其实，这种开发就是先写unit test case，这样的开发方式的主要目的是，为了防止你不会因为一个改动而引入Bug，但这并不会让你能写出更好的代码。这只会让你写出不会出错的代码。同第一点，这样的方法，只不过是防止糟糕的程序员，而并不是让程序员或代码质量更有长进。反而，通过Unit Test会为程序员的为自己代码做辩解的一种托辞。</p>
<p>最后，顺便说一下，以前去那个敏捷的公司面试，发现那个公司的某些技术人员中毒不浅，具体表现在上述的0、8、9 观点上。</p>
<p>&nbsp;</p>
<h2  class="related_post_title">相关文章</h2><ul class="related_post"><li><a target="_blank" href="http://blog.jobbole.com/18144/" title="张砷镓：我所信奉的编程哲学 ">张砷镓：我所信奉的编程哲学 </a></li><li><a target="_blank" href="http://blog.jobbole.com/17944/" title="拼凑代码与编程">拼凑代码与编程</a></li><li><a target="_blank" href="http://blog.jobbole.com/17666/" title="你所做过最有效提高编程技能的事情是什么？">你所做过最有效提高编程技能的事情是什么？</a></li><li><a target="_blank" href="http://blog.jobbole.com/15801/" title="也谈编程改革">也谈编程改革</a></li><li><a target="_blank" href="http://blog.jobbole.com/15032/" title="循序渐进学编程">循序渐进学编程</a></li><li><a target="_blank" href="http://blog.jobbole.com/12737/" title="7种从头开始免费学习编程的方法">7种从头开始免费学习编程的方法</a></li><li><a target="_blank" href="http://blog.jobbole.com/9047/" title="我讨厌剪切粘贴">我讨厌剪切粘贴</a></li><li><a target="_blank" href="http://blog.jobbole.com/10797/" title="为什么程序员喜欢在深夜工作">为什么程序员喜欢在深夜工作</a></li><li><a target="_blank" href="http://blog.jobbole.com/9726/" title="旅行，写作，编程">旅行，写作，编程</a></li><li><a target="_blank" href="http://blog.jobbole.com/8976/" title="高德纳谈计算机程序设计艺术（下） ">高德纳谈计算机程序设计艺术（下） </a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.jobbole.com/19511/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>三种东西永远不要放到数据库里</title>
		<link>http://blog.jobbole.com/19515/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25e4%25b8%2589%25e7%25a7%258d%25e4%25b8%259c%25e8%25a5%25bf%25e6%25b0%25b8%25e8%25bf%259c%25e4%25b8%258d%25e8%25a6%2581%25e6%2594%25be%25e5%2588%25b0%25e6%2595%25b0%25e6%258d%25ae%25e5%25ba%2593%25e9%2587%258c</link>
		<comments>http://blog.jobbole.com/19515/#comments</comments>
		<pubDate>Tue, 15 May 2012 00:16:06 +0000</pubDate>
		<dc:creator>齐哲</dc:creator>
				<category><![CDATA[IT技术]]></category>
		<category><![CDATA[数据库]]></category>

		<guid isPermaLink="false">http://blog.jobbole.com/?p=19515</guid>
		<description><![CDATA[我已经在很多演讲里说过，改进你的系统的最好的方法是先避免做“蠢事”。我并不是说你或你开发的东西“蠢”，只是有些决定很容易被人们忽略掉其暗含的牵连，认识不到这样做对系统维护尤其是系统升级带来多大的麻烦。作为一个顾问，像这样的事情我到处都能见到，我还从来没有见过做出这样的决定的人有过好的结果的。

<strong>图片，文件，二进制数据</strong>

既然数据库支持BLOB类型的数据，把文件塞进BLOB字段里一定没有错了！？错，不是这样的！别的先不提，在很多数据库语言里，处理大字段都不是很容易。

把文件存放在数据库里有很多问题：

●对数据库的读/写的速度永远都赶不上文件系统处理的速度

●数据库备份变的巨大，越来越耗时间

●对文件的访问需要穿越你的应用层和数据库层

这后两个是真正的杀手。把图片缩略图存到数据库里？很好，那你就不能使用nginx或其它类型的轻量级服务器来处理它们了。

给自己行个方便吧，在数据库里只简单的存放一个磁盘上你的文件的相对路径，或者使用S3或CDN之类的服务。

<strong>短生命期数据</strong>

使用情况统计数据，测量数据，GPS定位数据，session数据，任何只是短时间内对你有用，或经常变化的数据。如果你发现自己正在使用定时任务从某个表里删除有效期只有一小时，一天或数周的数据，那说明你没有找对正确的做事情的方法。使用<a href="http://redis.io/">redis</a>，<a href="https://github.com/etsy/statsd">statsd</a>/<a href="http://graphite.wikidot.com/">graphite</a>， <a href="http://basho.com/products/riak-overview/">Riak</a>，它们都是干这种事情更合适的工具。这建议也适用于对于收集那些短生命期的数据。

当然，用挖土机在后花园里种土豆也是可行的，但相比起从储物间里拿出一把铲子，你预约一台挖土机、等它赶到你的园子里挖坑，这显然更慢。你要选择合适的工具来处理手头上的事。

<strong>日志文件</strong>

把日志数据存放到数据库里，表面上看起来似乎不错，而且“将来也许我需要对这些数据进行复杂的查询”，这样的话很得人心。这样做并不是一个<strong>特别差</strong>的做法，但如果你把日志数据和你的产品数据存放到一个数据库里就非常不好了。

也许你的日志记录做的很保守，每次web请求只产生一条日志。对于整个网站的每个事件来说，这仍然会产生大量的数据库插入操作，争夺你用户需要的数据库资源。如果你的日志级别设置为verbose或debug，那等着看你的数据库着火吧。

你应该使用一些比如<a href="http://splunk.com/">Splunk</a> <a href="http://loggly.com/">Loggly</a>或纯文本文件来存放你的日志数据。这样去查看它们也许会不方便，但这样的时候不多，甚至有时候你需要写出一些代码来分析出你想要的答案，但总的来说是值得的。

可是稍等一下，你是那片不一样的雪花，你遇到的问题会如此的不同，所以，如果你把上面提到的三种东西中的某一种放到了数据库里也不会有问题。<strong>不，你错了，不，你不特殊。</strong>相信我。

&#160;
<p id="page-note">英文原文：<a href="http://www.revsys.com/blog/2012/may/01/three-things-you-should-never-put-your-database/">Three things you should never put in your database</a></p>
&#160;]]></description>
			<content:encoded><![CDATA[<p>我已经在很多演讲里说过，改进你的系统的最好的方法是先避免做“蠢事”。我并不是说你或你开发的东西“蠢”，只是有些决定很容易被人们忽略掉其暗含的牵连，认识不到这样做对系统维护尤其是系统升级带来多大的麻烦。作为一个顾问，像这样的事情我到处都能见到，我还从来没有见过做出这样的决定的人有过好的结果的。</p>
<p><strong>图片，文件，二进制数据</strong></p>
<p>既然数据库支持BLOB类型的数据，把文件塞进BLOB字段里一定没有错了！？错，不是这样的！别的先不提，在很多数据库语言里，处理大字段都不是很容易。</p>
<p>把文件存放在数据库里有很多问题：</p>
<p>●对数据库的读/写的速度永远都赶不上文件系统处理的速度</p>
<p>●数据库备份变的巨大，越来越耗时间</p>
<p>●对文件的访问需要穿越你的应用层和数据库层</p>
<p>这后两个是真正的杀手。把图片缩略图存到数据库里？很好，那你就不能使用nginx或其它类型的轻量级服务器来处理它们了。</p>
<p>给自己行个方便吧，在数据库里只简单的存放一个磁盘上你的文件的相对路径，或者使用S3或CDN之类的服务。</p>
<p><strong>短生命期数据</strong></p>
<p>使用情况统计数据，测量数据，GPS定位数据，session数据，任何只是短时间内对你有用，或经常变化的数据。如果你发现自己正在使用定时任务从某个表里删除有效期只有一小时，一天或数周的数据，那说明你没有找对正确的做事情的方法。使用<a href="http://redis.io/">redis</a>，<a href="https://github.com/etsy/statsd">statsd</a>/<a href="http://graphite.wikidot.com/">graphite</a>， <a href="http://basho.com/products/riak-overview/">Riak</a>，它们都是干这种事情更合适的工具。这建议也适用于对于收集那些短生命期的数据。</p>
<p>当然，用挖土机在后花园里种土豆也是可行的，但相比起从储物间里拿出一把铲子，你预约一台挖土机、等它赶到你的园子里挖坑，这显然更慢。你要选择合适的工具来处理手头上的事。</p>
<p><strong>日志文件</strong></p>
<p>把日志数据存放到数据库里，表面上看起来似乎不错，而且“将来也许我需要对这些数据进行复杂的查询”，这样的话很得人心。这样做并不是一个<strong>特别差</strong>的做法，但如果你把日志数据和你的产品数据存放到一个数据库里就非常不好了。</p>
<p>也许你的日志记录做的很保守，每次web请求只产生一条日志。对于整个网站的每个事件来说，这仍然会产生大量的数据库插入操作，争夺你用户需要的数据库资源。如果你的日志级别设置为verbose或debug，那等着看你的数据库着火吧。</p>
<p>你应该使用一些比如<a href="http://splunk.com/">Splunk</a> <a href="http://loggly.com/">Loggly</a>或纯文本文件来存放你的日志数据。这样去查看它们也许会不方便，但这样的时候不多，甚至有时候你需要写出一些代码来分析出你想要的答案，但总的来说是值得的。</p>
<p>可是稍等一下，你是那片不一样的雪花，你遇到的问题会如此的不同，所以，如果你把上面提到的三种东西中的某一种放到了数据库里也不会有问题。<strong>不，你错了，不，你不特殊。</strong>相信我。</p>
<p>&nbsp;</p>
<p id="page-note">英文原文：<a href="http://www.revsys.com/blog/2012/may/01/three-things-you-should-never-put-your-database/">Three things you should never put in your database</a></p>
<p>&nbsp;</p>
<h2  class="related_post_title">相关文章</h2><ul class="related_post"><li><a target="_blank" href="http://blog.jobbole.com/14213/" title="往返读取后台数据的代价">往返读取后台数据的代价</a></li><li><a target="_blank" href="http://blog.jobbole.com/18005/" title="一个备份MySQL数据库的简单Shell脚本">一个备份MySQL数据库的简单Shell脚本</a></li><li><a target="_blank" href="http://blog.jobbole.com/17274/" title="11 个重要的数据库设计规则">11 个重要的数据库设计规则</a></li><li><a target="_blank" href="http://blog.jobbole.com/14012/" title="MySQL数据库备份的10个教程">MySQL数据库备份的10个教程</a></li><li><a target="_blank" href="http://blog.jobbole.com/15499/" title="小荷：DBA应该具有什么样的素质？">小荷：DBA应该具有什么样的素质？</a></li><li><a target="_blank" href="http://blog.jobbole.com/9584/" title="我不小心删除了所有的数据">我不小心删除了所有的数据</a></li><li><a target="_blank" href="http://blog.jobbole.com/9426/" title="11个面向文档的开源NoSQL数据库">11个面向文档的开源NoSQL数据库</a></li><li><a target="_blank" href="http://blog.jobbole.com/7884/" title="一个计算机专业毕业生工作5年后的困惑">一个计算机专业毕业生工作5年后的困惑</a></li><li><a target="_blank" href="http://blog.jobbole.com/5701/" title="千万别用MongoDB？真的吗？">千万别用MongoDB？真的吗？</a></li><li><a target="_blank" href="http://blog.jobbole.com/1534/" title="要养成良好的书写SQL的习惯">要养成良好的书写SQL的习惯</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.jobbole.com/19515/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>美国科技公司软件工程师薪水排行</title>
		<link>http://blog.jobbole.com/19507/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25e7%25a7%2591%25e6%258a%2580%25e5%2585%25ac%25e5%258f%25b8%25e8%25bd%25af%25e4%25bb%25b6%25e5%25b7%25a5%25e7%25a8%258b%25e5%25b8%2588%25e8%2596%25aa%25e6%25b0%25b4%25e6%258e%2592%25e8%25a1%258c%25ef%25bc%259a%25e8%258b%25b9%25e6%259e%259c%25e4%25bb%2585%25e5%25b1%2585%25e7%25ac%25ac5%25e4%25bd%258d</link>
		<comments>http://blog.jobbole.com/19507/#comments</comments>
		<pubDate>Tue, 15 May 2012 00:07:59 +0000</pubDate>
		<dc:creator>齐哲</dc:creator>
				<category><![CDATA[资讯]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[薪水]]></category>
		<category><![CDATA[薪酬]]></category>
		<category><![CDATA[软件工程师]]></category>

		<guid isPermaLink="false">http://blog.jobbole.com/?p=19507</guid>
		<description><![CDATA[美国招聘网站GlassDoor的最新调查显示，在美国科技行业的入门级软件工程师中，Twitter给出的薪水最高，达到11.5万美元。

需要注意的是，该榜单主要反应的是入门级软件工程师的薪水，因此高级工程师的薪水可能会高很多。不过，这仍然可以从一定程度上反映出某些公司对人才的吸引力。

<strong>1、Twitter</strong>

平均年薪：114917美元<!--more-->

Twitter竟然是科技行业软件工程师薪水最高的企业，这着实令人有些意外。不仅薪水高，工程师还可以在这里参与一款改变世界的产品。

<strong>2、Facebook</strong>

平均年薪：111428美元

Facebook同样在开发改变世界的产品，薪水也相当可观。

<strong>3、LinkedIn</strong>

平均年薪：110902美元

LinkedIn或许创下了2011年最热门的IPO，所以拥有很多资金为工程师支付高薪。它同样是一家很年轻的企业。

<strong>4、思科</strong>

平均年薪：105562美元

没有多少软件工程师愿意到硬件公司工作，所以思科花大价钱吸引人才也就不足为奇了。

<strong>5、苹果</strong>

平均年薪：103883美元

苹果的工程师薪水略高于谷歌，但距离美国科技航行业头把交椅仍有不小的距离。不过，它毕竟是苹果，所以薪水或许没那么重要。

<strong>6、谷歌</strong>

平均年薪：103438美元

谷歌竟然不是第一，这令人很意外。但谷歌还是提供很多优秀的福利，并且可以获得丰富的计算资源，这同样可以形成很大的吸引力。

<strong>7、雅虎</strong>

平均年薪：102638美元

雅虎正在展开大规模裁员，所以要吸引人才就不得不开高价。现在看来，他们的确在这么做。

<strong>8、Zynga</strong>

平均年薪：100494美元

Zynga从EA等竞争对手那里挖来了很多员工，所以它的薪水显然更高。

<strong>9、甲骨文</strong>

平均年薪：99391美元

甲骨文员工的平均年薪很少会跌破10万美元，但甲骨文毕竟是大公司，而且拥有众多大牌客户。或许他们还提供一些隐形福利。

<strong>10、亚马逊</strong>

平均年薪：92613美元

亚马逊必须借助工程师来开发网站，并保障服务的顺利运行，所以自然要给出有竞争力的薪水，但并未跻身行业一线水平也在意料之中。

<strong>11、微软</strong>

平均年薪：87956美元

虽然微软的薪水不如谷歌等竞争对手，但或许可以在那里获得很多学习机会，所以，到微软工作可能也没有那么糟。

<strong>12、IBM</strong>

平均年薪：86608美元

作为老牌企业，虽然IBM薪水偏低，但仍然拥有非常优异的研发团队。]]></description>
			<content:encoded><![CDATA[<p>美国招聘网站GlassDoor的最新调查显示，在美国科技行业的入门级<span class='wp_keywordlink'><a href="http://blog.jobbole.com/344/" title="明星软件工程师的10种特质">软件工程师</a></span>中，Twitter给出的薪水最高，达到11.5万美元。</p>
<p>需要注意的是，该榜单主要反应的是入门级软件工程师的薪水，因此高级工程师的薪水可能会高很多。不过，这仍然可以从一定程度上反映出某些公司对人才的吸引力。</p>
<p><strong>1、Twitter</strong></p>
<p>平均年薪：114917美元<span id="more-19507"></span></p>
<p>Twitter竟然是科技行业软件工程师薪水最高的企业，这着实令人有些意外。不仅薪水高，工程师还可以在这里参与一款改变世界的产品。</p>
<p><strong>2、Facebook</strong></p>
<p>平均年薪：111428美元</p>
<p>Facebook同样在开发改变世界的产品，薪水也相当可观。</p>
<p><strong>3、LinkedIn</strong></p>
<p>平均年薪：110902美元</p>
<p>LinkedIn或许创下了2011年最热门的IPO，所以拥有很多资金为工程师支付高薪。它同样是一家很年轻的企业。</p>
<p><strong>4、思科</strong></p>
<p>平均年薪：105562美元</p>
<p>没有多少软件工程师愿意到硬件公司工作，所以思科花大价钱吸引人才也就不足为奇了。</p>
<p><strong>5、苹果</strong></p>
<p>平均年薪：103883美元</p>
<p>苹果的工程师薪水略高于谷歌，但距离美国科技航行业头把交椅仍有不小的距离。不过，它毕竟是苹果，所以薪水或许没那么重要。</p>
<p><strong>6、谷歌</strong></p>
<p>平均年薪：103438美元</p>
<p>谷歌竟然不是第一，这令人很意外。但谷歌还是提供很多优秀的福利，并且可以获得丰富的计算资源，这同样可以形成很大的吸引力。</p>
<p><strong>7、雅虎</strong></p>
<p>平均年薪：102638美元</p>
<p>雅虎正在展开大规模裁员，所以要吸引人才就不得不开高价。现在看来，他们的确在这么做。</p>
<p><strong>8、Zynga</strong></p>
<p>平均年薪：100494美元</p>
<p>Zynga从EA等竞争对手那里挖来了很多员工，所以它的薪水显然更高。</p>
<p><strong>9、甲骨文</strong></p>
<p>平均年薪：99391美元</p>
<p>甲骨文员工的平均年薪很少会跌破10万美元，但甲骨文毕竟是大公司，而且拥有众多大牌客户。或许他们还提供一些隐形福利。</p>
<p><strong>10、亚马逊</strong></p>
<p>平均年薪：92613美元</p>
<p>亚马逊必须借助工程师来开发网站，并保障服务的顺利运行，所以自然要给出有竞争力的薪水，但并未跻身行业一线水平也在意料之中。</p>
<p><strong>11、微软</strong></p>
<p>平均年薪：87956美元</p>
<p>虽然微软的薪水不如谷歌等竞争对手，但或许可以在那里获得很多学习机会，所以，到微软工作可能也没有那么糟。</p>
<p><strong>12、IBM</strong></p>
<p>平均年薪：86608美元</p>
<p>作为老牌企业，虽然IBM薪水偏低，但仍然拥有非常优异的研发团队。</p>
<h2  class="related_post_title">相关文章</h2><ul class="related_post"><li><a target="_blank" href="http://blog.jobbole.com/19124/" title="想招优秀的程序员，给他们付足够的钱吧！">想招优秀的程序员，给他们付足够的钱吧！</a></li><li><a target="_blank" href="http://blog.jobbole.com/18436/" title="RSS永生不灭">RSS永生不灭</a></li><li><a target="_blank" href="http://blog.jobbole.com/17529/" title="工程师如何不被PM欺负">工程师如何不被PM欺负</a></li><li><a target="_blank" href="http://blog.jobbole.com/17246/" title="2012年全美最佳最差职业：软件工程师最佳">2012年全美最佳最差职业：软件工程师最佳</a></li><li><a target="_blank" href="http://blog.jobbole.com/17193/" title="Twitter 开源其 MySQL 优化成果">Twitter 开源其 MySQL 优化成果</a></li><li><a target="_blank" href="http://blog.jobbole.com/5900/" title="Google软件工程师：从战争中得到的启示">Google软件工程师：从战争中得到的启示</a></li><li><a target="_blank" href="http://blog.jobbole.com/7965/" title="为什么项目经理拿的钱比程序员多？">为什么项目经理拿的钱比程序员多？</a></li><li><a target="_blank" href="http://blog.jobbole.com/5042/" title="微软资深软件工程师：阅读代码真的很难（第2篇）">微软资深软件工程师：阅读代码真的很难（第2篇）</a></li><li><a target="_blank" href="http://blog.jobbole.com/4429/" title="2011全美最佳最差职业一览：软件工程师居首">2011全美最佳最差职业一览：软件工程师居首</a></li><li><a target="_blank" href="http://blog.jobbole.com/1565/" title="硅谷科技公司的员工福利有多好">硅谷科技公司的员工福利有多好</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.jobbole.com/19507/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>史上最糟糕的两个变量名</title>
		<link>http://blog.jobbole.com/18304/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25e5%258f%25b2%25e4%25b8%258a%25e6%259c%2580%25e7%25b3%259f%25e7%25b3%2595%25e7%259a%2584%25e4%25b8%25a4%25e4%25b8%25aa%25e5%258f%2598%25e9%2587%258f%25e5%2590%258d</link>
		<comments>http://blog.jobbole.com/18304/#comments</comments>
		<pubDate>Mon, 14 May 2012 19:32:26 +0000</pubDate>
		<dc:creator>黄小非</dc:creator>
				<category><![CDATA[程序员]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[代码]]></category>
		<category><![CDATA[变量名]]></category>
		<category><![CDATA[程序]]></category>

		<guid isPermaLink="false">http://blog.jobbole.com/?p=18304</guid>
		<description><![CDATA[<p align="left">作为一个程序员，“起名字”是他们工作中非常重要的一部分。Phil Karlton就说过：“在计算机科学领域，有两大难题，如何验证缓存和如何给各种东西命名。”虽然很难，但是每次在写代码的时候，给事物起名字又是不可回避的工作。无论是程序变量名还是数据库表名或者是表里的列名，甚至是文件系统中的文件名，以及你的项目名称、产品名称，给这些东西起名字可不是个轻松活儿。</p>
<p align="left">糟糕的命名方式随处可见。你会发现，有的变量名字起得太短，根本没法提供足够的描述信息。或许有这个问题的人都做过TRS-80 BASIC程序员，在这种BASIC语言里，无论你起多长的变量名，只有名字的头两个字母有效，所以那个时候的程序员不得不在键盘边儿上放个笔记本，以便将很短的变量名称和他们的对应含义记录下来，这样才能不搞混淆。</p>
<p align="left">有的时候，你会发现这样的命名方法：直接将变量名称中的原音字母省略，以此来缩短变量的长度。这种方法被用来替代常用的“截断法”，也就是简单地把字母截断来缩短长度。比如你可以用$cstmr(原音省略)来代替$cust(直接截断). 但是，对于customers（顾客）和costumers（服装提供商）这两个单词来说，原音省略法就会造成混淆(customers和costumers采用原音省略法，其结果都是cstmr)。更糟糕的是，$cstmr缺乏原音字母，打字的时候会更加别扭，而且从读音的角度来说，也很难对其进行发音。</p>

<div class="mceTemp mceIEcenter" style="text-align: center;"><dl id="attachment_18320" class="wp-caption aligncenter" style="width: 310px;"><dt class="wp-caption-dt"><a href="http://blog.jobbole.com/wp-content/uploads/2012/04/tsr80.jpg"><img class="size-full wp-image-18320   " title="tsr80" src="http://blog.jobbole.com/wp-content/uploads/2012/04/tsr80.jpg" alt="" width="300" height="300" /></a></dt><dd class="wp-caption-dd">TSR80计算机，只支持4位的变量名</dd></dl></div>
<p align="left">还有一种人为的特殊命名方式，有的时候程序的作者只是为了小幽一默，所以起了些有趣的名字。我就曾经见到过有人把循环变量命名为$crap <span style="color: #888888;">(crap在英语里是轻微的咒骂，跟damm,shit这种词语差不多——译者注)</span>，我的一个同事告诉我，他在给一段代码做整理的时候，看到过有个函数被命名为:THE_LONE_RANGER_RIDES_AGAIN()。虽然这样的命名方式非常特殊，但是他们并不属于我说的“糟糕”的命名的范畴。</p>
<p align="left">虽然我很清楚，对于命名规范这种事情，大家是公说公有理，婆说婆有理，但是，我还是非常自信地宣布，我认为，史上最糟糕的命名是：<span style="color: #ff0000;"><strong>$data!</strong></span></p>
<p align="left">是的！必须是$data! 这个命名完全是循环定义，实际上就是一句废话。就仿佛你把你们家所有的东西都扔到一个行李箱里，然后在行李箱上面贴个条，赫然写着：“东西”</p>
<p align="left">正确变量命名应该写清楚变量的数据类型。因此在命名是考虑数据类型是一个很好的提升命名质量的办法。我有一次在看一段读数据库表记录的代码时，看到了$data这个名字，大概像下面这样：</p>

<pre class="brush: php; gutter: true">$data = read_record();

print &#34;ID = &#34;, $data[&#34;CUSTOMER_ID&#34;];</pre>
<p align="left">如果这时候问问：“$data是什么数据类型呢？”,然后你就很想给它换个名字了。把名字改成$record是一个好的开始。进一步改成$custormer_record，就更好一些了。</p>
<p align="left">模糊的命名相当糟糕，糟糕程度紧随其后的就是，长得几乎一样，无法分辨的变量名。因此，有史以来第二糟糕的变量名就是:<strong><span style="color: #ff0000;"> $data2</span></strong>.</p>
<p align="left">总的来说，任何仅仅依靠数字编号来区分的变量名都应该被重构。马上举个例子给你看，你就明白了：</p>

<pre class="brush: php; gutter: true">$total = $price * $qty;

$total2 = $total - $discount;

$total2 += $total2 * $taxrate;

$total3 = $purchase_order_value + $available_credit;

if ( $total2 &#60; $total3 ) {

    print &#34;You can&#039;t afford this order.&#34;;

}</pre>
&#160;
<p align="left">你可以发现，要读懂这个代码就跟读甲骨文一样痛苦。很明显，这个程序的目的就是要计算订单的总花费，$total. 如果程序的逻辑没有问题，那么$total这个变量名也算是恰如其分。但是，偏偏有人修改了这个程序，给添加了计算折扣和税率的功能，然后他还在变量命名上偷懒，直接起了个$total2, 更可恨的是，还有其他人在这个程序里计算了用户的可用账户金额，然后直接起名叫$total3!</p>
<p align="left">真正倒霉催的是下面这行代码：</p>

<pre class="brush: php; gutter: true">if ( $total2 &#60; $total3 )</pre>
<p align="left">如果你不回头看之前的代码，要想知道这句代码的意义是完全不可能的。所以你必须往回阅读，看看哪个变量究竟是什么意思。</p>
<p align="left">如果你看到了类似像$total2这样的变量，那就应该把这个名字改得更加具体一些。花5分钟的时间让这些变量名称变得更加合理。这个层面上的软件重构是最简单，代价最小，也是最安全的，尤其是在你要修改的变量是个局部变量的时候。</p>
<p align="left">让我们用最简单的“搜索-替换”功能来解决我们之前发现的问题</p>

<pre class="brush: php; gutter: true">$order_total = $price * $qty;

$payable_total = $order_total - $discount;

$payable_total += $payable_total * $taxrate;

$available_funds = $purchase_order_value + $available_credit;

if ( $payable_total &#60; $available_funds ) {

    print &#34;You can&#039;t afford this order.&#34;;

}</pre>
经过修改后，唯一变化的就是变量名，而且代码变得简单易懂了。现在对于每个<span lang="EN-US">_total</span>，就不存在二义性的问题了。看看我们发现了什么：原先<span lang="EN-US">if</span>语句中的两个比较变量的位置写反了。有效的命名方法让我们能够更快地发现错误。

通常，我们都认为用数字作为变量的结尾是不好的命名方法，但是有一个例外。如果变量描述的实体本身就是以数字结尾的，那变量名最好也是以数字结尾。比如，如果我们要定义一个<span lang="EN-US">SHA-1</span>哈希实体，那干脆就把它命名为<span lang="EN-US">$sha1,</span>这样就很好，你完全没有必要把它搞成<span lang="EN-US">$sha_one</span>，然后来避免在变量名中使用数字。

在我完成了对本文的第一版后，我创立了自己的命名规则，并使用<span lang="EN-US">Perl::Critic</span>包来检测上述提到的两种命名问题。我制作的插件 <span lang="EN-US">Perl::Critic::Bangs </span>可以检测出这两种问题：<span lang="EN-US">ProhibitVagueNames </span>和 <span lang="EN-US">ProhibitNumberNames.</span>

还有哪些其他的糟糕的命名方法逼得你发疯？你自己有去做些什么纠正这些错误么？

&#160;

英文原文：<a title="the-worlds-two-worst-variable-names" href="http://petdance.com/2012/04/the-worlds-two-worst-variable-names/" target="_blank">The world's two worst variable names</a>  编译：<a href="http://www.jobbole.com" target="_blank">伯乐</a>在线 - <a title="史上最糟糕的两个变量名" href="http://blog.jobbole.com/18304/" target="_blank">黄小非</a>

<span style="color: red;">【如需转载，请标注并保留原文链接、译文链接和译者等信息，谢谢合作！】</span>

&#160;]]></description>
			<content:encoded><![CDATA[<p align="left">作为一个<span class='wp_keywordlink'><a href="http://blog.jobbole.com/821/" title="程序员的本质">程序员</a></span>，“起名字”是他们工作中非常重要的一部分。Phil Karlton就说过：“在计算机科学领域，有两大难题，如何验证缓存和如何给各种东西命名。”虽然很难，但是每次在写代码的时候，给事物起名字又是不可回避的工作。无论是程序变量名还是数据库表名或者是表里的列名，甚至是文件系统中的文件名，以及你的项目名称、产品名称，给这些东西起名字可不是个轻松活儿。</p>
<p align="left">糟糕的命名方式随处可见。你会发现，有的变量名字起得太短，根本没法提供足够的描述信息。或许有这个问题的人都做过TRS-80 BASIC程序员，在这种BASIC语言里，无论你起多长的变量名，只有名字的头两个字母有效，所以那个时候的程序员不得不在键盘边儿上放个笔记本，以便将很短的变量名称和他们的对应含义记录下来，这样才能不搞混淆。</p>
<p align="left">有的时候，你会发现这样的命名方法：直接将变量名称中的原音字母省略，以此来缩短变量的长度。这种方法被用来替代常用的“截断法”，也就是简单地把字母截断来缩短长度。比如你可以用$cstmr(原音省略)来代替$cust(直接截断). 但是，对于customers（顾客）和costumers（服装提供商）这两个单词来说，原音省略法就会造成混淆(customers和costumers采用原音省略法，其结果都是cstmr)。更糟糕的是，$cstmr缺乏原音字母，打字的时候会更加别扭，而且从读音的角度来说，也很难对其进行发音。</p>
<div class="mceTemp mceIEcenter" style="text-align: center;">
<dl id="attachment_18320" class="wp-caption aligncenter" style="width: 310px;">
<dt class="wp-caption-dt"><a href="http://blog.jobbole.com/wp-content/uploads/2012/04/tsr80.jpg" rel="lightbox[18304]" title="tsr80"><img class="size-full wp-image-18320" title="tsr80" src="http://blog.jobbole.com/wp-content/uploads/2012/04/tsr80.jpg" alt="" width="300" height="300" /></a></dt>
<dd class="wp-caption-dd">TSR80计算机，只支持4位的变量名</dd>
</dl>
</div>
<p align="left">还有一种人为的特殊命名方式，有的时候程序的作者只是为了小幽一默，所以起了些有趣的名字。我就曾经见到过有人把循环变量命名为$crap <span style="color: #888888;">(crap在英语里是轻微的咒骂，跟damm,shit这种词语差不多——译者注)</span>，我的一个同事告诉我，他在给一段代码做整理的时候，看到过有个函数被命名为:THE_LONE_RANGER_RIDES_AGAIN()。虽然这样的命名方式非常特殊，但是他们并不属于我说的“糟糕”的命名的范畴。</p>
<p align="left">虽然我很清楚，对于命名规范这种事情，大家是公说公有理，婆说婆有理，但是，我还是非常自信地宣布，我认为，史上最糟糕的命名是：<span style="color: #ff0000;"><strong>$data!</strong></span></p>
<p align="left">是的！必须是$data! 这个命名完全是循环定义，实际上就是一句废话。就仿佛你把你们家所有的东西都扔到一个行李箱里，然后在行李箱上面贴个条，赫然写着：“东西”</p>
<p align="left">正确变量命名应该写清楚变量的数据类型。因此在命名是考虑数据类型是一个很好的提升命名质量的办法。我有一次在看一段读数据库表记录的代码时，看到了$data这个名字，大概像下面这样：</p>
<pre class="brush: php; gutter: true">$data = read_record();

print &quot;ID = &quot;, $data[&quot;CUSTOMER_ID&quot;];</pre>
<p align="left">如果这时候问问：“$data是什么数据类型呢？”,然后你就很想给它换个名字了。把名字改成$record是一个好的开始。进一步改成$custormer_record，就更好一些了。</p>
<p align="left">模糊的命名相当糟糕，糟糕程度紧随其后的就是，长得几乎一样，无法分辨的变量名。因此，有史以来第二糟糕的变量名就是:<strong><span style="color: #ff0000;"> $data2</span></strong>.</p>
<p align="left">总的来说，任何仅仅依靠数字编号来区分的变量名都应该被<span class='wp_keywordlink'><a href="http://www.amazon.cn/gp/product/B003BY6PLK/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=vastwork-23&linkCode=as2&camp=536&creative=3200&creativeASIN=B003BY6PLK" title="重构" rel="nofollow" target="_blank">重构</a></span>。马上举个例子给你看，你就明白了：</p>
<pre class="brush: php; gutter: true">$total = $price * $qty;

$total2 = $total - $discount;

$total2 += $total2 * $taxrate;

$total3 = $purchase_order_value + $available_credit;

if ( $total2 &lt; $total3 ) {

    print &quot;You can&#039;t afford this order.&quot;;

}</pre>
<p>&nbsp;</p>
<p align="left">你可以发现，要读懂这个代码就跟读甲骨文一样痛苦。很明显，这个程序的目的就是要计算订单的总花费，$total. 如果程序的逻辑没有问题，那么$total这个变量名也算是恰如其分。但是，偏偏有人修改了这个程序，给添加了计算折扣和税率的功能，然后他还在变量命名上偷懒，直接起了个$total2, 更可恨的是，还有其他人在这个程序里计算了用户的可用账户金额，然后直接起名叫$total3!</p>
<p align="left">真正倒霉催的是下面这行代码：</p>
<pre class="brush: php; gutter: true">if ( $total2 &lt; $total3 )</pre>
<p align="left">如果你不回头看之前的代码，要想知道这句代码的意义是完全不可能的。所以你必须往回阅读，看看哪个变量究竟是什么意思。</p>
<p align="left">如果你看到了类似像$total2这样的变量，那就应该把这个名字改得更加具体一些。花5分钟的时间让这些变量名称变得更加合理。这个层面上的软件重构是最简单，代价最小，也是最安全的，尤其是在你要修改的变量是个局部变量的时候。</p>
<p align="left">让我们用最简单的“搜索-替换”功能来解决我们之前发现的问题</p>
<pre class="brush: php; gutter: true">$order_total = $price * $qty;

$payable_total = $order_total - $discount;

$payable_total += $payable_total * $taxrate;

$available_funds = $purchase_order_value + $available_credit;

if ( $payable_total &lt; $available_funds ) {

    print &quot;You can&#039;t afford this order.&quot;;

}</pre>
<p>经过修改后，唯一变化的就是变量名，而且代码变得简单易懂了。现在对于每个<span lang="EN-US">_total</span>，就不存在二义性的问题了。看看我们发现了什么：原先<span lang="EN-US">if</span>语句中的两个比较变量的位置写反了。有效的命名方法让我们能够更快地发现错误。</p>
<p>通常，我们都认为用数字作为变量的结尾是不好的命名方法，但是有一个例外。如果变量描述的实体本身就是以数字结尾的，那变量名最好也是以数字结尾。比如，如果我们要定义一个<span lang="EN-US">SHA-1</span>哈希实体，那干脆就把它命名为<span lang="EN-US">$sha1,</span>这样就很好，你完全没有必要把它搞成<span lang="EN-US">$sha_one</span>，然后来避免在变量名中使用数字。</p>
<p>在我完成了对本文的第一版后，我创立了自己的命名规则，并使用<span lang="EN-US">Perl::Critic</span>包来检测上述提到的两种命名问题。我制作的插件 <span lang="EN-US">Perl::Critic::Bangs </span>可以检测出这两种问题：<span lang="EN-US">ProhibitVagueNames </span>和 <span lang="EN-US">ProhibitNumberNames.</span></p>
<p>还有哪些其他的糟糕的命名方法逼得你发疯？你自己有去做些什么纠正这些错误么？</p>
<p>&nbsp;</p>
<p>英文原文：<a title="the-worlds-two-worst-variable-names" href="http://petdance.com/2012/04/the-worlds-two-worst-variable-names/" target="_blank">The world&#8217;s two worst variable names</a>  编译：<a href="http://www.jobbole.com" target="_blank">伯乐</a>在线 &#8211; <a title="史上最糟糕的两个变量名" href="http://blog.jobbole.com/18304/" target="_blank">黄小非</a></p>
<p><span style="color: red;">【如需转载，请标注并保留原文链接、译文链接和译者等信息，谢谢合作！】</span></p>
<p>&nbsp;</p>
<h2  class="related_post_title">相关文章</h2><ul class="related_post"><li><a target="_blank" href="http://blog.jobbole.com/10319/" title="请立刻修改这段程序">请立刻修改这段程序</a></li><li><a target="_blank" href="http://blog.jobbole.com/5067/" title="程序代码里的幽默精神">程序代码里的幽默精神</a></li><li><a target="_blank" href="http://blog.jobbole.com/4246/" title="好程序需要你(至少)写两遍">好程序需要你(至少)写两遍</a></li><li><a target="_blank" href="http://blog.jobbole.com/1400/" title="为了写出好程序，有时候你需要先写出烂程序">为了写出好程序，有时候你需要先写出烂程序</a></li><li><a target="_blank" href="http://blog.jobbole.com/16979/" title="省时利器：代码美化与格式化工具">省时利器：代码美化与格式化工具</a></li><li><a target="_blank" href="http://blog.jobbole.com/19371/" title="什么是重构，什么不是重构 ">什么是重构，什么不是重构 </a></li><li><a target="_blank" href="http://blog.jobbole.com/19262/" title="浅谈PHP代码设计结构">浅谈PHP代码设计结构</a></li><li><a target="_blank" href="http://blog.jobbole.com/19016/" title="重构：代码异味">重构：代码异味</a></li><li><a target="_blank" href="http://blog.jobbole.com/18714/" title="13个超棒的代码资源网站推荐  ">13个超棒的代码资源网站推荐  </a></li><li><a target="_blank" href="http://blog.jobbole.com/18563/" title="如何为 PHP 贡献代码">如何为 PHP 贡献代码</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.jobbole.com/18304/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>网页设计中的30个令人惊叹的滚动效果</title>
		<link>http://blog.jobbole.com/17897/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25e7%25bd%2591%25e9%25a1%25b5%25e8%25ae%25be%25e8%25ae%25a1%25e4%25b8%25ad%25e7%259a%258430%25e4%25b8%25aa%25e4%25bb%25a4%25e4%25ba%25ba%25e6%2583%258a%25e5%258f%25b9%25e7%259a%2584%25e6%25bb%259a%25e5%258a%25a8%25e6%2595%2588%25e6%259e%259c</link>
		<comments>http://blog.jobbole.com/17897/#comments</comments>
		<pubDate>Mon, 14 May 2012 15:34:53 +0000</pubDate>
		<dc:creator>黄利民</dc:creator>
				<category><![CDATA[设计]]></category>
		<category><![CDATA[网页设计]]></category>

		<guid isPermaLink="false">http://blog.jobbole.com/?p=17897</guid>
		<description><![CDATA[Web开发的已经进化很多，其边界已从经典的栅格布局变化到现在不同寻常的布局设计。网页设计师经常做些一些惊人的设计作品，打破了传统页面布局，带来更多反应良好并赏心悦目的网站。在这些非比寻常的设计中就有滚动效果。滚动效果做得够好的话，可提高访客对网站的兴趣。一些把滚动效果做到极为精美。本文收集了30个这样的网站，点击进入这些网站，其设计应该可以让你眼前一亮。

<strong>1. <a title="Peter Pearson" href="http://www.peter-pearson.com/" target="_blank">Peter Pearson<!--more--></a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Peter-Pearson.jpg"><img class="aligncenter size-full wp-image-19442" title="Peter Pearson" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Peter-Pearson.jpg" alt="Peter Pearson" width="575" height="328" /></a>

&#160;

<strong>2. <a title="Campaign Monitor" href="http://www.campaignmonitor.com/hiring/" target="_blank">Campaign Monitor</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Campaign-Monitor.jpg"><img class="aligncenter size-full wp-image-19443" title="Campaign Monitor" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Campaign-Monitor.jpg" alt="Campaign Monitor" width="575" height="328" /></a>

&#160;

<strong>3. <a title="Buero-Buero" href="http://buero-buero.org/" target="_blank">Buero-Buero</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Buero-Buero.jpg"><img class="aligncenter size-full wp-image-19444" title="Buero-Buero" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Buero-Buero.jpg" alt="Buero-Buero" width="575" height="331" /></a>

&#160;

<strong>4. <a title="Lewers" href="http://www.lewers.com.au/#home" target="_blank">Lewers</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Lewers.jpg"><img class="aligncenter size-full wp-image-19445" title="Lewers" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Lewers.jpg" alt="Lewers" width="575" height="324" /></a>

&#160;

<strong>5. <a title="Siebennull" href="http://www.siebennull.com/" target="_blank">Siebennull</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Siebennull.jpg"><img class="aligncenter size-full wp-image-19446" title="Siebennull" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Siebennull.jpg" alt="Siebennull" width="575" height="326" /></a>

&#160;

<strong>6. <a title="Kalendiar" href="http://kalendiar.lenm.cz/2011/kalendiar-eng.html" target="_blank">Kalendiar</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Kalendiar.jpg"><img class="aligncenter size-full wp-image-19447" title="Kalendiar" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Kalendiar.jpg" alt="Kalendiar" width="575" height="311" /></a>

&#160;

<strong>7. <a title="Bartle Bogle Hegarty" href="http://www.bartleboglehegarty.com/#%21/asiapac" target="_blank">Bartle Bogle Hegarty</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Bartle-Bogle-Hegarty.jpg"><img class="aligncenter size-full wp-image-19448" title="Bartle Bogle Hegarty" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Bartle-Bogle-Hegarty.jpg" alt="Bartle Bogle Hegarty" width="575" height="340" /></a>
<strong>8. <a title="Ladio" href="http://ladio.ru/flash/en/index.html#" target="_blank">Ladio</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Ladio.jpg"><img class="aligncenter size-full wp-image-19449" title="Ladio" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Ladio.jpg" alt="Ladio" width="575" height="320" /></a>
<strong>9. <a title="Head 2 Heart" href="http://www.head2heart.us/" target="_blank">Head 2 Heart</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Head-2-Heart.jpg"><img class="aligncenter size-full wp-image-19450" title="Head 2 Heart" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Head-2-Heart.jpg" alt="Head 2 Heart" width="575" height="342" /></a>
<strong>10. <a title="Eric Johansson" href="http://www.ericj.se/" target="_blank">Eric Johansson</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Eric-Johansson.jpg"><img class="aligncenter size-full wp-image-19451" title="Eric Johansson" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Eric-Johansson.jpg" alt="Eric Johansson" width="575" height="312" /></a>
<strong>11. <a title="Graphic Therapy" href="http://graphictherapy.com/index2.html" target="_blank">Graphic Therapy</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Graphic-Therapy.jpg"><img class="aligncenter size-full wp-image-19452" title="Graphic Therapy" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Graphic-Therapy.jpg" alt="Graphic Therapy" width="575" height="300" /></a>
<strong>12. <a title="Carrot Creative" href="http://carrotcreative.com/#%21/" target="_blank">Carrot Creative</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Carrot-Creative.jpg"><img class="aligncenter size-full wp-image-19453" title="Carrot Creative" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Carrot-Creative.jpg" alt="Carrot Creative" width="575" height="359" /></a>
<strong>13. <a title="Dentsu Network" href="http://www.dentsunetwork.com/#/history" target="_blank">Dentsu Network</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Dentsu-Network.jpg"><img class="aligncenter size-full wp-image-19454" title="Dentsu Network" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Dentsu-Network.jpg" alt="Dentsu Network" width="575" height="321" /></a>
<strong>14. <a title="Netlash bSeen" href="http://www.netlash-bseen.be/" target="_blank">Netlash bSeen</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Netlash-bSeen.jpg"><img class="aligncenter size-full wp-image-19455" title="Netlash bSeen" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Netlash-bSeen.jpg" alt="Netlash bSeen" width="575" height="330" /></a>
<strong>15. <a title="New Zealand" href="http://www.newzealand.com/int/" target="_blank">New Zealand</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/New-Zealand.jpg"><img class="aligncenter size-full wp-image-19456" title="New Zealand" src="http://blog.jobbole.com/wp-content/uploads/2012/05/New-Zealand.jpg" alt="New Zealand" width="575" height="311" /></a>

&#160;

<strong>16. <a title="Activate Drinks" href="http://activatedrinks.com/#/activate" target="_blank">Activate Drinks</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Activate-Drinks.jpg"><img class="aligncenter size-full wp-image-19457" title="Activate Drinks" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Activate-Drinks.jpg" alt="Activate Drinks" width="575" height="324" /></a>
<strong>17. <a title="Egopop" href="http://www.egopop.net/" target="_blank">Egopop</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Egopop.jpg"><img class="aligncenter size-full wp-image-19458" title="Egopop" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Egopop.jpg" alt="Egopop" width="575" height="345" /></a>

&#160;

<strong>18. <a title="The Guide to the App Galaxy" href="http://www.guidetotheappgalaxy.com/#/developersguide/" target="_blank">The Guide to the App Galaxy</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/The-Guide-to-the-App-Galaxy.jpg"><img class="aligncenter size-full wp-image-19459" title="The Guide to the App Galaxy" src="http://blog.jobbole.com/wp-content/uploads/2012/05/The-Guide-to-the-App-Galaxy.jpg" alt="The Guide to the App Galaxy" width="575" height="349" /></a>
<strong>19. <a title="Nizo App" href="http://nizoapp.com/" target="_blank">Nizo App</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Nizo-App.jpg"><img class="aligncenter size-full wp-image-19460" title="Nizo App" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Nizo-App.jpg" alt="Nizo App" width="575" height="352" /></a>
<strong>20. <a title="Emm and Enn" href="http://www.emmandenn.com/" target="_blank">Emm and Enn</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Emm-and-Enn.jpg"><img class="aligncenter size-full wp-image-19461" title="Emm and Enn" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Emm-and-Enn.jpg" alt="Emm and Enn" width="575" height="329" /></a>
<strong>21. <a title="We Bleed Design" href="http://www.webleeddesign.com/" target="_blank">We Bleed Design</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/We-Bleed-Design.jpg"><img class="aligncenter size-full wp-image-19462" title="We Bleed Design" src="http://blog.jobbole.com/wp-content/uploads/2012/05/We-Bleed-Design.jpg" alt="We Bleed Design" width="575" height="383" /></a>
<strong>22. <a title="Bowtie" href="http://bowtieperiod.com/" target="_blank">Bowtie</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Bowtie.jpg"><img class="aligncenter size-full wp-image-19463" title="Bowtie" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Bowtie.jpg" alt="Bowtie" width="575" height="318" /></a>

&#160;

<strong>23. <a title="Elect-LO-nica" href="http://bunkai-kei.com/special/Elect-LO-nica/" target="_blank">Elect-LO-nica</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Elect-LO-nica.jpg"><img class="aligncenter size-full wp-image-19464" title="Elect-LO-nica" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Elect-LO-nica.jpg" alt="Elect-LO-nica" width="575" height="356" /></a>
<strong>24. <a title="Freestyle Night" href="http://www.freestyle-night.ch/" target="_blank">Freestyle Night</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Freestyle-Night.jpg"><img class="aligncenter size-full wp-image-19465" title="Freestyle Night" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Freestyle-Night.jpg" alt="Freestyle Night" width="575" height="334" /></a>

&#160;

<strong>25. <a title="MYM Creative" href="http://www.mymcreative.com/" target="_blank">MYM Creative</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/MYM-Creative.jpg"><img class="aligncenter size-full wp-image-19466" title="MYM Creative" src="http://blog.jobbole.com/wp-content/uploads/2012/05/MYM-Creative.jpg" alt="MYM Creative" width="575" height="338" /></a>
<strong>26. <a title="Batman 3D" href="http://www.batman-3d.de/" target="_blank">Batman 3D</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Batman-3D.jpg"><img class="aligncenter size-full wp-image-19467" title="Batman 3D" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Batman-3D.jpg" alt="Batman 3D" width="575" height="310" /></a>
<strong>27. <a title="Otokonaki" href="http://www.rohto.co.jp/otokonaki/" target="_blank">Otokonaki</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Otokonaki.jpg"><img class="aligncenter size-full wp-image-19468" title="Otokonaki" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Otokonaki.jpg" alt="Otokonaki" width="575" height="305" /></a>
<strong>28. <a title="Portfolio of Mohan Balaji" href="http://mohanbalaji.com/" target="_blank">Portfolio of Mohan Balaji</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Portfolio-of-Mohan-Balaji.jpg"><img class="aligncenter size-full wp-image-19469" title="Portfolio of Mohan Balaji" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Portfolio-of-Mohan-Balaji.jpg" alt="Portfolio of Mohan Balaji" width="575" height="338" /></a>
<strong>29. <a title="Beercamp" href="http://2011.beercamp.com/" target="_blank">Beercamp</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Beercamp.jpg"><img class="aligncenter size-full wp-image-19470" title="Beercamp" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Beercamp.jpg" alt="Beercamp" width="575" height="345" /></a>
<strong>30. <a title="Old Pulteney Row to the Pole" href="http://www.rowtothepole.com/" target="_blank">Old Pulteney Row to the Pole</a></strong>

<a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Old-Pulteney-Row-to-the-Pole.jpg"><img class="aligncenter size-full wp-image-19471" title="Old Pulteney Row to the Pole" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Old-Pulteney-Row-to-the-Pole.jpg" alt="Old Pulteney Row to the Pole" width="575" height="321" /></a>

&#160;

英文原文：<a href="http://inspirationmind.com/30-amazing-scrolling-effects-in-web-design/" target="_blank">Inspiration Mind</a>   编译：伯乐在线 - <a href="http://blog.jobbole.com/17897/" target="_blank">黄利民</a>

<span style="color: #ff0000;">【如需转载，请标注并保留原文链接、译文链接和译者等信息，谢谢合作！】</span>

&#160;]]></description>
			<content:encoded><![CDATA[<p>Web开发的已经进化很多，其边界已从经典的栅格布局变化到现在不同寻常的布局设计。网页设计师经常做些一些惊人的设计作品，打破了传统页面布局，带来更多反应良好并赏心悦目的网站。在这些非比寻常的设计中就有滚动效果。滚动效果做得够好的话，可提高访客对网站的兴趣。一些把滚动效果做到极为精美。本文收集了30个这样的网站，点击进入这些网站，其设计应该可以让你眼前一亮。</p>
<p><strong>1. <a title="Peter Pearson" href="http://www.peter-pearson.com/" target="_blank">Peter Pearson<span id="more-17897"></span></a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Peter-Pearson.jpg" rel="lightbox[17897]" title="Peter Pearson"><img class="aligncenter size-full wp-image-19442" title="Peter Pearson" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Peter-Pearson.jpg" alt="Peter Pearson" width="575" height="328" /></a></p>
<p>&nbsp;</p>
<p><strong>2. <a title="Campaign Monitor" href="http://www.campaignmonitor.com/hiring/" target="_blank">Campaign Monitor</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Campaign-Monitor.jpg" rel="lightbox[17897]" title="Campaign Monitor"><img class="aligncenter size-full wp-image-19443" title="Campaign Monitor" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Campaign-Monitor.jpg" alt="Campaign Monitor" width="575" height="328" /></a></p>
<p>&nbsp;</p>
<p><strong>3. <a title="Buero-Buero" href="http://buero-buero.org/" target="_blank">Buero-Buero</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Buero-Buero.jpg" rel="lightbox[17897]" title="Buero-Buero"><img class="aligncenter size-full wp-image-19444" title="Buero-Buero" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Buero-Buero.jpg" alt="Buero-Buero" width="575" height="331" /></a></p>
<p>&nbsp;</p>
<p><strong>4. <a title="Lewers" href="http://www.lewers.com.au/#home" target="_blank">Lewers</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Lewers.jpg" rel="lightbox[17897]" title="Lewers"><img class="aligncenter size-full wp-image-19445" title="Lewers" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Lewers.jpg" alt="Lewers" width="575" height="324" /></a></p>
<p>&nbsp;</p>
<p><strong>5. <a title="Siebennull" href="http://www.siebennull.com/" target="_blank">Siebennull</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Siebennull.jpg" rel="lightbox[17897]" title="Siebennull"><img class="aligncenter size-full wp-image-19446" title="Siebennull" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Siebennull.jpg" alt="Siebennull" width="575" height="326" /></a></p>
<p>&nbsp;</p>
<p><strong>6. <a title="Kalendiar" href="http://kalendiar.lenm.cz/2011/kalendiar-eng.html" target="_blank">Kalendiar</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Kalendiar.jpg" rel="lightbox[17897]" title="Kalendiar"><img class="aligncenter size-full wp-image-19447" title="Kalendiar" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Kalendiar.jpg" alt="Kalendiar" width="575" height="311" /></a></p>
<p>&nbsp;</p>
<p><strong>7. <a title="Bartle Bogle Hegarty" href="http://www.bartleboglehegarty.com/#%21/asiapac" target="_blank">Bartle Bogle Hegarty</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Bartle-Bogle-Hegarty.jpg" rel="lightbox[17897]" title="Bartle Bogle Hegarty"><img class="aligncenter size-full wp-image-19448" title="Bartle Bogle Hegarty" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Bartle-Bogle-Hegarty.jpg" alt="Bartle Bogle Hegarty" width="575" height="340" /></a><br />
<strong>8. <a title="Ladio" href="http://ladio.ru/flash/en/index.html#" target="_blank">Ladio</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Ladio.jpg" rel="lightbox[17897]" title="Ladio"><img class="aligncenter size-full wp-image-19449" title="Ladio" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Ladio.jpg" alt="Ladio" width="575" height="320" /></a><br />
<strong>9. <a title="Head 2 Heart" href="http://www.head2heart.us/" target="_blank">Head 2 Heart</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Head-2-Heart.jpg" rel="lightbox[17897]" title="Head 2 Heart"><img class="aligncenter size-full wp-image-19450" title="Head 2 Heart" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Head-2-Heart.jpg" alt="Head 2 Heart" width="575" height="342" /></a><br />
<strong>10. <a title="Eric Johansson" href="http://www.ericj.se/" target="_blank">Eric Johansson</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Eric-Johansson.jpg" rel="lightbox[17897]" title="Eric Johansson"><img class="aligncenter size-full wp-image-19451" title="Eric Johansson" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Eric-Johansson.jpg" alt="Eric Johansson" width="575" height="312" /></a><br />
<strong>11. <a title="Graphic Therapy" href="http://graphictherapy.com/index2.html" target="_blank">Graphic Therapy</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Graphic-Therapy.jpg" rel="lightbox[17897]" title="Graphic Therapy"><img class="aligncenter size-full wp-image-19452" title="Graphic Therapy" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Graphic-Therapy.jpg" alt="Graphic Therapy" width="575" height="300" /></a><br />
<strong>12. <a title="Carrot Creative" href="http://carrotcreative.com/#%21/" target="_blank">Carrot Creative</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Carrot-Creative.jpg" rel="lightbox[17897]" title="Carrot Creative"><img class="aligncenter size-full wp-image-19453" title="Carrot Creative" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Carrot-Creative.jpg" alt="Carrot Creative" width="575" height="359" /></a><br />
<strong>13. <a title="Dentsu Network" href="http://www.dentsunetwork.com/#/history" target="_blank">Dentsu Network</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Dentsu-Network.jpg" rel="lightbox[17897]" title="Dentsu Network"><img class="aligncenter size-full wp-image-19454" title="Dentsu Network" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Dentsu-Network.jpg" alt="Dentsu Network" width="575" height="321" /></a><br />
<strong>14. <a title="Netlash bSeen" href="http://www.netlash-bseen.be/" target="_blank">Netlash bSeen</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Netlash-bSeen.jpg" rel="lightbox[17897]" title="Netlash bSeen"><img class="aligncenter size-full wp-image-19455" title="Netlash bSeen" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Netlash-bSeen.jpg" alt="Netlash bSeen" width="575" height="330" /></a><br />
<strong>15. <a title="New Zealand" href="http://www.newzealand.com/int/" target="_blank">New Zealand</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/New-Zealand.jpg" rel="lightbox[17897]" title="New Zealand"><img class="aligncenter size-full wp-image-19456" title="New Zealand" src="http://blog.jobbole.com/wp-content/uploads/2012/05/New-Zealand.jpg" alt="New Zealand" width="575" height="311" /></a></p>
<p>&nbsp;</p>
<p><strong>16. <a title="Activate Drinks" href="http://activatedrinks.com/#/activate" target="_blank">Activate Drinks</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Activate-Drinks.jpg" rel="lightbox[17897]" title="Activate Drinks"><img class="aligncenter size-full wp-image-19457" title="Activate Drinks" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Activate-Drinks.jpg" alt="Activate Drinks" width="575" height="324" /></a><br />
<strong>17. <a title="Egopop" href="http://www.egopop.net/" target="_blank">Egopop</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Egopop.jpg" rel="lightbox[17897]" title="Egopop"><img class="aligncenter size-full wp-image-19458" title="Egopop" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Egopop.jpg" alt="Egopop" width="575" height="345" /></a></p>
<p>&nbsp;</p>
<p><strong>18. <a title="The Guide to the App Galaxy" href="http://www.guidetotheappgalaxy.com/#/developersguide/" target="_blank">The Guide to the App Galaxy</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/The-Guide-to-the-App-Galaxy.jpg" rel="lightbox[17897]" title="The Guide to the App Galaxy"><img class="aligncenter size-full wp-image-19459" title="The Guide to the App Galaxy" src="http://blog.jobbole.com/wp-content/uploads/2012/05/The-Guide-to-the-App-Galaxy.jpg" alt="The Guide to the App Galaxy" width="575" height="349" /></a><br />
<strong>19. <a title="Nizo App" href="http://nizoapp.com/" target="_blank">Nizo App</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Nizo-App.jpg" rel="lightbox[17897]" title="Nizo App"><img class="aligncenter size-full wp-image-19460" title="Nizo App" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Nizo-App.jpg" alt="Nizo App" width="575" height="352" /></a><br />
<strong>20. <a title="Emm and Enn" href="http://www.emmandenn.com/" target="_blank">Emm and Enn</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Emm-and-Enn.jpg" rel="lightbox[17897]" title="Emm and Enn"><img class="aligncenter size-full wp-image-19461" title="Emm and Enn" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Emm-and-Enn.jpg" alt="Emm and Enn" width="575" height="329" /></a><br />
<strong>21. <a title="We Bleed Design" href="http://www.webleeddesign.com/" target="_blank">We Bleed Design</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/We-Bleed-Design.jpg" rel="lightbox[17897]" title="We Bleed Design"><img class="aligncenter size-full wp-image-19462" title="We Bleed Design" src="http://blog.jobbole.com/wp-content/uploads/2012/05/We-Bleed-Design.jpg" alt="We Bleed Design" width="575" height="383" /></a><br />
<strong>22. <a title="Bowtie" href="http://bowtieperiod.com/" target="_blank">Bowtie</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Bowtie.jpg" rel="lightbox[17897]" title="Bowtie"><img class="aligncenter size-full wp-image-19463" title="Bowtie" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Bowtie.jpg" alt="Bowtie" width="575" height="318" /></a></p>
<p>&nbsp;</p>
<p><strong>23. <a title="Elect-LO-nica" href="http://bunkai-kei.com/special/Elect-LO-nica/" target="_blank">Elect-LO-nica</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Elect-LO-nica.jpg" rel="lightbox[17897]" title="Elect-LO-nica"><img class="aligncenter size-full wp-image-19464" title="Elect-LO-nica" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Elect-LO-nica.jpg" alt="Elect-LO-nica" width="575" height="356" /></a><br />
<strong>24. <a title="Freestyle Night" href="http://www.freestyle-night.ch/" target="_blank">Freestyle Night</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Freestyle-Night.jpg" rel="lightbox[17897]" title="Freestyle Night"><img class="aligncenter size-full wp-image-19465" title="Freestyle Night" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Freestyle-Night.jpg" alt="Freestyle Night" width="575" height="334" /></a></p>
<p>&nbsp;</p>
<p><strong>25. <a title="MYM Creative" href="http://www.mymcreative.com/" target="_blank">MYM Creative</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/MYM-Creative.jpg" rel="lightbox[17897]" title="MYM Creative"><img class="aligncenter size-full wp-image-19466" title="MYM Creative" src="http://blog.jobbole.com/wp-content/uploads/2012/05/MYM-Creative.jpg" alt="MYM Creative" width="575" height="338" /></a><br />
<strong>26. <a title="Batman 3D" href="http://www.batman-3d.de/" target="_blank">Batman 3D</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Batman-3D.jpg" rel="lightbox[17897]" title="Batman 3D"><img class="aligncenter size-full wp-image-19467" title="Batman 3D" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Batman-3D.jpg" alt="Batman 3D" width="575" height="310" /></a><br />
<strong>27. <a title="Otokonaki" href="http://www.rohto.co.jp/otokonaki/" target="_blank">Otokonaki</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Otokonaki.jpg" rel="lightbox[17897]" title="Otokonaki"><img class="aligncenter size-full wp-image-19468" title="Otokonaki" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Otokonaki.jpg" alt="Otokonaki" width="575" height="305" /></a><br />
<strong>28. <a title="Portfolio of Mohan Balaji" href="http://mohanbalaji.com/" target="_blank">Portfolio of Mohan Balaji</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Portfolio-of-Mohan-Balaji.jpg" rel="lightbox[17897]" title="Portfolio of Mohan Balaji"><img class="aligncenter size-full wp-image-19469" title="Portfolio of Mohan Balaji" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Portfolio-of-Mohan-Balaji.jpg" alt="Portfolio of Mohan Balaji" width="575" height="338" /></a><br />
<strong>29. <a title="Beercamp" href="http://2011.beercamp.com/" target="_blank">Beercamp</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Beercamp.jpg" rel="lightbox[17897]" title="Beercamp"><img class="aligncenter size-full wp-image-19470" title="Beercamp" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Beercamp.jpg" alt="Beercamp" width="575" height="345" /></a><br />
<strong>30. <a title="Old Pulteney Row to the Pole" href="http://www.rowtothepole.com/" target="_blank">Old Pulteney Row to the Pole</a></strong></p>
<p><a href="http://blog.jobbole.com/wp-content/uploads/2012/05/Old-Pulteney-Row-to-the-Pole.jpg" rel="lightbox[17897]" title="Old Pulteney Row to the Pole"><img class="aligncenter size-full wp-image-19471" title="Old Pulteney Row to the Pole" src="http://blog.jobbole.com/wp-content/uploads/2012/05/Old-Pulteney-Row-to-the-Pole.jpg" alt="Old Pulteney Row to the Pole" width="575" height="321" /></a></p>
<p>&nbsp;</p>
<p>英文原文：<a href="http://inspirationmind.com/30-amazing-scrolling-effects-in-web-design/" target="_blank">Inspiration Mind</a>   编译：<span class='wp_keywordlink'><a href="http://www.jobbole.com" title="伯乐">伯乐</a></span>在线 &#8211; <a href="http://blog.jobbole.com/17897/" target="_blank">黄利民</a></p>
<p><span style="color: #ff0000;">【如需转载，请标注并保留原文链接、译文链接和译者等信息，谢谢合作！】</span></p>
<p>&nbsp;</p>
<h2  class="related_post_title">相关文章</h2><ul class="related_post"><li><a target="_blank" href="http://blog.jobbole.com/18611/" title="自适应网页设计">自适应网页设计</a></li><li><a target="_blank" href="http://blog.jobbole.com/18283/" title="浅析平面设计与网页设计的差异性">浅析平面设计与网页设计的差异性</a></li><li><a target="_blank" href="http://blog.jobbole.com/17845/" title="20个视频播放器界面欣赏及点评 ">20个视频播放器界面欣赏及点评 </a></li><li><a target="_blank" href="http://blog.jobbole.com/13368/" title="42个激发灵感、漂亮的登陆页面设计">42个激发灵感、漂亮的登陆页面设计</a></li><li><a target="_blank" href="http://blog.jobbole.com/13166/" title="引发网页布局灾难的7个大错误">引发网页布局灾难的7个大错误</a></li><li><a target="_blank" href="http://blog.jobbole.com/13119/" title="有关响应式Web设计的7点启发 ">有关响应式Web设计的7点启发 </a></li><li><a target="_blank" href="http://blog.jobbole.com/12917/" title="Dieter Rams 关于优秀网页设计的10个原则">Dieter Rams 关于优秀网页设计的10个原则</a></li><li><a target="_blank" href="http://blog.jobbole.com/10390/" title="网站内容首页设计经验">网站内容首页设计经验</a></li><li><a target="_blank" href="http://blog.jobbole.com/10048/" title="2012年网页设计趋势">2012年网页设计趋势</a></li><li><a target="_blank" href="http://blog.jobbole.com/9383/" title="网站设计工作流程指南">网站设计工作流程指南</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.jobbole.com/17897/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>伯乐周刊：第23期</title>
		<link>http://blog.jobbole.com/19413/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=%25e4%25bc%25af%25e4%25b9%2590%25e5%259c%25a8%25e7%25ba%25bf%25ef%25bc%259a%25e7%25ac%25ac23%25e6%259c%259f</link>
		<comments>http://blog.jobbole.com/19413/#comments</comments>
		<pubDate>Mon, 14 May 2012 13:12:44 +0000</pubDate>
		<dc:creator>黄利民</dc:creator>
				<category><![CDATA[伯乐周刊]]></category>

		<guid isPermaLink="false">http://blog.jobbole.com/?p=19413</guid>
		<description><![CDATA[<span class="Apple-style-span" style="font-size: 18px; font-weight: bold;">业界资讯</span>

<strong>1.《<strong><a href="http://blog.jobbole.com/18976/" target="_blank">陪审团裁决Android侵犯甲骨文Java版权</a></strong>》 </strong>

<strong>文章摘要：</strong>根据 <a href="http://www.bbc.co.uk/news/business-17985085" rel="nofollow" target="_blank">BBC 的报道</a>，美国法官裁定 Google 侵犯了 Oracle Java 版权，但是尚未决定侵权行为是否属于版权法所允许的“合理公平使用”范畴。

位于加州旧金山的州法院裁定 Google 在 Android 系统中的 9 行代码侵犯了 Oracle 声称的三项 Java 版权中的一个，但是尚在审核该侵权行为是否适用于版权法中的“合理公平使用”范畴。并且，Oracle 现在仅能获得从 $200 到 $150000 之间的赔偿…（<a href="http://blog.jobbole.com/18976/" target="_blank">查看全文</a>）

&#160;

<strong>2. 《<strong><a href="http://blog.jobbole.com/19129/" target="_blank">Visual Studio 11 RC 版将呈现小清新界面</a></strong>》</strong>

<strong>文章摘要：</strong>微软于今年3月份发布的 VS11 beta版本，带来了全新的界面。之后微软根据 VS 11 beta 的反馈进行了调整，这些变化将在即将发布的RC版本中呈现。微软的产品用户体验总监Monty Hammontree在今天发表了一篇博客，透露了RC版的界面……（<a href="http://blog.jobbole.com/19129/" target="_blank">查看全文</a>）

&#160;

<strong>3.《<strong><a href="http://blog.jobbole.com/19114/" target="_blank">2012年5月编程语言排行榜：下一个大受欢迎的语言在哪里</a></strong>》</strong>

<strong>文章摘要：</strong>TIOBE 于近日公布了2012年5月<a title="如何选择语言和编程语言排名相关文章" href="http://blog.jobbole.com/tag/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/">编程语言</a>指数排行榜。排名前三的语言是：C 、Java 和 C++。

在过去 8 年中，除了 Objective-C 的进入和 Delphi 的退出，TIOBE 指数的 Top 10 排行榜几乎没有很大变化。除 Objective-C  之外，新<a title="如何选择语言和编程语言排名相关文章" href="http://blog.jobbole.com/tag/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/">编程语言</a>的接受情况，看起来比预期的要困难多了。这种情况的可能主要原因是，很难把一个大的代码库，从一种语言迁移至另外一种语言。故而变化缓慢…（<a href="http://blog.jobbole.com/19114/" target="_blank">查看全文</a>）

&#160;

&#160;

<span class="Apple-style-span" style="font-size: 18px; font-weight: bold;">职业分享</span>

<span class="Apple-style-span" style="font-size: 16px; font-weight: bold;">一、IT/互联网</span>

<strong>1.《<strong><a href="http://blog.jobbole.com/18865/" target="_blank">计算机天才 Phil Katz 短暂而饱受折磨的一生</a></strong>》</strong>

<strong>文章摘要：</strong>在新的网络精英层出不穷的年代里，我们不能忘记那些更早的技术奠基者。 Phil Katz（1962 – 2000）是压缩软件PKzip的创作者，他的压缩算法已经是Internet的一代压缩规范，正是他，zip 这个词成为了大家熟知的计算机术语。 这篇文章介绍了他短暂而悲剧性的一生…… （<a href="http://blog.jobbole.com/18865/" target="_blank">查看全文</a>）

<strong>读者评论：</strong>

@<a title="Boyface-Bowen" href="http://weibo.com/1149699651">Boyface-Bowen</a>： 1.单纯的技术人员是不适合创业的，至少需要个懂管理的；2.智商高的人，很多情商很低。

&#160;

<strong>2. 《<strong><strong><strong><a href="http://blog.jobbole.com/17630/" target="_blank">敏捷代码审查指南</a></strong></strong></strong>》</strong>

<strong>文章摘要：</strong>“通过一次真正彻底地代码审查（code reviews），仔细阅读你的代码，找出问题，这是我知道的最好的方式去检测早期的bug，但是他们很少去这样干过。某种意义上是因为他们花了大量的时间去写好代码，但是我认为主要是因为绝大部分<a title="程序员的本质" href="http://blog.jobbole.com/821/">程序员</a>害怕其他人审查自己的代码。作为专业的程序员我们要克服阻力，如果你不愿意别人阅读你的代码，然后只是按照自己的意愿写，如果其他人没法读懂它，又怎能让别人使用呢？”Jim Waldo – 《<a title="Java语言精粹" href="http://www.amazon.cn/gp/product/B0055OQT5Q/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&#38;tag=vastwork-23&#38;linkCode=as2&#38;camp=536&#38;creative=3200&#38;creativeASIN=B0055OQT5Q" rel="nofollow" target="_blank">Java语言精粹</a>》的作者…… （<a href="http://blog.jobbole.com/17630/" target="_blank">查看全文</a>）

&#160;

<strong>3. 《<strong><a href="http://blog.jobbole.com/10199/" target="_blank">在线集成开发环境 Compilr 的简单体验</a></strong>》</strong>

<strong>文章摘要：</strong>Compilr 是一个在线的集成开发怀集（IDE），目前支持9种<a title="如何选择语言和编程语言排名相关文章" href="http://blog.jobbole.com/tag/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/">编程语言</a>：C、C++、C#、Java、JavaScript、PHP、Python、Ruby 和 Visual Basic。 Compilr 由坐落于加拿大新斯科舍省的 <a href="http://ninjaotter.com/" rel="nofollow" target="_blank">Ninja Otter Inc</a> 公司开发… （<a href="http://blog.jobbole.com/10199/" target="_blank">查看全文</a>）

<strong>读者评论：</strong>

@<a title="zipZag柏格" href="http://weibo.com/1847240535">zipZag柏格</a>： 有程序员能忍受编译和运行的时候需要排队吗？没有！

&#160;

<strong>4. 《<strong><a href="http://blog.jobbole.com/18935/" target="_blank">for 循环为何可恨？</a></strong>》</strong>

<strong>文章摘要：</strong>Java的闭包(Closure)特征最近成为了一个热门话题。一些精英正在起草一份议案，要在Java将来的版本中加入闭包特征。然而，提议中的闭包语法以及语言上的这种扩充受到了众多Java<a title="程序员的本质" href="http://blog.jobbole.com/821/">程序员</a>的猛烈抨击。不久前，出版过数十本编程书籍的大作家<a href="http://www.elharo.com/" rel="nofollow" target="_blank">Elliotte Rusty Harold</a>发表了对Java中闭包的价值的质疑。尤其是他问道“ <a href="http://cafe.elharo.com/java/why-hate-the-for-loop/" rel="nofollow" target="_blank">for 循环为何可恨？</a>”… （<a href="http://blog.jobbole.com/18935/" target="_blank">查看全文</a>）

&#160;

<strong>5. 《<strong><a href="http://blog.jobbole.com/18940/" target="_blank">Google Drive、Dropbox、SkyDrive 三大云存储服务对比</a></strong>》</strong>

<strong>文章摘要：</strong>很多人都很期待Google推出的云存储服务，因为多数人相信，没有比google更适合做云存储的公司了，作为一个标准的Web公司或者说互联网公 司，云端理所应当的优秀。但比起几年前听传言时的激动，真正的Google Drive发布时，笔者对于google的云存储服务已经远没有以前的热情了。因为现有的云存储服务已经完全满足笔者的需求，更何况笔者用dropbox 已经有几年时间，对于像笔者这样有点恋旧情节的人来说，Google Drive如果在技术上领先的不是一大截，也是不具吸引力的…（<a href="http://blog.jobbole.com/18940/" target="_blank">查看全文</a>）

&#160;

<strong>6. 《<strong><a href="http://blog.jobbole.com/18987/" target="_blank">JavaScript面向对象15分钟教程</a></strong>》</strong>

<strong>文章摘要：</strong>本指南可以很快让你学会写优美的面向对象JavaScript代码，我保证！学会写简洁的JavaScript代码对一个开发者的发展很重要，随着像Node.js这类技术的出现，你现在可以在服务器端写JavaScript代码了，你甚至可以用JavaScript来查询像MongoDB这样的持久性数据存储… （<a href="http://blog.jobbole.com/18987/" target="_blank">查看全文</a>）

&#160;

<strong>7. 《<strong><a href="http://blog.jobbole.com/18992/" target="_blank">了解Instagram背后的技术</a></strong>》</strong>

<strong>文章摘要：</strong>刚被Facebook以10亿美金收购的著名手机照片分享应用Instagram最近吸引了无数人的眼球，Android版本登陆Google Play不到一个月下载量就突破1000万，总用户数即将超过5000万。Instagram联合创始人Mike Krieger说他们用了8周时间打造了最初的Instagram，但现在的系统肯定已经今非昔比。Instagram技术团队曾发表过一篇文章，介绍了Instagram背后的技术，日前Mike Krieger在名为Scaling Instagram的演讲里，又介绍了更多细节，让人们能了解到5名技术人员是如何支撑起整个系统的… （<a href="http://blog.jobbole.com/18992/" target="_blank">查看全文</a>）

<strong>读者评论：</strong>

@<a href="http://weibo.com/n/%E7%AC%A6%E5%BA%86%E6%98%8E">符庆明</a><em>: </em>在设计系统时，Instagram的设计哲学是简单、为最小化运维负担进行优化并监控一切内容；其核心原则是保持简单，不要重复发明轮子，尽可能使用经过验证、稳定可靠的技术

@<a title="Vincent_Lee_金阳" href="http://weibo.com/1853090144">Vincent_Lee_金阳</a>： 云时代，“小”团队也能创造“大”应用的奇迹，5个人要架设起支持海量数据运算的系统，在保持简单的同时，尽量采取成熟、稳定的（开源）技术，实为成功的best practise

@<a title="古月中心相心" href="http://weibo.com/huzhongxiang">古月中心相心</a>： 虽然团队只有5个人，但所用的技术都是搞层次的，没有五年以上的互联网从业经验，很难驾驭。再者amazon的弹性云为Instagram的奇迹提供了成功的前提，天朝没有amazon，所以更不可能有instagram。

&#160;

<strong>8. 《<strong><a href="http://blog.jobbole.com/18997/" target="_blank">请非技术人员不要对技术人员说这很容易实现</a></strong>》</strong>

<strong>文章摘要：</strong>“这个网站相当简单，所有你需要做的就是完成X，Y，Z。你看起来应该是技术很好，所以，我相信，你不需要花费太多时间就能把它搭建起来。”

我时不时的就会收到这样的Email。写这些邮件的人几乎都是跟技术不沾边的人，或正在研究他们的第一个产品。起初，当听到人们这样的话，我总是十分的恼怒。他们在跟谁辩论软件开发所需要的时间？但后来我意识到，即使<em>我自己</em>对<em>自己的</em>项目预测要花去多少开发时间,我也是一筹莫展。如果连我自己都做不好，我何必对那些人恼怒呢？真正让我郁闷的不是他们预估的错误。问题在于他们竟然认为自己可以做出正确的估计… （<a href="http://blog.jobbole.com/18997/" target="_blank">查看全文</a>）

<strong>读者评论：</strong>

@<a href="http://weibo.com/n/%E5%AD%98%E5%9C%A8%E5%A6%82%E6%A3%98">存在如棘</a>: 即使也是技术人员，甚至是专业内的人员，有时也会有这种错误，问题有多难，只有动手解决的人或者了解细节的人才知道。

@<a title="Elton鸿" href="http://weibo.com/eltongao">Elton鸿</a>：抛开角色的差异，这是对人不尊重的表现之一。经常遇到。

&#160;

<strong>9. 《<strong><a href="http://blog.jobbole.com/19001/" target="_blank">张洋：写给.NET程序员，不要困在自己建造的盒子里</a></strong>》</strong>

<strong>文章摘要：</strong>此文章的主旨是希望过于专注.NET<a title="程序员的本质" href="http://blog.jobbole.com/821/">程序员</a>在做好工作、写好.NET程序的同时，能分拨出一点时间接触一下.NET之外的东西（例如10%-20%的时间），而不是鼓动大家什么都去学最后什么都学不精，更不是说.NET不行或劝大家放弃.NET。恕我愚钝，此主旨在文中表达不够清楚，看评论中很多朋友误解了，特此说明。

另外，本文中的观点并不全部是我个人的想法，相当一部分来自我以前聊过天的某些大牛，他们很多来自微软、百度、腾讯等知名企业，并且很多已经成为技术骨干，我曾经从他们那里受益匪浅，于是我把他们的指教结合自身的经验和理解写成此文。这就是此文的来源… （<a href="http://blog.jobbole.com/19001/" target="_blank">查看全文</a>）

<strong>读者评论：</strong>

@<a title="LiuZD_Allen" href="http://weibo.com/1639839294">LiuZD_Allen</a>： 这篇文章好好看了，其实不止.net，做程序员都应该如此。泡上茶，摆上书，敲击键盘，翻资料。每天如此，把编程当娱乐当享受。。。随便吧。反正我是做不到的

&#160;

<strong>10. 《<strong><a href="http://blog.jobbole.com/19016/" target="_blank">重构：代码异味</a></strong>》</strong>

<strong>文章摘要：</strong>我以前写过《php杂谈 《<a title="重构" href="http://www.amazon.cn/gp/product/B003BY6PLK/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&#38;tag=vastwork-23&#38;linkCode=as2&#38;camp=536&#38;creative=3200&#38;creativeASIN=B003BY6PLK" rel="nofollow" target="_blank">重构</a>-改善既有代码的设计》之一重新组织你的函数》，其中代码坏味道，还有深入挖掘的地方，所以我再重点把这一篇提出来，分几篇再提一下，不要闲我烦。

我觉得重构是我们要用一生去研究的地方，跟文学一样，我们要用一生追求优秀的文学作品。我尽量以漫画的形式表现… （<a href="http://blog.jobbole.com/19016/" target="_blank">查看全文</a>）

&#160;

<strong>11. 《<strong><a href="http://blog.jobbole.com/19043/" target="_blank">常见的nginx的配置选项</a></strong>》</strong>

<strong>文章摘要：</strong>Google 上有丰富的 Nginx 的教程和样本配置文件，但很多时候时候，配置这些是需要一些技巧。对于想学 Nginx 的新人，这是一个非常不错的简明指导…… （<a href="http://blog.jobbole.com/19043/" target="_blank">查看全文</a>）

&#160;

<strong>12. 《<strong><a href="http://blog.jobbole.com/19048/" target="_blank">软件测试转型之路</a></strong>》</strong>

<strong>文章摘要：</strong>2010年12月31日，在网易从事了多年开发之后，依依不舍地离开，面临的是一个完全从零开始的全新职位：SQA，也就是tester。

当时对为什么被选择做软件质量保证，而不是继续在研发上进取，持有保留态度：凭什么要我转，不是别人？这个时候，多年的伙伴、领队——雷叔就把我的优点暴露出来了：认真、心细、负责；好吧，基于以上几点，只有“我行”，只能给力了… （<a href="http://blog.jobbole.com/19048/" target="_blank">查看全文</a>）

<strong>读者评论：</strong>

@<a href="http://weibo.com/2277501224">寒菜eric_han</a>：人尽其才，物尽其用。善于找到自己的优点，结合工作岗位是最好不过了。 ps：这图用xmind画的很不错啊

&#160;

<strong>13. 《<strong><a href="http://blog.jobbole.com/19062/" target="_blank">系统设计黄金法则：简单之美</a></strong>》</strong>

<strong>文章摘要：</strong>最近多次看到系统设计与实现的文章与讨论，再加上以前读过的其他资料以及自己的一些实践教训，让我觉得应该把这些资料汇总整理一下。如果要从讨论不同系统的众多资料中总结一条黄金法则的话，那只有一个词——“简单”；如果用一个英语单词来表达的话，那就是——KISS (Keep It Simple, Stupid!)… （<a href="http://blog.jobbole.com/19062/" target="_blank">查看全文</a>）

&#160;

<strong>14. 《<strong><a href="http://blog.jobbole.com/19072/" target="_blank">趣闻：.NET为什么被叫做.NET</a></strong>》</strong>

<strong>文章摘要：</strong>微软最初是在上世纪九十年代末开始开发.NET，最初.NET还不是叫做.NET，而是“Next Generation Windows Services” (NGWS)。那微软又为什么给它改名叫做.NET呢？这个奇怪的名字甚至非常不方便搜索引擎来索引。微软为什么会改名本身就是一个谜…… （<a href="http://blog.jobbole.com/19072/" target="_blank">查看全文</a>）

&#160;

<strong>15. 《<strong><a href="http://blog.jobbole.com/19188/" target="_blank">我猜我不是 “501” 程序员</a></strong>》</strong>

<strong>文章摘要：</strong>当我初次接触到<a href="http://501manifesto.org/" rel="nofollow" target="_blank">《501程序员宣言》</a>（译文见本文最后部分）时，我就高度赞同它的观点。程序员这个职业（尤其是在旧金山）通常鼓励加班。但我却不喜欢这样做，我向往的是一种快乐的编程方式。501程序员宣言，太棒了… （<a href="http://blog.jobbole.com/19188/" target="_blank">查看全文</a>）（注：501程序员指的是那些选择在每天5点01分下班的程序员，他们通常在下班后，就不再关心工作，而是把精力放在家庭上。）

&#160;

<strong>16. 《<strong><a href="http://blog.jobbole.com/19197/" target="_blank">网易邮箱前端Javascript编码规范</a></strong>》</strong>

<strong>文章摘要：</strong>在多年开发邮箱webmail过程中，网易邮箱前端团队积累了不少心得体会，我们开发了很多基础js库，实现了大量前端效果组件，开发了成熟的opoa框架以及api组件，在此向大家做一些分享。

第一篇：<a href="http://blog.jobbole.com/19197/" target="_blank">变量和函数的编码规范</a>

第二篇：<a href="http://blog.jobbole.com/19203/" target="_blank">类规范</a>

&#160;

<strong>17. 《<strong><a href="http://blog.jobbole.com/19227/" target="_blank">计算机科学不等于数学</a></strong>》</strong>

<strong>文章摘要：</strong>一些<a title="程序员的本质" href="http://blog.jobbole.com/821/">程序员</a>认为“计算机科学就是数学”。诚然，计算机科学是数学的一个分支学科，而如今我们认为，这种作为计算机科学基础的分支应当是“理论计算机科学“。如Alonzo Church的“<strong>λ</strong><strong>-</strong>演算”和Alan Turing的<a href="http://en.wikipedia.org/wiki/Turing_machine" rel="nofollow" target="_blank">图灵机</a>，他们为计算机提供了理论基础。当时，二人都自认为是数学家，并明确地从事数学工作。那么如果计算机科学的基础是数学，整个计算机科学怎么不是数学？… （<a href="http://blog.jobbole.com/19227/" target="_blank">查看全文</a>）

<strong>
</strong>

<strong>18. 《<strong><a href="http://blog.jobbole.com/18627/" target="_blank">我是如何在Stack Overflow找到工作的</a></strong>》</strong>

<strong>文章摘要：</strong>做为一个程序员，我经常使用Stack Overflow。因此我也会经常看网站显示的招聘信息。嘿，为啥不用那个找个工作呢？好办。我根据我在github的经历，做了一个个人简介，然后就开始应聘工作了。这个过程中我学到了一些东西，我觉得这对其他人可能也会有些帮助<em>…</em>… （<a href="http://blog.jobbole.com/18627/" target="_blank">查看全文</a>）

<strong>读者评论：</strong>

&#160;

<strong>19. 《<strong><a href="http://blog.jobbole.com/19262/" target="_blank">浅谈PHP代码设计结构</a></strong>》</strong>

<strong>文章摘要：</strong>编码多年，各种代码日夜相伴，如何跟代码友好的相处，不光成为职业生涯的一种回忆，也是编写者功力的直接显露。

如何看待程序和代码呢？那就让我们从程序定义来谈起。如果从业务最终呈现来看，一个程序可以看成是一个真实业务需求的逻辑代码映射。如果从程序逻辑结构看，程序就是数据结构加算法的结合… （<a href="http://blog.jobbole.com/19262/" target="_blank">查看全文</a>）

&#160;

<strong>20. 《<strong><a href="http://blog.jobbole.com/19321/" target="_blank">HTML5+CSS3+jQuery制作视频播放器完全指南</a></strong>》</strong>

<strong>文章摘要：</strong>毫无疑问HTML5已经是大势所趋，知名视频网站YouTube在两年前就开始推广HTML5播放器来代替Flash。虽然国内还没有完全普及HTML5<a title="浏览器" href="http://blog.jobbole.com/12749/">浏览器</a>，但在各大本土浏览器厂商的努力下，支持HTML5的浏览器在中国浏览器市场的占有率也在不断增长中。本教程将会手把手地教你制作一个基于HTML5&#38; CSS3&#38; JavaScript 技术的视频播放器… （<a href="http://blog.jobbole.com/19321/" target="_blank">查看全文</a>）

&#160;

&#160;

<span class="Apple-style-span" style="font-size: 16px; font-weight: bold;">二、创业</span>

<strong>1.《<strong><a href="http://blog.jobbole.com/19279/" target="_blank">崔博：创业两年回顾</a></strong>》</strong>

<strong>文章摘要：</strong>2010年的5月11日，是决定创业的开始，当时我还身处盛大，虽然创业的冲动一直有，但是没有去进行实际的努力，原因是盛大很稳定给员工的待遇相当丰厚，而决定最终决定创业的原因其实很简单，在公司内没有我个人有存在感的位置了，个人诉求和公司战略不符合，在原有职位上，只能成为我自己最鄙视的一类人，就是闲养着的公司蛀虫。

考虑创业的时候想了很多项目，也考虑了自己的很多优势了劣势，存在创业条件的是，有一定人脉，有一些个人资金，在网络游戏行业时间足够久，也经历了很多波折，在网络游戏这个领域内的各个环节相对熟悉，这是我自认为的优点，综合起来，觉得自己成功几率很大，<strong>具有讽刺的意义的是，我后来经历的波折，无一不和我所认为的这些优势相关</strong>…（<a href="http://blog.jobbole.com/19279/" target="_blank">查看全文</a>）

<strong>读者评论：</strong>

@<a href="http://weibo.com/hackerdesign">尘续缘shine_</a>：个人看法：创业前期从产品切入而不是从市场切入，这点我不认可。另外整个过程感觉始终没有重视创业团队的维护，没有搞清团队需求，人数等等因素。好在不少失败都较好的转为了软性资源，加之坚持不懈，以减少错误来构造成功

@<a title="胡杨树2460" href="http://weibo.com/2646577957">胡杨树2460</a>： 创业需要激情更需要掌控。

&#160;

<strong>
</strong>

<span class="Apple-style-span" style="font-size: 16px; font-weight: bold;">三、管理</span>

<strong>1. 《<strong><a href="http://blog.jobbole.com/19207/" target="_blank">川山甲：估算项目的时间进度!</a></strong>》</strong>

<strong>文章摘要：</strong>要做新的项目，产品经理Ａ来找我，问我，这个项目你需要多长时间完成？前提条件：我没看过需求，我只是泛泛的看了下demo，只是知道，页面上有哪些内容，有多少种情况？我没有办法回答她，因为自己也不知道到底用多长时间……（<a href="http://blog.jobbole.com/19207/" target="_blank">查看全文</a>）

<strong>读者评论：</strong>

@<a href="http://weibo.com/1400189083">winter-zh</a>：不是缺方法，也不是缺制度，缺的是各部门对项目管理的真正理解和执行

@<a href="http://weibo.com/houweizong">侯伟宗</a>：我们也是，真正开发人员都没有参与需求会议，周期就定出来了，还有需求无限变，中若有其它紧急事务耽搁进度最后自己绩效不好，真**憋屈

&#160;

<strong>
</strong>

<span class="Apple-style-span" style="font-size: 16px; font-weight: bold;">四、设计</span>

<strong>1. 《<strong><a title="编辑“30个漂亮的QR码名片设计”" href="http://blog.jobbole.com/wp-admin/post.php?post=18958&#38;action=edit">30个漂亮的QR码名片设计</a></strong>》</strong>

<strong>文章摘要：</strong>QR码名片上面有个二维条形码，很多现代智能手机都可以扫描。这个特性有助于给你的网站或社交媒体主页带来流量。对于收名片的人来说，QR码同样很有帮助，可以以数字格式存储所有信息。这也就是说更为安全的存储。不要担心相关设计和创意，本文就有……（查看全文）

&#160;

<strong>2. 《<strong><a href="http://blog.jobbole.com/18629/" target="_blank">非典型性吐槽：亲爱的Python，你为何如此丑陋</a></strong>》</strong>

<strong>文章摘要：</strong>亲爱的Python，有些事情已经困扰我一段时间了，恩，是这样的，其实你…有点丑。瞧，你的内在是如此美丽：Python是一种优美的<a title="如何选择语言和编程语言排名相关文章" href="http://blog.jobbole.com/tag/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/">编程语言</a>，而且Python社区也是开放和受欢迎的。但Python的一些相关资源已经丑到一定程度了，足以影响其可用性和接受程度了。这对整个Python社区都是有害的。

一些文档和教程常常难以导航，用Python构建起来的产品压根儿都没有思考过如何做设计（这里不是指程序的设计，而是指UI），用Python写的博客程序只会帮助产出更多丑陋的有关Python的博客。Pythonist（对Python<a title="程序员的本质" href="http://blog.jobbole.com/821/">程序员</a>的尊称）根本不关心产品的演示效果… （<a href="http://blog.jobbole.com/18629/" target="_blank">查看全文</a>）

&#160;

&#160;

<span class="Apple-style-span" style="font-size: 16px; font-weight: bold;">五、人力资源</span>

<strong>1. 《<strong><a href="http://blog.jobbole.com/19057/" target="_blank">苹果入职信：你会热爱的工作</a></strong>》</strong>

<strong>文章摘要：</strong>这是一封来自苹果公司给新入职员工的信，谈到了在苹果公司的“工作”。虽寥寥数语，但很让人共鸣。它让我看到信念的力量，对创造的热爱……（<a href="http://blog.jobbole.com/19057/" target="_blank">查看全文</a>）

<strong>
</strong>

&#160;]]></description>
			<content:encoded><![CDATA[<p><span class="Apple-style-span" style="font-size: 18px; font-weight: bold;">业界资讯</span></p>
<p><strong>1.《<strong><a href="http://blog.jobbole.com/18976/" target="_blank">陪审团裁决Android侵犯甲骨文Java版权</a></strong>》 </strong></p>
<p><strong>文章摘要：</strong>根据 <a href="http://www.bbc.co.uk/news/business-17985085" rel="nofollow" target="_blank">BBC 的报道</a>，美国法官裁定 Google 侵犯了 Oracle Java 版权，但是尚未决定侵权行为是否属于版权法所允许的“合理公平使用”范畴。</p>
<p>位于加州旧金山的州法院裁定 Google 在 Android 系统中的 9 行代码侵犯了 Oracle 声称的三项 Java 版权中的一个，但是尚在审核该侵权行为是否适用于版权法中的“合理公平使用”范畴。并且，Oracle 现在仅能获得从 $200 到 $150000 之间的赔偿…（<a href="http://blog.jobbole.com/18976/" target="_blank">查看全文</a>）</p>
<p>&nbsp;</p>
<p><strong>2. 《<strong><a href="http://blog.jobbole.com/19129/" target="_blank">Visual Studio 11 RC 版将呈现小清新界面</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>微软于今年3月份发布的 VS11 beta版本，带来了全新的界面。之后微软根据 VS 11 beta 的反馈进行了调整，这些变化将在即将发布的RC版本中呈现。微软的产品用户体验总监Monty Hammontree在今天发表了一篇博客，透露了RC版的界面……（<a href="http://blog.jobbole.com/19129/" target="_blank">查看全文</a>）</p>
<p>&nbsp;</p>
<p><strong>3.《<strong><a href="http://blog.jobbole.com/19114/" target="_blank">2012年5月编程语言排行榜：下一个大受欢迎的语言在哪里</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>TIOBE 于近日公布了2012年5月<a title="如何选择语言和编程语言排名相关文章" href="http://blog.jobbole.com/tag/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/">编程语言</a>指数排行榜。排名前三的语言是：C 、Java 和 C++。</p>
<p>在过去 8 年中，除了 Objective-C 的进入和 Delphi 的退出，TIOBE 指数的 Top 10 排行榜几乎没有很大变化。除 Objective-C  之外，新<a title="如何选择语言和编程语言排名相关文章" href="http://blog.jobbole.com/tag/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/">编程语言</a>的接受情况，看起来比预期的要困难多了。这种情况的可能主要原因是，很难把一个大的代码库，从一种语言迁移至另外一种语言。故而变化缓慢…（<a href="http://blog.jobbole.com/19114/" target="_blank">查看全文</a>）</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span class="Apple-style-span" style="font-size: 18px; font-weight: bold;">职业分享</span></p>
<p><span class="Apple-style-span" style="font-size: 16px; font-weight: bold;">一、IT/互联网</span></p>
<p><strong>1.《<strong><a href="http://blog.jobbole.com/18865/" target="_blank">计算机天才 Phil Katz 短暂而饱受折磨的一生</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>在新的网络精英层出不穷的年代里，我们不能忘记那些更早的技术奠基者。 Phil Katz（1962 – 2000）是压缩软件PKzip的创作者，他的压缩算法已经是Internet的一代压缩规范，正是他，zip 这个词成为了大家熟知的计算机术语。 这篇文章介绍了他短暂而悲剧性的一生…… （<a href="http://blog.jobbole.com/18865/" target="_blank">查看全文</a>）</p>
<p><strong>读者评论：</strong></p>
<p>@<a title="Boyface-Bowen" href="http://weibo.com/1149699651">Boyface-Bowen</a>： 1.单纯的技术人员是不适合创业的，至少需要个懂管理的；2.智商高的人，很多情商很低。</p>
<p>&nbsp;</p>
<p><strong>2. 《<strong><strong><strong><a href="http://blog.jobbole.com/17630/" target="_blank">敏捷代码审查指南</a></strong></strong></strong>》</strong></p>
<p><strong>文章摘要：</strong>“通过一次真正彻底地代码审查（code reviews），仔细阅读你的代码，找出问题，这是我知道的最好的方式去检测早期的bug，但是他们很少去这样干过。某种意义上是因为他们花了大量的时间去写好代码，但是我认为主要是因为绝大部分<a title="程序员的本质" href="http://blog.jobbole.com/821/">程序员</a>害怕其他人审查自己的代码。作为专业的<span class='wp_keywordlink'><a href="http://blog.jobbole.com/821/" title="程序员的本质">程序员</a></span>我们要克服阻力，如果你不愿意别人阅读你的代码，然后只是按照自己的意愿写，如果其他人没法读懂它，又怎能让别人使用呢？”Jim Waldo – 《<a title="Java语言精粹" href="http://www.amazon.cn/gp/product/B0055OQT5Q/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&amp;tag=vastwork-23&amp;linkCode=as2&amp;camp=536&amp;creative=3200&amp;creativeASIN=B0055OQT5Q" rel="nofollow" target="_blank">Java语言精粹</a>》的作者…… （<a href="http://blog.jobbole.com/17630/" target="_blank">查看全文</a>）</p>
<p>&nbsp;</p>
<p><strong>3. 《<strong><a href="http://blog.jobbole.com/10199/" target="_blank">在线集成开发环境 Compilr 的简单体验</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>Compilr 是一个在线的集成开发怀集（IDE），目前支持9种<a title="如何选择语言和编程语言排名相关文章" href="http://blog.jobbole.com/tag/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/">编程语言</a>：C、C++、C#、Java、JavaScript、PHP、Python、Ruby 和 Visual Basic。 Compilr 由坐落于加拿大新斯科舍省的 <a href="http://ninjaotter.com/" rel="nofollow" target="_blank">Ninja Otter Inc</a> 公司开发… （<a href="http://blog.jobbole.com/10199/" target="_blank">查看全文</a>）</p>
<p><strong>读者评论：</strong></p>
<p>@<a title="zipZag柏格" href="http://weibo.com/1847240535">zipZag柏格</a>： 有程序员能忍受编译和运行的时候需要排队吗？没有！</p>
<p>&nbsp;</p>
<p><strong>4. 《<strong><a href="http://blog.jobbole.com/18935/" target="_blank">for 循环为何可恨？</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>Java的闭包(Closure)特征最近成为了一个热门话题。一些精英正在起草一份议案，要在Java将来的版本中加入闭包特征。然而，提议中的闭包语法以及语言上的这种扩充受到了众多Java<a title="程序员的本质" href="http://blog.jobbole.com/821/">程序员</a>的猛烈抨击。不久前，出版过数十本编程书籍的大作家<a href="http://www.elharo.com/" rel="nofollow" target="_blank">Elliotte Rusty Harold</a>发表了对Java中闭包的价值的质疑。尤其是他问道“ <a href="http://cafe.elharo.com/java/why-hate-the-for-loop/" rel="nofollow" target="_blank">for 循环为何可恨？</a>”… （<a href="http://blog.jobbole.com/18935/" target="_blank">查看全文</a>）</p>
<p>&nbsp;</p>
<p><strong>5. 《<strong><a href="http://blog.jobbole.com/18940/" target="_blank">Google Drive、Dropbox、SkyDrive 三大云存储服务对比</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>很多人都很期待Google推出的云存储服务，因为多数人相信，没有比google更适合做云存储的公司了，作为一个标准的Web公司或者说互联网公 司，云端理所应当的优秀。但比起几年前听传言时的激动，真正的Google Drive发布时，笔者对于google的云存储服务已经远没有以前的热情了。因为现有的云存储服务已经完全满足笔者的需求，更何况笔者用dropbox 已经有几年时间，对于像笔者这样有点恋旧情节的人来说，Google Drive如果在技术上领先的不是一大截，也是不具吸引力的…（<a href="http://blog.jobbole.com/18940/" target="_blank">查看全文</a>）</p>
<p>&nbsp;</p>
<p><strong>6. 《<strong><a href="http://blog.jobbole.com/18987/" target="_blank">JavaScript面向对象15分钟教程</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>本指南可以很快让你学会写优美的面向对象JavaScript代码，我保证！学会写简洁的JavaScript代码对一个开发者的发展很重要，随着像Node.js这类技术的出现，你现在可以在服务器端写JavaScript代码了，你甚至可以用JavaScript来查询像MongoDB这样的持久性数据存储… （<a href="http://blog.jobbole.com/18987/" target="_blank">查看全文</a>）</p>
<p>&nbsp;</p>
<p><strong>7. 《<strong><a href="http://blog.jobbole.com/18992/" target="_blank">了解Instagram背后的技术</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>刚被Facebook以10亿美金收购的著名手机照片分享应用Instagram最近吸引了无数人的眼球，Android版本登陆Google Play不到一个月下载量就突破1000万，总用户数即将超过5000万。Instagram联合创始人Mike Krieger说他们用了8周时间打造了最初的Instagram，但现在的系统肯定已经今非昔比。Instagram技术团队曾发表过一篇文章，介绍了Instagram背后的技术，日前Mike Krieger在名为Scaling Instagram的演讲里，又介绍了更多细节，让人们能了解到5名技术人员是如何支撑起整个系统的… （<a href="http://blog.jobbole.com/18992/" target="_blank">查看全文</a>）</p>
<p><strong>读者评论：</strong></p>
<p>@<a href="http://weibo.com/n/%E7%AC%A6%E5%BA%86%E6%98%8E">符庆明</a><em>: </em>在设计系统时，Instagram的设计哲学是简单、为最小化运维负担进行优化并监控一切内容；其核心原则是保持简单，不要重复发明轮子，尽可能使用经过验证、稳定可靠的技术</p>
<p>@<a title="Vincent_Lee_金阳" href="http://weibo.com/1853090144">Vincent_Lee_金阳</a>： 云时代，“小”团队也能创造“大”应用的奇迹，5个人要架设起支持海量数据运算的系统，在保持简单的同时，尽量采取成熟、稳定的（开源）技术，实为成功的best practise</p>
<p>@<a title="古月中心相心" href="http://weibo.com/huzhongxiang">古月中心相心</a>： 虽然团队只有5个人，但所用的技术都是搞层次的，没有五年以上的互联网从业经验，很难驾驭。再者amazon的弹性云为Instagram的奇迹提供了成功的前提，天朝没有amazon，所以更不可能有instagram。</p>
<p>&nbsp;</p>
<p><strong>8. 《<strong><a href="http://blog.jobbole.com/18997/" target="_blank">请非技术人员不要对技术人员说这很容易实现</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>“这个网站相当简单，所有你需要做的就是完成X，Y，Z。你看起来应该是技术很好，所以，我相信，你不需要花费太多时间就能把它搭建起来。”</p>
<p>我时不时的就会收到这样的Email。写这些邮件的人几乎都是跟技术不沾边的人，或正在研究他们的第一个产品。起初，当听到人们这样的话，我总是十分的恼怒。他们在跟谁辩论软件开发所需要的时间？但后来我意识到，即使<em>我自己</em>对<em>自己的</em>项目预测要花去多少开发时间,我也是一筹莫展。如果连我自己都做不好，我何必对那些人恼怒呢？真正让我郁闷的不是他们预估的错误。问题在于他们竟然认为自己可以做出正确的估计… （<a href="http://blog.jobbole.com/18997/" target="_blank">查看全文</a>）</p>
<p><strong>读者评论：</strong></p>
<p>@<a href="http://weibo.com/n/%E5%AD%98%E5%9C%A8%E5%A6%82%E6%A3%98">存在如棘</a>: 即使也是技术人员，甚至是专业内的人员，有时也会有这种错误，问题有多难，只有动手解决的人或者了解细节的人才知道。</p>
<p>@<a title="Elton鸿" href="http://weibo.com/eltongao">Elton鸿</a>：抛开角色的差异，这是对人不尊重的表现之一。经常遇到。</p>
<p>&nbsp;</p>
<p><strong>9. 《<strong><a href="http://blog.jobbole.com/19001/" target="_blank">张洋：写给.NET程序员，不要困在自己建造的盒子里</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>此文章的主旨是希望过于专注.NET<a title="程序员的本质" href="http://blog.jobbole.com/821/">程序员</a>在做好工作、写好.NET程序的同时，能分拨出一点时间接触一下.NET之外的东西（例如10%-20%的时间），而不是鼓动大家什么都去学最后什么都学不精，更不是说.NET不行或劝大家放弃.NET。恕我愚钝，此主旨在文中表达不够清楚，看评论中很多朋友误解了，特此说明。</p>
<p>另外，本文中的观点并不全部是我个人的想法，相当一部分来自我以前聊过天的某些大牛，他们很多来自微软、百度、腾讯等知名企业，并且很多已经成为技术骨干，我曾经从他们那里受益匪浅，于是我把他们的指教结合自身的经验和理解写成此文。这就是此文的来源… （<a href="http://blog.jobbole.com/19001/" target="_blank">查看全文</a>）</p>
<p><strong>读者评论：</strong></p>
<p>@<a title="LiuZD_Allen" href="http://weibo.com/1639839294">LiuZD_Allen</a>： 这篇文章好好看了，其实不止.net，做程序员都应该如此。泡上茶，摆上书，敲击键盘，翻资料。每天如此，把编程当娱乐当享受。。。随便吧。反正我是做不到的</p>
<p>&nbsp;</p>
<p><strong>10. 《<strong><a href="http://blog.jobbole.com/19016/" target="_blank">重构：代码异味</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>我以前写过《php杂谈 《<a title="重构" href="http://www.amazon.cn/gp/product/B003BY6PLK/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&amp;tag=vastwork-23&amp;linkCode=as2&amp;camp=536&amp;creative=3200&amp;creativeASIN=B003BY6PLK" rel="nofollow" target="_blank">重构</a>-改善既有代码的设计》之一重新组织你的函数》，其中代码坏味道，还有深入挖掘的地方，所以我再重点把这一篇提出来，分几篇再提一下，不要闲我烦。</p>
<p>我觉得<span class='wp_keywordlink'><a href="http://www.amazon.cn/gp/product/B003BY6PLK/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=vastwork-23&linkCode=as2&camp=536&creative=3200&creativeASIN=B003BY6PLK" title="重构" rel="nofollow" target="_blank">重构</a></span>是我们要用一生去研究的地方，跟文学一样，我们要用一生追求优秀的文学作品。我尽量以漫画的形式表现… （<a href="http://blog.jobbole.com/19016/" target="_blank">查看全文</a>）</p>
<p>&nbsp;</p>
<p><strong>11. 《<strong><a href="http://blog.jobbole.com/19043/" target="_blank">常见的nginx的配置选项</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>Google 上有丰富的 Nginx 的教程和样本配置文件，但很多时候时候，配置这些是需要一些技巧。对于想学 Nginx 的新人，这是一个非常不错的简明指导…… （<a href="http://blog.jobbole.com/19043/" target="_blank">查看全文</a>）</p>
<p>&nbsp;</p>
<p><strong>12. 《<strong><a href="http://blog.jobbole.com/19048/" target="_blank">软件测试转型之路</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>2010年12月31日，在网易从事了多年开发之后，依依不舍地离开，面临的是一个完全从零开始的全新职位：SQA，也就是tester。</p>
<p>当时对为什么被选择做软件质量保证，而不是继续在研发上进取，持有保留态度：凭什么要我转，不是别人？这个时候，多年的伙伴、领队——雷叔就把我的优点暴露出来了：认真、心细、负责；好吧，基于以上几点，只有“我行”，只能给力了… （<a href="http://blog.jobbole.com/19048/" target="_blank">查看全文</a>）</p>
<p><strong>读者评论：</strong></p>
<p>@<a href="http://weibo.com/2277501224">寒菜eric_han</a>：人尽其才，物尽其用。善于找到自己的优点，结合工作岗位是最好不过了。 ps：这图用xmind画的很不错啊</p>
<p>&nbsp;</p>
<p><strong>13. 《<strong><a href="http://blog.jobbole.com/19062/" target="_blank">系统设计黄金法则：简单之美</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>最近多次看到系统设计与实现的文章与讨论，再加上以前读过的其他资料以及自己的一些实践教训，让我觉得应该把这些资料汇总整理一下。如果要从讨论不同系统的众多资料中总结一条黄金法则的话，那只有一个词——“简单”；如果用一个英语单词来表达的话，那就是——KISS (Keep It Simple, Stupid!)… （<a href="http://blog.jobbole.com/19062/" target="_blank">查看全文</a>）</p>
<p>&nbsp;</p>
<p><strong>14. 《<strong><a href="http://blog.jobbole.com/19072/" target="_blank">趣闻：.NET为什么被叫做.NET</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>微软最初是在上世纪九十年代末开始开发.NET，最初.NET还不是叫做.NET，而是“Next Generation Windows Services” (NGWS)。那微软又为什么给它改名叫做.NET呢？这个奇怪的名字甚至非常不方便搜索引擎来索引。微软为什么会改名本身就是一个谜…… （<a href="http://blog.jobbole.com/19072/" target="_blank">查看全文</a>）</p>
<p>&nbsp;</p>
<p><strong>15. 《<strong><a href="http://blog.jobbole.com/19188/" target="_blank">我猜我不是 “501” 程序员</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>当我初次接触到<a href="http://501manifesto.org/" rel="nofollow" target="_blank">《501程序员宣言》</a>（译文见本文最后部分）时，我就高度赞同它的观点。程序员这个职业（尤其是在旧金山）通常鼓励加班。但我却不喜欢这样做，我向往的是一种快乐的编程方式。501程序员宣言，太棒了… （<a href="http://blog.jobbole.com/19188/" target="_blank">查看全文</a>）（注：501程序员指的是那些选择在每天5点01分下班的程序员，他们通常在下班后，就不再关心工作，而是把精力放在家庭上。）</p>
<p>&nbsp;</p>
<p><strong>16. 《<strong><a href="http://blog.jobbole.com/19197/" target="_blank">网易邮箱前端Javascript编码规范</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>在多年开发邮箱webmail过程中，网易邮箱前端团队积累了不少心得体会，我们开发了很多基础js库，实现了大量前端效果组件，开发了成熟的opoa框架以及api组件，在此向大家做一些分享。</p>
<p>第一篇：<a href="http://blog.jobbole.com/19197/" target="_blank">变量和函数的编码规范</a></p>
<p>第二篇：<a href="http://blog.jobbole.com/19203/" target="_blank">类规范</a></p>
<p>&nbsp;</p>
<p><strong>17. 《<strong><a href="http://blog.jobbole.com/19227/" target="_blank">计算机科学不等于数学</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>一些<a title="程序员的本质" href="http://blog.jobbole.com/821/">程序员</a>认为“计算机科学就是数学”。诚然，计算机科学是数学的一个分支学科，而如今我们认为，这种作为计算机科学基础的分支应当是“理论计算机科学“。如Alonzo Church的“<strong>λ</strong><strong>-</strong>演算”和Alan Turing的<a href="http://en.wikipedia.org/wiki/Turing_machine" rel="nofollow" target="_blank">图灵机</a>，他们为计算机提供了理论基础。当时，二人都自认为是数学家，并明确地从事数学工作。那么如果计算机科学的基础是数学，整个计算机科学怎么不是数学？… （<a href="http://blog.jobbole.com/19227/" target="_blank">查看全文</a>）</p>
<p><strong><br />
</strong></p>
<p><strong>18. 《<strong><a href="http://blog.jobbole.com/18627/" target="_blank">我是如何在Stack Overflow找到工作的</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>做为一个程序员，我经常使用Stack Overflow。因此我也会经常看网站显示的招聘信息。嘿，为啥不用那个找个工作呢？好办。我根据我在github的经历，做了一个个人简介，然后就开始应聘工作了。这个过程中我学到了一些东西，我觉得这对其他人可能也会有些帮助<em>…</em>… （<a href="http://blog.jobbole.com/18627/" target="_blank">查看全文</a>）</p>
<p><strong>读者评论：</strong></p>
<p>&nbsp;</p>
<p><strong>19. 《<strong><a href="http://blog.jobbole.com/19262/" target="_blank">浅谈PHP代码设计结构</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>编码多年，各种代码日夜相伴，如何跟代码友好的相处，不光成为职业生涯的一种回忆，也是编写者功力的直接显露。</p>
<p>如何看待程序和代码呢？那就让我们从程序定义来谈起。如果从业务最终呈现来看，一个程序可以看成是一个真实业务需求的逻辑代码映射。如果从程序逻辑结构看，程序就是数据结构加算法的结合… （<a href="http://blog.jobbole.com/19262/" target="_blank">查看全文</a>）</p>
<p>&nbsp;</p>
<p><strong>20. 《<strong><a href="http://blog.jobbole.com/19321/" target="_blank">HTML5+CSS3+jQuery制作视频播放器完全指南</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>毫无疑问HTML5已经是大势所趋，知名视频网站YouTube在两年前就开始推广HTML5播放器来代替Flash。虽然国内还没有完全普及HTML5<a title="浏览器" href="http://blog.jobbole.com/12749/">浏览器</a>，但在各大本土<span class='wp_keywordlink'><a href="http://blog.jobbole.com/12749/" title="浏览器">浏览器</a></span>厂商的努力下，支持HTML5的浏览器在中国浏览器市场的占有率也在不断增长中。本教程将会手把手地教你制作一个基于HTML5&amp; CSS3&amp; JavaScript 技术的视频播放器… （<a href="http://blog.jobbole.com/19321/" target="_blank">查看全文</a>）</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span class="Apple-style-span" style="font-size: 16px; font-weight: bold;">二、创业</span></p>
<p><strong>1.《<strong><a href="http://blog.jobbole.com/19279/" target="_blank">崔博：创业两年回顾</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>2010年的5月11日，是决定创业的开始，当时我还身处盛大，虽然创业的冲动一直有，但是没有去进行实际的努力，原因是盛大很稳定给员工的待遇相当丰厚，而决定最终决定创业的原因其实很简单，在公司内没有我个人有存在感的位置了，个人诉求和公司战略不符合，在原有职位上，只能成为我自己最鄙视的一类人，就是闲养着的公司蛀虫。</p>
<p>考虑创业的时候想了很多项目，也考虑了自己的很多优势了劣势，存在创业条件的是，有一定人脉，有一些个人资金，在网络游戏行业时间足够久，也经历了很多波折，在网络游戏这个领域内的各个环节相对熟悉，这是我自认为的优点，综合起来，觉得自己成功几率很大，<strong>具有讽刺的意义的是，我后来经历的波折，无一不和我所认为的这些优势相关</strong>…（<a href="http://blog.jobbole.com/19279/" target="_blank">查看全文</a>）</p>
<p><strong>读者评论：</strong></p>
<p>@<a href="http://weibo.com/hackerdesign">尘续缘shine_</a>：个人看法：创业前期从产品切入而不是从市场切入，这点我不认可。另外整个过程感觉始终没有重视创业团队的维护，没有搞清团队需求，人数等等因素。好在不少失败都较好的转为了软性资源，加之坚持不懈，以减少错误来构造成功</p>
<p>@<a title="胡杨树2460" href="http://weibo.com/2646577957">胡杨树2460</a>： 创业需要激情更需要掌控。</p>
<p>&nbsp;</p>
<p><strong><br />
</strong></p>
<p><span class="Apple-style-span" style="font-size: 16px; font-weight: bold;">三、管理</span></p>
<p><strong>1. 《<strong><a href="http://blog.jobbole.com/19207/" target="_blank">川山甲：估算项目的时间进度!</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>要做新的项目，产品经理Ａ来找我，问我，这个项目你需要多长时间完成？前提条件：我没看过需求，我只是泛泛的看了下demo，只是知道，页面上有哪些内容，有多少种情况？我没有办法回答她，因为自己也不知道到底用多长时间……（<a href="http://blog.jobbole.com/19207/" target="_blank">查看全文</a>）</p>
<p><strong>读者评论：</strong></p>
<p>@<a href="http://weibo.com/1400189083">winter-zh</a>：不是缺方法，也不是缺制度，缺的是各部门对项目管理的真正理解和执行</p>
<p>@<a href="http://weibo.com/houweizong">侯伟宗</a>：我们也是，真正开发人员都没有参与需求会议，周期就定出来了，还有需求无限变，中若有其它紧急事务耽搁进度最后自己绩效不好，真**憋屈</p>
<p>&nbsp;</p>
<p><strong><br />
</strong></p>
<p><span class="Apple-style-span" style="font-size: 16px; font-weight: bold;">四、设计</span></p>
<p><strong>1. 《<strong><a title="编辑“30个漂亮的QR码名片设计”" href="http://blog.jobbole.com/wp-admin/post.php?post=18958&amp;action=edit">30个漂亮的QR码名片设计</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>QR码名片上面有个二维条形码，很多现代智能手机都可以扫描。这个特性有助于给你的网站或社交媒体主页带来流量。对于收名片的人来说，QR码同样很有帮助，可以以数字格式存储所有信息。这也就是说更为安全的存储。不要担心相关设计和创意，本文就有……（查看全文）</p>
<p>&nbsp;</p>
<p><strong>2. 《<strong><a href="http://blog.jobbole.com/18629/" target="_blank">非典型性吐槽：亲爱的Python，你为何如此丑陋</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>亲爱的Python，有些事情已经困扰我一段时间了，恩，是这样的，其实你…有点丑。瞧，你的内在是如此美丽：Python是一种优美的<a title="如何选择语言和编程语言排名相关文章" href="http://blog.jobbole.com/tag/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/">编程语言</a>，而且Python社区也是开放和受欢迎的。但Python的一些相关资源已经丑到一定程度了，足以影响其可用性和接受程度了。这对整个Python社区都是有害的。</p>
<p>一些文档和教程常常难以导航，用Python构建起来的产品压根儿都没有思考过如何做设计（这里不是指程序的设计，而是指UI），用Python写的博客程序只会帮助产出更多丑陋的有关Python的博客。Pythonist（对Python<a title="程序员的本质" href="http://blog.jobbole.com/821/">程序员</a>的尊称）根本不关心产品的演示效果… （<a href="http://blog.jobbole.com/18629/" target="_blank">查看全文</a>）</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span class="Apple-style-span" style="font-size: 16px; font-weight: bold;">五、人力资源</span></p>
<p><strong>1. 《<strong><a href="http://blog.jobbole.com/19057/" target="_blank">苹果入职信：你会热爱的工作</a></strong>》</strong></p>
<p><strong>文章摘要：</strong>这是一封来自苹果公司给新入职员工的信，谈到了在苹果公司的“工作”。虽寥寥数语，但很让人共鸣。它让我看到信念的力量，对创造的热爱……（<a href="http://blog.jobbole.com/19057/" target="_blank">查看全文</a>）</p>
<p><strong><br />
</strong></p>
<p>&nbsp;</p>
<h2  class="related_post_title">相关文章</h2><ul class="related_post"><li><a target="_blank" href="http://blog.jobbole.com/5910/" title="伯乐周刊：第22期">伯乐周刊：第22期</a></li><li><a target="_blank" href="http://blog.jobbole.com/18539/" title="伯乐周刊：第21期">伯乐周刊：第21期</a></li><li><a target="_blank" href="http://blog.jobbole.com/18075/" title="伯乐周刊：第20期">伯乐周刊：第20期</a></li><li><a target="_blank" href="http://blog.jobbole.com/17681/" title="伯乐周刊：第19期">伯乐周刊：第19期</a></li><li><a target="_blank" href="http://blog.jobbole.com/17099/" title="伯乐周刊：第18期">伯乐周刊：第18期</a></li><li><a target="_blank" href="http://blog.jobbole.com/16627/" title="伯乐周刊：第17期">伯乐周刊：第17期</a></li><li><a target="_blank" href="http://blog.jobbole.com/16017/" title="伯乐周刊：第16期">伯乐周刊：第16期</a></li><li><a target="_blank" href="http://blog.jobbole.com/15708/" title="伯乐周刊：第15期">伯乐周刊：第15期</a></li><li><a target="_blank" href="http://blog.jobbole.com/15076/" title="伯乐周刊：第14期">伯乐周刊：第14期</a></li><li><a target="_blank" href="http://blog.jobbole.com/14609/" title="伯乐周刊：第13期">伯乐周刊：第13期</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.jobbole.com/19413/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

