<?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>酷壳 - CoolShell.cn</title>
	<atom:link href="http://coolshell.cn/feed" rel="self" type="application/rss+xml" />
	<link>http://coolshell.cn</link>
	<description>享受编程和技术所带来的快乐 - http://coolshell.cn</description>
	<lastBuildDate>Thu, 17 May 2012 01:54:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>rsync 的核心算法</title>
		<link>http://coolshell.cn/articles/7425.html</link>
		<comments>http://coolshell.cn/articles/7425.html#comments</comments>
		<pubDate>Thu, 17 May 2012 00:25:38 +0000</pubDate>
		<dc:creator>陈皓</dc:creator>
				<category><![CDATA[杂项资源]]></category>
		<category><![CDATA[adler]]></category>
		<category><![CDATA[checksum]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[MD5]]></category>
		<category><![CDATA[rsync]]></category>
		<category><![CDATA[Unix]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=7425</guid>
		<description><![CDATA[rsync是unix/linux下同步文件的一个高效算法，它能同步更新两处计算机的文件与目录，并适当利用查找文件中的不同块以减少数据传输。rsync中一项与其他大部分类似程序或协定中所未见的重要特性是镜像是只对有变更的部分进行传送。rsync可拷贝／显示目录属性，以及拷贝文件，并可选择性的压缩以及递归拷贝。rsync利用由Andrew Tridgell发明的算法。这里不介绍其使用方法，只介绍其核心算法。我们可以看到，Unix下的东西，一个命令，一个工具都有很多很精妙的东西，怎么学也学不完，这就是Unix的文化啊。 本来不想写这篇文章的，因为原先发现有很多中文blog都说了这个算法，但是看了一下，发现这些中文blog要么翻译国外文章翻译地非常烂，要么就是介绍这个算法介绍得很乱让人看不懂，还有错误，误人不浅，所以让我觉得有必要写篇rsync算法介绍的文章。（当然，我成文比较仓促，可能会有一些错误，请指正） 问题 首先， 我们先来想一下rsync要解决的问题，如果我们要同步的文件只想传不同的部分，我们就需要对两边的文件做diff，但是这两个问题在两台不同的机器上，无法做diff。如果我们做diff，就要把一个文件传到另一台机器上做diff，但这样一来，我们就传了整个文件，这与我们只想传输不同部的初衷相背。 于是我们就要想一个办法，让这两边的文件见不到面，但还能知道它们间有什么不同。这就出现了rsync的算法。 算法 rsync的算法如下：（假设我们同步源文件名为fileSrc，同步目的文件叫fileDst） 1）分块Checksum算法。首先，我们会把fileDst的文件平均切分成若干个小块，比如每块512个字节（最后一块会小于这个数），然后对每块计算两个checksum， 一个叫rolling checksum，是弱checksum，32位的checksum，其使用的是Mark Adler发明的adler-32算法， 另一个是强checksum，128位的，以前用md4，现在用md5 hash算法。 为什么要这样？因为若干年前的硬件上跑md4的算法太慢了，所以，我们需要一个快算法来鉴别文件块的不同，但是弱的adler32算法碰撞概率太高了，所以我们还要引入强的checksum算法以保证两文件块是相同的。也就是说，弱的checksum是用来区别不同，而强的是用来确认相同。（checksum的具体公式可能看这篇文章） 2）传输算法。同步目标端会把fileDst的一个checksum列表传给同步源，这个列表里包括了三个东西，rolling checksum(32bits)，md5 checksume(128bits)，文件块编号。 我估计你猜到了同步源机器拿到了这个列表后，会对fileSrc做同样的checksum，然后和fileDst的checksum做对比，这样就知道哪些文件块改变了。 但是，聪明的你一定会有以下两个疑问： 如果我fileSrc这边在文件中间加了一个字符，这样后面的文件块都会位移一个字符，这样就完全和fileDst这边的不一样了，但理论上来说，我应该只需要传一个字符就好了。这个怎么解决？ 如果这个checksum列表特别长，而我的两边的相同的文件块可能并不是一样的顺序，那就需要查找，线性的查找起来应该特别慢吧。这个怎么解决？ 很好，让我们来看一下同步源端的算法。 3）checksum查找算法。同步源端拿到fileDst的checksum数组后，会把这个数据存到一个hash table中，用rolling checksum做hash，以便获得O(1)时间复杂度的查找性能。这个hash table是16bits的，所以，hash table的尺寸是2的16次方，对rolling checksum的hash会被散列到0 &#8211; 2^16 &#8211; 1中的某个值。（对于hash table，如果你不清楚，请回去看你大学时的数据结构那本教科书） 顺便说一下，我在网上看到很多文章说，“要对rolling checksum做排序”（比如这篇和这篇），这两篇文章都引用并翻译了原版的这篇文章，但是他们都理解错了，不是排序，就只是把fileDst的checksum数据，按rolling checksum做存到2^16的hash table中，当然会发生碰撞，把碰撞的做成一个链接就好了。这就是原文中所说的第二步。 4）比对算法。这是最关键的算法，细节如下： 4.1）取fileSrc的第一个文件块（我们假设的是512个长度），也就是从fileSrc的第1个字节到第512个字节，取出来后做rolling checksum计算。计算好的值到hash表中查。 4.2）如果查到了，说明发现在fileDst中有潜在相同的文件块，于是就再比较md5的checksum，因为rolling checksume太弱了，可能发生碰撞。于是还要算md5的128bits的checksum，这样一来，我们就有 2^-(32+128) = 2^-160的概率发生碰撞，这太小了可以忽略。如果rolling checksum和md5 checksum都相同，这说明在fileDst中有相同的块，我们需要记下这一块在fileDst下的文件编号。 4.3）如果fileSrc的rolling checksum 没有在hash table中找到，那就不用算md5 checksum了。表示这一块中有不同的信息。总之，只要rolling checksum [...]<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="Linux/Unix 新手和专家教程" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1042.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7425.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1042.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7425.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10437737.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Linux/Unix 新手和专家教程</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Unix 40年：Unix年鉴" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1032.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7425.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1032.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7425.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/04/23/6281985.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Unix 40年：Unix年鉴</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="高级Unix命令" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1044.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7425.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1044.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7425.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">高级Unix命令</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Unix 40年：昨天，今天和明天 " style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1023.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7425.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1023.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7425.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10437733.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Unix 40年：昨天，今天和明天 </font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Unix传奇(下篇)" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2324.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7425.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2324.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7425.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Unix传奇(下篇)</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table>]]></description>
			<content:encoded><![CDATA[<p><a href="http://en.wikipedia.org/wiki/Rsync" target="_blank" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Rsync?referer=');">rsync</a>是unix/linux下同步文件的一个高效算法，它能同步更新两处计算机的文件与目录，并适当利用查找文件中的不同块以减少数据传输。rsync中一项与其他大部分类似程序或协定中所未见的重要特性是镜像是只对有变更的部分进行传送。rsync可拷贝／显示目录属性，以及拷贝文件，并可选择性的压缩以及递归拷贝。rsync利用由<a href="http://en.wikipedia.org/wiki/Andrew_Tridgell" target="_blank" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Andrew_Tridgell?referer=');">Andrew Tridgell</a>发明的算法。这里不介绍其使用方法，只介绍其核心算法。我们可以看到，Unix下的东西，一个命令，一个工具都有很多很精妙的东西，怎么学也学不完，这就是<a title="Unix传奇(上篇)" href="http://coolshell.cn/articles/2322.html" target="_blank">Unix的文化</a>啊。</p>
<p>本来不想写这篇文章的，因为原先发现有很多中文blog都说了这个算法，但是看了一下，发现这些中文blog要么翻译国外文章翻译地非常烂，要么就是介绍这个算法介绍得很乱让人看不懂，还有错误，误人不浅，所以让我觉得有必要写篇rsync算法介绍的文章。（当然，我成文比较仓促，可能会有一些错误，请指正）</p>
<h4>问题</h4>
<p>首先， 我们先来想一下rsync要解决的问题，如果我们要同步的文件只想传不同的部分，我们就需要对两边的文件做diff，但是这两个问题在两台不同的机器上，无法做diff。如果我们做diff，就要把一个文件传到另一台机器上做diff，但这样一来，我们就传了整个文件，这与我们只想传输不同部的初衷相背。</p>
<p>于是我们就要想一个办法，让这两边的文件见不到面，但还能知道它们间有什么不同。这就出现了rsync的算法。</p>
<h4>算法</h4>
<p>rsync的算法如下：（<strong>假设我们同步源文件名为fileSrc，同步目的文件叫fileDst</strong>）</p>
<p><span id="more-7425"></span></p>
<p>1）<strong>分块Checksum算法</strong>。首先，我们会把fileDst的文件平均切分成若干个小块，比如每块512个字节（最后一块会小于这个数），然后对每块计算两个checksum，</p>
<ul>
<li>一个叫<a href="http://en.wikipedia.org/wiki/Rolling_hash" target="_blank" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Rolling_hash?referer=');">rolling checksum</a>，是弱checksum，32位的checksum，其使用的是Mark Adler发明的<a title="Adler-32" href="http://en.wikipedia.org/wiki/Adler-32" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Adler-32?referer=');">adler-32</a>算法，</li>
<li>另一个是强checksum，128位的，以前用md4，现在用md5 hash算法。</li>
</ul>
<p>为什么要这样？因为若干年前的硬件上跑md4的算法太慢了，所以，我们需要一个快算法来鉴别文件块的不同，但是弱的adler32算法碰撞概率太高了，所以我们还要引入强的checksum算法以保证两文件块是相同的。<strong>也就是说，弱的checksum是用来区别不同，而强的是用来确认相同</strong>。（checksum的具体公式可能看<a href="http://rsync.samba.org/tech_report/node3.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/rsync.samba.org/tech_report/node3.html?referer=');">这篇文章</a>）</p>
<p>2）<strong>传输算法。</strong>同步目标端会把fileDst的一个checksum列表传给同步源，这个列表里包括了三个东西，<strong>rolling checksum(32bits)</strong>，<strong>md5 checksume(128bits)</strong>，<strong>文件块编号</strong>。</p>
<p>我估计你猜到了同步源机器拿到了这个列表后，会对fileSrc做同样的checksum，然后和fileDst的checksum做对比，这样就知道哪些文件块改变了。</p>
<p>但是，聪明的你一定会有以下两个疑问：</p>
<ul>
<li>如果我fileSrc这边在文件中间加了一个字符，这样后面的文件块都会位移一个字符，这样就完全和fileDst这边的不一样了，但理论上来说，我应该只需要传一个字符就好了。这个怎么解决？</li>
</ul>
<ul>
<li>如果这个checksum列表特别长，而我的两边的相同的文件块可能并不是一样的顺序，那就需要查找，线性的查找起来应该特别慢吧。这个怎么解决？</li>
</ul>
<div>很好，让我们来看一下同步源端的算法。</div>
<p>3）<strong>checksum查找算法</strong>。同步源端拿到fileDst的checksum数组后，会把这个数据存到一个hash table中，用rolling checksum做hash，以便获得O(1)时间复杂度的查找性能。这个hash table是16bits的，所以，hash table的尺寸是2的16次方，对rolling checksum的hash会被散列到0 &#8211; 2^16 &#8211; 1中的某个值。（对于hash table，如果你不清楚，请回去看你大学时的数据结构那本教科书）</p>
<p>顺便说一下，我在网上看到很多文章说，“要对rolling checksum做排序”（比如<a href="http://www.yejun.cn/?p=472" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.yejun.cn/?p=472&amp;referer=');">这篇</a>和<a href="http://blog.csdn.net/tobeandnottobe/article/details/6719848" target="_blank" onclick="pageTracker._trackPageview('/outgoing/blog.csdn.net/tobeandnottobe/article/details/6719848?referer=');">这篇</a>），这两篇文章都引用并翻译了<a href="http://rsync.samba.org/tech_report/node4.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/rsync.samba.org/tech_report/node4.html?referer=');">原版的这篇文章</a>，但是他们都理解错了，不是排序，就只是把fileDst的checksum数据，按rolling checksum做存到2^16的hash table中，当然会发生碰撞，把碰撞的做成一个链接就好了。这就是<a href="http://rsync.samba.org/tech_report/node4.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/rsync.samba.org/tech_report/node4.html?referer=');">原文</a>中所说的第二步。</p>
<p>4）<strong>比对算法</strong>。这是最关键的算法，细节如下：</p>
<p style="padding-left: 30px;">4.1）取fileSrc的第一个文件块（我们假设的是512个长度），也就是从fileSrc的第1个字节到第512个字节，取出来后做rolling checksum计算。计算好的值到hash表中查。</p>
<p style="padding-left: 30px;">4.2）如果查到了，说明发现在fileDst中有潜在相同的文件块，于是就再比较md5的checksum，因为rolling checksume太弱了，可能发生碰撞。于是还要算md5的128bits的checksum，这样一来，我们就有 2^-(32+128) = 2^-160的概率发生碰撞，这太小了可以忽略。<strong>如果rolling checksum和md5 checksum都相同，这说明在fileDst中有相同的块，我们需要记下这一块在fileDst下的文件编号</strong>。</p>
<p style="padding-left: 30px;">4.3）如果fileSrc的rolling checksum 没有在hash table中找到，那就不用算md5 checksum了。表示这一块中有不同的信息。总之，只要rolling checksum 或 md5 checksum 其中有一个在fileDst的checksum hash表中找不到匹配项，那么就会触发算法对fileSrc的rolling动作。于是，<strong>算法会住后step 1个字节，取fileSrc中字节2-513的文件块要做checksum，go to (4.1) </strong>- 现在你明白什么叫rolling checksum了吧。</p>
<p style="padding-left: 30px;">4.4）这样，我们就可以找出fileSrc相邻两次匹配中的那些文本字符，这些就是我们要往同步目标端传的文件内容了。</p>
<h4>图示</h4>
<p>怎么，你没看懂？ 好吧，我送佛送上西，画个示意图给你看看（对图中的东西我就不再解释了）。</p>
<p><img class="aligncenter size-full wp-image-7428" title="rsync algorithm" src="http://coolshell.cn/wp-content/uploads/2012/05/rsync-algorithm.jpg" alt="" width="650" height="463" /></p>
<p>这样，最终，在同步源这端，我们的rsync算法可能会得到下面这个样子的一个数据数组，图中，红色块表示在目标端已匹配上，不用传输（注：我专门在其中显示了两块chunk #5，相信你会懂的），而白色的地方就是需要传输的内容（注意：这些白色的块是不定长的），这样，同步源这端把这个数组（白色的就是实际内容，红色的就放一个标号）压缩传到目的端，在目的端的rsync会根据这个表重新生成文件，这样，同步完成。</p>
<p><img class="aligncenter size-full wp-image-7427" title="rsync algorithm result" src="http://coolshell.cn/wp-content/uploads/2012/05/rsync-algorithm-result.jpg" alt="" width="606" height="82" /></p>
<p>最后想说一下，对于某些压缩文件使用rsync传输可能会传得更多，因为被压缩后的文件可能会非常的不同。对此，对于gzip和bzip2这样的命令，记得开启 “rsyncalbe” 模式。</p>
<p>（全文完，<strong>转载时请注明作者和出处</strong>）</p>
<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="Linux/Unix 新手和专家教程" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1042.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7425.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1042.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7425.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10437737.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Linux/Unix 新手和专家教程</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Unix 40年：Unix年鉴" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1032.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7425.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1032.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7425.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/04/23/6281985.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Unix 40年：Unix年鉴</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="高级Unix命令" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1044.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7425.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1044.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7425.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">高级Unix命令</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Unix 40年：昨天，今天和明天 " style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1023.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7425.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1023.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7425.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10437733.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Unix 40年：昨天，今天和明天 </font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Unix传奇(下篇)" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2324.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7425.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2324.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7425.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Unix传奇(下篇)</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table><h3  class="related_post_title">相关文章</h3><ul class="related_post"><li>2011年07月18日 -- <a href="http://coolshell.cn/articles/4990.html" title="程序员技术练级攻略">程序员技术练级攻略</a></li><li>2011年03月29日 -- <a href="http://coolshell.cn/articles/4102.html" title="如何学好C语言">如何学好C语言</a></li><li>2011年03月28日 -- <a href="http://coolshell.cn/articles/4077.html" title="纯文本配置还是注册表">纯文本配置还是注册表</a></li><li>2010年08月24日 -- <a href="http://coolshell.cn/articles/2822.html" title="使用grep恢复被删文件内容">使用grep恢复被删文件内容</a></li><li>2010年04月09日 -- <a href="http://coolshell.cn/articles/2322.html" title="Unix传奇(上篇)">Unix传奇(上篇)</a></li><li>2010年04月09日 -- <a href="http://coolshell.cn/articles/2324.html" title="Unix传奇(下篇)">Unix传奇(下篇)</a></li><li>2009年08月16日 -- <a href="http://coolshell.cn/articles/1272.html" title="操作系统航空公司">操作系统航空公司</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/7425.html/feed</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>NoSQL 数据建模技术</title>
		<link>http://coolshell.cn/articles/7270.html</link>
		<comments>http://coolshell.cn/articles/7270.html#comments</comments>
		<pubDate>Tue, 15 May 2012 00:22:13 +0000</pubDate>
		<dc:creator>陈皓</dc:creator>
				<category><![CDATA[数据库]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=7270</guid>
		<description><![CDATA[全文译自墙外文章“NoSQL Data Modeling Techniques”，译得不好，还请见谅。这篇文章看完之后，你可能会对NoSQL的数据结构会有些感觉。我的感觉是，关系型数据库想把一致性，完整性，索引，CRUD都干好，NoSQL只干某一种事，但是牺牲了很多别的东西。总体来说，我觉得NoSQL更适合做Cache。下面是正文—— NoSQL 数据库经常被用作很多非功能性的地方，如，扩展性，性能和一致性的地方。这些NoSQL的特性在理论和实践中都正在被大众广泛地研究着，研究的热点正是那些和性能分布式相关的非功能性的东西，我们都知道 CAP 理论被很好地应用于了 NoSQL 系统中（陈皓注：CAP即，一致性(Consistency)， 可用性(Availability)， 分区容忍性(Partition tolerance)，在分布式系统中，这三个要素最多只能同时实现两个，而NoSQL一般放弃的是一致性）。但在另一方面，NoSQL的数据建模技术却因为缺乏像关系型数据库那样的基础理论没有被世人很好地研究。这篇文章从数据建模方面对NoSQL家族进行了比较，并讨论几个常见的数据建模技术。 要开始讨论数据建模技术，我们不得不或多或少地先系统地看一下NoSQL数据模型的成长的趋势，以此我们可以了解一些他们内在的联系。下图是NoSQL家族的进化图，我们可以看到这样的进化：Key-Value时代，BigTable时代，Document时代，全文搜索时代，和Graph数据库时代：（陈皓注：注意图中SQL说的那句话，NoSQL再这样发展下去就是SQL了，哈哈。） NoSQL Data Models 首先，我们需要注意的是SQL和关系型数据模型已存在了很长的时间，这种面向用户的自然性意味着： 最终用户一般更感兴趣于数据的聚合显示，而不是分离的数据，这主要通过SQL来完成。 我们无法通过人手工控制数据的并发性，完整性，一致性，或是数据类型校验这些东西的。这就是为什么SQL需要在事务，二维表结构（schema）和外表联合上做很多事。 另一方面，SQL可以让软件应用程序在很多情况下不需要关心数据库的数据聚合，和数据完整性和有效性进行控制。而如果我们去除了数据一致性，完整性这些东西，会对性能和分布存储有着重的帮助。正因为如此，我们才有数据模型的进化： Key-Value 键值对存储是非常简单而强大的。下面的很多技术基本上都是基于这个技术开始发展的。但是，Key-Value有一个非常致命的问题，那就是如果我们需要查找一段范围内的key。（陈皓注：学过hash-table数据结构的人都应该知道，hash-table是非序列容器，其并不像数组，链接，队列这些有序容器，我们可以控制数据存储的顺序）。于是，有序键值 （Ordered Key-Value） 数据模型被设计出来解决这一限制，来从根本上提高数据集的问题。 Ordered Key-Value 有序键值模型也非常强大，但是，其也没有对Value提供某种数据模型。通常来说，Value的模型可以由应用负责解析和存取。这种很不方便，于是出现了 BigTable类型的数据库，这个数据模型其实就是map里有map，map里再套map，一层一层套下去，也就是层层嵌套的key-value（value里又是一个key-value），这种数据库的Value主要通过“列族”（column families），列，和时间戳来控制版本。（陈皓注：关于时间戳来对数据的版本控制主要是解决数据存储并发问题，也就是所谓的乐观锁，详见《多版本并发控制(MVCC)在分布式系统中的应用》） Document databases 文档数据库 改进了 BigTable 模型，并提供了两个有意义的改善。第一个是允许Value中有主观的模式（scheme），而不是map套map。第二个是索引。 Full Text Search Engines 全文搜索引擎可以被看作是文档数据库的一个变种，他们可以提供灵活的可变的数据模式（scheme）以及自动索引。他们之间的不同点主要是，文档数据库用字段名做索引，而全文搜索引擎用字段值做索引。 Graph data models 图式数据库 可以被认为是这个进化过程中从 Ordered Key-Value 数据库发展过来的一个分支。图式数据库允许构建议图结构的数据模型。它和文档数据库有关系的原因是，它的很多实现允许value可以是一个map或是一个document。  NoSQL 数据模型摘要 本文剩下的章节将向你介绍数据建模的技术实现和相关模式。但是，在介绍这些技术之前，先来一段序言： NoSQL 数据模型设计一般从业务应用的具体数据查询入手，而不是数据间的关系： 关系型的数据模型基本上是分析数据间的结构和关系。其设计理念是： ”What [...]<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="SQL的Where语句" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1889.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7270.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1889.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7270.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10437720.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">SQL的Where语句</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="【原创】SQL栏目树的代码" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F962.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7270.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F962.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7270.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">【原创】SQL栏目树的代码</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="图解SQL的Join" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3463.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7270.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3463.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7270.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/06/22/13778761.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">图解SQL的Join</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="几篇技术文章" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3311.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7270.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3311.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7270.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">几篇技术文章</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="MySQL性能优化的最佳20+条经验" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1846.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7270.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1846.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7270.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/09/16/31282265.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">MySQL性能优化的最佳20+条经验</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table>]]></description>
			<content:encoded><![CDATA[<p>全文译自墙外文章“<a href="http://highlyscalable.wordpress.com/2012/03/01/nosql-data-modeling-techniques/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/highlyscalable.wordpress.com/2012/03/01/nosql-data-modeling-techniques/?referer=');">NoSQL Data Modeling Techniques</a>”，译得不好，还请见谅。这篇文章看完之后，你可能会对NoSQL的数据结构会有些感觉。我的感觉是，关系型数据库想把一致性，完整性，索引，CRUD都干好，NoSQL只干某一种事，但是牺牲了很多别的东西。总体来说，我觉得NoSQL更适合做Cache。下面是正文——</p>
<p>NoSQL 数据库经常被用作很多非功能性的地方，如，扩展性，性能和一致性的地方。这些NoSQL的特性在理论和实践中都正在被大众广泛地研究着，研究的热点正是那些和性能分布式相关的非功能性的东西，我们都知道 <a href="http://en.wikipedia.org/wiki/CAP_theorem" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/CAP_theorem?referer=');">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://coolshell.cn/wp-content/uploads/2012/05/overview2.png"><img title="overview" src="http://coolshell.cn/wp-content/uploads/2012/05/overview2.png?w=594&amp;h=699" alt="" width="594" height="699" /><br />
</a>NoSQL Data Models</p>
</div>
<p>首先，我们需要注意的是SQL和关系型数据模型已存在了很长的时间，这种面向用户的自然性意味着：</p>
<p><span id="more-7270"></span></p>
<ul>
<li>最终用户一般更感兴趣于数据的聚合显示，而不是分离的数据，这主要通过SQL来完成。</li>
<li>我们无法通过人手工控制数据的并发性，完整性，一致性，或是数据类型校验这些东西的。这就是为什么SQL需要在事务，二维表结构（schema）和外表联合上做很多事。</li>
</ul>
<p>另一方面，SQL可以让软件应用程序在很多情况下不需要关心数据库的数据聚合，和数据完整性和有效性进行控制。而如果我们去除了数据一致性，完整性这些东西，会对性能和分布存储有着重的帮助。正因为如此，我们才有数据模型的进化：</p>
<ul>
<li><strong>Key-Value 键值对存储</strong>是非常简单而强大的。下面的很多技术基本上都是基于这个技术开始发展的。但是，Key-Value有一个非常致命的问题，那就是如果我们需要查找一段范围内的key。（陈皓注：学过hash-table数据结构的人都应该知道，hash-table是非序列容器，其并不像数组，链接，队列这些有序容器，我们可以控制数据存储的顺序）。于是，有序键值 （Ordered Key-Value） 数据模型被设计出来解决这一限制，来从根本上提高数据集的问题。</li>
</ul>
<ul>
<li><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>》）</li>
</ul>
<ul>
<li><strong>Document databases 文档数据库</strong> 改进了 BigTable 模型，并提供了两个有意义的改善。第一个是允许Value中有主观的模式（scheme），而不是map套map。第二个是索引。 <strong>Full Text Search Engines 全文搜索引擎</strong>可以被看作是文档数据库的一个变种，他们可以提供灵活的可变的数据模式（scheme）以及自动索引。他们之间的不同点主要是，文档数据库用字段名做索引，而全文搜索引擎用字段值做索引。</li>
</ul>
<ul>
<li><strong>Graph data models 图式数据库</strong> 可以被认为是这个进化过程中从 Ordered Key-Value 数据库发展过来的一个分支。图式数据库允许构建议图结构的数据模型。它和文档数据库有关系的原因是，它的很多实现允许value可以是一个map或是一个document。</li>
</ul>
<h4> NoSQL 数据模型摘要</h4>
<p>本文剩下的章节将向你介绍数据建模的技术实现和相关模式。但是，在介绍这些技术之前，先来一段序言：</p>
<ul>
<li>NoSQL 数据模型设计一般从业务应用的具体数据查询入手，而不是数据间的关系：</li>
<ul>
<li>关系型的数据模型基本上是分析数据间的结构和关系。其设计理念是： ”<strong>What answers do I have?”</strong><em> </em></li>
<li>NoSQL 数据模型基本上是从应用对数据的存取方式入手，如：我需要支持某种数据查询。其设计理念是<strong> ”What questions do I have?”</strong></li>
</ul>
</ul>
<ul>
<li>NoSQL 数据模型设计比关系型数据库需要对数据结构和算法的更深的了解。在这篇文章中我会和大家说那些尽人皆知的数据结构，这些数据结构并不只是被NoSQL使用，但是对于NoSQL的数据模型却非常有帮助。</li>
</ul>
<ul>
<li>数据冗余和反规格化是一等公民。</li>
</ul>
<ul>
<li>关系型数据库对于处理层级数据和图式数据非常的不方便。NoSQL用来解决图式数据明显是一个非常好的解决方案，几乎所有的NoSQL数据库可以很强地解决此类问题。这就是为什么这篇文章专门拿出一章来说明层级数据模型。</li>
</ul>
<div>下面是NoSQL的分类表，也是我用来写这篇文章时做实践的产品：</div>
<div>
<ul>
<li>Key-Value 存储: Oracle Coherence, Redis, Kyoto Cabinet</li>
<li>类BigTable存储: Apache HBase, Apache Cassandra</li>
<li>文档数据库: MongoDB, CouchDB</li>
<li>全文索引: Apache Lucene, Apache Solr</li>
<li>图数据库: neo4j, FlockDB</li>
</ul>
</div>
<h4>概念技术 Conceptual Techniques</h4>
<p>这一节主要介绍NoSQL数据模型的基本原则。</p>
<h5>(1) 反规格化 Denormalization</h5>
<p>反规格化 Denormalization 可以被认为是把相同的数据拷贝到不同的文档或是表中，这样就可以简化和优化查询，或是正好适合用户的某中特别的数据模型。这篇文章中所说的绝大多数技术都或多或少地导向了这一技术。</p>
<p>总体来说，反规格化需要权衡下面这些东西：</p>
<ul>
<li><strong><em>查询数据量 /查询IO </em></strong> VS  <strong><em>总数据量</em></strong>。使用反规格化，一方面可以把一条查询语句所需要的所有数据组合起来放到一个地方存储。这意味着，其它不同不同查询所需要的相同的数据，需要放在别不同的地方。因此，这产生了很多冗余的数据，从而导致了数据量的增大。</li>
</ul>
<ul>
<li><strong><em>处理复杂度 </em></strong> VS <strong><em>总数据量</em></strong>. 在符合范式的数据模式上进行表连接的查询，很显然会增加了查询处理的复杂度，尤其对于分布式系统来说更是。反规格化的数据模型允许我们以方便查询的方式来存构造数据结构以简化查询复杂度。</li>
</ul>
<p><strong>适用性</strong>: Key-Value Store 键值对数据库， Document Databases文档数据库， BigTable风格的数据库。</p>
<h5>(2) 聚合 Aggregates</h5>
<p>所有类型的NoSQL数据库都会提供灵活的Schema（数据结构，对数据格式的限制）：</p>
<ul>
<li>Key-Value Stores 和 Graph Databases 基本上来说不会Value的形式，所以Value可以是任意格式。这样一来，这使得我们可以任意组合一个业务实体的keys。比如，我们有一个用户帐号的业务实体，其可以被如下这些key组合起来： <em>UserID_name, UserID_email, UserID_messages</em> 等等。如果一个用户没有email或message，那么相应也不会有这样的记录。</li>
</ul>
<ul>
<li>BigTable 模型通过列集合来支持灵活的Schema，我们称之为列族（<em>column family</em>）。BigTable还可以在同一记录上出现不同的版本（通过时间戳）。</li>
</ul>
<ul>
<li>Document databases 文档数据库是一种层级式的“去Schema”的存储，虽然有些这样的数据库允许检验需要保存的数据是否满足某种Schema。</li>
</ul>
<p>灵活的Schema允许你可以用一种嵌套式的内部数据方式来存储一组有关联的业务实体（陈皓注：类似于JSON这样的数据封装格式）。这样可以为我们带来两个好处。</p>
<ul>
<li>最小化“一对多”关系——可以通过嵌套式的方式来存储实体，这样可以少一些表联结。</li>
</ul>
<ul>
<li>可以让内部技术上的数据存储更接近于业务实体，特别是那种混合式的业务实体。可能存于一个文档集或是一张表中。</li>
</ul>
<div>下图示意了这两种好处。图中描给了电子商务中的商品模型（陈皓注：我记得我在“<a title="挑战无处不在" href="http://coolshell.cn/articles/7048.html" target="_blank">挑战无处不在</a>”一文中说到过电商中产品分类数据库设计的挑战）</div>
<div>
<ul>
<li>首先，所有的商品Product都会有一个ID，Price 和 Description。</li>
</ul>
<ul>
<li>然后，我们可以知道不同的类型的商品会有不同的属性。比如，作者是书的属性，长度是牛仔裤的属性。其些属性可能是“一对多”或是“多对多”的关系，如：唱片中的曲目。</li>
</ul>
<ul>
<li>接下来，我们知道，某些业务实体不可能使用固定的类型。如：牛仔裤的属性并不是所有的牌子都有的，而且，有些名牌还会搞非常特别的属性。</li>
</ul>
<p>对于关系型数据库来说，要设计这样的数据模型并不简单，而且设计出来的绝对离优雅很远很远。而我们NoSQL中灵活的Schema允许你使用一个聚合 Aggregate (product) 可以建出所有不同种类的商品和他们的不同的属性：</p>
</div>
<div>
<div id="attachment_404">
<p><a href="http://coolshell.cn/wp-content/uploads/2012/05/soft-schema2.png"><img class="aligncenter" title="soft-schema" src="http://coolshell.cn/wp-content/uploads/2012/05/soft-schema2.png?w=594&amp;h=439" alt="" 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>
<h5>(3) 应用层联结 Application Side Joins</h5>
<p>表联结基本上不被NoSQL支持。正如我们前面所说的，NoSQL是“面向问题”而不是“面向答案”的，不支持表联结就是“面向问题”的后果。表的联结是在设计时被构造出来的，而不是在执行时建造出来的。所以，表联结在运行时是有很大开销的（陈皓注：搞过SQL表联结的都知道笛卡尔积是什么东西，大可以在参看以前酷壳的“<a title="图解SQL的Join" href="http://coolshell.cn/articles/3463.html" target="_blank">图解数据库表Joins</a>”），但是在使用了 Denormalization 和 Aggregates 技术后，我们基本不用进行表联结，如：你们使用嵌套式的数据实体。当然，如果你需要联结数据，你需要在应用层完成这个事。下面是几个主要的Use Case：</p>
<ul>
<li>多对多的数据实体关系——经常需要被连接或联结。</li>
</ul>
<ul>
<li>聚合 Aggregates 并不适用于数据字段经常被改变的情况。对此，我们需要把那些经常被改变的字段分到另外的表中，而在查询时我们需要联结数据。例如，我们有个Message系统可以有一个User实体，其包括了一个内嵌的Message实体。但是，如果用户不断在附加 message，那么，最好把message拆分到另一个独立的实体，但在查询时联结这User和Message这两个实体。如下图：</li>
</ul>
<p><a href="http://coolshell.cn/wp-content/uploads/2012/05/aggregates-joins.png"><img class="aligncenter" title="aggregates-joins" src="http://coolshell.cn/wp-content/uploads/2012/05/aggregates-joins.png?w=594" alt="" /></a></p>
<p><strong>适用性</strong>: Key-Value Store 键值对数据库， Document Databases文档数据库， BigTable风格的数据库， Graph Databases 图数据库。</p>
<h4>通用建模技术 General Modeling Techniques</h4>
<p>在本书中，我们将讨论NoSQL中各种不同的通用的数据建模技术。</p>
<h5>(4) 原子聚合 Atomic Aggregates</h5>
<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" onclick="pageTracker._trackPageview('/outgoing/highlyscalable.wordpress.com/2012/01/07/mvcc-transactions-key-value/?referer=');">应用层管理的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://coolshell.cn/wp-content/uploads/2012/05/atomic-aggregate1.png"><img class="aligncenter" title="atomic-aggregate" src="http://coolshell.cn/wp-content/uploads/2012/05/atomic-aggregate1.png?w=594" alt="" /><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>
<h5>(5) 可枚举键 Enumerable Keys</h5>
<p>也许，对于无顺序的Key-Value最大的好处是业务实体可以被容易地hash以分区在多个服务器上。而排序了的key会把事情搞复杂，但是有些时候，一个应用能从排序key中获得很多好处，就算是数据库本身不提供这个功能。让我们来思考下email消息的数据模型：</p>
<ol>
<li>一些NoSQL的数据库提供原子计数器以允许生一些连续的ID。在这种情况下，我们可以使用 <em>userID_messageID</em> 来做为一个组合key。如果我们知道最新的message ID，就可以知道前一个message，也可能知道再前面和后面的Message。</li>
<li>Messages可以被打包。比如，每天的邮件包。这样，我们就可以对邮件按指定的时间段来遍历。</li>
</ol>
<p><strong><strong><strong>适用性</strong>: </strong></strong>Key-Value Store 键值对数据库<strong>。</strong></p>
<h5>(6) 降维 Dimensionality Reduction</h5>
<p>Dimensionality Reduction 降维是一种技术可以允许把一个多维的数据映射成一个Key-Value或是其它非多给的数据模型。</p>
<p>传统的地理位置信息系统使用一些如“四分树<a href="http://en.wikipedia.org/wiki/Quadtree" target="_blank" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Quadtree?referer=');">QuadTree</a>” 或 “<a href="http://en.wikipedia.org/wiki/R-tree" target="_blank" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/R-tree?referer=');">R-Tree</a>” 来做地理位置索引。这些数据结构的内容需要被在适当的位置更新，并且，如果数据量很大的话，操作成本会很高。另一个方法是我们可以遍历一个二维的数据结构并把其扁平化成一个列表。一个众所周知的例子是<a href="http://en.wikipedia.org/wiki/Geohash" target="_blank" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Geohash?referer=');">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://coolshell.cn/wp-content/uploads/2012/05/geohash-traversal1.png"><img title="geohash-traversal" src="http://coolshell.cn/wp-content/uploads/2012/05/geohash-traversal1.png?w=594" alt="" /><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>
<h5>(7) 索引表 Index Table</h5>
<p>Index Table 索引表是一个非常直白的技术，其可以你在不支持索引的数据库中得到索引的好处。BigTable是这类最重要的数据库。这需要我们维护一个有相应存取模式的特别表。例如，我们有一个主表存着用户帐号，其可以被UserID存取。某查询需要查出某个城市里所有的用户，于是我们可以加入一张表，这张表用城市做主键，所有和这个城市相关的UserID是其Value，如下所示：</p>
<div id="attachment_399">
<p style="text-align: center;"><a href="http://coolshell.cn/wp-content/uploads/2012/05/index-table.png"><img title="index-table" src="http://coolshell.cn/wp-content/uploads/2012/05/index-table.png?w=594" alt="" /><br />
</a>Index Table Example</p>
</div>
<p>可见，城市索引表的需要和对主表用户表保持一致性，因此，主表的每一个更新可能需要对索引表进行更新，不然就是一个批处理更新。无论哪个方式，这都会损伤一些性能，因为需要保持一致性。</p>
<p>Index Table 索引表可以被认为是关系型数据库中的视图的等价物。</p>
<p><strong>适用性</strong>: BigTable 数据库。</p>
<h5>(8) 键组合索引 Composite Key Index</h5>
<p>Composite key 键组合是一个很常用的技术，对此，当我们的数据库支持键排序时能得到极大的好处。Composite key组合键的拼接成为第二排序字段可以让你构建出一种多维索引，这很像我们之前说过的 Dimensionality Reduction 降维技术。例如，我们需要存取用户统计。如果我们需要根据不同的地区来统计用户的分布情况，我们可以把Key设计成这样的格式 <em>(State:City:UserID)</em>，这样一来，就使得我们可以通过State到City来按组遍历用户，特别是我们的NoSQL数据库支持在key上按区查询（如：BigTable类的系统）：</p>
<pre class="brush: sql; title: ; notranslate">SELECT Values WHERE state=&quot;CA:*&quot;
SELECT Values WHERE city=&quot;CA:San Francisco*&quot;</pre>
<div id="attachment_477">
<p style="text-align: center;"><a href="http://highlyscalable.files.wordpress.com/2012/03/composite-key-index.png" onclick="pageTracker._trackPageview('/outgoing/highlyscalable.files.wordpress.com/2012/03/composite-key-index.png?referer=');"><img title="composite-key-index" src="http://highlyscalable.files.wordpress.com/2012/03/composite-key-index.png?w=594" alt="" /><br />
</a>Composite Key Index</p>
</div>
<p><strong><strong>适用性</strong>: </strong>BigTable 数据库。</p>
<h5>(9) 键组合聚合 Aggregation with Composite Keys</h5>
<p>Composite keys  键组合技术并不仅仅可以用来做索引，同样可以用来区分不用的类型的数据以支持数据分组。考虑一个例子，我们有一个海量的日志数组，这个日志记录了互联网上的用户的访问来源。我们需要计算从某一网站过来的独立访客的数量，在关系型数据库中，我们可能需要下面这样的SQL查询语句：</p>
<pre class="brush: sql; title: ; notranslate">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://coolshell.cn/wp-content/uploads/2012/05/composite-key-collating1.png"><img title="composite-key-collating" src="http://coolshell.cn/wp-content/uploads/2012/05/composite-key-collating1.png?w=594" alt="" /><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>
<h5>(10) 反转搜索 Inverted Search – 直接聚合 Direct Aggregation</h5>
<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; title: ; notranslate">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://coolshell.cn/wp-content/uploads/2012/05/invert-direct1.png"><img title="invert-direct" src="http://coolshell.cn/wp-content/uploads/2012/05/invert-direct1.png?w=594&amp;h=438" alt="" width="594" height="438" /><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>
<h5>(11) 树形聚合Tree Aggregation</h5>
<p>树形或是任意的图（需反规格化）可以被直接打成一条记录或文档存放。</p>
<ul>
<li>当树形结构被一次性取出时这会非常有效率（如：我们需要展示一个blog的树形评论）</li>
<li>搜索和任何存取这个实体都会存在问题。</li>
<li>对于大多数NoSQL的实现来说，更新数据都是很不经济的（相比起独立结点来说）</li>
</ul>
<div id="attachment_381">
<p style="text-align: center;"><a href="http://coolshell.cn/wp-content/uploads/2012/05/tree-aggregation.png"><img title="tree-aggregation" src="http://coolshell.cn/wp-content/uploads/2012/05/tree-aggregation.png?w=594" alt="" /><br />
</a>Tree Aggregation</p>
</div>
<p><strong>适用性</strong>: Key-Value 键值对数据库, Document Databases 文档数据库</p>
<h5>(12) 邻接列表 Adjacency Lists</h5>
<p>Adjacency Lists 邻接列表是一种图 &#8211; 每一个结点都是一个独立的记录，其包含了 所有的父结点或子结点。这样，我们就可以通过给定的父或子结点来进行搜索。当然，我们需要通过hop查询遍历图。这个技术在广度和深度查询，以及得到某个结点的子树上没有效率。</p>
<p><strong>适用性</strong>: Key-Value 键值对数据库, Document Databases 文档数据库</p>
<p><strong><br />
</strong></p>
<h5>(13) Materialized Paths</h5>
<p>Materialized Paths 可以帮助避免递归遍历（如：树形结构）。这个技术也可以被认为是反规格化的一种变种。其想法是为每个结点加上父结点或子结点的标识属性，这样就可以不需要遍历就知道所有的后裔结点和祖先结点了：</p>
<div id="attachment_372">
<p style="text-align: center;"><a href="http://coolshell.cn/wp-content/uploads/2012/05/materialized-paths2.png"><img title="materialized-paths" src="http://coolshell.cn/wp-content/uploads/2012/05/materialized-paths2.png?w=594" alt="" /><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://coolshell.cn/wp-content/uploads/2012/05/materialized-paths-2.png"><img title="materialized-paths-2" src="http://coolshell.cn/wp-content/uploads/2012/05/materialized-paths-2.png?w=594" alt="" /><br />
</a>Query Materialized Paths using RegExp</p>
</div>
<p><strong>适用性</strong>: Key-Value 键值对数据库, Document Databases 文档数据, Search Engines 搜索引擎</p>
<h5>(14) 嵌套集 Nested Sets</h5>
<p><a href="http://en.wikipedia.org/wiki/Nested_set_model" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Nested_set_model?referer=');">Nested sets</a> 嵌套集是树形结构的标准技术。它被广泛地用在了关系性数据库中，它完全地适用于 Key-Value 键值对数据库 和 Document Databases 文档数据库。这个技术的想法是把叶子结点存储成一个数组，并通过使用索引的开始和结束来映射每一个非叶子结点到一个叶子结点集，就如下图所示一样：</p>
<div id="attachment_360">
<p style="text-align: center;"><a href="http://coolshell.cn/wp-content/uploads/2012/05/nested-sets.png"><img title="nested-sets" src="http://coolshell.cn/wp-content/uploads/2012/05/nested-sets.png?w=594" alt="" /><br />
</a>Modeling of eCommerce Catalog using Nested Sets</p>
</div>
<p>这样的数据结构对于immutable data不变的数据 有非常不错的效率，因为其点内存空间小，并且可以很快地找出所有的叶子结点而不需要树的遍历。尽管如此，在插入和更新上需要很高的性能成本，因为新的叶子结点需要大规模地更新索引。</p>
<p><strong>适用性</strong>: Key-Value Stores 键值数据库, Document Databases 文档数据库</p>
<h4>(15) 嵌套文档扁平化：有限的字段名 Nested Documents Flattening: Numbered Field Names</h4>
<p>搜索引擎基本上来说和扁平文档一同工作，如：每一个文档是一个扁平的字段和值的例表。这种数据模型的用来把业务实体映射到一个文本文档上，如果你的业务实体有很复杂的内部结构，这可能会变得很有挑战。一个典型的挑战是把一个有层级的文档映映射出来。例如，文档中嵌套另一个文档。让我们看看下面的示例：</p>
<div id="attachment_363">
<p style="text-align: center;"><a href="http://coolshell.cn/wp-content/uploads/2012/05/nested-documents-1.png"><img title="nested-documents-1" src="http://coolshell.cn/wp-content/uploads/2012/05/nested-documents-1.png?w=594" alt="" /><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://coolshell.cn/wp-content/uploads/2012/05/nested-documents-3.png"><img title="nested-documents-3" src="http://coolshell.cn/wp-content/uploads/2012/05/nested-documents-3.png?w=594" alt="" /><br />
</a>Nested Document Modeling using Numbered Field Names</p>
</div>
<p>这样的方式根本没有扩展性，对于一些复杂的问题来说只会让代码复杂度和维护工作变大。</p>
<p><strong>适用性</strong>: Search Engines 全文搜索</p>
<h5>(16)嵌套文档扁平化：邻近查询 Nested Documents Flattening: Proximity Queries</h5>
<p>在附录 [4.6]中给出了这个技术用来解决扁平层次文档。它用邻近的查询来限制可被查询的单词的范围。下图中，所有的技能和等级被放在一个字段中，叫 SkillAndLevel，查询中出现的 “Excellent” 和 “Poetry” 必需一个紧跟另一个：</p>
<div id="attachment_364">
<p style="text-align: center;"><a href="http://coolshell.cn/wp-content/uploads/2012/05/nested-documents-2.png"><img title="nested-documents-2" src="http://coolshell.cn/wp-content/uploads/2012/05/nested-documents-2.png?w=594" alt="" /><br />
</a>Nested Document Modeling using Proximity Queries</p>
</div>
<p>附录 [4.3] 中讲述了这个技术被用在Solr中的一个成功案例。</p>
<p><strong>适用性</strong>: Search Engines 全文搜索</p>
<h5>(17) 图结构批处理 Batch Graph Processing</h5>
<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/" onclick="pageTracker._trackPageview('/outgoing/highlyscalable.wordpress.com/2012/02/01/mapreduce-patterns/?referer=');">在我前一篇的文章中的那个示例</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>
<ol>
<li>Key-Value Stores:
<ol>
<li><a href="http://www.devshed.com/c/a/MySQL/Database-Design-Using-KeyValue-Tables/" onclick="pageTracker._trackPageview('/outgoing/www.devshed.com/c/a/MySQL/Database-Design-Using-KeyValue-Tables/?referer=');">http://www.devshed.com/c/a/MySQL/Database-Design-Using-KeyValue-Tables/</a></li>
<li><a href="http://antirez.com/post/Sorting-in-key-value-data-model.html" onclick="pageTracker._trackPageview('/outgoing/antirez.com/post/Sorting-in-key-value-data-model.html?referer=');">http://antirez.com/post/Sorting-in-key-value-data-model.htm</a>l</li>
<li><a href="http://stackoverflow.com/questions/3554169/difference-between-document-based-and-key-value-based-databases" onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/questions/3554169/difference-between-document-based-and-key-value-based-databases?referer=');">http://stackoverflow.com/questions/3554169/difference-between-document-based-and-key-value-based-databases</a></li>
<li><a href="http://dbmsmusings.blogspot.com/2010/03/distinguishing-two-major-types-of_29.html" onclick="pageTracker._trackPageview('/outgoing/dbmsmusings.blogspot.com/2010/03/distinguishing-two-major-types-of_29.html?referer=');">http://dbmsmusings.blogspot.com/2010/03/distinguishing-two-major-types-of_29.html</a></li>
</ol>
</li>
<li>BigTable-style Databases:
<ol>
<li><a href="http://www.slideshare.net/ebenhewitt/cassandra-datamodel-4985524" onclick="pageTracker._trackPageview('/outgoing/www.slideshare.net/ebenhewitt/cassandra-datamodel-4985524?referer=');">http://www.slideshare.net/ebenhewitt/cassandra-datamodel-4985524</a></li>
<li><a href="http://www.slideshare.net/mattdennis/cassandra-data-modeling" onclick="pageTracker._trackPageview('/outgoing/www.slideshare.net/mattdennis/cassandra-data-modeling?referer=');">http://www.slideshare.net/mattdennis/cassandra-data-modeling</a></li>
<li><a href="http://nosql.mypopescu.com/post/17419074362/cassandra-data-modeling-examples-with-matthew-f-dennis" onclick="pageTracker._trackPageview('/outgoing/nosql.mypopescu.com/post/17419074362/cassandra-data-modeling-examples-with-matthew-f-dennis?referer=');">http://nosql.mypopescu.com/post/17419074362/cassandra-data-modeling-examples-with-matthew-f-dennis</a></li>
<li><a href="http://s-expressions.com/2009/03/08/hbase-on-designing-schemas-for-column-oriented-data-stores/" onclick="pageTracker._trackPageview('/outgoing/s-expressions.com/2009/03/08/hbase-on-designing-schemas-for-column-oriented-data-stores/?referer=');">http://s-expressions.com/2009/03/08/hbase-on-designing-schemas-for-column-oriented-data-stores/</a></li>
<li><a href="http://jimbojw.com/wiki/index.php?title=Understanding_Hbase_and_BigTable" onclick="pageTracker._trackPageview('/outgoing/jimbojw.com/wiki/index.php?title=Understanding_Hbase_and_BigTable&amp;referer=');">http://jimbojw.com/wiki/index.php?title=Understanding_Hbase_and_BigTable</a></li>
</ol>
</li>
<li>Document Databases:
<ol>
<li><a href="http://www.slideshare.net/mongodb/mongodb-schema-design-richard-kreuters-mongo-berlin-preso" onclick="pageTracker._trackPageview('/outgoing/www.slideshare.net/mongodb/mongodb-schema-design-richard-kreuters-mongo-berlin-preso?referer=');">http://www.slideshare.net/mongodb/mongodb-schema-design-richard-kreuters-mongo-berlin-preso</a></li>
<li><a href="http://www.michaelhamrah.com/blog/2011/08/data-modeling-at-scale-mongodb-mongoid-callbacks-and-denormalizing-data-for-efficiency/" onclick="pageTracker._trackPageview('/outgoing/www.michaelhamrah.com/blog/2011/08/data-modeling-at-scale-mongodb-mongoid-callbacks-and-denormalizing-data-for-efficiency/?referer=');">http://www.michaelhamrah.com/blog/2011/08/data-modeling-at-scale-mongodb-mongoid-callbacks-and-denormalizing-data-for-efficiency/</a></li>
<li><a href="http://seancribbs.com/tech/2009/09/28/modeling-a-tree-in-a-document-database/" onclick="pageTracker._trackPageview('/outgoing/seancribbs.com/tech/2009/09/28/modeling-a-tree-in-a-document-database/?referer=');">http://seancribbs.com/tech/2009/09/28/modeling-a-tree-in-a-document-database/</a></li>
<li><a href="http://www.mongodb.org/display/DOCS/Schema+Design" onclick="pageTracker._trackPageview('/outgoing/www.mongodb.org/display/DOCS/Schema+Design?referer=');">http://www.mongodb.org/display/DOCS/Schema+Design</a></li>
<li><a href="http://www.mongodb.org/display/DOCS/Trees+in+MongoDB" onclick="pageTracker._trackPageview('/outgoing/www.mongodb.org/display/DOCS/Trees+in+MongoDB?referer=');">http://www.mongodb.org/display/DOCS/Trees+in+MongoDB</a></li>
<li><a href="http://blog.fiesta.cc/post/11319522700/walkthrough-mongodb-data-modeling" onclick="pageTracker._trackPageview('/outgoing/blog.fiesta.cc/post/11319522700/walkthrough-mongodb-data-modeling?referer=');">http://blog.fiesta.cc/post/11319522700/walkthrough-mongodb-data-modeling</a></li>
</ol>
</li>
<li>Full Text Search Engines:
<ol>
<li><a href="http://www.searchworkings.org/blog/-/blogs/query-time-joining-in-lucene" onclick="pageTracker._trackPageview('/outgoing/www.searchworkings.org/blog/-/blogs/query-time-joining-in-lucene?referer=');">http://www.searchworkings.org/blog/-/blogs/query-time-joining-in-lucene</a></li>
<li><a href="http://www.lucidimagination.com/devzone/technical-articles/solr-and-rdbms-basics-designing-your-application-best-both" onclick="pageTracker._trackPageview('/outgoing/www.lucidimagination.com/devzone/technical-articles/solr-and-rdbms-basics-designing-your-application-best-both?referer=');">http://www.lucidimagination.com/devzone/technical-articles/solr-and-rdbms-basics-designing-your-application-best-both</a></li>
<li><a href="http://blog.griddynamics.com/2011/07/solr-experience-search-parent-child.html" onclick="pageTracker._trackPageview('/outgoing/blog.griddynamics.com/2011/07/solr-experience-search-parent-child.html?referer=');">http://blog.griddynamics.com/2011/07/solr-experience-search-parent-child.html</a></li>
<li><a href="http://www.lucidimagination.com/blog/2009/07/18/the-spanquery/" onclick="pageTracker._trackPageview('/outgoing/www.lucidimagination.com/blog/2009/07/18/the-spanquery/?referer=');">http://www.lucidimagination.com/blog/2009/07/18/the-spanquery/</a></li>
<li><a href="http://blog.mgm-tp.com/2011/03/non-standard-ways-of-using-lucene/" onclick="pageTracker._trackPageview('/outgoing/blog.mgm-tp.com/2011/03/non-standard-ways-of-using-lucene/?referer=');">http://blog.mgm-tp.com/2011/03/non-standard-ways-of-using-lucene/</a></li>
<li><a href="http://www.slideshare.net/MarkHarwood/proposal-for-nested-document-support-in-lucene" onclick="pageTracker._trackPageview('/outgoing/www.slideshare.net/MarkHarwood/proposal-for-nested-document-support-in-lucene?referer=');">http://www.slideshare.net/MarkHarwood/proposal-for-nested-document-support-in-lucene</a></li>
<li><a href="http://mysolr.com/tips/denormalized-data-structure/" onclick="pageTracker._trackPageview('/outgoing/mysolr.com/tips/denormalized-data-structure/?referer=');">http://mysolr.com/tips/denormalized-data-structure/</a></li>
<li><a href="http://sujitpal.blogspot.com/2010/10/denormalizing-maps-with-lucene-payloads.html" onclick="pageTracker._trackPageview('/outgoing/sujitpal.blogspot.com/2010/10/denormalizing-maps-with-lucene-payloads.html?referer=');">http://sujitpal.blogspot.com/2010/10/denormalizing-maps-with-lucene-payloads.html</a></li>
<li><a href="http://java.dzone.com/articles/hibernate-search-mapping-entit" onclick="pageTracker._trackPageview('/outgoing/java.dzone.com/articles/hibernate-search-mapping-entit?referer=');">http://java.dzone.com/articles/hibernate-search-mapping-entit</a></li>
</ol>
</li>
<li>Graph Databases:
<ol>
<li><a href="http://docs.neo4j.org/chunked/stable/tutorial-comparing-models.html" onclick="pageTracker._trackPageview('/outgoing/docs.neo4j.org/chunked/stable/tutorial-comparing-models.html?referer=');">http://docs.neo4j.org/chunked/stable/tutorial-comparing-models.html</a></li>
<li><a href="http://blog.neo4j.org/2010/03/modeling-categories-in-graph-database.html" onclick="pageTracker._trackPageview('/outgoing/blog.neo4j.org/2010/03/modeling-categories-in-graph-database.html?referer=');">http://blog.neo4j.org/2010/03/modeling-categories-in-graph-database.html</a></li>
<li><a href="http://skillsmatter.com/podcast/nosql/graph-modelling" onclick="pageTracker._trackPageview('/outgoing/skillsmatter.com/podcast/nosql/graph-modelling?referer=');">http://skillsmatter.com/podcast/nosql/graph-modelling</a></li>
<li><a href="http://www.umiacs.umd.edu/%7Ejimmylin/publications/Lin_Schatz_MLG2010.pdf" onclick="pageTracker._trackPageview('/outgoing/www.umiacs.umd.edu/_7Ejimmylin/publications/Lin_Schatz_MLG2010.pdf?referer=');">http://www.umiacs.umd.edu/~jimmylin/publications/Lin_Schatz_MLG2010.pdf</a></li>
</ol>
</li>
<li>Demensionality Reduction:
<ol>
<li><a href="http://www.slideshare.net/mmalone/scaling-gis-data-in-nonrelational-data-stores" onclick="pageTracker._trackPageview('/outgoing/www.slideshare.net/mmalone/scaling-gis-data-in-nonrelational-data-stores?referer=');">http://www.slideshare.net/mmalone/scaling-gis-data-in-nonrelational-data-stores</a></li>
<li><a href="http://blog.notdot.net/2009/11/Damn-Cool-Algorithms-Spatial-indexing-with-Quadtrees-and-Hilbert-Curves" onclick="pageTracker._trackPageview('/outgoing/blog.notdot.net/2009/11/Damn-Cool-Algorithms-Spatial-indexing-with-Quadtrees-and-Hilbert-Curves?referer=');">http://blog.notdot.net/2009/11/Damn-Cool-Algorithms-Spatial-indexing-with-Quadtrees-and-Hilbert-Curves</a></li>
<li><a href="http://www.trisis.co.uk/blog/?p=1287" onclick="pageTracker._trackPageview('/outgoing/www.trisis.co.uk/blog/?p=1287&amp;referer=');">http://www.trisis.co.uk/blog/?p=1287</a></li>
</ol>
</li>
</ol>
<p>（全文完）</p>
<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="SQL的Where语句" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1889.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7270.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1889.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7270.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10437720.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">SQL的Where语句</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="【原创】SQL栏目树的代码" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F962.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7270.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F962.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7270.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">【原创】SQL栏目树的代码</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="图解SQL的Join" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3463.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7270.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3463.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7270.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/06/22/13778761.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">图解SQL的Join</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="几篇技术文章" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3311.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7270.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3311.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7270.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">几篇技术文章</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="MySQL性能优化的最佳20+条经验" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1846.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7270.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1846.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7270.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/09/16/31282265.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">MySQL性能优化的最佳20+条经验</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table><h3  class="related_post_title">相关文章</h3><ul class="related_post"><li>2009年12月01日 -- <a href="http://coolshell.cn/articles/1889.html" title="SQL的Where语句">SQL的Where语句</a></li><li>2012年02月21日 -- <a href="http://coolshell.cn/articles/6639.html" title="千万别惹程序员 ">千万别惹程序员 </a></li><li>2011年11月10日 -- <a href="http://coolshell.cn/articles/5826.html" title="千万别用MongoDB？真的吗？！">千万别用MongoDB？真的吗？！</a></li><li>2011年06月08日 -- <a href="http://coolshell.cn/articles/4795.html" title="开源中最好的Web开发的资源">开源中最好的Web开发的资源</a></li><li>2011年01月11日 -- <a href="http://coolshell.cn/articles/3463.html" title="图解SQL的Join">图解SQL的Join</a></li><li>2010年12月31日 -- <a href="http://coolshell.cn/articles/3433.html" title="6个有用的MySQL语句">6个有用的MySQL语句</a></li><li>2010年11月25日 -- <a href="http://coolshell.cn/articles/3311.html" title="几篇技术文章">几篇技术文章</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/7270.html/feed</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>用Unix的设计思想来应对多变的需求</title>
		<link>http://coolshell.cn/articles/7236.html</link>
		<comments>http://coolshell.cn/articles/7236.html#comments</comments>
		<pubDate>Thu, 03 May 2012 00:14:20 +0000</pubDate>
		<dc:creator>陈皓</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[操作系统]]></category>
		<category><![CDATA[程序设计]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[design pattern]]></category>
		<category><![CDATA[Unix]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=7236</guid>
		<description><![CDATA[之前，@风枫峰 在“这是谁的错？”中说过开发团队对需求来者不拒，而@weidagang 也在“需求变更和IoC”中说过用IoC来最大程度地解决需求变更。今天我也想从Unix设计思想的角度来说说什么是好的软件设计，什么样的设计可以把需求变更对开发的影响降低。（注意：这并不能解决用户或是PM的无理需求，面对无理需求，需要仔细分析需求，而用技术的手段无法搞定这个事，但是可以减轻需求变更带来的痛苦） 我曾经在《Unix传奇》的下篇中写过一些Unix的设计哲学和思想（这里重点推荐大家看一下《The Art of Unix Programming》，我推荐过多次了），以前也发过一篇《一些软件设计的原则》，不过，这些东西都太多了，记不住。其实，这么多年来，我的经验告诉我，无论是Unix设计，还是面向对象设计，还是别的什么如SOA，ECB，消息，事件，MVC，网络七层模型，数据库设计，等等，他们都在干三件事——解耦，解耦，还是解耦！所谓解耦，就是让软件的模块和模块间尽量少地依赖起来。 现实当中的例子 让我先举几个现实生活中的例子： 1、现实社会中，制造灯具的工厂完全不关心制造灯泡的工厂，制造灯泡的工厂完全不关心制造灯具的工厂，但是，灯泡和灯饰可以很完美地组合成用户所喜欢的样子（这和@weidagang 在“需求变更和IoC”说到的那个PC的例子相仿）。他们是怎么做到的？ 2、互联网上，做网站的人完全不用关心用户在用什么样的操作系统，什么样的客户端浏览器（当然事实上，浏览器的不标准让网站那边很头痛，这里只是举个例），反过来，上网的人也不关心做网站的人在用什么的技术开发网站。但是大家在完全不关心对方的情况下，可以很正常地协同工作在一起。为什么？ 这样的例子太多了。为什么可以做成这样呢？因为大家依赖的是一个接口，灯具和灯泡并不互相依赖，他们依赖的是一个接口，做网站的人和浏览网站的人依赖的还是接口——HTTP协议。这就是面向对象的核心思想——依赖于接口而不是实现，这就是解耦。当你看过这两个例子以后，我希望你以后设计的软件至少不能比我们现实社会中的这些方法要差。不然，你就是在让社会倒退了，呵呵。 你会说，这和Unix，和应对需求变化有什么关系？好让我们再来看一下Unix的设计。 Unix设计的例子 下面是几个Unix下的例子： 1、Unix下，所有的硬件都可以通过文件的方式存取。其统统在/dev下。于是，软件和硬件的耦合被解开了，操作系统只需要把硬件统统变成文件，而程序只需要使用三个东西，一个是fd，一个是read()，一个是write()，就可以来操作任意的硬件了，这就是抽象，简单到不行。 2、Unix下，所有的命令都可以用管道串起来（管道绝对是个伟大的发明），这样，所有的命令间的交互全部解耦到只依赖于STD_IN, STD_OUT设备上。最酷的是，用户可以使用管道任意地拼装那些命令，以完成各式各样的功能。管道这个设计思想可以映射为今天的Web Service，你可以任意地拼装各种Web Service。 看到这里，你会发现，这还是解耦，本质上来说，也是一种依赖倒置——OOD的精髓。但是，Unix还不仅仅是这些。我们再来看几个例子： 1、Unix下，软件都是绿色地安装。在iOS上更明显——各个程序间基本上互不干扰，这个程序产生的垃圾文件不会影响到另一个程序。你删掉一个程序不会让另一个程序不举，各是各的空间。你可以删除这些程序，只要把内核心留着，系统照样可以启动。 2、Unix下，你可以通过设置一些环境变量，让多种环境同时存在，比如：某个LAMP用的是Apache 2.0, Mysql 4.0, PHP 4.0，某个LAMP用的是Apache 2.2, Mysql 5.0，PHP5.3，你不但可以方便地在系统中切换这两个环境，你甚至还可以同时启动他们。 3、Unix下，你可以随意地替换你想要的程序。比如，你不喜欢bash，你可以替换成ksh/csh等，你不喜欢awk ，你可以替换成 gawk ，所有的东西都像零件一样，你不喜欢什么，你就可以替换什么。 这三个例子告诉了我们——当你把你的软件设计地耦合度非常地低时，你可以随意地组合，随意地安排你的系统。相当的灵活，灵活到Windows到今天都学不会。 应对需求变化 看到这里，你可能明白我想说的是什么了，你可能开始觉得怎么样的系统设计会更有效了。如果你还记得《Steve Y 对平台的长篇大论》，你就会知道我想说什么了。是的，我想说的就是，当你真正了解了Unix的设计思想后，你会觉得今天的很多东西都是对Unix设计思想的一种传承或是变种。这种东西就是： 1）解耦，解耦，解耦。尽量地让你的模块不要在实现上耦合，而是耦合某个规范，某个标准。 2）KISS，KISS，KISS。要做到高度解耦，你的模块就一定要很简单，当然不是说简单到只有几行代码，而是简单到只干一件事，并把这件事干到极致。然后通过某个标准拼装起来。 3）拼装，拼装，拼装。我想不起来是谁说的了，这句话是这样的，当我想用一个模块的时候，我直接调用就好了，没有必要像C或Java一样，还要编译。是的，拼装需要一个框架，需要一种标准协议，然后让所有的系统都耦合在这种规范上，各自独立运行，就像一个机器上的各个部件一样，当我觉得这个部件不爽，换了就是了。（例如，当我们在尝试不同的算法的时候） 想想建材和家俱市场，无论用户过来想装修什么，我都可以满足用户的不同需求，只要你是和家装相关，我基本上都能满足你，不是吗？无论你怎么变，只要不变态，我基本上都可以满足你。这就是解耦，拼装带来的好处。 你可能会说我说得太简单了，另一方面，你可能觉得有一些系统这样做没必要，我承认，不过，你可以有选择的或多或少地试试。（其实，我相信你已经在不自觉得或多或少地使用这种方式开发软件了） （全文完） 相关文章2012年03月26日 -- 需求变化与IoC2011年04月25日 -- 一些软件设计的原则2012年05月17日 -- rsync 的核心算法2012年03月13日 -- 多版本并发控制(MVCC)在分布式系统中的应用2012年03月09日 [...]<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="JDK里的设计模式" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3320.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7236.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3320.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7236.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">JDK里的设计模式</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Alice梦游UNIX仙境" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1439.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7236.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1439.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7236.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Alice梦游UNIX仙境</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="101个设计模式" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F21.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7236.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F21.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7236.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10438085.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">101个设计模式</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="“另类” 设计模式" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F4844.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7236.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F4844.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7236.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">“另类” 设计模式</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Unix Pipes 管道原稿" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1351.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7236.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1351.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7236.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10437748.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Unix Pipes 管道原稿</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table>]]></description>
			<content:encoded><![CDATA[<p>之前，@<a title="风枫峰" href="http://weibo.com/hfcc?source=webim" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/hfcc?source=webim&amp;referer=');">风枫峰</a> 在“<a title="这到底是谁之错？" href="http://coolshell.cn/articles/7126.html" target="_blank">这是谁的错？</a>”中说过开发团队对需求来者不拒，而@<a title="weidagang" href="http://weibo.com/weidagang" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/weidagang?referer=');">weidagang</a> 也在“<a title="需求变化与IoC" href="http://coolshell.cn/articles/6950.html" target="_blank">需求变更和IoC</a>”中说过用IoC来最大程度地解决需求变更。今天我也想从Unix设计思想的角度来说说什么是好的软件设计，什么样的设计可以把需求变更对开发的影响降低。（<strong>注意</strong>：这并不能解决用户或是PM的无理需求，面对无理需求，需要仔细分析需求，而用技术的手段无法搞定这个事，但是可以减轻需求变更带来的痛苦） 我曾经在<a href="http://coolshell.cn/articles/2324.html" target="_blank">《Unix传奇》的下篇</a>中写过一些Unix的设计哲学和思想（这里重点推荐大家看一下《<em><a href="http://product.china-pub.com/197413" target="_blank" onclick="pageTracker._trackPageview('/outgoing/product.china-pub.com/197413?referer=');">The Art of Unix Programming</a></em>》，我推荐过多次了），以前也发过一篇《<a title="一些软件设计的原则" href="http://coolshell.cn/articles/4535.html" target="_blank">一些软件设计的原则</a>》，不过，这些东西都太多了，记不住。其实，这么多年来，我的经验告诉我，<strong>无论是Unix设计，还是面向对象设计，还是别的什么如SOA，ECB，消息，事件，MVC，网络七层模型，数据库设计，等等，他们都在干三件事——<span style="color: #cc0000;">解耦，解耦，还是解耦</span>！</strong>所谓解耦，就是让软件的模块和模块间尽量少地依赖起来。</p>
<p style="text-align: center;"><img class="aligncenter" title="Unix" src="http://coolshell.cn/wp-content/uploads/2012/05/Bannière-Unix-linux.jpg" alt="" width="448" height="173" /></p>
<h4>现实当中的例子</h4>
<p>让我先举几个现实生活中的例子：</p>
<p style="padding-left: 30px;">1、现实社会中，制造灯具的工厂完全不关心制造灯泡的工厂，制造灯泡的工厂完全不关心制造灯具的工厂，但是，灯泡和灯饰可以很完美地组合成用户所喜欢的样子（这和@<a title="weidagang" href="http://weibo.com/weidagang" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/weidagang?referer=');">weidagang</a> 在“<a title="需求变化与IoC" href="http://coolshell.cn/articles/6950.html" target="_blank">需求变更和IoC</a>”说到的那个PC的例子相仿）。他们是怎么做到的？</p>
<p style="padding-left: 30px;">2、互联网上，做网站的人完全不用关心用户在用什么样的操作系统，什么样的客户端浏览器（当然事实上，浏览器的不标准让网站那边很头痛，这里只是举个例），反过来，上网的人也不关心做网站的人在用什么的技术开发网站。但是大家在完全不关心对方的情况下，可以很正常地协同工作在一起。为什么？</p>
<p><span id="more-7236"></span> 这样的例子太多了。为什么可以做成这样呢？因为大家依赖的是一个接口，灯具和灯泡并不互相依赖，他们依赖的是一个接口，做网站的人和浏览网站的人依赖的还是接口——HTTP协议。这就是面向对象的核心思想——依赖于接口而不是实现，这就是解耦。<strong>当你看过这两个例子以后，我希望你以后设计的软件至少不能比我们现实社会中的这些方法要差</strong>。不然，你就是在让社会倒退了，呵呵。 你会说，这和Unix，和应对需求变化有什么关系？好让我们再来看一下Unix的设计。</p>
<h4>Unix设计的例子</h4>
<p>下面是几个Unix下的例子：</p>
<p style="padding-left: 30px;">1、Unix下，所有的硬件都可以通过文件的方式存取。其统统在/dev下。于是，软件和硬件的耦合被解开了，操作系统只需要把硬件统统变成文件，而程序只需要使用三个东西，一个是fd，一个是read()，一个是write()，就可以来操作任意的硬件了，这就是抽象，简单到不行。</p>
<p style="padding-left: 30px;">2、Unix下，所有的命令都可以用管道串起来（管道绝对是个伟大的发明），这样，所有的命令间的交互全部解耦到只依赖于STD_IN, STD_OUT设备上。最酷的是，用户可以使用管道任意地拼装那些命令，以完成各式各样的功能。管道这个设计思想可以映射为今天的Web Service，你可以任意地拼装各种Web Service。</p>
<p>看到这里，你会发现，这还是解耦，本质上来说，也是一种依赖倒置——OOD的精髓。但是，Unix还不仅仅是这些。我们再来看几个例子：</p>
<p style="padding-left: 30px;">1、Unix下，软件都是绿色地安装。在iOS上更明显——各个程序间基本上互不干扰，这个程序产生的垃圾文件不会影响到另一个程序。你删掉一个程序不会让另一个程序不举，各是各的空间。你可以删除这些程序，只要把内核心留着，系统照样可以启动。</p>
<p style="padding-left: 30px;">2、Unix下，你可以通过设置一些环境变量，让多种环境同时存在，比如：某个LAMP用的是Apache 2.0, Mysql 4.0, PHP 4.0，某个LAMP用的是Apache 2.2, Mysql 5.0，PHP5.3，你不但可以方便地在系统中切换这两个环境，你甚至还可以同时启动他们。</p>
<p style="padding-left: 30px;">3、Unix下，你可以随意地替换你想要的程序。比如，你不喜欢bash，你可以替换成ksh/csh等，你不喜欢awk ，你可以替换成 gawk ，所有的东西都像零件一样，你不喜欢什么，你就可以替换什么。</p>
<p>这三个例子告诉了我们——<strong>当你把你的软件设计地耦合度非常地低时，你可以随意地组合，随意地安排你的系统</strong>。相当的灵活，灵活到Windows到今天都学不会。</p>
<h4>应对需求变化</h4>
<p>看到这里，你可能明白我想说的是什么了，你可能开始觉得怎么样的系统设计会更有效了。如果你还记得《<a title="SteveY对Amazon和Google平台的长篇大论" href="http://coolshell.cn/articles/5701.html" target="_blank">Steve Y 对平台的长篇大论</a>》，你就会知道我想说什么了。是的，我想说的就是，<strong>当你真正了解了Unix的设计思想后，你会觉得今天的很多东西都是对Unix设计思想的一种传承或是变种</strong>。这种东西就是：</p>
<p style="padding-left: 30px;">1）<strong>解耦，解耦，解耦</strong>。尽量地让你的模块不要在实现上耦合，而是耦合某个规范，某个标准。</p>
<p style="padding-left: 30px;">2）<strong>KISS，KISS，KISS</strong>。要做到高度解耦，你的模块就一定要很简单，当然不是说简单到只有几行代码，而是简单到只干一件事，并把这件事干到极致。然后通过某个标准拼装起来。</p>
<p style="padding-left: 30px;">3）<strong>拼装，拼装，拼装。</strong>我想不起来是谁说的了，这句话是这样的，当我想用一个模块的时候，我直接调用就好了，没有必要像C或Java一样，还要编译。是的，拼装需要一个框架，需要一种标准协议，然后让所有的系统都耦合在这种规范上，各自独立运行，就像一个机器上的各个部件一样，当我觉得这个部件不爽，换了就是了。（例如，当我们在尝试不同的算法的时候）</p>
<p>想想建材和家俱市场，无论用户过来想装修什么，我都可以满足用户的不同需求，只要你是和家装相关，我基本上都能满足你，不是吗？无论你怎么变，只要不变态，我基本上都可以满足你。这就是解耦，拼装带来的好处。 你可能会说我说得太简单了，另一方面，你可能觉得有一些系统这样做没必要，我承认，不过，你可以有选择的或多或少地试试。（其实，我相信你已经在不自觉得或多或少地使用这种方式开发软件了） （全文完）</p>
<div></div>
<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="JDK里的设计模式" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3320.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7236.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3320.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7236.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">JDK里的设计模式</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Alice梦游UNIX仙境" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1439.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7236.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1439.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7236.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Alice梦游UNIX仙境</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="101个设计模式" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F21.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7236.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F21.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7236.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10438085.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">101个设计模式</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="“另类” 设计模式" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F4844.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7236.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F4844.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7236.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">“另类” 设计模式</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Unix Pipes 管道原稿" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1351.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7236.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1351.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7236.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10437748.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Unix Pipes 管道原稿</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table><h3  class="related_post_title">相关文章</h3><ul class="related_post"><li>2012年03月26日 -- <a href="http://coolshell.cn/articles/6950.html" title="需求变化与IoC">需求变化与IoC</a></li><li>2011年04月25日 -- <a href="http://coolshell.cn/articles/4535.html" title="一些软件设计的原则">一些软件设计的原则</a></li><li>2012年05月17日 -- <a href="http://coolshell.cn/articles/7425.html" title="rsync 的核心算法">rsync 的核心算法</a></li><li>2012年03月13日 -- <a href="http://coolshell.cn/articles/6790.html" title="多版本并发控制(MVCC)在分布式系统中的应用">多版本并发控制(MVCC)在分布式系统中的应用</a></li><li>2012年03月09日 -- <a href="http://coolshell.cn/articles/6775.html" title="Bret Victor &#8211; Inventing on Principle">Bret Victor &#8211; Inventing on Principle</a></li><li>2012年01月16日 -- <a href="http://coolshell.cn/articles/6470.html" title="由12306.cn谈谈网站性能技术 ">由12306.cn谈谈网站性能技术 </a></li><li>2011年11月24日 -- <a href="http://coolshell.cn/articles/5537.html" title="一些文章资源和趣闻">一些文章资源和趣闻</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/7236.html/feed</wfw:commentRss>
		<slash:comments>59</slash:comments>
		</item>
		<item>
		<title>做个环保主义的程序员</title>
		<link>http://coolshell.cn/articles/7186.html</link>
		<comments>http://coolshell.cn/articles/7186.html#comments</comments>
		<pubDate>Fri, 27 Apr 2012 00:26:44 +0000</pubDate>
		<dc:creator>陈皓</dc:creator>
				<category><![CDATA[杂项资源]]></category>
		<category><![CDATA[Green]]></category>
		<category><![CDATA[IE]]></category>
		<category><![CDATA[Programmer]]></category>
		<category><![CDATA[QQ]]></category>
		<category><![CDATA[程序员]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=7186</guid>
		<description><![CDATA[十多年前刚走入社会工作的时候，那时的中国软件开发根本没有什么版本管理，也没有什么编程规范，软件开发相比起今天来说非常地混乱，那时仅凭自己的一些学习总结了一些C语言编程中的好的小笔记，后来，这些笔记写成了一篇叫《编程修养》的文章。今天，又有些感触，想把这个话题扩大一下，从“个人修养”扩大到“环境保护”，所谓，穷则独善其身，富则达济天下，今天的技术人员比十多年前在技术和环境上都富有了许多，所以，也应该或多或少地担负起“达济天下”的责任了。 环境保护说白了就是保护一个良好的环境，为好的环境添砖加瓦，与破坏环境的人和事做斗争。其实，从技术人员来说，我们可以做一些力所能及的事。因为我们身边的技术环境还有很大的改善的空间，而一些来之不易的东西还需要我们去小心维护。另外，对于我们自己来说，少吃一些垃圾食品，健康生活，对自己也有益。 环保主义软件开发 先说说软件开发中的环保。比如： 环保需求。当我们分析需求的时候，如果我们能做到不要像“这是到底是谁的错”一文中那样的来者不拒，如果我们在面对需求能多问这样几个问题：为什么 要有这样的需求？这个功能主要能解决什么 样的问题？为什么不是另外那一种？可不可以简化一下？其实，我们并不需要创新，只需要真正地问好这几个问题，我们就可以少看着一些弯路，少一些苦逼的加班，少一些内耗，少一些埋怨，也就可以为这个社会节省下一些资源，从而环保。 环保开发。当我们做设计写代码的时候，如果我们多花一些时间去思考一下，我们就可以少一些代码（参看“多一些时间少一些代码”）。如果我们在一开始多思考一下，不要急着马上去用迭代的方式认识世界，多思考一下怎么把复杂的东西解藕，把复杂的东西简化，怎么做出一个优雅的设计，怎么让我们的程序少一些tricky的东西，怎么让我们的程序变得更简洁，更清楚，更直，在一开始思考一下未来需求可能的变化，未来软件需要怎么测试，未来的系统需要怎么的运维，那么，我们可以少一些返工，少一些重构，少欠一些债，少一些低级错误，少承担一些系统上线后的压力，那么，我们同样可以为这个社会节约一些资源。说得再直白一点，你用更少的代码产生出更高的效益，少耗一些CPU，就能省一些电，间接地保护了环境。（参看 Why C++？） 环保文化。当我们在做软件开发的时候，如果你能影响并帮助你身边的同事，让他们写出更有修养更有效率质量更高的代码来，并发动团队树立工程师的文化，用团队去影响你的老板，你的公司，让他们能再多一点地重视技术，重视技术人员，那么你必然也会成为一个受益者。 环保管理。当你做为一个管理者，做为一个方法推动者，如果你能更多地注重软件开发中真正创造生产力的程序员，为他们分忧，为他们铺路，为他们创造条件，那么，他们就会更多的回馈于你，就会少了一些不信任，就会少了一些被动，就会多一些主动，就会多一分责任，不但可以激发团队热情，同时可以有更大的生产力。同样是一种环保。 当然，这样的东西还有很多，你也可能会觉得太过理想主义了，我们不可能马上改变之，但是我们可以试一试。 技术环保主义 其实，我们身边有很多可以做的技术环保工作。比如说，在Linux下少用root用户，SQL的时候，delete前先select，这样，你就不会做出一些让你后悔的事（参看程序员那些悲催的事），不会让你重头来过，从而至少不会浪费电能。写代码的时候要很小心管理好内存，以及各种资源，和线程并发，组织好的你的代码中的业务逻辑，做好单元测试，自动化回归测试，等，这样你就可以少一点遇到BUG，在遇到BUG时少一些时间去做调查。操作电脑的时候少下一些破解软件，少访问一些乱七八遭的网站，这样，你就会少中一些病毒，少一些损失，少一些重做系统，一样可以节省电能，最重要的是可以节省你的很多时间，让你可以去做一些更有价值 的事情。 当然，除此之外，我们更应该做为一个大气的，高瞻的环保主义者，比如下面的事情： 拒绝IE6。如果你坚决不用IE6，并影响你身边的人，让他们升级IE6，尝试Chrome 或 Firefox，多告诉一下自己身边的朋友，怎么设计口令，怎么在互联网上保护自己的隐私和安全，怎么防木马，这样就能少一些问题，少装两次系统，就能省一些电，也就能多一些时间去做一些更有意义的事。也是在为整个世界整个人类做贡献。（看看某些软件产商，占据着用户桌面的江山，还整天弹窗弹窗的，说这不安全，那不安全的。你还是做安全的，你居然能容忍IE6装在用户的机器上，你还做个屁的安全！）2011年3月份，我国的IE6用户的百分比是34%， 那时中国网民4.5亿，平均每三个人中有一个，2012年3月份，中国的比例还有24%左右，不过中国的网民数达到了5.13亿，也就是说，平均5个人里有一个，但是中国依然是全世界的IE6占有量最大的，参看下图（来自：http://www.ie6countdown.com）面对下面的图片，你作何感想呢？ “Friend Don&#8217;t Let Friend Use IE6” 拒绝破解软件。为什么要拒绝这些东西，因为你恐怕不知道这个软件的危害，包括一些汉化版的开源软件。这些软件中都会带 一些木马，比如：你下个putty的中文版，结果里有木马，人家就把你网站的口令盗了。关于网游，你可能不知道，连接网游私服的电脑基本上全是肉鸡，而 且，有很多的站点骗你下载软件破解程序，其实你下载到了一个木马。等等。这些生活都非常地不健康。 拒绝抄袭和山寨。如果你鄙视那些赤祼祼地抄袭者，不使用他们的产品，有的人会说你就是想标榜自己的高尚，ZB，假高尚，大家会说你没有必要。其实并不是，你这样做，其实是为了“环保”，为了“保护一个健康的IT环境”，虽然你没有创新，但是你的行为却是在鼓励创新的环境，这样，如果当整个大环境都是在创新文化影响之下，才会更健康，技术人员也才会被尊重，而我们自己最终会受益。虽然只是抑制抄袭和山寨，但是我们间接地为社会做了贡献。（看看那N多的抄袭团队，加入他们实在是耗费这个社会的资源） （那个整天复制这个复制这个复制那个的公司，看看你自己做的那些产品线？乱糟糟的。你自己看看，你有个人空间，还有群空间，还有校友录，然后你还要做个facebook式的“朋友”，还要搞个微博，然后还要搞个微信，大哥啊，你把这些相似度很大的东西放在了N多的服务器上，你不觉得浪费吗？你真是山寨之王啊，自己都一直在复制自己的产品。还有人说你们的产品经理一流，真是脑残啊。对于你们的复制精神，我只能拜了！） 拒绝百度搜索。如果你学得百度还是可以的话，你不妨看看我的微博（这个，这个（抓图），还有这个）(以前，百度搜索出来的很多的开源软件（PuTTY、WinSCP）的第一个链接全是带木马的，百度就是一个网上的病毒 )，你会发现百度不单单是广告的问题，很多东西根本搜不出来，包括他自己的内容。用百度就是浪费时间，浪费计算资源。如果你告诉你身边的朋友不要用百度搜索，而是用Google，并能耐心地教会他们翻墙，这样，我们就可以让那些“穷则穷凶极恶，富则为富不仁”的企业少一些自以为是，最重要的是可以让他们少制造一些垃圾信息和垃圾产品，世界少一些垃圾，自然也就环保了。 拒绝过重的商业氛围。很多社区的商业氛围实在是太浓了，全都是广告。整个社区根本都不是为技术人员来做的，而为了那些软件产商，为了那些公司。他们只知道为那些大公司写软文，做广告，开大会。他们只想着挣钱。网页上全是花花绿绿的广告，打开他们的网页，就会多耗许多电，浏览他们网站上的文章，到他们的大会上听他们的软件广告分享，就会让自己的生命和时间浪费，自己消耗了体力不说，却还没得到什么营养，相当的不环保。 拒绝浮燥。比如：浮燥地创业者们，被风投们一轮一轮地压榨。为了让风投满意，牺牲自己的初衷，去找水军刷排名，去发垃圾邮件，去烧钱买吆喝，制造虚假的繁荣，等等。另外，少去追那些新的技术，少一些浮夸，不要开口闭口的就是海量数据，高性能，要当个架构师，经理，要拿多少多少的工资，与其这样，还不如多静下心来研究一下那些十来年的技术，思考一下自己身边的问题，一步一步走踏实，少摔几个跟头，这样，你也就能多一些能力，多一些自信，也就能多做一些事，多解决一些问题，你的职业生源走好了，也就很环保了。 还有很多，我相信大家明白我想说什么。其实，我想说的是，这不单单是一种“个人修养”，这也是一种对社会贡献的方式，更是一种“低碳环保”的生活方式。 让我们一起来做有修养的环保主义的程序员吧，少吃一些垃圾食品，多一些绿色的健康生活！ —————— 更新 2012年4月27 —————— 我看到很多网友并不同意我的观点，并指责我的偏激和极端。挺好的，我知道，我说到了你们最敏感的地方，我很高兴。 你可以对现实妥协，你可以继续钟爱你的垃圾食品，你可以继续使用百度搜索，你可以继续生活在墙内，我虽然替你感到惋惜，但是我不会勉强你，因为我能理解你可以不环保，本来也是，这些事情，你能做到固然好，你做不到，也是你的选择。每个人的生活每个人自己去选择，想健康地生活，或是不健康地生活，都是你自己的权利。 （全文完） 相关文章2012年04月19日 -- 这到底是谁之错？2012年04月17日 -- 挑战无处不在2012年04月11日 -- 我们需要专职的QA吗？2012年03月09日 -- Bret Victor [...]<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="惹恼程序员的十件事" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F340.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7186.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F340.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7186.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/02/12/2675402.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">惹恼程序员的十件事</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="漫画：程序员的一生" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1103.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7186.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1103.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7186.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10437646.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">漫画：程序员的一生</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="别的程序员是怎么读你的简历的" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1695.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7186.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1695.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7186.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/01/07/1885248.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">别的程序员是怎么读你的简历的</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="一个女程序员的故事" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6312.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7186.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6312.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7186.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">一个女程序员的故事</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="程序员因为女孩而美丽！" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6346.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7186.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6346.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7186.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">程序员因为女孩而美丽！</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table>]]></description>
			<content:encoded><![CDATA[<p><strong></strong>十多年前刚走入社会工作的时候，那时的中国软件开发根本没有什么版本管理，也没有什么编程规范，软件开发相比起今天来说非常地混乱，那时仅凭自己的一些学习总结了一些C语言编程中的好的小笔记，后来，这些笔记写成了一篇叫《<a href="http://blog.csdn.net/haoel/article/details/2872" target="_blank" onclick="pageTracker._trackPageview('/outgoing/blog.csdn.net/haoel/article/details/2872?referer=');">编程修养</a>》的文章。今天，又有些感触，想把这个话题扩大一下，从“个人修养”扩大到“环境保护”，所谓，穷则独善其身，富则达济天下，今天的技术人员比十多年前在技术和环境上都富有了许多，所以，也应该或多或少地担负起“达济天下”的责任了。</p>
<p>环境保护说白了就是保护一个良好的环境，为好的环境添砖加瓦，与破坏环境的人和事做斗争。其实，从技术人员来说，我们可以做一些力所能及的事。因为我们身边的技术环境还有很大的改善的空间，而一些来之不易的东西还需要我们去小心维护。另外，对于我们自己来说，少吃一些垃圾食品，健康生活，对自己也有益。</p>
<h4>环保主义软件开发</h4>
<p><strong><img class="alignright" title="Green Computing" src="http://coolshell.cn/wp-content/uploads/2012/04/Green-Computing.jpg" alt="" width="285" height="233" /></strong>先说说软件开发中的环保。比如：</p>
<ul>
<li><strong>环保需求</strong>。当我们分析需求的时候，如果我们能做到不要像“<a title="这到底是谁之错？" href="http://coolshell.cn/articles/7126.html" target="_blank">这是到底是谁的错</a>”一文中那样的来者不拒，如果我们在面对需求能多问这样几个问题：为什么 要有这样的需求？这个功能主要能解决什么 样的问题？为什么不是另外那一种？可不可以简化一下？其实，我们并不需要创新，只需要真正地问好这几个问题，我们就可以少看着一些弯路，少一些苦逼的加班，少一些内耗，少一些埋怨，也就可以为这个社会节省下一些资源，从而环保。</li>
</ul>
<div></div>
<ul>
<li><strong>环保开发</strong>。当我们做设计写代码的时候，如果我们多花一些时间去思考一下，我们就可以少一些代码（参看“<a title="多些时间能少写些代码" href="http://coolshell.cn/articles/5686.html" target="_blank">多一些时间少一些代码</a>”）。如果我们在一开始多思考一下，不要急着马上去用迭代的方式认识世界，多思考一下怎么把复杂的东西解藕，把复杂的东西简化，怎么做出一个优雅的设计，怎么让我们的程序少一些tricky的东西，怎么让我们的程序变得更简洁，更清楚，更直，在一开始思考一下未来需求可能的变化，未来软件需要怎么测试，未来的系统需要怎么的运维，那么，我们可以少一些返工，少一些重构，少欠一些债，少一些低级错误，少承担一些系统上线后的压力，那么，我们同样可以为这个社会节约一些资源。说得再直白一点，你用更少的代码产生出更高的效益，少耗一些CPU，就能省一些电，间接地保护了环境。（参看<a title="Why C++ ? 王者归来" href="http://coolshell.cn/articles/6548.html" target="_blank"> Why C++？</a>）</li>
</ul>
<div><span id="more-7186"></span></div>
<ul>
<li><strong>环保文化</strong>。当我们在做软件开发的时候，如果你能影响并帮助你身边的同事，让他们写出更有修养更有效率质量更高的代码来，并发动团队树立工程师的文化，用团队去影响你的老板，你的公司，让他们能再多一点地重视技术，重视技术人员，那么你必然也会成为一个受益者。</li>
</ul>
<div></div>
<ul>
<li><strong>环保管理</strong>。当你做为一个管理者，做为一个方法推动者，如果你能更多地注重软件开发中真正创造生产力的程序员，为他们分忧，为他们铺路，为他们创造条件，那么，他们就会更多的回馈于你，就会少了一些不信任，就会少了一些被动，就会多一些主动，就会多一分责任，不但可以激发团队热情，同时可以有更大的生产力。同样是一种环保。</li>
</ul>
<p>当然，这样的东西还有很多，你也可能会觉得太过理想主义了，我们不可能马上改变之，但是我们可以试一试。</p>
<h4>技术环保主义</h4>
<p>其实，我们身边有很多可以做的技术环保工作。比如说，在Linux下少用root用户，SQL的时候，delete前先select，这样，你就不会做出一些让你后悔的事（参看<a title="程序员那些悲催的事儿" href="http://coolshell.cn/articles/3980.html" target="_blank">程序员那些悲催的事</a>），不会让你重头来过，从而至少不会浪费电能。写代码的时候要很小心管理好内存，以及各种资源，和线程并发，组织好的你的代码中的业务逻辑，做好单元测试，自动化回归测试，等，这样你就可以少一点遇到BUG，在遇到BUG时少一些时间去做调查。操作电脑的时候少下一些破解软件，少访问一些乱七八遭的网站，这样，你就会少中一些病毒，少一些损失，少一些重做系统，一样可以节省电能，最重要的是可以节省你的很多时间，让你可以去做一些更有价值 的事情。</p>
<p>当然，除此之外，我们更应该做为一个大气的，高瞻的环保主义者，比如下面的事情：</p>
<ul>
<li><strong>拒绝IE6</strong>。如果你坚决不用IE6，并影响你身边的人，让他们升级IE6，尝试Chrome 或 Firefox，多告诉一下自己身边的朋友，怎么设计口令，怎么在互联网上保护自己的隐私和安全，怎么防木马，这样就能少一些问题，少装两次系统，就能省一些电，也就能多一些时间去做一些更有意义的事。也是在为整个世界整个人类做贡献。（<strong>看看某些软件产商，占据着用户桌面的江山，还整天弹窗弹窗的，说这不安全，那不安全的。你还是做安全的，你居然能容忍IE6装在用户的机器上，你还做个屁的安全！</strong>）2011年3月份，<a title="中国仍是IE6的重灾区" href="http://coolshell.cn/articles/3921.html" target="_blank">我国的IE6用户的百分比是34%</a>， 那时中国网民4.5亿，平均每三个人中有一个，2012年3月份，中国的比例还有24%左右，不过<a href="http://it.sohu.com/20120116/n332237326.shtml" target="_blank" onclick="pageTracker._trackPageview('/outgoing/it.sohu.com/20120116/n332237326.shtml?referer=');">中国的网民数达到了5.13亿</a>，也就是说，平均5个人里有一个，但是中国依然是全世界的IE6占有量最大的，参看下图（来自：<a href="http://www.ie6countdown.com/" onclick="pageTracker._trackPageview('/outgoing/www.ie6countdown.com/?referer=');">http://www.ie6countdown.com</a>）面对下面的图片，你作何感想呢？</li>
</ul>
<p style="text-align: center;"><em>“<strong><span style="color: #cc0000;">Friend Don&#8217;t Let Friend Use IE6</span></strong>”</em></p>
<div><a href="http://www.ie6countdown.com" onclick="pageTracker._trackPageview('/outgoing/www.ie6countdown.com?referer=');"><img class="aligncenter size-full wp-image-7214" title="The Internet Explorer 6 Countdown" src="http://coolshell.cn/wp-content/uploads/2012/04/iecountdown2012.jpg" alt="" width="450" height="296" /></a></div>
<div></div>
<ul>
<li><strong>拒绝破解软件</strong>。为什么要拒绝这些东西，因为你恐怕不知道这个软件的危害，包括一些汉化版的开源软件。这些软件中都会带 一些木马，比如：你下个putty的中文版，结果里有木马，人家就把你网站的口令盗了。关于网游，你可能不知道，连接网游私服的电脑基本上全是肉鸡，而 且，有很多的站点骗你下载软件破解程序，其实你下载到了一个木马。等等。这些生活都非常地不健康。</li>
</ul>
<ul>
<li><strong>拒绝抄袭和山寨</strong>。如果你鄙视那些赤祼祼地抄袭者，不使用他们的产品，有的人会说你就是想标榜自己的高尚，ZB，假高尚，大家会说你没有必要。其实并不是，你这样做，其实是为了“环保”，为了“保护一个健康的IT环境”，虽然你没有创新，但是你的行为却是在鼓励创新的环境，这样，如果当整个大环境都是在创新文化影响之下，才会更健康，技术人员也才会被尊重，而我们自己最终会受益。虽然只是抑制抄袭和山寨，但是我们间接地为社会做了贡献。（看看那N多的抄袭团队，加入他们实在是耗费这个社会的资源） （那个整天复制这个复制这个复制那个的公司，看看你自己做的那些产品线？乱糟糟的。<strong>你自己看看，你有个人空间，还有群空间，还有校友录，然后你还要做个facebook式的“朋友”，还要搞个微博，然后还要搞个微信，大哥啊，你把这些相似度很大的东西放在了N多的服务器上，你不觉得浪费吗？你真是山寨之王啊，自己都一直在复制自己的产品</strong>。还有人说你们的产品经理一流，真是脑残啊。对于你们的复制精神，我只能拜了！）</li>
</ul>
<ul>
<li><strong>拒绝百度搜索</strong>。如果你学得百度还是可以的话，你不妨看看我的微博（<a href="http://weibo.com/1401880315/ybN502xZ9" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/1401880315/ybN502xZ9?referer=');">这个</a>，<a href="http://weibo.com/1401880315/ye6wNFTUW" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/1401880315/ye6wNFTUW?referer=');">这个</a>（<a href="http://weibo.com/1401880315/ye6E0a4zN" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/1401880315/ye6E0a4zN?referer=');">抓图</a>），还有<a href="http://weibo.com/1401880315/yfC4yzonW" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/1401880315/yfC4yzonW?referer=');">这个</a>）(以前，百度搜索出来的很多的开源软件（PuTTY、WinSCP）的第一个链接全是带木马的，百度就是一个网上的病毒 )，你会发现百度不单单是广告的问题，很多东西根本搜不出来，包括他自己的内容。<strong>用百度就是浪费时间，浪费计算资源</strong>。如果你告诉你身边的朋友不要用百度搜索，而是用Google，并能耐心地教会他们翻墙，这样，我们就可以让那些“穷则穷凶极恶，富则为富不仁”的企业少一些自以为是，最重要的是可以让他们少制造一些垃圾信息和垃圾产品，世界少一些垃圾，自然也就环保了。</li>
</ul>
<ul>
<li><strong>拒绝过重的商业氛围</strong>。很多社区的商业氛围实在是太浓了，全都是广告。整个社区根本都不是为技术人员来做的，而为了那些软件产商，为了那些公司。他们只知道为那些大公司写软文，做广告，开大会。他们只想着挣钱。网页上全是花花绿绿的广告，打开他们的网页，就会多耗许多电，浏览他们网站上的文章，到他们的大会上听他们的软件广告分享，就会让自己的生命和时间浪费，自己消耗了体力不说，却还没得到什么营养，相当的不环保。</li>
</ul>
<ul>
<li><strong>拒绝浮燥</strong>。比如：浮燥地创业者们，被风投们一轮一轮地压榨。为了让风投满意，牺牲自己的初衷，去找水军刷排名，去发垃圾邮件，去烧钱买吆喝，制造虚假的繁荣，等等。另外，少去追那些新的技术，少一些浮夸，不要开口闭口的就是海量数据，高性能，要当个架构师，经理，要拿多少多少的工资，与其这样，还不如多静下心来研究一下那些十来年的技术，思考一下自己身边的问题，一步一步走踏实，少摔几个跟头，这样，你也就能多一些能力，多一些自信，也就能多做一些事，多解决一些问题，你的职业生源走好了，也就很环保了。</li>
</ul>
<p>还有很多，我相信大家明白我想说什么。<strong></strong>其实，我想说的是，<strong>这不单单是一种“个人修养”，这也是一种对社会贡献的方式，更是一种“低碳环保”的生活方式</strong>。</p>
<p><span style="color: #cc0000;"><strong>让我们一起来做有修养的环保主义的程序员吧，少吃一些垃圾食品，多一些绿色的健康生活！</strong></span></p>
<p><em><strong>—————— 更新 2012年4月27 ——————</strong></em></p>
<p>我看到很多网友并不同意我的观点，并指责我的偏激和极端。挺好的，我知道，我说到了你们最敏感的地方，我很高兴。</p>
<p><strong>你可以对现实妥协，你可以继续钟爱你的垃圾食品，你可以继续使用百度搜索，你可以继续生活在墙内，我虽然替你感到惋惜，但是我不会勉强你，因为我能理解你可以不环保，本来也是，这些事情，你能做到固然好，你做不到，也是你的选择。每个人的生活每个人自己去选择，想健康地生活，或是不健康地生活，都是你自己的权利</strong>。</p>
<p>（全文完）</p>
<div><strong><br />
</strong></div>
<div><strong><br />
</strong></div>
<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="惹恼程序员的十件事" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F340.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7186.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F340.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7186.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/02/12/2675402.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">惹恼程序员的十件事</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="漫画：程序员的一生" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1103.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7186.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1103.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7186.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10437646.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">漫画：程序员的一生</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="别的程序员是怎么读你的简历的" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1695.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7186.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1695.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7186.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/01/07/1885248.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">别的程序员是怎么读你的简历的</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="一个女程序员的故事" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6312.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7186.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6312.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7186.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">一个女程序员的故事</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="程序员因为女孩而美丽！" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6346.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7186.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6346.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7186.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">程序员因为女孩而美丽！</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table><h3  class="related_post_title">相关文章</h3><ul class="related_post"><li>2012年04月19日 -- <a href="http://coolshell.cn/articles/7126.html" title="这到底是谁之错？">这到底是谁之错？</a></li><li>2012年04月17日 -- <a href="http://coolshell.cn/articles/7048.html" title="挑战无处不在">挑战无处不在</a></li><li>2012年04月11日 -- <a href="http://coolshell.cn/articles/6994.html" title="我们需要专职的QA吗？">我们需要专职的QA吗？</a></li><li>2012年03月09日 -- <a href="http://coolshell.cn/articles/6775.html" title="Bret Victor &#8211; Inventing on Principle">Bret Victor &#8211; Inventing on Principle</a></li><li>2012年02月21日 -- <a href="http://coolshell.cn/articles/6639.html" title="千万别惹程序员 ">千万别惹程序员 </a></li><li>2012年01月30日 -- <a href="http://coolshell.cn/articles/6526.html" title="软件开发的“三重门”">软件开发的“三重门”</a></li><li>2012年01月04日 -- <a href="http://coolshell.cn/articles/6346.html" title="程序员因为女孩而美丽！">程序员因为女孩而美丽！</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/7186.html/feed</wfw:commentRss>
		<slash:comments>83</slash:comments>
		</item>
		<item>
		<title>游戏：VIM大冒险</title>
		<link>http://coolshell.cn/articles/7166.html</link>
		<comments>http://coolshell.cn/articles/7166.html#comments</comments>
		<pubDate>Thu, 26 Apr 2012 00:22:22 +0000</pubDate>
		<dc:creator>陈皓</dc:creator>
				<category><![CDATA[杂项资源]]></category>
		<category><![CDATA[轶事趣闻]]></category>
		<category><![CDATA[vi]]></category>
		<category><![CDATA[vim]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=7166</guid>
		<description><![CDATA[不知道大家是否还记得“Vim简明攻略”呢？你是不是对Vim的那一大堆热键很头痛呢？现在好好，下面这个游戏是一个使用VIM热键玩的游戏。你可以在玩游戏的过程中熟悉Vim的热键。 你可以点击图片，或是图片下的网址打开这个游戏 http://vim-adventures.com/ 我试玩了一下这个游戏，真的很不错，下面是一些我给的游戏攻略。 第一关，场景一，首先是使用vim的h, j, k, l四个键来控制方向。（如果你妄图使用光标键的话，系统会出现黄色警告的）你需要使用h, j, k, l 四个方向走到图的右边，找到一把钥匙。（注意：迷宫墙上有些斜面，你可以通过斜面），找到钥匙后，钥匙会出现在你的右上角的位置，示意着你的光标要向那个方向移动，当你到达一个门的时候，会自动开门，进入第二关。 第二关，每一关的小人都会给你一些英文提示，教你怎么玩。关于第二关，你会看到你过不去，小会提示你，那些绿草地就向我们文件中的行，你在行上按上下键，光标会在这一列上移动，如果这一下面的一行没有这么长，光标会到行尾。这个vim的特性会告诉我们如何过这一关——移到最上面的行尾（因为是最长的可以越过最下面的障碍），然后按下光标键，到最后一行时你就会发现光标已经过了阻碍。如此通过第二场景，达到一个小人后，按下键，进入第二关。 第三关，我们可以看到地图上有很多的字母，我们还可以看到有两个键，一个是w，一个是e，我们可以把光标移到w上吃到w后，我们就可以使用w键了——以单词为单位移动光标，这样，我们就可以吃到e了和第一把钥匙，我们按w和e我们就可以看到这两个按键都是以单词为单位移动光标的，一个是单词头，一个是单词尾（参看我以前给大家的vim按键速查卡）。然后，我们在最后一行通过单词跳跃到最右边吃到b—— 回到该单词的头，可以得到第二把钥匙。然后往上走，使用b 和 e键拿到第三把钥匙。然后就可以打开三个门通关了。 然后，就需要你注册才能玩了。作者说，因为需要发的邮件太多了，所以现在系统发不出邮件了，请等待。所以，不知道作者是用来收集邮件的，还是没有开发完，不过，这个游戏的创意实在是太赞了。推荐给大家。 哪位会做游戏又熟Vim的朋友也能做一个？ （全文完） 相关文章2010年10月12日 -- 主流文本编辑器学习曲线2010年10月09日 -- 三个教程2010年09月28日 -- 一些非常有意思的杂项资源2009年05月23日 -- 将vim变得简单:如何在vim中得到你最喜爱的IDE特性2011年09月20日 -- 一些文章和各种资源2011年09月16日 -- 给程序员的VIM速查卡2011年09月07日 -- 简明 Vim 练级攻略<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="简明 Vim 练级攻略" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5426.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7166.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5426.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7166.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/09/20/32305122.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">简明 Vim 练级攻略</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="将vim变得简单:如何在vim中得到你最喜爱的IDE特性" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F894.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7166.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F894.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7166.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">将vim变得简单:如何在vim中得到你最喜爱的IDE特性</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Vim命令速查卡" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F150.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7166.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F150.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7166.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/07/19/18062655.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Vim命令速查卡</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="《Vim Recipes》免费的Vim Cookbook" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F956.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7166.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F956.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7166.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">《Vim Recipes》免费的Vim Cookbook</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Eclipse 和 Vim" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1837.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7166.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1837.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7166.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10435142.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Eclipse 和 Vim</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table>]]></description>
			<content:encoded><![CDATA[<p>不知道大家是否还记得“<a title="简明 Vim 练级攻略" href="http://coolshell.cn/articles/5426.html" target="_blank">Vim简明攻略</a>”呢？你是不是对Vim的那一大堆热键很头痛呢？现在好好，下面这个游戏是一个使用VIM热键玩的游戏。你可以在玩游戏的过程中熟悉Vim的热键。</p>
<p><strong>你可以点击图片，或是图片下的网址打开这个游戏</strong></p>
<p style="text-align: center;"><strong><a href="http://vim-adventures.com/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/vim-adventures.com/?referer=');">http://vim-adventures.com/</a></strong></p>
<p style="text-align: center;"><a href="http://vim-adventures.com/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/vim-adventures.com/?referer=');"><img class=" wp-image-7172 aligncenter" title="VIM Adventures" src="http://coolshell.cn/wp-content/uploads/2012/04/vimadventuresgamefun.jpg" alt="VIM大冒险" width="600" height="369" /></a></p>
<p style="text-align: left;">我试玩了一下这个游戏，真的很不错，下面是一些我给的游戏攻略。</p>
<p style="text-align: left;"><span id="more-7166"></span></p>
<ul>
<li>第一关，场景一，首先是使用vim的h, j, k, l四个键来控制方向。（如果你妄图使用光标键的话，系统会出现黄色警告的）你需要使用h, j, k, l 四个方向走到图的右边，找到一把钥匙。（注意：迷宫墙上有些斜面，你可以通过斜面），找到钥匙后，钥匙会出现在你的右上角的位置，示意着你的光标要向那个方向移动，当你到达一个门的时候，会自动开门，进入第二关。</li>
</ul>
<ul>
<li>第二关，每一关的小人都会给你一些英文提示，教你怎么玩。关于第二关，你会看到你过不去，小会提示你，那些绿草地就向我们文件中的行，你在行上按上下键，光标会在这一列上移动，如果这一下面的一行没有这么长，光标会到行尾。这个vim的特性会告诉我们如何过这一关——移到最上面的行尾（因为是最长的可以越过最下面的障碍），然后按下光标键，到最后一行时你就会发现光标已经过了阻碍。如此通过第二场景，达到一个小人后，按下键，进入第二关。</li>
</ul>
<ul>
<li>第三关，我们可以看到地图上有很多的字母，我们还可以看到有两个键，一个是w，一个是e，我们可以把光标移到w上吃到w后，我们就可以使用w键了——以单词为单位移动光标，这样，我们就可以吃到e了和第一把钥匙，我们按w和e我们就可以看到这两个按键都是以单词为单位移动光标的，一个是单词头，一个是单词尾（参看我以前给大家的<a title="给程序员的VIM速查卡" href="http://coolshell.cn/articles/5479.html" target="_blank">vim按键速查卡</a>）。然后，我们在最后一行通过单词跳跃到最右边吃到b—— 回到该单词的头，可以得到第二把钥匙。然后往上走，使用b 和 e键拿到第三把钥匙。然后就可以打开三个门通关了。</li>
</ul>
<div id="attachment_7174" class="wp-caption aligncenter" style="width: 441px"><a href="http://vim-adventures.com/" onclick="pageTracker._trackPageview('/outgoing/vim-adventures.com/?referer=');"><img class="size-full wp-image-7174" title="Vim Adventures 第三关" src="http://coolshell.cn/wp-content/uploads/2012/04/vimadventuresgamefun02.jpg" alt="Vim Adventures 第三关" width="431" height="286" /></a><p class="wp-caption-text">Vim Adventures 第三关</p></div>
<p style="text-align: left;">然后，就需要你注册才能玩了。作者说，因为需要发的邮件太多了，所以现在系统发不出邮件了，请等待。所以，不知道作者是用来收集邮件的，还是没有开发完，不过，<strong>这个游戏的创意实在是太赞了</strong>。推荐给大家。</p>
<p style="text-align: left;"><strong>哪位会做游戏又熟Vim的朋友也能做一个？</strong></p>
<p style="text-align: left;">（全文完）</p>
<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="简明 Vim 练级攻略" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5426.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7166.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5426.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7166.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/09/20/32305122.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">简明 Vim 练级攻略</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="将vim变得简单:如何在vim中得到你最喜爱的IDE特性" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F894.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7166.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F894.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7166.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">将vim变得简单:如何在vim中得到你最喜爱的IDE特性</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Vim命令速查卡" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F150.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7166.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F150.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7166.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/07/19/18062655.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Vim命令速查卡</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="《Vim Recipes》免费的Vim Cookbook" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F956.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7166.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F956.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7166.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">《Vim Recipes》免费的Vim Cookbook</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Eclipse 和 Vim" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1837.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7166.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1837.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7166.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10435142.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Eclipse 和 Vim</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table><h3  class="related_post_title">相关文章</h3><ul class="related_post"><li>2010年10月12日 -- <a href="http://coolshell.cn/articles/3125.html" title="主流文本编辑器学习曲线">主流文本编辑器学习曲线</a></li><li>2010年10月09日 -- <a href="http://coolshell.cn/articles/3083.html" title="三个教程">三个教程</a></li><li>2010年09月28日 -- <a href="http://coolshell.cn/articles/3013.html" title="一些非常有意思的杂项资源">一些非常有意思的杂项资源</a></li><li>2009年05月23日 -- <a href="http://coolshell.cn/articles/894.html" title="将vim变得简单:如何在vim中得到你最喜爱的IDE特性">将vim变得简单:如何在vim中得到你最喜爱的IDE特性</a></li><li>2011年09月20日 -- <a href="http://coolshell.cn/articles/5224.html" title="一些文章和各种资源">一些文章和各种资源</a></li><li>2011年09月16日 -- <a href="http://coolshell.cn/articles/5479.html" title="给程序员的VIM速查卡">给程序员的VIM速查卡</a></li><li>2011年09月07日 -- <a href="http://coolshell.cn/articles/5426.html" title="简明 Vim 练级攻略">简明 Vim 练级攻略</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/7166.html/feed</wfw:commentRss>
		<slash:comments>41</slash:comments>
		</item>
		<item>
		<title>这到底是谁之错？</title>
		<link>http://coolshell.cn/articles/7126.html</link>
		<comments>http://coolshell.cn/articles/7126.html#comments</comments>
		<pubDate>Thu, 19 Apr 2012 02:11:05 +0000</pubDate>
		<dc:creator>hfcc8685</dc:creator>
				<category><![CDATA[杂项资源]]></category>
		<category><![CDATA[职场生涯]]></category>
		<category><![CDATA[Programmer]]></category>
		<category><![CDATA[程序员]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=7126</guid>
		<description><![CDATA[【感谢 @风枫峰 投递本文】 故事一： 背景介绍：RT是一个外包公司，ZWZX是项目承接公司，YD是甲方。 RT公司每天下班的时候都会接到ZWZX负责人的电话，询问一天的工作情况，然后布置任务要求晚上加班做完，RT公司的员工很无奈也很气愤因为每天都要加班，员工们就问项目经理：“为什么天天加班赶需求，今天才提一个需求，明天就要上线，还让不让人活了?” 项目经理无奈的说：“我有什么办法啊？这是人家ZWZX负责人说的啊，对方逼得紧。” 多次以后项目经理也忍不住了，就问ZWZX的负责人怎么天天这样啊，ZWZX的负责人就说了:”明天就要向YD的负责人展示这个页面，我也没有办法啊？YD那边老总就是这么要求的，我怎么办，我也不想这样啊？” 然后RT的项目经理实在受不了了就辞职了，新上任的项目经理又会走他的老路，因为从开始我们就被培养“满足客户的需求是最重要的”。RT的员工也就这样一直抱怨着，一直忍受着。天天在心里咒骂YD的老总真是没有人性，不拿人当人看啊！ 人换了一批又一批，加班也就慢慢的变成了应该的，你不加班说明你不敬业，不合格。 故事二： IE6一直存活着，所有的前端开发人员都痛恨它，都不想兼容它，可是产品经理看到IE6的市场占有率还是这么高，就会要求前端开发人员必须兼容IE6。 矛盾又来了，就像故事一一样，前端开发人员天天抱怨，产品经理也天天抱怨，但是面对IE6的市场份额，产品经理会劝开发人员说：“我有什么办法啊？IE6的市场份额就是这么高，不兼容怎么办啊？我也不想啊！” 开发人员也就这样忍受着，然后不断地抱怨用IE6的用户低端，没文化，怎么还用IE6啊！天天兼容IE6就够烦的了，还怎么创新啊！ 这两个故事里出现的问题到底是谁的错误引起的？  故事一的罪魁祸首是YD的老总吗？ 故事二的罪魁祸首是那些还用着IE6的用户吗？ 从这两个嫌疑最大的罪魁祸首眼中看一下这两个故事： 故事一： 我是YD的老总，我要建立一个网站，找到了ZWZX公司，签订了合同，我提需求他们实现。 我不懂制作网站，可是我才思敏捷，创意无限，不停的会有好点子从我的脑海里蹦出来，每当有一个好点子蹦出来后，我都会给ZWZX公司的负责人讲清楚我的想法，让他实现，开始我不知道做一个页面需要多长时间。第一次我试探性的说了一周必须把我这个点子做出来，ZWZX公司负责人很痛快的答应了，一周后我果然看到了这个功能。 可是会不会我给他们的时间太长了？对！肯定是，要不也不会答应的这么痛快。这些人啊！天天就是想拖时间，好多骗我点钱。 点子又来了，这次我要求5天做出来，这个点子和上个点子类似，我倒要看看5天能不能做出来~  ZWZX公司负责人一副痛苦的表情，我会不会逼的太紧了，5天是不是真的做不出来？到时候看看吧，如果5天没做出来估计是我给的时间太少了。 5天过去了ZWZX公司的负责人很高兴的拿出了我要的功能实现，哎，看来开始真的骗了我两天。就是不知道5天会不会还是多了啊？下次给3天~ 又拿出来了，虽然他装的好像时间太紧似的，可别以为我不知道，你第一个功能最多3天就做出来了，我还给了你7天的项目经费，你们多赚了我多少啊！！！！ 真是没良心。 下次1天！！！ 啊啊啊啊啊啊啊啊!!! 1天就出来了，这些人。。。。。  有没有良心，原来做这个这么简单，以后就给1天，不 ！ 一天N个功能。 故事二： 我买了个电脑，没什么别的用途，就是打开电脑上上网，上上QQ和儿子聊聊天，QQ是儿子给我装上的，这样我就可以和他视频了。有一次QQ提醒我说我的QQ版本太低了，不能视频了，我打电话问儿子，儿子说按提示升级一下QQ就行了，呵呵，我按QQ的提示，儿子的指示一步一步的升级QQ成功了，看来电脑也不难啊！ 到这里您认为开始的两个故事的罪魁祸首是谁啊？ 我们一直以加班，甚至通宵去满足客户不合理的要求，只因为他是客户。只因为人人都认为满足客户的要求是我们最大的 价值，可是不合理的要求不能去拒绝吗？套用刘欢说的一句话“我们是不是活的应该有些尊严”，一味的迎合客户，只会让我们自己越来越痛苦，反而得不到用户的尊重，肯定。 我一直有个疑惑，很多人说网站不支持IE6，而选择让用户去升级IE，这样的用户体验不好！如果按照按照这个逻辑，是不是我们都应该是Web应用，而且都应该是IE6下的Web应用呢？为什么微软还要出WIN8，一直XP不是挺好的吗？让用户升级系统，用户体验多么不好啊？QQ，360，搜狗输入法，等等客户端软件用户体验不都不好吗？ 都还要用户下载。 实在搞不懂为什么我们做个东西非要去支持IE6呢？检测到用户是IE6，给个提示，给个升级链接不就行了？ 这样做用户体验是有多么不好吗？ 你天天去支持IE6，还要天天磨叽用户使用IE6，你不觉的很矛盾吗？再说我一个普通用户，你如果不提醒，我怎么知道要升级IE6啊？ 对于遭遇了故事一，故事二的人只能送上一句话“哀其不幸，怒其不争！” 原文链接：http://hfcc8685.github.com/blog/2012/04/19/shui-zhi-cuo/ 相关文章2012年04月27日 -- 做个环保主义的程序员2012年04月17日 -- 挑战无处不在2012年04月11日 -- 我们需要专职的QA吗？2012年03月09日 -- Bret Victor &#8211; Inventing [...]<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="程序员的八个级别" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F343.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7126.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F343.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7126.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10437645.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">程序员的八个级别</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="做个环保主义的程序员" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7186.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7126.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7186.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7126.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2012/04/27/23798602.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">做个环保主义的程序员</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="程序员版的凡客" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2806.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7126.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2806.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7126.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/06/21/13669995.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">程序员版的凡客</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="惹恼程序员的十件事" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F340.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7126.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F340.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7126.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/02/12/2675402.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">惹恼程序员的十件事</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="程序员因为女孩而美丽！" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6346.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7126.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6346.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7126.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">程序员因为女孩而美丽！</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table>]]></description>
			<content:encoded><![CDATA[<p>【感谢 @<a title="风枫峰" href="http://weibo.com/hfcc?source=webim" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/hfcc?source=webim&amp;referer=');">风枫峰</a> 投递本文】</p>
<p><strong>故事一：</strong><br />
背景介绍：RT是一个外包公司，ZWZX是项目承接公司，YD是甲方。</p>
<p>RT公司每天下班的时候都会接到ZWZX负责人的电话，询问一天的工作情况，然后布置任务要求晚上加班做完，RT公司的员工很无奈也很气愤因为每天都要加班，员工们就问项目经理：“为什么天天加班赶需求，今天才提一个需求，明天就要上线，还让不让人活了?” 项目经理无奈的说：“我有什么办法啊？这是人家ZWZX负责人说的啊，对方逼得紧。”</p>
<p>多次以后项目经理也忍不住了，就问ZWZX的负责人怎么天天这样啊，ZWZX的负责人就说了:”明天就要向YD的负责人展示这个页面，我也没有办法啊？YD那边老总就是这么要求的，我怎么办，我也不想这样啊？”</p>
<p>然后RT的项目经理实在受不了了就辞职了，新上任的项目经理又会走他的老路，因为从开始我们就被培养“满足客户的需求是最重要的”。RT的员工也就这样一直抱怨着，一直忍受着。天天在心里咒骂YD的老总真是没有人性，不拿人当人看啊！</p>
<p>人换了一批又一批，加班也就慢慢的变成了应该的，你不加班说明你不敬业，不合格。</p>
<p><strong>故事二：</strong><br />
IE6一直存活着，所有的前端开发人员都痛恨它，都不想兼容它，可是产品经理看到IE6的市场占有率还是这么高，就会要求前端开发人员必须兼容IE6。</p>
<p><span id="more-7126"></span></p>
<p>矛盾又来了，就像故事一一样，前端开发人员天天抱怨，产品经理也天天抱怨，但是面对IE6的市场份额，产品经理会劝开发人员说：“我有什么办法啊？IE6的市场份额就是这么高，不兼容怎么办啊？我也不想啊！” 开发人员也就这样忍受着，然后不断地抱怨用IE6的用户低端，没文化，怎么还用IE6啊！天天兼容IE6就够烦的了，还怎么创新啊！</p>
<p><strong>这两个故事里出现的问题到底是谁的错误引起的？ </strong></p>
<p>故事一的罪魁祸首是YD的老总吗？</p>
<p>故事二的罪魁祸首是那些还用着IE6的用户吗？</p>
<p>从这两个嫌疑最大的罪魁祸首眼中看一下这两个故事：</p>
<p><strong>故事一：</strong><br />
我是YD的老总，我要建立一个网站，找到了ZWZX公司，签订了合同，我提需求他们实现。</p>
<p>我不懂制作网站，可是我才思敏捷，创意无限，不停的会有好点子从我的脑海里蹦出来，每当有一个好点子蹦出来后，我都会给ZWZX公司的负责人讲清楚我的想法，让他实现，开始我不知道做一个页面需要多长时间。第一次我试探性的说了一周必须把我这个点子做出来，ZWZX公司负责人很痛快的答应了，一周后我果然看到了这个功能。</p>
<p>可是会不会我给他们的时间太长了？对！肯定是，要不也不会答应的这么痛快。这些人啊！天天就是想拖时间，好多骗我点钱。</p>
<p>点子又来了，这次我要求5天做出来，这个点子和上个点子类似，我倒要看看5天能不能做出来~  ZWZX公司负责人一副痛苦的表情，我会不会逼的太紧了，5天是不是真的做不出来？到时候看看吧，如果5天没做出来估计是我给的时间太少了。</p>
<p>5天过去了ZWZX公司的负责人很高兴的拿出了我要的功能实现，哎，看来开始真的骗了我两天。就是不知道5天会不会还是多了啊？下次给3天~</p>
<p>又拿出来了，虽然他装的好像时间太紧似的，可别以为我不知道，你第一个功能最多3天就做出来了，我还给了你7天的项目经费，你们多赚了我多少啊！！！！ 真是没良心。 下次1天！！！</p>
<p>啊啊啊啊啊啊啊啊!!! 1天就出来了，这些人。。。。。  有没有良心，原来做这个这么简单，以后就给1天，不 ！ 一天N个功能。</p>
<p><strong>故事二：</strong><br />
我买了个电脑，没什么别的用途，就是打开电脑上上网，上上QQ和儿子聊聊天，QQ是儿子给我装上的，这样我就可以和他视频了。有一次QQ提醒我说我的QQ版本太低了，不能视频了，我打电话问儿子，儿子说按提示升级一下QQ就行了，呵呵，我按QQ的提示，儿子的指示一步一步的升级QQ成功了，看来电脑也不难啊！</p>
<p><strong>到这里您认为开始的两个故事的罪魁祸首是谁啊？</strong></p>
<p>我们一直以加班，甚至通宵去满足客户不合理的要求，只因为他是客户。只因为人人都认为满足客户的要求是我们最大的<br />
价值，可是不合理的要求不能去拒绝吗？套用刘欢说的一句话“我们是不是活的应该有些尊严”，一味的迎合客户，只会让我们自己越来越痛苦，反而得不到用户的尊重，肯定。</p>
<p>我一直有个疑惑，很多人说网站不支持IE6，而选择让用户去升级IE，这样的用户体验不好！如果按照按照这个逻辑，是不是我们都应该是Web应用，而且都应该是IE6下的Web应用呢？为什么微软还要出WIN8，一直XP不是挺好的吗？让用户升级系统，用户体验多么不好啊？QQ，360，搜狗输入法，等等客户端软件用户体验不都不好吗？ 都还要用户下载。</p>
<p>实在搞不懂为什么我们做个东西非要去支持IE6呢？检测到用户是IE6，给个提示，给个升级链接不就行了？ 这样做用户体验是有多么不好吗？ 你天天去支持IE6，还要天天磨叽用户使用IE6，你不觉的很矛盾吗？再说我一个普通用户，你如果不提醒，我怎么知道要升级IE6啊？</p>
<p><strong>对于遭遇了故事一，故事二的人只能送上一句话“哀其不幸，怒其不争！”</strong></p>
<p>原文链接：<a href="http://hfcc8685.github.com/blog/2012/04/19/shui-zhi-cuo/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/hfcc8685.github.com/blog/2012/04/19/shui-zhi-cuo/?referer=');">http://hfcc8685.github.com/blog/2012/04/19/shui-zhi-cuo/</a></p>
<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="程序员的八个级别" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F343.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7126.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F343.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7126.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10437645.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">程序员的八个级别</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="做个环保主义的程序员" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7186.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7126.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7186.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7126.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2012/04/27/23798602.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">做个环保主义的程序员</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="程序员版的凡客" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2806.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7126.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2806.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7126.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/06/21/13669995.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">程序员版的凡客</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="惹恼程序员的十件事" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F340.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7126.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F340.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7126.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/02/12/2675402.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">惹恼程序员的十件事</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="程序员因为女孩而美丽！" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6346.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7126.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6346.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7126.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">程序员因为女孩而美丽！</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table><h3  class="related_post_title">相关文章</h3><ul class="related_post"><li>2012年04月27日 -- <a href="http://coolshell.cn/articles/7186.html" title="做个环保主义的程序员">做个环保主义的程序员</a></li><li>2012年04月17日 -- <a href="http://coolshell.cn/articles/7048.html" title="挑战无处不在">挑战无处不在</a></li><li>2012年04月11日 -- <a href="http://coolshell.cn/articles/6994.html" title="我们需要专职的QA吗？">我们需要专职的QA吗？</a></li><li>2012年03月09日 -- <a href="http://coolshell.cn/articles/6775.html" title="Bret Victor &#8211; Inventing on Principle">Bret Victor &#8211; Inventing on Principle</a></li><li>2012年02月21日 -- <a href="http://coolshell.cn/articles/6639.html" title="千万别惹程序员 ">千万别惹程序员 </a></li><li>2012年01月30日 -- <a href="http://coolshell.cn/articles/6526.html" title="软件开发的“三重门”">软件开发的“三重门”</a></li><li>2012年01月04日 -- <a href="http://coolshell.cn/articles/6346.html" title="程序员因为女孩而美丽！">程序员因为女孩而美丽！</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/7126.html/feed</wfw:commentRss>
		<slash:comments>70</slash:comments>
		</item>
		<item>
		<title>挑战无处不在</title>
		<link>http://coolshell.cn/articles/7048.html</link>
		<comments>http://coolshell.cn/articles/7048.html#comments</comments>
		<pubDate>Tue, 17 Apr 2012 02:06:16 +0000</pubDate>
		<dc:creator>陈皓</dc:creator>
				<category><![CDATA[杂项资源]]></category>
		<category><![CDATA[程序设计]]></category>
		<category><![CDATA[职场生涯]]></category>
		<category><![CDATA[Programmer]]></category>
		<category><![CDATA[程序员]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=7048</guid>
		<description><![CDATA[面试过一些应聘者，当我问到为什么换工作的时候，他们都会告诉我，现在的工作没有挑战，无聊，所以想换一个有挑战的工作。于是我问了一下他的工作情况，发现那些有挑战的东西他还没有搞懂。我总是为有这样的认识的朋友感到惋惜，因为我总是认为有挑战的东西无处不在啊，不能因为工作上没有，自己就放纵了自己。比如，面试过一个做地图的工程师，他的工作是做计算地图上任意两点的最短或最优路径的一部分功能。我觉得这个事很有挑战，也有难度，应聘者说，没什么挑战，因为他做的东西只是调用相关的算法库。他在这个项目干了2年了，当我问他有没有看过算法库，知不知道地图是怎么存储的？他却告诉我，因为没有去做，所以就没有去了解，等做的时候再了解（我希望有这样想法的人都去看看程序员的谎谬之言还是至理名言？）。这样的例子很多，很多应聘者在面试中不能和我一起解决某个问题的时候，比如：OOD，数据库设计，系统设计，等，他们都会告诉我，不好意思，因为没有做过相关的事情，所以就不懂了，所以，他需要一个像我们这样的项目来学习和锻炼。我并不要求你能解决你所不擅长的问题，但毕竟数据库，OO，系统设计都是软件开发的基础知识，多少要懂一些吧。 但另外一方面，他们都会告诉我他们对技术充满和热情和兴趣，有着很强的学习能力，也有很能吃苦的态度。这也许是某面试宝典上看来的，面经上可能都会说，如果面对不能作答问题，可以说一下自己的态度和决心。可惜的是，我并不这么想的，我在我的两篇关于招聘的文章里（我是怎么招聘程序员的，再谈我是怎么招聘程序员的）都说过一些我对如何择人的想法。这里重点说明一下其中两个观点： 关于热情和态度，说白了就是不要给自己找借口。比如：“工作忙事多没时间学所以可以不懂”，“工作中没用到所以可以不懂”，“工作没有挑战，一直没有遇到合适的项目”等等。时间可以挤，工作之余可以学，随时随地去思考，挑战是无处不在的…… 想想那些你有热情的事，你会发现，几乎没有什么可以阻止你去做那些事。 对于某些事情，如果以前没有在你身上发生过，那么这个事情在未来也不会发生。如果你以前没有对你接触过的东西去学习，去深挖，去思考，去改善，那么我不会相信你会在未来面对新的东西的时候也会有这样的态度；如果你以前没有用业余时间学习一些项目之外的东西，那么我也不会相信你会在未来会这样做；如果你以前没有把你的热情和态度转换成你的知识，经验和成果，那么我也不会相信你会在未来能做到。 这两个观点可能太刻薄了，但是，当我回想我自己的经历的时候，观察程序员的成长过程的时候，我发现，优秀的程序员都是相似的，当他们还在是一个菜鸟的时候，就已经有各种成为高手的苗头了，这些苗头就是——他们热爱思考，喜欢解决难题，对新鲜事物非常好奇，总是找人讨论，可以用自己的业余时间狠命研究很多和工作无关的技术，会在业余的时间里写些有趣的小程序，或是会把自己的思路书写下来，等等，等等。 一些问题 我这样说，大家可能会觉得“挑战无处不在”这句话太虚了，而且可能不明白什么叫“热爱思考”，这里，我把我的或别人的思考的东西罗列一下，这些问题，有的会让我思考推敲，有的会让我疯狂地查资料，问人，或是找人讨论，询问。大家不妨可以跟着我一起思考一下。 酷壳上有一些小问题，比如：火车运煤问题，赛马问题，这些问题都不够实际，我觉得也这些问题有点无聊，我们不妨观察一下我们身边的东西，我们就可以看到很多有挑的战的东西，对于这些问题，如果是你来做，你会怎么做呢？ 0）许多年前，当我看到珊瑚虫QQ把IP转成地实际地址的时候，我就在思考，如果我有一个IP网段的数据（全球IP地址数据），我怎么来完成这个功能呢？比如：某地点的IP网段是：10.10.1.* &#8211; 10.10.5.*。我要有一个IP地址是：10.10.3.20，我怎么匹配这个网段？用Hash表吗？好像有问题。把IP字串转成整型？排序+二分法，好像更容易解决一些，但是如果有一些修改的话好像有点不方便。用树型结构（森林）会不会更好一些呢？如果我要通过地点反查IP段呢？ 1）网上短网址服务，你有想过这个短网址生成的算法是什么，如何能做到能最短？怎么查询？你也许觉得会用key-value的NoSQL。那么，如果对于同一个URL，如果要重用已生成的短网址，你怎么用key-value的NoSQL来解决？ 英汉词典的检索和这个很相似，如果通过英文查汉语，又通过汉语查英文？如果是N多种语言的互相翻译呢？你的数据存储和检索如何做呢？ 2）当我看到Dropbox这样的云同步的软件的时候，我不知道你是否会和我一样会去思考，在多个设备间的文件同步是怎么做的？如果网盘上有几万，甚至几百万个文件，当要和我的本地数据同步时，他如何比较经济地知道哪些文件更改了？需要向服务端同步或是向客户端同步。更进一步，你有没有想过没有中心结点的文件同步问题？你有没有想过，文件冲突的问题？ 3）我们的新员工入职的时候，有一些公司会给新员工的帐号生成一个随机口令，然后新员工可以在登录后修改口令（我一直在想我们的银行应该为用户生成一个随机口令，而不是设置一个6个0或是6个8的初始口令）。那么，对生成随机安全口令的算法知道怎么做吗？如果你写出这个算法来了，你怎么证明这个算法是足够随机，生成的密码强度足够大的？（你会发现，测试口令是否随机是否安全的程序，会比生成器更难写） 4）关于动态密码RSA SecurID（如下图），这个小设备上的6位数字会每60秒变一次，在你登录的时候，需要输入这6位数字，服务器上会认证这6个数字，那么这个事怎么做？再试想一下，这样的小设备我要发给我的客户，我希望我的每个客户都使用不一样的随机算法，就算是算法一样，算法的种子也不能一样。那么，如果我的客户一共有百万甚至千万，我的服务端怎么管理这些用户的SecurID？ 5）看看我们的网银或是ATM的用户登录功能，如果你登录时输错口令超过3次以上，你的帐号就会被冻结，需要去柜台重置口令。这个功能看上去很安全，因为可以防止黑客在线尝试破解你的登录口令。不过这又带来了另一个问题，如果有一个恶意用户知道你的卡号，他就上网或是造个卡故意输错你的口令，导致你的帐号被冻结，让你一次又一次地去银行排队重置。面对这样的情况，你该怎么解决？ 6）当你在网上购物的时候，你会去一些电子商务的网站，这些网站都会对他们的产品进行分类，有大分类有子分类。你进到分类后，你可以通过不同的属性来过滤不同该分类下的商品，注意，不同分类下的商品的过滤属性不一样，如，手机分类和电视分类的属性都不一样。试问，你如何设计你的数据库表结构？ 7）当你在泡各种论坛或SNS社区的时候，你会看到，用户在互相回复的时候存在一个问题，尤其是用户量很大的时候，大家的回复完全交织在一起什么 也看不清楚。以前有的论坛使用树形列表来解决这个问题，树形列表好是好，但是把一棵大树放在那里还是很难看。Twitter.com给了一个非常不错的解决方式，就是所有人的回复或是回复的回复都按时间线放在一起，如果你要查看某回复的上下文的话，点击一下这个回复就可以看到了（我在我在“国内微博和Twitter的最大不同”中批评过这个事）。新浪微博在禁评论事件后也开发出了这个功能。你知道这个事怎么做吗？ 更进一步，新浪微博的设计上有很多的缺陷，单说新开发的“查看评论”功能这个事来说，还是不完美，因为某些评论会随着转发带到别的地方去，他的“查看评论”功能只能看到当个贴子下的东西，不能把所有转发出去的贴子的评论一起综合起来。虽然这对于用户使用来说没有什么在不了的，但是对于软件设计来说，我们不妨做一个练习，可以思考一下，怎么样设计会更好。 再举一反三，有时候，我发现多个网友会提出同样的问题，我很想用一个回复同时回复他们。如果有这样的功能的话，我们的回复就会从一个树形变成另外一种形状了，我们又该如何设计才能支持这样的功能呢？ 8）说到新浪微博，我就想多说几句，我最近观察到了两个事： 一个是验证码的事，如果你在你的帐号设置里设置了“登录需要验证码”，你会发现，在登录新浪微博的时候，仅当你输对了口令后，系统才会提示你输入验证码。为什么呢？因为，这个“登录需要验证码”这绑定在你的帐号设置里的，所以，要取这个设置，就需要你登录成功（？！），老实说，这个功能在设计上有点二（中国特色）。如果是你，你怎么设计呢？ 另一个事情是新浪微博或Twitter的用户名修改后，被他人@过的信息就再也链接不到你这里来了。我们来试想一下，如果是你，你怎么解决这个问题？（我的我的微博里讨论过这个事，不一定对，供大家参考） 9）我有时候我会发一些快递，有时候是一些小东西，有时候是一些大包裹，有时候近，有时候远。我发现一个有趣的现象，就是快递员来收件的时候，快递的价格都是快递员自己说了算的，我还可以和他们砍价。我观察到他们会以距离，重量大小来订价。于是我在想如果你要运营一个物流公司，你作为这个物流公司的程序员，你需要开发一个软件来标注快递价格，你会怎么做？比如，这个快递公司会说，在北京五环以内是一个价，以外是一个价，出省后，上海以北是一个价，上海以南是一个价，等等，这只是北京的，如果把全国的各个城市到别的城市的价格都考虑进来，还要受到重量，体积，价格，是否加急等等因素的影响，你的数据库设计要怎么做呢？ A）国内的水军太恐怖了。他们活动的刷排名，刷信用，刷积分，刷粉丝等等地方，你是否想过如何解决这个问题？还有广告联盟的欺诈问题，等等。这些东西，有的还是可以通过技术手段进行限制和计算的，你有思考过应该使用什么样的方法吗？ B）说到水军就不能不提垃圾邮件和垃圾短信。你有没有想过邮件系统怎么过滤垃圾信息的？ C）关于推荐功能，这必然是一个热点，这是软件产品从request -&#62; response的被动方式到主动方式的进化。微博上有推荐关注者的功能，电商有推荐商品的功能，豆瓣上有推荐影片音乐书籍的功能。不同的领域的推荐算法各不相同，你有没有思考过，如果是你来做推荐算法的时候，你会怎么做吗？更进一步，推荐通常伴随着学习和匹配，学习用户的行为，匹配相似的东西，你想过怎么学习用户的行为，怎么匹配相似的东西了吗？ D）关于微博，某名人有几千万的粉丝，当这个名人发一个微博的时候，需要通知这几千万个粉丝，这个在系统架构上应该怎么做？如果某天这个名人与人发生口角，和人吵架，拼命的刷微博，那么，系统架构要怎么设计才能支持这样的事呢？ E）想想火车票的分段卖票的方式，现有的解决方案是为每个站点预留票，于是我们可以看到火车始发时，有很多空坐，这些空坐都是留给下一个站点的，我们能否开发出一个系统来，可以把一条线上的这些这站上那站下的旅客统筹规划一下，制定出一个最经济的方式，让火车运行得更有效。 F）对于地铁公交网络，我们希望这个网络既能有更多的覆盖，又能节省路线，你能不能设计出一个系统，当我们输入一些数据（如：站点，是否终点或起点站，该站的下一站可能方向（多个），该站是以上车为主，还是下车为主，等等），你的系统能自动安排出各种线路吗？ 这样的问题实在是太多了，都是可以让我们去思考的，并不一定有经济效益，但是至少可以让你锻炼一下怎么去分析问题，怎么去思考，怎么去解决问题。 总结 综上所述，我想说的是： 1） 只要你想，挑战是无处不在的。那怕是你现有的觉得无聊的东西，只要你想做到极致，那怕是一个简单的功能（比如用户登录的功能）也会让你充满挑战。 2）观察身边的事物，去思考，去调查，举一反三，这才是你成长的源泉。不要把你的成长推给客观原因。 3）我的软件开发的三重门中说过，第三重门是解决实际问题，让你的业务处理更为的智能，更为地强大。我不知道为什么这一两年，我们的圈子里所有的人都在关注着“云”，“海量数据处理”，“高性能架构”这样的东西，尤其是那些性能调的高性能的东西并不很难，而这些更为实际问题更有挑战性，也更有前景。 （全文完） 相关文章2012年04月27日 -- 做个环保主义的程序员2012年04月19日 -- 这到底是谁之错？2012年04月11日 -- 我们需要专职的QA吗？2012年03月09日 -- Bret Victor &#8211; [...]<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="做个环保主义的程序员" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7186.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7048.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7186.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7048.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2012/04/27/23798602.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">做个环保主义的程序员</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="漫画：程序员的一生" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1103.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7048.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1103.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7048.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10437646.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">漫画：程序员的一生</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="惹恼程序员的十件事" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F340.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7048.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F340.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7048.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/02/12/2675402.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">惹恼程序员的十件事</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="C++ 程序员自信心曲线图" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2287.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7048.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2287.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7048.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/06/21/13670426.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">C++ 程序员自信心曲线图</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="幽默：程序员的进化" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F172.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7048.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F172.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7048.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">幽默：程序员的进化</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table>]]></description>
			<content:encoded><![CDATA[<p><img class="alignright" title="解决问题" src="http://coolshell.cn/wp-content/uploads/2012/04/11_154056_1-300x225.jpg" alt="" width="300" height="225" />面试过一些应聘者，当我问到为什么换工作的时候，<strong>他们都会告诉我，现在的工作没有挑战，无聊，所以想换一个有挑战的工作</strong>。于是我问了一下他的工作情况，发现那些有挑战的东西他还没有搞懂。我总是为有这样的认识的朋友感到惋惜，因为我总是认为有挑战的东西无处不在啊，不能因为工作上没有，自己就放纵了自己。比如，面试过一个做地图的工程师，他的工作是做计算地图上任意两点的最短或最优路径的一部分功能。我觉得这个事很有挑战，也有难度，应聘者说，没什么挑战，因为他做的东西只是调用相关的算法库。他在这个项目干了2年了，当我问他有没有看过算法库，知不知道地图是怎么存储的？他却告诉我，<strong>因为没有去做，所以就没有去了解，等做的时候再了解</strong>（我希望有这样想法的人都去看看<a href="http://coolshell.cn/articles/4235.html" rel="bookmark">程序员的谎谬之言还是至理名言？</a>）。这样的例子很多，很多应聘者在面试中不能和我一起解决某个问题的时候，比如：OOD，数据库设计，系统设计，等，<strong>他们都会告诉我，不好意思，因为没有做过相关的事情，所以就不懂了，所以，他需要一个像我们这样的项目来学习和锻炼</strong>。我并不要求你能解决你所不擅长的问题，但毕竟数据库，OO，系统设计都是软件开发的基础知识，多少要懂一些吧。</p>
<p>但另外一方面，他们都会告诉我他们对技术充满和热情和兴趣，有着很强的学习能力，也有很能吃苦的态度。这也许是某面试宝典上看来的，面经上可能都会说，如果面对不能作答问题，可以说一下自己的态度和决心。可惜的是，我并不这么想的，我在我的两篇关于招聘的文章里（<a title="我是怎么招聘程序员的" href="http://coolshell.cn/articles/1870.html" target="_blank">我是怎么招聘程序员的</a>，<a title="再谈“我是怎么招聘程序员的”（上）" href="http://coolshell.cn/articles/4506.html" target="_blank">再谈我是怎么招聘程序员的</a>）都说过一些我对如何择人的想法。这里重点说明一下其中两个观点：</p>
<ul>
<li><strong>关于热情和态度，说白了就是不要给自己找借口</strong>。比如：“工作忙事多没时间学所以可以不懂”，“工作中没用到所以可以不懂”，“工作没有挑战，一直没有遇到合适的项目”等等。时间可以挤，工作之余可以学，随时随地去思考，挑战是无处不在的…… 想想那些你有热情的事，你会发现，几乎没有什么可以阻止你去做那些事。</li>
</ul>
<ul>
<li><strong>对于某些事情，如果以前没有在你身上发生过，那么这个事情在未来也不会发生</strong>。如果你以前没有对你接触过的东西去学习，去深挖，去思考，去改善，那么我不会相信你会在未来面对新的东西的时候也会有这样的态度；如果你以前没有用业余时间学习一些项目之外的东西，那么我也不会相信你会在未来会这样做；如果你以前没有把你的热情和态度转换成你的知识，经验和成果，那么我也不会相信你会在未来能做到。</li>
</ul>
<p>这两个观点可能太刻薄了，但是，当我回想我自己的经历的时候，观察程序员的成长过程的时候，我发现，优秀的程序员都是相似的，当他们还在是一个菜鸟的时候，就已经有各种成为高手的苗头了，这些苗头就是——<strong>他们热爱思考，喜欢解决难题，对新鲜事物非常好奇，总是找人讨论，可以用自己的业余时间狠命研究很多和工作无关的技术，会在业余的时间里写些有趣的小程序，或是会把自己的思路书写下来，等等，等等</strong>。</p>
<p><span id="more-7048"></span></p>
<h4>一些问题</h4>
<p>我这样说，大家可能会觉得“挑战无处不在”这句话太虚了，而且可能不明白什么叫“热爱思考”，这里，我把我的或别人的思考的东西罗列一下，这些问题，有的会让我思考推敲，有的会让我疯狂地查资料，问人，或是找人讨论，询问。大家不妨可以跟着我一起思考一下。</p>
<p>酷壳上有一些小问题，比如：<a title="面试题：火车运煤问题" href="http://coolshell.cn/articles/4429.html" target="_blank">火车运煤问题</a>，<a title="面试题：赛马问题" href="http://coolshell.cn/articles/1202.html" target="_blank">赛马问题</a>，这些问题都不够实际，我觉得也这些问题有点无聊，我们不妨观察一下我们身边的东西，我们就可以看到很多有挑的战的东西，对于这些问题，如果是你来做，你会怎么做呢？</p>
<p>0）许多年前，当我看到珊瑚虫QQ把IP转成地实际地址的时候，我就在思考，如果我有一个IP网段的数据（<a title="全球IP地址数据库" href="http://coolshell.cn/articles/244.html" target="_blank">全球IP地址数据</a>），我怎么来完成这个功能呢？比如：某地点的IP网段是：10.10.1.* &#8211; 10.10.5.*。我要有一个IP地址是：10.10.3.20，我怎么匹配这个网段？用Hash表吗？好像有问题。把IP字串转成整型？排序+二分法，好像更容易解决一些，但是如果有一些修改的话好像有点不方便。用树型结构（森林）会不会更好一些呢？如果我要通过地点反查IP段呢？</p>
<p>1）网上短网址服务，你有想过这个短网址生成的算法是什么，如何能做到能最短？怎么查询？你也许觉得会用key-value的NoSQL。那么，如果对于同一个URL，如果要重用已生成的短网址，你怎么用key-value的NoSQL来解决？</p>
<p>英汉词典的检索和这个很相似，如果通过英文查汉语，又通过汉语查英文？如果是N多种语言的互相翻译呢？你的数据存储和检索如何做呢？</p>
<p>2）当我看到Dropbox这样的云同步的软件的时候，我不知道你是否会和我一样会去思考，在多个设备间的文件同步是怎么做的？如果网盘上有几万，甚至几百万个文件，当要和我的本地数据同步时，他如何比较经济地知道哪些文件更改了？需要向服务端同步或是向客户端同步。更进一步，你有没有想过没有中心结点的文件同步问题？你有没有想过，文件冲突的问题？</p>
<p>3）我们的新员工入职的时候，有一些公司会给新员工的帐号生成一个随机口令，然后新员工可以在登录后修改口令（我一直在想我们的银行应该为用户生成一个随机口令，而不是设置一个6个0或是6个8的初始口令）。那么，对生成随机安全口令的算法知道怎么做吗？如果你写出这个算法来了，你怎么证明这个算法是足够随机，生成的密码强度足够大的？（你会发现，测试口令是否随机是否安全的程序，会比生成器更难写）</p>
<p>4）关于动态密码RSA SecurID（如下图），这个小设备上的6位数字会每60秒变一次，在你登录的时候，需要输入这6位数字，服务器上会认证这6个数字，那么这个事怎么做？再试想一下，这样的小设备我要发给我的客户，我希望我的每个客户都使用不一样的随机算法，就算是算法一样，算法的种子也不能一样。那么，如果我的客户一共有百万甚至千万，我的服务端怎么管理这些用户的SecurID？</p>
<p><img class="aligncenter" title="RSA Secure ID" src="http://keithelder.net/blog/images/keithelder_net/blog/WindowsLiveWriter/SettingupRSASecureIDonWindowsMobile_A318/image_1.png" alt="" width="230" height="125" /></p>
<p>5）看看我们的网银或是ATM的用户登录功能，如果你登录时输错口令超过3次以上，你的帐号就会被冻结，需要去柜台重置口令。这个功能看上去很安全，因为可以防止黑客在线尝试破解你的登录口令。不过这又带来了另一个问题，如果有一个恶意用户知道你的卡号，他就上网或是造个卡故意输错你的口令，导致你的帐号被冻结，让你一次又一次地去银行排队重置。面对这样的情况，你该怎么解决？</p>
<p>6）当你在网上购物的时候，你会去一些电子商务的网站，这些网站都会对他们的产品进行分类，有大分类有子分类。你进到分类后，你可以通过不同的属性来过滤不同该分类下的商品，注意，不同分类下的商品的过滤属性不一样，如，手机分类和电视分类的属性都不一样。试问，你如何设计你的数据库表结构？</p>
<p>7）当你在泡各种论坛或SNS社区的时候，你会看到，用户在互相回复的时候存在一个问题，尤其是用户量很大的时候，大家的回复完全交织在一起什么 也看不清楚。以前有的论坛使用树形列表来解决这个问题，树形列表好是好，但是把一棵大树放在那里还是很难看。Twitter.com给了一个非常不错的解决方式，就是所有人的回复或是回复的回复都按时间线放在一起，如果你要查看某回复的上下文的话，点击一下这个回复就可以看到了（我在我在“<a title="国内微博和Twitter的最大不同" href="http://coolshell.cn/articles/5247.html" target="_blank">国内微博和Twitter的最大不同</a>”中批评过这个事）。新浪微博在禁评论事件后也开发出了这个功能。你知道这个事怎么做吗？</p>
<p>更进一步，新浪微博的设计上有很多的缺陷，单说新开发的“查看评论”功能这个事来说，还是不完美，因为某些评论会随着转发带到别的地方去，他的“查看评论”功能只能看到当个贴子下的东西，不能把所有转发出去的贴子的评论一起综合起来。虽然这对于用户使用来说没有什么在不了的，但是对于软件设计来说，我们不妨做一个练习，可以思考一下，怎么样设计会更好。</p>
<p>再举一反三，有时候，我发现多个网友会提出同样的问题，我很想用一个回复同时回复他们。如果有这样的功能的话，我们的回复就会从一个树形变成另外一种形状了，我们又该如何设计才能支持这样的功能呢？</p>
<p>8）说到新浪微博，我就想多说几句，我最近观察到了两个事：</p>
<ul>
<li>一个是验证码的事，如果你在你的帐号设置里设置了“登录需要验证码”，你会发现，在登录新浪微博的时候，仅当你输对了口令后，系统才会提示你输入验证码。为什么呢？因为，这个“登录需要验证码”这绑定在你的帐号设置里的，所以，要取这个设置，就需要你登录成功（？！），老实说，这个功能在设计上有点二（中国特色）。如果是你，你怎么设计呢？</li>
</ul>
<ul>
<li>另一个事情是新浪微博或Twitter的用户名修改后，被他人@过的信息就再也链接不到你这里来了。我们来试想一下，如果是你，你怎么解决这个问题？（我的<a href="http://weibo.com/1401880315/yclT9m6Fp" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/1401880315/yclT9m6Fp?referer=');">我的微博里讨论过这个事</a>，不一定对，供大家参考）</li>
</ul>
<p>9）我有时候我会发一些快递，有时候是一些小东西，有时候是一些大包裹，有时候近，有时候远。我发现一个有趣的现象，就是快递员来收件的时候，快递的价格都是快递员自己说了算的，我还可以和他们砍价。我观察到他们会以距离，重量大小来订价。于是我在想如果你要运营一个物流公司，你作为这个物流公司的程序员，你需要开发一个软件来标注快递价格，你会怎么做？比如，这个快递公司会说，在北京五环以内是一个价，以外是一个价，出省后，上海以北是一个价，上海以南是一个价，等等，这只是北京的，如果把全国的各个城市到别的城市的价格都考虑进来，还要受到重量，体积，价格，是否加急等等因素的影响，你的数据库设计要怎么做呢？</p>
<p>A）国内的水军太恐怖了。他们活动的刷排名，刷信用，刷积分，刷粉丝等等地方，你是否想过如何解决这个问题？还有广告联盟的欺诈问题，等等。这些东西，有的还是可以通过技术手段进行限制和计算的，你有思考过应该使用什么样的方法吗？</p>
<p>B）说到水军就不能不提垃圾邮件和垃圾短信。你有没有想过邮件系统怎么过滤垃圾信息的？</p>
<p>C）关于推荐功能，这必然是一个热点，这是软件产品从request -&gt; response的被动方式到主动方式的进化。微博上有推荐关注者的功能，电商有推荐商品的功能，豆瓣上有推荐影片音乐书籍的功能。不同的领域的推荐算法各不相同，你有没有思考过，如果是你来做推荐算法的时候，你会怎么做吗？更进一步，推荐通常伴随着学习和匹配，学习用户的行为，匹配相似的东西，你想过怎么学习用户的行为，怎么匹配相似的东西了吗？</p>
<p>D）关于微博，某名人有几千万的粉丝，当这个名人发一个微博的时候，需要通知这几千万个粉丝，这个在系统架构上应该怎么做？如果某天这个名人与人发生口角，和人吵架，拼命的刷微博，那么，系统架构要怎么设计才能支持这样的事呢？</p>
<p>E）想想火车票的分段卖票的方式，现有的解决方案是为每个站点预留票，于是我们可以看到火车始发时，有很多空坐，这些空坐都是留给下一个站点的，我们能否开发出一个系统来，可以把一条线上的这些这站上那站下的旅客统筹规划一下，制定出一个最经济的方式，让火车运行得更有效。</p>
<p>F）对于地铁公交网络，我们希望这个网络既能有更多的覆盖，又能节省路线，你能不能设计出一个系统，当我们输入一些数据（如：站点，是否终点或起点站，该站的下一站可能方向（多个），该站是以上车为主，还是下车为主，等等），你的系统能自动安排出各种线路吗？</p>
<p><strong>这样的问题实在是太多了，都是可以让我们去思考的，并不一定有经济效益，但是至少可以让你锻炼一下怎么去分析问题，怎么去思考，怎么去解决问题</strong>。</p>
<h4>总结</h4>
<p>综上所述，我想说的是：</p>
<p>1） 只要你想，挑战是无处不在的。那怕是你现有的觉得无聊的东西，只要你想做到极致，那怕是一个简单的功能（比如<a title="你会做Web上的用户登录功能吗？" href="http://coolshell.cn/articles/5353.html" target="_blank">用户登录的功能</a>）也会让你充满挑战。</p>
<p>2）观察身边的事物，去思考，去调查，举一反三，这才是你成长的源泉。不要把你的成长推给客观原因。</p>
<p>3）我的<a title="软件开发的“三重门”" href="http://coolshell.cn/articles/6526.html" target="_blank">软件开发的三重门</a>中说过，第三重门是解决实际问题，让你的业务处理更为的智能，更为地强大。我不知道为什么这一两年，我们的圈子里所有的人都在关注着“云”，“海量数据处理”，“高性能架构”这样的东西，尤其是那些性能调的高性能的东西并不很难，而这些更为实际问题更有挑战性，也更有前景。</p>
<p>（全文完）</p>
<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="做个环保主义的程序员" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7186.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7048.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7186.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7048.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2012/04/27/23798602.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">做个环保主义的程序员</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="漫画：程序员的一生" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1103.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7048.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1103.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7048.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10437646.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">漫画：程序员的一生</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="惹恼程序员的十件事" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F340.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7048.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F340.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7048.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/02/12/2675402.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">惹恼程序员的十件事</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="C++ 程序员自信心曲线图" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2287.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7048.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2287.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7048.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/06/21/13670426.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">C++ 程序员自信心曲线图</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="幽默：程序员的进化" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F172.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7048.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F172.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7048.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">幽默：程序员的进化</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table><h3  class="related_post_title">相关文章</h3><ul class="related_post"><li>2012年04月27日 -- <a href="http://coolshell.cn/articles/7186.html" title="做个环保主义的程序员">做个环保主义的程序员</a></li><li>2012年04月19日 -- <a href="http://coolshell.cn/articles/7126.html" title="这到底是谁之错？">这到底是谁之错？</a></li><li>2012年04月11日 -- <a href="http://coolshell.cn/articles/6994.html" title="我们需要专职的QA吗？">我们需要专职的QA吗？</a></li><li>2012年03月09日 -- <a href="http://coolshell.cn/articles/6775.html" title="Bret Victor &#8211; Inventing on Principle">Bret Victor &#8211; Inventing on Principle</a></li><li>2012年02月21日 -- <a href="http://coolshell.cn/articles/6639.html" title="千万别惹程序员 ">千万别惹程序员 </a></li><li>2012年01月30日 -- <a href="http://coolshell.cn/articles/6526.html" title="软件开发的“三重门”">软件开发的“三重门”</a></li><li>2012年01月04日 -- <a href="http://coolshell.cn/articles/6346.html" title="程序员因为女孩而美丽！">程序员因为女孩而美丽！</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/7048.html/feed</wfw:commentRss>
		<slash:comments>90</slash:comments>
		</item>
		<item>
		<title>我们需要专职的QA吗？</title>
		<link>http://coolshell.cn/articles/6994.html</link>
		<comments>http://coolshell.cn/articles/6994.html#comments</comments>
		<pubDate>Wed, 11 Apr 2012 00:48:59 +0000</pubDate>
		<dc:creator>陈皓</dc:creator>
				<category><![CDATA[技术管理]]></category>
		<category><![CDATA[流程方法]]></category>
		<category><![CDATA[Programmer]]></category>
		<category><![CDATA[QA]]></category>
		<category><![CDATA[测试]]></category>
		<category><![CDATA[程序员]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=6994</guid>
		<description><![CDATA[这个文章必然是有争议的，我在我的微博上讨论过很多次了，每次都是很有争议的。有不同的观点，有争论总是一件好事，这样可以引发大家的思考。所以，对于我的这篇博文，如果你赞同我的观点，我会感到高兴，如果你会去认真地深入思考，我也会高兴，如果你反对，没关系，可以讨论。 在此之前，我想说明一下我观点里的这个“专职QA”是怎么定义的。 其是很多公司成立的专门做测试的技术人员，仅测试不开发。 这些QA对于软件开发技术并不熟悉，甚至不懂。 我经历过一些公司都有专职的QA团队（专职的测试人员），自从上个公司我的开发团队在一个项目上被QA部门搞得一团糟，我越来越怀疑专职QA存在在意义。我的观点不一定对，但请让我鲜明地表达一下——我觉得是不需要全职的QA的，甚至不需要QA这一专职角色或部门，因为，不懂开发的人必然做不好测试。就像不懂开发的研发经理必然管不好研发团队一样。我越来越觉得Dev应该应该是做测试最合适的人选，这必然是未来的趋势 （因为我已经看到了中国程序员的进步，相比起10年前，今天的程序员已经是非常全面了，再来十年，必然证明我的观点是对的）。 在我正在展开说明之前，我想引用两篇文章： 两篇文章 一篇是  “On testers and testing”(中文翻译)，本文的作者Sriram Krishnan是一名程序员，曾在Yahoo和微软工作过，开发过很多软件，曾被纽约时报报道，写过一本书，本文是他的一篇博客。他在文章中表达了这几个观点—— 大多数的开发团队并不需要一个独立的测试角色。即使要有，那么所有的开发时间比上所有的测试时间应该 &#62;20:1的。。证据吗？光看看一些从古至今最成功的软件开发团队就知道了。不论是当今的Facebook，还是30年前最初的NT团队，很多伟大的产品都是出自没有或很少测试人员的团队。 开发人员应该测试自己的代码。没什么可说的。背后的道理并不重要。这包括单元测试，全覆盖的自动化测试或手工测试或组合测试。如果你的开发人员不能/不愿意或认为这“不归我管”，那你需要更好的程序员。 另一篇文章是邹欣的“现代软件工程讲义 9 测试 QA 的角色和分工”，这是一篇很不错的文章。他在文章里提到了分工的必要性，比如第三方的鉴定机构，并且也指出了分工的一些问题，比如，画地为牢的分工，无明确责任的分工，等，这些问题直接命中了分工的要害。我隐约觉得，我和邹欣的很多观点是相同的，我们内容上是相同的，只是形式上还有分歧。另外，我的观点太鲜明了，从而容易导向极端的理解。 你看，我们都同意，Dev要懂测试，QA要懂开发，只不过分工不同，既然你中有我，我中有你，那就不要分彼此了，一起携手开发测试吧。（另外，我个人觉得不懂开发的测试人员不可能测试得好） &#8212;- update&#8212;- {      //本篇文章出来后，网上出现了一些对此讨论的文章，我一并更新在这里 【 《对《我们需要专职QA吗？》的回应》作者：@段念-段文韬 】 【 《关于“我们需要专职的QA吗”》作者：@Jacky郭 】 【 《我们需要专职的QA吗？（评）》作者：@Monkey陳曄曄 】 【《 《我们需要专职的QA吗？》读后感》作者：@ 花生色魔叔】 } 我的故事 我再说说我最糟糕的QA经历吧，这个公司的QA部门只做测试，他们的leader觉得所有的test design和test 的过程都不需要Dev参与，他们是独立于Dev之外的部门，他们几乎不关心Dev的设计和实现，他们只关心能跑通他们自己设计的test case。但是去执行Test Case的时候，又需要Dev的支持，尤其在环境设置，测试工具使用，确认是否是bug方面，全都在消耗着Dev的资源，最扯的是，他们对任何线上的问题不负责，反正出了问题由Dev加班搞定。 我有一次私自review他们的test case的时候，发现很多的test case这样写到 &#8211; “Expected Result：Make sure every thing is [...]<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="我们需要专职的QA吗？ | 酷壳 - CoolShell.cn" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6994.html%2Fcomment-page-2&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6994.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6994.html_2Fcomment-page-2_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6994.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">我们需要专职的QA吗？ | 酷壳 - CoolShell.cn</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="惹恼程序员的十件事" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F340.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6994.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F340.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6994.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/02/12/2675402.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">惹恼程序员的十件事</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="做个环保主义的程序员" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7186.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6994.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7186.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6994.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2012/04/27/23798602.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">做个环保主义的程序员</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="程序员的八个级别" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F343.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6994.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F343.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6994.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10437645.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">程序员的八个级别</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="C++ 程序员自信心曲线图" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2287.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6994.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2287.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6994.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/06/21/13670426.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">C++ 程序员自信心曲线图</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table>]]></description>
			<content:encoded><![CDATA[<p>这个文章必然是有争议的，我在我的<a href="http://coolshell.cn/" target="_blank">微博</a>上讨论过很多次了，每次都是很有争议的。有不同的观点，有争论总是一件好事，这样可以引发大家的思考。所以，对于我的这篇博文，如果你赞同我的观点，我会感到高兴，如果你会去认真地深入思考，我也会高兴，如果你反对，没关系，可以讨论。</p>
<p>在此之前，我想说明一下我观点里的这个“专职QA”是怎么定义的。</p>
<ol>
<li>其是很多公司成立的专门做测试的技术人员，仅测试不开发。</li>
<li>这些QA对于软件开发技术并不熟悉，甚至不懂。</li>
</ol>
<p>我经历过一些公司都有专职的QA团队（专职的测试人员），自从上个公司我的开发团队在一个项目上被QA部门搞得一团糟，我越来越怀疑专职QA存在在意义。我的观点不一定对，但请让我鲜明地表达一下——<strong>我觉得是不需要全职的QA的，甚至不需要QA这一专职角色或部门，因为，不懂开发的人必然做不好测试。就像不懂开发的研发经理必然管不好研发团队一样。</strong>我越来越觉得Dev应该应该是做测试最合适的人选，这必然是未来的趋势 （因为我已经看到了中国程序员的进步，相比起10年前，今天的程序员已经是非常全面了，再来十年，必然证明我的观点是对的）。</p>
<p>在我正在展开说明之前，我想引用两篇文章：</p>
<h4>两篇文章</h4>
<p>一篇是  “<a href="http://sriramk.com/blog/2012/01/testing.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/sriramk.com/blog/2012/01/testing.html?referer=');">On testers and testing</a>”(<a href="http://www.aqee.net/on-testers-and-testing/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.aqee.net/on-testers-and-testing/?referer=');">中文翻译</a>)，本文的作者Sriram Krishnan是一名程序员，曾在Yahoo和微软工作过，开发过很多软件，曾被纽约时报<a href="http://www.nytimes.com/2011/02/27/business/27novel.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.nytimes.com/2011/02/27/business/27novel.html?referer=');">报道</a>，写过<a href="http://amzn.to/progazure" target="_blank" onclick="pageTracker._trackPageview('/outgoing/amzn.to/progazure?referer=');">一本书</a>，本文是他的一篇博客。他在文章中表达了这几个观点——</p>
<blockquote><p>大多数的开发团队并不需要一个独立的测试角色。即使要有，那么所有的开发时间比上所有的测试时间应该 &gt;20:1的。。证据吗？光看看一些从古至今最成功的软件开发团队就知道了。不论是当今的Facebook，还是30年前最初的NT团队，很多伟大的产品都是出自没有或很少测试人员的团队。</p>
<p>开发人员应该测试自己的代码。没什么可说的。背后的道理并不重要。这包括单元测试，全覆盖的自动化测试或手工测试或组合测试。如果你的开发人员不能/不愿意或认为这“不归我管”，那你需要更好的程序员。</p></blockquote>
<p>另一篇文章是邹欣的“<a id="cb_post_title_url" href="http://www.cnblogs.com/xinz/archive/2012/04/09/2439695.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.cnblogs.com/xinz/archive/2012/04/09/2439695.html?referer=');">现代软件工程讲义 9 测试 QA 的角色和分工</a>”，这是一篇很不错的文章。他在文章里提到了分工的必要性，比如第三方的鉴定机构，<strong>并且也指出了分工的一些问题，比如，画地为牢的分工，无明确责任的分工，等，这些问题直接命中了分工的要害</strong>。我隐约觉得，我和邹欣的很多观点是相同的，我们内容上是相同的，只是形式上还有分歧。另外，我的观点太鲜明了，从而容易导向极端的理解。</p>
<p>你看，<strong>我们都同意，Dev要懂测试，QA要懂开发，只不过分工不同，既然你中有我，我中有你，那就不要分彼此了，一起携手开发测试吧</strong>。（另外，我个人觉得不懂开发的测试人员不可能测试得好）</p>
<p><em><strong>&#8212;- update&#8212;- </strong></em>{</p>
<p><span style="color: #008000;">     //本篇文章出来后，网上出现了一些对此讨论的文章，我一并更新在这里</span><br />
【 《<a id="cb_post_title_url" href="http://www.cnblogs.com/guanhe/archive/2012/04/12/response_to_do_we_need_qa.html" onclick="pageTracker._trackPageview('/outgoing/www.cnblogs.com/guanhe/archive/2012/04/12/response_to_do_we_need_qa.html?referer=');">对《我们需要专职QA吗？》的回应</a>》作者：<a href="http://weibo.com/n/%E6%AE%B5%E5%BF%B5-%E6%AE%B5%E6%96%87%E9%9F%AC" onclick="pageTracker._trackPageview('/outgoing/weibo.com/n/_E6_AE_B5_E5_BF_B5-_E6_AE_B5_E6_96_87_E9_9F_AC?referer=');">@段念-段文韬</a> 】<br />
【 《<a href="http://blog.sina.com.cn/s/blog_55ba8b460100yawe.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/blog.sina.com.cn/s/blog_55ba8b460100yawe.html?referer=');">关于“我们需要专职的QA吗”》</a>作者：<a href="http://weibo.com/u/1764108363" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/u/1764108363?referer=');">@Jacky郭</a> 】<br />
【 《<a href="http://blog.sina.com.cn/s/blog_7022adbf0100zgqo.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/blog.sina.com.cn/s/blog_7022adbf0100zgqo.html?referer=');">我们需要专职的QA吗？（评）</a>》作者：@<a title="Monkey陳曄曄" href="http://weibo.com/aiwanglinjun" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/aiwanglinjun?referer=');">Monkey陳曄曄</a> 】<br />
【《 <a id="blog-title-link" href="http://thinkcool.weebly.com/1/post/2012/04/qa.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/thinkcool.weebly.com/1/post/2012/04/qa.html?referer=');">《我们需要专职的QA吗？》读后感</a>》作者：@ <a title="花生色魔叔" href="http://weibo.com/bluesgu" onclick="pageTracker._trackPageview('/outgoing/weibo.com/bluesgu?referer=');">花生色魔叔</a>】</p>
<p>}</p>
<p><span id="more-6994"></span></p>
<h4>我的故事</h4>
<p>我再说说我最糟糕的QA经历吧，这个公司的QA部门只做测试，他们的leader觉得所有的test design和test 的过程都不需要Dev参与，他们是独立于Dev之外的部门，他们几乎不关心Dev的设计和实现，他们只关心能跑通他们自己设计的test case。但是去执行Test Case的时候，又需要Dev的支持，尤其在环境设置，测试工具使用，确认是否是bug方面，全都在消耗着Dev的资源，最扯的是，他们对任何线上的问题不负责，反正出了问题由Dev加班搞定。</p>
<p>我有一次私自review他们的test case的时候，发现很多的test case这样写到 &#8211; “Expected Result：Make sure every thing is fine” ，WTF，什么叫“Every thing is fine”？！而在test case design的时候，没有说明test environment/configuration 是什么？没有说明test data在哪里？Test Case、Test Data、Test Configuration都没有版本控制，还有很多Test Case设计得非常冗余（多个Test Case只测试了一个功能），不懂得分析Function Point就做Test Design。另外，我不知道他们为什么那么热衷于设计一堆各式各样的Negative Test Case，而有很多Positive的Test Case没有覆盖到。为什么呢，因为他们不知道开发和设计的细节，所以没有办法设计出Effective的Test Case，只能从需求和表面上做黑盒。</p>
<p>在做性能测试的时候，需要Dev手把手的教怎么做性能测试，如何找到系统性能极限，如何测试系统的latency，如何观察系统的负载（CPU，内存，网络带宽，磁盘和网卡I/O，内存换页……）如何做Soak Test，如何观察各个线程的资源使用情况，如何通过配置网络交换机来模拟各种网络错误，等等，等等。</p>
<p>测试做得也不认真，大量的False Alarm，都是环境问题，比如：安装新版本后没有重启服务，没有使用新的配置文件，网络配置，等等，等等。</p>
<p>在项目快要上线前的一周，我又私自查看了一下他们的Test Result，我看到5天的Soak Test 的内存使用一直往上涨，很明显的内存泄露，这个情况发生在2个月前，但是一直都没有报告，我只好和我的程序员每天都加班到凌晨，赶在上线前解决了这个问题。但是，QA部门的同学们就像没发生什么事似的，依然正常上下班。哎……</p>
<p>为什么会这样？我觉得有这么几点原因（和邹欣的观点一样）</p>
<ol>
<li>给了QA全部测试的权力，但是没有给相应的责任，</li>
<li>QA没有体会过软件质量出问题后的痛苦（解决线上问题的压力），导致QA不会主动思考和改进。</li>
<li>QA对Dev的开发过程和技术完全不了解，增加了很多QA和Dev的沟通。</li>
<li>QA对软件项目的设计和实现要点不了解，导致了很多不有效的测试。</li>
</ol>
<p><span style="color: #cc0000;"><strong>注：我无意在这里贬低QA的能力工作。只是我看到了QA因为没有参与开发的一些现实问题。</strong></span></p>
<h4>我的观点</h4>
<p>邹欣对于分工出现的问题给出了两点解决方法：</p>
<blockquote>
<ul>
<li>充分授权和信任（Empower team members）</li>
<li>各司其职，对项目共同负责（Establish clear accountability and shared responsibility）</li>
</ul>
</blockquote>
<div>我的观点是，<strong>理论上正确，操作上太虚了。这就像我们国家喊的“为人民服务”的口号一样，没有具体的方法，根本无法落实。</strong></div>
<p>我无意在这里贬低QA的工作，我也无意因为这个事走向另一个极端。但是，我在现在公司的经历，还有很多新兴公司的做法，<span style="color: #cc0000;"><strong>我越来越觉得软件开发，真的不需要专职的QA，更不需要只写代码不懂做测试的专职的Dev</strong></span>。观点如下：</p>
<p><strong>1）</strong> <strong>开发人员做测试更有效</strong></p>
<ul>
<li>开发人员本来就要测试自己写的软件，如果开发人员不懂测试，或是对测试不专业，那么这就不是一个专业的开发人员。</li>
<li>开发人员了解整个软件的设计和开发过程，开发人员是最清楚应该怎么测试的，这包括单元测试，功能测试，性能测试，回归测试，以及Soak Test 等。</li>
<li>开发人员知道怎么测试是最有效的。开发人员知道所有的function point，知道fix一个bug后，哪些测试要做回归和验证，哪些不需要。开发人员的技术能力知道怎么才能更好的做测试。</li>
</ul>
<p>很多开发人员只喜欢写代码，不喜欢做测试，或是他们说，开发人员应该关注于开发，而不是测试。这个思路相当的错误。开发人员最应该关注的是软件质量，需要证明自己的开发成果的质量。<strong>开发人员如果都不知道怎么做测试，这个开发人员就是一个不合格的开发人员</strong>。</p>
<p>另外，<strong>我始终不明白，为什么不做开发的QA会比Dev在测试上更专业？ 这一点都说不通啊</strong>。</p>
<p><strong>2）减少沟通，扯皮，和推诿</strong></p>
<p>想想下面的这些情况你是否似曾相识？</p>
<ul>
<li>QA 做的测试计划，测试案例设计，测试结果，总是需要Dev来评审和检查。</li>
<li>QA在做测试的过程中，总是需要Dev对其测试的环境，配置，过程做指导。</li>
<li>QA总是会和Dev争吵某个问题是不是BUG，争吵要不要解决。</li>
<li>无论发现什么样的问题，总是Dev去解决，QA从不fix问题。</li>
<li>我们总是能听到，线上发生问题的时候，Dev的抱怨QA这样的问题居然没测出来，</li>
<li>QA也总会抱怨Dev代码太差，一点也不懂测试，没怎么测就给hand over 给QA了。</li>
<li>QA总是会push Dev，这个bug再不fix，你就影响我的进度了。</li>
<li>等等，等等。</li>
</ul>
<p>如果没有QA，那么就没有这么多事了，DEV自己的干出来的问题，自己处理，没什么好扯皮的。</p>
<p>而一方面，QA说Dev不懂测试，另一方面Dev说QA不懂技术，而我们还要让他们隔离开来，各干各的，这一点都不利于把Dev和QA的代沟给填平了。<strong>要让Dev理解QA，让QA理解Dev，减少公说公有理，婆说婆有理的只站在自己立场上的沟通，只有一个方法，那就是让Dev来做测试，让QA来做开发</strong>。这样一样，大家都是程序员了。</p>
<p><strong>3）吃自己的狗食</strong></p>
<p>真的优秀的开发团队都是要吃自己狗食的。这句话的意思是——<strong>如果你不能切身体会到自己干的烂事，自己的痛苦，你就不会有想要去改进的动机</strong>。<strong>没有痛苦，就不会真正地去思考，没有真正的思考，就没有真正的进步</strong>。</p>
<p>在我现在的公司，程序员要干几乎有的事，从需求分析，设计，编码，集成，测试，部署，运维，OnCall，从头到尾，因为：</p>
<ul>
<li>只有了解了测试的难度，你才明白怎么写出可测试的软件，怎么去做测试的自动化和测试系统。</li>
<li>只有自己真正去运维自己的系统，你才知道怎么在程序里写日志，做监控，做统计……</li>
<li>只有自己去使用自己的系统，你才明白用户的反馈，用户的想法，和用户的需求。</li>
</ul>
<p>所以，<strong>真正的工程师是能真正明白软件开发不单单只是coding，还更要明白整个软件工程</strong>。只明白或是只喜欢coding的，那只是码农，不能称之为工程师。</p>
<p><strong>4）其它问题</strong></p>
<ul>
<li><strong>关于SDET</strong>。全称是Software Development Engineer on Test。像微软，Google， Amazon都有这样的职位。但我不知道这样的职位在微软和Google的比例是多少，在Amazon是非常少的。那么像这样的懂开发的专职测试可以有吗？我的答案是可以有！但是，我在想，<strong>如果一个人懂开发，为什么只让其专职做测试呢？这样的程序员分工合理吗？把程序员分成两等公民有意义吗？试问有多少懂开发的程序员愿意只做测试开发呢？</strong>所以，SDET在实际的操作中，更多的还是对开发不熟的测试人员。还是哪句话，不懂开发的人是做不好测试的。</li>
</ul>
<ul>
<li><strong>如果你说Dev对测试不专业，不细心，不认真</strong>，那么我们同样也无法保证QA的专业，细心和认真。在Dev上可能出现的问题，在QA也也会一样出现。而出了问题QA不会来加班解决，还是开发人员自己解决。所以，如果QA不用来解决问题，那么，QA怎么可能真正的细心和认真呢？</li>
</ul>
<ul>
<li><strong>如果你说不要QA的话，Dev人手会不够</strong>。你这样想一下，如果把你团队中现有的QA全部变成Dev，然后，大家一起开发，一起测试，亲密无间，沟通方便，你会不会觉得这样会更有效？你有没有发现，在重大问题上，Dev可以帮上QA的忙，但是QA帮不上Dev的忙。</li>
</ul>
<ul>
<li><strong>第三方中立，你会说人总是测不好自己写的东西，因为有思维定式</strong>。没错，我同意。但是如果是Dev交叉测试呢？你可能会说开发人员会有开发人员的思维定式。那这只能说明开发人员还不成熟，他们还不合格。没关系，只要吃自己的狗食，痛苦了，就会负责的。</li>
</ul>
<ul>
<li><strong>磨刀不误砍柴功</strong>。如果你开发的东西自己在用，那么自己就是自己天然的QA，如果有别的团队也在用你开发的模块，那么，别的团队也就很自然地在帮你做测试了，而且是最真实的测试。</li>
</ul>
<ul>
<li><strong>你可能会说吃狗食就是个笑话，因为如果是我，我把事干烂后，就离职走人了，让别人去吃我的狗食</strong>。这个在现实中的确会发生，也是很现实的。但是想一想，你为什么在一开始让他把事干烂了？另外，如果你的团队在设计评审和代码评审里没有把好关，让某人把事给干烂了，那么这个人的离职带来的问题还是这个团队来扛，于是整个团队都在吃自己的狗食，挺公平的。痛苦过一次，你的团队下次怎么干了，就不敢乱招人了，就不敢随意评审代码了，就不敢让人只做一块东西了。最终还是没有逃脱吃狗食的范畴。</li>
</ul>
<ul>
<li><strong>关于系统集成测试。</strong>所谓集成测试，就是把多个开发团队开发的模块集中起来测试。因为开发人员可能无法看到全局，不了解别个团队的系统，而且步调不一，所以需要有统管全局的专职的QA进行统筹规划并做测试。对这个方面，我并不反对，在实际操作过程中，好像的确用专职的做集成测试的QA统一调度各团队的时度更有效一些。不过，这还是不能让我停止去思考两个问题，1) 如果开发人员看不到全局，他能开发出更好的软件吗？2）这个全职的做集成测试的QA难道不能是各个团队的骨干Dev来组成吗？3）统一调度这个事，不更像是Project Manager要做的事吗？</li>
</ul>
<ul>
<li><strong>关于自动化测试</strong>。所谓自动化的意思是，这是一个机械的重复劳动。我想让测试人员思考一下，你是否在干这样的事？如果你正在干这样的事，那么，你要思考一下你的价值了。但凡是重复性比较高的机械性的劳动，总有一天都会被机器取代的。</li>
</ul>
<ul>
<li><strong>关于线上测试</strong>。我们都知道，无论自己内测的怎么样，到了用户那边，总是会有一些测试不到的东西。所以，有些公司会整出个UAT，用户验收测试。做产品的公司会叫Beta测试。无论怎么样，你总是要上生产线做真正测试的。对于互联网企业来说，生产线上测试有的在玩A/B测试，有的玩部分用户测试，比如，新上线的功能只有10%的用户可以访问得到，这样不会因为出问题让全部用户受到影响。做这种测试系统的人必然是开发人员。</li>
</ul>
<p>好吧，我暂时写这么多，我会视大家的讨论再补充我的观点的。</p>
<p><em><strong>&#8212;&#8211; update  2012/4/11&#8212;&#8211;</strong></em></p>
<p>一些人觉得我是在泄私愤，我能够理解为什么我会被这样误解，但是没有关系，很多新东西新观点总是会被误解的，我坦然面对。请大家抛开我的这些情感因素，单纯的思考一下，没有专职QA的的团队架构是否有积极的意义在里面？</p>
<p><strong>再补充一点，大家思考一下，QA是保证质量的，但是很多QA是在做测试，软件质量是测试出来的吗？如果不从需求分析，软件设计，代码实现上做好控制，到测试的时候你还怎么保证质量呢？</strong></p>
<p>（全文完）</p>
<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="我们需要专职的QA吗？ | 酷壳 - CoolShell.cn" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6994.html%2Fcomment-page-2&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6994.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6994.html_2Fcomment-page-2_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6994.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">我们需要专职的QA吗？ | 酷壳 - CoolShell.cn</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="惹恼程序员的十件事" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F340.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6994.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F340.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6994.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/02/12/2675402.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">惹恼程序员的十件事</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="做个环保主义的程序员" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7186.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6994.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7186.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6994.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2012/04/27/23798602.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">做个环保主义的程序员</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="程序员的八个级别" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F343.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6994.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F343.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6994.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10437645.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">程序员的八个级别</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="C++ 程序员自信心曲线图" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2287.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6994.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2287.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6994.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/06/21/13670426.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">C++ 程序员自信心曲线图</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table><h3  class="related_post_title">相关文章</h3><ul class="related_post"><li>2012年04月27日 -- <a href="http://coolshell.cn/articles/7186.html" title="做个环保主义的程序员">做个环保主义的程序员</a></li><li>2012年04月19日 -- <a href="http://coolshell.cn/articles/7126.html" title="这到底是谁之错？">这到底是谁之错？</a></li><li>2012年04月17日 -- <a href="http://coolshell.cn/articles/7048.html" title="挑战无处不在">挑战无处不在</a></li><li>2012年03月09日 -- <a href="http://coolshell.cn/articles/6775.html" title="Bret Victor &#8211; Inventing on Principle">Bret Victor &#8211; Inventing on Principle</a></li><li>2012年02月21日 -- <a href="http://coolshell.cn/articles/6639.html" title="千万别惹程序员 ">千万别惹程序员 </a></li><li>2012年01月30日 -- <a href="http://coolshell.cn/articles/6526.html" title="软件开发的“三重门”">软件开发的“三重门”</a></li><li>2012年01月04日 -- <a href="http://coolshell.cn/articles/6346.html" title="程序员因为女孩而美丽！">程序员因为女孩而美丽！</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/6994.html/feed</wfw:commentRss>
		<slash:comments>143</slash:comments>
		</item>
		<item>
		<title>谈谈数据安全和云存储</title>
		<link>http://coolshell.cn/articles/6976.html</link>
		<comments>http://coolshell.cn/articles/6976.html#comments</comments>
		<pubDate>Mon, 09 Apr 2012 00:33:22 +0000</pubDate>
		<dc:creator>陈皓</dc:creator>
				<category><![CDATA[业界新闻]]></category>
		<category><![CDATA[杂项资源]]></category>
		<category><![CDATA[网络安全]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[安全]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=6976</guid>
		<description><![CDATA[前些天，创新工场李开复同学在2012博鳌亚洲论坛表示： “你们有多少人丢过手机？大概有15%。你们有多少人数据放在微软掉过的？我想不见得很多吧。所以相对来说是安全的。放在大公司里比自己拿着掉的概率更大，你不相信的话，可以问陈冠希先生。” 两种安全 看到这个消息的时候，我觉得李开复同学混淆了云存储和安全这两个概念，在英文里，有两个单词，一个是Safe，一个是Security，很不幸的是，这两个英文单词翻译成中文都叫“安全”，因此总是被混淆，熟知英文又熟悉IT业的李开复同学在这个句子中混淆了这“两种安全”，我在我的微博上指出来后，居然还有很多网友继续混淆这两点，所以，这让我产生了写篇博文的说明一下，并顺着说说云存储和数据安全的个人理解。 所谓Safe，也就是数据不丢失的意思。这是目前云存储解决的问题，你可以把你的数据放在云端，你的所有的终端设备都可以通过云端来共享同步你的数据，这样，云端就成了你数据同步和备份的数据中枢。说得专业一点，这又叫Availability，中文叫可用性，意思是，你的数据总是可用的，基本不会丢失 ， 所谓Security，也就是数据的隐私和不泄露。这就是德艺双馨的陈冠希老师的痛，因为本来隐私和机密的数据被泄露出去了。就目前而言，我看到的云存储解决的都是Availability，而不是Security。Security解决的是私密和不泄露的问题。所以，李开复同学要让陈冠希老师把他的那些数据存到云端是可笑的，对于那些私密照片，我相信陈冠希老师要求的是“Security”，而不是“Availability”。 有网友在我的微博上指出：”一种数据是不能丢，但是可以泄露，那可以放云端，另一种是宁可丢都不能泄露，这就不能放在云端了”。这句话可以帮你更好地理解什么是Availability和Security。 Security &#8211; 本地 vs 云端 现在的云解决的更多的是不丢失，而不是不泄漏。有一些网友在微博上和我争论道，其实云存储也能保证Security，因为有加密认证，云端会加密数据。我对此存有不同意见，对于Security，我个人更觉得，Security的数据应该完全私有化，所以，放在本地会有更好的Security。我的理由如下： 先问你自己一个问题，无论是不是大公司的云服务，你敢把你的银行帐号和口令存在云端吗？你的银行帐号和口令你可能都不敢放在你的电脑里。因为你要找到一个完全绝对只有你能访问的地方。比如说你的大脑。 云端的认证和云端的数据加密有用吗？没有用的，因为我只要破解了这个用户口令，想想你的电脑成了肉鸡，你网盘的口令都不要，你云端的数据一下都成了浮云了。想想去年年底各大网站的口令泄露吧。 数据存放在本地的移动硬盘上时，只有你的电脑同时插着USB链接线了上网线时，别人才有机会入侵，一旦你发现入侵，你还可以拔线。而你的数据放在云端，黑客可以全天候地入侵你的云端数据，得手后你都不知道你自己的帐号被黑了。 无论是云端或是本地都防不住你的客户端被肉鸡，而云端还要面对比本地更多的风险，比如，云端无良员工，云端的代码漏洞，云端的黑客入侵，还有电邮电话诈骗，钓鱼网站，DNS劫持，政府审查，等等，等等。 看看银行和金融行业，完全是自己的专用网络，和互联网物理隔绝，这就是为了Security。Security就必需是完全绝对的对数据的私有化。比如某些公司的电脑不能使用USB，光驱等等外设，所有内网与外网的数据交换都必需受到监控。 再多说一点，其实，要黑你的云端帐号并不用很高深的技术，有调查表明，伪装成客服人员或是警察给你打个电话问你要口令，大多数人是会告诉自己的帐号和口令的。还有就是抓住人的占便宜的心理，比如：在大街上撒U盘，大多数人是会捡回去插在自己或公司的电脑上浏览里面的内容的。 所以，所谓物理隔绝不单单只是网线，还有这些外设。 Availability &#8211; 本地 vs 云端 硬盘是有寿命的，如果你不间断开机，你的硬盘估计也就能支持5年左右。光盘也是有寿命，因为是塑料也会老化的，和存放的条件有关。所以，在本地看来，数据总是容易丢失的。因为我们本地的存储设备并不可靠，只是家用级的，不是工业级的。 云存储可以使用RAID之类的家庭里用不到的技术来镜像数据等技术手机，从而可以保证可用性很高，所以，放在云端的数据库可用性会更高一些（当然，就像开复老师说的一样还是要大公司才靠谱）。 再多说一点，现在很多云存储仅仅只是做简单的和客户端本地的数据同步，没有版本控制，这意味着，如果你本地的文件本来是好的，但是后来你的电脑中了病毒后，你本地的数据被损坏了，不幸的是，这些被损坏的数据也同步到了云端，并分发到了你所有的终端设备中，于是灾难还是一样发生。所以，不支持版本控制，或是更轻量一些的“数据快照”功能的云，其实其数据并不Safe。 家庭私有云存储 云存储，对于PC用户来说，就目前而言，最多的应用还是那些各种各样的Dropbox类的网盘应用，这些应用很好地解决了数据的——备份、同步、共享这三个问题。但是，我觉得还是有一些如下问题没有解决。 Security问题。就是陈冠希老师的数据私密性的问题。 费用问题。相对于本地的存储来说，网盘费用太高了，还是一月或一年的算，Dropbox 100GB的网盘要200USD一年，这够买两个1TB的硬盘了，而且绝对可以用超过1年以上。 备份效率问题。通过网络备份，同步和共享，对于数据量大一点，效率太差了。 我不知道大家怎么样？我现在更多的数据备份是我的一些家庭照片和视频，随着现在的数码相机的像素越来越高，一张照片的大小可以在4MB甚至10M，数据量太大了。而且，这些照片都个人的照片，不能传到网上做备份。每次在我的SD卡，PC，移动硬盘，iPad，手机上倒腾这些照片和视频的时候，总是很麻烦。（我昨晚在微博上做了个小调查，发现很多人家里是有很多设备的，像我这样，家里有3个本，2个台式机，2个kindle，1个iPad，2个智能手机，1个高清播放机的家庭都算是比较节俭的了） 我觉得就目前这样的情况，个人家庭的私有云解决方案应该要出现了。也就是家庭内的数据中心解决方案，也许只需要像高清播放机那样的一个小盒子，里面可以用软件RAID两块或多块硬盘以保证数据的可用性，其还可以让你的数据在N多设备中共享，同步，备份，但你又不用担心互联网安全来担心这些数据，因为这仅仅是你的家庭局域网。 因为小孩让家庭照片和视频暴增，导致我去年就在想应该有一个家庭私有网盘的东西，所以，当我前些天看到Space Monkey （新闻报道）的时候，我立马就觉得这就是我想要的东西。 不过，国内还没有相应的产品，有想法的同学不妨试试去做一个类似于这样的产品，动作要快，千万不要让创新工场和腾讯抢先了。;-) （全文完） 相关文章2012年01月06日 -- Hash Collision DoS 问题2011年12月22日 -- CSDN明文口令泄露的启示2011年12月07日 -- Web开发中需要了解的东西2011年11月28日 -- 如何设计“找回用户帐号”功能2011年11月25日 -- 腾讯帐号申诉的用户体验2011年08月25日 [...]<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="微软的安全补丁分析" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2305.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6976.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2305.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6976.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/06/21/13642093.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">微软的安全补丁分析</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="HTML 安全列表" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2416.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6976.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2416.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6976.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">HTML 安全列表</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="CSDN明文口令泄露的启示" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6193.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6976.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6193.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6976.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/12/22/12873627.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">CSDN明文口令泄露的启示</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="如何管理并设计你的口令" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2428.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6976.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2428.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6976.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">如何管理并设计你的口令</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Web开发中需要了解的东西" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6043.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6976.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6043.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6976.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Web开发中需要了解的东西</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table>]]></description>
			<content:encoded><![CDATA[<p>前些天，创新工场李开复同学<a title="李开复：数据存在大公司比身边安全 不信问陈冠希" href="http://weibo.com/1197161814/ycNUWw7hz" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/1197161814/ycNUWw7hz?referer=');">在2012博鳌亚洲论坛表示</a>：</p>
<blockquote><p>“你们有多少人丢过手机？大概有15%。你们有多少人数据放在微软掉过的？我想不见得很多吧。所以相对来说是安全的。<strong>放在大公司里比自己拿着掉的概率更大，你不相信的话，可以问陈冠希先生。</strong>”</p></blockquote>
<p><img class="aligncenter" src="http://ww4.sinaimg.cn/bmiddle/61e04755jw1drlo96bsktj.jpg" alt="" width="440" /></p>
<h4>两种安全</h4>
<p>看到这个消息的时候，我觉得李开复同学混淆了云存储和安全这两个概念，在英文里，有两个单词，<strong>一个是Safe，一个是Security，很不幸的是，这两个英文单词翻译成中文都叫“安全”</strong>，因此总是被混淆，熟知英文又熟悉IT业的李开复同学在这个句子中混淆了这“两种安全”，我在<a href="http://weibo.com/haoel" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/haoel?referer=');">我的微博</a>上指出来后，居然还有很多网友继续混淆这两点，所以，这让我产生了写篇博文的说明一下，并顺着说说云存储和数据安全的个人理解。</p>
<p><span id="more-6976"></span></p>
<ul>
<li><strong>所谓Safe，也就是数据不丢失的意思。</strong>这是目前云存储解决的问题，你可以把你的数据放在云端，你的所有的终端设备都可以通过云端来共享同步你的数据，这样，<strong>云端就成了你数据同步和备份的数据中枢</strong>。<strong>说得专业一点，这又叫Availability</strong>，中文叫可用性，意思是，你的数据总是可用的，基本不会丢失 ，</li>
</ul>
<ul>
<li><strong>所谓Security，也就是数据的隐私和不泄露</strong>。这就是德艺双馨的陈冠希老师的痛，因为本来隐私和机密的数据被泄露出去了。就目前而言，我看到的云存储解决的都是Availability，而不是Security。Security解决的是私密和不泄露的问题。所以，李开复同学要让陈冠希老师把他的那些数据存到云端是可笑的，<strong>对于那些私密照片，我相信陈冠希老师要求的是“Security”，而不是“Availability”</strong>。</li>
</ul>
<p>有网友在我的微博上指出：”一种数据是不能丢，但是可以泄露，那可以放云端，另一种是宁可丢都不能泄露，这就不能放在云端了”。这句话可以帮你更好地理解什么是Availability和Security。</p>
<h4>Security &#8211; 本地 vs 云端</h4>
<p>现在的云解决的更多的是不丢失，而不是不泄漏。有一些网友在微博上和我争论道，其实云存储也能保证Security，因为有加密认证，云端会加密数据。我对此存有不同意见，<strong>对于Security，我个人更觉得，Security的数据应该完全私有化，所以，放在本地会有更好的Security</strong>。我的理由如下：</p>
<ul>
<li>先问你自己一个问题，无论是不是大公司的云服务，你敢把你的银行帐号和口令存在云端吗？你的银行帐号和口令你可能都不敢放在你的电脑里。因为你要找到一个完全绝对只有你能访问的地方。比如说你的大脑。</li>
</ul>
<ul>
<li>云端的认证和云端的数据加密有用吗？没有用的，因为我只要破解了这个用户口令，想想你的电脑成了肉鸡，你网盘的口令都不要，你云端的数据一下都成了浮云了。想想去年年底各大网站的口令泄露吧。</li>
</ul>
<ul>
<li>数据存放在本地的移动硬盘上时，只有你的电脑同时插着USB链接线了上网线时，别人才有机会入侵，一旦你发现入侵，你还可以拔线。而你的数据放在云端，黑客可以全天候地入侵你的云端数据，得手后你都不知道你自己的帐号被黑了。</li>
</ul>
<ul>
<li>无论是云端或是本地都防不住你的客户端被肉鸡，而云端还要面对比本地更多的风险，比如，云端无良员工，云端的代码漏洞，云端的黑客入侵，还有电邮电话诈骗，钓鱼网站，DNS劫持，政府审查，等等，等等。</li>
</ul>
<p>看看银行和金融行业，完全是自己的专用网络，和互联网物理隔绝，这就是为了Security。Security就必需是完全绝对的对数据的私有化。比如某些公司的电脑不能使用USB，光驱等等外设，所有内网与外网的数据交换都必需受到监控。</p>
<p>再多说一点，其实，要黑你的云端帐号并不用很高深的技术，有调查表明，伪装成客服人员或是警察给你打个电话问你要口令，大多数人是会告诉自己的帐号和口令的。还有就是抓住人的占便宜的心理，比如：在大街上撒U盘，大多数人是会捡回去插在自己或公司的电脑上浏览里面的内容的。</p>
<p>所以，所谓物理隔绝不单单只是网线，还有这些外设。</p>
<h4>Availability &#8211; 本地 vs 云端</h4>
<p>硬盘是有寿命的，如果你不间断开机，你的硬盘估计也就能支持5年左右。光盘也是有寿命，因为是塑料也会老化的，和存放的条件有关。所以，在本地看来，数据总是容易丢失的。因为我们本地的存储设备并不可靠，只是家用级的，不是工业级的。</p>
<p>云存储可以使用RAID之类的家庭里用不到的技术来镜像数据等技术手机，从而可以保证可用性很高，所以，放在云端的数据库可用性会更高一些（当然，就像开复老师说的一样还是要大公司才靠谱）。</p>
<p>再多说一点，现在很多云存储仅仅只是做简单的和客户端本地的数据同步，没有版本控制，这意味着，如果你本地的文件本来是好的，但是后来你的电脑中了病毒后，你本地的数据被损坏了，不幸的是，这些被损坏的数据也同步到了云端，并分发到了你所有的终端设备中，于是灾难还是一样发生。所以，不支持版本控制，或是更轻量一些的“数据快照”功能的云，其实其数据并不Safe。</p>
<h4>家庭私有云存储</h4>
<p>云存储，对于PC用户来说，就目前而言，最多的应用还是那些各种各样的Dropbox类的网盘应用，这些应用很好地解决了数据的——备份、同步、共享这三个问题。但是，我觉得还是有一些如下问题没有解决。</p>
<ul>
<li>Security问题。就是陈冠希老师的数据私密性的问题。</li>
<li>费用问题。相对于本地的存储来说，网盘费用太高了，还是一月或一年的算，Dropbox 100GB的网盘要200USD一年，这够买两个1TB的硬盘了，而且绝对可以用超过1年以上。</li>
<li>备份效率问题。通过网络备份，同步和共享，对于数据量大一点，效率太差了。</li>
</ul>
<p>我不知道大家怎么样？我现在更多的数据备份是我的一些家庭照片和视频，随着现在的数码相机的像素越来越高，一张照片的大小可以在4MB甚至10M，数据量太大了。而且，这些照片都个人的照片，不能传到网上做备份。每次在我的SD卡，PC，移动硬盘，iPad，手机上倒腾这些照片和视频的时候，总是很麻烦。（我昨晚在微博上<a href="http://weibo.com/1401880315/ydGN1zXGz" onclick="pageTracker._trackPageview('/outgoing/weibo.com/1401880315/ydGN1zXGz?referer=');">做了个小调查</a>，发现很多人家里是有很多设备的，像我这样，家里有3个本，2个台式机，2个kindle，1个iPad，2个智能手机，1个高清播放机的家庭都算是比较节俭的了）</p>
<p><strong>我觉得就目前这样的情况，个人家庭的私有云解决方案应该要出现了</strong>。也就是家庭内的数据中心解决方案，也许只需要像高清播放机那样的一个小盒子，里面可以用软件RAID两块或多块硬盘以保证数据的可用性，其还可以让你的数据在N多设备中共享，同步，备份，但你又不用担心互联网安全来担心这些数据，因为这仅仅是你的家庭局域网。</p>
<p>因为小孩让家庭照片和视频暴增，导致我去年就在想应该有一个家庭私有网盘的东西，所以，当我前些天看到<a href="http://www.spacemonkey.com/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.spacemonkey.com/?referer=');">Space Monkey</a> （<a href="http://news.cnet.com/8301-19882_3-57391989-250/dropbox-rival-space-monkey-puts-cloud-in-your-house/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/news.cnet.com/8301-19882_3-57391989-250/dropbox-rival-space-monkey-puts-cloud-in-your-house/?referer=');">新闻报道</a>）的时候，我立马就觉得这就是我想要的东西。</p>
<p><img class="aligncenter" src="http://asset1.cbsistatic.com/cnwk.1d/i/tim/2012/03/07/spacemonkeyHW_270x283.JPG" alt="" /></p>
<p>不过，国内还没有相应的产品，有想法的同学不妨试试去做一个类似于这样的产品，动作要快，千万不要让创新工场和腾讯抢先了。;-)</p>
<p>（全文完）</p>
<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="微软的安全补丁分析" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2305.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6976.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2305.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6976.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/06/21/13642093.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">微软的安全补丁分析</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="HTML 安全列表" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2416.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6976.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2416.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6976.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">HTML 安全列表</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="CSDN明文口令泄露的启示" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6193.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6976.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6193.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6976.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/12/22/12873627.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">CSDN明文口令泄露的启示</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="如何管理并设计你的口令" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2428.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6976.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2428.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6976.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">如何管理并设计你的口令</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Web开发中需要了解的东西" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6043.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6976.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6043.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6976.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Web开发中需要了解的东西</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table><h3  class="related_post_title">相关文章</h3><ul class="related_post"><li>2012年01月06日 -- <a href="http://coolshell.cn/articles/6424.html" title="Hash Collision DoS 问题">Hash Collision DoS 问题</a></li><li>2011年12月22日 -- <a href="http://coolshell.cn/articles/6193.html" title="CSDN明文口令泄露的启示">CSDN明文口令泄露的启示</a></li><li>2011年12月07日 -- <a href="http://coolshell.cn/articles/6043.html" title="Web开发中需要了解的东西">Web开发中需要了解的东西</a></li><li>2011年11月28日 -- <a href="http://coolshell.cn/articles/5987.html" title="如何设计“找回用户帐号”功能">如何设计“找回用户帐号”功能</a></li><li>2011年11月25日 -- <a href="http://coolshell.cn/articles/5966.html" title="腾讯帐号申诉的用户体验">腾讯帐号申诉的用户体验</a></li><li>2011年08月25日 -- <a href="http://coolshell.cn/articles/5353.html" title="你会做Web上的用户登录功能吗？">你会做Web上的用户登录功能吗？</a></li><li>2011年03月03日 -- <a href="http://coolshell.cn/articles/3877.html" title="另类UX让你输入强口令">另类UX让你输入强口令</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/6976.html/feed</wfw:commentRss>
		<slash:comments>55</slash:comments>
		</item>
		<item>
		<title>需求变化与IoC</title>
		<link>http://coolshell.cn/articles/6950.html</link>
		<comments>http://coolshell.cn/articles/6950.html#comments</comments>
		<pubDate>Mon, 26 Mar 2012 03:01:07 +0000</pubDate>
		<dc:creator>Todd</dc:creator>
				<category><![CDATA[程序设计]]></category>
		<category><![CDATA[系统架构]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[design pattern]]></category>
		<category><![CDATA[IoC]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=6950</guid>
		<description><![CDATA[【感谢 Todd投递本文 – 微博帐号：@weidagang 】 需求又变了，怎么办？ 先上一个轻松的段子： 程序员XX遭遇车祸成植物人，医生说活下来的希望只有万分之一，唤醒更为渺茫。可他的Lead和亲人没有放弃，他们根据XX工作如命的作风，每天都在他身边念：“XX，需求又改了，该干活了，你快来呀！”，奇迹终于发生了，XX醒来了，第一句话：“需求又改了？”。 这个段子用幽默的方式反映了需求变化是每一个程序员、架构师或项目经理都会经常遇到的问题。面对这个问题，不同的人有不同的应对之道，最近微博上有一段关于需求变化的讨论： @假装刺猬的猪：我们在软件开发过程中，会持续碰到客户需求变更的情况。如果没有领域建模，我们单纯将问题使用直觉将问题解决，那么等到客户需求变更或者有新的需求时，就会面临一个僵硬的前设计！无法在以前的设计上持续深入的优化模型，导致需求变更无法及时深化。设计实现均滞后与变更！ @高煥堂: &#60;碰到客户需求变更的情况&#62;是合理的；但&#60;领域建模&#62;不是美好的手段!!! @weidagang: 要不被客户牵着鼻子走，需要自己有很强的设计能力，反过来让客户跟着你的设计来满足你的要求。能做到这点的公司很少，但这是软件行业唯一有希望的出路。 @高煥堂: &#60;这是软件行业唯一有希望的出路&#62;。 Great!! 如何应对需求变化？ @假装刺猬的猪 的答案是领域建模，并持续优化模型，适应需求的变化。@高煥堂 则认为领域建模不是美好的手段。我进一步补充，应该“反过来”让自己在需求变化中处于主导地位，而不是被动地适应。 控制反转 (IoC) 什么样就算是“反过来”了呢？举个例子： 用户想购买一台普通PC，他只想电脑能流畅运行魔兽世界，他根本不想知道什么叫主板，什么叫内存，什么叫CPU；但他不得不接受必须购买主板、CPU、内存的事实，因为PC架构是产业标准，而不是由用户定的。客户有选择的权利，但没有设计的权利，客户的需求必须在设计框架下得到满足。 这里我们要问PC架构是保护了谁的利益？显然，直接的受益者是厂商。如果没有PC架构的保护，厂商就会直接面对客户，客户说我需要功能A，我马上分析设计实现功能A；客户说我要功能B，我马上分析设计实现功能B &#8230; 有了PC架构的保护，厂商就变得更加强势，用户的一切需求都必须在PC架构下来谈。厂商可以倾听用户的声音，不断改进产品，但设计主导权永远在自己手中。我们IT行业常常用“做产品”和“做项目”的视角来区分不同的公司，但很少有人用“做设计”的视角来看。实际上，关键的问题在于设计主导权是厂商还是在客户。如果设计主导权在客户，不管是做产品、做服务还是做项目，其命运必然是疲于奔命应付客户，最后获得微薄的利润；如果设计主导权在厂商，不管做产品、做服务还是做项目都能有更多的话语权和更高的利润。 当然，光有设计还不够，必须客户接受才能起到通过设计掌握主导权的作用。这一方面需要自己具有很强的设计能力，如苹果就是以设计能力著称的公司；另一方面，和其他厂商结盟壮大阵营也是一种方法，如最著名的Wintel联盟(Windows+Intel)，以及现在的日益壮大的Android阵营都属于此类。假如有厂商不遵守PC产业标准，说我的PC就没有主板，没有显卡，因为用户更不不需要这些东西；那么，它要么像苹果一样独树一帜成为一种新的标准，要么无人问津。 我所谈到的“反过来”本质上就是软件设计中的控制反转 (Inversion of Control, IoC)思想。IoC是每一个初级程序员向高级进阶所需要了解的最重要的设计思想。由于Spring等开发框架的流行，知道IoC概念的程序员不在少数，但不少人对于IoC的理解仅仅停留在通过依赖注入 (Dependency Injection)实现解耦这个层面。实际上，IoC的应用不仅包括解耦，它还是框架的基本原理，在非计算机领域，IoC也是无处不在，如果你能从上面的例子中体会到IoC，这才算是融会贯通了。 软件开发中一种最常见的模式是“以用户为出发点，以需求分析为核心”。该模式提倡从用户需求中分析推导出设计和实现，比如，TDD式的设计正是这类典型。而IoC式的软件设计与此截然相反，IoC的设计是一种“以愿景（自身利益是愿景的重要方面）为出发点，以架构为核心”的模式。如果用户的需求是一台电脑，我们如何能通过第一种模式分析需求推导出“主板-CPU-内存-外设”的PC架构呢？恐怕很难。IoC式的设计是以用户看不见摸不着的架构为核心，自己主导设计，用户需求是设计的约束条件和验证手段，而不是出发点和目标。我们想要掌握主动，不被需求变化搞得疲于奔命，就必须熟练使用第二种模式。 我们的人生都被环境和各种客观条件所束缚，多数人只能随波逐流，听从命运的安排。你有没有想过要拥有人生的主导权呢？既然你是程序员，你懂IoC，你能否设计自己的人生框架呢？Yes，you can! 相关文章2012年05月03日 -- 用Unix的设计思想来应对多变的需求2012年03月13日 -- 多版本并发控制(MVCC)在分布式系统中的应用2012年03月09日 -- Bret Victor &#8211; Inventing on Principle2012年01月16日 -- 由12306.cn谈谈网站性能技术 2011年11月24日 -- [...]<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="用Unix的设计思想来应对多变的需求" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7236.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6950.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7236.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6950.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2012/05/03/24506481.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">用Unix的设计思想来应对多变的需求</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="浏览器正则表达式检查插件" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2667.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6950.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2667.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6950.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/06/21/13667974.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">浏览器正则表达式检查插件</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="三个事和三个问题" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6142.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6950.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6142.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6950.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/12/20/12660933.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">三个事和三个问题</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="你确信你了解时间吗？" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5075.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6950.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5075.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6950.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/08/03/20651186.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">你确信你了解时间吗？</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="做个环保主义的程序员" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7186.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6950.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7186.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6950.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2012/04/27/23798602.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">做个环保主义的程序员</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table>]]></description>
			<content:encoded><![CDATA[<p>【<span style="color: #cc0000;">感谢 Todd投递本文 – 微博帐号</span>：@<a title="weidagang" onclick="pageTracker._trackPageview('/outgoing/weibo.com/weidagang?referer=');pageTracker._trackPageview('/outgoing/weibo.com/weidagang?referer=http%3A%2F%2Fcoolshell.cn%2F');" href="http://weibo.com/weidagang" target="_blank">weidagang</a> 】</p>
<h4>需求又变了，怎么办？</h4>
<p>先上一个轻松的段子：</p>
<blockquote><p>程序员XX遭遇车祸成植物人，医生说活下来的希望只有万分之一，唤醒更为渺茫。可他的Lead和亲人没有放弃，他们根据XX工作如命的作风，每天都在他身边念：“XX，需求又改了，该干活了，你快来呀！”，奇迹终于发生了，XX醒来了，第一句话：“需求又改了？”。</p></blockquote>
<p>这个段子用幽默的方式反映了需求变化是每一个程序员、架构师或项目经理都会经常遇到的问题。面对这个问题，不同的人有不同的应对之道，最近微博上有一段关于需求变化的讨论：</p>
<blockquote><p>@假装刺猬的猪：我们在软件开发过程中，会持续碰到客户需求变更的情况。如果没有领域建模，我们单纯将问题使用直觉将问题解决，那么等到客户需求变更或者有新的需求时，就会面临一个僵硬的前设计！无法在以前的设计上持续深入的优化模型，导致需求变更无法及时深化。设计实现均滞后与变更！</p>
<p>@高煥堂: &lt;碰到客户需求变更的情况&gt;是合理的；但&lt;领域建模&gt;不是美好的手段!!!</p>
<p>@weidagang: 要不被客户牵着鼻子走，需要自己有很强的设计能力，<strong>反过来</strong>让客户跟着你的设计来满足你的要求。能做到这点的公司很少，但这是软件行业唯一有希望的出路。</p>
<p>@高煥堂: &lt;这是软件行业唯一有希望的出路&gt;。 Great!!</p></blockquote>
<p>如何应对需求变化？ @假装刺猬的猪 的答案是领域建模，并持续优化模型，适应需求的变化。@高煥堂 则认为领域建模不是美好的手段。我进一步补充，应该<strong>“反过来”</strong>让自己在需求变化中处于主导地位，而不是被动地适应。</p>
<p><span id="more-6950"></span></p>
<h4>控制反转 (IoC)</h4>
<p>什么样就算是“反过来”了呢？举个例子：</p>
<blockquote><p>用户想购买一台普通PC，他只想电脑能流畅运行魔兽世界，他根本不想知道什么叫主板，什么叫内存，什么叫CPU；但他不得不接受必须购买主板、CPU、内存的事实，因为PC架构是产业标准，而不是由用户定的。客户有选择的权利，但没有设计的权利，客户的需求必须在设计框架下得到满足。</p></blockquote>
<p>这里我们要问PC架构是保护了谁的利益？显然，直接的受益者是厂商。如果没有PC架构的保护，厂商就会直接面对客户，客户说我需要功能A，我马上分析设计实现功能A；客户说我要功能B，我马上分析设计实现功能B &#8230; 有了PC架构的保护，厂商就变得更加强势，用户的一切需求都必须在PC架构下来谈。厂商可以倾听用户的声音，不断改进产品，但设计主导权永远在自己手中。我们IT行业常常用“做产品”和“做项目”的视角来区分不同的公司，但很少有人用“做设计”的视角来看。实际上，关键的问题在于设计主导权是厂商还是在客户。如果设计主导权在客户，不管是做产品、做服务还是做项目，其命运必然是疲于奔命应付客户，最后获得微薄的利润；如果设计主导权在厂商，不管做产品、做服务还是做项目都能有更多的话语权和更高的利润。</p>
<p>当然，光有设计还不够，必须客户接受才能起到通过设计掌握主导权的作用。这一方面需要自己具有很强的设计能力，如苹果就是以设计能力著称的公司；另一方面，和其他厂商结盟壮大阵营也是一种方法，如最著名的Wintel联盟(Windows+Intel)，以及现在的日益壮大的Android阵营都属于此类。假如有厂商不遵守PC产业标准，说我的PC就没有主板，没有显卡，因为用户更不不需要这些东西；那么，它要么像苹果一样独树一帜成为一种新的标准，要么无人问津。</p>
<p>我所谈到的“反过来”本质上就是软件设计中的控制反转 (Inversion of Control, IoC)思想。IoC是每一个初级程序员向高级进阶所需要了解的<strong>最重要</strong>的设计思想。由于Spring等开发框架的流行，知道IoC概念的程序员不在少数，但不少人对于IoC的理解仅仅停留在通过依赖注入 (Dependency Injection)实现解耦这个层面。实际上，IoC的应用不仅包括解耦，它还是框架的基本原理，在非计算机领域，IoC也是无处不在，如果你能从上面的例子中体会到IoC，这才算是融会贯通了。</p>
<p>软件开发中一种最常见的模式是“以用户为出发点，以需求分析为核心”。该模式提倡从用户需求中分析推导出设计和实现，比如，TDD式的设计正是这类典型。而IoC式的软件设计与此截然相反，IoC的设计是一种“以愿景（自身利益是愿景的重要方面）为出发点，以架构为核心”的模式。如果用户的需求是一台电脑，我们如何能通过第一种模式分析需求推导出“主板-CPU-内存-外设”的PC架构呢？恐怕很难。IoC式的设计是以用户看不见摸不着的架构为核心，自己主导设计，用户需求是设计的约束条件和验证手段，而不是出发点和目标。我们想要掌握主动，不被需求变化搞得疲于奔命，就必须熟练使用第二种模式。</p>
<p>我们的人生都被环境和各种客观条件所束缚，多数人只能随波逐流，听从命运的安排。你有没有想过要拥有人生的主导权呢？既然你是程序员，你懂IoC，你能否设计自己的人生框架呢？Yes，you can!</p>
<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="用Unix的设计思想来应对多变的需求" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7236.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6950.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7236.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6950.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2012/05/03/24506481.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">用Unix的设计思想来应对多变的需求</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="操作系统航空公司" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1272.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6950.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1272.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6950.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10437735.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">操作系统航空公司</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Vim命令速查卡" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F150.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6950.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F150.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6950.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/07/19/18062655.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Vim命令速查卡</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="优质代码的十诫" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1007.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6950.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1007.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6950.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10437778.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">优质代码的十诫</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Eclipse 和 Vim" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1837.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6950.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1837.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6950.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10435142.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Eclipse 和 Vim</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table><h3  class="related_post_title">相关文章</h3><ul class="related_post"><li>2012年05月03日 -- <a href="http://coolshell.cn/articles/7236.html" title="用Unix的设计思想来应对多变的需求">用Unix的设计思想来应对多变的需求</a></li><li>2012年03月13日 -- <a href="http://coolshell.cn/articles/6790.html" title="多版本并发控制(MVCC)在分布式系统中的应用">多版本并发控制(MVCC)在分布式系统中的应用</a></li><li>2012年03月09日 -- <a href="http://coolshell.cn/articles/6775.html" title="Bret Victor &#8211; Inventing on Principle">Bret Victor &#8211; Inventing on Principle</a></li><li>2012年01月16日 -- <a href="http://coolshell.cn/articles/6470.html" title="由12306.cn谈谈网站性能技术 ">由12306.cn谈谈网站性能技术 </a></li><li>2011年11月24日 -- <a href="http://coolshell.cn/articles/5537.html" title="一些文章资源和趣闻">一些文章资源和趣闻</a></li><li>2011年10月25日 -- <a href="http://coolshell.cn/articles/5686.html" title="多些时间能少写些代码">多些时间能少写些代码</a></li><li>2011年09月08日 -- <a href="http://coolshell.cn/articles/5444.html" title="千万不要把 bool 设计成函数参数">千万不要把 bool 设计成函数参数</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/6950.html/feed</wfw:commentRss>
		<slash:comments>44</slash:comments>
		</item>
		<item>
		<title>神奇的CSS形状</title>
		<link>http://coolshell.cn/articles/6913.html</link>
		<comments>http://coolshell.cn/articles/6913.html#comments</comments>
		<pubDate>Sat, 24 Mar 2012 12:35:41 +0000</pubDate>
		<dc:creator>Neo</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[编程语言]]></category>
		<category><![CDATA[趣味问题]]></category>
		<category><![CDATA[CSS]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=6913</guid>
		<description><![CDATA[【感谢 Neo 投递本文 – 微博帐号：@_锟_ 】 在StackOverflow上有这么一个问题，有位同学在http://css-tricks.com/examples/ShapesOfCSS/  找到一些使用CSS做的形状，其中一位同学对下面的这个形状充满了疑问。 形状是： 代码是： 这位同学就提问啦，为啥这么这么几句就能画出一个三角形呢？ 于是呢，有高人出现，这个高人图文并茂的解释了这个三角的成因 首先呢，我们需要了解HTML标记的Box Model（盒模型），这个例子中呢我们将content，padding都看作content。忽略掉margin。那么一个盒模型就是下图 中间是内容，然后是4条边。每一条边都有宽度。 根据上面CSS的定义，没有border-top（顶边）的情形下 ,我们的图形如下： width设置为0后 ，内容没有了就成为下图： height也设置为0，只有底边了。 然后两条边都是设置为透明，最后我们就得到了 这个属于奇技淫巧，但是也说明CSS的强大，没有做不到只有想不到。另外http://css-tricks.com/examples/ShapesOfCSS/ 还能找到很多其他的形状，感兴趣的同学可以自己去看。还有酷壳以前的这篇文章《CSS实现的各种形状》 相关文章2012年03月19日 -- CSS 布局:40个教程、技巧、例子和最佳实践2011年12月07日 -- Web开发中需要了解的东西2011年08月15日 -- CSS图形2011年03月04日 -- 一些有意思的贴子和工具2011年02月16日 -- Web开发人员速查卡2010年10月20日 -- 30+ Web下拉菜单2010年10月08日 -- 40个很不错的CSS技术<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="22个不错的CSS技术" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F648.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6913.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F648.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6913.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10438281.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">22个不错的CSS技术</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="IE的CSS相关的BUG" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1245.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6913.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1245.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6913.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/14/10752902.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">IE的CSS相关的BUG</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="30种时尚的CSS网站导航条" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F562.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6913.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F562.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6913.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/07/09/16776513.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">30种时尚的CSS网站导航条</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="40个很不错的CSS技术" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3063.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6913.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3063.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6913.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/06/21/13646971.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">40个很不错的CSS技术</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="纯CSS做的3D效果" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1962.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6913.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1962.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6913.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">纯CSS做的3D效果</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table>]]></description>
			<content:encoded><![CDATA[<p>【<span style="color: #cc0000;">感谢 Neo 投递本文 – 微博帐号</span>：<a title="_锟_" href="http://weibo.com/gandalfthegrey" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/gandalfthegrey?referer=');">@_锟_</a> 】</p>
<p style="text-align: left;">在StackOverflow上有这么一个问题，有位同学在<a href="http://css-tricks.com/examples/ShapesOfCSS/" onclick="pageTracker._trackPageview('/outgoing/css-tricks.com/examples/ShapesOfCSS/?referer=');">http://css-tricks.com/examples/ShapesOfCSS/ </a> 找到一些使用CSS做的形状，其中一位同学对下面的这个形状充满了疑问。</p>
<p style="text-align: left;">形状是：</p>
<p style="text-align: left;"><img class="size-full wp-image-6914" src="http://coolshell.cn/wp-content/uploads/2012/03/a.png" alt="" width="103" height="102" /></p>
<p style="text-align: left;">代码是：</p>
<pre class="brush: css; title: ; notranslate">
#triangle-up {
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid red;
}
</pre>
<p>这位同学就提问啦，为啥这么这么几句就能画出一个三角形呢？<br />
于是呢，有高人出现，这个高人图文并茂的解释了这个三角的成因</p>
<p><span id="more-6913"></span><br />
首先呢，我们需要了解HTML标记的Box Model（盒模型），这个例子中呢我们将content，padding都看作content。忽略掉margin。那么一个盒模型就是下图</p>
<p style="text-align: left;"><img class="size-full wp-image-6915" src="http://coolshell.cn/wp-content/uploads/2012/03/b.png" alt="" width="340" height="266" /></p>
<p>中间是内容，然后是4条边。每一条边都有宽度。<br />
根据上面CSS的定义，没有border-top（顶边）的情形下 ,我们的图形如下：</p>
<p style="text-align: left;"><img class="size-full wp-image-6916" src="http://coolshell.cn/wp-content/uploads/2012/03/c.png" alt="" width="340" height="266" /></p>
<p>width设置为0后 ，内容没有了就成为下图：</p>
<p style="text-align: left;"><img class="size-full wp-image-6917" src="http://coolshell.cn/wp-content/uploads/2012/03/d.png" alt="" width="340" height="266" /></p>
<p>height也设置为0，只有底边了。</p>
<p style="text-align: left;"><img class="size-full wp-image-6918" src="http://coolshell.cn/wp-content/uploads/2012/03/e.png" alt="" width="200" height="122" /></p>
<p>然后两条边都是设置为透明，最后我们就得到了</p>
<p style="text-align: left;"><img class="size-full wp-image-6919" src="http://coolshell.cn/wp-content/uploads/2012/03/f.png" alt="" width="200" height="122" /></p>
<p>这个属于奇技淫巧，但是也说明CSS的强大，没有做不到只有想不到。另外<a href="http://css-tricks.com/examples/ShapesOfCSS/" onclick="pageTracker._trackPageview('/outgoing/css-tricks.com/examples/ShapesOfCSS/?referer=');">http://css-tricks.com/examples/ShapesOfCSS/ </a>还能找到很多其他的形状，感兴趣的同学可以自己去看。还有酷壳以前的这篇文章《<a title="CSS图形" href="http://coolshell.cn/articles/5164.html" target="_blank">CSS实现的各种形状</a>》</p>
<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="22个不错的CSS技术" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F648.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6913.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F648.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6913.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10438281.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">22个不错的CSS技术</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="IE的CSS相关的BUG" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1245.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6913.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1245.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6913.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/14/10752902.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">IE的CSS相关的BUG</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="30种时尚的CSS网站导航条" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F562.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6913.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F562.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6913.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/07/09/16776513.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">30种时尚的CSS网站导航条</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="40个很不错的CSS技术" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3063.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6913.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3063.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6913.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/06/21/13646971.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">40个很不错的CSS技术</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="纯CSS做的3D效果" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1962.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6913.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1962.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6913.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">纯CSS做的3D效果</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table><h3  class="related_post_title">相关文章</h3><ul class="related_post"><li>2012年03月19日 -- <a href="http://coolshell.cn/articles/6840.html" title="CSS 布局:40个教程、技巧、例子和最佳实践">CSS 布局:40个教程、技巧、例子和最佳实践</a></li><li>2011年12月07日 -- <a href="http://coolshell.cn/articles/6043.html" title="Web开发中需要了解的东西">Web开发中需要了解的东西</a></li><li>2011年08月15日 -- <a href="http://coolshell.cn/articles/5164.html" title="CSS图形">CSS图形</a></li><li>2011年03月04日 -- <a href="http://coolshell.cn/articles/3903.html" title="一些有意思的贴子和工具">一些有意思的贴子和工具</a></li><li>2011年02月16日 -- <a href="http://coolshell.cn/articles/3684.html" title="Web开发人员速查卡">Web开发人员速查卡</a></li><li>2010年10月20日 -- <a href="http://coolshell.cn/articles/3207.html" title="30+ Web下拉菜单">30+ Web下拉菜单</a></li><li>2010年10月08日 -- <a href="http://coolshell.cn/articles/3063.html" title="40个很不错的CSS技术">40个很不错的CSS技术</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/6913.html/feed</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>CSS 布局:40个教程、技巧、例子和最佳实践</title>
		<link>http://coolshell.cn/articles/6840.html</link>
		<comments>http://coolshell.cn/articles/6840.html#comments</comments>
		<pubDate>Mon, 19 Mar 2012 00:25:46 +0000</pubDate>
		<dc:creator>Neo</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[杂项资源]]></category>
		<category><![CDATA[编程语言]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=6840</guid>
		<description><![CDATA[【感谢 Neo 投递本文 – 微博帐号：_锟_ 】 前言： 布局是WEB开发一个重要的课题，进入XHTML/CSS后，使用TABLE布局的方式逐渐淡出，CSS布局以众多优点成为主流，本文将介绍40个基于CSS的web布局的资源和教程。文章的出处在http://www.noupe.com/css/css-layouts-40-tutorials-tips-demos-and-best-practices.html。文中的不少的例子在一本经典的CSS书籍《CCS: The Missing Manual, 2nd Edition》中都可以找到，据我所知，第二版在中国没有翻译出版。你可以从这里下载英文版（不过需要注册个用户名） 正文 基于CSS的布局能提供更灵活布局方式和更强的用户视觉体验。一些重要技巧和关键点可以帮助初学者理解CSS布局的基础和本质。这也是本文成文的原因 ——找到那些完美的布局，完全灵活的，等高栏和工作完美的布局。 因此下面这个列表就是我们整理了网络上关于基于CSS布局的一些技巧，教程和最佳实践的列表。 当然你也可能对下面这些和CSS相关的主题有兴趣： The 7 CSS Hacks that we should use Using CSS to Do Anything: 50+ Creative Examples and Tutorials Using CSS to Fix Anything: 20+ Common Bugs and Fixes CSS 布局教程 1-使用CSS完成三栏固定布局结构- 这篇文章解释了如何实现一个基于的HTML/CSS来设计一个简单的带有基本要素（顶部的logo条，导航条，文本区，定义分类的中部栏，右边侧栏插入google的120X600的广告区）的固定三栏页面布局。 2-使用CSS设计页面布局- 如何使用CSS文件来为你的站点设计页面布局。 3-如何创建一个水平布局的站点- 创建不同于常规的水平布局的站点技术（译者注：水平布局，客户体验也就仁者见仁了） 例子查看这里 [...]<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="神奇的CSS形状" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6913.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6840.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6913.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6840.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2012/03/24/18083200.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">神奇的CSS形状</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="22个不错的CSS技术" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F648.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6840.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F648.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6840.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10438281.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">22个不错的CSS技术</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="40个很不错的CSS技术" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3063.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6840.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3063.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6840.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/06/21/13646971.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">40个很不错的CSS技术</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="30种时尚的CSS网站导航条" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F562.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6840.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F562.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6840.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/07/09/16776513.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">30种时尚的CSS网站导航条</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="CSS图形" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5164.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6840.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5164.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6840.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">CSS图形</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table>]]></description>
			<content:encoded><![CDATA[<p>【<span style="color: #cc0000;">感谢 Neo 投递本文 – 微博帐号</span>：<a title="_锟_" href="http://weibo.com/gandalfthegrey" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/gandalfthegrey?referer=');">_锟_</a> 】</p>
<p><strong>前言：</strong> 布局是WEB开发一个重要的课题，进入XHTML/CSS后，使用TABLE布局的方式逐渐淡出，CSS布局以众多优点成为主流，本文将介绍40个基于CSS的web布局的资源和教程。文章的出处在<a href="http://www.noupe.com/css/css-layouts-40-tutorials-tips-demos-and-best-practices.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.noupe.com/css/css-layouts-40-tutorials-tips-demos-and-best-practices.html?referer=');">http://www.noupe.com/css/css-layouts-40-tutorials-tips-demos-and-best-practices.html</a>。文中的不少的例子在一本经典的CSS书籍<a href="http://shop.oreilly.com/product/9780596802455.do" onclick="pageTracker._trackPageview('/outgoing/shop.oreilly.com/product/9780596802455.do?referer=');">《CCS: The Missing Manual, 2nd Edition》</a>中都可以找到，据我所知，第二版在中国没有翻译出版。你可以从<a href="http://www.itpub.net/forum.php?mod=viewthread&amp;tid=1210179&amp;highlight=CSS%2Bthe%2Bmissing%2Bmanual" onclick="pageTracker._trackPageview('/outgoing/www.itpub.net/forum.php?mod=viewthread_amp_tid=1210179_amp_highlight=CSS_2Bthe_2Bmissing_2Bmanual&amp;referer=');">这里</a>下载英文版（不过需要注册个用户名）</p>
<p><strong>正文</strong><br />
<strong>基于CSS的布局</strong>能提供更灵活布局方式和更强的用户视觉体验。一些重要技巧和关键点可以帮助初学者理解CSS布局的基础和本质。这也是本文成文的原因 ——找到那些完美的布局，<strong>完全灵活的，等高栏</strong>和工作完美的布局。<br />
因此下面这个列表就是我们整理了网络上关于基于CSS布局的一些技巧，教程和最佳实践的列表。<br />
当然你也可能对下面这些和CSS相关的主题有兴趣：</p>
<p><a href="http://www.noupe.com/css/9-timeless-3-column-layout-techniques.html&gt;9 Timeless 3 Column Layout Techniques&lt;/a&gt;&lt;/ui&gt;&lt;br /&gt; &lt;ui&gt;&lt;a href=" onclick="pageTracker._trackPageview('/outgoing/www.noupe.com/css/9-timeless-3-column-layout-techniques.html_gt_9_Timeless_3_Column_Layout_Techniques_lt_/a_gt_lt_/ui_gt_lt_br_/_gt_lt_ui_gt_lt_a_href=?referer=');">The 7 CSS Hacks that we should use</a><br />
<a href="http://www.noupe.com/css/using-css-to-do-anything-50-creative-examples-and-tutorials.html" onclick="pageTracker._trackPageview('/outgoing/www.noupe.com/css/using-css-to-do-anything-50-creative-examples-and-tutorials.html?referer=');">Using CSS to Do Anything: 50+ Creative Examples and Tutorials</a><br />
<a href="http://www.noupe.com/css/using-css-to-fix-anything-20-common-bugs-and-fixes.html" onclick="pageTracker._trackPageview('/outgoing/www.noupe.com/css/using-css-to-fix-anything-20-common-bugs-and-fixes.html?referer=');">Using CSS to Fix Anything: 20+ Common Bugs and Fixes</a></p>
<p><span id="more-6840"></span></p>
<h4><strong><span style="color: #008000;">CSS 布局教程</span></strong></h4>
<p>1-<a href="http://woork.blogspot.com/2008/01/three-column-fixed-layout-structure.html" onclick="pageTracker._trackPageview('/outgoing/woork.blogspot.com/2008/01/three-column-fixed-layout-structure.html?referer=');">使用CSS完成三栏固定布局结构</a>- 这篇文章解释了如何实现一个基于的HTML/CSS来设计一个简单的带有基本要素（顶部的logo条，导航条，文本区，定义分类的中部栏，右边侧栏插入google的120X600的广告区）的固定三栏页面布局。</p>
<p><img class="size-full wp-image-6843 aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts.gif" alt="" width="450" height="297" /></p>
<p>2-<a href="http://woork.blogspot.com/2007/10/design-page-layout-using-css.html" onclick="pageTracker._trackPageview('/outgoing/woork.blogspot.com/2007/10/design-page-layout-using-css.html?referer=');">使用CSS设计页面布局</a>- 如何使用CSS文件来为你的站点设计页面布局。<br />
<img class="size-full wp-image-6844 aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts2.gif" alt="" width="450" height="200" /></p>
<p>3-<a href="http://css-tricks.com/how-to-create-a-horizontally-scrolling-site/" onclick="pageTracker._trackPageview('/outgoing/css-tricks.com/how-to-create-a-horizontally-scrolling-site/?referer=');">如何创建一个水平布局的站点</a>- 创建不同于常规的水平布局的站点技术（译者注：水平布局，客户体验也就仁者见仁了）</p>
<p><img class="aligncenter size-full wp-image-6845" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts3.gif" alt="" width="450" height="190" /><br />
例子<a href="http://css-tricks.com/examples/HorzScrolling" onclick="pageTracker._trackPageview('/outgoing/css-tricks.com/examples/HorzScrolling?referer=');">查看这里</a> |<a href="http://css-tricks.com/examples/HorzScrolling.zip" onclick="pageTracker._trackPageview('/outgoing/css-tricks.com/examples/HorzScrolling.zip?referer=');">下载</a></p>
<p>4-<a href="http://css-tricks.com/super-simple-two-column-layout/" onclick="pageTracker._trackPageview('/outgoing/css-tricks.com/super-simple-two-column-layout/?referer=');">超级简单的两栏布局</a>- 创建不同于常规的水平布局的站点技术（译者注：这里是原作者笔误吧和上面的内容一样）.</p>
<p><img class="aligncenter size-full wp-image-6849" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts4.gif" alt="" width="450" height="100" /></p>
<p>例子<a href="http://css-tricks.com/examples/SuperSimpleTwoColumn" onclick="pageTracker._trackPageview('/outgoing/css-tricks.com/examples/SuperSimpleTwoColumn?referer=');">查看这里</a> <a href="http://css-tricks.com/examples/SuperSimpleTwoColumn.zip" onclick="pageTracker._trackPageview('/outgoing/css-tricks.com/examples/SuperSimpleTwoColumn.zip?referer=');">下载</a></p>
<p>5-<a href="http://www.456bereastreet.com/lab/developing_with_web_standards/csslayout/2-col/" onclick="pageTracker._trackPageview('/outgoing/www.456bereastreet.com/lab/developing_with_web_standards/csslayout/2-col/?referer=');">简单两栏CSS布局</a>- 这是一个创建简单两栏布局的教程。这种布局包含了一个标题区，一个水平导航条，主内容区，边侧栏，和页脚区。并且这个布局是水平居中的。</p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts6.gif" alt="" width="450" height="150" /></p>
<p>例子<a href="http://www.456bereastreet.com/lab/developing_with_web_standards/csslayout/2-col/finished.html" onclick="pageTracker._trackPageview('/outgoing/www.456bereastreet.com/lab/developing_with_web_standards/csslayout/2-col/finished.html?referer=');">查看这里</a></p>
<p>6-<a href="http://dnevnikeklektika.com/en/the-holy-grail-layout-3-columns-and-a-lot-less-problems" onclick="pageTracker._trackPageview('/outgoing/dnevnikeklektika.com/en/the-holy-grail-layout-3-columns-and-a-lot-less-problems?referer=');">圣杯布局(The holy grail layout)</a> – 3栏布局会有一些问题 ，这篇文章讨论了一种三栏布局——两栏固定宽度边侧栏加上一栏变宽中栏布局，保证了页面的良好结构和清晰。</p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts7.gif" alt="" width="450" height="362" /></p>
<p>例子<a href="http://dnevnikeklektika.com/css/3ColLayout/working.html" onclick="pageTracker._trackPageview('/outgoing/dnevnikeklektika.com/css/3ColLayout/working.html?referer=');">查看这里</a></p>
<p>7-<a href="http://www.simplebits.com/notebook/2004/09/08/centering.html" onclick="pageTracker._trackPageview('/outgoing/www.simplebits.com/notebook/2004/09/08/centering.html?referer=');">CSS居中101</a>- 如何使用CSS完成居中一个固定宽度的布局</p>
<p>使用CSS，通过下面两条规则完成对id为container的DIV所包含的内容居中</p>
<pre class="brush: xml; title: ; notranslate">
&lt;body&gt;
 &lt;div id=&quot;container&quot;&gt; ...entire layout goes here...
&lt;/div&gt;
&lt;/body&gt;
</pre>
<pre class="brush: css; title: ; notranslate">
body {
    text-align: center;
}
#container {
    margin: 0 auto;
    width: xxxpx;
    text-align: left;
}
</pre>
<p>8-<a href="http://www.subcide.com/tutorials/csslayout/index.aspx" onclick="pageTracker._trackPageview('/outgoing/www.subcide.com/tutorials/csslayout/index.aspx?referer=');">从头创建CSS布局</a>- 这个指南通过创建一个全功能的 CSS布局来一步步教你入门CSS布局。</p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts9.gif" alt="" width="450" height="255" /></p>
<p>9-<a href="http://www.alistapart.com/articles/multicolumnlayouts/" onclick="pageTracker._trackPageview('/outgoing/www.alistapart.com/articles/multicolumnlayouts/?referer=');">非主流！多栏布局</a>- 多栏布局，等高栏（每一列的高度都相等），固定或变宽中央区，简洁标记，CSS 。(译者注：原文作者的图配的和上图一样)</p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts9.gif" alt="" width="450" height="255" /></p>
<p>例子<a href="http://www.alistapart.com/d/multicolumnlayouts/3ColLiquid.html" onclick="pageTracker._trackPageview('/outgoing/www.alistapart.com/d/multicolumnlayouts/3ColLiquid.html?referer=');">查看这里</a></p>
<p>10- <a href="http://www.positioniseverything.net/articles/onetruelayout/" onclick="pageTracker._trackPageview('/outgoing/www.positioniseverything.net/articles/onetruelayout/?referer=');">创建天下无双的CSS布局</a>- 高灵活性布局,等高栏，跨栏垂直摆放元素。本文告诉你通过何等手段完成这些目标，并使用它们创建天下无双的CSS布局（译者注:原文是One True Layout ，不知道怎么翻译，就天下无双吧。）</p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts22.gif" alt="" width="450" height="180" /></p>
<p><a href="http://www.positioniseverything.net/articles/onetruelayout/examples" onclick="pageTracker._trackPageview('/outgoing/www.positioniseverything.net/articles/onetruelayout/examples?referer=');">查看这里</a></p>
<p>11-<a href="http://nettuts.com/site-builds/from-psd-to-html-building-a-set-of-website-designs-step-by-step/" onclick="pageTracker._trackPageview('/outgoing/nettuts.com/site-builds/from-psd-to-html-building-a-set-of-website-designs-step-by-step/?referer=');">从PSD到HTML，手把手完成WEB设计</a>-从Photoshop到完整HTML，全过程手把手教会你。</p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts34.jpg" alt="" width="450" height="341" /></p>
<p>例子<a href="http://nettuts.s3.amazonaws.com/017_Creatif/Site/index.html" onclick="pageTracker._trackPageview('/outgoing/nettuts.s3.amazonaws.com/017_Creatif/Site/index.html?referer=');">查看这里</a> | <a href="http://nettuts.s3.amazonaws.com/017_Creatif/Site_Download.zip" onclick="pageTracker._trackPageview('/outgoing/nettuts.s3.amazonaws.com/017_Creatif/Site_Download.zip?referer=');">下载</a></p>
<p>12- <a href="http://tutorialblog.org/5-tips-for-coding-xhtmlcss-layouts/" onclick="pageTracker._trackPageview('/outgoing/tutorialblog.org/5-tips-for-coding-xhtmlcss-layouts/?referer=');">5个XHTML/CSS技巧</a> &#8211; 5个CSS技巧帮助你完成从基于表格的布局到基于CSS的布局。</p>
<p>13-<a href="http://veerle.duoh.com/index.php/blog/comments/designing_a_css_based_template_part_i/" onclick="pageTracker._trackPageview('/outgoing/veerle.duoh.com/index.php/blog/comments/designing_a_css_based_template_part_i/?referer=');">设计一个基于CSS的模板</a> &#8211; 这是一个教你创建基于CSS的模板页的基础教程。这个教程由下面几个部分构成：第一部分覆盖了在Photoshop CS*中的创建导航条按钮，第二部分：创建背景接下来的清单是标题和页面布局，最后的部分在XHTML和CSS中实现。</p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts35.jpg" alt="" width="450" height="250" /></p>
<p><a href="http://homepage.mac.com/vpieters/css_step2/step2_whooshes.mov.zip" onclick="pageTracker._trackPageview('/outgoing/homepage.mac.com/vpieters/css_step2/step2_whooshes.mov.zip?referer=');">下载</a></p>
<p>14-<a href="http://www.sitepoint.com/article/breaking-out-of-the-box" onclick="pageTracker._trackPageview('/outgoing/www.sitepoint.com/article/breaking-out-of-the-box?referer=');">使用CSS布局跳出常规布局</a>- 如果你理解了基于表格布局的工作方式，你能通过合并或拆分表格创建你随心所欲的布局。就这个目标（同时支持灵活性和可维护性），CSS能够提供比基于表格更多地东西。Jina Bolton的教程解释如何达到这个目标。</p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts36.gif" alt="" width="450" height="250" /></p>
<p>15-<a href="http://www.webreference.com/authoring/style/sheets/layout/advanced/" onclick="pageTracker._trackPageview('/outgoing/www.webreference.com/authoring/style/sheets/layout/advanced/?referer=');">高级CSS教程:手把手</a>- 这个教程的终极目标创建一个CSS布局，这个CSS布局精确地重组了原有使用table的WebReference.com的布局。</p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts29.gif" alt="" width="450" height="263" /></p>
<p>16-<a href="http://snook.ca/archives/html_and_css/six_keys_to_understanding_css_layouts/" onclick="pageTracker._trackPageview('/outgoing/snook.ca/archives/html_and_css/six_keys_to_understanding_css_layouts/?referer=');">了解CSS布局的6个关键要素</a>-本文讲述了6件基于CSS布局需要了解的事情：盒模型(Box Model)，浮动栏(Floated Columns) （译者注：float是WEB布局最重要的一个属性了）。使用Em来设置尺寸（Sizing Using Ems），图片替换（Image Replacement）,浮动导航和Sprintes。</p>
<p>17-<a href="http://wisdump.com/design/are-you-making-these-common-blog-layout-mistakes/" onclick="pageTracker._trackPageview('/outgoing/wisdump.com/design/are-you-making-these-common-blog-layout-mistakes/?referer=');">你会犯这些常见的博客布局错误吗？</a>-讨论4个博客布局中常见而且易修复的错误。</p>
<p>18-<a href="http://www.htmldog.com/guides/cssadvanced/layout/" onclick="pageTracker._trackPageview('/outgoing/www.htmldog.com/guides/cssadvanced/layout/?referer=');">页面布局</a>-CSS页面布局中的浮动元素和定位元素实践指导。</p>
<p>你可以查看这些例子：<a href="http://www.htmldog.com/examples/positioning4.html" onclick="pageTracker._trackPageview('/outgoing/www.htmldog.com/examples/positioning4.html?referer=');">Absolute Position within a relative box</a><a href="http://www.htmldog.com/examples/float2.html" onclick="pageTracker._trackPageview('/outgoing/www.htmldog.com/examples/float2.html?referer=');"> two floated boxes</a>和<a href="http://www.htmldog.com/examples/pagelayout3.html" onclick="pageTracker._trackPageview('/outgoing/www.htmldog.com/examples/pagelayout3.html?referer=');"> using a border to provide the background for a column</a></p>
<p>19-<a href="http://leftjustified.net/site-in-an-hour/" onclick="pageTracker._trackPageview('/outgoing/leftjustified.net/site-in-an-hour/?referer=');">Site in an Hour</a>- 使用复杂CCS布局完成简单的工作。</p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts40.jpg" alt="" width="450" height="250" /></p>
<h4><strong><span style="color: #008000;">关于布局的最佳资源</span></strong></h4>
<p>下面的大多数这些资源不需要许可就能直接使用，然而，其中的一些需要先发邮件确认一下是否可以使用这些资源。因此，在使用之前最好先检查资源的版权信息。</p>
<p>20-<a href="http://www.maxdesign.com.au/presentation/page_layouts/" onclick="pageTracker._trackPageview('/outgoing/www.maxdesign.com.au/presentation/page_layouts/?referer=');">简单CSS页面布局</a>- 这里有一套2栏和3栏的CSS布局。</p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts10.jpg" alt="" width="450" height="255" /></p>
<p>你可以通过这里查看这些样例<a href="http://www.maxdesign.com.au/presentation/process/example23.htm" onclick="pageTracker._trackPageview('/outgoing/www.maxdesign.com.au/presentation/process/example23.htm?referer=');"> Liquid three column layout</a>,<a href="http://www.maxdesign.com.au/presentation/page_layouts/single04.htm" onclick="pageTracker._trackPageview('/outgoing/www.maxdesign.com.au/presentation/page_layouts/single04.htm?referer=');"> Left aligned, set width</a> and <a href="http://www.maxdesign.com.au/presentation/liquid/example13.htm" onclick="pageTracker._trackPageview('/outgoing/www.maxdesign.com.au/presentation/liquid/example13.htm?referer=');">Liquid insanity</a>.</p>
<p>21-<a href="http://matthewjamestaylor.com/blog/perfect-3-column.htm" onclick="pageTracker._trackPageview('/outgoing/matthewjamestaylor.com/blog/perfect-3-column.htm?referer=');">完美的三栏变宽布局（百分比定宽度）The Perfect 3 Column Liquid Layout (Percentage widths)</a>- 没有CSS hack（译者注：不知道怎么翻译，点击<a href="http://baike.baidu.com/view/1119452.htm" onclick="pageTracker._trackPageview('/outgoing/baike.baidu.com/view/1119452.htm?referer=');">这里</a>查看解释）. 良好地收索引擎优化.无图. 无Javascript. 跨浏览器 和IPHONE设备兼容</p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts11.gif" alt="" width="450" height="370" /></p>
<p>你可以通过这里查看样例 <a href="http://www.maxdesign.com.au/presentation/process/example23.htm" onclick="pageTracker._trackPageview('/outgoing/www.maxdesign.com.au/presentation/process/example23.htm?referer=');">Liquid three column layout</a>, <a href="http://www.maxdesign.com.au/presentation/page_layouts/single04.htm" onclick="pageTracker._trackPageview('/outgoing/www.maxdesign.com.au/presentation/page_layouts/single04.htm?referer=');">Left aligned, set width</a> 和 <a href="http://www.maxdesign.com.au/presentation/liquid/example13.htm" onclick="pageTracker._trackPageview('/outgoing/www.maxdesign.com.au/presentation/liquid/example13.htm?referer=');">Liquid insanity</a>. (译者注：这里的链接和上面重复了，哎，原文的错误吧)</p>
<p>22-<a href="http://www.intensivstation.ch/en/templates/" onclick="pageTracker._trackPageview('/outgoing/www.intensivstation.ch/en/templates/?referer=');">CSS模板和样例</a></p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts21.gif" alt="" width="450" height="380" /></p>
<p>你可以通过这里查看这些样例<a href="http://www.intensivstation.ch/files/en_templates/temp06.html" onclick="pageTracker._trackPageview('/outgoing/www.intensivstation.ch/files/en_templates/temp06.html?referer=');"> 3 columns fixed</a> <a href="http://www.intensivstation.ch/files/en_templates/temp06.html" onclick="pageTracker._trackPageview('/outgoing/www.intensivstation.ch/files/en_templates/temp06.html?referer=');">centered</a>, <a href="http://www.intensivstation.ch/files/en_templates/temp11.html" onclick="pageTracker._trackPageview('/outgoing/www.intensivstation.ch/files/en_templates/temp11.html?referer=');">fixed Box totally</a><a href="http://www.intensivstation.ch/files/en_templates/temp11.html" onclick="pageTracker._trackPageview('/outgoing/www.intensivstation.ch/files/en_templates/temp11.html?referer=');">centered</a> and <a href="http://www.intensivstation.ch/files/en_templates/temp03.html" onclick="pageTracker._trackPageview('/outgoing/www.intensivstation.ch/files/en_templates/temp03.html?referer=');">3 columns, all</a><a href="http://www.intensivstation.ch/files/en_templates/temp03.html" onclick="pageTracker._trackPageview('/outgoing/www.intensivstation.ch/files/en_templates/temp03.html?referer=');">dynamic</a></p>
<p>23-<a href="http://layouts.ironmyers.com/" onclick="pageTracker._trackPageview('/outgoing/layouts.ironmyers.com/?referer=');">IM 布局</a>- IM 布局是一种简单地的CSS布局系统，IM布局提供了全A级的浏览器的支持。</p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts24.gif" alt="" width="450" height="250" /></p>
<p>你可以通过这里查看这些样例:<a href="http://www.ironmyers.com/examples/three_column_layout.html" onclick="pageTracker._trackPageview('/outgoing/www.ironmyers.com/examples/three_column_layout.html?referer=');"> The Holy Grail 3 Column Layout</a>, <a href="http://www.ironmyers.com/examples/classic_blog.html" onclick="pageTracker._trackPageview('/outgoing/www.ironmyers.com/examples/classic_blog.html?referer=');">The Classic Blog Layout </a>和<a href="http://www.ironmyers.com/examples/multi_column.html" onclick="pageTracker._trackPageview('/outgoing/www.ironmyers.com/examples/multi_column.html?referer=');"> The Multi Column Layout.</a></p>
<p>24-<a href="http://www.cssplay.co.uk/layouts/index.html" onclick="pageTracker._trackPageview('/outgoing/www.cssplay.co.uk/layouts/index.html?referer=');">CSSplay </a>- CSS布局列表</p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts25.gif" alt="" width="450" height="87" /></p>
<p>你可以通过这里查看这些样例:<a href="http://www.cssplay.co.uk/layouts/fixit.html" onclick="pageTracker._trackPageview('/outgoing/www.cssplay.co.uk/layouts/fixit.html?referer=');">Cross browser FIXED</a>, <a href="http://www.cssplay.co.uk/layouts/threecol.html" onclick="pageTracker._trackPageview('/outgoing/www.cssplay.co.uk/layouts/threecol.html?referer=');">Three columns</a> and <a href="http://www.cssplay.co.uk/layouts/frame.html" onclick="pageTracker._trackPageview('/outgoing/www.cssplay.co.uk/layouts/frame.html?referer=');">CSS Frame – The Holy Grill</a>.</p>
<p>25-<a href="http://blog.html.it/layoutgala/" onclick="pageTracker._trackPageview('/outgoing/blog.html.it/layoutgala/?referer=');">Layoutgala </a>- 基于同样的的标记l得到最大数量的不同的布局方式。没有CCS hack，没有CSS workaround ，良好的浏览器兼容性。40种不同布局。</p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts26.gif" alt="" width="450" height="180" /></p>
<p>你可以通过这里查看这些样例:<a href="http://blog.html.it/layoutgala/LayoutGala07.html" onclick="pageTracker._trackPageview('/outgoing/blog.html.it/layoutgala/LayoutGala07.html?referer=');">Three fixed Columns</a>, <a href="http://blog.html.it/layoutgala/LayoutGala04.html" onclick="pageTracker._trackPageview('/outgoing/blog.html.it/layoutgala/LayoutGala04.html?referer=');">Three percentage columns</a> and <a href="http://blog.html.it/layoutgala/LayoutGala19.html" onclick="pageTracker._trackPageview('/outgoing/blog.html.it/layoutgala/LayoutGala19.html?referer=');">Liquid, three columns, hybrid widths </a>(吐槽：没有等高，不好看).</p>
<p>26-<a href="http://www.glish.com/css/" onclick="pageTracker._trackPageview('/outgoing/www.glish.com/css/?referer=');">Glish</a>- 许多有用的跨浏览器布局技术</p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts27.gif" alt="" width="450" height="125" /></p>
<p>你可以通过这里查看这些样例: <a href="http://www.glish.com/css/7.asp" onclick="pageTracker._trackPageview('/outgoing/www.glish.com/css/7.asp?referer=');">3 columns, the holy grail</a>,<a href="http://www.glish.com/css/9.asp" onclick="pageTracker._trackPageview('/outgoing/www.glish.com/css/9.asp?referer=');"> 2 columns, ALA style</a> and <a href="http://www.glish.com/css/2.asp" onclick="pageTracker._trackPageview('/outgoing/www.glish.com/css/2.asp?referer=');">3 columns, all fluid </a></p>
<p>27-<a href="http://www.thenoodleincident.com/tutorials/box_lesson/boxes.html" onclick="pageTracker._trackPageview('/outgoing/www.thenoodleincident.com/tutorials/box_lesson/boxes.html?referer=');">Thenoodleincident</a>- CSS 从简单的单盒到3盒并增加一个顶部条，所有都是变宽。</p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts28.gif" alt="" width="450" height="140" /></p>
<p>28-<a href="http://www.bluerobot.com/web/layouts/" onclick="pageTracker._trackPageview('/outgoing/www.bluerobot.com/web/layouts/?referer=');">The Layout Reservoir</a>- 很多有用的CSS布局技术</p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts30.gif" alt="" width="450" height="225" /></p>
<p>你可以通过这里查看这些样例:<a href="http://bluerobot.com/web/layouts/layout1.html" onclick="pageTracker._trackPageview('/outgoing/bluerobot.com/web/layouts/layout1.html?referer=');"> 2 columns – left menu</a>,<a href="http://bluerobot.com/web/layouts/layout3.html" onclick="pageTracker._trackPageview('/outgoing/bluerobot.com/web/layouts/layout3.html?referer=');"> 3 columns – flanking menus</a>和<a href="http://bluerobot.com/web/css/center1.html" onclick="pageTracker._trackPageview('/outgoing/bluerobot.com/web/css/center1.html?referer=');"> Auto-width Margins </a>.</p>
<p>29-<a href="http://www.strictlycss.com/articles/article/40/the-only-css-layout-you-need" onclick="pageTracker._trackPageview('/outgoing/www.strictlycss.com/articles/article/40/the-only-css-layout-you-need?referer=');">The only CSS layout you need</a>- 在这篇文章中将会为你展现10个基于同一的HTML的不同的的布局。</p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts32.gif" alt="" width="450" height="225" /></p>
<p>你可以通过这里查看这些样例: <a href="http://www.strictlycss.com/examples/three-column-layout-1.asp" onclick="pageTracker._trackPageview('/outgoing/www.strictlycss.com/examples/three-column-layout-1.asp?referer=');"> Three column CSS layout – left and right menu</a>, <a href="http://www.strictlycss.com/examples/three-column-layout-2.asp" onclick="pageTracker._trackPageview('/outgoing/www.strictlycss.com/examples/three-column-layout-2.asp?referer=');">Two column CSS layout – top and left menu</a> 和 <a href="http://www.strictlycss.com/examples/three-column-layout-7.asp" onclick="pageTracker._trackPageview('/outgoing/www.strictlycss.com/examples/three-column-layout-7.asp?referer=');">Three column CSS fluid layout: 100% width</a></p>
<p>30-<a href="http://www.yaml.de/" onclick="pageTracker._trackPageview('/outgoing/www.yaml.de/?referer=');">另一个多栏布局</a>-是一个创建当代流行的变宽的浮动布局的XHTML/CSS框架。这是一个多功能实用的布局。</p>
<p>点击<a href="http://www.yaml.de/fileadmin/download/release_306/yaml_306_080609.zip" onclick="pageTracker._trackPageview('/outgoing/www.yaml.de/fileadmin/download/release_306/yaml_306_080609.zip?referer=');">这里</a>下载.</p>
<p>31-<a href="http://www.cssliquid.com/" onclick="pageTracker._trackPageview('/outgoing/www.cssliquid.com/?referer=');">Liquid Designs</a>- 使用XHTML和CSS的变宽设计库。</p>
<h4><strong><span style="color: #008000;">最佳实践</span></strong></h4>
<p>如果你需要寻找一些布局灵感，你可以从下面的网站链接中找到。这些站点演示了CSS布局如何应用于不同类型的网站。查看这些网站是如何分成2栏或3栏，或混合宽栏和窄栏布局。</p>
<p>32-<a href="http://helldesign.net/" onclick="pageTracker._trackPageview('/outgoing/helldesign.net/?referer=');">Helldesign</a></p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts5.jpg" alt="" width="450" height="365" /></p>
<p>33-<a href="http://silverbackapp.com/" onclick="pageTracker._trackPageview('/outgoing/silverbackapp.com/?referer=');">Silverbackapp</a></p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts12.jpg" alt="" width="450" height="325" /></p>
<p>34-<a href="http://www.os.ca/accueil.php" onclick="pageTracker._trackPageview('/outgoing/www.os.ca/accueil.php?referer=');">OS communications informatiques</a></p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts13.jpg" alt="" width="450" height="310" /></p>
<p>35-<a href="http://rockatee.com/" onclick="pageTracker._trackPageview('/outgoing/rockatee.com/?referer=');">Rockatee</a></p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts14.jpg" alt="" width="450" height="310" /></p>
<p>36-<a href="http://www.darrenhoyt.com/" onclick="pageTracker._trackPageview('/outgoing/www.darrenhoyt.com/?referer=');">Darrenhoyt</a></p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts15.jpg" alt="" width="450" height="225" /></p>
<p>37-<a href="http://www.makebetterwebsites.com/" onclick="pageTracker._trackPageview('/outgoing/www.makebetterwebsites.com/?referer=');">Makebetterwebsites</a></p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts16.jpg" alt="" width="450" height="250" /></p>
<p>38-<a href="http://elitetheme.com/" onclick="pageTracker._trackPageview('/outgoing/elitetheme.com/?referer=');">Elitetheme</a></p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts17.jpg" alt="" width="450" height="250" /></p>
<p>39-<a href="http://www.studio7designs.com/" onclick="pageTracker._trackPageview('/outgoing/www.studio7designs.com/?referer=');">Studio7designs</a></p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts18.jpg" alt="" width="450" height="250" /></p>
<p>40-<a href="http://brightcreative.com/" onclick="pageTracker._trackPageview('/outgoing/brightcreative.com/?referer=');">Brightcreative</a></p>
<p><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2012/03/css-layouts19.jpg" alt="" width="450" height="300" /></p>
<p><em>(全文完)</em></p>
<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="神奇的CSS形状" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6913.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6840.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6913.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6840.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2012/03/24/18083200.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">神奇的CSS形状</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="22个不错的CSS技术" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F648.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6840.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F648.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6840.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10438281.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">22个不错的CSS技术</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="40个很不错的CSS技术" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3063.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6840.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3063.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6840.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/06/21/13646971.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">40个很不错的CSS技术</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="30种时尚的CSS网站导航条" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F562.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6840.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F562.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6840.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/07/09/16776513.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">30种时尚的CSS网站导航条</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="CSS图形" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5164.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6840.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5164.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6840.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">CSS图形</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table><h3  class="related_post_title">相关文章</h3><ul class="related_post"><li>2011年03月04日 -- <a href="http://coolshell.cn/articles/3903.html" title="一些有意思的贴子和工具">一些有意思的贴子和工具</a></li><li>2011年02月16日 -- <a href="http://coolshell.cn/articles/3684.html" title="Web开发人员速查卡">Web开发人员速查卡</a></li><li>2010年09月28日 -- <a href="http://coolshell.cn/articles/3013.html" title="一些非常有意思的杂项资源">一些非常有意思的杂项资源</a></li><li>2009年12月15日 -- <a href="http://coolshell.cn/articles/1949.html" title="Web中的省略号">Web中的省略号</a></li><li>2011年12月07日 -- <a href="http://coolshell.cn/articles/6043.html" title="Web开发中需要了解的东西">Web开发中需要了解的东西</a></li><li>2011年11月24日 -- <a href="http://coolshell.cn/articles/5537.html" title="一些文章资源和趣闻">一些文章资源和趣闻</a></li><li>2011年09月20日 -- <a href="http://coolshell.cn/articles/5224.html" title="一些文章和各种资源">一些文章和各种资源</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/6840.html/feed</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>多版本并发控制(MVCC)在分布式系统中的应用</title>
		<link>http://coolshell.cn/articles/6790.html</link>
		<comments>http://coolshell.cn/articles/6790.html#comments</comments>
		<pubDate>Tue, 13 Mar 2012 00:36:53 +0000</pubDate>
		<dc:creator>Todd</dc:creator>
				<category><![CDATA[程序设计]]></category>
		<category><![CDATA[系统架构]]></category>
		<category><![CDATA[cas]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[lock-free]]></category>
		<category><![CDATA[mvcc]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=6790</guid>
		<description><![CDATA[【感谢 Todd投递本文 – 微博帐号：weidagang 】 问题 最近项目中遇到了一个分布式系统的并发控制问题。该问题可以抽象为：某分布式系统由一个数据中心D和若干业务处理中心L1，L2 &#8230; Ln组成；D本质上是一个key-value存储，它对外提供基于HTTP协议的CRUD操作接口。L的业务逻辑可以抽象为下面3个步骤： read: 根据keySet {k1, &#8230; kn}从D获取keyValueSet {k1:v1, &#8230; kn:vn} do: 根据keyValueSet进行业务处理，得到需要更新的数据集keyValueSet&#8217; {k1&#8242;:v1&#8242;, &#8230; km&#8217;:vm&#8217;} (注：读取的keySet和更新的keySet&#8217;可能不同) update: 把keyValueSet&#8217;更新到D （注：D保证在一次调用更新多个key的原子性） 在没有事务支持的情况下，多个L进行并发处理可能会导致数据一致性问题。比如，考虑L1和L2的如下执行顺序： L1从D读取key:123对应的值100 L2从D读取key:123对应的100 L1将key:123更新为100 + 1 L2将key:123更新为100 + 2 如果L1和L2串行执行，key:123对应的值将为103，但上面并发执行中L1的执行效果完全被L2所覆盖，实际key:123所对应的值变成了102。 解决方案1：基于锁的事务 为了让L的处理具有可串行化特性(Serializability)，一种最直接的解决方案就是考虑为D加上基于锁的简单事务。让L在进行业务处理前先锁定D，完成以后释放锁。另外，为了防止持有锁的L由于某种原因长时间未提交事务，D还需要具有超时机制，当L尝试提交一个已超时的事务时会得到一个错误响应。 本方案的优点是实现简单，缺点是锁定了整个数据集，粒度太大；时间上包含了L的整个处理时间，跨度太长。虽然我们可以考虑把锁定粒度降低到数据项级别，按key进行锁定，但这又会带来其他的问题。由于更新的keySet&#8217;可能是事先不确定的，所以可能无法在开始事务时锁定所有的key；如果分阶段来锁定需要的key，又可能出现死锁(Deadlock)问题。另外，按key锁定在有锁争用的情况下并不能解决锁定时间太长的问题。所以，按key锁定仍然存在重要的不足之处。 解决方案2：多版本并发控制 为了实现可串行化，同时避免锁机制存在的各种问题，我们可以采用基于多版本并发控制（Multiversion concurrency control，MVCC）思想的无锁事务机制。人们一般把基于锁的并发控制机制称成为悲观机制，而把MVCC机制称为乐观机制。这是因为锁机制是一种预防性的，读会阻塞写，写也会阻塞读，当锁定粒度较大，时间较长时并发性能就不会太好；而MVCC是一种后验性的，读不阻塞写，写也不阻塞读，等到提交的时候才检验是否有冲突，由于没有锁，所以读写不会相互阻塞，从而大大提升了并发性能。我们可以借用源代码版本控制来理解MVCC，每个人都可以自由地阅读和修改本地的代码，相互之间不会阻塞，只在提交的时候版本控制器会检查冲突，并提示merge。目前，Oracle、PostgreSQL和MySQL都已支持基于MVCC的并发机制，但具体实现各有不同。 MVCC的一种简单实现是基于CAS（Compare-and-swap）思想的有条件更新（Conditional Update）。普通的update参数只包含了一个keyValueSet&#8217;，Conditional Update在此基础上加上了一组更新条件conditionSet { &#8230; data[keyx]=valuex, &#8230; }，即只有在D满足更新条件的情况下才将数据更新为keyValueSet&#8217;；否则，返回错误信息。这样，L就形成了如下图所示的Try/Conditional Update/(Try again)的处理模式： 虽然对单个L来讲不能保证每次都成功更新，但从整个系统来看，总是有任务能够顺利进行。这种方案利用Conditional Update避免了大粒度和长时间的锁定，当各个业务之间资源争用不大的情况下，并发性能很好。不过，由于Conditional [...]<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="Titanium - 桌面和移动应用开发平台" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2117.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6790.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2117.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6790.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/06/21/13642141.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Titanium - 桌面和移动应用开发平台</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="别只谈系统备份，谈谈怎样恢复系统吧！" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2155.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6790.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2155.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6790.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">别只谈系统备份，谈谈怎样恢复系统吧！</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Martin Fowler 在 ThoughtWorks 内部关于版本控制工具的调查" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2135.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6790.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2135.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6790.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Martin Fowler 在 ThoughtWorks 内部关于版本控制工具的调查</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Eclipse开发Android应用程序入门:重装上阵" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F4334.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6790.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F4334.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6790.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/06/21/13628553.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Eclipse开发Android应用程序入门:重装上阵</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="一张关于操作系统的图" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1579.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6790.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1579.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6790.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/05/04/7521504.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">一张关于操作系统的图</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table>]]></description>
			<content:encoded><![CDATA[<p>【<span style="color: #cc0000">感谢 Todd投递本文 – 微博帐号：</span><a title="weidagang" href="http://weibo.com/weidagang" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/weidagang?referer=');">weidagang</a> 】</p>
<h4>问题</h4>
<p>最近项目中遇到了一个分布式系统的并发控制问题。该问题可以抽象为：某分布式系统由一个数据中心D和若干业务处理中心L1，L2 &#8230; Ln组成；D本质上是一个key-value存储，它对外提供基于HTTP协议的CRUD操作接口。L的业务逻辑可以抽象为下面3个步骤：</p>
<ol>
<li>read: 根据keySet {k1, &#8230; kn}从D获取keyValueSet {k1:v1, &#8230; kn:vn}</li>
<li>do: 根据keyValueSet进行业务处理，得到需要更新的数据集keyValueSet&#8217; {k1&#8242;:v1&#8242;, &#8230; km&#8217;:vm&#8217;} (<strong>注</strong>：读取的keySet和更新的keySet&#8217;可能不同)</li>
<li>update: 把keyValueSet&#8217;更新到D （<strong>注</strong>：D保证在一次调用更新多个key的原子性）</li>
</ol>
<p>在没有事务支持的情况下，多个L进行并发处理可能会导致数据一致性问题。比如，考虑L1和L2的如下执行顺序：</p>
<ol>
<li>L1从D读取key:123对应的值100</li>
<li>L2从D读取key:123对应的100</li>
<li>L1将key:123更新为100 + 1</li>
<li>L2将key:123更新为100 + 2</li>
</ol>
<p>如果L1和L2串行执行，key:123对应的值将为103，但上面并发执行中L1的执行效果完全被L2所覆盖，实际key:123所对应的值变成了102。</p>
<p><span id="more-6790"></span></p>
<h4>解决方案1：基于锁的事务</h4>
<p>为了让L的处理具有可串行化特性(Serializability)，一种最直接的解决方案就是考虑为D加上基于锁的简单事务。让L在进行业务处理前先锁定D，完成以后释放锁。另外，为了防止持有锁的L由于某种原因长时间未提交事务，D还需要具有超时机制，当L尝试提交一个已超时的事务时会得到一个错误响应。</p>
<p><img src="http://images.cnblogs.com/cnblogs_com/weidagang2046/362318/o_conditional_update_1.PNG" alt="" /></p>
<p>本方案的优点是实现简单，缺点是锁定了整个数据集，粒度太大；时间上包含了L的整个处理时间，跨度太长。虽然我们可以考虑把锁定粒度降低到数据项级别，按key进行锁定，但这又会带来其他的问题。由于更新的keySet&#8217;可能是事先不确定的，所以可能无法在开始事务时锁定所有的key；如果分阶段来锁定需要的key，又可能出现死锁(Deadlock)问题。另外，按key锁定在有锁争用的情况下并不能解决锁定时间太长的问题。所以，按key锁定仍然存在重要的不足之处。</p>
<h4>解决方案2：多版本并发控制</h4>
<p>为了实现可串行化，同时避免锁机制存在的各种问题，我们可以采用基于多版本并发控制（Multiversion concurrency control，MVCC）思想的无锁事务机制。人们一般把基于锁的并发控制机制称成为悲观机制，而把MVCC机制称为乐观机制。这是因为锁机制是一种预防性的，读会阻塞写，写也会阻塞读，当锁定粒度较大，时间较长时并发性能就不会太好；而MVCC是一种后验性的，读不阻塞写，写也不阻塞读，等到提交的时候才检验是否有冲突，由于没有锁，所以读写不会相互阻塞，从而大大提升了并发性能。我们可以借用源代码版本控制来理解MVCC，每个人都可以自由地阅读和修改本地的代码，相互之间不会阻塞，只在提交的时候版本控制器会检查冲突，并提示merge。目前，Oracle、PostgreSQL和MySQL都已支持基于MVCC的并发机制，但具体实现各有不同。</p>
<p>MVCC的一种简单实现是基于CAS（Compare-and-swap）思想的有条件更新（Conditional Update）。普通的update参数只包含了一个keyValueSet&#8217;，Conditional Update在此基础上加上了一组更新条件conditionSet { &#8230; data[keyx]=valuex, &#8230; }，即只有在D满足更新条件的情况下才将数据更新为keyValueSet&#8217;；否则，返回错误信息。这样，L就形成了如下图所示的Try/Conditional Update/(Try again)的处理模式：</p>
<p><img src="http://images.cnblogs.com/cnblogs_com/weidagang2046/362318/o_mvcc_2.png" alt="" /></p>
<p>虽然对单个L来讲不能保证每次都成功更新，但从整个系统来看，总是有任务能够顺利进行。这种方案利用Conditional Update避免了大粒度和长时间的锁定，当各个业务之间资源争用不大的情况下，并发性能很好。不过，由于Conditional Update需要更多的参数，如果condition中value的长度很长，那么每次网络传送的数据量就会比较大，从而导致性能下降。特别是当需要更新的keyValueSet&#8217;很小，而condition很大时，就显得非常不经济。</p>
<p>为了避免condition太大所带来的性能问题，可以为每条数据项增加一个int型的版本号字段，由D维护该版本号，每次数据有更新就增加版本号；L在进行Conditional Update时，通过版本号取代具体的值。</p>
<p><img src="http://images.cnblogs.com/cnblogs_com/weidagang2046/362318/o_mvcc_3.png" alt="" /></p>
<p>另一个问题是上面的解决方案假设了D是可以支持Conditional Update的；那么，如果D是一个不支持Conditional Update的第三方的key-value存储怎么办呢？这时，我们可以在L和D之间增加一个P作为代理，所有的CRUD操作都必须经过P，让P来进行条件检查，而实际的数据操作放在D。这种方式实现了条件检查和数据操作的分离，但同时降低了性能，需要在P中增加cache，提升性能。由于P是D的唯一客户端；所以，P的cache管理是非常简单的，不必像多客户端情形担心缓存的失效。不过，实际上，据我所知redis和Amazon SimpleDB都已经有了Conditional Update的支持。</p>
<h4>悲观锁和MVCC对比</h4>
<p>上面介绍了悲观锁和MVCC的基本原理，但是对于它们分别适用于什么场合，不同的场合下两种机制优劣具体表现在什么地方还不是很清楚。这里我就对一些典型的应用场景进行简单的分析。需要注意的是下面的分析不针对分布式，悲观锁和MVCC两种机制在分布式系统、单数据库系统、甚至到内存变量各个层次都存在。</p>
<p>### 场景1：对读的响应速度要求高</p>
<p>有一类系统更新特别频繁，并且对读的响应速度要求很高，如股票交易系统。在悲观锁机制下，写会阻塞读，那么当有写操作时，读操作的响应速度就会受到影响；而MVCC不存在读写锁，读操作是不受任何阻塞的，所以读的响应速度会更快更稳定。</p>
<p>### 场景2：读远多于写</p>
<p>对于许多系统来讲，读操作的比例往往远大于写操作，特别是某些海量并发读的系统。在悲观锁机制下，当有写操作占用锁，就会有大量的读操作被阻塞，影响并发性能；而MVCC可以保持比较高且稳定的读并发能力。</p>
<p>### 场景3：写操作冲突频繁</p>
<p>如果系统中写操作的比例很高，且冲突频繁，这时就需要仔细评估。假设两个有冲突的业务L1和L2，它们在单独执行是分别耗时t1，t2。在悲观锁机制下，它们的总时间大约等于串行执行的时间：</p>
<p>    T = t1 + t2</p>
<p>而在MVCC下，假设L1在L2之前更新，L2需要retry一次，它们的总时间大约等于L2执行两次的时间（这里假设L2的两次执行耗时相等，更好的情况是，如果第1次能缓存下部分有效结果，第二次执行L2耗时是可能减小的）：</p>
<p>    T&#8217; = 2 * t2</p>
<p>这时关键是要评估retry的代价，如果retry的代价很低，比如，对某个计数器递增，又或者第二次执行可以比第一次快很多，这时采用MVCC机制就比较适合。反之，如果retry的代价很大，比如，报表统计运算需要算几小时甚至一天那就应该采用锁机制避免retry。</p>
<p>从上面的分析，我们可以简单的得出这样的结论：对读的响应速度和并发性要求比较高的场景适合MVCC；而retry代价越大的场景越适合悲观锁机制。</p>
<h4>总结</h4>
<p>本文介绍了一种基于多版本并发控制（MVCC）思想的Conditional Update解决分布式系统并发控制问题的方法。和基于悲观锁的方法相比，该方法避免了大粒度和长时间的锁定，能更好地适应对读的响应速度和并发性要求高的场景。</p>
<h4>参考</h4>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Serializability" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Serializability?referer=');">Wikipedia &#8211; Serializability</a></li>
<li><a href="http://en.wikipedia.org/wiki/Compare-and-swap" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Compare-and-swap?referer=');">Wikipedia &#8211; Compare-and-swap</a></li>
<li><a href="http://en.wikipedia.org/wiki/Multiversion_concurrency_control" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Multiversion_concurrency_control?referer=');">Wikipedia &#8211; Multiversion concurrency control</a></li>
<li><a href="http://blogs.msdn.com/b/oldnewthing/archive/2011/04/12/10152296.aspx" onclick="pageTracker._trackPageview('/outgoing/blogs.msdn.com/b/oldnewthing/archive/2011/04/12/10152296.aspx?referer=');">Lock-free algorithms: The try/commit/(try again) pattern</a></li>
<li><a href="http://aws.amazon.com/simpledb/faqs/#Does_Amazon_SimpleDB_support_transactions" onclick="pageTracker._trackPageview('/outgoing/aws.amazon.com/simpledb/faqs/_Does_Amazon_SimpleDB_support_transactions?referer=');">Amazon SimpleDB FAQs &#8211; Does Amazon SimpleDB support transactions?</a></li>
<li><a href="http://redis.io/topics/transactions" onclick="pageTracker._trackPageview('/outgoing/redis.io/topics/transactions?referer=');">redis &#8211; Transactions</a></li>
<li><a href="http://simpledbm.googlecode.com/files/mvcc-survey-1.0.pdf" onclick="pageTracker._trackPageview('/outgoing/simpledbm.googlecode.com/files/mvcc-survey-1.0.pdf?referer=');">A Quick Survey of MultiVersion Concurrency Algorithms</a></li>
<li><a href="http://www.cnblogs.com/jobs/archive/2007/11/13/957446.html" onclick="pageTracker._trackPageview('/outgoing/www.cnblogs.com/jobs/archive/2007/11/13/957446.html?referer=');">非阻塞算法思想在关系数据库应用程序开发中的使用</a></li>
</ul>
<h4>友情推荐</h4>
<p>本文的图是用我自己开发的<a href="http://textdiagram.sinaapp.com" onclick="pageTracker._trackPageview('/outgoing/textdiagram.sinaapp.com?referer=');">TextDiagram</a>工具画的，欢迎试用！如果您喜欢，请推荐给朋友，谢谢！</p>
<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="Titanium - 桌面和移动应用开发平台" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2117.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6790.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2117.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6790.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/06/21/13642141.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Titanium - 桌面和移动应用开发平台</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="别只谈系统备份，谈谈怎样恢复系统吧！" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2155.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6790.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2155.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6790.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">别只谈系统备份，谈谈怎样恢复系统吧！</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Martin Fowler 在 ThoughtWorks 内部关于版本控制工具的调查" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2135.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6790.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2135.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6790.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Martin Fowler 在 ThoughtWorks 内部关于版本控制工具的调查</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Eclipse开发Android应用程序入门:重装上阵" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F4334.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6790.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F4334.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6790.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/06/21/13628553.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Eclipse开发Android应用程序入门:重装上阵</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="一张关于操作系统的图" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1579.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6790.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1579.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6790.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/05/04/7521504.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">一张关于操作系统的图</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table><h3  class="related_post_title">相关文章</h3><ul class="related_post"><li>2012年01月16日 -- <a href="http://coolshell.cn/articles/6470.html" title="由12306.cn谈谈网站性能技术 ">由12306.cn谈谈网站性能技术 </a></li><li>2012年05月03日 -- <a href="http://coolshell.cn/articles/7236.html" title="用Unix的设计思想来应对多变的需求">用Unix的设计思想来应对多变的需求</a></li><li>2012年03月26日 -- <a href="http://coolshell.cn/articles/6950.html" title="需求变化与IoC">需求变化与IoC</a></li><li>2012年03月09日 -- <a href="http://coolshell.cn/articles/6775.html" title="Bret Victor &#8211; Inventing on Principle">Bret Victor &#8211; Inventing on Principle</a></li><li>2012年02月02日 -- <a href="http://coolshell.cn/articles/6548.html" title="Why C++ ? 王者归来">Why C++ ? 王者归来</a></li><li>2011年10月25日 -- <a href="http://coolshell.cn/articles/5686.html" title="多些时间能少写些代码">多些时间能少写些代码</a></li><li>2011年09月20日 -- <a href="http://coolshell.cn/articles/5224.html" title="一些文章和各种资源">一些文章和各种资源</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/6790.html/feed</wfw:commentRss>
		<slash:comments>36</slash:comments>
		</item>
		<item>
		<title>Bret Victor &#8211; Inventing on Principle</title>
		<link>http://coolshell.cn/articles/6775.html</link>
		<comments>http://coolshell.cn/articles/6775.html#comments</comments>
		<pubDate>Fri, 09 Mar 2012 00:38:48 +0000</pubDate>
		<dc:creator>陈皓</dc:creator>
				<category><![CDATA[技术新闻]]></category>
		<category><![CDATA[杂项资源]]></category>
		<category><![CDATA[程序设计]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Bret Victor]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Programmer]]></category>
		<category><![CDATA[程序员]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=6775</guid>
		<description><![CDATA[Bret Victor（简历） &#8211; 苹果公司的UI交互设计师（大神级的人），在 CUSEC（Canadian University Software Engineering Conference） 上做了一个题为 “Inventing on Principle” 的演讲（vimeo视频链接），这个演讲中展示了五个示例： 用程序画树。如何把程序绘图变成实时的，如何把程序和图映射起来。 游戏调试。在实时编程的基础上，可以更容易的让你看到程序参数对游戏的调整，甚至对游戏过程的可视化调试。 算法调试。在写二分查找算法时可以实时看到程序的执行过程。边写边看到。 电路图。可以实时地看到电路图中各个部件的对1/0信号的处理。 动画。一种比flash制作动画更NB 的方法。 下面是优酷上的视频——你一定会被示例中的那些编程工具所震撼！ 不过，Bret并不是在说什么编程，也不是在说什么技术，他是在说 How to live your life。 他认为，在我们的生活当中，我们听到太多的诸如：“跟随你的喜好”、“跟随你的兴趣”，“跟随你的热情”之类的东西，但他更认为，更应该是“跟随一个原则 follow you principle”，他认为真正能让你把事做正确的不是你的喜好，不是你的兴趣，也不是热情，而一个做事的原则。在这个演讲中Bret介绍了他自己的原则和他人的原则，供你参考和并找到你的原则从而live in your life。 Bret的原则是，他觉得人总是会有很多想法，而把这些想法变成现实是一件非常重要的事，也是最难的事。他觉得当我们在写代码实现一个东西的时候，在实现一个游戏，算法，电路，动画的时候，人很难把自己脑海里的东西映射成现实的东西，因为一个想法变成现实，需要反反复复的调整，如果看不见，就没办法调整。而我们在写好程序，需要编译程序，运行程序，才能看到结果，之后，有些东西发现并不满意，需要做调整，于是需要猜着去改一下程序，再编译运行，再看结果，于是，这个调整的过程相当令人痛苦，因为代码里的那些数字，我需要一点一点地去试，调大调小，总是不能调到我们想要的结果，从而让人无法正常思考。所以，他的原则是——创造者需要对自己的创造的东西有实时的反馈。于是出现了视频中的实时编程的那些示例。（其实，这个东西和Firebug很相似，我还记得以前和朋友说过，如果写C/C++程序也能有像Firebug的这种工具就好了，现在果然离实现不远了） Bret说起他的动机的时候，他说，他把这个事当成了一种责任而不是一种机会。他说，这就好像我们听到的：审查机制，性别歧视，环境破坏，违反人权等这些问题，绝大多数人是不会把这些事当成一个机会的，而那些有责任感的人会把解决这些问题当作一种责任。同样，当他看到我们被工具或环境限制住了我们创造东西的过程时，他并不觉得这是一个可以发明更好的产品的机会，甚至这是开创自己事业的机会，或是对社会做贡献的机会。他认为想法相当的宝贵，如果一个好的想法推动不了的时候，他会很难受，就像看到一场灾难一样，他觉得，让大家的想法能够顺的进行，这是他的一个责任。 后面他，举到了很多人的例子， Larry Tesler &#8211; 著名的计算机科学家，前苹果的首席科学家，图形界面的创造者（在“SteveY对Amazon和Google平台的长篇大论”中提到过他）。他在70年代看到人们在使用电脑文本编辑器时，需要按某个键进入某种模式（Mode），然后才能输入（VI）。他觉得这样操作起来很复杂，也很不舒服，所以，他为自己设定了一个原则——“Don&#8217;t Mode Me In”，他做了很多尝试，做了一个叫Gypsy的文档编辑器，可以通过拖拽移动字符，而且他还发明了复制粘贴，对于一个没有使用过电脑的人来说，只需半个小时的训练就可以输入文字了。Larry把消除模式设置成了自己的原则或责任。他的个人主页是：http://www.nomodes.com，他的Twitter是 @nomodes，甚至他的车牌也是nomodes. Elizabeth Cady Stanton，100年前的一个美国的女权主义者，当时，她主张妇女的各项权益，比如参与投票，所有人都以为他疯了，今天看来，她是对的，她消除了性别歧视。这和Larry 很相似，他们都看到了一种文化上的错误，并要预见到了未来的样子，他们都为自己设定了一个原则或是信仰，而去为之奋斗。 Doug Engelbart，美国发明家，瑞典人和挪威人后裔。最广为人知的是他发明了鼠标，另外他的小组是人机交互的先锋，开发了超文本系统、网络计算机，以及图形用户界面的先驱；并致力于倡导运用计算机和网络，来协同解决世界上日益增长的紧急而又复杂的问题。 Alan Kay，美国计算机科学家，在面向对象编程和窗口式图形用户界面方面作出了先驱性贡献。2003年获得图灵奖。目前担任Viewpoints研究院院长，加州大学伯克利分校兼职教授。曾任Apple公司院士，惠普公司资深院士。他有一句尽人皆知的名言——预测未来的最好办法就是创造未来。他相信如果小孩能够熟练掌握电脑，如果写程序是和读书写字一样成为基础知识，那么人们就掌握了一种新的方式去思考，新的方式去了解世界。他所有发明的东西都基于他自己的原则或信条。 Richard Stallman，是美国自由软件运动的精神领袖、GNU计划以及自由软件基金会（Free [...]<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="惹恼程序员的十件事" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F340.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6775.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F340.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6775.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/02/12/2675402.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">惹恼程序员的十件事</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="程序员需要具备的基本技能" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F428.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6775.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F428.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6775.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">程序员需要具备的基本技能</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="做个环保主义的程序员" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7186.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6775.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7186.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6775.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2012/04/27/23798602.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">做个环保主义的程序员</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="未来五年程序员需要掌握的10项技能" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F511.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6775.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F511.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6775.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">未来五年程序员需要掌握的10项技能</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="程序员的八个级别" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F343.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6775.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F343.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6775.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10437645.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">程序员的八个级别</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table>]]></description>
			<content:encoded><![CDATA[<p><a href="http://worrydream.com" target="_blank" onclick="pageTracker._trackPageview('/outgoing/worrydream.com?referer=');">Bret Victor</a>（<a href="http://worrydream.com/#!/cv/bret_victor_resume.pdf" target="_blank" onclick="pageTracker._trackPageview('/outgoing/worrydream.com/_/cv/bret_victor_resume.pdf?referer=');">简历</a>） &#8211; 苹果公司的UI交互设计师（大神级的人），在 <a href="http://cusec.net" target="_blank" onclick="pageTracker._trackPageview('/outgoing/cusec.net?referer=');">CUSEC</a>（<em>Canadian University Software Engineering Conference</em>） 上做了一个题为 “Inventing on Principle” 的演讲（<a href="http://vimeo.com/36579366" target="_blank" onclick="pageTracker._trackPageview('/outgoing/vimeo.com/36579366?referer=');">vimeo视频链接</a>），这个演讲中展示了五个示例：</p>
<ul>
<li>用程序画树。如何把程序绘图变成实时的，如何把程序和图映射起来。</li>
<li>游戏调试。在实时编程的基础上，可以更容易的让你看到程序参数对游戏的调整，甚至对游戏过程的可视化调试。</li>
<li>算法调试。在写二分查找算法时可以实时看到程序的执行过程。边写边看到。</li>
<li>电路图。可以实时地看到电路图中各个部件的对1/0信号的处理。</li>
<li>动画。一种比flash制作动画更NB 的方法。</li>
</ul>
<p>下面是优酷上的视频——你一定会被示例中的那些编程工具所震撼！</p>
<p><center><embed src="http://player.youku.com/player.php/sid/XMzUyOTIyNzg0/v.swf" allowFullScreen="true" quality="high" width="480" height="400" align="middle" allowScriptAccess="always" type="application/x-shockwave-flash"></embed></center></p>
<p>不过，Bret并不是在说什么编程，也不是在说什么技术，他是在说 How to live your life。</p>
<p><span id="more-6775"></span></p>
<p>他认为，在我们的生活当中，我们听到太多的诸如：“跟随你的喜好”、“跟随你的兴趣”，“跟随你的热情”之类的东西，但他更认为，更应该是“跟随一个原则 follow you principle”，他认为真正能让你把事做正确的不是你的喜好，不是你的兴趣，也不是热情，而一个做事的原则。在这个演讲中Bret介绍了他自己的原则和他人的原则，供你参考和并找到你的原则从而live in your life。</p>
<p>Bret的原则是，他觉得人总是会有很多想法，而把这些想法变成现实是一件非常重要的事，也是最难的事。他觉得当我们在写代码实现一个东西的时候，在实现一个游戏，算法，电路，动画的时候，人很难把自己脑海里的东西映射成现实的东西，因为一个想法变成现实，需要反反复复的调整，如果看不见，就没办法调整。而我们在写好程序，需要编译程序，运行程序，才能看到结果，之后，有些东西发现并不满意，需要做调整，于是需要猜着去改一下程序，再编译运行，再看结果，于是，这个调整的过程相当令人痛苦，因为代码里的那些数字，我需要一点一点地去试，调大调小，总是不能调到我们想要的结果，从而让人无法正常思考。所以，他的原则是——<strong>创造者需要对自己的创造的东西有实时的反馈</strong>。于是出现了视频中的实时编程的那些示例。（其实，这个东西和Firebug很相似，我还记得以前和朋友说过，如果写C/C++程序也能有像Firebug的这种工具就好了，现在果然离实现不远了）</p>
<p>Bret说起他的动机的时候，他说，他把这个事当成了一种责任而不是一种机会。他说，这就好像我们听到的：审查机制，性别歧视，环境破坏，违反人权等这些问题，绝大多数人是不会把这些事当成一个机会的，而那些有责任感的人会把解决这些问题当作一种责任。同样，当他看到我们被工具或环境限制住了我们创造东西的过程时，他并不觉得这是一个可以发明更好的产品的机会，甚至这是开创自己事业的机会，或是对社会做贡献的机会。他认为想法相当的宝贵，如果一个好的想法推动不了的时候，他会很难受，就像看到一场灾难一样，他觉得，让大家的想法能够顺的进行，这是他的一个责任。</p>
<p>后面他，举到了很多人的例子，</p>
<p style="padding-left: 30px;"><a href="http://en.wikipedia.org/wiki/Larry_Tesler" target="_blank" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Larry_Tesler?referer=');">Larry Tesler</a> &#8211; 著名的计算机科学家，前苹果的首席科学家，图形界面的创造者（在“<a title="SteveY对Amazon和Google平台的长篇大论" href="http://coolshell.cn/articles/5701.html" target="_blank">SteveY对Amazon和Google平台的长篇大论</a>”中提到过他）。他在70年代看到人们在使用电脑文本编辑器时，需要按某个键进入某种模式（Mode），然后才能输入（VI）。他觉得这样操作起来很复杂，也很不舒服，所以，他为自己设定了一个原则——“Don&#8217;t Mode Me In”，他做了很多尝试，做了一个叫Gypsy的文档编辑器，可以通过拖拽移动字符，而且他还发明了复制粘贴，对于一个没有使用过电脑的人来说，只需半个小时的训练就可以输入文字了。Larry把消除模式设置成了自己的原则或责任。他的个人主页是：http://www.nomodes.com，他的Twitter是 @nomodes，甚至他的车牌也是nomodes.</p>
<p style="padding-left: 30px;"><a href="http://en.wikipedia.org/wiki/Elizabeth_Cady_Stanton" target="_blank" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Elizabeth_Cady_Stanton?referer=');">Elizabeth Cady Stanton</a>，100年前的一个美国的女权主义者，当时，她主张妇女的各项权益，比如参与投票，所有人都以为他疯了，今天看来，她是对的，她消除了性别歧视。这和Larry 很相似，他们都看到了一种文化上的错误，并要预见到了未来的样子，他们都为自己设定了一个原则或是信仰，而去为之奋斗。</p>
<p style="padding-left: 30px;"><a href="http://en.wikipedia.org/wiki/Doug_Engelbart" target="_blank" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Doug_Engelbart?referer=');">Doug Engelbart</a>，美国发明家，瑞典人和挪威人后裔。最广为人知的是他发明了鼠标，另外他的小组是人机交互的先锋，开发了超文本系统、网络计算机，以及图形用户界面的先驱；并致力于倡导运用计算机和网络，来协同解决世界上日益增长的紧急而又复杂的问题。</p>
<p style="padding-left: 30px;"><a href="http://en.wikipedia.org/wiki/Alan_Kay" target="_blank" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Alan_Kay?referer=');">Alan Kay</a>，美国计算机科学家，在面向对象编程和窗口式图形用户界面方面作出了先驱性贡献。2003年获得图灵奖。目前担任Viewpoints研究院院长，加州大学伯克利分校兼职教授。曾任Apple公司院士，惠普公司资深院士。他有一句尽人皆知的名言——预测未来的最好办法就是创造未来。他相信如果小孩能够熟练掌握电脑，如果写程序是和读书写字一样成为基础知识，那么人们就掌握了一种新的方式去思考，新的方式去了解世界。他所有发明的东西都基于他自己的原则或信条。</p>
<p style="padding-left: 30px;"><a href="http://en.wikipedia.org/wiki/Richard_Stallman" target="_blank" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Richard_Stallman?referer=');">Richard Stallman</a>，是美国自由软件运动的精神领袖、GNU计划以及自由软件基金会（Free Software Foundation）的创立者。作为一个著名的黑客，他的主要成就包括Emacs及后来的GNU Emacs，GNU C 编译器及GDB 调试器。他所写作的GNU通用公共许可证（GNU GPL）是世上最广为采用的自由软件许可证，为copyleft观念开拓出一条崭新的道路。他的原则，是软件必须是自由的，他认为软件的自由是关乎道义上的对错的，关系到人类的自由。他没车没房没结婚没孩子，也不用手机，但他有非常忠实自由的信条和责任感。</p>
<p>Bret通过这些例子继续强调——他并不是要大家样做，他只是给大家一个选择。你可以成为一个非常优秀的工程师，非常熟练地掌握了一些技术，你也可以为这个社会做很多贡献，这是成为一个工匠的路，也是大多数人走的路。不过旁边还有一条路，值得去走，那就是解决问题的路，这条路往一头走是创业者，往另一头走是学者，但你需要找到一个你自己的原则，你可能需要很长时间才能找到你的原则，Bret说他花了10年才搞清楚他的原则是什么。</p>
<p>个人以为，Bret所说这个原则也好，信条也好，是一种对自己创造力有引导性质的原则和信条，并不是那些已有的原则或信条，否则那只不过是在跟从了，所以，这些原则和信条应该是新的东西，是自己悟出来的东西，这样的原则和信条会导致你有一种责任感向正确的方向去创造。当然，这些原则也不是那些非常笼统和模糊的东西，比如，要创业开公司，要设计出有更好的用户体验的东西，要创造有很多用户使用的产品，或是有更好的收入什么的。其应该是明确的，有指导性的，就像Bret他自己的信条一样——“创造者需要即时的反馈”，就像他演示的那样，当你在一行一行修改你的代码的时候，你可以立即看到代码运行的过程和效果。这个原则可以指导着他要对一切达不到这个原则的东西负责，并引导着他知道应该做什么，不应该做什么，从而去创造新的东西，解决问题。</p>
<p>当然，世界是多元的，每个人都有每个人自己的原则。不同的原则必然会把你导到不同的路上。不管你是否同意，视频中的那些演示是相当令人震撼的。</p>
<p>（全文完）</p>
<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="惹恼程序员的十件事" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F340.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6775.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F340.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6775.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/02/12/2675402.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">惹恼程序员的十件事</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="程序员需要具备的基本技能" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F428.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6775.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F428.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6775.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">程序员需要具备的基本技能</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="做个环保主义的程序员" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F7186.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6775.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F7186.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6775.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2012/04/27/23798602.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">做个环保主义的程序员</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="未来五年程序员需要掌握的10项技能" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F511.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6775.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F511.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6775.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">未来五年程序员需要掌握的10项技能</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="程序员的八个级别" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F343.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6775.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F343.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6775.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10437645.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">程序员的八个级别</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table><h3  class="related_post_title">相关文章</h3><ul class="related_post"><li>2011年10月25日 -- <a href="http://coolshell.cn/articles/5686.html" title="多些时间能少写些代码">多些时间能少写些代码</a></li><li>2011年09月08日 -- <a href="http://coolshell.cn/articles/5444.html" title="千万不要把 bool 设计成函数参数">千万不要把 bool 设计成函数参数</a></li><li>2011年06月10日 -- <a href="http://coolshell.cn/articles/4811.html" title="软件真的好难做啊">软件真的好难做啊</a></li><li>2012年04月27日 -- <a href="http://coolshell.cn/articles/7186.html" title="做个环保主义的程序员">做个环保主义的程序员</a></li><li>2012年04月19日 -- <a href="http://coolshell.cn/articles/7126.html" title="这到底是谁之错？">这到底是谁之错？</a></li><li>2012年04月17日 -- <a href="http://coolshell.cn/articles/7048.html" title="挑战无处不在">挑战无处不在</a></li><li>2012年04月11日 -- <a href="http://coolshell.cn/articles/6994.html" title="我们需要专职的QA吗？">我们需要专职的QA吗？</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/6775.html/feed</wfw:commentRss>
		<slash:comments>43</slash:comments>
		</item>
		<item>
		<title>理解Javascript的闭包</title>
		<link>http://coolshell.cn/articles/6731.html</link>
		<comments>http://coolshell.cn/articles/6731.html#comments</comments>
		<pubDate>Wed, 07 Mar 2012 00:30:43 +0000</pubDate>
		<dc:creator>Neo</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[编程语言]]></category>
		<category><![CDATA[ECMAScript]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[OOP]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=6731</guid>
		<description><![CDATA[【感谢 Neo 投递本文 &#8211; 微博帐号：_锟_ 】 前言：还是一篇入门文章。Javascript中有几个非常重要的语言特性——对象、原型继承、闭包。其中闭包对于那些使用传统静态语言C/C++的程序员来说是一个新的语言特性。本文将以例子入手来介绍Javascript闭包的语言特性，并结合一点ECMAScript语言规范来使读者可以更深入的理解闭包。 注：本文是入门文章，例子素材整理于网络，如果你是高手，欢迎针对文章提出技术性建议和意见。本文讨论的是Javascript，不想做语言对比，如果您对Javascript天生不适，请自行绕道。 什么是闭包 闭包是什么?闭包是Closure，这是静态语言所不具有的一个新特性。但是闭包也不是什么复杂到不可理解的东西，简而言之，闭包就是： 闭包就是函数的局部变量集合，只是这些局部变量在函数返回后会继续存在。 闭包就是就是函数的“堆栈”在函数返回后并不释放，我们也可以理解为这些函数堆栈并不在栈上分配而是在堆上分配 当在一个函数内定义另外一个函数就会产生闭包 上面的第二定义是第一个补充说明，抽取第一个定义的主谓宾——闭包是函数的‘局部变量’集合。只是这个局部变量是可以在函数返回后被访问。（这个不是官方定义，但是这个定义应该更有利于你理解闭包） 做为局部变量都可以被函数内的代码访问，这个和静态语言是没有差别。闭包的差别在于局部变变量可以在函数执行结束后仍然被函数外的代码访问。这意味着函数必须返回一个指向闭包的“引用”，或将这个”引用”赋值给某个外部变量，才能保证闭包中局部变量被外部代码访问。当然包含这个引用的实体应该是一个对象，因为在Javascript中除了基本类型剩下的就都是对象了。可惜的是，ECMAScript并没有提供相关的成员和方法来访问闭包中的局部变量。但是在ECMAScript中，函数对象中定义的内部函数(inner function)是可以直接访问外部函数的局部变量，通过这种机制，我们就可以以如下的方式完成对闭包的访问了。 上述代码的执行结果是：Hello Closure，因为sayHello()函数在greeting函数执行完毕后，仍然可以访问到了定义在其之内的局部变量text。 好了，这个就是传说中闭包的效果，闭包在Javascript中有多种应用场景和模式，比如Singleton，Power Constructor等这些Javascript模式都离不开对闭包的使用。 ECMAScript闭包模型 ECMAScript到底是如何实现闭包的呢？想深入了解的亲们可以获取ECMAScript 规范进行研究，我这里也只做一个简单的讲解，内容也是来自于网络。 在ECMAscript的脚本的函数运行时，每个函数关联都有一个执行上下文场景(Execution Context) ，这个执行上下文场景中包含三个部分 文法环境（The LexicalEnvironment） 变量环境（The VariableEnvironment） this绑定 其中第三点this绑定与闭包无关，不在本文中讨论。文法环境中用于解析函数执行过程使用到的变量标识符。我们可以将文法环境想象成一个对象，该对象包含了两个重要组件，环境记录(Enviroment Recode)，和外部引用(指针)。环境记录包含包含了函数内部声明的局部变量和参数变量，外部引用指向了外部函数对象的上下文执行场景。全局的上下文场景中此引用值为NULL。这样的数据结构就构成了一个单向的链表，每个引用都指向外层的上下文场景。 例如上面我们例子的闭包模型应该是这样，sayHello函数在最下层，上层是函数greeting，最外层是全局场景。如下图： 因此当sayHello被调用的时候，sayHello会通过上下文场景找到局部变量text的值，因此在屏幕的对话框中显示出”Hello Closure” 变量环境(The VariableEnvironment)和文法环境的作用基本相似，具体的区别请参看ECMAScript的规范文档。 闭包的样列 前面的我大致了解了Javascript闭包是什么，闭包在Javascript是怎么实现的。下面我们通过针对一些例子来帮助大家更加深入的理解闭包，下面共有5个样例，例子来自于JavaScript Closures For Dummies(镜像)。 例子1:闭包中局部变量是引用而非拷贝 因此执行结果应该弹出的667而非666。 例子2：多个函数绑定同一个闭包，因为他们定义在同一个函数内。 例子3：当在一个循环中赋值函数时，这些函数将绑定同样的闭包 testList的执行结果是弹出item3 undefined窗口三次，因为这三个函数绑定了同一个闭包，而且item的值为最后计算的结果，但是当i跳出循环时i值为4，所以list[4]的结果为undefined. 例子4：外部函数所有局部变量都在闭包内，即使这个变量声明在内部函数定义之后。 执行结果是弹出”Hello Alice”的窗口。即使局部变量声明在函数sayAlert之后，局部变量仍然可以被访问到。 例子5：每次函数调用的时候创建一个新的闭包 闭包的应用 Singleton 单件： [...]<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="再谈javascript面向对象编程 " style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6668.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6731.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6668.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6731.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2012/02/27/16161591.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">再谈javascript面向对象编程 </font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Javascript 面向对象编程" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6441.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6731.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6441.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6731.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Javascript 面向对象编程</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Javascript的两本书" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1608.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6731.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1608.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6731.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10437626.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Javascript的两本书</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="一段Javascript的代码" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3540.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6731.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3540.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6731.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">一段Javascript的代码</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="20个优秀的Javascript导航技术" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F918.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6731.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F918.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6731.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">20个优秀的Javascript导航技术</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table>]]></description>
			<content:encoded><![CDATA[<p>【<span style="color: #cc0000">感谢 Neo 投递本文 &#8211; 微博帐号：<a title="_锟_" href="http://weibo.com/gandalfthegrey" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/gandalfthegrey?referer=');">_锟_</a> </span>】</p>
<p><strong>前言：还是一篇入门文章。</strong>Javascript中有几个非常重要的语言特性——对象、原型继承、闭包。其中闭包对于那些使用传统静态语言C/C++的程序员来说是一个新的语言特性。本文将以例子入手来介绍Javascript闭包的语言特性，并结合一点ECMAScript语言规范来使读者可以更深入的理解闭包。</p>
<p>注：<strong>本文是入门文章，例子素材整理于网络<strong>，如果你是高手，欢迎针对文章提出技术性建议和意见。本文讨论的是Javascript，不想做语言对比，如果您对Javascript天生不适，请自行绕道。</strong></strong></p>
<h4><strong><span style="color: #008000">什么是闭包</span></strong></h4>
<p>闭包是什么?闭包是Closure，这是静态语言所不具有的一个新特性。但是闭包也不是什么复杂到不可理解的东西，简而言之，闭包就是：<strong></strong></p>
<ul>
<li><strong>闭包就是函数的局部变量集合，只是这些局部变量在函数返回后会继续存在。</strong></li>
<li><strong>闭包就是就是函数的“堆栈”在函数返回后并不释放，我们也可以理解为这些函数堆栈并不在栈上分配而是在堆上分配</strong></li>
<li><strong>当在一个函数内定义另外一个函数就会产生闭包</strong></li>
</ul>
<p>上面的第二定义是第一个补充说明，抽取第一个定义的主谓宾——闭包是<strong>函数的‘局部变量’集合</strong>。只是这个局部变量是可以在函数返回后被访问。（这个不是官方定义，但是这个定义应该更有利于你理解闭包）</p>
<p>做为局部变量都可以被函数内的代码访问，这个和静态语言是没有差别。闭包的差别在于局部变变量可以在函数执行结束后仍然被函数外的代码访问。这意味着函数必须返回一个指向闭包的“引用”，或将这个”引用”赋值给某个外部变量，才能保证闭包中局部变量被外部代码访问。当然包含这个引用的实体应该是一个对象，因为在Javascript中除了基本类型剩下的就都是对象了。可惜的是，ECMAScript并没有提供相关的成员和方法来访问闭包中的局部变量。但是在ECMAScript中，函数对象中定义的<strong>内部函数(inner function)</strong>是可以直接访问外部函数的局部变量，通过这种机制，我们就可以以如下的方式完成对闭包的访问了。</p>
<p><span id="more-6731"></span></p>
<pre class="brush: jscript; title: ; notranslate">
function greeting(name) {
    var text = 'Hello ' + name; // local variable
    // 每次调用时，产生闭包，并返回内部函数对象给调用者
    return function() { alert(text); }
}
var sayHello=greeting(&quot;Closure&quot;);
sayHello()  // 通过闭包访问到了局部变量text
</pre>
<p>上述代码的执行结果是：Hello Closure，因为sayHello()函数在greeting函数执行完毕后，仍然可以访问到了定义在其之内的局部变量text。</p>
<p>好了，这个就是传说中闭包的效果，闭包在Javascript中有多种应用场景和模式，比如Singleton，Power Constructor等这些Javascript模式都离不开对闭包的使用。</p>
<h4><strong><span style="color: #008000">ECMAScript闭包模型</span></strong></h4>
<p>ECMAScript到底是如何实现闭包的呢？想深入了解的亲们可以获取<a href="http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf" onclick="pageTracker._trackPageview('/outgoing/www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf?referer=');">ECMAScript 规范</a>进行研究，我这里也只做一个简单的讲解，内容也是来自于网络。</p>
<p>在ECMAscript的脚本的函数运行时，每个函数关联都有一个执行上下文场景(Execution Context) ，这个执行上下文场景中包含三个部分</p>
<ul>
<li>文法环境（The LexicalEnvironment）</li>
<li>变量环境（The VariableEnvironment）</li>
<li>this绑定</li>
</ul>
<p>其中第三点this绑定与闭包无关，不在本文中讨论。文法环境中用于解析函数执行过程使用到的变量标识符。我们可以将文法环境想象成一个对象，该对象包含了两个重要组件，环境记录(Enviroment Recode)，和外部引用(指针)。环境记录包含包含了函数内部声明的局部变量和参数变量，外部引用指向了外部函数对象的上下文执行场景。全局的上下文场景中此引用值为NULL。这样的数据结构就构成了一个单向的链表，每个引用都指向外层的上下文场景。</p>
<p>例如上面我们例子的闭包模型应该是这样，sayHello函数在最下层，上层是函数greeting，最外层是全局场景。如下图：<br />
<img class="aligncenter size-full wp-image-6741" src="http://coolshell.cn/wp-content/uploads/2012/03/closure.png" alt="" width="658" height="478" /><br />
因此当sayHello被调用的时候，sayHello会通过上下文场景找到局部变量text的值，因此在屏幕的对话框中显示出”Hello Closure”<br />
变量环境(The VariableEnvironment)和文法环境的作用基本相似，具体的区别请参看ECMAScript的规范文档。</p>
<h4><strong><span style="color: #008000">闭包的样列</span></strong></h4>
<p>前面的我大致了解了Javascript闭包是什么，闭包在Javascript是怎么实现的。下面我们通过针对一些例子来帮助大家更加深入的理解闭包，下面共有5个样例，例子来自于<a href="http://blog.morrisjohns.com/javascript_closures_for_dummies.html" onclick="pageTracker._trackPageview('/outgoing/blog.morrisjohns.com/javascript_closures_for_dummies.html?referer=');">JavaScript Closures For Dummies(</a><a href="http://web.archive.org/web/20080209105120/http://blog.morrisjohns.com/javascript_closures_for_dummies" onclick="pageTracker._trackPageview('/outgoing/web.archive.org/web/20080209105120/http_//blog.morrisjohns.com/javascript_closures_for_dummies?referer=');">镜像</a><a href="http://blog.morrisjohns.com/javascript_closures_for_dummies.html" onclick="pageTracker._trackPageview('/outgoing/blog.morrisjohns.com/javascript_closures_for_dummies.html?referer=');">)</a>。<br />
<strong>例子1:闭包中局部变量是引用而非拷贝</strong></p>
<pre class="brush: jscript; title: ; notranslate">
function say667() {
    // Local variable that ends up within closure
    var num = 666;
    var sayAlert = function() { alert(num); }
    num++;
    return sayAlert;
}

var sayAlert = say667();
sayAlert()
</pre>
<p>因此执行结果应该弹出的667而非666。</p>
<p><strong>例子2：多个函数绑定同一个闭包，因为他们定义在同一个函数内。</strong></p>
<pre class="brush: jscript; title: ; notranslate">
function setupSomeGlobals() {
    // Local variable that ends up within closure
    var num = 666;
    // Store some references to functions as global variables
    gAlertNumber = function() { alert(num); }
    gIncreaseNumber = function() { num++; }
    gSetNumber = function(x) { num = x; }
}
setupSomeGlobals(); // 为三个全局变量赋值
gAlertNumber(); //666
gIncreaseNumber();
gAlertNumber(); // 667
gSetNumber(12);//
gAlertNumber();//12
</pre>
<p><strong>例子3：当在一个循环中赋值函数时，这些函数将绑定同样的闭包</strong></p>
<pre class="brush: jscript; title: ; notranslate">
function buildList(list) {
    var result = [];
    for (var i = 0; i &lt; list.length; i++) {
        var item = 'item' + list[i];
        result.push( function() {alert(item + ' ' + list[i])} );
    }
    return result;
}

function testList() {
    var fnlist = buildList([1,2,3]);
    // using j only to help prevent confusion - could use i
    for (var j = 0; j &lt; fnlist.length; j++) {
        fnlist[j]();
    }
}
</pre>
<p>testList的执行结果是弹出item3 undefined窗口三次，因为这三个函数绑定了同一个闭包，而且item的值为最后计算的结果，但是当i跳出循环时i值为4，所以list[4]的结果为undefined.</p>
<p><strong>例子4：外部函数所有局部变量都在闭包内，即使这个变量声明在内部函数定义之后。</strong></p>
<pre class="brush: jscript; title: ; notranslate">
function sayAlice() {
    var sayAlert = function() { alert(alice); }
    // Local variable that ends up within closure
    var alice = 'Hello Alice';
    return sayAlert;
}
var helloAlice=sayAlice();
helloAlice();
</pre>
<p>执行结果是弹出”Hello Alice”的窗口。即使局部变量声明在函数sayAlert之后，局部变量仍然可以被访问到。</p>
<p><strong>例子5：每次函数调用的时候创建一个新的闭包</strong></p>
<pre class="brush: jscript; title: ; notranslate">
function newClosure(someNum, someRef) {
    // Local variables that end up within closure
    var num = someNum;
    var anArray = [1,2,3];
    var ref = someRef;
    return function(x) {
        num += x;
        anArray.push(num);
        alert('num: ' + num +
        '\nanArray ' + anArray.toString() +
        '\nref.someVar ' + ref.someVar);
    }
}
closure1=newClosure(40,{someVar:'closure 1'});
closure2=newClosure(1000,{someVar:'closure 2'});

closure1(5); // num:45 anArray[1,2,3,45] ref:'someVar closure1'
closure2(-10);// num:990 anArray[1,2,3,990] ref:'someVar closure2'
</pre>
<h4><strong><span style="color: #008000">闭包的应用</span></strong></h4>
<p><strong>Singleton 单件：</strong></p>
<pre class="brush: jscript; title: ; notranslate">
var singleton = function () {
    var privateVariable;
    function privateFunction(x) {
        ...privateVariable...
    }

    return {
        firstMethod: function (a, b) {
            ...privateVariable...
        },
        secondMethod: function (c) {
            ...privateFunction()...
        }
    };
}();
</pre>
<p>这个单件通过闭包来实现。通过闭包完成了私有的成员和方法的封装。匿名主函数返回一个对象。对象包含了两个方法，方法1可以方法私有变量，方法2访问内部私有函数。需要注意的地方是匿名主函数结束的地方的&#8217;()&#8217;，如果没有这个&#8217;()&#8217;就不能产生单件。因为匿名函数只能返回了唯一的对象，而且不能被其他地方调用。这个就是利用闭包产生单件的方法。</p>
<h2><strong><span style="color: #008000">参考：</span></strong></h2>
<p><a href="http://blog.morrisjohns.com/javascript_closures_for_dummies.html" onclick="pageTracker._trackPageview('/outgoing/blog.morrisjohns.com/javascript_closures_for_dummies.html?referer=');">JavaScript Closures For Dummies(</a><a href="http://web.archive.org/web/20080209105120/http://blog.morrisjohns.com/javascript_closures_for_dummies" onclick="pageTracker._trackPageview('/outgoing/web.archive.org/web/20080209105120/http_//blog.morrisjohns.com/javascript_closures_for_dummies?referer=');">镜像</a><a href="http://blog.morrisjohns.com/javascript_closures_for_dummies.html" onclick="pageTracker._trackPageview('/outgoing/blog.morrisjohns.com/javascript_closures_for_dummies.html?referer=');">)</a> 可惜都被墙了。<br />
<a href="http://yuiblog.com/blog/2006/11/27/video-crockford-advjs/" onclick="pageTracker._trackPageview('/outgoing/yuiblog.com/blog/2006/11/27/video-crockford-advjs/?referer=');">Advance Javascript</a> （Douglas Crockford 大神的视频，一定要看啊）</p>
<table class="wumii-related-items" cellspacing="0" cellpadding="3" border="0"  style="clear: both;">
    
    <tr>
        <td colspan="5"><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
        <tr>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important;">
                    <a target="_blank" title="再谈javascript面向对象编程 " style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6668.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6731.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6668.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6731.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2012/02/27/16161591.png" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">再谈javascript面向对象编程 </font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Javascript 面向对象编程" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6441.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6731.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6441.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6731.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Javascript 面向对象编程</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="Javascript的两本书" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1608.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6731.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1608.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6731.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/site_images/2011/11/08/10437626.jpg" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">Javascript的两本书</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="一段Javascript的代码" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3540.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6731.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3540.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6731.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">一段Javascript的代码</font>
                    </a>
                </td>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="20个优秀的Javascript导航技术" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F918.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6731.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F918.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6731.html&amp;referer=');">
                        <img style="margin: 0 !important; padding: 2px !important; border: 1px solid #DDDDDD !important; width: 96px !important; height: 96px !important;" src="http://static.wumii.com/images/blogWidget/wordpress_default.gif" width="96px" height="96px" /><br />
                        <font size="-1" color="#333333" style="display: block !important; line-height: 15px !important; width: 102px !important; font: 12px/15px arial !important; height: 60px !important; margin: 3px 0 0 0 !important; padding: 0 !important; overflow: hidden !important;">20个优秀的Javascript导航技术</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems?referer=');">
                <font size="-1" color="#bbbbbb" style="display: block !important; font-family: arial !important; padding: 5px 0 !important; font-size: 12px !important; color: #bbb !important;">无觅</font>
            </a>
        </td>
    </tr>
</table><h3  class="related_post_title">相关文章</h3><ul class="related_post"><li>2012年02月27日 -- <a href="http://coolshell.cn/articles/6668.html" title="再谈javascript面向对象编程 ">再谈javascript面向对象编程 </a></li><li>2012年01月09日 -- <a href="http://coolshell.cn/articles/6441.html" title="Javascript 面向对象编程">Javascript 面向对象编程</a></li><li>2011年08月15日 -- <a href="http://coolshell.cn/articles/5202.html" title="对象的消息模型">对象的消息模型</a></li><li>2011年12月07日 -- <a href="http://coolshell.cn/articles/6043.html" title="Web开发中需要了解的东西">Web开发中需要了解的东西</a></li><li>2011年11月24日 -- <a href="http://coolshell.cn/articles/5537.html" title="一些文章资源和趣闻">一些文章资源和趣闻</a></li><li>2011年10月31日 -- <a href="http://coolshell.cn/articles/5709.html" title="API设计：用流畅接口构造内部DSL">API设计：用流畅接口构造内部DSL</a></li><li>2011年07月21日 -- <a href="http://coolshell.cn/articles/5035.html" title="面向对象的Shell脚本">面向对象的Shell脚本</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/6731.html/feed</wfw:commentRss>
		<slash:comments>41</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 22.941 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-05-17 11:21:43 -->
<!-- Compression = gzip -->
