<?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, 02 Feb 2012 06:38:30 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Why C++ ? 王者归来</title>
		<link>http://coolshell.cn/articles/6548.html</link>
		<comments>http://coolshell.cn/articles/6548.html#comments</comments>
		<pubDate>Thu, 02 Feb 2012 00:22:57 +0000</pubDate>
		<dc:creator>陈皓</dc:creator>
				<category><![CDATA[C/C++语言]]></category>
		<category><![CDATA[业界新闻]]></category>
		<category><![CDATA[技术读物]]></category>
		<category><![CDATA[编程语言]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=6548</guid>
		<description><![CDATA[因为又有人邀请我去Quora的C2C网站去回答问题去了，这回是 关于 @laiyonghao 的这篇有点争议的博文《2012 不宜进入的三个技术点》ActionScript，Thread 和 C++， C++争议的争议最大。（要我说，.NET比C++更需要慎重进入，呵）。我就在这里回复一下这个问题吧。 正好我一个月前看到一个视频，这个演讲视频还比较著名，这个演讲者是Exceptional C++ 和 C++ Coding Standards 的作者，还是ISO C++ 委员会的Chair，C++/CLI首席架构师，还是Microsoft的软件架构师，他叫Herb Sutter，他的这个演讲视频是 C++ and Beyond 2011上的一次公开演讲，题目是——Why C++? （如果你觉得那里的视频比较慢，你可以看优酷上的视频）（英文听力好的同学可以看一样，因为都没有中文字幕） 我觉得这篇文章就足够可以说明很多问题了，所以，我把Herb的演讲幻灯片截了几页放到这里，并做上一些注释，算是一个演讲内容摘要吧。 1） 为什么C++？因为 Performance per $，也就是说performance 就是钱，这个分成三个方面， 耗电，芯片的耗电量，移动设备的耗电量，家用电脑的耗电量都和钱有关系。 资源，家用电脑和移动设备上的处理器资源有限，因为要让一般消费者买的起。 体验，在更小的设备上会有更好的体验，有更好的体验就可以挣更多的钱。 移动设备上的耗电量相信用过智能手机的人都知道吧，Android手机的耗电量实在是太大了。就算是iPhone在开启Wifi和3G的情况下耗电量也很快。 2）C++的进化分成三个时代： 1979 &#8211; 1989：研究C的对象能力。主要是为C++做准备 1989 &#8211; 1999：C++成了主流。 1999 &#8211; 2009：Coffee-based语言（Java, .NET）出现了，极大的提高了开发生产力。 对于第三个时代，Herb说了很多，他说这个并没有什么错，因为这个时候我们非常关注开发的生产力，这个非常重要，这就是为什么C++一下就失去优势的地方。但是是否这些Coffee-Based的语言可以做任重要的事呢？不行，很多时候，这是一个Trade-Off的事，也就是生产力不是免费的是需要你用别的东西去交换的。 3）第四个时期。 Herb认为，2009-2019是第四个时期，因为我们又喜欢Native Code了，C++从被驱逐后又被请回来了。因为网站的性能越来越是个问题，移动端的设备非常流行。但主要是因为Performance就是钱，因为前面的三个因素，性能影响的是dollar，不尊重性能的公司都会发现花钱的速度太快了。（比如去年大家热炒的京东促销和12306.cn的问题，12306给整个社会造成了巨大的金钱浪费） Herb把这个时期比做 The Return of the [...]<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="我有一个Hello World的C++程序编译不过" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F4170.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6548.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F4170.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6548.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/10437575.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;">我有一个Hello World的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="恐怖的C++语言" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1724.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6548.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1724.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6548.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/12/8508808.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;">恐怖的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="如何加密/混乱C源代码" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F933.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6548.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F933.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6548.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;">如何加密/混乱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="6个变态的C语言Hello World程序" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F914.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6548.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F914.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6548.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;">6个变态的C语言Hello World程序</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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F4119.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6548.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F4119.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6548.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;">如何学好C++语言</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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>因为又有人邀请我去Quora的C2C网站去回答问题去了，这回是 关于 <a href="http://weibo.com/n/laiyonghao" onclick="pageTracker._trackPageview('/outgoing/weibo.com/n/laiyonghao?referer=');">@laiyonghao</a> 的这篇有点争议的博文《2012 不宜进入的三个技术点》ActionScript，Thread 和 C++，<a href="http://blog.csdn.net/lanphaday/article/details/7223385" target="_blank" onclick="pageTracker._trackPageview('/outgoing/blog.csdn.net/lanphaday/article/details/7223385?referer=');"> C++争议的争议最大</a>。（要我说，.NET比C++更需要慎重进入，呵）。我就在这里回复一下这个问题吧。</p>
<p>正好我一个月前看到一个视频，这个演讲视频还比较著名，这个演讲者是<em>Exceptional C++ </em>和 <em>C++ Coding Standards</em> 的作者，还是ISO C++ 委员会的Chair，C++/CLI首席架构师，还是Microsoft的软件架构师，他叫<a href="http://herbsutter.com/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/herbsutter.com/?referer=');">Herb Sutter</a>，他的这个演讲视频是 <a href="http://cppandbeyond.com/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/cppandbeyond.com/?referer=');">C++ and Beyond 2011</a>上的一次公开演讲，题目是——<a href="http://channel9.msdn.com/posts/C-and-Beyond-2011-Herb-Sutter-Why-C" target="_blank" onclick="pageTracker._trackPageview('/outgoing/channel9.msdn.com/posts/C-and-Beyond-2011-Herb-Sutter-Why-C?referer=');">Why C++</a>? （如果你觉得那里的视频比较慢，你可以看<a href="http://v.youku.com/v_show/id_XMzA5OTIwODIw.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/v.youku.com/v_show/id_XMzA5OTIwODIw.html?referer=');">优酷上的视频</a>）（英文听力好的同学可以看一样，因为都没有中文字幕）</p>
<p>我觉得这篇文章就足够可以说明很多问题了，所以，我把Herb的演讲幻灯片截了几页放到这里，并做上一些注释，算是一个演讲内容摘要吧。</p>
<p>1） 为什么C++？因为 Performance per $，也就是说performance 就是钱，这个分成三个方面，</p>
<ul>
<li>耗电，芯片的耗电量，移动设备的耗电量，家用电脑的耗电量都和钱有关系。</li>
<li>资源，家用电脑和移动设备上的处理器资源有限，因为要让一般消费者买的起。</li>
<li>体验，在更小的设备上会有更好的体验，有更好的体验就可以挣更多的钱。</li>
</ul>
<p>移动设备上的耗电量相信用过智能手机的人都知道吧，Android手机的耗电量实在是太大了。就算是iPhone在开启Wifi和3G的情况下耗电量也很快。</p>
<p><img class="aligncenter size-full wp-image-6550" title="" src="http://coolshell.cn/wp-content/uploads/2012/02/WhyCPP.01.jpg" alt="" width="566" height="319" /></p>
<p><span id="more-6548"></span></p>
<p>2）C++的进化分成三个时代：</p>
<ul>
<li>1979 &#8211; 1989：研究C的对象能力。主要是为C++做准备</li>
<li>1989 &#8211; 1999：C++成了主流。</li>
<li>1999 &#8211; 2009：Coffee-based语言（Java, .NET）出现了，极大的提高了开发生产力。</li>
</ul>
<p style="padding-left: 30px;">对于第三个时代，Herb说了很多，他说这个并没有什么错，因为这个时候我们非常关注开发的生产力，这个非常重要，这就是为什么C++一下就失去优势的地方。但是是否这些Coffee-Based的语言可以做任重要的事呢？不行，很多时候，这是一个Trade-Off的事，也就是生产力不是免费的是需要你用别的东西去交换的。</p>
<p><img class="aligncenter size-full wp-image-6551" title="" src="http://coolshell.cn/wp-content/uploads/2012/02/WhyCPP.02.jpg" alt="" width="567" height="319" /></p>
<p>3）第四个时期。</p>
<p style="padding-left: 30px;">Herb认为，2009-2019是第四个时期，因为我们又喜欢Native Code了，C++从被驱逐后又被请回来了。因为网站的性能越来越是个问题，移动端的设备非常流行。但主要是因为Performance就是钱，因为前面的三个因素，性能影响的是dollar，不尊重性能的公司都会发现花钱的速度太快了。（比如去年大家热炒的京东促销和12306.cn的问题，12306给整个社会造成了巨大的金钱浪费）</p>
<p style="padding-left: 30px;">Herb把这个时期比做 The Return of the King。（指环王的第三部：王者归来）<strong> 性能为王！</strong></p>
<p style="padding-left: 30px;">这就好像我在“<a title="软件开发的“三重门”" href="http://coolshell.cn/articles/6526.html" target="_blank">软件开发的三重门</a>”里说的，开垦时代需要的是快和生产力，而开垦完后就得保证其稳定性。</p>
<p><img class="aligncenter size-full wp-image-6552" title="" src="http://coolshell.cn/wp-content/uploads/2012/02/WhyCPP.03.jpg" alt="" width="567" height="318" /></p>
<p>4）Herb还给了一张幻灯片问，“The World is built on &#8230;.”，后面例出了多个语言。然后Herb说，世界是由C和C++构成的。</p>
<p style="text-align: center;"><img class="aligncenter  wp-image-6562" title="WhyCPP.03.01" src="http://coolshell.cn/wp-content/uploads/2012/02/WhyCPP.03.01.jpg" alt="" width="397" height="224" /></p>
<p>5）Herb给了一张表格，这张表可相当形像。如果把我们的对编程语言的需求总结为四个：<strong>效率，灵活，抽象，生产率</strong>。那么，C语言玩的是前两个，而C++玩的是前三个，Java和C#玩的是后两个（抽象和生产率）</p>
<p>任保一种设计都不可能让你什么都要的，这就是Trade-Off——什么事都需要交换的。</p>
<p><img class="aligncenter size-full wp-image-6553" title="" src="http://coolshell.cn/wp-content/uploads/2012/02/WhyCPP.04.jpg" alt="" width="567" height="318" /></p>
<p>6）Herb举了一个微软内的例子，用C++ 和 ATL 来开发IE工具条的报告，意思是你可以用脚本在IE的工具条上加按钮，但是作者建议使用C++，因为用.NET或是脚本有重大的limitation，尤其是性能上的问题。</p>
<p style="text-align: center;"><img class="aligncenter  wp-image-6554" src="http://coolshell.cn/wp-content/uploads/2012/02/WhyCPP.05.jpg" alt="" width="600" height="339" /></p>
<p style="text-align: left;">7）接下来，我们来看看移动设备。</p>
<p style="text-align: left; padding-left: 30px;">下图中，第一个是iOS，第二个是Android，第三个是WinPhone。Herd说了几个事：</p>
<p style="text-align: left; padding-left: 30px;">a）比Web APP，人们更喜欢Native的APP，这个在用移动设备上可以得到验证。</p>
<p style="text-align: left; padding-left: 30px;">b）iOS也好，Android也好，WinPhone也好，他们不是在搞操作系统，而是在搞应用，为的是让智能手机更好。手机就是一个App。</p>
<p style="text-align: left; padding-left: 30px;">c）这三个手机在第一版出来时都不支持C++，而第二版出来时都支持C++了。因为他们要兼顾性能和一定程度上的开发效率。WinPhone还没有到第二版，让我们拭目以待。（我以前写过一篇<a title="Android将允许纯C/C++开发应用" href="http://coolshell.cn/articles/3549.html" target="_blank">调侃Android支持C++开发</a>的文章，这也只是一年前的事，说明C++全面回归了）</p>
<p><img class="aligncenter size-full wp-image-6555" title="" src="http://coolshell.cn/wp-content/uploads/2012/02/WhyCPP.06.jpg" alt="" width="567" height="319" /></p>
<p>8）如果你还是不相信的话，我们可以看看为什么Apple和Google都在搞C++的编译器，因为他们觉得g++性能不行。所以，基于LLVM的编译器正在领导潮流，因为我们关注Natvie Code的性能优化。</p>
<p><img class="aligncenter size-full wp-image-6556" title="" src="http://coolshell.cn/wp-content/uploads/2012/02/WhyCPP.07.jpg" alt="" width="539" height="615" /></p>
<p>9）接下来，Herb说了一下数据中心，你知道数据中心最花钱的是什么吗？三个事：</p>
<blockquote>
<ul>
<li>57% 花在了硬件上。</li>
<li>18% 花在了配电和降温上。</li>
<li>13% 花在了耗电上。</li>
</ul>
</blockquote>
<p style="padding-left: 30px;">88%的钱花在了硬件和电力上。这可是很大一笔费用啊。（还有人说硬件比软件便宜吗？）我记得我上一个公司的数据中心每年要花的电费就在百万美元以上。</p>
<p><img class="aligncenter size-full wp-image-6557" title="" src="http://coolshell.cn/wp-content/uploads/2012/02/WhyCPP.08.jpg" alt="" width="566" height="319" /></p>
<p>10）昨天在<a href="http://weibo.com/1401880315/y3kshD9jf" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/1401880315/y3kshD9jf?referer=');">微博上有个笑话</a>，说是某咨询师要求程序员把代码打印出来走查，程序员问是不是要用彩打？哈哈。我说，这至少不环保嘛。消耗太大了。是的，C++是可以省电的，以及于C++之父都在YouTube 说C++是可以减轻全球变暖的问题。哇，C++开始真正造福人类了。</p>
<p><img class="aligncenter size-full wp-image-6558" title="" src="http://coolshell.cn/wp-content/uploads/2012/02/WhyCPP.09.jpg" alt="" width="516" height="397" /></p>
<p>11）我还需要重温一下老大的这句话——</p>
<blockquote><p><strong>My contribution to the fight against global warming is C++’s efficiency</strong>: Just think if Google had to have twice as many server farms! Each uses as much energy as a small town. And it’s not just a factor of two…<strong> Efficiency is not just running fast or running bigger programs, it’s also running using less resources</strong>.</p>
<p style="text-align: right;">Bjarne Stroustrup, June 2011</p>
</blockquote>
<p style="text-align: left; padding-left: 30px;">最后一句说的非常好！<strong>效率不仅仅只是跑得，跑得多，更是可以使用更少的资源</strong>。</p>
<p style="text-align: left;">12）下面让我们再来看一张表，一张把钱投到哪里的表格，这样我们可以看到一些趋势。</p>
<ul>
<li>70年代80年代，资源不够，主要是把钱投在性能上。</li>
<li>80年代到90代，主要是90年代开始有一半的投次到了抽象和生产率上。</li>
<li>00年代，完全都在抽象和生产率上。</li>
<li>10年代，80%的钱都要回头来解决性能问题。这就是C/C++的王者归来。</li>
</ul>
<p><img class="aligncenter size-full wp-image-6559" title="" src="http://coolshell.cn/wp-content/uploads/2012/02/WhyCPP.10.jpg" alt="" width="567" height="319" /></p>
<p>13）当然，不是C++不注重 开发效率，看看C++0X的标准引入了多少东西我们就知道了。但是本质上，<strong>C++还是致力于性能和抽象的完全平衡</strong>。</p>
<p><img class="aligncenter size-full wp-image-6560" title="" src="http://coolshell.cn/wp-content/uploads/2012/02/WhyCPP.11.jpg" alt="" width="567" height="319" /></p>
<p>那么，我们还会觉得C++要被淘汰了，不适合进入了吗？看完这个演讲，你应该有答案的。</p>
<p>后面讲了C++的文艺复兴，你可以在Google 搜索 “<a href="https://www.google.com/search?q=C%2B%2B+Renaissance" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.google.com/search?q=C_2B_2B+Renaissance&amp;referer=');">C++ Renaissance</a>”看看。另外，<strong>该视频的讲议可以在<a href="http://ecn.channel9.msdn.com/content/WhyCPPCB2011.pdf" target="_blank" onclick="pageTracker._trackPageview('/outgoing/ecn.channel9.msdn.com/content/WhyCPPCB2011.pdf?referer=');">这里下载</a></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="我有一个Hello World的C++程序编译不过" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F4170.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6548.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F4170.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6548.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/10437575.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;">我有一个Hello World的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="恐怖的C++语言" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1724.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6548.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1724.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6548.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/12/8508808.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;">恐怖的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="如何加密/混乱C源代码" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F933.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6548.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F933.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6548.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;">如何加密/混乱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="6个变态的C语言Hello World程序" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F914.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6548.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F914.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6548.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;">6个变态的C语言Hello World程序</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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F4119.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6548.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F4119.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6548.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;">如何学好C++语言</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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>2011年11月29日 -- <a href="http://coolshell.cn/articles/6010.html" title="一些有意思的算法代码">一些有意思的算法代码</a></li><li>2011年11月01日 -- <a href="http://coolshell.cn/articles/5761.html" title="深入理解C语言">深入理解C语言</a></li><li>2011年10月14日 -- <a href="http://coolshell.cn/articles/5576.html" title="那些曾伴我走过编程之路的软件">那些曾伴我走过编程之路的软件</a></li><li>2011年09月20日 -- <a href="http://coolshell.cn/articles/5224.html" title="一些文章和各种资源">一些文章和各种资源</a></li><li>2011年08月26日 -- <a href="http://coolshell.cn/articles/5388.html" title="C语言中史上最愚蠢的Bug">C语言中史上最愚蠢的Bug</a></li><li>2011年08月19日 -- <a href="http://coolshell.cn/articles/5265.html" title=" C++11 中值得关注的几大变化（详解）"> C++11 中值得关注的几大变化（详解）</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/6548.html/feed</wfw:commentRss>
		<slash:comments>55</slash:comments>
		</item>
		<item>
		<title>软件开发的“三重门”</title>
		<link>http://coolshell.cn/articles/6526.html</link>
		<comments>http://coolshell.cn/articles/6526.html#comments</comments>
		<pubDate>Mon, 30 Jan 2012 03:00:50 +0000</pubDate>
		<dc:creator>陈皓</dc:creator>
				<category><![CDATA[杂项资源]]></category>
		<category><![CDATA[职场生涯]]></category>
		<category><![CDATA[Programmer]]></category>
		<category><![CDATA[程序员]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=6526</guid>
		<description><![CDATA[自从上次写了“程序员技术练级攻略” 以来，就觉得似乎还有很多东西没有谈到，但当时没有继续思考了。而春节前有人问我，是做底层技术，还是做业务。这问题让我思考了很多，不由自主地回顾了一 下我这十多年的软件开发经历，并顺着整理分类了一下自己解决过的若干问题，还发散想了很多，经过了一个春节假期的发酵，产生了下面这篇文章。 前言 这篇文章必然是通过我的个人经历来写的。所以，我先说说个人经历吧。我的经历基本分成三个阶段。 第一阶段：我 刚毕业时在家乡的某银行工作，做些银行的业务系统，还搞些网络，电子邮件系统，OA什么的，因为大四的时候在老师的公司里实习，银行里的人际关系太复杂， 而且技术都包给了产商，所以在银行的每一天都觉得不能适应里面的工作环境。两年后离职，单位分的房也不要了，直接去了上海，在上海呆了两年，本来想做互联 网的，但是泡沫来了，最终去了一家做系统集成的国企公司还是继续做银行业务。这四年来，主要解决的都是一些业务上的问题，银行里的会计业务，OA业务，国 际业务，中间对公业务都非常地复杂，而且因为当时的软件开发相当的不规范，所以基本上是在一种比较混乱的状态下度过的，而银行方面又很强势，所以，这段时 间主要是做业务。所以，技术上主要是积累了如何使用那些技术。C+/Java， Windows编程，Unix编程，网络编程主要是这段时间学的，看了太多的书（我大学课程里没有C++和Java，也没有Windows/Unix和网 络编程，所以，只能拼命地看书和自学）。 第二阶段：然后，我来了北京，到了一家做分布式计算系统的公 司，整天和一个高性能技术高可用性的企业级的集群式的软件产品打交道（这家公司去年被IBM收购了），在这家公司把Windows/Unix和网络编程有 了更深入的了解，对我长进比较大的是明白了怎么做一个性能高，可用性高的集群式的系统，天天和底层打交道，干了4年多。然后去了一家金融信息公司，这家金 融公司主要做全球的金融信息数据处理，而我主要还是做核心数据发布系统的性能调优的项目，金融数据的实时性要求的高，数据量非常地大，高可用性要求得高， 得想尽一切办法省网络带宽，增加系统性能，还要保持高的可用性，不当机，不丢包。又干了4年多，入职的时候从国外接过来两个系统，其性能单机每秒可处理 120K message，我走的时候，我和团队把其优化到了每秒1.4M messages 的吞吐，另一个系统，从接手时的100k message/s优化到了500k message/s。这八年多的时候，全是在和这些高计算高性能的项目打交量，几乎没有什么业务，都是纯技术，积累到了很多和性能有关的高并发高计算系统 架构级的知识。 第三阶段：两 年前来到了现在的做电子商务的互联网公司，还是在做一个数据处理量很大的业务系统，因为要干的是要把电子商务全球化的东西。但是，因为电子商 务的特殊性，必需要去兼顾业务的特点，而且在这家电商公司，耳读目染了很多有趣的业务难题，比如，库存计划，配送优化，等等。虽然很多东西还不明白，但发 现，用技术来解决业务难题真是太有意思了。 我的这三个阶段，第一个阶段花了4年，第二个阶段花了8年，第三阶段刚刚开始2年不到，有时候我也去别的公司讲课，所以，我很有幸经历了中国软件开发的进化过程。我的经历可以说是中国软件行业进程的一个缩影，而我把这三个阶段称为——软件开发的三重门。它们分别是： 业务功能 &#8211; 粗放地开垦 业务性能 &#8211; 扩大化生产 业务智能 &#8211; 精耕细作 之所以加上“业务”二字，是因为我以为计算机是一个工具，其用来解决实际问题，所以，什么都离不开业务，就算是性能优化也一样，通过之前那篇“12306.cn的性能优化”中的“业务分析”段落，我们可以知道业务的不同，系统的难度和解决方法就可以不同。所以，我们总是用技术在解决业务问题。业务的形态对软件的开发有决定性的作用。 下面让我具体描述一下。 一重门：业务功能 这 是软件开发的第一重门，也就是掌握可以实现业务功能的技术。通常分成三块：语言+系统+数据处理。在这个阶段，主要是能掌握各种技术，比如：开发用的各种 工具（如：IDE，XUnit，Debugger，等），各种代码库和框架（如：C++的STL，ACE，Boost，等，Java的 Spring，Hibernate等），各种系统知识（如：Windows API，Unix/Linux API，TCP/IP，Socket，多线程多进程间的同步、互斥，并发安全，还包括Web平台，移动平台，等等），还需要掌握数据处理的知识（如：数据 结构，基本算法，数据库设计，数据库引擎 ，SQL等），等等…… 这个阶段主要是把这些不同的技术组织成可以实现业务功能的解决方案。重点是能掌握和使用技术。很多流程和方法论的东西基本上就在这一重门里。这重门主要解决的是业务实现问题。 二重门：业务性能 业务的功能搞定了以后，就是业务的性能问题了。搞定功能并不难，搞定性能是有点技术含量的事。有句话不是那么说的吗——每个人都可以搞一个网站出来，但不是每个人都能搞出能支持百万级访问量的网站。但是，我看到很多技术团队或是工程师脱离了业务，只单纯地搞性能，比如：单台服务器支持10万个TCP链接的并发，等等。这些东西虽然在技术上有点意思，但是没有业务的环境，也只能是自娱自乐了。 我们可以看到一些企业开始注重这个问题了，性能问题也是最近被大家讨论得最多的问题，京东商场的性能问题，12306的性能问题，等等。 当然，所谓性能不并单单指系统的吞吐力，还指系统运行时的总体性能，比如，系统安全性能，易用性能，系统的Accessbility的性能，系统的扩展性性能，等等，就像是前段时间“Web开发中需要注意的问题”一文中谈到的那些事一样。这表明着你对系统的全面和深入的了解。 [...]<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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1103.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6526.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1103.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6526.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F343.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6526.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F343.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6526.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6346.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6526.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6346.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6526.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1870.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6526.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1870.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6526.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/05/7699954.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="程序员惯用的解释(Top 25)" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1174.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6526.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1174.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6526.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;">程序员惯用的解释(Top 25)</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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://coolshell.cn/articles/4990.html" target="_blank">程序员技术练级攻略</a>” 以来，就觉得似乎还有很多东西没有谈到，但当时没有继续思考了。而春节前有人问我，是做底层技术，还是做业务。这问题让我思考了很多，不由自主地回顾了一 下我这十多年的软件开发经历，并顺着整理分类了一下自己解决过的若干问题，还发散想了很多，经过了一个春节假期的发酵，产生了下面这篇文章。</p>
<h4>前言</h4>
<p>这篇文章必然是通过我的个人经历来写的。所以，我先说说个人经历吧。我的经历基本分成三个阶段。</p>
<p><strong>第一阶段：</strong>我 刚毕业时在家乡的某银行工作，做些银行的业务系统，还搞些网络，电子邮件系统，OA什么的，因为大四的时候在老师的公司里实习，银行里的人际关系太复杂， 而且技术都包给了产商，所以在银行的每一天都觉得不能适应里面的工作环境。两年后离职，单位分的房也不要了，直接去了上海，在上海呆了两年，本来想做互联 网的，但是泡沫来了，最终去了一家做系统集成的国企公司还是继续做银行业务。这四年来，主要解决的都是一些业务上的问题，银行里的会计业务，OA业务，国 际业务，中间对公业务都非常地复杂，而且因为当时的软件开发相当的不规范，所以基本上是在一种比较混乱的状态下度过的，而银行方面又很强势，所以，这段时 间主要是做业务。所以，技术上主要是积累了如何使用那些技术。C+/Java， Windows编程，Unix编程，网络编程主要是这段时间学的，看了太多的书（我大学课程里没有C++和Java，也没有Windows/Unix和网 络编程，所以，只能拼命地看书和自学）。</p>
<p><strong>第二阶段：</strong>然后，我来了北京，到了一家做分布式计算系统的公 司，整天和一个高性能技术高可用性的企业级的集群式的软件产品打交道（这家公司去年被IBM收购了），在这家公司把Windows/Unix和网络编程有 了更深入的了解，对我长进比较大的是明白了怎么做一个性能高，可用性高的集群式的系统，天天和底层打交道，干了4年多。然后去了一家金融信息公司，这家金 融公司主要做全球的金融信息数据处理，而我主要还是做核心数据发布系统的性能调优的项目，金融数据的实时性要求的高，数据量非常地大，高可用性要求得高， 得想尽一切办法省网络带宽，增加系统性能，还要保持高的可用性，不当机，不丢包。又干了4年多，入职的时候从国外接过来两个系统，其性能单机每秒可处理 120K message，我走的时候，我和团队把其优化到了每秒1.4M messages 的吞吐，另一个系统，从接手时的100k message/s优化到了500k message/s。这八年多的时候，全是在和这些高计算高性能的项目打交量，几乎没有什么业务，都是纯技术，积累到了很多和性能有关的高并发高计算系统 架构级的知识。</p>
<p><span id="more-6526"></span></p>
<p><strong>第三阶段：</strong>两 年前来到了现在的做电子商务的互联网公司，还是在做一个数据处理量很大的业务系统，因为要干的是要把电子商务全球化的东西。但是，因为电子商 务的特殊性，必需要去兼顾业务的特点，而且在这家电商公司，耳读目染了很多有趣的业务难题，比如，库存计划，配送优化，等等。虽然很多东西还不明白，但发 现，用技术来解决业务难题真是太有意思了。</p>
<p>我的这三个阶段，第一个阶段花了4年，第二个阶段花了8年，第三阶段刚刚开始2年不到，有时候我也去别的公司讲课，所以，我很有幸经历了中国软件开发的进化过程。<strong>我的经历可以说是中国软件行业进程的一个缩影，而我把这三个阶段称为</strong>——<strong>软件开发的三重门</strong>。它们分别是：</p>
<ul>
<li><strong>业务功能 &#8211; </strong>粗放地开垦<strong><br />
</strong></li>
<li><strong>业务性能 &#8211; </strong>扩大化生产<strong><br />
</strong></li>
<li><strong>业务智能 &#8211; </strong>精耕细作<strong><br />
</strong></li>
</ul>
<p>之所以加上“业务”二字，是因为我以为计算机是一个工具，其用来解决实际问题，所以，什么都离不开业务，就算是性能优化也一样，通过之前那篇“<a title="由12306.cn谈谈网站性能技术" href="http://coolshell.cn/articles/6470.html" target="_blank">12306.cn的性能优化</a>”中的“业务分析”段落，我们可以知道业务的不同，系统的难度和解决方法就可以不同。所以，我们总是用技术在解决业务问题。<strong>业务的形态对软件的开发有决定性的作用</strong>。</p>
<p>下面让我具体描述一下。</p>
<h4>一重门：业务功能</h4>
<p>这 是软件开发的第一重门，也就是掌握可以实现业务功能的技术。通常分成三块：语言+系统+数据处理。在这个阶段，主要是能掌握各种技术，比如：开发用的各种 工具（如：IDE，XUnit，Debugger，等），各种代码库和框架（如：C++的STL，ACE，Boost，等，Java的 Spring，Hibernate等），各种系统知识（如：Windows API，Unix/Linux API，TCP/IP，Socket，多线程多进程间的同步、互斥，并发安全，还包括Web平台，移动平台，等等），还需要掌握数据处理的知识（如：数据 结构，基本算法，数据库设计，数据库引擎 ，SQL等），等等……</p>
<p>这个阶段主要是把这些不同的技术组织成可以实现业务功能的解决方案。重点是能掌握和使用技术。很多流程和方法论的东西基本上就在这一重门里。<strong>这重门主要解决的是业务实现问题</strong>。</p>
<h4>二重门：业务性能</h4>
<p>业务的功能搞定了以后，就是业务的性能问题了。搞定功能并不难，搞定性能是有点技术含量的事。有句话不是那么说的吗——<strong>每个人都可以搞一个网站出来，但不是每个人都能搞出能支持百万级访问量的网站</strong>。但是，我看到很多技术团队或是工程师脱离了业务，只单纯地搞性能，比如：单台服务器支持10万个TCP链接的并发，等等。这些东西虽然在技术上有点意思，但是没有业务的环境，也只能是自娱自乐了。</p>
<p>我们可以看到一些企业开始注重这个问题了，性能问题也是最近被大家讨论得最多的问题，京东商场的性能问题，12306的性能问题，等等。</p>
<p>当然，<strong>所谓性能不并单单指系统的吞吐力，还指系统运行时的总体性能</strong>，比如，系统安全性能，易用性能，系统的Accessbility的性能，系统的扩展性性能，等等，就像是前段时间“<a title="Web开发中需要了解的东西" href="http://coolshell.cn/articles/6043.html" target="_blank">Web开发中需要注意的问题</a>”一文中谈到的那些事一样。这表明着你对系统的全面和深入的了解。</p>
<p>在 这个阶段，需要对业务模型，数据流，业务流，系统架构，算法，和各种技术有深入的了解，要了解到本质上来。比如，在第一重门中，我们只需同要知 道，Java有同步关键字，在这一重门中，我们还要知道同步或互斥对性能的巨大伤害性，在第一重门中，我们只需要知道STL中的智能指针或是STL的用 法，这一重门中，我们还要知道智能指针中的refcnt的同步加锁对性能的损害，还需要知道STL中容器的size()方法在某些时候是性能很差的。在第 一重门中，我们需要知道hash表的效率，在这一重门中，我们还需要知道<a title="Hash Collision DoS 问题" href="http://coolshell.cn/articles/6424.html" target="_blank">hash表的碰撞问题</a>。</p>
<p>最重要的是，<strong>在这重门重点是软件的设计问题</strong>。你需要有足够多的经验能比较不同设计方案的优缺点，比如TCP和UDP，同步和异步，epoll和select，push和pull，水平扩展的各种方案…… 还记得本站的那篇“<a title="程序员的谎谬之言还是至理名言？" href="http://coolshell.cn/articles/4235.html" target="_blank">程序员的谎谬之言还是至理名言</a>”，广度是你深度的副产品。所以，这重门是看你的技术视野有多深有多广。</p>
<h4>三重门：业务智能</h4>
<p>这 重门可能是最难的一重门了，如果你能进到这重门里，你应该是科学家级的程序员了。让你有智能的业务，这个事可能是顶级的技术难题了。第一和第二重门都不算 难，这重门是最难的。参看Amazon的个性化推荐系统，或是Google搜索引擎的结果个性化推荐等等（比如我输入“黑天鹅”关键字，你怎么知道我要找 的是动物，电影，音乐，还是本书？怎么让搜索出来的结果排名即公正又可个性？），你就知道，用技术来解决这种类似的问题难度可想而知，不然就不会出现如 Hadoop之类的技术了。</p>
<p>我再举两个这重门里的业务方面的例子。</p>
<ul>
<li>一个例子是关于库存计划的，需要像天气预报一样 预测未来的销售量从而决定库存，所以，最简单的做法是，监测各个商品的销售统计，然后看一下最近的销售趋势，还要看一下往年的销售趋势（因为某些节假日会 是一个高峰期），还要分析一下大众的喜好变化，比如，在某影评网站上的某电影的热度其会告诉我哪个电影的DVD要滞销了，得打折卖，哪个电影的DVD要畅 销了，得多进货了。还可能需要监控新闻评论，比如某权威人士推荐了某个商品，那么我得赶快进货了。等等。这完全就是一门科学。</li>
</ul>
<ul>
<li>还有一个例子是配送问题。我有一辆卡车要处理我仓库和配送站间的物流问题，我需要找到一条最经济的路线来在有限的时间内处理最多的物流。这个不是最短路径问题，这是个计划统筹学的东西。也是一门科学。</li>
</ul>
<p>还有近期“方韩之争”里有很多人来分析文章相似度的技术，这些东西都属于三重门里的东西。</p>
<p>到了这重门里，可能技术反而不是重要的了，而是数学模型。<strong>这重门里主要是业务模型，数据模型和算法问题</strong>。这些东西和你的业务模型密切相关。能解决这样的问题，是真正的大牛。对于我来说，可能是高山仰止了。</p>
<h4>后记</h4>
<p>通过上面的说明，我们可以看到下面这些东西，</p>
<ul>
<li>我的那篇“<a title="程序员技术练级攻略" href="http://coolshell.cn/articles/4990.html" target="_blank">程序员技术练级攻略</a>”里的东西只能让我们最多达到1.1 到 1.2重门。</li>
</ul>
<ul>
<li>一重门像是开垦荒地，二重门像是扩大生产，三重门像是精耕细作。</li>
</ul>
<ul>
<li>一重门（业务实现）里聚集着大量的劳动密集型的企业，劳动密集型的企业通常都需要流程和方法论。敏捷过程改进这类的东西只在一重门里。</li>
</ul>
<ul>
<li>二重门和三重门里只有少数不多的技术型的公司。这类的公司通常非常注重技术，并且是企业文化是工程师的文化。</li>
</ul>
<ul>
<li>三重门里可以产生的创新和那些可以用来改变世界的技术。</li>
</ul>
<ul>
<li>国内现在的情况是，一重门优化阶段 + 二重门的学习阶段。三重门里似乎还没有什么见术。不过，我看到一些公司已在尝试三重门的东西了。</li>
</ul>
<ul>
<li>作为技术人员的你，如果你想跟上时代，让自己有价值的话，你至少要达到二重门。</li>
</ul>
<ul>
<li>因 为国内的技术环境等不良因素，导致大量的程序员在一重门的时候就已经失去信心，或被大浪淘沙淘掉了，所以，二重门里的程序员比较少了，但是随着年轻的一代 和技术的日趋成熟，也会慢慢多起来的，我现在已经看到这个趋势了。而三重门里的程序员成了稀缺的大熊猫。因为大量的二重门程序员干到那个时候都转管理了。</li>
</ul>
<p><strong>我的这些言论不一定对，但希望能让大家有启发，有所思考。</strong></p>
<p><strong>注</strong>：本来这篇文章的标题想取成“<strong>程序员要解决的三种问题</strong>”， 但是因为过年都在关注 “方韩之争”，所以，干脆取成了这个名字。你可以认为我比较调皮，也可以认为我爱ZB，还可以认为我标题党，反正，请随意理解。（这篇文章是我的自己写 的，没有代笔，因为你一定会在这篇文章中看到属于我的用五笔打出来的错别字，当然，我无法自证，哈哈）</p>
<p>（<span style="color: #cc0000;"><strong>转载时请注明作者和出处，请勿用于商业用途</strong></span>）</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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1103.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6526.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1103.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6526.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F343.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6526.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F343.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6526.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6346.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6526.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6346.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6526.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1870.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6526.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1870.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6526.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/05/7699954.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="程序员惯用的解释(Top 25)" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1174.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6526.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1174.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6526.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;">程序员惯用的解释(Top 25)</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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月04日 -- <a href="http://coolshell.cn/articles/6346.html" title="程序员因为女孩而美丽！">程序员因为女孩而美丽！</a></li><li>2011年12月30日 -- <a href="http://coolshell.cn/articles/6312.html" title="一个女程序员的故事">一个女程序员的故事</a></li><li>2011年12月20日 -- <a href="http://coolshell.cn/articles/6142.html" title="三个事和三个问题">三个事和三个问题</a></li><li>2011年11月15日 -- <a href="http://coolshell.cn/articles/5815.html" title="来信， 创业 和 移动互联网">来信， 创业 和 移动互联网</a></li><li>2011年10月25日 -- <a href="http://coolshell.cn/articles/5686.html" title="多些时间能少写些代码">多些时间能少写些代码</a></li><li>2011年10月20日 -- <a href="http://coolshell.cn/articles/5651.html" title="Stay Hungry, Stay Foolish ！！">Stay Hungry, Stay Foolish ！！</a></li><li>2011年09月21日 -- <a href="http://coolshell.cn/articles/5514.html" title="如果你看不见你还能编程吗？">如果你看不见你还能编程吗？</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/6526.html/feed</wfw:commentRss>
		<slash:comments>74</slash:comments>
		</item>
		<item>
		<title>由12306.cn谈谈网站性能技术</title>
		<link>http://coolshell.cn/articles/6470.html</link>
		<comments>http://coolshell.cn/articles/6470.html#comments</comments>
		<pubDate>Mon, 16 Jan 2012 00:20:22 +0000</pubDate>
		<dc:creator>陈皓</dc:creator>
				<category><![CDATA[杂项资源]]></category>
		<category><![CDATA[程序设计]]></category>
		<category><![CDATA[系统架构]]></category>
		<category><![CDATA[12306.cn]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[eComm]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=6470</guid>
		<description><![CDATA[12306.cn网站挂了，被全国人民骂了。我这两天也在思考这个事，我想以这个事来粗略地和大家讨论一下网站性能的问题。因为仓促，而且完全基于本人有限的经验和了解，所以，如果有什么问题还请大家一起讨论和指正。（这又是一篇长文，只讨论性能问题，不讨论那些UI，用户体验，或是是否把支付和购票下单环节分开的功能性的东西） 业务 任何技术都离不开业务需求，所以，要说明性能问题，首先还是想先说说业务问题。 其一，有人可能把这个东西和QQ或是网游相比。但我觉得这两者是不一样的，网游和QQ在线或是登录时访问的更多的是用户自己的数据，而订票系统访问的是中心的票量数据，这是不一样的。不要觉得网游或是QQ能行你就以为这是一样的。网游和QQ 的后端负载相对于电子商务的系统还是简单。 其二，有人说春节期间订火车的这个事好像网站的秒杀活动。的确很相似，但是如果你的思考不在表面的话，你会发现这也有些不一样。火车票这个事，还有很多查询操作，查时间，查座位，查铺位，一个车次不 行，又查另一个车次，其伴随着大量的查询操作，下单的时候需要对数据库操作。而秒杀，直接杀就好了。另外，关于秒杀，完全可以做成只接受前N个用户的请求（完全不操作后端的任何数据， 仅仅只是对用户的下单操作log），这种业务，只要把各个服务器的时间精确同步了就可以了，无需在当时操作任何数据库。可以订单数够后，停止秒杀，然后批量写数据库。火车票这个岂止是秒杀那么简单。能不能买到票得当时告诉用户啊。 其三，有人拿这个系统和奥运会的票务系统比较。我觉得还是不一样。虽然奥运会的票务系统当年也一上线就废了。但是奥运会用的是抽奖的方式，也就是说不存在先来先得的抢的方式，而且，是事后抽奖，事前只需要收信息，事前不需要保证数据一致性，没有锁，很容易水平扩展。 其四，订票系统应该和电子商务的订单系统很相似，都是需要对库存进行：1）占住库存，2）支付（可选），3）扣除库存的操作。这个是需要有一致性的检查的，也就是在并发时需要对数据加锁的。B2C的电商基本上都会把这个事干成异步的，也就是说，你下的订单并不是马上处理的，而是延时处理的，只有成功处理了，系统才会给你一封确认邮件说是订单成功。我相信有很多朋友都收到认单不成功的邮件。这就是说，数据一致性在并发下是一个瓶颈。 其五，铁路的票务业务很变态，其采用的是突然放票，而有的票又远远不够大家分，所以，大家才会有抢票这种有中国特色的业务的做法。于是当票放出来的时候，就会有几百万人甚至上千万人杀上去，查询，下单。几十分钟内，一个网站能接受几千万的访问量，这个是很恐怖的事情。据说12306的高峰访问是10亿PV，集中在早8点到10点，每秒PV在高峰时上千万。 多说几句： 库存是B2C的恶梦，库存管理相当的复杂。不信，你可以问问所有传统和电务零售业的企业，看看他们管理库存是多么难的一件事。不然，就不会有那么多人在问凡客的库存问题了。（你还可以看看《乔布斯传》，你就知道为什么Tim会接任Apple的CEO了，因为他搞定了苹果的库存问题） 对于一个网站来说，浏览网页的高负载很容易搞定，查询的负载有一定的难度去处理，不过还是可以通过缓存查询结果来搞定，最难的就是下单的负载。因为要访问库存啊，对于下单，基本上是用异步来搞定的。去年双11节，淘宝的每小时的订单数大约在60万左右，京东一天也才能支持40万（居然比12306还差），亚马逊5年前一小时可支持70万订单量。可见，下订单的操作并没有我们相像的那么性能高。 淘宝要比B2C的网站要简单得多，因为没有仓库，所以，不存在像B2C这样有N个仓库对同一商品库存更新和查询的操作。下单的时候，B2C的 网站要去找一个仓库，又要离用户近，又要有库存，这需要很多计算。试想，你在北京买了一本书，北京的仓库没货了，就要从周边的仓库调，那就要去看看沈阳或 是西安的仓库有没有货，如果没有，又得看看江苏的仓库，等等。淘宝的就没有那么多事了，每个商户有自己的库存，库存分到商户头上了，反而有利于性能。 数据一致性才是真正的性能瓶颈。有 人说nginx可以搞定每秒10万的静态请求，我不怀疑。但这只是静态请求，理论值，只要带宽、I/O够强，服务器计算能力够，并支持的并发连接数顶得住10万TCP链接的建立 的话，那没有问题。但在数据一致性面前，这10万就完完全全成了一个可望不可及的理论值了。 我说那么多，我只是想从业务上告诉大家，我们需要从业务上真正了解春运铁路订票这样业务的变态之处。 前端性能优化技术 要解决性能的问题，有很多种常用的方法，我在下面列举一下，我相信12306这个网站使用下面的这些技术会让其性能有质的飞跃。 一、前端负载均衡 通过DNS的负载均衡器（一般在路由器上根据路由的负载重定向）可以把用户的访问均匀地分散在多个Web服务器上。这样可以减少Web服务器的请求负载。因为http的请求都是短作业，所以，可以通过很简单的负载均衡器来完成这一功能。最好是有CDN网络让用户连接与其最近的服务器（CDN通常伴随着分布式存储）。（关于负载均衡更为详细的说明见“后端的负载均衡”） 二、减少前端链接数 我看了一下12306.cn，打开主页需要建60多个HTTP连接，车票预订页面则有70多个HTTP请求，现在的浏览器都是并发请求的。所以，只要有100万个用户，就会有6000万个链接，太多了。一个登录查询页面就好了。把js打成一个文件，把css也打成一个文件，把图标也打成一个文件，用css分块展示。把链接数减到最低。 三、减少网页大小增加带宽 这个世界不是哪个公司都敢做图片服务的，因为图片太耗带宽了。现在宽带时代很难有人能体会到当拨号时代做个图页都不敢用图片的情形（现在在手机端浏览也是这个情形）。我查看了一下12306首页的需要下载的总文件大小大约在900KB左右，如果你访问过了，浏览器会帮你缓存很多，只需下载10K左右的文件。但是我们可以想像一个极端一点的案例，1百万用户同时访问，且都是第一次访问，每人下载量需要1M，如果需要在120秒内返回，那么就需要，1M * 1M /120 * 8 = 66Gbps的带宽。很惊人吧。所以，我估计在当天，12306的阻塞基本上应该是网络带宽，所以，你可能看到的是没有响应。后面随着浏览器的缓存帮助12306减少很多带宽占用，于是负载一下就到了后端，后端的数据处理瓶颈一下就出来。于是你会看到很多http 500之类的错误。这说明服务器垮了。 四、前端页面静态化 静态化一些不常变的页面和数据，并gzip一下。还有一个并态的方法是把这些静态页面放在/dev/shm下，这个目录就是内存，直接从内存中把文件读出来返回，这样可以减少昂贵的磁盘I/O。 五、优化查询 很多人查询都是在查一样的，完全可以用反向代理合并这些并发的相同的查询。这样的技术主要用查询结果缓存来实现，第一次查询走数据库获得数据，并把数据放到缓存，后面的查询统统直接访问高速缓存。为每个查询做Hash，使用NoSQL的技术可以完成这个优化。（这个技术也可以用做静态页面） 对于火车票量的查询，个人觉得不要显示数字，就显示一个“有”或“无”就好了，这样可以大大简化系统复杂度，并提升性能。 六、缓存的问题 缓存可以用来缓存动态页面，也可以用来缓存查询的数据。缓存通常有那么几个问题： 1）缓存的更新。也叫缓存和数据库的同步。有这么几种方法，一是缓存time out，让缓存失效，重查，二是，由后端通知更新，一量后端发生变化，通知前端更新。前者实现起来比较简单，但实时性不高，后者实现起来比较复杂 ，但实时性高。 2）缓存的换页。内存可能不够，所以，需要把一些不活跃的数据换出内存，这个和操作系统的内存换页和交换内存很相似。FIFO、LRU、LFU都是比较经典的换页算法。相关内容参看Wikipeida的缓存算法。 3）缓存的重建和持久化。缓存在内存，系统总要维护，所以，缓存就会丢失，如果缓存没了，就需要重建，如果数据量很大，缓存重建的过程会很慢，这会影响生产环境，所以，缓存的持久化也是需要考虑的。 诸多强大的NoSQL都很好支持了上述三大缓存的问题。 后端性能优化技术 前面讨论了前端性能的优化技术，于是前端可能就不是瓶颈问题了。那么性能问题就会到后端数据上来了。下面说几个后端常见的性能优化技术。 一、数据冗余 关于数据冗余，也就是说，把我们的数据库的数据冗余处理，也就是减少表连接这样的开销比较大的操作，但这样会牺牲数据的一致性。风险比较大。很多人把NoSQL用做数据，快是快了，因为数据冗余了，但这对数据一致性有大的风险。这需要根据不同的业务进行分析和处理。（注意：用关系型数据库很容易移植到NoSQL上，但是反过来从NoSQL到关系型就难了） 二、数据镜像 [...]<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="Why C++ ? 王者归来" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6548.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6470.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6548.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6470.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/03/14687960.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;">Why 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="酷壳 – CoolShell.cn" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2F&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6470.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2F_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6470.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/10/14/9143047.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;">酷壳 – 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="Amazon的书为什么卖到了$2000万" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F4605.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6470.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F4605.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6470.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/13619257.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;">Amazon的书为什么卖到了$2000万</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="35个强大的UI设计教程" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F363.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6470.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F363.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6470.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/26/2955944.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;">35个强大的UI设计教程</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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3833.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6470.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3833.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6470.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.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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>12306.cn网站挂了，被全国人民骂了。我这两天也在思考这个事，我想以这个事来粗略地和大家讨论一下网站性能的问题。因为仓促，而且完全基于本人有限的经验和了解，所以，如果有什么问题还请大家一起讨论和指正。（这又是一篇长文，只讨论性能问题，不讨论那些UI，用户体验，或是是否把支付和购票下单环节分开的功能性的东西）</p>
<h4>业务</h4>
<p>任何技术都离不开业务需求，所以，要说明性能问题，首先还是想先说说业务问题。</p>
<ul>
<li><strong>其一</strong>，<strong>有人可能把这个东西和QQ或是网游相比</strong>。但我觉得这两者是不一样的，网游和QQ在线或是登录时访问的更多的是用户自己的数据，而订票系统访问的是中心的票量数据，这是不一样的。不要觉得网游或是QQ能行你就以为这是一样的。网游和QQ 的后端负载相对于电子商务的系统还是简单。</li>
</ul>
<ul>
<li><strong>其二</strong>，<strong>有人说春节期间订火车的这个事好像网站的秒杀活动</strong>。的确很相似，但是如果你的思考不在表面的话，你会发现这也有些不一样。火车票这个事，还有很多查询操作，查时间，查座位，查铺位，一个车次不 行，又查另一个车次，其伴随着大量的查询操作，下单的时候需要对数据库操作。而秒杀，直接杀就好了。另外，关于秒杀，完全可以做成只接受前N个用户的请求（完全不操作后端的任何数据， 仅仅只是对用户的下单操作log），这种业务，只要把各个服务器的时间精确同步了就可以了，无需在当时操作任何数据库。可以订单数够后，停止秒杀，然后批量写数据库。火车票这个岂止是秒杀那么简单。能不能买到票得当时告诉用户啊。</li>
</ul>
<ul>
<li><strong>其三</strong>，<strong>有人拿这个系统和奥运会的票务系统比较</strong>。我觉得还是不一样。虽然奥运会的票务系统当年也一上线就废了。但是奥运会用的是抽奖的方式，也就是说不存在先来先得的抢的方式，而且，是事后抽奖，事前只需要收信息，事前不需要保证数据一致性，没有锁，很容易水平扩展。</li>
</ul>
<ul>
<li><strong>其四</strong>，<strong>订票系统应该和电子商务的订单系统很相似</strong>，都是需要对库存进行：1）占住库存，2）支付（可选），3）扣除库存的操作。这个是需要有一致性的检查的，也就是在并发时需要对数据加锁的。B2C的电商基本上都会把这个事干成异步的，也就是说，你下的订单并不是马上处理的，而是延时处理的，只有成功处理了，系统才会给你一封确认邮件说是订单成功。我相信有很多朋友都收到认单不成功的邮件。<strong>这就是说，数据一致性在并发下是一个瓶颈</strong>。</li>
</ul>
<p><span id="more-6470"></span></p>
<ul>
<li><strong>其五</strong>，<strong>铁路的票务业务很变态</strong>，其采用的是突然放票，而有的票又远远不够大家分，所以，大家才会有抢票这种有中国特色的业务的做法。于是当票放出来的时候，就会有几百万人甚至上千万人杀上去，查询，下单。几十分钟内，一个网站能接受几千万的访问量，这个是很恐怖的事情。<a href="http://www.linuxso.com/architecture/17006.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.linuxso.com/architecture/17006.html?referer=');">据说12306的高峰访问是10亿PV</a>，集中在早8点到10点，每秒PV在高峰时上千万。</li>
</ul>
<p>多说几句：</p>
<ul>
<li><strong>库存是B2C的恶梦，库存管理相当的复杂</strong>。不信，你可以问问所有传统和电务零售业的企业，看看他们管理库存是多么难的一件事。不然，就不会有那么多人在问凡客的库存问题了。（你还可以看看《乔布斯传》，你就知道为什么Tim会接任Apple的CEO了，因为他搞定了苹果的库存问题）</li>
</ul>
<ul>
<li><strong>对于一个网站来说，浏览网页的高负载很容易搞定，查询的负载有一定的难度去处理，不过还是可以通过缓存查询结果来搞定，最难的就是下单的负载</strong>。因为要访问库存啊，对于下单，基本上是用异步来搞定的。去年双11节，淘宝的每小时的订单数大约在60万左右，京东一天也才能支持40万（居然比12306还差），亚马逊5年前一小时可支持70万订单量。可见，下订单的操作并没有我们相像的那么性能高。</li>
</ul>
<ul>
<li><strong>淘宝要比B2C的网站要简单得多，因为没有仓库</strong>，所以，不存在像B2C这样有N个仓库对同一商品库存更新和查询的操作。下单的时候，B2C的 网站要去找一个仓库，又要离用户近，又要有库存，这需要很多计算。试想，你在北京买了一本书，北京的仓库没货了，就要从周边的仓库调，那就要去看看沈阳或 是西安的仓库有没有货，如果没有，又得看看江苏的仓库，等等。淘宝的就没有那么多事了，每个商户有自己的库存，库存分到商户头上了，反而有利于性能。</li>
</ul>
<ul>
<li><strong>数据一致性才是真正的性能瓶颈</strong>。有 人说nginx可以搞定每秒10万的静态请求，我不怀疑。但这只是静态请求，理论值，只要带宽、I/O够强，服务器计算能力够，并支持的并发连接数顶得住10万TCP链接的建立 的话，那没有问题。但在数据一致性面前，这10万就完完全全成了一个可望不可及的理论值了。</li>
</ul>
<p>我说那么多，我只是想从业务上告诉大家，我们需要从业务上真正了解春运铁路订票这样业务的变态之处。</p>
<h4>前端性能优化技术</h4>
<p>要解决性能的问题，有很多种常用的方法，我在下面列举一下，我相信12306这个网站使用下面的这些技术会让其性能有质的飞跃。</p>
<h5>一、前端负载均衡</h5>
<p>通过DNS的负载均衡器（一般在路由器上根据路由的负载重定向）可以把用户的访问均匀地分散在多个Web服务器上。这样可以减少Web服务器的请求负载。因为http的请求都是短作业，所以，可以通过很简单的负载均衡器来完成这一功能。最好是有CDN网络让用户连接与其最近的服务器（CDN通常伴随着分布式存储）。（关于负载均衡更为详细的说明见“后端的负载均衡”）</p>
<h5>二、减少前端链接数</h5>
<p>我看了一下12306.cn，打开主页需要建60多个HTTP连接，车票预订页面则有70多个HTTP请求，现在的浏览器都是并发请求的。所以，只要有100万个用户，就会有6000万个链接，太多了。一个登录查询页面就好了。把js打成一个文件，把css也打成一个文件，把图标也打成一个文件，用css分块展示。把链接数减到最低。</p>
<h5>三、减少网页大小增加带宽</h5>
<p>这个世界不是哪个公司都敢做图片服务的，因为图片太耗带宽了。现在宽带时代很难有人能体会到当拨号时代做个图页都不敢用图片的情形（现在在手机端浏览也是这个情形）。我查看了一下12306首页的需要下载的总文件大小大约在900KB左右，如果你访问过了，浏览器会帮你缓存很多，只需下载10K左右的文件。但是我们可以想像一个极端一点的案例，1百万用户同时访问，且都是第一次访问，每人下载量需要1M，如果需要在120秒内返回，那么就需要，1M * 1M /120 * 8 = 66Gbps的带宽。很惊人吧。所以，我估计在当天，12306的阻塞基本上应该是网络带宽，所以，你可能看到的是没有响应。后面随着浏览器的缓存帮助12306减少很多带宽占用，于是负载一下就到了后端，后端的数据处理瓶颈一下就出来。于是你会看到很多http 500之类的错误。这说明服务器垮了。</p>
<h5>四、前端页面静态化</h5>
<p>静态化一些不常变的页面和数据，并gzip一下。还有一个并态的方法是把这些静态页面放在/dev/shm下，这个目录就是内存，直接从内存中把文件读出来返回，这样可以减少昂贵的磁盘I/O。</p>
<h5>五、优化查询</h5>
<p>很多人查询都是在查一样的，完全可以用反向代理合并这些并发的相同的查询。这样的技术主要用查询结果缓存来实现，第一次查询走数据库获得数据，并把数据放到缓存，后面的查询统统直接访问高速缓存。为每个查询做Hash，使用NoSQL的技术可以完成这个优化。（这个技术也可以用做静态页面）</p>
<p>对于火车票量的查询，个人觉得不要显示数字，就显示一个“有”或“无”就好了，这样可以大大简化系统复杂度，并提升性能。</p>
<h5>六、缓存的问题</h5>
<p>缓存可以用来缓存动态页面，也可以用来缓存查询的数据。缓存通常有那么几个问题：</p>
<p>1）缓存的更新。也叫缓存和数据库的同步。有这么几种方法，一是缓存time out，让缓存失效，重查，二是，由后端通知更新，一量后端发生变化，通知前端更新。前者实现起来比较简单，但实时性不高，后者实现起来比较复杂 ，但实时性高。</p>
<p>2）缓存的换页。内存可能不够，所以，需要把一些不活跃的数据换出内存，这个和操作系统的内存换页和交换内存很相似。FIFO、LRU、LFU都是比较经典的换页算法。相关内容参看<a href="http://en.wikipedia.org/wiki/Cache_algorithms" target="_blank" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Cache_algorithms?referer=');">Wikipeida的缓存算法</a>。</p>
<p>3）缓存的重建和持久化。缓存在内存，系统总要维护，所以，缓存就会丢失，如果缓存没了，就需要重建，如果数据量很大，缓存重建的过程会很慢，这会影响生产环境，所以，缓存的持久化也是需要考虑的。</p>
<p>诸多强大的NoSQL都很好支持了上述三大缓存的问题。</p>
<h4>后端性能优化技术</h4>
<p>前面讨论了前端性能的优化技术，于是前端可能就不是瓶颈问题了。那么性能问题就会到后端数据上来了。下面说几个后端常见的性能优化技术。</p>
<h5>一、数据冗余</h5>
<p>关于数据冗余，也就是说，把我们的数据库的数据冗余处理，也就是减少表连接这样的开销比较大的操作，但这样会牺牲数据的一致性。风险比较大。很多人把NoSQL用做数据，快是快了，因为数据冗余了，但这对数据一致性有大的风险。这需要根据不同的业务进行分析和处理。（注意：用关系型数据库很容易移植到NoSQL上，但是反过来从NoSQL到关系型就难了）</p>
<h5>二、数据镜像</h5>
<p>几乎所有主流的数据库都支持镜像，也就是replication。数据库的镜像带来的好处就是可以做负载均衡。把一台数据库的负载均分到多台上，同时又保证了数据一致性（Oracle的SCN）。最重要的是，这样还可以有高可用性，一台废了，还有另一台在服务。</p>
<p>数据镜像的数据一致性可能是个复杂的问题，所以我们要在单条数据上进行数据分区，也就是说，把一个畅销商品的库存均分到不同的服务器上，如，一个畅销商品有1万的库存，我们可以设置10台服务器，每台服务器上有1000个库存，这就好像B2C的仓库一样。</p>
<h5>三、数据分区</h5>
<p>数据镜像不能解决的一个问题就是数据表里的记录太多，导致数据库操作太慢。所以，把数据分区。数据分区有很多种做法，一般来说有下面这几种：</p>
<p>1）把数据把某种逻辑来分类。比如火车票的订票系统可以按各铁路局来分，可按各种车型分，可以按始发站分，可以按目的地分……，反正就是把一张表拆成多张有一样的字段但是不同种类的表，这样，这些表就可以存在不同的机器上以达到分担负载的目的。</p>
<p>2）把数据按字段分，也就是竖着分表。比如把一些不经常改的数据放在一个表里，经常改的数据放在另外多个表里。把一张表变成1对1的关系，这样，你可以减少表的字段个数，同样可以提升一定的性能。另外，字段多会造成一条记录的存储会被放到不同的页表里，这对于读写性能都有问题。但这样一来会有很多复杂的控制。</p>
<p>3）平均分表。因为第一种方法是并不一定平均分均，可能某个种类的数据还是很多。所以，也有采用平均分配的方式，通过主键ID的范围来分表。</p>
<p>4）同一数据分区。这个在上面数据镜像提过。也就是把同一商品的库存值分到不同的服务器上，比如有10000个库存，可以分到10台服务器上，一台上有1000个库存。然后负载均衡。</p>
<p>这三种分区都有好有坏。最常用的还是第一种。数据一旦分区，你就需要有一个或是多个调度来让你的前端程序知道去哪里找数据。<strong>把火车票的数据分区，并放在各个省市，会对12306这个系统有非常有意义的质的性能的提高</strong>。</p>
<h5>四、后端系统负载均衡</h5>
<p>前面说了数据分区，数据分区可以在一定程度上减轻负载，但是无法减轻热销商品的负载，对于火车票来说，可以认为是大城市的某些主干线上的车票。这就需要使用数据镜像来减轻负载。使用数据镜像，你必然要使用负载均衡，在后端，我们可能很难使用像路由器上的负载均衡器，因为那是均衡流量的，因为流量并不代表服务器的繁忙程度。因此，我们需要一个任务分配系统，其还能监控各个服务器的负载情况。</p>
<p>任务分配服务器有一些难点：</p>
<ul>
<li>负载情况比较复杂。什么叫忙？是CPU高？还是磁盘I/O高？还是内存使用高？还是并发高？还是内存换页率高？你可能需要全部都要考虑。这些信息要发送给那个任务分配器上，由任务分配器挑选一台负载最轻的服务器来处理。</li>
</ul>
<ul>
<li>任务分配服务器上需要对任务队列，不能丢任务啊，所以还需要持久化。并且可以以批量的方式把任务分配给计算服务器。</li>
</ul>
<ul>
<li>任务分配服务器死了怎么办？这里需要一些如Live-Standby或是failover等高可用性的技术。我们还需要注意那些持久化了的任务的队列如何转移到别的服务器上的问题。</li>
</ul>
<p>我看到有很多系统都用静态的方式来分配，有的用hash，有的就简单地轮流分析。这些都不够好，一个是不能完美地负载均衡，另一个静态的方法的致命缺陷是，如果有一台计算服务器死机了，或是我们需要加入新的服务器，对于我们的分配器来说，都需要知道的。</p>
<p>还有一种方法是使用抢占式的方式进行负载均衡，由下游的计算服务器去任务服务器上拿任务。让这些计算服务器自己决定自己是否要任务。这样的好处是可以简化系统的复杂度，而且还可以任意实时地减少或增加计算服务器。但是唯一不好的就是，如果有一些任务只能在某种服务器上处理，这可能会引入一些复杂度。不过总体来说，这种方法可能是比较好的负载均衡。</p>
<h5>五、异步、 throttle 和 批量处理</h5>
<p>异步、throttle（节流阀） 和批量处理都需要对并发请求数做队列处理的。</p>
<ul>
<li>异步在业务上一般来说就是收集请求，然后延时处理。在技术上就是可以把各个处理程序做成并行的，也就可以水平扩展了。但是异步的技术问题大概有这些，a）被调用方的结果返回，会涉及进程线程间通信的问题。b）如果程序需要回滚，回滚会有点复杂。c）异步通常都会伴随多线程多进程，并发的控制也相对麻烦一些。d）很多异步系统都用消息机制，消息的丢失和乱序也会是比较复杂的问题。</li>
</ul>
<ul>
<li>throttle 技术其实并不提升性能，这个技术主要是防止系统被超过自己不能处理的流量给搞垮了，这其实是个保护机制。使用throttle技术一般来说是对于一些自己无法控制的系统，比如，和你网站对接的银行系统。</li>
</ul>
<ul>
<li>批量处理的技术，是把一堆基本相同的请求批量处理。比如，大家同时购买同一个商品，没有必要你买一个我就写一次数据库，完全可以收集到一定数量的请求，一次操作。这个技术可以用作很多方面。比如节省网络带宽，我们都知道网络上的MTU（最大传输单元），以态网是1500字节，光纤可以达到4000多个字节，如果你的一个网络包没有放满这个MTU，那就是在浪费网络带宽，因为网卡的驱动程序只有一块一块地读效率才会高。因此，网络发包时，我们需要收集到足够多的信息后再做网络I/O，这也是一种批量处理的方式。批量处理的敌人是流量低，所以，批量处理的系统一般都会设置上两个阀值，一个是作业量，另一个是timeout，只要有一个条件满足，就会开始提交处理。</li>
</ul>
<p>所以，<strong>只要是异步，一般都会有throttle机制，一般都会有队列来排队，有队列，就会有持久化，而系统一般都会使用批量的方式来处理</strong>。</p>
<p><a href="http://blog.codingnow.com/2012/01/ticket_queue.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/blog.codingnow.com/2012/01/ticket_queue.html?referer=');">云风同学设计的“排队系统”</a> 就是这个技术。这和电子商务的订单系统很相似，就是说，我的系统收到了你的购票下单请求，但是我还没有真正处理，我的系统会跟据我自己的处理能力来throttle住这些大量的请求，并一点一点地处理。一旦处理完成，我就可以发邮件或短信告诉用户你来可以真正购票了。</p>
<p>在这里，我想通过业务和用户需求方面讨论一下云风同学的这个排队系统，因为其从技术上看似解决了这个问题，但是从业务和用户需求上来说可能还是有一些值得我们去深入思考的地方：</p>
<p style="padding-left: 30px;">1）<strong>队列的DoS攻击</strong>。首先，我们思考一下，这个队是个单纯地排队的吗？这样做还不够好，因为这样我们不能杜绝黄牛，而且单纯的ticket_id很容易发生DoS攻击，比如，我发起N个 ticket_id，进入购票流程后，我不买，我就耗你半个小时，很容易我就可以让想买票的人几天都买不到票。有人说，用户应该要用身份证来排队， 这样在购买里就必需要用这个身份证来买，但这也还不能杜绝黄牛排队或是号贩子。因为他们可以注册N个帐号来排队，但就是不买。黄牛这些人这个时候只需要干一个事，把网站搞得正常人不能访问，让用户只能通过他们来买。</p>
<p style="padding-left: 30px;">2）<strong>对列的一致性</strong>？对这个队列的操作是不是需要锁？只要有锁，性能一定上不去。试想，100万个人同时要求你来分配位置号，这个队列将会成为性能瓶颈。你一定没有数据库实现得性能好，所以，可能比现在还差</p>
<p style="padding-left: 30px;">3）<strong>队列的等待时间</strong>。购票时间半小时够不够？多不多？要是那时用户正好不能上网呢？如果时间短了，用户不够时间操作也会抱怨，如果时间长了，后面在排队的那些人也会抱怨。这个方法可能在实际操作上会有很多问题。另外，半个小时太长了，这完全不现实，我们用15分钟来举例：有1千万用户，每一个时刻只能放进去1万个，这1万个用户需要15分钟完成所有操作，那么，这1千万用户全部处理完，需要1000*15m = 250小时，10天半，火车早开了。（我并非乱说，<a href="http://t.cn/z0g7dGJ" target="_blank" onclick="pageTracker._trackPageview('/outgoing/t.cn/z0g7dGJ?referer=');">根据铁道部专家的说明</a>：这几天，平均一天下单100万，所以，处理1000万的用户需要十天。这个计算可能有点简单了，我只是想说，<strong>在这样低负载的系统下用排队可能都不能解决问题</strong>）</p>
<p style="padding-left: 30px;">4）<strong>队列的分布式</strong>。这个排队系统只有一个队列好吗？还不足够好。因为，如果你放进去的可以购票的人如果在买同一个车次的同样的类型的票（比如某动车卧铺），还是等于在抢票，也就是说系统的负载还是会有可能集中到其中某台服务器上。因此，最好的方法是根据用户的需求——提供出发地和目的地，来对用户进行排队。而这样一来，队列也就可以是多个，只要是多个队列，就可以水平扩展了。</p>
<p>我觉得完全可以向网上购物学习。在排队（下单）的时候，收集好用户的信息和想要买的票，并允许用户设置购票的优先级，比如，A车次卧铺买 不到就买 B车次的卧铺，如果还买不到就买硬座等等，然后用户把所需的钱先充值好，接下来就是系统完全自动地异步处理订单。成功不成功都发短信或邮件通知用户。这样，系统不仅可以省去那半个小时的用户交互时间，自动化加快处理，还可以合并相同购票请求的人，进行批处理（减少数据库的操作次数）。这种方法最妙的事是可以知道这些排队用户的需求，不但可以优化用户的队列，把用户分布到不同的队列，还可以像亚马逊的心愿单一样，让铁道部做车次统筹安排和调整（最后，排队系统（下单系统）还是要保存在数据库里的或做持久化，不能只放在内存中，不然机器一down，就等着被骂吧）。</p>
<h4>小结</h4>
<p>写了那么多，我小结一下：</p>
<p>0）<strong>无论你怎么设计，你的系统一定要能容易地水平扩展</strong>。也就是说，你的整个数据流中，所有的环节都要能够水平扩展。这样，当你的系统有性能问题时，“加3倍的服务器”才不会被人讥笑。</p>
<p>1）<strong>上述的技术不是一朝一夕能搞定的，没有长期的积累，基本无望</strong>。我们可以看到，无论你用哪种都会引发一些复杂性。</p>
<p>2）集中式的卖票很难搞定，使用上述的技术可以让订票系统能有几佰倍的性能提升。而在<strong>各个省市建分站，分开卖票，是能让现有系统性能有质的提升的最好方法</strong>。</p>
<p>3）<strong>春运前夕抢票且票量供远小于求这种业务模式是相当变态的</strong>，让几千万甚至上亿的人在某个早晨的8点钟同时登录同时抢票的这种业务模式是变态中的变态。业务形态的变态决定了无论他们怎么办干一定会被骂。</p>
<p>4）<strong>为了那么一两个星期而搞那么大的系统</strong>，而其它时间都在闲着，有些可惜了，这也就是铁路才干得出来这样的事了。</p>
<p>（<span style="color: #cc0000;"><strong>本文转载时请注明作者和出处，请勿于记商业目的</strong></span>）</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="Why C++ ? 王者归来" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6548.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6470.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6548.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6470.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/03/14687960.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;">Why 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="酷壳 – CoolShell.cn" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2F&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6470.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2F_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6470.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/10/14/9143047.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;">酷壳 – 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="Amazon的书为什么卖到了$2000万" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F4605.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6470.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F4605.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6470.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/13619257.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;">Amazon的书为什么卖到了$2000万</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="35个强大的UI设计教程" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F363.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6470.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F363.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6470.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/26/2955944.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;">35个强大的UI设计教程</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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3833.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6470.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3833.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6470.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.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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月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><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>2011年05月03日 -- <a href="http://coolshell.cn/articles/4626.html" title="读书笔记：对线程模型的批评">读书笔记：对线程模型的批评</a></li><li>2011年04月28日 -- <a href="http://coolshell.cn/articles/4605.html" title="Amazon的书为什么卖到了$2000万">Amazon的书为什么卖到了$2000万</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/6470.html/feed</wfw:commentRss>
		<slash:comments>187</slash:comments>
		</item>
		<item>
		<title>Javascript 面向对象编程</title>
		<link>http://coolshell.cn/articles/6441.html</link>
		<comments>http://coolshell.cn/articles/6441.html#comments</comments>
		<pubDate>Mon, 09 Jan 2012 00:16:27 +0000</pubDate>
		<dc:creator>陈皓</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=6441</guid>
		<description><![CDATA[Javascript是一个类C的语言，他的面向对象的东西相对于C++/Java比较奇怪，但是其的确相当的强大，在 Todd 同学的“对象的消息模型”一文中我们已经可以看到一些端倪了。这两天有个前同事总在问我Javascript面向对象的东西，所以，索性写篇文章让他看去吧，这里这篇文章主要想从一个整体的角度来说明一下Javascript的面向对象的编程。（成文比较仓促，应该有不准确或是有误的地方，请大家批评指正） 另，这篇文章主要基于 ECMAScript 5， 旨在介绍新技术。关于兼容性的东西，请看最后一节。 初探 我们知道Javascript中的变量定义基本如下： 如果要用对象来写的话，就是下面这个样子： 于是，我就可以这样访问： 关于函数，我们知道Javascript的函数是这样的： 于是，我们可以这么干： 相信这些东西都比较简单，大家都明白了。 可以看到javascript对象函数是直接声明，直接赋值，直接就用了。runtime的动态语言。 还有一种比较规范的写法是： 顺便说一下，要删除对象的属性，很简单： 上面的这些例子，我们可以看到这样几点： Javascript的数据和成员封装很简单。没有类完全是对象操作。纯动态！ Javascript function中的this指针很关键，如果没有的话，那就是局部变量或局部函数。 Javascript对象成员函数可以在使用时临时声明，并把一个全局函数直接赋过去就好了。 Javascript的成员函数可以在实例上进行修改，也就是说不同实例相同函数名的行为不一定一样。 属性配置 &#8211; Object.defineProperty 先看下面的代码： 下面就说说这些属性配置是什么意思。 writable：这个属性的值是否可以改。 configurable：这个属性的配置是否可以改。 enumerable：这个属性是否能在for&#8230;in循环中遍历出来或在Object.keys中列举出来。 value：属性值。 get()/set(_value)：get和set访问器。 Get/Set 访问器 关于get/set访问器，它的意思就是用get/set来取代value（其不能和value一起使用），示例如下： 我们再看一个更为实用的例子——利用已有的属性(age)通过get和set构造新的属性(birth_year)： 这样做好像有点麻烦，你说，我为什么不写成下面这个样子： 是的，你的确可以这样的，不过通过defineProperty()你可以干这些事： 1）设置如 writable，configurable，enumerable 等这类的属性配置。 2）动态地为一个对象加属性。比如：一些HTML的DOM对像。 查看对象属性配置 如果查看并管理对象的这些配置，下面有个程序可以输出对象的属性和配置等东西： call，apply， bind 和 this 关于Javascript的this指针，和C++/Java很类似。 我们来看个示例：（这个示例很简单了，我就不多说了） 我们再来看看call 和 apply，这两个函数的差别就是参数的样子不一样，另一个就是性能不一样，apply的性能要差很多。（关于性能，可到 JSPerf 上去跑跑看看） 但是在bind后，this指针，可能会有不一样，但是因为Javascript是动态的。如下面的示例 [...]<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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1608.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6441.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1608.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6441.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1924.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6441.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1924.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6441.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/21/9139797.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="20个优秀的Javascript导航技术" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F918.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6441.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F918.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6441.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>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="把Flash转成Javascript/HTML5" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2497.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6441.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2497.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6441.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/20/23739426.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;">把Flash转成Javascript/HTML5</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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1850.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6441.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1850.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6441.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/10437573.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>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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>Javascript是一个类C的语言，他的面向对象的东西相对于C++/Java比较奇怪，但是其的确相当的强大，在 <a href="http://www.cnblogs.com/weidagang2046/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.cnblogs.com/weidagang2046/?referer=');">Todd 同学</a>的“<a title="对象的消息模型" href="http://coolshell.cn/articles/5202.html" rel="bookmark" target="_blank">对象的消息模型</a>”一文中我们已经可以看到一些端倪了。这两天有个前同事总在问我Javascript面向对象的东西，所以，索性写篇文章让他看去吧，这里这篇文章主要想从一个整体的角度来说明一下Javascript的面向对象的编程。（<strong>成文比较仓促，应该有不准确或是有误的地方，请大家批评指正</strong>）</p>
<p>另，这篇文章主要基于 <a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.ecma-international.org/publications/standards/Ecma-262.htm?referer=');">ECMAScript 5</a>， 旨在介绍新技术。关于兼容性的东西，请看最后一节。</p>
<h4>初探</h4>
<p>我们知道Javascript中的变量定义基本如下：</p>
<pre class="brush: jscript; title: ; notranslate">var name = 'Chen Hao';;
var email = 'haoel(@)hotmail.com';
var website = 'http://coolshell.cn';</pre>
<p>如果要用对象来写的话，就是下面这个样子：</p>
<pre class="brush: jscript; title: ; notranslate">var chenhao = {
    name :'Chen Hao',
    email : 'haoel(@)hotmail.com',
    website : 'http://coolshell.cn'
};</pre>
<p>于是，我就可以这样访问：</p>
<pre class="brush: jscript; title: ; notranslate">
//以成员的方式
chenhao.name;
chenhao.email;
chenhao.website;

//以hash map的方式
chenhao[&quot;name&quot;];
chenhao[&quot;email&quot;];
chenhao[&quot;website&quot;];
</pre>
<p>关于函数，我们知道Javascript的函数是这样的：</p>
<p><span id="more-6441"></span></p>
<pre class="brush: jscript; title: ; notranslate">var doSomething = function(){
   alert('Hello World.');
};</pre>
<p>于是，我们可以这么干：</p>
<pre class="brush: jscript; title: ; notranslate">
var sayHello = function(){
   var hello = &quot;Hello, I'm &quot;+ this.name
                + &quot;, my email is: &quot; + this.email
                + &quot;, my website is: &quot; + this.website;
   alert(hello);
};

//直接赋值，这里很像C/C++的函数指针
chenhao.Hello = sayHello;

chenhao.Hello();
</pre>
<p>相信这些东西都比较简单，大家都明白了。 可以看到javascript对象函数是直接声明，直接赋值，直接就用了。runtime的动态语言。</p>
<p>还有一种比较规范的写法是：</p>
<pre class="brush: jscript; title: ; notranslate">
//我们可以看到， 其用function来做class。
var Person = function(name, email, website){
    this.name = name;
    this.email = email;
    this.website = website;

    this.sayHello = function(){
        var hello = &quot;Hello, I'm &quot;+ this.name  + &quot;, \n&quot; +
                    &quot;my email is: &quot; + this.email + &quot;, \n&quot; +
                    &quot;my website is: &quot; + this.website;
        alert(hello);
    };
};

var chenhao = new Person(&quot;Chen Hao&quot;, &quot;haoel@hotmail.com&quot;,
                                     &quot;http://coolshell.cn&quot;);
chenhao.sayHello(); </pre>
<p>顺便说一下，要删除对象的属性，很简单：</p>
<pre class="brush: jscript; title: ; notranslate">delete chenhao['email']</pre>
<p>上面的这些例子，我们可以看到这样几点：</p>
<ol>
<li>Javascript的数据和成员封装很简单。没有类完全是对象操作。纯动态！</li>
<li>Javascript function中的this指针很关键，如果没有的话，那就是局部变量或局部函数。</li>
<li>Javascript对象成员函数可以在使用时临时声明，并把一个全局函数直接赋过去就好了。</li>
<li>Javascript的成员函数可以在实例上进行修改，也就是说不同实例相同函数名的行为不一定一样。</li>
</ol>
<h4>属性配置 &#8211; Object.defineProperty</h4>
<p>先看下面的代码：</p>
<pre class="brush: jscript; title: ; notranslate">
//创建对象
var chenhao = Object.create(null);

//设置一个属性
 Object.defineProperty( chenhao,
                'name', { value:  'Chen Hao',
                          writable:     true,
                          configurable: true,
                          enumerable:   true });

//设置多个属性
Object.defineProperties( chenhao,
    {
        'email'  : { value:  'haoel@hotmail.com',
                     writable:     true,
                     configurable: true,
                     enumerable:   true },
        'website': { value: 'http://coolshell.cn',
                     writable:     true,
                     configurable: true,
                     enumerable:   true }
    }
);
</pre>
<p>下面就说说这些属性配置是什么意思。</p>
<ul>
<li>writable：这个属性的值是否可以改。</li>
<li>configurable：这个属性的配置是否可以改。</li>
<li>enumerable：这个属性是否能在for&#8230;in循环中遍历出来或在Object.keys中列举出来。</li>
<li>value：属性值。</li>
<li>get()/set(_value)：get和set访问器。</li>
</ul>
<h4>Get/Set 访问器</h4>
<p>关于get/set访问器，它的意思就是用get/set来取代value（其不能和value一起使用），示例如下：</p>
<pre class="brush: jscript; title: ; notranslate">var  age = 0;
Object.defineProperty( chenhao,
            'age', {
                      get: function() {return age+1;},
                      set: function(value) {age = value;}
                      enumerable : true,
                      configurable : true
                    }
);
chenhao.age = 100; //调用set
alert(chenhao.age); //调用get 输出101（get中+1了）;
</pre>
<p>我们再看一个更为实用的例子——利用已有的属性(age)通过get和set构造新的属性(birth_year)：</p>
<pre class="brush: jscript; title: ; notranslate">
Object.defineProperty( chenhao,
            'birth_year',
            {
                get: function() {
                    var d = new Date();
                    var y = d.getFullYear();
                    return ( y - this.age );
                },
                set: function(year) {
                    var d = new Date();
                    var y = d.getFullYear();
                    this.age = y - year;
                }
            }
);

alert(chenhao.birth_year);
chenhao.birth_year = 2000;
alert(chenhao.age);
</pre>
<p>这样做好像有点麻烦，你说，我为什么不写成下面这个样子：</p>
<pre class="brush: jscript; title: ; notranslate">
var chenhao = {
    name: &quot;Chen Hao&quot;,
    email: &quot;haoel@hotmail.com&quot;,
    website: &quot;http://coolshell.cn&quot;,
    age: 100,
    get birth_year() {
        var d = new Date();
        var y = d.getFullYear();
        return ( y - this.age );
    },
    set birth_year(year) {
        var d = new Date();
        var y = d.getFullYear();
        this.age = y - year;
    }

};
alert(chenhao.birth_year);
chenhao.birth_year = 2000;
alert(chenhao.age);
</pre>
<p>是的，你的确可以这样的，不过通过defineProperty()你可以干这些事：<br />
1）设置如 writable，configurable，enumerable 等这类的属性配置。<br />
2）动态地为一个对象加属性。比如：一些HTML的DOM对像。</p>
<h4>查看对象属性配置</h4>
<p>如果查看并管理对象的这些配置，下面有个程序可以输出对象的属性和配置等东西：</p>
<pre class="brush: jscript; title: ; notranslate">//列出对象的属性.
function listProperties(obj)
{
    var newLine = &quot;&lt;br /&gt;&quot;;
    var names = Object.getOwnPropertyNames(obj);
    for (var i = 0; i &lt; names.length; i++) {
        var prop = names[i];
        document.write(prop + newLine);

        // 列出对象的属性配置（descriptor）动用getOwnPropertyDescriptor函数。
        var descriptor = Object.getOwnPropertyDescriptor(obj, prop);
        for (var attr in descriptor) {
            document.write(&quot;...&quot; + attr + ': ' + descriptor[attr]);
            document.write(newLine);
        }
        document.write(newLine);
    }
}

listProperties(chenhao);</pre>
<h4>call，apply， bind 和 this</h4>
<p>关于Javascript的this指针，和C++/Java很类似。 我们来看个示例：（这个示例很简单了，我就不多说了）</p>
<pre class="brush: jscript; title: ; notranslate">function print(text){
    document.write(this.value + ' - ' + text+ '&lt;br&gt;');
}

var a = {value: 10, print : print};
var b = {value: 20, print : print};

print('hello');// this =&gt; global, output &quot;undefined - hello&quot;

a.print('a');// this =&gt; a, output &quot;10 - a&quot;
b.print('b'); // this =&gt; b, output &quot;20 - b&quot;

a['print']('a'); // this =&gt; a, output &quot;10 - a&quot;
</pre>
<p>我们再来看看call 和 apply，这两个函数的差别就是参数的样子不一样，另一个就是性能不一样，apply的性能要差很多。（关于性能，可到 <a href="http://jsperf.com/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/jsperf.com/?referer=');">JSPerf</a> 上去跑跑看看）</p>
<pre class="brush: jscript; title: ; notranslate">print.call(a, 'a'); // this =&gt; a, output &quot;10 - a&quot;
print.call(b, 'b'); // this =&gt; b, output &quot;20 - b&quot;

print.apply(a, ['a']); // this =&gt; a, output &quot;10 - a&quot;
print.apply(b, ['b']); // this =&gt; b, output &quot;20 - b&quot;</pre>
<p>但是在bind后，this指针，可能会有不一样，但是因为Javascript是动态的。如下面的示例</p>
<pre class="brush: jscript; title: ; notranslate">var p = print.bind(a);
p('a');             // this =&gt; a, output &quot;10 - a&quot;
p.call(b, 'b');     // this =&gt; a, output &quot;10 - b&quot;
p.apply(b, ['b']);  // this =&gt; a, output &quot;10 - b&quot;</pre>
<h4>继承 和 重载</h4>
<p>通过上面的那些示例，我们可以通过Object.create()来实际继承，请看下面的代码，Student继承于Object。</p>
<pre class="brush: jscript; highlight: [20]; title: ; notranslate">
var Person = Object.create(null);

Object.defineProperties
(
    Person,
    {
        'name'  : {  value: 'Chen Hao'},
        'email'  : { value : 'haoel@hotmail.com'},
        'website': { value: 'http://coolshell.cn'}
    }
);

Person.sayHello = function () {
    var hello = &quot;&lt;p&gt;Hello, I am &quot;+ this.name  + &quot;, &lt;br&gt;&quot; +
                &quot;my email is: &quot; + this.email + &quot;, &lt;br&gt;&quot; +
                &quot;my website is: &quot; + this.website;
    document.write(hello + &quot;&lt;br&gt;&quot;);
}

var Student = Object.create(Person);
Student.no = &quot;1234567&quot;; //学号
Student.dept = &quot;Computer Science&quot;; //系

//使用Person的属性
document.write(Student.name + ' ' + Student.email + ' ' + Student.website +'&lt;br&gt;');

//使用Person的方法
Student.sayHello();

//重载SayHello方法
Student.sayHello = function (person) {
    var hello = &quot;&lt;p&gt;Hello, I am &quot;+ this.name  + &quot;, &lt;br&gt;&quot; +
                &quot;my email is: &quot; + this.email + &quot;, &lt;br&gt;&quot; +
                &quot;my website is: &quot; + this.website + &quot;, &lt;br&gt;&quot; +
                &quot;my student no is: &quot; + this. no + &quot;, &lt;br&gt;&quot; +
                &quot;my departent is: &quot; + this. dept;
    document.write(hello + '&lt;br&gt;');
}
//再次调用
Student.sayHello();

//查看Student的属性（只有 no 、 dept 和 重载了的sayHello）
document.write('&lt;p&gt;' + Object.keys(Student) + '&lt;br&gt;');
</pre>
<p>通用上面这个示例，我们可以看到，Person里的属性并没有被真正复制到了Student中来，但是我们可以去存取。这是因为Javascript用委托实现了这一机制。其实，这就是Prototype，Person是Student的Prototype。</p>
<p>当我们的代码需要一个属性的时候，Javascript的引擎会先看当前的这个对象中是否有这个属性，如果没有的话，就会查找他的Prototype对象是否有这个属性，一直继续下去，直到找到或是直到没有Prototype对象。</p>
<p>为了证明这个事，我们可以使用Object.getPrototypeOf()来检验一下：</p>
<pre class="brush: jscript; title: ; notranslate">Student.name = 'aaa';

//输出 aaa
document.write('&lt;p&gt;' + Student.name + '&lt;/p&gt;');

//输出 Chen Hao
document.write('&lt;p&gt;' +Object.getPrototypeOf(Student).name + '&lt;/p&gt;');</pre>
<p>于是，你还可以在子对象的函数里调用父对象的函数，就好像C++里的 Base::func() 一样。于是，我们重载hello的方法就可以使用父类的代码了，如下所示：</p>
<pre class="brush: jscript; highlight: [3]; title: ; notranslate">//新版的重载SayHello方法
Student.sayHello = function (person) {
    Object.getPrototypeOf(this).sayHello.call(this);
    var hello = &quot;my student no is: &quot; + this. no + &quot;, &lt;br&gt;&quot; +
                &quot;my departent is: &quot; + this. dept;
    document.write(hello + '&lt;br&gt;');
}</pre>
<p>这个很强大吧。</p>
<h4>组合</h4>
<p>上面的那个东西还不能满足我们的要求，我们可能希望这些对象能真正的组合起来。为什么要组合？因为我们都知道是这是OO设计的最重要的东西。不过，这对于Javascript来并没有支持得特别好，不好我们依然可以搞定个事。</p>
<p>首先，我们需要定义一个Composition的函数：（target是作用于是对象，source是源对象），下面这个代码还是很简单的，就是把source里的属性一个一个拿出来然后定义到target中。</p>
<pre class="brush: jscript; title: ; notranslate">
function Composition(target, source)
{
    var desc  = Object.getOwnPropertyDescriptor;
    var prop  = Object.getOwnPropertyNames;
    var def_prop = Object.defineProperty;

    prop(source).forEach(
        function(key) {
            def_prop(target, key, desc(source, key))
        }
    )
    return target;
}
</pre>
<p>有了这个函数以后，我们就可以这来玩了：</p>
<pre class="brush: jscript; highlight: [19,23]; title: ; notranslate">
//艺术家
var Artist = Object.create(null);
Artist.sing = function() {
    return this.name + ' starts singing...';
}
Artist.paint = function() {
    return this.name + ' starts painting...';
}

//运动员
var Sporter = Object.create(null);
Sporter.run = function() {
    return this.name + ' starts running...';
}
Sporter.swim = function() {
    return this.name + ' starts swimming...';
}

Composition(Person, Artist);
document.write(Person.sing() + '&lt;br&gt;');
document.write(Person.paint() + '&lt;br&gt;');

Composition(Person, Sporter);
document.write(Person.run() + '&lt;br&gt;');
document.write(Person.swim() + '&lt;br&gt;');

//看看 Person中有什么？（输出：sayHello,sing,paint,swim,run）
document.write('&lt;p&gt;' + Object.keys(Person) + '&lt;br&gt;');
</pre>
<h4>Prototype 和 继承</h4>
<p>我们先来说说Prototype。我们先看下面的例程，这个例程不需要解释吧，很像C语言里的函数指针，在C语言里这样的东西见得多了。</p>
<pre class="brush: jscript; title: ; notranslate">var plus = function(x,y){
    document.write( x + ' + ' + y + ' = ' + (x+y) + '&lt;br&gt;');
    return x + y;
};

var minus = function(x,y){
    document.write(x + ' - ' + y + ' = ' + (x-y) + '&lt;br&gt;');
    return x - y;
};

var operations = {
    '+': plus,
    '-': minus
};

var calculate = function(x, y, operation){
    return operations[operation](x, y);
};

calculate(12, 4, '+');
calculate(24, 3, '-');
</pre>
<p>那么，我们能不能把这些东西封装起来呢，我们需要使用prototype。看下面的示例：</p>
<pre class="brush: jscript; highlight: [6,11]; title: ; notranslate">var Cal = function(x, y){
    this.x = x;
    this.y = y;
}

Cal.prototype.operations = {
    '+': function(x, y) { return x+y;},
    '-': function(x, y) { return x-y;}
};

Cal.prototype.calculate = function(operation){
    return this.operations[operation](this.x, this.y);
};

var c = new Cal(4, 5);

c.calculate('+');
c.calculate('-');</pre>
<p>这就是prototype的用法，prototype 是javascript这个语言中最重要的内容。网上有太多的文章介始这个东西了。说白了，prototype就是对一对象进行扩展，其特点在于通过“复制”一个已经存在的实例来返回新的实例,而不是新建实例。被复制的实例就是我们所称的“原型”，这个原型是可定制的（当然，这里没有真正的复制，实际只是委托）。上面的这个例子中，我们扩展了实例Cal，让其有了一个operations的属性和一个calculate的方法。</p>
<p>这样，我们可以通过这一特性来实现继承。还记得我们最最前面的那个Person吧， 下面的示例是创建一个Student来继承Person。</p>
<pre class="brush: jscript; title: ; notranslate">
function Person(name, email, website){
    this.name = name;
    this.email = email;
    this.website = website;
};

Person.prototype.sayHello = function(){
    var hello = &quot;Hello, I am &quot;+ this.name  + &quot;, &lt;br&gt;&quot; +
                &quot;my email is: &quot; + this.email + &quot;, &lt;br&gt;&quot; +
                &quot;my website is: &quot; + this.website;
    return hello;
};

function Student(name, email, website, no, dept){
    var proto = Object.getPrototypeOf;
    proto(Student.prototype).constructor.call(this, name, email, website);
    this.no = no;
    this.dept = dept;
}

// 继承prototype
Student.prototype = Object.create(Person.prototype);

//重置构造函数
Student.prototype.constructor = Student;

//重载sayHello()
Student.prototype.sayHello = function(){
    var proto = Object.getPrototypeOf;
    var hello = proto(Student.prototype).sayHello.call(this) + '&lt;br&gt;';
    hello += &quot;my student no is: &quot; + this. no + &quot;, &lt;br&gt;&quot; +
             &quot;my departent is: &quot; + this. dept;
    return hello;
};

var me = new Student(
    &quot;Chen Hao&quot;,
    &quot;haoel@hotmail.com&quot;,
    &quot;http://coolshell.cn&quot;,
    &quot;12345678&quot;,
    &quot;Computer Science&quot;
);
document.write(me.sayHello());</pre>
<h4>兼容性</h4>
<p>上面的这些代码并不一定能在所有的浏览器下都能运行，因为上面这些代码遵循 ECMAScript 5 的规范，关于ECMAScript 5 的浏览器兼容列表，你可以看这里“<a href="http://kangax.github.com/es5-compat-table/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/kangax.github.com/es5-compat-table/?referer=');">ES5浏览器兼容表</a>”。</p>
<p>本文中的所有代码都在Chrome最新版中测试过了。</p>
<p>下面是一些函数，可以用在不兼容ES5的浏览器中：</p>
<h5>Object.create()函数</h5>
<pre class="brush: jscript; title: ; notranslate">function clone(proto) {
    function Dummy() { }

    Dummy.prototype             = proto;
    Dummy.prototype.constructor = Dummy;

    return new Dummy(); //等价于Object.create(Person);
}

var me = clone(Person);
</pre>
<h5>defineProperty()函数</h5>
<pre class="brush: jscript; title: ; notranslate">function defineProperty(target, key, descriptor) {
    if (descriptor.value){
        target[key] = descriptor.value;
    }else {
        descriptor.get &amp;&amp; target.__defineGetter__(key, descriptor.get);
        descriptor.set &amp;&amp; target.__defineSetter__(key, descriptor.set);
    }

    return target
}</pre>
<h5>keys()函数</h5>
<pre class="brush: jscript; title: ; notranslate">function keys(object) { var result, key
    result = [];
    for (key in object){
        if (object.hasOwnProperty(key))  result.push(key)
    }

    return result;
}</pre>
<h5>Object.getPrototypeOf() 函数</h5>
<pre class="brush: jscript; title: ; notranslate">function proto(object) {
    return !object?                null
         : '__proto__' in object?  object.__proto__
         : /* not exposed? */      object.constructor.prototype
}</pre>
<h5>bind 函数</h5>
<pre class="brush: jscript; title: ; notranslate">var slice = [].slice

function bind(fn, bound_this) { var bound_args
    bound_args = slice.call(arguments, 2)
    return function() { var args
        args = bound_args.concat(slice.call(arguments))
        return fn.apply(bound_this, args) }
}
</pre>
<h4>参考</h4>
<ul>
<li>W3CSchool</li>
<li>MDN (Mozilla Developer Network)</li>
<li>MSDN (Microsoft Software Development Network)</li>
<li><a href="http://killdream.github.com/blog/2011/10/understanding-javascript-oop/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/killdream.github.com/blog/2011/10/understanding-javascript-oop/?referer=');">Understanding Javascript OOP</a>.</li>
</ul>
<p><span style="color: #cc0000;"><strong>（转载时请注明作者和出处，请勿用于任何商业用途）</strong></span></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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1608.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6441.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1608.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6441.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1924.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6441.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1924.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6441.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/21/9139797.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="20个优秀的Javascript导航技术" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F918.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6441.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F918.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6441.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>
                <td width="102" valign="top" style="padding: 5px !important; margin: 0 !important; border-left: 1px solid #DDDDDD !important;">
                    <a target="_blank" title="把Flash转成Javascript/HTML5" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2497.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6441.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2497.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6441.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/20/23739426.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;">把Flash转成Javascript/HTML5</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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1850.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6441.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1850.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6441.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/10437573.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>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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年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><li>2011年06月08日 -- <a href="http://coolshell.cn/articles/4795.html" title="开源中最好的Web开发的资源">开源中最好的Web开发的资源</a></li><li>2011年05月19日 -- <a href="http://coolshell.cn/articles/4722.html" title="在Web上运行Linux">在Web上运行Linux</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/6441.html/feed</wfw:commentRss>
		<slash:comments>55</slash:comments>
		</item>
		<item>
		<title>Hash Collision DoS 问题</title>
		<link>http://coolshell.cn/articles/6424.html</link>
		<comments>http://coolshell.cn/articles/6424.html#comments</comments>
		<pubDate>Fri, 06 Jan 2012 00:36:05 +0000</pubDate>
		<dc:creator>陈皓</dc:creator>
				<category><![CDATA[业界新闻]]></category>
		<category><![CDATA[网络安全]]></category>
		<category><![CDATA[Hash]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[安全]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=6424</guid>
		<description><![CDATA[最近，除了国内明文密码的安全事件，还有一个事是比较大的，那就是 Hash Collision DoS （Hash碰撞的拒绝式服务攻击），有恶意的人会通过这个安全弱点会让你的服务器运行巨慢无比。这个安全弱点利用了各语言的Hash算法的“非随机性”可以制造出N多的value不一样，但是key一样数据，然后让你的Hash表成为一张单向链表，而导致你的整个网站或是程序的运行性能以级数下降（可以很轻松的让你的CPU升到100%）。目前，这个问题出现于Java, JRuby, PHP, Python, Rubinius, Ruby这些语言中，主要： Java, 所有版本 JRuby &#60;= 1.6.5 （目前fix在 1.6.5.1） PHP &#60;= 5.3.8, &#60;= 5.4.0RC3 （目前fix在 5.3.9,  5.4.0RC4） Python, all versions Rubinius, all versions Ruby &#60;= 1.8.7-p356 （目前fix在 1.8.7-p357, 1.9.x） Apache Geronimo, 所有版本 Apache Tomcat &#60;= 5.5.34, &#60;= 6.0.34, &#60;= 7.0.22 （目前fix在 5.5.35,  6.0.35,  7.0.23） Oracle Glassfish &#60;= 3.1.1 （目前fix在mainline） Jetty, 所有版本 Plone, 所有版本 Rack [...]<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="Java构造时成员初始化的陷阱" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1106.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6424.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1106.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6424.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;">Java构造时成员初始化的陷阱</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="JAVA的字符串拼接与性能" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2235.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6424.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2235.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6424.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/13691753.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;">JAVA的字符串拼接与性能</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非常有用的Java程序片段" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F889.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6424.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F889.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6424.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非常有用的Java程序片段</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="Java书籍Top 10" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F14.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6424.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F14.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6424.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/10437602.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;">Java书籍Top 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="C++和JAVA传统中积极的一面" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F209.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6424.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F209.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6424.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/10434907.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;">C++和JAVA传统中积极的一面</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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>最近，除了国内明文密码的安全事件，还有一个事是比较大的，那就是 Hash Collision DoS （Hash碰撞的拒绝式服务攻击），有恶意的人会通过这个安全弱点会让你的服务器运行巨慢无比。<strong>这个安全弱点利用了各语言的Hash算法的“非随机性”可以制造出N多的value不一样，但是key一样数据，然后让你的Hash表成为一张单向链表，而导致你的整个网站或是程序的运行性能以级数下降（可以很轻松的让你的CPU升到100%）</strong>。目前，这个问题出现于<a href="http://www.java.com/" onclick="pageTracker._trackPageview('/outgoing/www.java.com/?referer=');">Java</a>, <a href="http://jruby.org/" onclick="pageTracker._trackPageview('/outgoing/jruby.org/?referer=');">JRuby</a>, <a href="http://www.php.net/" onclick="pageTracker._trackPageview('/outgoing/www.php.net/?referer=');">PHP</a>, <a href="http://python.org/" onclick="pageTracker._trackPageview('/outgoing/python.org/?referer=');">Python</a>, <a href="http://rubini.us/" onclick="pageTracker._trackPageview('/outgoing/rubini.us/?referer=');">Rubinius</a>, <a href="http://www.ruby-lang.org/" onclick="pageTracker._trackPageview('/outgoing/www.ruby-lang.org/?referer=');">Ruby</a>这些语言中，主要：</p>
<ul>
<li><a href="http://www.java.com" onclick="pageTracker._trackPageview('/outgoing/www.java.com?referer=');">Java</a>, 所有版本</li>
<li><a href="http://jruby.org/" onclick="pageTracker._trackPageview('/outgoing/jruby.org/?referer=');">JRuby</a> &lt;= 1.6.5 （目前fix在 1.6.5.1）</li>
<li><a href="http://www.php.net/" onclick="pageTracker._trackPageview('/outgoing/www.php.net/?referer=');">PHP</a> &lt;= 5.3.8, &lt;= 5.4.0RC3 （目前fix在 5.3.9,  5.4.0RC4）</li>
<li><a href="http://python.org/" onclick="pageTracker._trackPageview('/outgoing/python.org/?referer=');">Python</a>, all versions</li>
<li><a href="http://rubini.us/" onclick="pageTracker._trackPageview('/outgoing/rubini.us/?referer=');">Rubinius</a>, all versions</li>
<li><a href="http://www.ruby-lang.org/" onclick="pageTracker._trackPageview('/outgoing/www.ruby-lang.org/?referer=');">Ruby</a> &lt;= 1.8.7-p356 （目前fix在 1.8.7-p357, 1.9.x）</li>
<li><a href="http://geronimo.apache.org/" onclick="pageTracker._trackPageview('/outgoing/geronimo.apache.org/?referer=');">Apache Geronimo</a>, 所有版本</li>
<li><a href="http://tomcat.apache.org/" onclick="pageTracker._trackPageview('/outgoing/tomcat.apache.org/?referer=');">Apache Tomcat</a> &lt;= 5.5.34, &lt;= 6.0.34, &lt;= 7.0.22 （目前fix在 5.5.35,  6.0.35,  7.0.23）</li>
<li><a href="http://glassfish.java.net/" onclick="pageTracker._trackPageview('/outgoing/glassfish.java.net/?referer=');">Oracle Glassfish</a> &lt;= 3.1.1 （目前fix在mainline）</li>
<li><a href="http://www.eclipse.org/jetty/" onclick="pageTracker._trackPageview('/outgoing/www.eclipse.org/jetty/?referer=');">Jetty</a>, 所有版本</li>
<li><a href="http://plone.org/" onclick="pageTracker._trackPageview('/outgoing/plone.org/?referer=');">Plone</a>, 所有版本</li>
<li><a href="http://rack.rubyforge.org/" onclick="pageTracker._trackPageview('/outgoing/rack.rubyforge.org/?referer=');">Rack</a> &lt;= 1.3.5, &lt;= 1.2.4, &lt;= 1.1.2 （目前fix 在 1.4.0, 1.3.6, 1.2.5, 1.1.3）</li>
<li><a href="http://code.google.com/p/v8/" onclick="pageTracker._trackPageview('/outgoing/code.google.com/p/v8/?referer=');">V8 JavaScript Engine</a>, 所有版本</li>
<li>ASP.NET 没有打MS11-100补丁</li>
</ul>
<p>注意，Perl没有这个问题，因为Perl在N年前就fix了这个问题了。关于这个列表的更新，请参看 <a href="http://www.ocert.org/advisories/ocert-2011-003.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.ocert.org/advisories/ocert-2011-003.html?referer=');">oCERT的2011-003报告</a>，比较坑爹的是，这个问题早在2003 年就在论文《<a href="http://www.cs.rice.edu/~scrosby/hash/CrosbyWallach_UsenixSec2003.pdf" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.cs.rice.edu/_scrosby/hash/CrosbyWallach_UsenixSec2003.pdf?referer=');">通过算法复杂性进行拒绝式服务攻击</a>》中被报告了，但是好像没有引起注意，尤其是Java。</p>
<h4>弱点攻击解释</h4>
<p>你可以会觉得这个问题没有什么大不了的，因为黑客是看不到hash算法的，如果你这么认为，那么你就错了，这说明对Web编程的了解还不足够底层。</p>
<p><span id="more-6424"></span></p>
<p>无论你用JSP，PHP，Python，Ruby来写后台网页的时候，在处理HTTP POST数据的时候，你的后台程序可以很容易地以访问表单字段名来访问表单值，就像下面这段程序一样：</p>
<pre class="brush: php; title: ; notranslate">

$usrname = $_POST['username'];
$passwd = $_POST['password'];
</pre>
<p>这是怎么实现的呢？这后面的东西就是Hash Map啊，所以，我可以给你后台提交一个有10K字段的表单，这些字段名都被我精心地设计过，他们全是Hash Collision ，于是你的Web Server或语言处理这个表单的时候，就会建造这个hash map，于是在每插入一个表单字段的时候，都会先遍历一遍你所有已插入的字段，于是你的服务器的CPU一下就100%了，你会觉得这10K没什么，那么我就发很多个的请求，你的服务器一下就不行了。</p>
<p>举个例子，你可能更容易理解：</p>
<p>如果你有n个值—— v1, v2, v3, &#8230; vn，把他们放到hash表中应该是足够散列的，这样性能才高：</p>
<blockquote><p>0 -&gt; v2<br />
1 -&gt; v4<br />
2 -&gt; v1<br />
&#8230;<br />
&#8230;<br />
n -&gt; v(x)</p></blockquote>
<p>但是，这个攻击可以让我造出N个值——  dos1, dos2, &#8230;., dosn，他们的hash key都是一样的（也就是Hash Collision），导致你的hash表成了下面这个样子：</p>
<blockquote><p>0 &#8211; &gt; dos1 -&gt; dos2 -&gt; dos3 -&gt; &#8230;. -&gt;dosn<br />
1 -&gt; null<br />
2 -&gt; null<br />
&#8230;<br />
&#8230;<br />
n -&gt; null</p></blockquote>
<p>于是，单向链接就这样出现了。这样一来，O(1)的搜索算法复杂度就成了O(n)，而插入N个数据的算法复杂度就成了O(n^2)，你想想这是什么样的性能。</p>
<p>（关于Hash表的实现，如果你忘了，那就把大学时的《数据结构》一书拿出来看看）</p>
<h4>  Hash Collision DoS 详解</h4>
<p>StackOverflow.com是个好网站， 合格的程序员都应该知道这个网站。上去一查，就看到了这个贴子“<a title="Application vulnerability due to Non Random Hash Functions" href="http://stackoverflow.com/questions/8669946/application-vulnerability-due-to-non-random-hash-functions" target="_blank" onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/questions/8669946/application-vulnerability-due-to-non-random-hash-functions?referer=');">Application vulnerability due to Non Random Hash Functions</a>”。我把这个贴子里的东西摘一些过来。</p>
<p>首先，这些语言使用的Hash算法都是“非随机的”，如下所示，这个是Java和Oracle使用的Hash函数：</p>
<pre class="brush: cpp; title: ; notranslate">static int hash(int h)
{
h ^= (h &gt;&gt;&gt; 20) ^ (h &gt;&gt;&gt; 12);
return h ^ (h &gt;&gt;&gt; 7) ^ (h &gt;&gt;&gt; 4);
}</pre>
<p>所谓“非随机的” Hash算法，就可以猜。比如：</p>
<p>1）在Java里， Aa和BB这两个字符串的hash code(或hash key) 是一样的，也就是Collision 。</p>
<p>2）于是，我们就可以通过这两个种子生成更多的拥有同一个hash key的字符串。如：”AaAa”, “AaBB”, “BBAa”, “BBBB”。这是第一次迭代。其实就是一个排列组合，写个程序就搞定了。</p>
<p>3）然后，我们可以用这4个长度的字符串，构造8个长度的字符串，如下所示：</p>
<pre style="padding-left: 30px;"><code>"AaAaAaAa", "AaAaBBBB", "AaAaAaBB", "AaAaBBAa", 
"BBBBAaAa", "BBBBBBBB", "BBBBAaBB", "BBBBBBAa", 
"AaBBAaAa", "AaBBBBBB", "AaBBAaBB", "AaBBBBAa", 
"BBAaAaAa", "BBAaBBBB", "BBAaAaBB", "BBAaBBAa",</code></pre>
<p><code>4）同理，我们就可以生成16个长度的，以及256个长度的字符串，总之，很容易生成N多的这样的值。</code></p>
<p>在攻击时，我只需要把这些数据做成一个HTTP POST 表单，然后写一个无限循环的程序，不停地提交这个表单。你用你的浏览器就可以了。当然，如果做得更精妙一点的话，把你的这个表单做成一个跨站脚本，然后找一些网站的跨站漏洞，放上去，于是能过SNS的力量就可以找到N多个用户来帮你从不同的IP来攻击某服务器。</p>
<p>&nbsp;</p>
<h4>防守</h4>
<p>要防守这样的攻击，有下面几个招：</p>
<ul>
<li>打补丁，把hash算法改了。</li>
<li>限制POST的参数个数，限制POST的请求长度。</li>
<li>最好还有防火墙检测异常的请求。</li>
</ul>
<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="Java构造时成员初始化的陷阱" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1106.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6424.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1106.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6424.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;">Java构造时成员初始化的陷阱</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="JAVA的字符串拼接与性能" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2235.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6424.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2235.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6424.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/13691753.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;">JAVA的字符串拼接与性能</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非常有用的Java程序片段" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F889.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6424.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F889.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6424.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非常有用的Java程序片段</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="Java书籍Top 10" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F14.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6424.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F14.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6424.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/10437602.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;">Java书籍Top 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="C++和JAVA传统中积极的一面" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F209.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6424.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F209.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6424.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/10434907.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;">C++和JAVA传统中积极的一面</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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月05日 -- <a href="http://coolshell.cn/articles/6335.html" title="Resin服务器getResource揭秘">Resin服务器getResource揭秘</a></li><li>2011年12月28日 -- <a href="http://coolshell.cn/articles/6112.html" title="由一个问题到 Resin ClassLoader 的学习">由一个问题到 Resin ClassLoader 的学习</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年10月31日 -- <a href="http://coolshell.cn/articles/5709.html" title="API设计：用流畅接口构造内部DSL">API设计：用流畅接口构造内部DSL</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/6424.html/feed</wfw:commentRss>
		<slash:comments>54</slash:comments>
		</item>
		<item>
		<title>Resin服务器getResource揭秘</title>
		<link>http://coolshell.cn/articles/6335.html</link>
		<comments>http://coolshell.cn/articles/6335.html#comments</comments>
		<pubDate>Thu, 05 Jan 2012 00:28:59 +0000</pubDate>
		<dc:creator>liuxiaori</dc:creator>
				<category><![CDATA[Java语言]]></category>
		<category><![CDATA[编程语言]]></category>
		<category><![CDATA[ClassLoader]]></category>
		<category><![CDATA[getResource]]></category>
		<category><![CDATA[getResourceAsStream]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Resin]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=6335</guid>
		<description><![CDATA[（感谢网友 liuxiaori 继续分享其经历）这样的详细的图文并茂的文章让我很佩服！ 前言 接上文“由一个问题到Resin ClassLoader的学习”，本文将以this.getClass().getResource(“/”).getPath()和this.getClass().getResourceAsStream(“/a.txt”)为例，一步步解析加载的过程。 调试环境 下载resin3.0.23的源码(http://www.caucho.com/download/resin-3.0.23-src.zip)。 部署到myeclipse中，有错误，本人忽略了。Resin可运行。 将EhCacheTestAnnotation部署到resin3.0.23中。 调试this.getClass().getResource(“/”).getPath()。 问题来了，无论如何也模拟不出来&#60;compiling-loader&#62;所造成的影响，一直输出：/D:/work_other/project/resin-3.0.23/bin/ 。无奈之下，采用了这种方式：使用两个eclipse，一个使用发布版本的，部署EhCacheTestAnnotation进行调试；另外一个部署resin3.0.23源码，调试到哪里对照看源码。 开始 1) this.getClass().getResource(“/”).getPath() 本次调试涉及的所有类加载器为： EnvironmentClassLoader$24156236[web-app:http://localhost:8787/EhCacheTestAnnotation] EnvironmentClassLoader$7806641[host:http://localhost:8787] EnvironmentClassLoader$22459270[servlet-server:] sun.misc.Launcher$AppClassLoader@7259da sun.misc.Launcher$ExtClassLoader@16930e2 首先进入Class的getResource(String name)方法，如下图： 最后委托给ClassLoader的getResource方法。那么这个ClassLoader是哪个呢？一看下图便知： 是DynamicClassLoader的getResource方法，原理上文已述。 最终会委托给sun.misc.Launcher$ExtClassLoader@16930e2类加载器的getResource方法，返回null，然后开始回溯。 还记得吗？当java.net.URLClassLoader分支的ClassLoader的getResource方法返回值为null后，就要遍历嵌入DynamicClassLoader中的Resin的Loader(即_loaders集合)。 当然回溯到EnvironmentClassLoader$22459270[servlet-server:]中，那么它中_loaders这个集合中的Loader又有哪些呢？ 以图为证，当天确实回溯到该ClassLoader，而且开始准备遍历_loaders集合。 DynamicClassLoader的1306行，没问题，resin3.0.23源码截图为证： 不做多余解释，那么“servlet-server”这个ClassLoader中的_loaders集合中都放了一些什么呢？ 存放了两个TreeLoader(Loader的子类)，然未找到结果，返回null。继续回溯。 这次轮到遍历EnvironmentClassLoader$7806641[host:http://localhost:8787]的_loaders。下图为证： _loaders中的内容如下图： 比较长，我贴出来： [CompilingLoader[src:/D:/work/resin-3.0.23/webapps/WEB-INF/classes], LibraryLoader[com.caucho.config.types.FileSetType@fb6763], CompilingLoader[src:/D:/work/resin-3.0.23/webapps/WEB-INF/classes], LibraryLoader[com.caucho.config.types.FileSetType@140b8fd], CompilingLoader[src:/D:/work/resin-3.0.23/webapps/WEB-INF/classes], LibraryLoader[com.caucho.config.types.FileSetType@30fc1f]] 注意到了吧，主角来了。那仔细调试下把。爆料一下：CompilingLoader[src:/D:/work/resin-3.0.23/webapps/WEB-INF/classes]就是主角。 看到了吧，遍历时，当前的Loader为CompilingLoader[src:/D:/work/resin-3.0.23/webapps/WEB-INF/classes]，而且url可是不为null了哦。再贴一张，看看url的值到底是什么！ 嗯，不用多做解释了吧。 最后看看程序输出是否吻合，如下图： 然后修改resin.conf中的&#60;compiling-loader&#62;将其注释掉，看看程序结果会不会是我们期望的：/D:/work/resin-3.0.23/webapps/EhCacheTestAnnotation/WEB-INF/classes/。拭目以待。 为节省篇幅，一下只关注关键位置。 首先调试到EnvironmentClassLoader$7806641[host:http://localhost:8787]，我们需要停下来一下。 再看一下_loaders的值。 贴一个详细的： [LibraryLoader[com.caucho.config.types.FileSetType@1299f7e], LibraryLoader[com.caucho.config.types.FileSetType@1a631cc], LibraryLoader[com.caucho.config.types.FileSetType@f6398]] 对比一下，在注释掉&#60;compiling-loader&#62;后，loaders中是没有CompilingClassLoader实例的。 继续，下面就轮到EnvironmentClassLoader$24156236[web-app:http://localhost:8787/EhCacheTestAnnotation]这个ClassLoader了，会是什么样子呢？ 进入该ClassLoader时，url值依旧为null，那_loaders会有变化吗？如下图： 继续遍历_loaders。 到这里就结束了，url在EnvironmentClassLoader$24156236[web-app:http://localhost:8787/EhCacheTestAnnotation]中被加载。 1) this.getClass().getResourceAsStream(“/a.txt”) getResourceAsStream(String name)方法也是采用双亲委派的方式。在前一篇文章中提出“getResourceAsStream可是将获取路径委托给getResource，&#60;compiling-loader&#62;却没有对getResourceAsStream产生影响” ClassLoader中getResourceAsStream源码也确实是委托为getResource了，可是为什么呢？ getResourceAsStream(String name)方法。 其实不难解释，JVM中ClassLoader的getResourceAsStream(“/a.txt”)返回了null，然后开始回溯，与getResource方法的原理一致，直到某个ClassLoader及其子类或者Loader及其子类找到了”/a.txt”，并以流的形式返回，当然谁都没找到就返回null。 捡重点的说。 [...]<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="由一个问题到 Resin ClassLoader 的学习" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6112.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6335.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6112.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6335.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/28/13163053.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;">由一个问题到 Resin ClassLoader 的学习</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="Java书籍Top 10" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F14.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6335.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F14.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6335.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/10437602.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;">Java书籍Top 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="Java构造时成员初始化的陷阱" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1106.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6335.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1106.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6335.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;">Java构造时成员初始化的陷阱</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="JAVA的字符串拼接与性能" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2235.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6335.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2235.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6335.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/13691753.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;">JAVA的字符串拼接与性能</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="如何在Java中避免equals方法的隐藏陷阱" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1051.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6335.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1051.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6335.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;">如何在Java中避免equals方法的隐藏陷阱</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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>（<span style="color: #cc0000;">感谢网友 liuxiaori 继续分享其经历</span>）这样的详细的图文并茂的文章让我很佩服！</strong></p>
<h4>前言</h4>
<p>接上文“<a title="由一个问题到 Resin ClassLoader 的学习" href="http://coolshell.cn/articles/6112.html" target="_blank">由一个问题到Resin ClassLoader的学习</a>”，本文将以this.getClass().getResource(“/”).getPath()和this.getClass().getResourceAsStream(“/a.txt”)为例，一步步解析加载的过程。</p>
<h4>调试环境</h4>
<ol>
<li>下载resin3.0.23的源码(<a href="http://www.caucho.com/download/resin-3.0.23-src.zip" onclick="pageTracker._trackPageview('/outgoing/www.caucho.com/download/resin-3.0.23-src.zip?referer=');">http://www.caucho.com/download/resin-3.0.23-src.zip</a>)。</li>
<li>部署到myeclipse中，有错误，本人忽略了。Resin可运行。</li>
<li>将EhCacheTestAnnotation部署到resin3.0.23中。</li>
<li>调试this.getClass().getResource(“/”).getPath()。</li>
</ol>
<p>问题来了，无论如何也模拟不出来&lt;compiling-loader&gt;所造成的影响，一直输出：/D:/work_other/project/resin-3.0.23/bin/ 。无奈之下，采用了这种方式：使用两个eclipse，一个使用发布版本的，部署EhCacheTestAnnotation进行调试；另外一个部署resin3.0.23源码，调试到哪里对照看源码。</p>
<h4>开始</h4>
<h5>1) this.getClass().getResource(“/”).getPath()</h5>
<p>本次调试涉及的所有类加载器为：</p>
<blockquote><p>EnvironmentClassLoader$24156236[web-app:http://localhost:8787/EhCacheTestAnnotation]</p>
<p>EnvironmentClassLoader$7806641[host:http://localhost:8787]</p>
<p>EnvironmentClassLoader$22459270[servlet-server:]</p>
<p>sun.misc.Launcher$AppClassLoader@7259da</p>
<p>sun.misc.Launcher$ExtClassLoader@16930e2</p></blockquote>
<p>首先进入Class的getResource(String name)方法，如下图：</p>
<p><span id="more-6335"></span></p>
<div id="attachment_6390" class="wp-caption aligncenter" style="width: 563px"><img class="size-full wp-image-6390" title="图片1" src="http://coolshell.cn/wp-content/uploads/2012/01/图片1.png" alt="图片1" width="553" height="182" /><p class="wp-caption-text">图1</p></div>
<p>最后委托给ClassLoader的getResource方法。那么这个ClassLoader是哪个呢？一看下图便知：</p>
<div id="attachment_6391" class="wp-caption aligncenter" style="width: 563px"><img class="size-full wp-image-6391" title="图片2" src="http://coolshell.cn/wp-content/uploads/2012/01/图片2.png" alt="图片2" width="553" height="85" /><p class="wp-caption-text">图2</p></div>
<p>是DynamicClassLoader的getResource方法，原理上文已述。</p>
<p>最终会委托给sun.misc.Launcher$ExtClassLoader@16930e2类加载器的getResource方法，返回null，然后开始回溯。</p>
<p>还记得吗？当java.net.URLClassLoader分支的ClassLoader的getResource方法返回值为null后，就要遍历嵌入DynamicClassLoader中的Resin的Loader(即_loaders集合)。</p>
<p>当然回溯到EnvironmentClassLoader$22459270[servlet-server:]中，那么它中_loaders这个集合中的Loader又有哪些呢？</p>
<p>以图为证，当天确实回溯到该ClassLoader，而且开始准备遍历_loaders集合。</p>
<div id="attachment_6392" class="wp-caption aligncenter" style="width: 564px"><img class="size-full wp-image-6392" title="图3" src="http://coolshell.cn/wp-content/uploads/2012/01/图片3.png" alt="图3" width="554" height="74" /><p class="wp-caption-text">图3</p></div>
<p>DynamicClassLoader的1306行，没问题，resin3.0.23源码截图为证：</p>
<div id="attachment_6393" class="wp-caption aligncenter" style="width: 564px"><img class="size-full wp-image-6393" title="图4" src="http://coolshell.cn/wp-content/uploads/2012/01/图片4.png" alt="图4" width="554" height="236" /><p class="wp-caption-text">图4</p></div>
<p>不做多余解释，那么“servlet-server”这个ClassLoader中的_loaders集合中都放了一些什么呢？</p>
<div id="attachment_6394" class="wp-caption aligncenter" style="width: 564px"><img class="size-full wp-image-6394" title="图5" src="http://coolshell.cn/wp-content/uploads/2012/01/图片5.png" alt="图5" width="554" height="121" /><p class="wp-caption-text">图5</p></div>
<p>存放了两个TreeLoader(Loader的子类)，然未找到结果，返回null。继续回溯。</p>
<p>这次轮到遍历EnvironmentClassLoader$7806641[host:http://localhost:8787]的_loaders。下图为证：</p>
<div id="attachment_6395" class="wp-caption aligncenter" style="width: 564px"><img class="size-full wp-image-6395" title="图6" src="http://coolshell.cn/wp-content/uploads/2012/01/图片6.png" alt="图6" width="554" height="170" /><p class="wp-caption-text">图6</p></div>
<p>_loaders中的内容如下图：</p>
<div id="attachment_6396" class="wp-caption aligncenter" style="width: 564px"><img class="size-full wp-image-6396" title="图7" src="http://coolshell.cn/wp-content/uploads/2012/01/图片7.png" alt="图7" width="554" height="193" /><p class="wp-caption-text">图7</p></div>
<p>比较长，我贴出来：</p>
<blockquote><p>[CompilingLoader[src:/D:/work/resin-3.0.23/webapps/WEB-INF/classes], LibraryLoader[com.caucho.config.types.FileSetType@fb6763], CompilingLoader[src:/D:/work/resin-3.0.23/webapps/WEB-INF/classes], LibraryLoader[com.caucho.config.types.FileSetType@140b8fd], CompilingLoader[src:/D:/work/resin-3.0.23/webapps/WEB-INF/classes], LibraryLoader[com.caucho.config.types.FileSetType@30fc1f]]</p></blockquote>
<p>注意到了吧，主角来了。那仔细调试下把。爆料一下：CompilingLoader[src:/D:/work/resin-3.0.23/webapps/WEB-INF/classes]就是主角。</p>
<div id="attachment_6397" class="wp-caption aligncenter" style="width: 564px"><img class="size-full wp-image-6397" title="图8" src="http://coolshell.cn/wp-content/uploads/2012/01/图片8.png" alt="图8" width="554" height="251" /><p class="wp-caption-text">图8</p></div>
<p>看到了吧，遍历时，当前的Loader为CompilingLoader[src:/D:/work/resin-3.0.23/webapps/WEB-INF/classes]，而且url可是不为null了哦。再贴一张，看看url的值到底是什么！</p>
<div id="attachment_6400" class="wp-caption aligncenter" style="width: 564px"><img class="size-full wp-image-6400" title="图9" src="http://coolshell.cn/wp-content/uploads/2012/01/图片9.png" alt="图9" width="554" height="250" /><p class="wp-caption-text">图9</p></div>
<p>嗯，不用多做解释了吧。</p>
<p>最后看看程序输出是否吻合，如下图：</p>
<div id="attachment_6401" class="wp-caption aligncenter" style="width: 564px"><img class="size-full wp-image-6401" title="图10" src="http://coolshell.cn/wp-content/uploads/2012/01/图片10.png" alt="图10" width="554" height="81" /><p class="wp-caption-text">图10</p></div>
<p>然后修改resin.conf中的&lt;compiling-loader&gt;将其注释掉，看看程序结果会不会是我们期望的：/D:/work/resin-3.0.23/webapps/EhCacheTestAnnotation/WEB-INF/classes/。拭目以待。</p>
<div id="attachment_6402" class="wp-caption aligncenter" style="width: 564px"><img class="size-full wp-image-6402" title="图11" src="http://coolshell.cn/wp-content/uploads/2012/01/图片11.png" alt="图11" width="554" height="106" /><p class="wp-caption-text">图11</p></div>
<p>为节省篇幅，一下只关注关键位置。</p>
<p>首先调试到EnvironmentClassLoader$7806641[host:http://localhost:8787]，我们需要停下来一下。</p>
<div id="attachment_6403" class="wp-caption aligncenter" style="width: 564px"><img class="size-full wp-image-6403" title="图12" src="http://coolshell.cn/wp-content/uploads/2012/01/图片12.png" alt="图12" width="554" height="154" /><p class="wp-caption-text">图12</p></div>
<p>再看一下_loaders的值。</p>
<div id="attachment_6404" class="wp-caption aligncenter" style="width: 564px"><img class="size-full wp-image-6404" title="图13" src="http://coolshell.cn/wp-content/uploads/2012/01/图片13.png" alt="图13" width="554" height="157" /><p class="wp-caption-text">图13</p></div>
<p>贴一个详细的：</p>
<blockquote><p>[LibraryLoader[com.caucho.config.types.FileSetType@1299f7e], LibraryLoader[com.caucho.config.types.FileSetType@1a631cc], LibraryLoader[com.caucho.config.types.FileSetType@f6398]]</p></blockquote>
<p>对比一下，在注释掉&lt;compiling-loader&gt;后，loaders中是没有CompilingClassLoader实例的。</p>
<p>继续，下面就轮到EnvironmentClassLoader$24156236[web-app:http://localhost:8787/EhCacheTestAnnotation]这个ClassLoader了，会是什么样子呢？</p>
<div id="attachment_6405" class="wp-caption aligncenter" style="width: 564px"><img class="size-full wp-image-6405" title="图14" src="http://coolshell.cn/wp-content/uploads/2012/01/图片14.png" alt="图14" width="554" height="154" /><p class="wp-caption-text">图14</p></div>
<p>进入该ClassLoader时，url值依旧为null，那_loaders会有变化吗？如下图：</p>
<div id="attachment_6406" class="wp-caption aligncenter" style="width: 564px"><img class="size-full wp-image-6406" title="图15" src="http://coolshell.cn/wp-content/uploads/2012/01/图片15.png" alt="图15" width="554" height="149" /><p class="wp-caption-text">图15</p></div>
<p>继续遍历_loaders。</p>
<div id="attachment_6407" class="wp-caption aligncenter" style="width: 564px"><img class="size-full wp-image-6407" title="图16" src="http://coolshell.cn/wp-content/uploads/2012/01/图片16.png" alt="图16" width="554" height="211" /><p class="wp-caption-text">图16</p></div>
<p>到这里就结束了，url在EnvironmentClassLoader$24156236[web-app:http://localhost:8787/EhCacheTestAnnotation]中被加载。</p>
<h5>1) this.getClass().getResourceAsStream(“/a.txt”)</h5>
<p>getResourceAsStream(String name)方法也是采用双亲委派的方式。在前一篇文章中提出“getResourceAsStream可是将获取路径委托给getResource，&lt;compiling-loader&gt;却没有对getResourceAsStream产生影响”</p>
<p>ClassLoader中getResourceAsStream源码也确实是委托为getResource了，可是为什么呢？</p>
<p>getResourceAsStream(String name)方法。</p>
<pre class="brush: java; title: ; notranslate">
public InputStream getResourceAsStream(String name) {
    URL url = getResource(name);
    try {
        return url != null ? url.openStream() : null;
    } catch (IOException e) {
        return null;
    }
}
</pre>
<p>其实不难解释，JVM中ClassLoader的getResourceAsStream(“/a.txt”)返回了null，然后开始回溯，与getResource方法的原理一致，直到某个ClassLoader及其子类或者Loader及其子类找到了”/a.txt”，并以流的形式返回，当然谁都没找到就返回null。</p>
<p>捡重点的说。</p>
<p>调试到sun.misc.Launcher$AppClassLoader@18d107f，即ClassLoader的子类，情形如下图：</p>
<div id="attachment_6408" class="wp-caption aligncenter" style="width: 564px"><img class="size-full wp-image-6408" title="图17" src="http://coolshell.cn/wp-content/uploads/2012/01/图片17.png" alt="图17" width="554" height="249" /><p class="wp-caption-text">图17</p></div>
<p>看见getResource(name)喽，按F5进去看个究竟。如下图，其parent为：sun.misc.Launcher$ExtClassLoader@360be0，其返回null。</p>
<div id="attachment_6398" class="wp-caption aligncenter" style="width: 564px"><img class="size-full wp-image-6398" title="图18" src="http://coolshell.cn/wp-content/uploads/2012/01/图片18.png" alt="图18" width="554" height="278" /><p class="wp-caption-text">图18</p></div>
<p>开始回溯到：EnvironmentClassLoader$1497769[servlet-server:]，与getResource方法一致，开始遍历_loaders集合。</p>
<p>这样就可以解释为何&lt;compiling-loader&gt;没有影响到getResourceAsStream了。因为资源(这里是/a.txt)，就不是由AppClassLoader和ExtClassLoader加载的，而是由DynamicClassLoader或者其内部的_loaders集合完成的加载。或者更确切的说是由CompilingClassLoader获取到的URL，再转换成InputStream。</p>
<p><span style="color: #ff0000;"><strong>&lt;comiling-loader&gt;其实对getResourceAsStream还是有点影响的，如果配置中配置了&lt;comiling-loader&gt;，并且&lt;comiling-loader&gt;配置的路径下，与实际项目的指定路径下，都放置了同名资源，则会先加载&lt;comiling-loader&gt;配置路径下的资源。</strong></span></p>
<p>比如，下图所示：</p>
<div id="attachment_6399" class="wp-caption aligncenter" style="width: 564px"><img class="size-full wp-image-6399" title="图19" src="http://coolshell.cn/wp-content/uploads/2012/01/图片19.png" alt="图19" width="554" height="266" /><p class="wp-caption-text">图19</p></div>
<p>&lt;compiling-loader&gt;配置的路径为：&lt;compiling-loader path=”webapps/WEB-INF/classes”/&gt;</p>
<p>在加载”/a.txt”时，优先加载webapps/WEB-INF/classes/a.txt。</p>
<h4>总结</h4>
<ol>
<li>&lt;compiling-loader&gt;如被注释掉，则只会在EnvironmentClassLoader$24156236[web-app:http://localhost:8787/EhCacheTestAnnotation]中的_loaders中被初始化，否则会在EnvironmentClassLoader$24156236[web-app:http://localhost:8787/EhCacheTestAnnotation]和EnvironmentClassLoader$7806641[host:http://localhost:8787两个类加载器各自的_loaders集合中被初始化。(通过调试this.getClass().getResource("/test").getPath()验证)</li>
<li>&lt;compiling-loader&gt;未注释掉，"/"(根路径)由EnvironmentClassLoader$7806641[host:http://localhost:8787]加载，注释掉后由EnvironmentClassLoader$24156236[web-app:http://localhost:8787/EhCacheTestAnnotation]加载。</li>
<li>EnvironmentClassLoader$7806641[host:http://localhost:8787]为Resin server的类加载器实例，EnvironmentClassLoader$24156236[web-app:http://localhost:8787/EhCacheTestAnnotation]为Web应用程序的类加载器实例。他们都属于java.net.URLClassLoader的实例。</li>
<li>&lt;compiling-loader&gt;某种程度上对getResourceAsStream方法有影响。</li>
</ol>
<p>现在&lt;compiling-loader&gt;如何影响getResource(“/”)，以及getResourceAsStream“不”被影响全部真相大白。</p>
<p><span style="color: #ff0000;">注：&lt;compiling-loader&gt;只对获取根路径产生影响，也就是参数为”/”。比如加载”/test/Path.class”不会产生影响。</span></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="由一个问题到 Resin ClassLoader 的学习" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6112.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6335.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6112.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6335.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/28/13163053.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;">由一个问题到 Resin ClassLoader 的学习</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="Java书籍Top 10" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F14.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6335.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F14.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6335.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/10437602.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;">Java书籍Top 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="Java构造时成员初始化的陷阱" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1106.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6335.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1106.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6335.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;">Java构造时成员初始化的陷阱</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="JAVA的字符串拼接与性能" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2235.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6335.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2235.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6335.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/13691753.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;">JAVA的字符串拼接与性能</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="如何在Java中避免equals方法的隐藏陷阱" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1051.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6335.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1051.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6335.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;">如何在Java中避免equals方法的隐藏陷阱</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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年12月28日 -- <a href="http://coolshell.cn/articles/6112.html" title="由一个问题到 Resin ClassLoader 的学习">由一个问题到 Resin ClassLoader 的学习</a></li><li>2012年01月06日 -- <a href="http://coolshell.cn/articles/6424.html" title="Hash Collision DoS 问题">Hash Collision DoS 问题</a></li><li>2011年10月31日 -- <a href="http://coolshell.cn/articles/5709.html" title="API设计：用流畅接口构造内部DSL">API设计：用流畅接口构造内部DSL</a></li><li>2011年10月14日 -- <a href="http://coolshell.cn/articles/5576.html" title="那些曾伴我走过编程之路的软件">那些曾伴我走过编程之路的软件</a></li><li>2011年08月01日 -- <a href="http://coolshell.cn/articles/5075.html" title="你确信你了解时间吗？">你确信你了解时间吗？</a></li><li>2011年07月18日 -- <a href="http://coolshell.cn/articles/4990.html" title="程序员技术练级攻略">程序员技术练级攻略</a></li><li>2011年06月29日 -- <a href="http://coolshell.cn/articles/4905.html" title="语言的数据亲和力">语言的数据亲和力</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/6335.html/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>程序员因为女孩而美丽！</title>
		<link>http://coolshell.cn/articles/6346.html</link>
		<comments>http://coolshell.cn/articles/6346.html#comments</comments>
		<pubDate>Wed, 04 Jan 2012 00:29:08 +0000</pubDate>
		<dc:creator>陈皓</dc:creator>
				<category><![CDATA[杂项资源]]></category>
		<category><![CDATA[职场生涯]]></category>
		<category><![CDATA[Programmer]]></category>
		<category><![CDATA[程序员]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=6346</guid>
		<description><![CDATA[女程序员是程序员里美丽的风景线，我希望这些女程序员的经历能让我们在这个“重男轻女”的社会中可以给女程员有更多平等的机会和条件，以及相应的尊重。因为，她们其中不乏优秀的程序员，而且在心态、态度和努力上还强过很多男性程序员，很多东西都值得我们大家向她们学习。 这篇文章的来由是因为Eva在“三个事和三个问题”的评论里问我女孩子是否能做技术，她说她的很多师兄都告诉他不要做技术，所以，她有些不坚定了。我的回复是告诉了她我工作经历中的两个技术很牛的女孩，并且我从她们身上学到了多技术。但是，后面有一些人回复说我误导了别人。所以，我在新浪微博和twitter上征集女程序员的故事和想法。我一共收到了19封邮件，其中有17封邮件来自女程序员。其中有一个已经发布了（一个女程序员的故事），其中的一些观点已经在网上传播，并得到了大家的刮目和称赞。但这并不是特例，因为下面的这些故事中，还有很多令人刮目相看的东西。 说明：先说明一下，这篇文章并不想讨论女孩子是不是适合做技术，这不值得讨论，因为，在“一个女程序员的故事”中我们已经知道，态度和努力才是原因，而不是性别。这里，也只是想告诉那些有“性别歧视”、“看不起女程序员”、“骄傲自大”的男程序员们，那些女程序员不为所知的一面。我把几乎所有的故事都列在这篇文章里了，我觉得我不用再多说什么了，这些故事组成的风景线，可以让你充分地了解女程序员。 在看到那些故事之前，我们需要了解这样的现实—— 大多数女孩子并不喜欢技术。这点从我们的计算机专业的学校就可以看到了。我上大学时，两个专业60个同学，有15个女生，男女比例已经失衡。不过，这些女生今天基本全部都还在做技术。现在，十多年了，她们其中女生还在各个公司的技术部门，主要做 开发和运维。这些是70后的女生。对于80后和90后的女生来说，可能喜欢技术的就更少了。Gavin在来信中说：“我们学院每届大约有800名学生，也就是说每年整个计算机学院只有大约50名女生。在这50名女生中，据我所知有至少一半的女生从开始到最后对编程一点兴趣都没有，这一半的女生有的准备跨专业考研，有的在考公务员，有的去了跟计算机专业几乎不沾边的行业去工作了，有的在大二的时候就已经开始修双专业了”。不过，在这里我们来看看做技术的女孩子是什么样的。 女孩子在找工作的时候总是会被歧视。很多用人单位都会问女孩子生孩子的问题，这简直就是干涉隐私和性别歧视，要在西方国家里，完全可以对这样的公司进行起诉。对于这种不尊重女性的公司，无论男女，一定不会尊重员工的。所以，这样的公司一定不要去。而很多女孩也会觉得结婚生子后就不能再从事技术了，所以，她们也对技术行业的未来没有信心。Myma在来信中说：“女人做技术最怕就是世俗的偏见，尤其是过了30，生了孩子，明显感觉出来了，职业瓶颈”。 召娣说：“面试的时候会问有没有男朋友，下一步会不会结婚，接下来就是会不会要孩子之类的”，几乎所有的女程序员都在说这个事。 自大的男程序员看不起女程序员。女程序员在工作中受到太多的不公平的待遇了。就连平时男程序员们都以一种高人一头的语气和她们说话。这样的例子太多了，在我blog中的回复中，在平时，我们都可以看得到。而我们的大多数的女性都会因为别人看不起而失去信心。当然，这点男程序员也一样，因为技术好的人总是会看不起技术不好的人。这是技术人员的通病。冰在来信中说：“另一个困扰的问题是，可能女生少的原因，在本部门风言风语不断，给我个人生活不少的精神压力，平时同事也会半开玩笑的说，嫁了吧，写什么代码，而且跟一些比较资深的程序员聊天时，总会呵呵的轻笑，然后说你是程序员啊。。。部门一些杂务，通常都扔了给我处理，这个我觉得吃点亏也没什么大事，但是就是忍受不了那种受轻视的感觉”。Cathy说：“项目组的组长是一个博士，人很好但是不太会和女孩子打交道，或者说有一些性别歧视吧。” 但是这些现实中的东西，对于我们的女程序员来说算不了什么！不信，你看看他们的故事。至少你会发现，做技术的女孩一点也不浮华！ 女程序员的故事 下面的故事，都是原文，没有经过任何编辑。下面的故事，很多也很长，她们串成了一个非常美丽的风景线，我真的希望你有空能读一读这些故事。你会发现这些故事都有我们自己的身影。 真的非常感谢大家对我的信任，给我发来这么多的故事，谢谢你们的支持。我完全相信—— 程序员因为女孩而美丽！ Shaofei &#8211; 妈妈是个程序员 1.我老妈是程序员，老朽今年二十有七了，可以想象年龄。 2.她20来岁的时候，背着全部门写的程序——一卷打孔纸带去北京上机调试，要排机时，还要给重要的项目让路，改程序么，就是把纸带剪断，用胶粘一段上去之类的。 3.她们那个时代的程序员都是直接读机器码的，大约就是5665表示begin之类的东西，而且是用打孔纸带二进制表示的，嗯，小时候有印象，她读程序就是站在床上一手拿着纸带卷，另一手抽着读，读过的就拖到地上。 4.好吧，那个时代的程序员应该坚持到现在的不多，很遗憾她中间也转了管理又转了市场，后来创创业也没成，于是现在待在家里悠闲。 zxy_snow &#8211; 半女程序员流水账 自我介绍下，女，大三，某高校软件工程专业。 我想，严格意义上来说，我还算不上女程序员吧，还是一个弱弱的学生。 接触程序还是在大学开始，或者说，大一下接触ACM 之后吧。当初和朋友一起做ACM，这一年半，不停地学算法、刷题，也成就了一个水题博客（我的CSDN密码??），交到了很多其他大学的朋友，人外有人，深知这句话的意思。虽然算不上太聪明，不过不笨，另外，还算坚持，想想搞ACM 的时候，经常攒着电影没时间看放寒暑假回家看，看一个电影都能刷个题了都。现在想想，那些日子真的很开心。吃饭的时候可以想想，啊，这个应该用这个算法，和朋友们出去的时候可以一起讨论。用学长的话，有一个你可以一直在脑袋里想的问题，多好啊！庆幸自己遇到了ACM，做自己喜欢的事情，尽自己全力，在大学阶段，真的很难 得。毕竟大学之前，就像机器一样，大家都这么做，我也就这么做，但是大学之后，是完全靠自己想法行动的，无论做什么，都是自己的意愿，这样很有成就感。 还记得，大二的时候，是好孩子，不想逃课，就印了题、算法、论文去课堂上看，看懂后果断逃课回去敲代码，哈哈，不是个好孩子呢！翘了不少课。寒暑假总被老妈说，说别学了，出去玩玩，哈哈！如果她知道我学的和课业无关她会不会还这么说，嘻嘻！ 今年的11 月，区域赛结束后，算是告别ACM，开始踏上了网络方面的不归路。确切的说，是因为需要做课程设计。我用了俩星期从J2EE 啥也不懂然后和朋友们完成我们的项目，很开心。我想，这些学习能力、代码能力是ACM 给我的。开始一个完全未知的领域真的好难啊，各种不懂，我的“to learn list.txt”一大堆东西，慢慢来吧，近期把JS 的基础视频看完了，《正则表达式必知必》会看完了，struts2 视频正在学，寒假还有各种任务呢！哈，想想寒假我都好兴奋，寒假学习效率会很高的。当然，先应付完期末考试。引用另一位学长的话，搞ACM的要当学霸！优秀应该是各个方面的。 这次寒假的主要任务是做学校的在线测评系统，怎么说呢，我觉得这是又一件我真心想做并且想把它做得完美的东西。这样的感觉很少有了，但是这次，我真心想把它弄好，所以学架构，写需求分析，数据库设计，学各种需要的知识，但是总感觉，学得越多，自己越需要学的东西就越多，不过，只要开始学了，就有进步的。 不知道符合要求不，似乎又写了一篇流水账，所以说我觉得我还不算是程序员，不过未来很希望成为一名程序员，写代码多开心呐！ 璀璨 &#8211; 时刻准备着 我：大四在一家叫食草堂的公司做网络管理及网店运营，但基本用不到专业知识。毕业后男朋友坚持不让我再随便找工作，他一个人挣钱并供我去学习java语言，学习了8个月找到了一份做ip网管软件的公司，男友在一家培训机构做教师，后来渐渐觉得不快乐不充实，被封闭在这样的空间内，不能去接触新技术新人，视野渐渐狭窄。于是我们一起辞职从天津来到了杭州，只面试了一家就来上班了，当时觉得自己能力有限，不应该是我挑工作。。。在这里做手机阅读网站，接触不到数据库，我们负责的是中间层，将数据从接口取出展示在页面上，由于我工作积极主动活泼开朗，喜爱解决疑难杂症，又爱组织这个那个的，PM将我提升为开发组负责人，但是转眼一年多过去了，我并没有觉得有成就感，相反觉得自己在技术上一事无成、在管理上又不专业，不想走管理的道路。这一年来我和男友去上海参加了几次技术大会，每回回来都会热血沸腾，我工作很忙又懒惰，导致技术水平一直无法提高，很多书都没看。每天都有强烈的自责感，但又觉得没有学不会的东西，所以就无法放弃。也因为自己对技术能力表示质疑，不敢去大的公司应聘，导致现在总是时刻准备着。。。 回想这些年，我心中所树立的理想、信念，我对it行业的向往、甚至我现在的自责感，都和男友对我的影响有关，他的眼界和思考能力要远高于我认识的人，所以有时候我想我的某些思想是依赖于他的更新而更新的。是那种容易被别人感化的人。 说说其他的女程序员吧，她们之前的人生经历我不说了，就聊一聊我认识的几种女生在工作上的类型吧。 我的同事A：刚毕业没多久的小女生，我每天从男友那里或者我自己这里获得的最新新闻和哲理我都会讲给她听，她认真听，回去也看书，每次都会骄傲的对我说又看完一本了，但技术始终上不来，这大概是那种应试教育下的女生代表类型，就像我们计算机系当年得前三名的女生一样，在实际工作后比不上倒数几名的男生。 我的同事B：已经做妈妈了，工作出色，考虑事情全面，只是她的生活完全和世界脱轨，新事物几乎不接触，新技术也是，但是如果工作用到她会积极去学，并且能把工作做好，对未来没有规划，过好日子就行。 我的同事C：毕业时是C的佼佼者，毕业后一年多就落后了，被爱情和无聊的日子所累，也总是自责，但找不到学习的方向。 看过这么多女程序员的状态，对于自身没有坚定信念和方向的我们来说，我觉得工作环境真的很重要，每天身边是什么人在交流，是什么人在一起工作，团队氛围如何，都会潜移默化影响着每个人，自身的努力和态度也固然不可忽视。 冰 &#8211; coding是我们的共同语言 昨天见到了你的关于女程序员的征文，也趁着年末，给个小小的回顾自己吧。也算不上什么经验，只是谈下个人经历感受。 [...]<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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F343.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6346.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F343.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6346.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F340.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6346.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F340.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6346.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2287.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6346.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2287.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6346.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1103.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6346.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1103.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6346.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1695.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6346.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1695.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6346.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>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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;"><strong>女程序员是程序员里美丽的风景线，我希望这些女程序员的经历能让我们</strong><strong>在这个“重男轻女”的社会中可以给女程员有更多平等的机会和条件，以及相应的尊重</strong><strong>。</strong><strong>因为，她们其中不乏优秀的程序员，而且在心态、态度和努力上还强过很多男性程序员，很多东西都值得我们大家<strong>向她们学习</strong></strong></span>。</p>
<p>这篇文章的来由是因为Eva在“<a title="三个事和三个问题" href="http://coolshell.cn/articles/6142.html" target="_blank">三个事和三个问题</a>”的评论里<a href="http://coolshell.cn/articles/6142.html/comment-page-1#comment-113406" target="_blank">问我女孩子是否能做技术</a>，她说她的很多师兄都告诉他不要做技术，所以，她有些不坚定了。我的回复是告诉了她我工作经历中的两个技术很牛的女孩，并且我从她们身上学到了多技术。但是，后面有一些人回复说我误导了别人。所以，我在<a href="http://weibo.com/1401880315/xE597iX6J" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/1401880315/xE597iX6J?referer=');">新浪微博</a>和<a href="https://twitter.com/#!/haoel/status/151856699387547649" target="_blank" onclick="pageTracker._trackPageview('/outgoing/twitter.com/_/haoel/status/151856699387547649?referer=');">twitter</a>上征集女程序员的故事和想法。我一共收到了19封邮件，其中有17封邮件来自女程序员。其中有一个已经发布了（<a title="一个女程序员的故事" href="http://coolshell.cn/articles/6312.html" target="_blank">一个女程序员的故事</a>），其中的一些观点已经在网上传播，并得到了大家的刮目和称赞。但这并不是特例，因为下面的这些故事中，还有很多令人刮目相看的东西。</p>
<p><strong>说明</strong>：先说明一下，这篇文章并不想讨论女孩子是不是适合做技术，这不值得讨论，因为，在“<a title="一个女程序员的故事" href="http://coolshell.cn/articles/6312.html" target="_blank">一个女程序员的故事</a>”中我们已经知道，态度和努力才是原因，而不是性别。这里，也只是想告诉那些有“性别歧视”、“看不起女程序员”、“骄傲自大”的男程序员们，那些女程序员不为所知的一面。<strong>我把几乎所有的故事都列在这篇文章里了，我觉得我不用再多说什么了，这些故事组成的风景线，可以让你充分地了解女程序员</strong>。</p>
<div id="attachment_6378" class="wp-caption aligncenter" style="width: 347px"><img class=" wp-image-6378 " title="Ada Lovelace 世界第一个程序员" src="http://coolshell.cn/wp-content/uploads/2012/01/481px-Ada_Lovelace_1838.jpg" alt="Ada Lovelace 世界第一个程序员" width="337" height="419" /><p class="wp-caption-text">Ada Lovelace 世界第一个程序员</p></div>
<p>在看到那些故事之前，我们需要了解这样的现实——</p>
<p><span id="more-6346"></span></p>
<ul>
<li><strong>大多数女孩子并不喜欢技术</strong>。这点从我们的计算机专业的学校就可以看到了。我上大学时，两个专业60个同学，有15个女生，男女比例已经失衡。不过，这些女生今天基本全部都还在做技术。现在，十多年了，她们其中女生还在各个公司的技术部门，主要做 开发和运维。这些是70后的女生。对于80后和90后的女生来说，可能喜欢技术的就更少了。<span style="color: #003366;">Gavin在来信中说：“我们学院每届大约有800名学生，也就是说每年整个计算机学院只有大约50名女生。在这50名女生中，据我所知有至少一半的女生从开始到最后对编程一点兴趣都没有，这一半的女生有的准备跨专业考研，有的在考公务员，有的去了跟计算机专业几乎不沾边的行业去工作了，有的在大二的时候就已经开始修双专业了”。</span>不过，在这里我们来看看做技术的女孩子是什么样的。</li>
</ul>
<div></div>
<ul>
<li><strong>女孩子在找工作的时候总是会被歧视</strong>。很多用人单位都会问女孩子生孩子的问题，这简直就是干涉隐私和性别歧视，要在西方国家里，完全可以对这样的公司进行起诉。对于这种不尊重女性的公司，无论男女，一定不会尊重员工的。所以，这样的公司一定不要去。而很多女孩也会觉得结婚生子后就不能再从事技术了，所以，她们也对技术行业的未来没有信心。<span style="color: #003366;"><strong>Myma</strong>在来信中说：“女人做技术最怕就是世俗的偏见，尤其是过了30，生了孩子，明显感觉出来了，职业瓶颈”。 <strong>召娣</strong>说：“面试的时候会问有没有男朋友，下一步会不会结婚，接下来就是会不会要孩子之类的”</span>，几乎所有的女程序员都在说这个事。</li>
</ul>
<div></div>
<ul>
<li><strong>自大的男程序员看不起女程序员</strong>。女程序员在工作中受到太多的不公平的待遇了。就连平时男程序员们都以一种高人一头的语气和她们说话。这样的例子太多了，在我blog中的回复中，在平时，我们都可以看得到。而我们的大多数的女性都会因为别人看不起而失去信心。当然，这点男程序员也一样，因为技术好的人总是会看不起技术不好的人。这是技术人员的通病。<span style="color: #003366;"><strong>冰</strong>在来信中说：“另一个困扰的问题是，可能女生少的原因，在本部门风言风语不断，给我个人生活不少的精神压力，平时同事也会半开玩笑的说，嫁了吧，写什么代码，而且跟一些比较资深的程序员聊天时，总会呵呵的轻笑，然后说你是程序员啊。。。部门一些杂务，通常都扔了给我处理，这个我觉得吃点亏也没什么大事，但是就是忍受不了那种受轻视的感觉”。<strong>Cathy</strong>说：“项目组的组长是一个博士，人很好但是不太会和女孩子打交道，或者说有一些性别歧视吧。”</span></li>
</ul>
<div>但是这些现实中的东西，对于我们的女程序员来说算不了什么！不信，你看看他们的故事。<strong>至少你会发现，做技术的女孩一点也不浮华</strong>！</div>
<h4>女程序员的故事</h4>
<p>下面的故事，都是原文，没有经过任何编辑。下面的故事，很多也很长，她们串成了一个非常美丽的风景线，<strong>我真的希望你有空能读一读这些故事。你会发现这些故事都有我们自己的身影</strong>。</p>
<p>真的非常感谢大家对我的信任，给我发来这么多的故事，谢谢你们的支持。我完全相信——</p>
<h5 style="color: #cc0000; text-align: center; font-size: 20px;">程序员因为女孩而美丽！</h5>
<div style="font-family: 'Microsoft YaHei'; font-size: 13px; background-color: #fafafa; border: solid 1px #EEE; margin: 4px 5px 4px 30px; padding: 0px 10px 0px 10px; border-radius: 10px; box-shadow: inset 0 0 4px rgba(0,0,0,0.5);">
<h5 style="font-size: 15px; margin: 5px 0px; border-bottom: solid 1px #CCC;">Shaofei &#8211; 妈妈是个程序员</h5>
<p>1.我老妈是程序员，老朽今年二十有七了，可以想象年龄。</p>
<p>2.她20来岁的时候，背着全部门写的程序——一卷打孔纸带去北京上机调试，要排机时，还要给重要的项目让路，改程序么，就是把纸带剪断，用胶粘一段上去之类的。</p>
<p>3.她们那个时代的程序员都是直接读机器码的，大约就是5665表示begin之类的东西，而且是用打孔纸带二进制表示的，嗯，小时候有印象，她读程序就是站在床上一手拿着纸带卷，另一手抽着读，读过的就拖到地上。</p>
<p>4.好吧，那个时代的程序员应该坚持到现在的不多，很遗憾她中间也转了管理又转了市场，后来创创业也没成，于是现在待在家里悠闲。</p>
</div>
<div style="font-family: 'Microsoft YaHei'; font-size: 13px; background-color: #fafafa; border: solid 1px #EEE; margin: 4px 5px 4px 30px; padding: 0px 10px 0px 10px; border-radius: 10px; box-shadow: inset 0 0 4px rgba(0,0,0,0.5);">
<h5 style="font-size: 15px; margin: 5px 0px; border-bottom: solid 1px #CCC;">zxy_snow &#8211; 半女程序员流水账</h5>
<p>自我介绍下，女，大三，某高校软件工程专业。</p>
<p>我想，严格意义上来说，我还算不上女程序员吧，还是一个弱弱的学生。</p>
<p>接触程序还是在大学开始，或者说，大一下接触ACM 之后吧。当初和朋友一起做ACM，这一年半，不停地学算法、刷题，也成就了一个水题博客（我的CSDN密码??），交到了很多其他大学的朋友，人外有人，深知这句话的意思。虽然算不上太聪明，不过不笨，另外，还算坚持，想想搞ACM 的时候，经常攒着电影没时间看放寒暑假回家看，看一个电影都能刷个题了都。现在想想，那些日子真的很开心。吃饭的时候可以想想，啊，这个应该用这个算法，和朋友们出去的时候可以一起讨论。用学长的话，有一个你可以一直在脑袋里想的问题，多好啊！庆幸自己遇到了ACM，做自己喜欢的事情，尽自己全力，在大学阶段，真的很难<br />
得。毕竟大学之前，就像机器一样，大家都这么做，我也就这么做，但是大学之后，是完全靠自己想法行动的，无论做什么，都是自己的意愿，这样很有成就感。</p>
<p>还记得，大二的时候，是好孩子，不想逃课，就印了题、算法、论文去课堂上看，看懂后果断逃课回去敲代码，哈哈，不是个好孩子呢！翘了不少课。寒暑假总被老妈说，说别学了，出去玩玩，哈哈！如果她知道我学的和课业无关她会不会还这么说，嘻嘻！</p>
<p>今年的11 月，区域赛结束后，算是告别ACM，开始踏上了网络方面的不归路。确切的说，是因为需要做课程设计。我用了俩星期从J2EE 啥也不懂然后和朋友们完成我们的项目，很开心。我想，这些学习能力、代码能力是ACM 给我的。开始一个完全未知的领域真的好难啊，各种不懂，我的“to learn list.txt”一大堆东西，慢慢来吧，近期把JS 的基础视频看完了，《正则表达式必知必》会看完了，struts2 视频正在学，寒假还有各种任务呢！哈，想想寒假我都好兴奋，寒假学习效率会很高的。当然，先应付完期末考试。引用另一位学长的话，搞ACM的要当学霸！优秀应该是各个方面的。</p>
<p>这次寒假的主要任务是做学校的在线测评系统，怎么说呢，我觉得这是又一件我真心想做并且想把它做得完美的东西。这样的感觉很少有了，但是这次，我真心想把它弄好，所以学架构，写需求分析，数据库设计，学各种需要的知识，但是总感觉，学得越多，自己越需要学的东西就越多，不过，只要开始学了，就有进步的。</p>
<p>不知道符合要求不，似乎又写了一篇流水账，所以说我觉得我还不算是程序员，不过未来很希望成为一名程序员，写代码多开心呐！</p>
</div>
<div style="font-family: 'Microsoft YaHei'; font-size: 13px; background-color: #fafafa; border: solid 1px #EEE; margin: 4px 5px 4px 30px; padding: 0px 10px 0px 10px; border-radius: 10px; box-shadow: inset 0 0 4px rgba(0,0,0,0.5);">
<h5 style="font-size: 15px; margin: 5px 0px; border-bottom: solid 1px #CCC;">璀璨 &#8211; 时刻准备着</h5>
<p>我：大四在一家叫食草堂的公司做网络管理及网店运营，但基本用不到专业知识。毕业后男朋友坚持不让我再随便找工作，他一个人挣钱并供我去学习java语言，学习了8个月找到了一份做ip网管软件的公司，男友在一家培训机构做教师，后来渐渐觉得不快乐不充实，被封闭在这样的空间内，不能去接触新技术新人，视野渐渐狭窄。于是我们一起辞职从天津来到了杭州，只面试了一家就来上班了，当时觉得自己能力有限，不应该是我挑工作。。。在这里做手机阅读网站，接触不到数据库，我们负责的是中间层，将数据从接口取出展示在页面上，由于我工作积极主动活泼开朗，喜爱解决疑难杂症，又爱组织这个那个的，PM将我提升为开发组负责人，但是转眼一年多过去了，我并没有觉得有成就感，相反觉得自己在技术上一事无成、在管理上又不专业，不想走管理的道路。这一年来我和男友去上海参加了几次技术大会，每回回来都会热血沸腾，我工作很忙又懒惰，导致技术水平一直无法提高，很多书都没看。每天都有强烈的自责感，但又觉得没有学不会的东西，所以就无法放弃。也因为自己对技术能力表示质疑，不敢去大的公司应聘，导致现在总是时刻准备着。。。</p>
<p>回想这些年，我心中所树立的理想、信念，我对it行业的向往、甚至我现在的自责感，都和男友对我的影响有关，他的眼界和思考能力要远高于我认识的人，所以有时候我想我的某些思想是依赖于他的更新而更新的。是那种容易被别人感化的人。</p>
<p>说说其他的女程序员吧，她们之前的人生经历我不说了，就聊一聊我认识的几种女生在工作上的类型吧。</p>
<p>我的同事A：刚毕业没多久的小女生，我每天从男友那里或者我自己这里获得的最新新闻和哲理我都会讲给她听，她认真听，回去也看书，每次都会骄傲的对我说又看完一本了，但技术始终上不来，这大概是那种应试教育下的女生代表类型，就像我们计算机系当年得前三名的女生一样，在实际工作后比不上倒数几名的男生。</p>
<p>我的同事B：已经做妈妈了，工作出色，考虑事情全面，只是她的生活完全和世界脱轨，新事物几乎不接触，新技术也是，但是如果工作用到她会积极去学，并且能把工作做好，对未来没有规划，过好日子就行。</p>
<p>我的同事C：毕业时是C的佼佼者，毕业后一年多就落后了，被爱情和无聊的日子所累，也总是自责，但找不到学习的方向。</p>
<p>看过这么多女程序员的状态，对于自身没有坚定信念和方向的我们来说，我觉得工作环境真的很重要，每天身边是什么人在交流，是什么人在一起工作，团队氛围如何，都会潜移默化影响着每个人，自身的努力和态度也固然不可忽视。</p>
</div>
<div style="font-family: 'Microsoft YaHei'; font-size: 13px; background-color: #fafafa; border: solid 1px #EEE; margin: 4px 5px 4px 30px; padding: 0px 10px 0px 10px; border-radius: 10px; box-shadow: inset 0 0 4px rgba(0,0,0,0.5);">
<h5 style="font-size: 15px; margin: 5px 0px; border-bottom: solid 1px #CCC;">冰 &#8211; coding是我们的共同语言</h5>
<p>昨天见到了你的关于女程序员的征文，也趁着年末，给个小小的回顾自己吧。也算不上什么经验，只是谈下个人经历感受。</p>
<p>上大学第一天就知道，班里面只有4个女生，但也并没有任何特殊优厚待遇，一般开什么班会，都是女生迁就男生，大老远跑他们那边去开会，常感受到的是，特别容易被老师或同学质疑，这个是你做的吗？你完成上机实验了吗？要独立完成等等。。。</p>
<p>印象比较深刻的是，有一次，电脑坏了，找男生修，结果他说身为计算机专业的女生，连个都不会，在以后的日子里，我就没有再去麻烦过他，也许他们是那些所谓的Geek，但我理解不了这份傲慢，牛人多的去，尤其在我现在工作的公司，一位资深架构师，不论问题大小，都会给你很好的解答，并进一步发散问题，每次聊天都受益匪浅。当然这些也只是少数，大学里面是最好的学习环境，而且很奇怪地，我发现，学习好的女生，都是在一个宿舍，而不学无术的，又会在一个宿舍，工作以后，大半都没有再从事计算机方面的工作了，要么考个公务员，要么做个辅导员，或去个银行什么的。同生同是，一个宿舍里，好像就是一场编程的竞赛，谁更努力，谁更有资本炫，也许这是学习的动力。</p>
<p>说下出来毕业出来找工作，当时确实茫然，展望整个专业，本来就女生不多，还有大半都去考研考公务员等等的，觉得自己出路在哪啊，男生这么优秀，你凭什么跟他们一拼高下，一次又一次的经历招聘会的沮丧，信心都快打击光了。后来，收到了第一个offer，就马上把自己卖了，这也是我的第一份工作，我是09年毕业的，当年市场确实也不怎么景气，有好些同学，都是在年末才找到工作，甚至先去上了个什么一万多的达内啊青鸟啊之类的软件培训课程。</p>
<p>上班之后，也没多好受，原来老大当初把我招进来，有一个原因是想解决下公司内部单身男士的需求，给我的一般是轻活，自然奖金工资总比同进来的男生少（私底下交流过），自问没做得比他们少。值得庆幸的是我跟了一个不错的组长，他会给跟老大提出要求，可以给我安排些挑战性的任务，由于过去一年确实也收获不少，虽然不是在金钱上，一直比别人努力希望能纠正老大眼中的我是花瓶的感觉。</p>
<p>同时，另一个困扰的问题是，可能女生少的原因，本人有几分姿色，在本部门受不少人追，风言风语不断，给我个人生活不少的精神压力，平时同事也会半开玩笑的说，嫁了吧，写什么代码，而且跟一些比较资深的程序员聊天时，总会呵呵的轻笑，然后说你是程序员啊。。。部门一些杂务，通常都扔了给我处理，这个我觉得吃点亏也没什么大事，但是就是忍受不了那种受轻视的感觉。</p>
<p>处心积累了一年半，跳离了这个是非之地，目前在工作的公司。终于呼吸到新鲜的空气，现在整个开发团队，只有我一女的，开会什么的我就显得特别突出，办活动或者聚会什么的，总不能太融入他们，他们一帮程序猿，辟酒通宵桌游聊天，我总不能也凑上去喝个烂醉吧，活动吧，他们篮球啊足球啊，我根本掺和不上，剩下的就是大家吃个饭，感情上总是欠缺一些，但是他们都很照顾我和接纳我，也教会我了用很多的工具，大家总以邮件形式来分享代码中遇到的抽疯问题，白痴陷阱，即使错了也没关系，反正就是可拍砖可嘉奖，气氛相当的学习火热型。</p>
<p>另外一样是，coding我们可能有共同语言，但退下工作后，基本上，跟一群男程序猿聊一起很难话题不多，偶尔遇到一两个话多一些风趣一些，其他都是木纳得很；而作为女性，当然会爱逛街爱八卦爱打扮，但同学已经各散东西，同事中没几个女的，生活已经没有几个女伴一起做女生爱做的事，而且，上班时，我总是小心翼翼不能穿得太性感，不打扮，怕会遭人闲语。</p>
<p>呵呵。本文就一啰嗦。莫见怪。</p>
</div>
<div style="font-family: 'Microsoft YaHei'; font-size: 13px; background-color: #fafafa; border: solid 1px #EEE; margin: 4px 5px 4px 30px; padding: 0px 10px 0px 10px; border-radius: 10px; box-shadow: inset 0 0 4px rgba(0,0,0,0.5);">
<h5 style="font-size: 15px; margin: 5px 0px; border-bottom: solid 1px #CCC;">Maya Maya &#8211; “左手代码，右手诗”</h5>
<p>从小我喜欢画画，喜欢文学，上大学的时候，听了家人的意见，报了计算机，从此理想和现实分开。我大学毕业已经10多年了，当年毕业进了高校当老师，两年后为了爱情放弃舒适的生活来到北京北漂，对计算机不是那么爱好，开始做测试，后来转作网站开发，和互联网结下了不解之缘。互联网是节奏很快的公司，虽然自己年纪大了，可是和年轻人在一起，觉得自己心态还很年轻，哈哈~</p>
<p>说起做技术，也是满腹心酸，刚到北京，一个小公司，老板不懂，今天说给我开发一个无纸办公室软件，明天那个，那个时候晚上下班累的洗脚时躺着就睡着了。可是自己没有放弃，逐渐喜欢上了技术，后来去了一家公司，有个大师级人物，虽然大家都说他性格古怪，可我和他相处很好，他算是我一个师傅，和他2年多，自己技术提高了不少，做技术的兴趣也多了很多。最苦的时候加班两个通宵，除了公司坐上出租车就睡着了，但是心里很充实很开心。</p>
<p>女人做技术最怕就是世俗的偏见，尤其是过了30，生了孩子，明显感觉出来了，职业瓶颈。不少人劝我找个轻松的工作，可是我还是没有放弃，还在坚持，不是为了为了养家糊口，为了自己的心愿吧。我做事喜欢亲力亲为，每次招聘约小孩面试，他们都问我，你是助理吗？面试结束，小孩们又说，女的做技术很少的，做技术的女领导应该很严格吧。其实对于别人的任何看法，我从来都是笑笑不语，我带团队，总是希望新人能在我这里学到东西，走的时候能上一个更高的台阶，因人而异给他们提供机会。互联网发展快，我自己也要学习，不然就跟不上，我每天很早来公司，晚上也走得相对晚些，下班了才有自己时间看点东西，上班琐事太多。顾了公司顾不了家庭，回家是孩子睡了，老公一脸的不高兴，生活或许如此，不能尽善尽美。任何事情都有游戏规则，既然选择就要遵守。</p>
<p>互联网的泡沫其实很多，我经常给刚毕业学生说，30岁之前不要看钱，而是给自己长本事，积攒资历。发现在线小孩浮躁的很多，很难静下心来认真做一件事情，总是看着别人的薪水多高，看别人的收获，却没看到别人背后的付出。</p>
<p>程序员给人感觉都很闷，可是我喜欢读小说，红楼梦最爱，很喜欢惠新宸的那句话：“左手代码，右手诗。”</p>
</div>
<div style="font-family: 'Microsoft YaHei'; font-size: 13px; background-color: #fafafa; border: solid 1px #EEE; margin: 4px 5px 4px 30px; padding: 0px 10px 0px 10px; border-radius: 10px; box-shadow: inset 0 0 4px rgba(0,0,0,0.5);">
<h5 style="font-size: 15px; margin: 5px 0px; border-bottom: solid 1px #CCC;">Joyic &#8211; 只要努力，一切皆有可能</h5>
<p>看过“一个女程序员的故事”这篇文章，很有感触。我是2010年的硕士毕业生，也是个女生，和故事中的女主角比起来，我的故事其实才刚刚开始。或许平淡，但希望能给即将找工作，还在徘徊和犹豫的学弟学妹们一些鼓舞。</p>
<p>经历的小学和初中的辉煌，经历了高中的低潮，我进入了一所211本科，不是985，一所不上不下的大学，专业是信息管理与信息系统。这个计算机相关专业让我接触到了C语言，数据结构，Java，Web编程以及数据库，我发现自己从来没对哪些课程有如此大的热情，这些热情带给我的动力以及对知识的渴望，换来的不仅仅是优异的成绩，最重要的，让我拾回了高中三年几乎丧失殆尽的信心，我又开始相信自己。</p>
<p>转眼大四，与保研失之交臂，考研又没能进入理想的学校。又一次进入了一所不上不下的211学校，一切似乎又回到了原点，这次的专业是软件工程。不幸中的万幸，我还没离开自己喜欢的专业。研二的上半年，我得到了导师的一个横向项目，给四川的某出版社分社做一个信息管理系统。这是我得到的第一个锻炼机会，用的是最简单的jsp+servlet技术，系统结构不复杂但内容很庞大（就一个dev来说），我一个人硬着头皮码了十几万行的代码，需求、开发、安装、调试、培训一个人从头干到尾，中间多少次我都觉得自己做不了了，要放弃了，这个功能我完不成了，没时间了，咬咬牙，全过来了。现在想想，这个系统错露百出，但它使我完成了从无到有的涅槃，不再是看看书，写个百十来行的练习，是真正做出来个东西。</p>
<p>完成了这个项目，对自己的信心又增强了。我有了下一个目标，找个实习，去IBM试试！</p>
<p>以我所在的学校，能拿到IBM实习offer的人凤毛翎角。“应届生”网站上随时会有IBM招intern的消息，我的简历因为有了刚刚做过的这个项目，基本都能得到电话面试的机会。当时我的知识面还很窄，加上没有为面试好好复习过基础知识，屡试屡败，有时拿到面试也是铩羽而归。“WSDL是什么？”，“你对SOAP有什么了解？”，“设计模式你熟悉么？”，“解释一下Spring的依赖注入”一次次的失败也指引了我学习的方向。不会我就学么。至少面了5个team，我终于拿到了IBM的offer，当上了intern！现在想想，这个时刻带给我的喜悦甚至超过了我毕业真正找到工作的时候。我再一次给自己画了一条遥不可及的线，再一次把自己扔了过去。</p>
<p>实习了不到一年，让我学到了很多，也适应的外企的工作环境。开始真正的找工作了。有学校的项目和IBM实习经历，我的简历更加丰满，加上自己经历多次intern的面试，积累了一些面试经验，很顺利的，我拿到了Oracle，IBM和我现在公司的Offer。</p>
<p>工作到现在工作一年多了，有过一次promote，也得到了一次出国培训的机会。真正的工作中，我的技术和工作过3、5年的同事尚有差距，我把很大一部分精力放在了解业务上，通读了产品所有的design文档，对架构及所有workflow了然于心，专挑一些别人不愿碰的硬骨头，亦因此建立起自己在team中的reputation。</p>
<p>最后，我想说，我身边也有在学校的时候就能写出操作系统的牛人，我也是无比尊敬和仰慕着他们。作为一个热爱着编程又天赋一般的普通人，没有清华北大北航北邮…的好出身，也没有根红苗正的计算机科学与技术专业背景，一步步的走过，被兴趣爱好还有自己的执着指引至今。</p>
<p>给向往着大公司的学弟学妹们，可能你的学校使你没有运气在面试的时候发现面试官刚好是自己的师兄师姐，但只要努力，一切皆有可能。</p>
<p>给我的老师和帮助过我的同事，你们引领我一步步走进了这个行业。</p>
<p>还有我相伴7年的男友，我还记得大学的时候我们打电话时讨论技术，宿舍姐妹们看我的眼神儿。哈哈哈。</p>
</div>
<div style="font-family: 'Microsoft YaHei'; font-size: 13px; background-color: #fafafa; border: solid 1px #EEE; margin: 4px 5px 4px 30px; padding: 0px 10px 0px 10px; border-radius: 10px; box-shadow: inset 0 0 4px rgba(0,0,0,0.5);">
<h5 style="font-size: 15px; margin: 5px 0px; border-bottom: solid 1px #CCC;">叨叨 &#8211; 为了忘却的纪念-我在恒生的七年</h5>
<p><strong>叨叨的博客</strong><br />
<a href="http://blog.sina.com.cn/u/1892569084" target="_blank" onclick="pageTracker._trackPageview('/outgoing/blog.sina.com.cn/u/1892569084?referer=');"> http://blog.sina.com.cn/u/1892569084</a></p>
<p><span style="color: #ff0000;">强烈建议大家看看这个连载，你一定能从中看到很多东西的</span></p>
<ul>
<li><strong>前传 </span></strong><a  href="http://blog.sina.com.cn/s/blog_70ce4ffc01011h8z.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/blog.sina.com.cn/s/blog_70ce4ffc01011h8z.html?referer=');">http://blog.sina.com.cn/s/blog_70ce4ffc01011h8z.html</a></li>
<li><strong>初出茅庐（上） </span></strong><a  href="http://blog.sina.com.cn/s/blog_70ce4ffc01011h93.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/blog.sina.com.cn/s/blog_70ce4ffc01011h93.html?referer=');">http://blog.sina.com.cn/s/blog_70ce4ffc01011h93.html</a></li>
<li><strong>初出茅庐（下） </span></strong><a  href="http://blog.sina.com.cn/s/blog_70ce4ffc01011hs6.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/blog.sina.com.cn/s/blog_70ce4ffc01011hs6.html?referer=');">http://blog.sina.com.cn/s/blog_70ce4ffc01011hs6.html</a></li>
<li><strong>初露锋芒（上） </span></strong><a  href="http://blog.sina.com.cn/s/blog_70ce4ffc01011igb.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/blog.sina.com.cn/s/blog_70ce4ffc01011igb.html?referer=');">http://blog.sina.com.cn/s/blog_70ce4ffc01011igb.html</a></li>
<li><strong>初露锋芒（下） </span></strong><a  href="http://blog.sina.com.cn/s/blog_70ce4ffc01011j7z.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/blog.sina.com.cn/s/blog_70ce4ffc01011j7z.html?referer=');">http://blog.sina.com.cn/s/blog_70ce4ffc01011j7z.html</a></li>
<li><strong>一波三折（上</strong>）</span><a  href="http://blog.sina.com.cn/s/blog_70ce4ffc01011jur.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/blog.sina.com.cn/s/blog_70ce4ffc01011jur.html?referer=');">http://blog.sina.com.cn/s/blog_70ce4ffc01011jur.html</a></li>
</ul>
<p>（本文发布时，这个故事还在继续中……）</p>
</div>
<div style="font-family: 'Microsoft YaHei'; font-size: 13px; background-color: #fafafa; border: solid 1px #EEE; margin: 4px 5px 4px 30px; padding: 0px 10px 0px 10px; border-radius: 10px; box-shadow: inset 0 0 4px rgba(0,0,0,0.5);">
<h5 style="font-size: 15px; margin: 5px 0px; border-bottom: solid 1px #CCC;">Kelan &#8211; 在coding和修复bug中享受无限的快乐和价值感</h5>
<p>我是一名入职不到一年的女程序员，很幸运，能进入一家知名的互联网公司做web开发，用的Java。我记得当时面试的时候，我在技术上毫无优势，公司要用到的很多框架，我都没有使用过，只是听说过，知道一点点概念，但是过了两个技术面，面试官很nice，觉得我有潜力。第三面是HR面，当时HR问我，为什么要做技术，我当时思都没思考就回答：喜欢！我一直很惊异这个答案，也许，那是一个连我都不敢相信的真实的答案。</p>
<p>我在的team里面，就我一个女生，又是最小的，大家相当照顾我，在工作上给与了我很大的帮助，不得不提的是，我不仅遇到了一个很和谐的团队，还遇到了一个打着灯笼都难找的boss，对于这一点，我觉得也许是上辈子积了德，呵呵呵。也正因为他们对我很好，我在工作上不敢懈怠，我知道我基础很欠缺，我不想因为这个影响到整个团队。我会主动的去学习相关的东西，但是，从前的一些经历，让我对自己很不自信，当我看到同事游刃有余的处理工作，讨论技术，研究业务的时候，我很羡慕，同时也觉得自己很苍白，不知道何时才能和他们一样，同时也很害怕让他们失望。</p>
<p>很多人都觉得女生就该做像女生的工作，比如hr，比如行政，做技术也可以选测试…我也有过疑惑迷茫的时候，不知道未来的路如何走，也想过自己是不是选对了职业的方向。但我不得不承认，coding和修复bug后给我带来了无限的快乐和价值感，那种感觉很好很好。</p>
<p>我没有太多的分享工作经验，只是想说说自己的迷茫。我从前一直觉得，要做技术大牛才是技术人员的目标，而技术大牛四个字，我望尘莫及。我很堕落的想过，我可不可以不做技术大牛，我就写我的代码，去实现各种业务流程，做一个平凡的程序员，这样算不算不思进取？我看了你分享的文章后，觉得我的想法也许没有那么不堪，每个人都有选择成为哪种人的权利。既然现在的我喜欢code，那我就写好每天应该写好的code，至于以后，那是以后的事了。</p>
<p>我觉得，也许很多女程序员和我有相同的困惑，不知道，有谁可以解惑？言语有些乱，因为最近也被这些问题烦扰。但我还是想给自己一个机会，在技术领域，至少五年，如果真的不适合，我放弃，去选择另一种人生；如果相反，呵呵呵，那我真是很幸运，从一开始就选对了路：-）</p>
</div>
<div style="font-family: 'Microsoft YaHei'; font-size: 13px; background-color: #fafafa; border: solid 1px #EEE; margin: 4px 5px 4px 30px; padding: 0px 10px 0px 10px; border-radius: 10px; box-shadow: inset 0 0 4px rgba(0,0,0,0.5);">
<h5 style="font-size: 15px; margin: 5px 0px; border-bottom: solid 1px #CCC;">WaterMask &#8211; 踏踏实实的做coder，每天写好每一行代码</h5>
<p>偶也是个女程序员，看了cool shell上的blog，发现同自己想法一样的人很多，我也想说说自己的事情。（可能会有点长，如果您能读完我会很荣幸，因为一直都是我读你的blog来着么，呵呵~）</p>
<p>我是09届毕业生，加上实习时间也不过3年不到，所以还是个新手。</p>
<p>毕业那年正赶上金融危机，就业形势一片糟糕。对于非名牌大学的我来说，简历通常都是石沉大海。身边的同学如果自家有门路的基本都舒舒服服的实习了或者考公务员什么，心里不是没有憋屈的。虽然自己家里也不是一点门路也没有，但是我还是想能靠自己的能力找到工作。（工作到现在我发现，做IT的都不喜欢走后门，大家都靠自己的实力面试工作之类的，恩~所以我更爱这个行当了~）</p>
<p>我的专业是计算机科学与技术，所以除了程序员，我基本没有想过要做别的职业……不晓得为什么当时我会这么想</p>
<p>实习的第一家公司是在一家展会公司做网管。公司在市中心的高档办公楼，只有一个hr面试我，没有任何的技术问题。接到录取电话的时候，还是开心极了，因为那时候简历投的基本要发狂了。之后去那边上班才发现受骗了，那家公司其实就只有一个部门——电话销售部门。所有的人每天都是不停的打电话做推销（原来那些成堆成堆卖客户资料的人都是卖给这种公司了……居然还有电话过去找的那人死了好多年的……）。于是我干了没几天就走了。</p>
<p>沮丧的很，本来以为是难得的实习机会。因为知道自己其实除了计算机系毕业的外，连真正的代码也没有敲过几行，对于自己想干什么能干什么都很模糊。当时甚至觉得如果有一家软件公司肯要我，给我一个学习的平台，我工资也可以不要的……</p>
<p>之后我认真修改了简历，也去了几家公司面试，不过可能因为技术方面太贫乏，都没有公司有回音。除了再接再厉外，我也没别的方法。正好当时学校里已经没有课了，只剩下毕业设计，于是我有大把的时间出去找工作。</p>
<p>最后拿到offer的是一家民营公司，专做外包的。（虽然当时我对外包这次词其实不是很理解）我只能说我的运气很好，这家公司的hr是个很nice的姑娘，通过笔试面试之后，她还和我聊了很久，问我为什么非要做程序员之类的，而我也破天荒的说了很多心里的想法。（应届生面试总会事先准备一些问题和答案，有些可能会有点冠冕堂皇）。我记得我跟她说我觉得写程序应该是一件充满想象力和创造力的工作，我喜欢当完成一段代码像完成一件作品一样的成就感。面试完之后，我其实没想过会被录取，只是觉得把心里面的话说出来了，觉得很舒服。过了不久就接到去上班的通知了，心里是非常愉悦的，这次是真正的程序员了！</p>
<p>开始工作之后才发现了梦想和现实之间的差距。因为是外包公司，所以项目进度非常的紧，而且需求也是三天两头的变。我所在的项目组一共5个人，却有6个项目在同是开工，其中3个人事项目经理。不过那时候的我没想那么多，加班就加班呗，我觉得是自己学习的机会。因为我是项目组里唯一的女生，所以大家都非常的照顾我。在写代码的过程中有遇到什么问题，基本都会抽时间帮我解决。有时候我怕会打扰别人就到网上搜搜解决办法，看看文档。每次靠自己解决问题之后，都会很有满足感。我觉得我所有的代码知识几乎都来源于实践，有点现学现卖的。</p>
<p>在工作了一年之后，我甚至觉得自己进步的很快。因为有同事跳槽的关系，项目组里缺人，我居然开始一个人负责一个项目。天啊，我觉得自己太伟大了！是个网上办事的电子平台的OA项目，还有一些杂七杂八的附带功能，视频、聊天、发短信什么……面向的客户是政府机构，使用的人员基本也都是事业单位或者是公务员。（这就不难理解为啥要那些杂七杂八的功能……）</p>
<p>我接受这个项目的时候已经是中后期，从跟客户需求沟通，到代码，到测试，到现场实施，到后期维护……几乎就是我一个人在做。其中的苦辣酸甜也就不谈了，常常被客户骂的饭也吃不下。我就这么浑浑噩噩的又干了半年左右，每天都是白天接到客户的需求变更或者使用的bug（测试也是我自己做的……所以bug非常多）下午代码，晚上就跑到客户机房去调试补环境……</p>
<p>通过这样的长期反复，我开始思考自己一开始的初衷，我为什么要做程序员？我每天都要花很多的时间去理解和分析客户的需求，然后想尽办法修改我的代码，我的代码几经修改已经面目全非，已经没有任何代码质量和运行效率的考虑，纯粹只是为了实现功能而功能。由于工作时间的增加，我也看到了身边很多其他同事的工作状态，除了那些和我一样埋头苦干的所谓项目负责人外，其他的人都善于跟客户周旋，用一些看似很专业的辞藻去推脱用户提出的各种要求，实在推不了的，才勉为其难的答应下来。</p>
<p>诚然，当公司把这个项目交给我的时候，我是充满热情的。但是现在，我终于清醒了。我想这不是我要的工作，我还只是一个刚刚毕业的本科生，不能夜郎自大的认为自己已经可以独挡一面。我根本不懂项目架构，不懂项目管理（虽然也木有人给我管理……），不懂得如何消化来自客户的需求并从中取舍（并不是客户所有的意见都要接受，这是我通过身体力行才了解到的……），我的能力仅仅停留在知其然而不知其所以然，我只能实现一个功能，但不知道怎样优化这个实现。所以我想，我应该去一个能教会我这些东西的地方</p>
<p>2011年初的时候，我离开了原来的公司，到现在的公司上班。公司只有30多个人，研发部10人，测试部10人，剩下的有行政和销售。这是一家做产品的公司，产品主要涉及网络运维管理，安全策略啥的。公司非常注重产品质量，对于每次产品升级而变更的代码都会做code review，写的不好的地方就要改。也有详细的项目管理流程，项目经理会合理安排每一个时间节点的工作任务。在这样的环境下，对我的帮助是巨大的。</p>
<p>一切都要重头开始学，我第一次写python因为之前一直习惯的分号结果而郁闷不已，第一次用vi编辑代码，折腾了大半天才码出了一段代码，小心奕奕的保存好……现在回头想想都觉得很有意思</p>
<p>我也想过今后要往什么方向发展，是一直做技术？还是做管理？做前期需求？</p>
<p>以前总以为做IT，就是写代码。但当自己干了这些日子，才明白软件工程的每一个环节都是非常重要的，程序员只是其中的一个环节。但是无论今后自己要转什么方向，程序员的经验一定会为我在IT行业打下坚实的烙印。</p>
<p>我坚信一个不会写代码的管理者，一定不是一个优秀的管理者。</p>
<p>IT行业和别的行业很大的不同是人。IT都很喜欢分享，只要肯问或者寻求帮助，就算对方不是很懂，也会非常乐意帮助我解决。我觉得这样的氛围很好，互帮互助，共同进步。这个是我在别的行当很少看到的。我有很多同学都会跟我抱怨她们办公室里错综复杂的人际关系，每天听到那些事情，我都会庆幸自己从未遇到过。</p>
<p>所以我想，我现在非常喜欢自己的职业，喜欢自己的行当，我就踏踏实实的做好我的工作。我就是一个简单的coder，每天写好每一行代码就好。至于今后的发展，今后的职业规划也不用想的太细。既然我要一直混迹于IT这个行业，那么多做几年程序员不也挺好。顶着程序员这个头衔，我就需要不断的学习，不断的接触新鲜的知识，让自己不会落后。</p>
</div>
<div style="font-family: 'Microsoft YaHei'; font-size: 13px; background-color: #fafafa; border: solid 1px #EEE; margin: 4px 5px 4px 30px; padding: 0px 10px 0px 10px; border-radius: 10px; box-shadow: inset 0 0 4px rgba(0,0,0,0.5);">
<h5 style="font-size: 15px; margin: 5px 0px; border-bottom: solid 1px #CCC;">禾禾木木 &#8211; 女程序员的路可以很长</h5>
<p>简要的说下自己，本科调档不幸进入计算机行业，于是开始了跟计算机，跟开发的纠结。本科在一个很差很封闭的学校，就死学了，只会考试，实践的东西基本没有~考研上 了一个挺好的学校，可是因为一些原因只读了个跟计算机相关的专业，自己接了几个活做学院网站什么的，网站虽然基本是自己前端后端一个人忙乎乎地整起来的， 但是质量很差，重复的代码很多，现在想想，太恐怖了，那时候就知道，功能实现就ok了。现在很后悔在学校的时候，在思维最活跃的时候没有错接触点新的东西。</p>
<p>毕业。来上海，在一家外资民企工作至今。</p>
<p>之前在学校里女生很好，特别计算机这块的，女孩子真的是宝，受着宠。工作了就不一样了。虽然男人帮们还是很帮助女孩子的，但是，毕竟工作是靠绩效靠能力来权衡的，尤其是技术领域。按照你完成的事情多少和能力强弱来决定关注度的，虽然大家感情都不错，但是我还是能明显地感觉出来，因为自己能力比同组的男同胞差，老大不太敢把重要的事情给我做，承担不了重要的事情，在关注度，升职加薪等 等上面就打了很多折扣。</p>
<p>为什么会坚持下来呢？因为喜欢这个行业，也因为自己学的是这个，也因为自己小小的虚荣心，因为一般大家听说女程序员都觉得是很牛的，似乎女孩子加上了这个职业就有个光环在头上，只是我的一个想法，不知道大家有没有这么想过~还有，这个职业对我来说还是蛮有吸引力的，我也喜欢做这些事情，虽然进步不快，但是看着自己整出来的东西大家玩的开心，自己也很开心。</p>
<p>我虽然每天笑嘻嘻的，其实自己知道自己有多么辛苦。想写精致点的代码，重构，可是没有太多的时间，工作任务还是很重的，强度也大，基本上每个晚上到八九点走。要学习很多新的东西，我脑子还反应很慢，很多时候老大给同组的人讲的东西，可能大家马上就会了，可是我还是没听懂，老大会很无奈，我会记下来，有时间就去看。有时候会去关注下招聘的事情，不是为了跳槽，而是看看需要什么样的人，看到很多要求有开源代码经验的，在github上面整了代码的，我也会去关注，以后计划着自己整个人的网站，写技术文章，多交流。我还是很有热情和很负责的一个人，为了赶进度，周末两天都可以放工作进去，把上淘宝的时间都用来看新的东西了，逛街，基本一两个月去一次的。即便如此，老大从我们一个组走过，还是只会关心那些写代码写得好，事情做得好的人。虽然会很难过，但是我还是挺下来了。告诉自己说，既然坚持了这个行业，就开开心心地走下去，看看自己跟别人有什么不足，为什么会有差距，弥补弥补。这么坚持下来，虽然我还是没有同组的人进步快，但相比刚开始工作的时候，什么东西都不知道，还不知道该怎么去学，怎么去把程序写好，已经好了不知道多少倍。我也会去参加一些会议，去关注一些小组，在女孩子看韩剧的那些时间了，可能我关注的是一些技术的博客论坛等等，这么样，也增加了自己的见识等。我不敢说我现在是有多么强，至少，在我周围的认识的女孩子转行，退避的时候我坚持了下来，算是女孩子中不错的吧。</p>
<p>觉得女孩子跟男孩子差别并不大。可能他们真的思维会不一样，劳动强度能更承担些，但是，其他的应该都还好。我有个朋友，也是女孩子在做开发，长得很漂亮，她 说她经常碰到了问题，一大帮男的会过来帮忙，依赖心很强。我觉得依赖心强的女孩子做不好开发的，男孩子做得好开发，是因为他们喜欢自己专研，依赖别人了会 被人瞧不起，但是如果是女生，基本上还是有求必应的，所以，很多时候做不好，是因为自己还不在悬崖边，还有很多绳子牵着，虽然不至于让自己摔死，但是也被 绊住了，前进不了。还有，我自己的观察，长时间的专注和精益求精也是写好程序的关键。我自己最缺乏的就是长时间的专注，于是在找bug，看源码方面就欠缺 了很多，不能深入进去，要有在茫茫多的代码中调试的那种心境，一点点地挖掘到底是哪里出问题了，哪里影响效率了，哪里内存泄露了，一点点地试验等，能力就 提高了。精益求精才能写出好的代码出来，我也是受着周围男人帮的影响，从马大哈，从写完了程序就想玩想放手变成了事关审视代码，看哪里能够重构，哪里能够 抽象，去掉重复等，代码才能写得好。</p>
<p>曾经一度，自己也很喜欢抱怨，抱怨自己怎么就没有别人进步那么快，就得不到重视，还这么辛苦，想走人，那段时间也就是我自己觉得最虚度，最没有成效的时间。现在想想，与其这样，还不如拿出时间来好好做好自己的事情，如果真的承受不下去了，觉得自己真的不适合做这个行业了，那么就转吧。我看到过一些女孩子，做程序做得很轻松，她们很聪慧，或者很有方法，我不是这种人，在这里我想鼓励那些不是 天才的女孩子们，如果你在做开发这个行业，如果你喜欢这个，那么坚持自己吧~</p>
<p>有人会说，做IT的女孩子，老得快。其实我觉得这说法也不全对。我周围也有些长得很漂亮，打扮得也很好，生活各方面都维持得很不错的女开发人员。很久以前看过有女孩子一边写着程序一边吃着芦荟啊，抹着各种护肤品，我们也可以做做瑜伽啊，平时煮点汤给自己补补脑子什么的，周末不宅着，去锻炼锻炼身体，虽然可能没那么多时间去逛街，但是也可以抽个空给自 己买些好看的衣服来让自己开心点。写程序的女孩子也是女孩子嘛。</p>
<p>我没有讨论更多的技术方面的东西，我觉得工作态度，人生态度是很首要的。有个开心乐观的心境，加上好的方法和总结，我觉得，女孩子走程序员道路还是能走很长久的，也能做得很好。共勉。</p>
</div>
<div style="font-family: 'Microsoft YaHei'; font-size: 13px; background-color: #fafafa; border: solid 1px #EEE; margin: 4px 5px 4px 30px; padding: 0px 10px 0px 10px; border-radius: 10px; box-shadow: inset 0 0 4px rgba(0,0,0,0.5);">
<h5 style="font-size: 15px; margin: 5px 0px; border-bottom: solid 1px #CCC;">Bana &#8211; 我是一名女程序员 我无怨无悔</h5>
<p>我在大学学的是计算机与信息科学专业，那是大家有两个方向：计算机和数学。我想我以后肯定是不会从事计算机的，试想一个在电脑前面坐上一个小时就腰酸背痛的人&amp;不能熬夜的人，会从事计算机方面的工作吗？</p>
<p>现实与人所想差距是很大的。一晃，我已经在IT行业混了3年多了。现在除了不能熬夜，叫我在电脑前面坐上12个小时，一点问题也没有。</p>
<p>大学我考研是考的数学方面的。那时很是迷茫，不知道自己能干什么，在大学我全身心的投入到那些毫无意义的课本知识上，最后获得的只是一叠毫无价值的证书。考研没有考上我报考的学校。调剂到了另外一所学校，我没有打算读，但是竟然跑出复试了。也许是为了给大学生活句号吧。</p>
<p>离校时间到了，我已经放弃了读研，而工作是没有着落的，我揣着优秀毕业生的证书被毕业了。毕业那一年的经历，对我打击很大。曾经的自信心，已经荡然无存。时至今日，才恢复得差不多了。2008年6月份，一个偶然的机会，让我走上了IT行业。</p>
<p>在上海的一个朋友，他公司有人休产假要招人，他在他老大面前极力推荐我，结果就是他老大自掏腰包，出我往返的车费。当时我在湖北。当时的情况是：我只是在大三的时候考过一个程序员的东东，似乎在代码方面得分蛮高的（我记忆不好）。毕业设计的时候做了一个简单得不能再简单的发邮件的东东。我已经有一年没有碰任何跟代码有关的东西。就这样我从湖北跑去上海面试了。其实心里是没有底的，只是有一个强烈的愿望，一定要通过。我急需要改变目前的状况，这一次对于我意义重大。</p>
<p>面试的时候，是朋友的老大和休产假的同事。也没有问什么，后来说叫我一个礼拜做一个用VB写的计算器。我应聘的工作是维护一个VB 6.0写的ERP系统。面试完后，我就赶紧整合多方资源来解决这个留给我的题目。从网上找相应的资料，寻找朋友的帮忙。</p>
<p>回到湖北的时候，是表哥去接我的。我请的假比较长，就先去表哥那里啦。这时对于我来说，要紧要的事情就是完成那面试题目并Email出去。在坐了15个多小时的火车后（我坐的是硬座），一直到我把题目给解决后，一刻也不敢耽误。那时精神超好，后来题目解决后，我倒在床上就睡着了。把代码打包连带一篇非常诚恳的文字给面试的人发了过去，之后就焦急的等待结果。终于等来了电话，问我什么时候可以去上班，并说了薪水。当时我高兴坏了，辞了当时的工作，就奔赴上海了！</p>
<p>最开始的一个月，很难熬啊。我什么都不懂的。专程跑出上海书城买了一本VB 6.0的书来看。等到了我适应得差不多的时候，公司发生了一件事，要裁员了。金融危机呀，当时心惶惶啊，好害怕自己被Fire掉了。因为我这个岗位当时招了2个人，而且我总觉得我是多余的。最后的结局是：我被调出负责另外一个用ASP写的OA系统。之前负责的那人被Fire掉了。</p>
<p>ASP，我不会。当初老大问的时候，我说应该还好，没有什么问题的。当初说好交接时间是一个月的，那人不同意，最后说是一个星期完成交接。结果是她最后上班的一个星期，她只来了两天。My God！那段时间是我最难熬的时候，User的电话打个不停，而我都不知道怎么解决，而且也找不到人帮忙。真是叫天天不灵，叫地地不应的。全靠自己一点一点的摸索。最终工作终于是游刃有余了。但是ASP我只是皮毛。</p>
<p>我最初进公司的目的是想学C#，直到09年7月份的时候才接触到了C#。公司的系统要进行改版，用C#来编写。之前的老大因为一些原因，离开了。当时我差点流眼泪了，如果当初不是他，我还不知道自己会怎么样，会不会一生就那样了，就是痛苦的一生了。</p>
<p>新来的经理，对于我产生了很大的影响。他给我们培训C#的相关知识，其实韩磊翻译的那本经典的C#书籍我都不知道翻了多少篇了，但是因为没有操作，了解到的很少。当经理给我们培训的时候，有一种豁然开朗的感觉，听起来特别带劲。经理给我们讲了程式命名的规范，SP命名的规范，自此我一直按照这些规范来规范着自己。接着就写了关于人事系统的几个窗体。看书和写代码完全是两回事。</p>
<p>新系统改版，我没有参与多少。能力不够的，在新系统上线（2010年10月份）的时候，了解了一些业务知识。当时心里很苦闷，我想做开发的，不想做维护的。维护做得没有意思，也学不到多少东西。而且要想学东西学得快的话，做开发是学得最快的。实际参与其中，才会去思考相应的解决方法。在寻找解决方法的过程中，就学到了东西。</p>
<p>现有的工作岗位满足不了我的需求，但是此刻我又不能去找工作，因为我不自信。还是觉得自己什么都不会，其实也就是什么也不会。阅读是排遣痛苦最好的方法，我陆续的阅读了一些书籍。关于心理学方面的，在我认为，最重要的源头就是心理。找到了源头就好解决问题了。</p>
<p>就这样，让我接触到了周金根的敏捷个人(有关敏捷个人的话题，需用另一篇日志来讲述)。2011年节后返回上海，当时上班没事看，我就看《遇见未知的自己》，因为我正面临着一个问题，不知道是怎么回事，就想从书里面寻找答案。谁知，看完不懂后，又跑出看了《秘密》。而敏捷练习也在进行着，在做个人生活方向盘的时候，我明白了什么对于我来说是最重要的。</p>
<p>当下也就有了计划，准备换工作了。当对某事有着强烈的愿望时，那事一定会实现的。</p>
<p>4月中旬，经理离职了，去武汉开公司。我就跟着经理回武汉了。这真是一个很好的机会，在武汉，我周末就可以回家。更重要的是，我做开发，做我喜欢做的事情。此时我已经找不到待在上海的意义了。家人和个人的前途对于我来说，是最重要的。</p>
<p>经理建议我们至少读三本英文原文书籍，这样之后就看英文就不会排斥了。为什么看书呢？你解决某个问题的时候，在网上找到的资料时很片面的。书里面的知识比较全面，但是需要花时间。还推荐了一些关注的英文网站。Code Project 是必备的。提高搜商是必须的，找准问题的关键点。坚持每天看书。关键是要多思考。充分的运用各种知识的能力。</p>
<p>我意识到某个地方不足的时候，会找相应的书籍来充电。让我一段时间不看书，会浑身不舒服的。当然我看的书的范围很广泛的。</p>
<p>从事这个行业，本来就不是那么轻松的事情。而我不喜欢轻松的工作。这个行业不断的出现新的知识，需要不停的学习。其实不管哪个行业，都需要不停的学习，否则很快被淘汰的。</p>
<p>爸妈曾经说过，如果我当初去读研，毕业后去学校教书就好了，工作稳定。未来的事情谁说得到呢。我不喜欢当老师，而且在这个变化莫测的社会，又有什么是稳定的呢？同学、朋友跟我讲，女孩子干这行太辛苦了，转行吧。可是我能够体会到乐趣所在。为自己写出了一段好的代码，或者是解决了某个困难的问题。</p>
<p>这个行业要加班，熬夜，那么为什么不能从别的角度来看这个问题呢？提高自己的工作效率，管理好自己，是不是可以解决这个问题呢。</p>
<p>这一年，我一直在修生养性，读灵修方面的书籍。人管理好自己后，其他的是不是就不是问题！</p>
<p>从事这个行业，我无怨无悔。现在我还是菜鸟，需要学习的东西很多。未来的路还很长，我坚信我会走好的。</p>
</div>
<div style="font-family: 'Microsoft YaHei'; font-size: 13px; background-color: #fafafa; border: solid 1px #EEE; margin: 4px 5px 4px 30px; padding: 0px 10px 0px 10px; border-radius: 10px; box-shadow: inset 0 0 4px rgba(0,0,0,0.5);">
<h5 style="font-size: 15px; margin: 5px 0px; border-bottom: solid 1px #CCC;">Cathy &#8211; 一个非典型的女程序员的曲折经历</h5>
<p>简单介绍一下我自己吧，我07年从一所TOP10的著名理工大学计算机专业硕士毕业，目前在一间世界500强的欧美通信公司担任高级系统软件工程师的职位。</p>
<p>因为本科并不是学的传统计算机专业，而是计算机与通信的交叉学科（课程设置上少了面向对象、JAVA程序设计等计算机高级专业课程，增加了很多电子线路设计、通信、信号论等）。毕业时因为专业课成绩优异直接保研。如果说本科毕业的时候，自己还是颇为踌躇满志，那研究生的三年就是郁闷的开始。保研后，虽然还在计算机专业但主要从事的是硬件电路板的开发。项目组的组长是一个博士，人很好但是不太会和女孩子打交道，或者说有一些性别歧视吧。进入项目组之后，一开始做了一些电路板的Schematics、PCB layout和Debug的工作，也得到了组长的好评。但是渐渐的，由于我并没有表现得非常的积极主动和对技术充满热情，组长分给我的任务越来越少。我也越来越苦闷，当时的我还并不知道该如何面对这种情况。组里曾经也来过一个女生，面临比我还要糟糕的情况，记得一次项目组吃饭当时那个女生没来，组长直接对我们大家说这个女生能力不行，没过多久她就被调去别的组了。但是我还留在这里，组长几乎很少和我说话，当时的我不知道如何向他表达我的心情也不知道自己想要什么，陷入对自己能力的深深的否定中，当时的想法只有一个：赶快毕业吧。这种情况一直持续到研二下学期。最后一年碰到了一个去国外实习半年的机会，毫不犹豫的就去了，是在一个很牛的电子公司里做电子工程师助理。干的活基本和在项目组干的差不多，画图调板子打杂，但是这半年我想清楚了一件事，就是我对干硬件没啥兴趣如果不能做IC design的话就转去做软件吧！</p>
<p>但是，当时的我还陷入在对自己能力的盲目乐观中，总觉得自己之前成绩很好，做实验写程序从来不输给男生，想转应该不难吧。回国后迅速搞定论文就开始找工作了。找工作的时候，现实很快无情地把我打倒了。因为当时我的男朋友也是现在的老公已经早我几年毕业在北京工作了，而且发展得很不错，所以当时我也一心只想找北京的工作。可是自己过去三年几乎没有写过程序，和学校里众多写过N年程序的同学竞争，结果可想而知。我只能拿到去其他城市做硬件的offer，但是却无法拿到去北京做软件的offer。这时，我的自信心跌到了谷底，TOP10大学的TOP10学生（即使读研期间很郁闷但是还是拿了不少奖学金，而且去国外半年也赚了不少钱）居然找不到工作。后来，在一个师兄的推荐下，得到了我的第一份工作，在北京的一个小公司做嵌入式软件开发。</p>
<p>虽然能来北京做软件，但和我去Google、Microsoft、IBM的同学相比，失落感不言而喻。几乎每个认识的人都会问我为什么去那个公司，为什么不去大外企，为什么不留在国外。这种失落情绪笼罩了我工作的第一年。但是还好，这个公司没什么牛人，并且因为我很好的学习能力，很快上手了。因为做底层软件需要对各种硬件接口、中断、DMA、处理器深入理解，我之前做硬件的经验也派上了用场，只用了半年时间，我就开始独立负责项目了。从第二年开始，我开始参与公司一些重要产品的开发，越来越得心应手。</p>
<p>期间，公司从其他部门调了一个工作多年的男程序员来做我的领导。一开始，我很高兴，因为了解到这个人技术不错，而且一直做上层软件所以对面向对象、设计模式、软件架构、代码规范都颇有经验，我正好可以向他学习。但是，一起工作了一段时间后，矛盾出现了。这个人认为我虽然学东西很快对公司产品业务熟悉，但是对技术缺乏热情很少主动学习技术，对很多软件开发的基础也掌握得不够，所以每次对我的评估结果就是一般；而我当时初出茅庐，认为这个人对硬件毫无了解并且没有很快在做底层软件上证明自己比我牛，所以很不服气。记得当时一起开发一个产品，因为我对主要的业务逻辑更熟悉，所以挑了最复杂的业务逻辑模块来做；他则负责其他几个通用模块的开发。为了证明自己，我只用了他一半的时间就完成了所有功能。在联调测试过程中，由于他是项目的负责人，所以每次Bug都是先提交到他那里然后再由他来指派给对应的人来负责。因为他对平台不熟悉，所以每次解Bug都要连调试器跟很久，而我常常只通过代码Review就能找出问题所在。渐渐的，所有测试的问题都直接反馈到我这边；后来产品上市，售后碰到解决不了的问题也会直接反馈到我这里。等到我们一起开发第二个产品的时候，那个男程序员几乎完全交由我独立负责。半年后，他调回了他之前的部门，我们共同开发的两个产品也顺理成章由我独立负责下去。</p>
<p>在公司工作三年以后，我对继续呆在这个部门里干软件开发渐渐失去了兴趣，基本都是重复性的劳动，而且由于是小公司除了开发之外还有很多杂事（比如因为公司售前售后没有技术背景，常常需要开发去Support；因为薪资不高常常会招一些水平较低的工程师，需要很多力气去Training）软件水平也难以再提高。而这时，公司也有意让我转向业务型负责人的方向，这几乎是在当时公司晋升的唯一途径；而如果升职，之后基本和程序员Say Bye了。可是真的要放弃做开发吗？以当时所在行业规模和公司本身的名气地位来说，如果不做开发，我很难想象以后跳槽的机会在哪儿；如果做开发，我又很难在公司继续获得我想要的。于是，我接受了公司的安排，去体验一下程序员之外的工作是否适合，同时也积极寻求跳槽的机会。在公司的最后半年，我几乎脱离了开发的工作，主要的工作内容是调研公司计划新开辟的产品线的产品形态及技术，去往各地出差做客户交流，和开发部门开会制定产品开发计划。在这半年里，我开始怀念单纯的程序员生活，不用去应酬形形色色的陌生人，即使公司倒闭也能很快找到工作养家糊口的踏实感。</p>
<p>第二次找工作的经历和第一次完全不同，有了之前几年的工作经验，我很快就拿到了几个大公司的offer。通过面试，我也逐渐认清了自己的不足之处。回想起来，我觉得之前那个男程序员说的一点没错。我并不是个本身对技术非常有热情的人，之前的研究生经历也是如此，后来工作也常常认为自己学东西快所以技术可以等到用的时候再学。面试的时候和一些经验丰富的面试官交流，可以非常明显得感受到热情这个东西对技术水平有着多么重要的影响。但是，另一方面，我对技术也并不是完全没有热情，这种热情很大程度受外界环境的影响。如果在一个大家都很牛都很积极学技术的环境，我也非常乐在其中。选择目前的公司，一是因为当时经历了比较艰苦的几轮技术面试，另一个重要的因素就是这里是有可以正面影响我的环境。目前在现在的公司工作了大半年，虽然部门三十多个程序员就我一个女孩（但是很多男程序员级别都比我低，哈哈）但是很开心，周围都是聪明并且富有经验的同事，让我受益很多，对技术也越来越有兴趣。</p>
<p>这就是我有点曲折的女程序员经历，但也是女程序员们很有可能会碰到的情况，譬如性别歧视，譬如对技术的热情等等。我觉得做女程序员不容易，女程序员由于女性的心理特质容易把负面的情绪扩大。所以女程序员最重要的是内心强大，碰到不信任你的领导或男同事，要大胆说出自己的想法，同时拿出有说服力的行动。另外，从我自己的经历和我面试过的女程序员来看，女孩通常会专注于完成工作，不像男孩那么对技术有热情；而且社会上也有各种声音说女孩不适合做程序员，于是女孩也容易自我怀疑。我的经验是，有时候先暂时不要想究竟适不适合，努力做一段时间，有些事情需要深入到一定程度才会有兴趣，如果还是不喜欢再考虑是不是放弃。</p>
</div>
<div style="font-family: 'Microsoft YaHei'; font-size: 13px; background-color: #fafafa; border: solid 1px #EEE; margin: 4px 5px 4px 30px; padding: 0px 10px 0px 10px; border-radius: 10px; box-shadow: inset 0 0 4px rgba(0,0,0,0.5);">
<h5 style="font-size: 15px; margin: 5px 0px; border-bottom: solid 1px #CCC;">Linn &#8211; 误打误撞的程序员</h5>
<p>昨天老公发来的网址给我看。<br />
那时候刚好项目上线，大家要去聚餐，就匆忙的瞅了一眼，跟老公开玩笑说，怎么样，我也写一篇？<br />
他说好啊。</p>
<p>今天是2011年的最后一天。<br />
挺有纪念意义的，回顾一下。</p>
<p>我是高中生，05年毕业，去了北大青鸟，我知道现在很多人对北大青鸟的看法褒贬不一。<br />
怎么说呢，一母生九子吧。</p>
<p>其实当初高考失败，我不想去上大专，更不想复习，我知道自己学不进去。<br />
那时候接触电脑不多，可能也就一周一次的电脑上机课，但我就是对它很有兴趣。很单纯的。</p>
<p>接着，同学听别人说了北大青鸟，然后想让我跟她一起去。<br />
其实，当时我连编程是干什么的都不知道。哈哈。<br />
我那个同学也是女的。<br />
我说服不了我爸爸，我爸爸还是比较想让我上大专，他说至少你出去长长见识。<br />
我脾气比较倔，想一件事，就一定要去做，我带我同学去我家，她的劝说能力比较强，最后我爸无奈之下同意了。</p>
<p>然后我就离开了我们县，去了我们省的省会。</p>
<p>第一次出远门。<br />
我当时不会讲普通话，我觉得自卑（现在想想我真是很容易自卑），到了那里后，同学跟她姐姐有事出去了几天。<br />
那几天我就跟个傻子一样，就在她姐姐租来的小屋子里呆着，没有电视，没有电脑，甚至我不怎么出去吃饭。<br />
寂寞、孤独、无助、茫然。<br />
其实人的恐惧源于无知。对这个城市的无知，对未来生活的无知。</p>
<p>我终于没有忍住，给家里打了个电话，哭了。<br />
我爸跟同学的爸爸听说后，立马就坐车到了我住的地方，我那时候真的没有想到有那么严重的结果。<br />
我爸爸一直都比较宠我，我没想到他们会来。<br />
那天我刚好跟同学还有她姐姐出去玩，很晚才回来。<br />
那是夏天，很热，就看到两个老人满头大汗的在我们住的屋子对门那家，吃西瓜。<br />
我差点又哭了。<br />
第二天早上，我爸问我，他说，你还想留下吗。<br />
我说想。<br />
就这么回去了，我觉得没脸。</p>
<p>我想那时候我爸就彻底死了劝我回去的心了吧。</p>
<p>然后交钱上课。</p>
<p>大家刚学编程的时候可能都会有那样的经历，计算机本来就是一个很抽象的东西，编程，就是抽象中的抽象。<br />
刚上课的时候，很久没有玩过电脑，我甚至忘记了本来就不怎么熟悉的盲打。<br />
我很清楚的记得班主任跟我说：盲打还不会，基础不行啊，多练习练习。</p>
<p>2005年8月份，到2007年3月份，我毕业了。</p>
<p>这时候我的状态：学过多门编程语言，主打java，当初学了app4.0，4.0的课程里有struts1.2，oracle等。<br />
但，知其然不知其所以然，还是懵懵懂懂的样子。</p>
<p>其实我们当时有两个就业方向.NET，J2EE，当时还是叫J2EE的。<br />
都说J2EE是比较难的，我为什么学这个，说起来也有点搞笑，因为我觉得，.NET可视化功能太强大了。<br />
我本来就学的懵懂，不精，控件拖来拖去的，我就更迷糊了。不如JAVA一行行代码写起来来的踏实，哈哈。</p>
<p>第一次面试，现在说起来真的很鄙视当时的自己。<br />
我本来是相当老实一孩子。<br />
我们当时有就业部，负责学生就业。<br />
教我们如何面试，如果跟面试官交流，如何突出自己的优点。<br />
我记得特清楚的是，如果人家问你的缺点，你可不能真说你自己的缺点，要说一种看起来像缺点，实际对编程或者公司来说是优点的。<br />
我真是傻孩子，我这么干了，记不太清我的原话了，但大意说自己比较执着什么的。<br />
面试官最后说了一句话让我无地自容至今，他说：这不还是你优点吗？</p>
<p>07年4月9号入职。公司做一个门户网站。</p>
<p>公司给新员工机会，试用三天。<br />
就是看公司原有的框架spring+ibatis，做一个功能给pm看，如果可以，就留下。<br />
我运气有点背，机器有问题，不时的挂。<br />
再说我也没怎么看懂的说，三天过去以后，没能拿出来一个东西。<br />
pm过来看了一下，然后跟人事说，回来的时候表达要我离开的意思。<br />
当时我内向啊，有点懵。<br />
我跟他说，我机器有问题。<br />
pm人也很好，他说那再给你半天吧。<br />
这时，我后来的组长，真的给我很大的帮助，他说你应该怎么怎么来。<br />
其实我本来有些懂的，他那么一说，我顿悟了。<br />
1个小时，或许不到，反正很短，我又叫pm过来看。<br />
他跟我说，好了，你可以留下了。<br />
我跑到卫生间，那瞬间，真的很想大哭。兴奋、激动、委屈。我也读不懂当时的那种感情。</p>
<p>其实这个公司并没有让我的技术提高多少。<br />
pm是一个技术相当强悍的人，至今见过这么多人，我依旧这么觉得。<br />
框架里的很多东西，当时不太能理解的了。<br />
但是当初经历的那群人，真的让我铭记至今。</p>
<p>09年，男朋友毕业，留在了另外一个城市，我所在的公司宣布解散，于是我也过去了。</p>
<p>其实我觉得我内心深处有一股非常强烈的自卑，我不知道这自卑来自于过度的谦虚，还是觉得自己的水平真的不行。我想或许两者兼有。</p>
<p>在这个城市的面试很糟糕，我是一个很简单的人，只是想尽自己的努力去做一些事情。<br />
后来留在了一家公司，公司新开的一个部门。<br />
招的都是几个大学刚毕业的学生，有几个从达内出来的。<br />
他们的技术不是不怎么样，是真的很不行！<br />
于是我跟另外一个男同事就成了头儿。</p>
<p>那时候的项目是给公司自己用，做页面，写css，写代码，服务器，几乎都是我来牵头。<br />
那一年的时间，对我的感触很大，技术也提高很多，因为什么事情都是你自己来做，自己去想。<br />
压力很大，但也很茫然。我不知道自己在做些什么。因为公司毕竟不是正规的it公司，我自认自己技术挺烂，真的需要人协助。</p>
<p>说一下我的男朋友。<br />
他一直喜欢手机上的东西，知识面覆盖非常广。<br />
10年6月份的时候，北京有一个机会，他过来面试，然后留下做iphone手机开发了。<br />
于是我也着手辞职跟着过来。</p>
<p>北京的面试依旧不怎么乐观。于是我几乎每天晚上看基础知识看到很晚。<br />
我一个同事说的好。他说如果你不能说，你就只能靠做面试题来让对方看到你的水平。</p>
<p>我还是算运气比较好，一个星期的时间，我收到了现在公司的offer。</p>
<p>或许你看到这里已经明白，我几乎是跟着男朋友的脚步走。<br />
事实上，是这样的。<br />
做程序员，只是我要做的一件事。而家庭是我的全部。<br />
事业上，我其实一直都很茫然。<br />
我想是有这样一部分的人存在，他们没有梦想，没有目标。<br />
我说的梦想是指那种真心喜欢，并能为之奋斗一生的事情。<br />
我想我就是那样的人。<br />
但这种人必然有另外一种追逐的东西，比如，我时刻都很清楚家庭才是我的全部。<br />
我会找一份不很累的工作，有充裕的时间，来陪伴他们，同时也让自己有事情做，不空虚，不无聊，不虚度。<br />
但这不代表我工作会做的很糟糕，相反，我第一个项目经理跟我说，以后如果我开了公司，我第一个就会找你。<br />
我第二家公司的老板，在我来北京之后还打电话叫我回去。<br />
现在的公司，领导跟我说，我见过很多跟你一样条件，从北大青鸟出来的人，但像你这样的，真的少见。</p>
<p>我做程序员，其实算误打误撞，现在想想，我当时向往的应该是美工设计之类的工作。<br />
我不是什么技术大牛，我碰到的女程序员，也没有什么技术大牛的。<br />
但是他们都有一个共同点，就是不管他们做任何东西，只要交到他们手上，在相等条件下都会比男同事做的好。<br />
这可能跟女孩子天生的认真细心有关。</p>
<p>这篇文章，可能看起来比较乱。<br />
但我想表达的一个意思就是，其实女程序员很普通，也特别，神秘，也不神秘，如果你了解了的话。<br />
但她们绝对是可爱的。大多数有着男孩子的性格，豪爽。<br />
所以我时常说这世界上有男人、女人、女博士、女程序员，哈哈。</p>
</div>
<div style="font-family: 'Microsoft YaHei'; font-size: 13px; background-color: #fafafa; border: solid 1px #EEE; margin: 4px 5px 4px 30px; padding: 0px 10px 0px 10px; border-radius: 10px; box-shadow: inset 0 0 4px rgba(0,0,0,0.5);">
<h5 style="font-size: 15px; margin: 5px 0px; border-bottom: solid 1px #CCC;">Nana &#8211; 做喜欢做的事，所以很开心</h5>
<p>你好，关于女程序员的那篇blog是群里一个GG推荐我看的。这应该算一个励志故事吧，可是一般励志故事都没什么意思，不是苦大深仇，就是从委屈一路走到故事末尾，见到一点小小的胜利。说的故事虽然到了末尾，但人还活着啊，所以真正的故事还没完呢。对励志剧不太感兴趣，因为事实往往是，努力不一定会成功，而且不成功的在大多数。</p>
<p>我的故事无关成功与失败，随便看看。先说说为什么会去写程序这件事吧。起初完全不相关的，我喜欢的是动漫。但是对于自己的画画和分镜都不看好，于是想到了游戏。动漫游，是不分家的。游戏行业有许多种职业，常见的小工有：策划美术程序。这3种职业的相关基础课都上了下，其中，编程给我留下了非同寻常的印象：这件事情，太TM好玩了！！即便会拉3D模型、会设计游戏的灵魂世界观，也不能同它相比。于是，几乎没怎么犹豫就开始学习编程了。</p>
<p>一开始是学java，比较容易的。后来接触了C++，貌似稍微复杂点，不过总的来说，会了一门语言其它的都有点异曲同工，所以不管性别如何，其实没啥差别。在工作中，也没觉得人家拿我性别说事或特殊化，大家都凭能力干活拿薪水，可能比某些靠关系的行业好一点。很想推荐下我们项目组正在开发的这个游戏，但又怕一说名字就暴露了，呵呵，我们组就我一个mm。</p>
<p>人家都说，编程薪水高，我不能说这是假的，但我的同学中，薪水高的都是加班连轴转、除了程序不太想其它的。用那样的精力时间换来的高薪，到哪个行业都能换到吧。</p>
<p>学历，貌似在编程这个行业里更加渺小了吧。只有一次去面试一家大游戏公司时，被问过是不是重点大学。其它公司基本不怎么关心，更看重能力。也只有一次，在面试中，被问到是否已婚。可能是怕生孩子耽误工作吧，人走了活儿给其他人干，其他人虽然不说什么，但无形中增加的压力是肯定有的。但在这里我要说一句，这些面试官思维都有点传统啊，其实不结婚也可以生孩子、已婚生完孩子的也可以再生啊。要不你们干脆就说，女性勿面试，不是更好？！</p>
<p>做程序是吃青春饭，这话有点道理的。我现在的工作，是喜欢干的事，所以很开心。但如果是一个需要养家糊口的GG，可能就不能只顾着自己开心了。所以说，做程序员，mm也许更合适？</p>
<p>呵呵，午休结束了，回去干活～</p>
</div>
<div style="font-family: 'Microsoft YaHei'; font-size: 13px; background-color: #fafafa; border: solid 1px #EEE; margin: 4px 5px 4px 30px; padding: 0px 10px 0px 10px; border-radius: 10px; box-shadow: inset 0 0 4px rgba(0,0,0,0.5);">
<h5 style="font-size: 15px; margin: 5px 0px; border-bottom: solid 1px #CCC;">Gift &#8211; 当一名战士就是一支军队，那些软件不需要工程的时候</h5>
<p>请允许我为公正评价女程序员做一点贡献。以下文字所提到的关同学是一位女程序员。</p>
<p>注：以下文字已发表于[http://blog.csdn.net/younggift/article/details/7166600]。</p>
<p>* 最初的代码</p>
<p>1994年，当我开始对编程感兴趣的时候，还没有软件蓝领这一说法，但是我已经有了后来软件蓝领流行起来以后的困惑。</p>
<p>我第一次做的比较大的程序，是用GW-BASIC写的，没有IDE界面，需要按行号插入，黑底绿字的显示器，单个软驱倒腾用两张盘。 (感谢我们的导员刘春光老师每天中午借我用他的计算机) 要编的程序是自己想出来做着玩的，一个DOS界面下CGA显示模式，菜单方式的……班费管理程序。如同齐同学的那个定票系统，这个软件并没有实际应用，不过，它对我来说，比此后所有写的程序都更难。</p>
<p>代码后来参加一个比赛的时候，打印了唯一的一份纸质版，打印纸抻开比我举起手还要高。我当时遇到了程序设计中的核心问题&#8211;大量的代码，复杂的逻辑。</p>
<p>我当时使用了GW-BASIC提供的一个非BASIC的功能 gosub，类似于函数调用，它帮助我逃过了程序彻底混乱的厄运。后来当我学到模块化思想的时候，如遇故人。我毫不费力地就接受了这个观念，因为痛过，所以印象深刻。</p>
<p>后来经常见到有初学的同学函数写得超出两三屏，还很得意自己逻辑控制能力。我就在心里撇嘴，你那是还没受够罪。</p>
<p>大量的代码，复杂的逻辑。软件工程给了我们某个答案，就是软件蓝领，它声称大量的人工、短期培训、重复地简单劳动，能够解决&#8211;以工程的方法&#8211;大量代码和复杂逻辑的问题。</p>
<p>是的，我们这么干过，好几千看前就这样做。埃及盖金字塔，是没有起重机的，而是靠几千几万人力完成的；中国的古长城 (不是当代的) ，也没有等待现代电子计算机和通信技术的发展，而是靠万喜良们的双手堆砌出来的。</p>
<p>那个时候，他们一定期待一种东西，可以用燃油作为动作，稳妥精确地运输沉重的材料。</p>
<p>但是他们没有。因为是时代是父亲是民族选择我们，而不是反过来，所以很多时候很多事情都不能一蹴而就。</p>
<p>有的时候，智力或自然的法则也参与限制。</p>
<p>* 他们说，没有解析解</p>
<p>在数学当中，有一种解题的方法得出的结论称为解析解。我们解一个方程，得到结果，如果我们所做的常见运算只需要 有限次，那么，这个结果就称为解析解。</p>
<p>这是什么意思呢？就是说，你可以通过公式，只需要一个大式子，可能非常大，但是最终可以计算出结果，直接地。</p>
<p>难道不都是这样么？不幸的是，还有一些方程，伟大的牛人数学家们告诉我们，有些方程就是不能通过公式求出来。而我们在工业生活中还需要求解。</p>
<p>数学家牛人们还是有办法的。他们创造了另一种方法，用猜测-比较-再猜测，大致这样的方法，逼近我们寻找的那个数。这些牛人们中的第一位就是著名的牛顿。</p>
<p>但是，我们得到的是那个”数”，是整个方程中的一段，而且是粗糙的。精细的完全一致的解，可能永远也无法求得，我们得到的就是对于当前的应用”足够”精确<br />
的个案。</p>
<p>人类是多么地热爱形而上，热爱一次性解决所有问题啊。可是，数学牛人们说，有时候，你哭也没有用，就是不行。</p>
<p>在程序设计中也是一样，只有工程方法，有人说，就是蓝领方法，才能解决大量代码和逻辑复杂的问题。</p>
<p>如果没有燃油，没有热功当量，除了征服更多的奴隶，又有什么方法能够赢得自己的自由呢？</p>
<p>但是，我们是否已经判定程序设计一定没有解析解，所以只能靠人力逼近？</p>
<p>* 解析解</p>
<p>我和李记者曾经对刘典同学怀有偏见，认为他(没有虽然技)技术极好 ，但是却从不注重软件中的工程，也不怎么注重合作。</p>
<p>今天，关同学用事实给了我强烈的教育。她用事实告诉我：软件工程为什么有时可以忽略？因为有的程序员，她一个人可以完成超过100个程序员的。</p>
<p>就像有的战士，一个人就是一支军队。</p>
<p>刘典同学讲过他写数据库的程序用了编译原理生成代码，讲过写手机游戏的时候用虚拟机。前几天，我刚刚写了3千多的代码生成器，吐出来近6万行代码。这些<br />
给我的印象也都没有今天这样深刻。</p>
<p>程序设计，是一种创造工作，就像写小说。与写小说不同的，你所创造的是一台机器，它可以做很多事，你甚至可以制造一台机器，它以代替你写作最终需要的<br />
代码。</p>
<p>在所有的计算机本科都开设了相关的课程，叫做编译原理。在一定程度上，这是一个解析解。</p>
<p>* 关同学</p>
<p>今天我CIAC的导师请大家吃饭，辛苦一年。导师本人想参加，我托包师弟说：不欢迎他。如果导师出现，今天稍微拘谨的场面，就可能令聚会完全不同。</p>
<p>我们讨论了，我们吃午饭了，我们唱歌了，我们又吃晚饭了。</p>
<p>刚开始吃晚饭没多久，包师弟说：2012的上半年，我们有一些任务要完成，相当于本年度完成任务的40倍工作量。</p>
<p>他说：这些工作都是相似的。</p>
<p>可是这些相似的工作如果不能抽象出其中相同的部分，就没有一点相似。我们人类看到的相似，对于构造代码而言，毫无用处。</p>
<p>我看不出来相似。然后我想了几个方案，又都推翻&#8211;我在想从哪里抓那么多奴隶来，又用什么报偿他们，工程本身于他们何益。其实，同学们并非奴隶，必须保<br />
证同学们有足够利益和受益，否则除了我自己，一个人也派不出来。</p>
<p>我说：包师弟啊，你能不能别在吃饭的时候说这个，我都吃不下去了。</p>
<p>我真的吃不下去了。焦虑。而且，从这以后，我真的几乎没吃啥。</p>
<p>奇迹时刻。</p>
<p>关同学说：老师其实我想了，这些方案都是类似的。</p>
<p>我说：啊？</p>
<p>她说：所有的界面都可以……根据配置文件，new 出 一个 label来……</p>
<p>是的，不熟悉关同学的，对女生能否写好程序有疑问的，请仔细看一下，她，不是他。</p>
<p>而且，她也不必再解释这个方案，因为软件组可以全体解散，而剩下的工作，只需她一个人短时间就可以完成。</p>
<p>这就是抽象的力量。</p>
<p>她没有写GUI，而是解析配置文件生成了GUI；她绕过了令我头疼的C#如何表示GUI&#8211;这样就可以生成RC文件，在编译前，我考虑过的方案&#8211;而是在运行时，new<br />
出所有的GUI控件来，相当于解释执行的。</p>
<p>* 后来</p>
<p>后来，全体软件组成员加入了硬件组，将承担下位机的代码。很好，我终于不用再讨厌他们用的IDE了，因为再也没有他们熟悉的VS什么的了。我们都开始进入<br />
单片机或ARM的世界。</p>
<p>后来，关同学对我的赞不绝口指出：这个方案是你告诉我的啊。</p>
<p>我说：啊？</p>
<p>她说：就是大仪网的时候，你告诉我blabla。</p>
<p>我想起来了。不过，这仍不是我的方案，而是她的。一个方案之所以好(像这个，好到如此突出，以致你一眼就能看到，绝不可能错过，如果你看到了的话)，是因为它被应用在一个恰好合适的领域，恰好解决了一个难题。至于这个方案有多难有多容易，有多高科技，其实不是多重要。</p>
<p>关同学刚毕业的时候，我们在CIAC讨论一个框架，当时我说：这个倒是可以再抽象，不过我的方案有点耍赖了。</p>
<p>关同学说：你是不是要用函数指针。</p>
<p>是的。而且我非常欣慰了一下，因为学生优秀。</p>
<p>黄同学当时认为：函数指针，也没啥难的啊。</p>
<p>是的。函数指针一点也不难，能想到用函数指针解决这个问题，是一个高度。</p>
<p>关同学在此刻想到了一个如此好的方案，所以接下来的半年，我们都不必那么焦虑了。</p>
<p>这就是解析解。</p>
<p>关的方案，不是减轻了劳动，不是像我以工程的方法、各种测试 (关今天还提出用MATLAB生成测试数据，也很好，后来给齐同学用上了) 来控制代码质量，用框架规范程序员的行为，这些都不是，关同学直接替代十来个人把40个用例生成了出来。</p>
<p>代码质量如此一致和优秀，是由图灵保证的。</p>
<p>* 后后记</p>
<p>上午，与一位技术人员和一位经理谈话。</p>
<p>我提到 通用的CMS &gt; 定制的站点 &gt; 使用CMS。</p>
<p>那位技术人员不认可。我说：我刚刚说错了啊，我不是指复杂，而是指困难。</p>
<p>那位技术人员blabla说，这不困难，只要如何如何即可。</p>
<p>我说：其实我们也不必达成一致意见。我的意思不是说我们无法实现，我说的我会收更多的钱。</p>
<p>争执略去，我同意那位技术人员的下面这个观点 (大致意思，我翻译过的) ，但是当时没有时间表达：这不是工作量，而是更高的高度。</p>
<p>是的，那不是更复杂，不是更消耗时间，甚至不是更困难。</p>
<p>那就是更值钱。</p>
<p>关同学用事实告诉我：一名战士完全可以是一支军队。没错。</p>
</div>
<div style="font-family: 'Microsoft YaHei'; font-size: 13px; background-color: #fafafa; border: solid 1px #EEE; margin: 4px 5px 4px 30px; padding: 0px 10px 0px 10px; border-radius: 10px; box-shadow: inset 0 0 4px rgba(0,0,0,0.5);">
<h5 style="font-size: 15px; margin: 5px 0px; border-bottom: solid 1px #CCC;">Zheng &#8211; 永不放弃程序员的工作</h5>
<p>从工作年限来说，我还不能算是一个程序员，因为现在还是一个大四的学生。但是我已经认定了程序员的这条道路。<br />
高考结束后考虑专业问题，那时我的兴趣是文学，但是因为现实社会的关系和家庭经济的原因，我在毕业生收入排行榜上选择了平均收入最高的专业，软件工程。大一时懵懵懂懂，挂了很多科目，重修，从大二起开始拿奖学金，开始参加项目。因为大一评奖学金时看到自己排在倒数第二的位置，看到同班的同学参加各种软件比赛，我那时就开始思考，我在做什么？于是开始疯狂地写程序，重新学基础知识，认真上课，经常去看一些IT博客。在一家公司实习，我开始接触分布式系统的东西，那时leader让我一个人负责这一块，我就像实验的小白鼠的一样，但是我却感到很如鱼得水，我喜欢快速掌握一门新的领域，并学会总结。那是我真正意义上的在linux下的开发工作，学会了c网络编程，shell，python，hadoop,hive。那里的开发团队只有我一个女生，我见识到一个优秀的程序员所应该具备的一些素质，对技术热点的掌握，对产品的敏锐，不仅是代码，而且是融入产品的设计中，能提出作为一名开发者的意见。如果说作为一个女程序，我与他们不同之处，恐怕是得到更多的照顾，也学到很多。</p>
<p>实习两三个月后，我选择离职，在我看来，没有毕业的我实习就是一个新的课程，工作经验就像是旅程，经历的风景是阅历，也是财富。我选择了去一家做云存储服务的公司，在那边更深入地了解关于分布式系统的知识，而这些知识的获取是我自己间接得到的，并非公司培训。我刚到那里，发现还有另一个女程序，她很活泼，而且在项目开发中占据很重要的位置。从一个程序员的角度出发，我并不觉得会写代码是一件多么厉害的事，重要的是上手的能力，系统设计的能力，构架高性能的能力。而基础这些东西只要是一个智力水平相当的人，通过一定时间的磨练，都有可能掌握的。这家公司的资源很丰盛，我的任务并不多，更多的时间是自我学习和研究毕设课题。因为leader没有放手让我干活，干的只要是python脚本的一些开发，所以每次任务来的时候我都很快完成，一般leader上午给任务，下午下班前我就可以提交代码，剩下时间就做自己喜欢的c/c++的cli小应用和一些nosql开源项目。有时一个程序出错，就很偏执地想把错误找出来以后再收工，导致吃饭误点，这样的习惯对身体很不好，现在也正在努力改正中。工作经历差不多就是这些,不介意的话讲一下求职经历。</p>
<p>我去面试时，很多面试官都会问我，女生做开发人员的问题。我想这本来就不是一个问题，作为一个人，你需要养家糊口，我也需要。我也有自己的职业规划，清楚知道自己想要什么。从懵懂到略知一二，到准备跳进火坑里塑造一个雷厉风行的新的自我。我一直相信人的某些性质是会变的，随着阅历，经历，实践的不同也产生质的改变。你现在看到的是一个弱女子，未必将来你不会看到一个女架构师。这些都是在进入hr面以后经常会和hr聊到的东西。这份工作能体现我的价值，我就来了。这就是我求职一路的态度。后来成功拿到一些公司的offer。</p>
<p>在未来的职场上，我也会不放弃程序员这份工作。学习的态度，认真负责的做事风格，即便我不是一个天才工程师，也可以成为优秀的程序员，不用刻意加“女”字。</p></div>
<h5 style="color: #cc0000; text-align: center; font-size: 20px; margin: 30px 0px;">女程序员们，为你们骄傲，祝你们2012年更上一层楼。</h5>
<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="程序员的八个级别" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F343.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6346.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F343.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6346.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F340.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6346.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F340.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6346.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2287.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6346.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2287.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6346.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1103.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6346.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1103.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6346.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1695.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6346.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1695.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6346.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>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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月30日 -- <a href="http://coolshell.cn/articles/6526.html" title="软件开发的“三重门”">软件开发的“三重门”</a></li><li>2011年12月30日 -- <a href="http://coolshell.cn/articles/6312.html" title="一个女程序员的故事">一个女程序员的故事</a></li><li>2011年12月20日 -- <a href="http://coolshell.cn/articles/6142.html" title="三个事和三个问题">三个事和三个问题</a></li><li>2011年11月15日 -- <a href="http://coolshell.cn/articles/5815.html" title="来信， 创业 和 移动互联网">来信， 创业 和 移动互联网</a></li><li>2011年10月25日 -- <a href="http://coolshell.cn/articles/5686.html" title="多些时间能少写些代码">多些时间能少写些代码</a></li><li>2011年10月20日 -- <a href="http://coolshell.cn/articles/5651.html" title="Stay Hungry, Stay Foolish ！！">Stay Hungry, Stay Foolish ！！</a></li><li>2011年09月21日 -- <a href="http://coolshell.cn/articles/5514.html" title="如果你看不见你还能编程吗？">如果你看不见你还能编程吗？</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/6346.html/feed</wfw:commentRss>
		<slash:comments>93</slash:comments>
		</item>
		<item>
		<title>一个女程序员的故事</title>
		<link>http://coolshell.cn/articles/6312.html</link>
		<comments>http://coolshell.cn/articles/6312.html#comments</comments>
		<pubDate>Fri, 30 Dec 2011 02:25:02 +0000</pubDate>
		<dc:creator>陈皓</dc:creator>
				<category><![CDATA[职场生涯]]></category>
		<category><![CDATA[轶事趣闻]]></category>
		<category><![CDATA[Programmer]]></category>
		<category><![CDATA[程序员]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=6312</guid>
		<description><![CDATA[因为有人在酷壳里评论里说我给一个女程序员的建议不靠谱，我不服，因为我的工作经历中的一些女程序员都很不错，比那些男程序员都强，所以，我在新浪微博和twitter上征集女程序员的故事和想法，这两天来，我收到了好几封邮件，让我很感动。其中，有一个故事让我回味很久，在脑海里挥之不去，可能是因为她的经历和我很相似，她的想法和我很有共鸣。 本来，我想通过收到的这些故事然后编辑成一篇关于女程序员的文章，但是我觉得这个故事已经足够好了，任何的编辑都是对这个故事的不尊重，所以，我原封不动，一字不改地把这个故事转到这里。我把一些我认为精彩的地方加了粗。 当然，我还是会再写一篇关于女程序员的文章，酷壳2011年底的最后篇文章和2012年的第一篇文章都是给女程序员的，因为，我为你们骄傲！ 从哪里说起呢，我的程序员之路。有些话只是自己心里想的很明白，还从没说过。希望你有耐心看完，因为我的故事不精彩，也算不上奋斗史。我的文笔和叙事能力也很差。 高中报志愿的时候坚定的报了计算机技术及应用，当时对计算机的认识只是机房里的苹果机，和老师教的用basic 输出一个正方形之类的。 我当时觉得我对计算机一无所知，我想了解他，就选择了这个专业，当然当时程序员的收入也是可观的。 ：） 大学四年下来，我的成绩不好，基础也不好，没拿过奖学金。大学的课程很多不喜欢，我不知道为什么计算机系还要学高等物理，和马列毛邓。这是题外话。说实在的，很多课上的我一头雾水。毕业后找工作不满意，我直接去读了软件工程（考研的专业课成绩没到线）。两年制，一年上课，一年实习。我想给自己的履历上增加一些至少能给我面试机会的经历。（我仔细思考过我成绩不好的原因，心里因素是主要的，高中在重点中学，我不能接受自己不是尖子生的事实，总在想自己为什么这么差，以至于这样的心情影响了我很多年，一直到工作后的几年） 实习的第一家公司是个私企，工作两周后他们不满意辞退了我，沮丧是当然的，我知道我的能力是有差距的。虽然他们没有任何培训，直接拉去干活，起码的业务流程也没给我讲，但是我真的发自内心感谢他们辞了我，让我认清了自己。其实当时干的就是一些perl 脚本和php的网页开发。 实习的第二家也是私企，给运营商做项目。我参加的是一个工作流项目，用java开发。我当时的java技术仅限书本身的不怎么牢靠基础知识，至于怎么设计这个系统也没有一点概念，终于一个月后我决定退出了。经过这一个多月，我似乎知道了自己该从哪里开始了。就从java开始吧。 经同学介绍，去了第三家实习公司，面试的经理对实习生要求不高，让我能有机会实习。做的是银行和证券公司的网站，我主要做前端jsp的页面，同时我也选修了学校请的一位Weblogic的工程师开设的J2EE的课程。总算开始入门了。公司的同事很帮助我，有耐心让我了解了系统后台的架构。后来我随几位去客户那里出差，周末和晚上加班，为了他们临时改的需求。同事说，你一个女生出差一点不发憷啊。其实我一点不觉得累。同组的team lead没事就鞭策我说，你就甘心写code么，不能总是做开发，该为以后想想。但是我当时想法是，我的视野当时有限，还不确定自己能做成什么样子。我在这家公司完成了毕业论文。然后毕业。 毕业找工作，我没有留在实习的公司，我想多试试。找工作的经历不多，我去过联想面试，笔试过了，一面是HR面，题目现在大概还记得，如果有化学家，天文学家，医生，乞丐，孕妇，在一个荒岛上，你只能带走一个，你带走谁呢？分组讨论，得出一致的结论，也要说出自己的结论。 同组有清华的毕业生，真的很自信，她说要带走天文学家。我说，出于人道，我肯定带走孕妇。后来就没了消息。难道医生可以留下照顾孕妇么，还是HR以为我选孕妇是注重家庭的人，没有事业心呢，我觉得这题真的不能说明什么。 之后面试了一家日资企业，一面是很多人一起面，我听了一圈之后，觉得自己有些把握，因为同组的人比我差，看来我运气挺好的。他们之中有本科生，有研究生，都是男生，就我一个女生。问的也挺基础，就是servlet如何工作，写没写过SP，其中有个人问，什么是SP，没人理他，我告诉他是store procedure。面试官是个部长。后来HR的人过来让我留下二面，说我一面打败了所有男士。说来惭愧，我真的是运气好，没碰到牛人。二面经理只问了些平常的问题，就过了，于是我来到这家工作。考虑的是，外企多少工作流程上比较规范，也见见日本人是怎么工作的，还有就是自己能力有限，欧美大公司估计是没戏的，我还是从力所能及的开始吧。 日本人工作的风格大家应该有所耳闻，就是喜欢加班，我进公司的第一个项目是代码改造，把VB6.0d code重写为VB.net。 加班到凌晨是常事，另外一个就是team lead的风格是没事也不能早走，也得耗到半夜才行。开始做的真是一点技术含量都没有，都是日本人写好guide，告诉你什么改成什么，别问为什么，不能有异议，他们怎么说你怎么改。弄得我当时都不去思考这里的技术细节，这是我当时犯傻的表现。除了技术本身，还有很多需要学习的。后来陆续做了一些我喜欢的java的项目，用到了sping，hibernate，ibatis, struts, ant等等。还有一些日本人自己开发的框架。每个项目的业务也都不同。在这家工作了三年，我觉得这不是我要的，我的技术提高有限，做的事都是别人设计好，甚至告诉你code应该如何写，而且做事风格不是我想要的。 我想去欧美文化的公司试试。也想做通讯相关的。 同学帮我投简历，我面试一家对欧美的外包企业，一面是本公司的人面，问了项目情况，说了说英语，我准备还算充分，过了，二面是公司的客户面，到公司和客户开电话会议面试，第一次和老美直接对话，我虽说有点紧张，但是还是专心听他的问题，听不清的就让他重复一遍，我现在记得的一个问题是如何写出高效的SQL。面完回家等通知。过了几天我收到了offer。 客户是为运营商提供软硬件服务。我们做的是BOSS系统的一个模块。都是java api。 几乎用到了J2EE中定义的所有组件和java相关的框架。我在这家工作至今。技术从不熟悉到熟悉，业务逻辑从不熟悉到熟悉，都是在开发每个feature和改的defect中慢慢了解的，硕大的系统不允许我一口吃个胖子。只要脑子里绷根弦就每天都有进步。加班不是常事，但是也有紧张的时候。 有时候一个defect要跟踪成千上万行代码，你才知道哪里出了问题，这是需要耐心和细心的。给客户的客户做support的时候，经常被半夜的电话叫醒去看一个现场的问题，我不觉得累和烦，我觉得这是我价值的体现（当然这不会每天发生）。修复一个defect我会有一点小小的成就感，每天晚上回家方便的话也会看看邮箱，看看有没有紧急的事情。有的人认为你下班了就没必要再管工作邮箱了，但是我愿意这么做，我觉得这是我职业精神的一部分，也是工作态度。 偶尔会帮着公司招聘毕业生，有时候会遇到什么简单问题都答不上来的人，我感觉就像看见当初刚毕业的我，临走，我会说一句，没关系，回去好好准备，看看基础知识。 我曾经怀疑过自己是否适合做技术，总觉得自己不如男生，也总在问自己的路在哪。而且没有自信，曾经紧张到，有人看我打字，都紧张的手抖。到现在，我觉得做技术挺好，就像你说的，我清楚的认识自己，我不是技术大牛，就每天写着自己的code，了解业务，挺好，但是不代表我不上进。很多女同学现在都不做技术了，也不写code了，但是我还在做，甚至越来越喜欢，在中国有种普遍的想法是，作几年技术该转去做管理，否则认为你不成功，这是人云亦云的说法。我想我为什么不能一直做技术呢？虽然中国的大环境可能不适合你一直做技术，但是我愿意试试。我不愿意放弃多年来积攒的一点点优势。何况我现在工作上越来越得心应手，不久前，我收到客户的邀请，他们想让我transfer到美国或者加拿大成为他们的一员，我在等待漫长的人事流程，也有可能会pending。但是我无所谓，我现在自信，知道想要什么。一直做技术，怎么了，不行么？ 谈到男女程序员的问题，有些男人以技术强自居，而少了一点谦逊和工作的严谨。有些技术不强的，有些懒散，得过且过。都是我遇到过真实的人。同组的一个女生来了几个月就比一个来了一年多的男生上手快，这说明什么的，态度和努力是重要的。我更认同的是技术和男女无关，和个人有关，任何以偏概全都是片面的。 同组的男同事们没有因为我是女性而轻视我，我很感谢他们，在一个team工作，技术是必要条件不是充分条件，合作，交流，态度，遵守流程，任何一个都缺少不了。如果我只是技术差点，那么我提高的空间是很大的。 多看看书，真的不难。虽然我可能离amazon或者是google这些企业的要求还有差距，但是那是我的方向。不过像baidu，腾讯这些流氓公司，给我多少钱也不去，女程序员也是有傲骨的，虽然也有可能他们看不上我的能力，但是，那又有什么所谓呢。 如果你能看完我这如白开水的文字，很感谢，因为我写的实在太不好了，这些经历普通不过，也证明我是个普通的人，如果我高中的时候不那么在意自己是不是优秀生，就能放轻松，大学（也在想这些）会有个好成绩，没准我就能如愿的毕业就进欧美大企业，不过那样我可能也少了以上跌入谷底的经历和现在平和的心态，我想后者对我更有意义。 不用署名，有的话，一个女程序员，哈哈。有错误处，见谅，中午休息，仓促的回顾了这些。技术本身心得有限，我就不班门弄斧了，还需努力。也请不要注我的微薄行号啦。另外我老公也是程序员，我和他能谈些技术和项目上的事情，我想是非女程序员感受不到的乐趣，哈哈哈。 看到这里你还不想为她鼓掌吗？ 最后，请让我我再次征集—— call 所有的女程序员，我想给你们写一篇blog，希望你们能和我分享你们的程序员的经历和技术心得。你是男程序员也没有问题，也欢迎分享你身边女程员的故事。 大家可以发邮件至：haoel(at)hotmail.com （全文完） 相关文章2012年01月30日 -- 软件开发的“三重门”2012年01月04日 -- 程序员因为女孩而美丽！2011年12月20日 -- 三个事和三个问题2011年11月15日 -- 来信， 创业 和 移动互联网2011年10月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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1103.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6312.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1103.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6312.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1695.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6312.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1695.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6312.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2806.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6312.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2806.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6312.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F222.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6312.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F222.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6312.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F340.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6312.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F340.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6312.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>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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/articles/6142.html/comment-page-3#comment-113607" target="_blank">酷壳里评论</a>里说我给一个女程序员的建议不靠谱，我不服，因为我的工作经历中的一些女程序员都很不错，比那些男程序员都强，所以，我在<a href="http://weibo.com/1401880315/xE597iX6J" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/1401880315/xE597iX6J?referer=');">新浪微博</a>和<a href="https://twitter.com/#!/haoel/status/151856699387547649" target="_blank" onclick="pageTracker._trackPageview('/outgoing/twitter.com/_/haoel/status/151856699387547649?referer=');">twitter</a>上征集女程序员的故事和想法，这两天来，我收到了好几封邮件，让我很感动。其中，有一个故事让我回味很久，在脑海里挥之不去，可能是因为她的经历和我很相似，她的想法和我很有共鸣。</p>
<p>本来，我想通过收到的这些故事然后编辑成一篇关于女程序员的文章，但是我觉得这个故事已经足够好了，任何的编辑都是对这个故事的不尊重，所以，我原封不动，一字不改地把这个故事转到这里。我把一些我认为精彩的地方加了粗。</p>
<p>当然，我还是会再写一篇关于女程序员的文章，酷壳2011年底的最后篇文章和2012年的第一篇文章都是给女程序员的，因为，我为你们骄傲！</p>
<p style="padding-left: 30px;"><span style="color: #000000;">从哪里说起呢，我的程序员之路。有些话只是自己心里想的很明白，还从没说过。希望你有耐心看完，因为我的故事不精彩，也算不上奋斗史。我的文笔和叙事能力也很差。</span></p>
<p style="padding-left: 30px;"><span style="color: #000000;">高中报志愿的时候坚定的报了计算机技术及应用，当时对计算机的认识只是机房里的苹果机，和老师教的用basic 输出一个正方形之类的。 我当时觉得我对计算机一无所知，我想了解他，就选择了这个专业，当然当时程序员的收入也是可观的。 ：）</span></p>
<p style="padding-left: 30px;"><span style="color: #000000;">大学四年下来，我的成绩不好，基础也不好，没拿过奖学金。大学的课程很多不喜欢，我不知道为什么计算机系还要学高等物理，和马列毛邓。这是题外话。说实在的，很多课上的我一头雾水。毕业后找工作不满意，我直接去读了软件工程（考研的专业课成绩没到线）。两年制，一年上课，一年实习。我想给自己的履历上增加一些至少能给我面试机会的经历。（我仔细思考过我成绩不好的原因，心里因素是主要的，高中在重点中学，我不能接受自己不是尖子生的事实，总在想自己为什么这么差，以至于这样的心情影响了我很多年，一直到工作后的几年）</span></p>
<p><span id="more-6312"></span></p>
<p style="padding-left: 30px;"><span style="color: #000000;"><strong>实习的第一家公司是个私企，工作两周后他们不满意辞退了我，沮丧是当然的，我知道我的能力是有差距的。虽然他们没有任何培训，直接拉去干活，起码的业务流程也没给我讲，但是我真的发自内心感谢他们辞了我，让我认清了自己</strong>。其实当时干的就是一些perl 脚本和php的网页开发。</span></p>
<p style="padding-left: 30px;"><span style="color: #000000;">实习的第二家也是私企，给运营商做项目。我参加的是一个工作流项目，用java开发。我当时的java技术仅限书本身的不怎么牢靠基础知识，至于怎么设计这个系统也没有一点概念，终于一个月后我决定退出了。<strong>经过这一个多月，我似乎知道了自己该从哪里开始了。就从java开始吧</strong>。</span></p>
<p style="padding-left: 30px;"><span style="color: #000000;">经同学介绍，去了第三家实习公司，面试的经理对实习生要求不高，让我能有机会实习。做的是银行和证券公司的网站，我主要做前端jsp的页面，同时我也选修了学校请的一位Weblogic的工程师开设的J2EE的课程。总算开始入门了。公司的同事很帮助我，有耐心让我了解了系统后台的架构。后来我随几位去客户那里出差，周末和晚上加班，为了他们临时改的需求。同事说，你一个女生出差一点不发憷啊。其实我一点不觉得累。同组的team lead没事就鞭策我说，你就甘心写code么，不能总是做开发，该为以后想想。但是我当时想法是，我的视野当时有限，还不确定自己能做成什么样子。我在这家公司完成了毕业论文。然后毕业。</span></p>
<p style="padding-left: 30px;"><span style="color: #000000;">毕业找工作，我没有留在实习的公司，我想多试试。找工作的经历不多，我去过联想面试，笔试过了，一面是HR面，题目现在大概还记得，如果有化学家，天文学家，医生，乞丐，孕妇，在一个荒岛上，你只能带走一个，你带走谁呢？分组讨论，得出一致的结论，也要说出自己的结论。 同组有清华的毕业生，真的很自信，她说要带走天文学家。我说，出于人道，我肯定带走孕妇。后来就没了消息。难道医生可以留下照顾孕妇么，还是HR以为我选孕妇是注重家庭的人，没有事业心呢，我觉得这题真的不能说明什么。</span></p>
<p style="padding-left: 30px;"><span style="color: #000000;">之后面试了一家日资企业，一面是很多人一起面，我听了一圈之后，觉得自己有些把握，因为同组的人比我差，看来我运气挺好的。他们之中有本科生，有研究生，都是男生，就我一个女生。问的也挺基础，就是servlet如何工作，写没写过SP，其中有个人问，什么是SP，没人理他，我告诉他是store procedure。面试官是个部长。<strong>后来HR的人过来让我留下二面，说我一面打败了所有男士。</strong>说来惭愧，我真的是运气好，没碰到牛人。二面经理只问了些平常的问题，就过了，于是我来到这家工作。考虑的是，外企多少工作流程上比较规范，也见见日本人是怎么工作的，还有就是自己能力有限，欧美大公司估计是没戏的，我还是从力所能及的开始吧。</span></p>
<p style="padding-left: 30px;"><span style="color: #000000;">日本人工作的风格大家应该有所耳闻，就是喜欢加班，我进公司的第一个项目是代码改造，把VB6.0d code重写为VB.net。 加班到凌晨是常事，另外一个就是team lead的风格是没事也不能早走，也得耗到半夜才行。开始做的真是一点技术含量都没有，都是日本人写好guide，告诉你什么改成什么，别问为什么，不能有异议，他们怎么说你怎么改。弄得我当时都不去思考这里的技术细节，这是我当时犯傻的表现。除了技术本身，还有很多需要学习的。后来陆续做了一些我喜欢的java的项目，用到了sping，hibernate，ibatis, struts, ant等等。还有一些日本人自己开发的框架。每个项目的业务也都不同。在这家工作了三年，我觉得这不是我要的，我的技术提高有限，做的事都是别人设计好，甚至告诉你code应该如何写，而且做事风格不是我想要的。 我想去欧美文化的公司试试。也想做通讯相关的。</span></p>
<p style="padding-left: 30px;"><span style="color: #000000;">同学帮我投简历，我面试一家对欧美的外包企业，一面是本公司的人面，问了项目情况，说了说英语，我准备还算充分，过了，二面是公司的客户面，到公司和客户开电话会议面试，第一次和老美直接对话，我虽说有点紧张，但是还是专心听他的问题，听不清的就让他重复一遍，我现在记得的一个问题是如何写出高效的SQL。面完回家等通知。过了几天我收到了offer。</span></p>
<p style="padding-left: 30px;"><span style="color: #000000;">客户是为运营商提供软硬件服务。我们做的是BOSS系统的一个模块。都是java api。 几乎用到了J2EE中定义的所有组件和java相关的框架。我在这家工作至今。技术从不熟悉到熟悉，业务逻辑从不熟悉到熟悉，都是在开发每个feature和改的defect中慢慢了解的，硕大的系统不允许我一口吃个胖子。<strong>只要脑子里绷根弦就每天都有进步</strong>。加班不是常事，但是也有紧张的时候。 有时候一个defect要跟踪成千上万行代码，你才知道哪里出了问题，这是需要耐心和细心的。给客户的客户做support的时候，<strong>经常被半夜的电话叫醒去看一个现场的问题，我不觉得累和烦，我觉得这是我价值的体现</strong>（当然这不会每天发生）。修复一个defect我会有一点小小的成就感，每天晚上回家方便的话也会看看邮箱，看看有没有紧急的事情。<strong>有的人认为你下班了就没必要再管工作邮箱了，但是我愿意这么做，我觉得这是我职业精神的一部分，也是工作态度</strong>。</span></p>
<p style="padding-left: 30px;"><span style="color: #000000;">偶尔会帮着公司招聘毕业生，有时候会遇到什么简单问题都答不上来的人，我感觉就像看见当初刚毕业的我，临走，我会说一句，没关系，回去好好准备，看看基础知识。</span></p>
<p style="padding-left: 30px;"><span style="color: #000000;">我曾经怀疑过自己是否适合做技术，总觉得自己不如男生，也总在问自己的路在哪。而且没有自信，曾经紧张到，有人看我打字，都紧张的手抖。到现在，我觉得做技术挺好，就像你说的，我清楚的认识自己，我不是技术大牛，就每天写着自己的code，了解业务，挺好，但是不代表我不上进。很多女同学现在都不做技术了，也不写code了，但是我还在做，甚至越来越喜欢，在中国有种普遍的想法是，作几年技术该转去做管理，否则认为你不成功，这是人云亦云的说法。我想我为什么不能一直做技术呢？虽然中国的大环境可能不适合你一直做技术，但是我愿意试试。我不愿意放弃多年来积攒的一点点优势。何况我现在工作上越来越得心应手，<strong>不久前，我收到客户的邀请，他们想让我transfer到美国或者加拿大成为他们的一员，我在等待漫长的人事流程，也有可能会pending。但是我无所谓，我现在自信，知道想要什么。一直做技术，怎么了，不行么？</strong></span></p>
<p style="padding-left: 30px;"><span style="color: #000000;"><strong>谈到男女程序员的问题，有些男人以技术强自居，而少了一点谦逊和工作的严谨。有些技术不强的，有些懒散，得过且过。都是我遇到过真实的人。同组的一个女生来了几个月就比一个来了一年多的男生上手快，这说明什么的，态度和努力是重要的。我更认同的是技术和男女无关，和个人有关，任何以偏概全都是片面的</strong>。</span></p>
<p style="padding-left: 30px;"><span style="color: #000000;">同组的男同事们没有因为我是女性而轻视我，我很感谢他们，在一个team工作，技术是必要条件不是充分条件，合作，交流，态度，遵守流程，任何一个都缺少不了。<strong>如果我只是技术差点，那么我提高的空间是很大的。 多看看书，真的不难</strong>。虽然我可能离amazon或者是google这些企业的要求还有差距，但是那是我的方向<strong>。不过像baidu，腾讯这些流氓公司，给我多少钱也不去，女程序员也是有傲骨的</strong>，虽然也有可能他们看不上我的能力，但是，那又有什么所谓呢。</span></p>
<p style="padding-left: 30px;"><span style="color: #000000;">如果你能看完我这如白开水的文字，很感谢，因为我写的实在太不好了，这些经历普通不过，也证明我是个普通的人，<strong>如果我高中的时候不那么在意自己是不是优秀生，就能放轻松，大学（也在想这些）会有个好成绩，没准我就能如愿的毕业就进欧美大企业，不过那样我可能也少了以上跌入谷底的经历和现在平和的心态，我想后者对我更有意义</strong>。</span></p>
<p style="padding-left: 30px;"><span style="color: #000000;">不用署名，有的话，一个女程序员，哈哈。有错误处，见谅，中午休息，仓促的回顾了这些。技术本身心得有限，我就不班门弄斧了，还需努力。也请不要注我的微薄行号啦。另外我老公也是程序员，我和他能谈些技术和项目上的事情，我想是非女程序员感受不到的乐趣，哈哈哈。</span></p>
<p>看到这里你还不想为她鼓掌吗？</p>
<p>最后，请让我我再次征集——</p>
<p>call 所有的女程序员，我想给你们写一篇blog，希望你们能和我分享你们的程序员的经历和技术心得。你是男程序员也没有问题，也欢迎分享你身边女程员的故事。 大家可以发邮件至：haoel(at)hotmail.com</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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1103.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6312.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1103.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6312.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1695.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6312.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1695.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6312.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2806.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6312.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2806.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6312.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F222.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6312.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F222.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6312.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F340.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6312.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F340.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6312.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>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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月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><li>2011年12月20日 -- <a href="http://coolshell.cn/articles/6142.html" title="三个事和三个问题">三个事和三个问题</a></li><li>2011年11月15日 -- <a href="http://coolshell.cn/articles/5815.html" title="来信， 创业 和 移动互联网">来信， 创业 和 移动互联网</a></li><li>2011年10月25日 -- <a href="http://coolshell.cn/articles/5686.html" title="多些时间能少写些代码">多些时间能少写些代码</a></li><li>2011年10月20日 -- <a href="http://coolshell.cn/articles/5651.html" title="Stay Hungry, Stay Foolish ！！">Stay Hungry, Stay Foolish ！！</a></li><li>2011年09月21日 -- <a href="http://coolshell.cn/articles/5514.html" title="如果你看不见你还能编程吗？">如果你看不见你还能编程吗？</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/6312.html/feed</wfw:commentRss>
		<slash:comments>172</slash:comments>
		</item>
		<item>
		<title>由一个问题到 Resin ClassLoader 的学习</title>
		<link>http://coolshell.cn/articles/6112.html</link>
		<comments>http://coolshell.cn/articles/6112.html#comments</comments>
		<pubDate>Wed, 28 Dec 2011 04:22:55 +0000</pubDate>
		<dc:creator>liuxiaori</dc:creator>
				<category><![CDATA[Java语言]]></category>
		<category><![CDATA[ClassLoader]]></category>
		<category><![CDATA[getResource]]></category>
		<category><![CDATA[getResourceAsStream]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Resin]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=6112</guid>
		<description><![CDATA[（感谢网友 liuxiaori 分享其经历）, 从这个分享我们可以看到什么叫真正的学习。牛！ 背景 某日临近下班，一个同事欲取任何类中获取项目绝对路径，不通过Request方式获取，可是始终获取不到预想的路径。于是晚上回家google了一下，误以为是System.getProperty(“java.class.path”)-未实际进行测试，早上来和同事沟通，提出了使用这个内置方法，结果人家早已验证过，该方法是打印出CLASSPATH环境变量的值。 于是乎，继续google，找到了Class的getResource与getResourceAsStream两个方法。这两个方法会委托给ClassLoader对应的同名方法。以为这样就可以搞定(实际上确实可以搞定)，但验证过程中却发生了奇怪的事情。 软件环境：Windows XP、Resin 3、Tomcat6.0、Myeclipse、JDK1.5 发展 我的验证思路是这样的： 定义一个Servlet，然后在该Servlet中调用Path类的getPath方法，getPath方法返回工程classpath的绝对路径，显示在jsp中。 另外在Path类中，通过Class的getResourceAsStream读取当前工程classpath路径中的a.txt文件，写入到getResource路径下的b.txt。 由于时间匆忙，代码没有好好去组织。大致能看出上述两个功能，很简单不做解释。 在此之前使用main函数测试Path.class.getResource(“/”).getPath()打印出预想的路径为：/D:/work/project/EhCacheTestAnnotation/WebRoot/WEB-INF/classes/ 于是将WEB应用部署到Resin下，运行定义好的Servlet，出乎意料的结果是：/D:/work/resin-3.0.23/webapps/WEB-INF/classes/ 。特别奇怪，怎么会丢掉项目名称：EhCacheTestAnnotation呢？ 还有一点值得注意，getPath方法中使用getResourceAsStream(“/a.txt”)却正常的读到了位于下图的a.txt。 然后写到了如下图的b.txt中。代码中是这样实现的：File file = new File(Path.class.getResource(“/”).getPath()+”/b.txt”);本意是想在a.txt文件目录下入b.txt。结果却和料想的不一样。 请注意，区别还是丢掉了项目名称。 写的比较乱，稍微总结下： 程序中使用ClassLoader的两个方法：getResourceAsStream和getResource。但是事实证明在WEB应用的场景下却得到了不同的结果。大家别误会啊，看名字他们两个方法肯定不一样，这个我知道，但是getResourceAsStream总会获取指定路径下的文件吧，示例中的参数为”/a.txt”，正确读取“/D:/work/resin-3.0.23/webapps/EhCacheTestAnnotation/WEB-INF/classes/ ”下的a.txt，可是将文件写到getResource方法的getPath返回路径的b.txt文件。两个位置的差别在项目名称(EhCacheTestAnnotation)。 这样我暂且得出一个结论：通过getResourceAsStream和getResource两个方法获取的路径是不同的。但是为什么呢？ 于是查看了ClassLoader的源码，贴出getResource和getResourceAsStream的源码。 从代码中看，getResourceAsStream将获取URL委托给了getResource方法。天啊，这是怎么回事儿？由此我彻底迷茫了，百思不得其解。 但是没有因此就放弃，继续回想了一遍整个过程： 在main函数中，测试getResource与getResourceAsStream是完全相同的，正确的。 将其部署到Resin下，导致了getResource与getResourceAsStream获取的路径不一致。 一个闪光点，是不是与web容器有关啊，于是换成Tomcat6.0。OMG，“奇迹”出现了，真的是这样子啊，换成Tomcat就一样了啊！和预想的一致。 在Tomcat下运行结果如下图： 对，这就是我想要的。 因此我对Resin产生了厌恶感，之前也因为在Resin下程序报错，在Tomcat下正常运行而纠结了好久。记得看《松本行弘的程序世界》中对C++中的多继承是这样评价的(大概意思)：多重继承带来的负面影响多数是由于使用不当造成的。是不是因为对Resin使用不得当才使得和Tomcat下得到不同的结果。 最终，在查阅Resin配置文件resin.conf时候在&#60;host-default&#62;标签下发现了这样一段： 其中的compiling-loader很可能与之有关，遂将其注释掉，一切正常。担心是错觉，于是将compiling-loader的path属性改成：webapps/WEB-INF/classes1，然后运行pathServlet，b.txt位置如下图： 确实与compiling-loader有关。 结论 终于通过将&#60;class-loader&#62;标签注释掉，同样可以在Resin中获取“预想”的路径。验证了的确是使用Resin的人出了问题。 疑问 但是没有这样就结束，我继续对getResource的源码进行了跟进，由于能力有限，没有弄清楚getResource的原理。 最终留下了两个疑问： 1、如果追踪到getResource方法的最底层(也许是JVM层面)，它实现的原理是什么？ 2、为何Resin中&#60;class-loader&#62;的配置会对getResource产生影响，但是对getResourceAsStream毫无影响(getResourceAsStream可是将获取路径委托给getResource的啊)。还是这里我理解或者使用错误了？ 本来文章到这里就结束了，本来是想问问牛人的，但是这个问题引起了很多的好奇心，于是我又花了一两周做了下面的调查。 Resin中类加载器 在我了解的ClassLoader是在com.caucho.loader包下，结构请看下图： 图1 图2 从上面两幅图中可以看出，图1是与Jdk有关联的，继承自java.net.URLClassLoader。DynamicClassLoader的注释是这样的： EnvironmentClassLoader又继承了DynamicClassLoader。 图2应该是Resin本身的ClassLoader，其中Loader是一个抽象类，包含了各种子类类加载器。 从两幅图中是看不出Resin自身的Loader体系与继承自JVM的类加载器存在关系，那是不是他们就不存在某种关联呢？其实不是这样子的。请看下面DynamicClassLoader源码的片段： 清楚了吧，这两个Loader分支通过组合的方式协作。 类加载器顺序 既然Resin标准的Loader及其子类以组合的方式嵌入到DynamicClassLoader中，那么在加载一个“资源”时，Loader分支和java.net.URLClassLoader分支的先后顺序是什么样子的呢？ 首先使用下面这段代码，将类加载器名称打印到控制台： 输出的结果为： [...]<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="Resin服务器getResource揭秘" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6335.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6112.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6335.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6112.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/01/05/13442866.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;">Resin服务器getResource揭秘</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="JAVA的字符串拼接与性能" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2235.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6112.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2235.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6112.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/13691753.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;">JAVA的字符串拼接与性能</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="Java EE6 初探" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6112.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6112.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;">Java EE6 初探</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="Java构造时成员初始化的陷阱" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1106.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6112.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1106.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6112.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;">Java构造时成员初始化的陷阱</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="Java书籍Top 10" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F14.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6112.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F14.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6112.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/10437602.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;">Java书籍Top 10</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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>（<font color=#CC0000>感谢网友 liuxiaori 分享其经历</font>）, 从这个分享我们可以看到什么叫真正的学习。牛！</strong></p>
<h4>背景</h4>
<p>某日临近下班，一个同事欲取任何类中获取项目绝对路径，不通过Request方式获取，可是始终获取不到预想的路径。于是晚上回家google了一下，误以为是System.getProperty(“java.class.path”)-未实际进行测试，早上来和同事沟通，提出了使用这个内置方法，结果人家早已验证过，该方法是打印出CLASSPATH环境变量的值。</p>
<p>于是乎，继续google，找到了Class的getResource与getResourceAsStream两个方法。这两个方法会委托给ClassLoader对应的同名方法。以为这样就可以搞定(实际上确实可以搞定)，但验证过程中却发生了奇怪的事情。</p>
<p>软件环境：Windows XP、Resin 3、Tomcat6.0、Myeclipse、JDK1.5</p>
<h4>发展</h4>
<p>我的验证思路是这样的：</p>
<ol>
<li>定义一个Servlet，然后在该Servlet中调用Path类的getPath方法，getPath方法返回工程classpath的绝对路径，显示在jsp中。</li>
<li>另外在Path类中，通过Class的getResourceAsStream读取当前工程classpath路径中的a.txt文件，写入到getResource路径下的b.txt。</li>
</ol>
<p>由于时间匆忙，代码没有好好去组织。大致能看出上述两个功能，很简单不做解释。</p>
<p><span id="more-6112"></span></p>
<pre class="brush: java; title: Path.java; notranslate">
public class Path {
    public String getPath() throws IOException
    {
        InputStream is = this.getClass().getResourceAsStream(&quot;/a.txt&quot;);
        File file = new File(Path.class.getResource(&quot;/&quot;).getPath()+&quot;/b.txt&quot;);
        OutputStream os = new FileOutputStream(file);
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        while ((bytesRead = is.read(buffer, 0, 8192)) != -1) {
            os.write(buffer, 0, bytesRead);
        }
        os.close();
        is.close();
        return this.getClass().getResource(&quot;/&quot;).getPath();
    }
}
</pre>
<pre class="brush: java; title: PathServlet.java; notranslate">
public class PathServlet extends HttpServlet {
    private static final long serialVersionUID = 4443655831011903288L;
    public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException
    {
        Path path = new Path();
        request.setAttribute(&quot;path&quot;, path.getPath());
        PrintWriter out = response.getWriter();
        out.println(&quot;Class.getResource('/').getPath():&quot; + path.getPath());
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException
    {
        doGet(request, response);
    }
}</pre>
<p>在此之前使用main函数测试Path.class.getResource(“/”).getPath()打印出预想的路径为：/D:/work/project/EhCacheTestAnnotation/WebRoot/WEB-INF/classes/</p>
<p>于是将WEB应用部署到Resin下，运行定义好的Servlet，出乎意料的结果是：/D:/work/resin-3.0.23/webapps/WEB-INF/classes/ 。特别奇怪，怎么会丢掉项目名称：EhCacheTestAnnotation呢？</p>
<p>还有一点值得注意，getPath方法中使用getResourceAsStream(“/a.txt”)却正常的读到了位于下图的a.txt。<br />
<img class="aligncenter size-full wp-image-6280" title="resin01" src="http://coolshell.cn/wp-content/uploads/2011/12/resin01.png" alt="" width="547" height="154" /></p>
<p style="text-align: center;">然后写到了如下图的b.txt中。代码中是这样实现的：File file = new File(Path.class.getResource(“/”).getPath()+”/b.txt”);本意是想在a.txt文件目录下入b.txt。结果却和料想的不一样。<br />
<img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2011/12/resin02.png" alt="" width="430" height="119" /></p>
<p>请注意，区别还是丢掉了项目名称。</p>
<p>写的比较乱，稍微总结下：</p>
<p>程序中使用ClassLoader的两个方法：getResourceAsStream和getResource。但是事实证明在WEB应用的场景下却得到了不同的结果。大家别误会啊，看名字他们两个方法肯定不一样，这个我知道，但是getResourceAsStream总会获取指定路径下的文件吧，示例中的参数为”/a.txt”，正确读取“/D:/work/resin-3.0.23/webapps/EhCacheTestAnnotation/WEB-INF/classes/ ”下的a.txt，可是将文件写到getResource方法的getPath返回路径的b.txt文件。两个位置的差别在项目名称(EhCacheTestAnnotation)。</p>
<p>这样我暂且得出一个结论：通过getResourceAsStream和getResource两个方法获取的路径是不同的。但是为什么呢？</p>
<p>于是查看了ClassLoader的源码，贴出getResource和getResourceAsStream的源码。</p>
<pre class="brush: java; title: ; notranslate">
public URL getResource(String name) {
    URL url;
    if (parent != null) {
        url = parent.getResource(name);
    } else {
        url = getBootstrapResource(name);
    }

    if (url == null) {
        url = findResource(name);
    }
    return url;
}

public InputStream getResourceAsStream(String name) {
    URL url = getResource(name);
    try {
        return url != null ? url.openStream() : null;
    } catch (IOException e) {
        return null;
    }
}</pre>
<p>从代码中看，getResourceAsStream将获取URL委托给了getResource方法。天啊，这是怎么回事儿？由此我彻底迷茫了，百思不得其解。</p>
<p>但是没有因此就放弃，继续回想了一遍整个过程：</p>
<ol>
<li>在main函数中，测试getResource与getResourceAsStream是完全相同的，正确的。</li>
<li>将其部署到Resin下，导致了getResource与getResourceAsStream获取的路径不一致。</li>
</ol>
<p>一个闪光点，是不是与web容器有关啊，于是换成Tomcat6.0。OMG，“奇迹”出现了，真的是这样子啊，换成Tomcat就一样了啊！和预想的一致。</p>
<p style="text-align: center;">在Tomcat下运行结果如下图：<br />
<img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2011/12/resin03.png" alt="" width="554" height="107" /></p>
<p>对，这就是我想要的。</p>
<p>因此我对Resin产生了厌恶感，之前也因为在Resin下程序报错，在Tomcat下正常运行而纠结了好久。记得看《松本行弘的程序世界》中对C++中的多继承是这样评价的(大概意思)：多重继承带来的负面影响多数是由于使用不当造成的。是不是因为对Resin使用不得当才使得和Tomcat下得到不同的结果。</p>
<p>最终，在查阅Resin配置文件resin.conf时候在&lt;host-default&gt;标签下发现了这样一段：</p>
<pre class="brush: xml; title: ; notranslate">
&lt;class-loader&gt;
        &lt;compiling-loader path=&quot;webapps/WEB-INF/classes&quot;/&gt;
        &lt;library-loader path=&quot;webapps/WEB-INF/lib&quot;/&gt; 
&lt;/class-loader&gt;</pre>
<p>其中的compiling-loader很可能与之有关，遂将其注释掉，一切正常。担心是错觉，于是将compiling-loader的path属性改成：webapps/WEB-INF/classes1，然后运行pathServlet，b.txt位置如下图：</p>
<p style="text-align: center;"><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2011/12/resin04.png" alt="" width="483" height="93" /></p>
<p>确实与compiling-loader有关。</p>
<h4>结论</h4>
<p>终于通过将&lt;class-loader&gt;标签注释掉，同样可以在Resin中获取“预想”的路径。验证了的确是使用Resin的人出了问题。</p>
<h4>疑问</h4>
<div>
<p>但是没有这样就结束，我继续对getResource的源码进行了跟进，由于能力有限，没有弄清楚getResource的原理。</p>
<p>最终留下了两个疑问：</p>
<p>1、如果追踪到getResource方法的最底层(也许是JVM层面)，它实现的原理是什么？</p>
<p>2、为何Resin中&lt;class-loader&gt;的配置会对getResource产生影响，但是对getResourceAsStream毫无影响(getResourceAsStream可是将获取路径委托给getResource的啊)。还是这里我理解或者使用错误了？</p>
<p>本来文章到这里就结束了，本来是想问问牛人的，但是这个问题引起了很多的好奇心，于是我又花了一两周做了下面的调查。</p>
<h4>Resin中类加载器</h4>
<p>在我了解的<span style="font-family: 'Times New Roman';">ClassLoader</span><span style="font-family: 宋体;">是在</span>com.caucho.loader包下，结构请看下图：<br />
<img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2011/12/resin05.png" alt="图1" width="390" height="810" /><br />
图1<br />
<a href="http://coolshell.cn/wp-content/uploads/2011/12/resin06.png"><img class="aligncenter" src="http://coolshell.cn/wp-content/uploads/2011/12/resin06.png" alt="图2 （点击看大图）" width="677" height="354" /></a><br />
图2</p>
<p>从上面两幅图中可以看出，图1是与Jdk有关联的，继承自java.net.URLClassLoader。DynamicClassLoader的注释是这样的：</p>
<pre class="brush: java; title: ; notranslate">
/**
* Class	loader which checks for changes in class files and automatically
* picks up new jars.
*
* DynamicClassLoaders can be chained creating one virtual class loader.
* From the perspective of the JDK, it's all one classloader.  Internally,
* the class loader chain searches like a classpath.
*/
</pre>
<p>EnvironmentClassLoader又继承了DynamicClassLoader<span style="font-family: 宋体;">。</span></p>
<p>图<span style="font-family: 'Times New Roman';">2</span><span style="font-family: 宋体;">应该是</span><span style="font-family: 'Times New Roman';">Resin</span><span style="font-family: 宋体;">本身的</span><span style="font-family: 'Times New Roman';">ClassLoader</span><span style="font-family: 宋体;">，其中</span><span style="font-family: 'Times New Roman';">Loader</span><span style="font-family: 宋体;">是一个抽象类，包含了各种子类类加载器。</span></p>
<p>从两幅图中是看不出<span style="font-family: 'Times New Roman';">Resin</span><span style="font-family: 宋体;">自身的</span><span style="font-family: 'Times New Roman';">Loader</span><span style="font-family: 宋体;">体系与继承自</span><span style="font-family: 'Times New Roman';">JVM</span><span style="font-family: 宋体;">的类加载器存在关系，那是不是他们就不存在某种关联呢？其实不是这样子的。请看下面</span><span style="font-family: 'Times New Roman';">DynamicClassLoader</span><span style="font-family: 宋体;">源码的片段：</span></p>
<pre class="brush: java; title: ; notranslate">
// List of resource loaders
private ArrayList _loaders = new ArrayList();
private JarLoader _jarLoader;
private PathLoader _pathLoader;
</pre>
<p>清楚了吧，这两个Loader<span style="font-family: 宋体;">分支通过组合的方式协作。</span></p>
<h4>类加载器顺序</h4>
<p>既然<span style="font-family: 'Times New Roman';">Resin</span><span style="font-family: 宋体;">标准的</span><span style="font-family: 'Times New Roman';">Loader</span><span style="font-family: 宋体;">及其子类以组合的方式嵌入到</span><span style="font-family: 'Times New Roman';">DynamicClassLoader</span><span style="font-family: 宋体;">中，那么在加载一个“资源”时，</span><span style="font-family: 'Times New Roman';">Loader</span><span style="font-family: 宋体;">分支和</span><span style="font-family: 'Times New Roman';">java.net.URLClassLoader</span><span style="font-family: 宋体;">分支的先后顺序是什么样子的呢？</span></p>
<p>首先使用下面这段代码，将类加载器名称打印到控制台：</p>
<pre class="brush: java; title: ; notranslate">
ClassLoader loader = PathServlet.class.getClassLoader();
while (loader != null) {
    System.out.println(loader.toString());
    loader = loader.getParent();
}
</pre>
<p>输出的结果为：</p>
<blockquote><p><em>EnvironmentClassLoader[web-app:http://localhost:8080/Test]</em></p>
<p><em><em>EnvironmentClassLoader[web-app:http://localhost:8080]</em></em></p>
<p><em>EnvironmentClassLoader[cluster ]</em></p>
<p><em><em>EnvironmentClassLoader[]</em></em></p>
<p><em>sun.misc.Launcher$AppClassLoader@cac268</em></p>
<p><em>sun.misc.Launcher$ExtClassLoader@1a16869</em></p></blockquote>
<p>额，没有任何一个Resin<span style="font-family: 宋体;">的</span><span style="font-family: 'Courier New';">Loader</span><span style="font-family: 宋体;">被打印出来啊，对头，有就错了。下面就让我们看看</span><span style="font-family: 'Courier New';">DynamicClassLoader</span><span style="font-family: 宋体;">中</span><span style="font-family: 'Courier New';">getResource</span><span style="font-family: 宋体;">的源码来解答。</span></p>
<pre class="brush: java; title: getResource(String name); notranslate">
/**
* Gets the named resource
*
* @param name name of the resource
*/

public URL getResource(String name)
{
    if (_resourceCache == null) {
        long expireInterval = getDependencyCheckInterval();
        _resourceCache = new TimedCache(256, expireInterval);
    }

    URL url = _resourceCache.get(name);
    if (url == NULL_URL)
        return null;
    else if (url != null)
        return url;

    boolean isNormalJdkOrder = isNormalJdkOrder(name);

    if (isNormalJdkOrder) {
    url = getParentResource(name);
    if (url != null)
        return url;
    }

    ArrayList loaders = _loaders;
    for (int i = 0; loaders != null &amp;&amp; i &lt; loaders.size(); i++) {
        Loader loader = loaders.get(i);
        url = loader.getResource(name);

        if (url != null) {
            _resourceCache.put(name, url);
            return url;
        }

    }

    if (! isNormalJdkOrder) {
        url = getParentResource(name);
        if (url != null)
            return url;
    }

    _resourceCache.put(name, NULL_URL);
    return null;
}
</pre>
<p>代码不难懂，我画了一张流程图，不规范，凑合看下。<br />
<img class="aligncenter size-full wp-image-6286" title="resin07" src="http://coolshell.cn/wp-content/uploads/2011/12/resin07.png" alt="" width="326" height="601" /></p>
<h4>总结</h4>
<pre class="brush: java; title: ; notranslate">
boolean isNormalJdkOrder = isNormalJdkOrder(name);
</pre>
<p>这行代码控制着Resin<span style="font-family: 宋体;">类加载的顺序，如果是常规的类加载顺序</span><span style="font-family: 'Courier New';">(</span><span style="font-family: 宋体;">向上代理，原文：</span>Returns true if the class loader should use the normal order, i.e. looking at the parents first.)<span style="font-family: 宋体;">，则先</span>url = getParentResource(name)，后遍历_loaders。否则是按照先遍历_loaders<span style="font-family: 宋体;">再</span>url = getParentResource(name)向上代理。</p>
<p>在我的调试经历中，一直都是先向上代理，后遍历_loaders<span style="font-family: 宋体;">的顺序，未遇到第二种方式。</span></p>
<p>文字对先向上代理，后遍历的顺序做点儿说明：</p>
<ol>
<li>首先使用“最上层”的<em>sun.misc.Launcher$ExtClassLoader@1a16869</em>加载name<span style="font-family: 宋体;">资源，如果找到就返回</span><span style="font-family: 'Courier New';">URL</span><span style="font-family: 宋体;">否则返回</span><span style="font-family: 'Courier New';">null</span></li>
<li>程序返回到<em>sun.misc.Launcher$AppClassLoader@cac268</em>，首先判断父类加载器返回的<span style="font-family: 'Courier New';">url</span><span style="font-family: 宋体;">是否为</span><span style="font-family: 'Courier New';">null</span><span style="font-family: 宋体;">，如果不为</span><span style="font-family: 'Courier New';">null</span><span style="font-family: 宋体;">则返回</span><span style="font-family: 'Courier New';">url</span><span style="font-family: 宋体;">，返回</span><span style="font-family: 'Courier New';">null</span><span style="font-family: 宋体;">。</span></li>
<li><span style="font-family: 宋体;"><em><em><em>EnvironmentClassLoader[]</em></em></em></span></li>
<li>程序返回到<em>EnvironmentClassLoader[cluster ]</em>的getParentResource<span style="font-family: 宋体;">，再返回到</span><span style="font-family: 'Courier New';">getResource</span><span style="font-family: 宋体;">，如果</span><span style="font-family: 'Courier New';">url</span><span style="font-family: 宋体;">不为</span><span style="font-family: 'Courier New';">null</span><span style="font-family: 宋体;">，则直接返回，否则遍历</span>ArrayList&lt;Loader&gt; loaders = _loaders;从各个loader<span style="font-family: 宋体;">中加载</span><span style="font-family: 'Courier New';">name</span><span style="font-family: 宋体;">，如果加载成功，即不为</span><span style="font-family: 'Courier New';">null</span><span style="font-family: 宋体;">，则返回，否则继续遍历，直至遍历完成。</span></li>
<li><em><em>EnvironmentClassLoader[web-app:http://localhost:8080]</em></em>同4</li>
<li><em>EnvironmentClassLoader[web-app:http://localhost:8080/Test]</em>同4</li>
</ol>
<p>OK<span style="font-family: 宋体;">，完事儿，后续还有，准备好好写几篇。</span></p>
<p>本文同时发布于：</p>
<ul>
<li><a href="http://www.oschina.net/question/129471_34225" onclick="pageTracker._trackPageview('/outgoing/www.oschina.net/question/129471_34225?referer=');">http://www.oschina.net/question/129471_34225</a>。</li>
<li><a href="http://www.oschina.net/question/129471_35231#AnchorAnswer143898" onclick="pageTracker._trackPageview('/outgoing/www.oschina.net/question/129471_35231_AnchorAnswer143898?referer=');">http://www.oschina.net/question/129471_35231#AnchorAnswer143898</a></li>
</ul>
</div>
<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="Resin服务器getResource揭秘" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6335.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6112.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6335.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6112.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/01/05/13442866.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;">Resin服务器getResource揭秘</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="JAVA的字符串拼接与性能" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2235.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6112.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2235.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6112.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/13691753.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;">JAVA的字符串拼接与性能</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="Java EE6 初探" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6112.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6112.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;">Java EE6 初探</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="Java构造时成员初始化的陷阱" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1106.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6112.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1106.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6112.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;">Java构造时成员初始化的陷阱</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="Java书籍Top 10" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F14.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6112.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F14.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6112.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/10437602.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;">Java书籍Top 10</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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月05日 -- <a href="http://coolshell.cn/articles/6335.html" title="Resin服务器getResource揭秘">Resin服务器getResource揭秘</a></li><li>2012年01月06日 -- <a href="http://coolshell.cn/articles/6424.html" title="Hash Collision DoS 问题">Hash Collision DoS 问题</a></li><li>2011年10月31日 -- <a href="http://coolshell.cn/articles/5709.html" title="API设计：用流畅接口构造内部DSL">API设计：用流畅接口构造内部DSL</a></li><li>2011年10月14日 -- <a href="http://coolshell.cn/articles/5576.html" title="那些曾伴我走过编程之路的软件">那些曾伴我走过编程之路的软件</a></li><li>2011年08月01日 -- <a href="http://coolshell.cn/articles/5075.html" title="你确信你了解时间吗？">你确信你了解时间吗？</a></li><li>2011年07月18日 -- <a href="http://coolshell.cn/articles/4990.html" title="程序员技术练级攻略">程序员技术练级攻略</a></li><li>2011年06月29日 -- <a href="http://coolshell.cn/articles/4905.html" title="语言的数据亲和力">语言的数据亲和力</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/6112.html/feed</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>CSDN明文口令泄露的启示</title>
		<link>http://coolshell.cn/articles/6193.html</link>
		<comments>http://coolshell.cn/articles/6193.html#comments</comments>
		<pubDate>Thu, 22 Dec 2011 04:08:27 +0000</pubDate>
		<dc:creator>陈皓</dc:creator>
				<category><![CDATA[业界新闻]]></category>
		<category><![CDATA[CSDN]]></category>
		<category><![CDATA[password]]></category>
		<category><![CDATA[口令]]></category>
		<category><![CDATA[安全]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=6193</guid>
		<description><![CDATA[2011年12月21日晚，某计算机专业的大学生寝室，某同学大叫到：“兄弟们，最新的日本XX女星的AV片已经下好，大家快过来看啊，相当精彩啊~~~”，然而，这个寝室里的其它同学似乎没有听到这哥们的呼喊，于是，这哥们又叫了三次，没有人理他，因为大家都在眉飞色舞地谈论着CSDN的明文密码和用户帐号泄露的事情，并在网上查找着下载CSDN那600万的用户数据……上面这个故事是我编的，只是想描述一下昨晚的情形。 其实，CSDN明文密码并不是什么稀奇的事情，我是2000年注册CSDN的吧，当时找回口令的机制就是把口令直接传回来了，这一定是明文了。去年去CSDN参加移动互联网沙龙的时候，范凯和蒋涛说过明文密码的事，不过他们说的是很早以前的事了，而且一笔带过了。1年后的今天，事情又暴了，可见，“出来混的，迟早是要还的”这句话是几近真理的。 我在以前的BLOG里就提到过CSDN的明文密码（在“如何设计用户登录功能”一文）和 帐号泄露（“如何设计自己的口令”） 的事（由此可见，酷壳里的很多文章里的事都应验了，因为我知道“出来混的，迟早是要还的”） （可悲吧？还是程序员的网站呢，明文口令和用户信息泄露有悖于一个程序员网站的称号） 泄露的密码分析 我昨晚下载了www.csdn.net.sql文件，并分析了一下这个文件，经过各种awk, grep, sort, uniq, sed后，下面是我看到的东西： 有近45万的用户使用 123456789 和 12345678 做口令。 有近40万的用户使用自己的生日做口令。 有近15万的用户使用自己的手机号做口令。 有近25万的用户使用自己的QQ号做口令。 设置成弱口令的用户占了590万，也就是那种就算你用MD5或是SHA散列的也能很快就被暴力破解出来的口令。 只有8000多个用户的口令里在8个长度以上，并有大写字母，小写字母，数字，并不在字典表里。 （很好，这回泄露的还不单单只是明文用户密码和用户邮件，还有用户的手机号，生日和QQ号。挺好的） 下面，我们来看一下top 100的口令是什么？（第一列是采用这个密码个数，第二列是密码，我擦 dearbook是什么啊）简单地看了一下，top 一万的口令都很SB。比如什么woshishui, 123abc, aaa123456，01010101，haohaoxuexi，msconfig 相当的2B，还有P@ssw0rd，q1w2e3r4t5，看似文艺，实际很2的口令&#8230;. （可悲吧？还是程序员的网站呢，自己设的口令有悖于一个程序员的称号） 235033 123456789 212751 12345678 76346 11111111 45902 dearbook 34953 00000000 19986 123123123 17791 1234567890 15033 88888888 6995 111111111 5966 147258369 5553 987654321 5459 aaaaaaaa [...]<table class="wumii-related-items" cellspacing="0" cellpadding="2" border="0" width="100%" style="clear: both;">
    
    <tr>
        <td ><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
            <tr>
                <td style="margin: 0 !important; padding: 0 !important; line-height: 20px !important;">
                    <img border="0" src="http://static.wumii.com/images/widget/widget_solidPoint.gif">
                    <a target="_blank" style="text-decoration: none !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2428.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6193.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2428.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6193.html&amp;referer=');">
                        <font size="-1" color="#333333" style="line-height: 1.65em; font-size: 12px !important;">如何管理并设计你的口令</font>
                    </a>
                </td>
            </tr>
            <tr>
                <td style="margin: 0 !important; padding: 0 !important; line-height: 20px !important;">
                    <img border="0" src="http://static.wumii.com/images/widget/widget_solidPoint.gif">
                    <a target="_blank" style="text-decoration: none !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3801.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6193.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3801.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6193.html&amp;referer=');">
                        <font size="-1" color="#333333" style="line-height: 1.65em; font-size: 12px !important;">破解你的口令</font>
                    </a>
                </td>
            </tr>
            <tr>
                <td style="margin: 0 !important; padding: 0 !important; line-height: 20px !important;">
                    <img border="0" src="http://static.wumii.com/images/widget/widget_solidPoint.gif">
                    <a target="_blank" style="text-decoration: none !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2451.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6193.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2451.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6193.html&amp;referer=');">
                        <font size="-1" color="#333333" style="line-height: 1.65em; font-size: 12px !important;">Twitter的禁用口令</font>
                    </a>
                </td>
            </tr>
            <tr>
                <td style="margin: 0 !important; padding: 0 !important; line-height: 20px !important;">
                    <img border="0" src="http://static.wumii.com/images/widget/widget_solidPoint.gif">
                    <a target="_blank" style="text-decoration: none !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3877.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6193.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3877.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6193.html&amp;referer=');">
                        <font size="-1" color="#333333" style="line-height: 1.65em; font-size: 12px !important;">另类UX让你输入强口令</font>
                    </a>
                </td>
            </tr>
            <tr>
                <td style="margin: 0 !important; padding: 0 !important; line-height: 20px !important;">
                    <img border="0" src="http://static.wumii.com/images/widget/widget_solidPoint.gif">
                    <a target="_blank" style="text-decoration: none !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2078.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6193.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2078.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6193.html&amp;referer=');">
                        <font size="-1" color="#333333" style="line-height: 1.65em; font-size: 12px !important;">如何防范密码被破解</font>
                    </a>
                </td>
            </tr>
    
    <tr>
        <td  align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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>2011年12月21日晚，某计算机专业的大学生寝室，某同学大叫到：“兄弟们，最新的日本XX女星的AV片已经下好，大家快过来看啊，相当精彩啊~~~”，然而，这个寝室里的其它同学似乎没有听到这哥们的呼喊，于是，这哥们又叫了三次，没有人理他，因为大家都在眉飞色舞地谈论着CSDN的明文密码和用户帐号泄露的事情，并在网上查找着下载CSDN那600万的用户数据……上面这个故事是我编的，只是想描述一下昨晚的情形。</p>
<p>其实，CSDN明文密码并不是什么稀奇的事情，我是2000年注册CSDN的吧，当时找回口令的机制就是把口令直接传回来了，这一定是明文了。去年去CSDN参加移动互联网沙龙的时候，范凯和蒋涛说过明文密码的事，不过他们说的是很早以前的事了，而且一笔带过了。1年后的今天，事情又暴了，可见，“出来混的，迟早是要还的”这句话是几近真理的。</p>
<p>我在以前的BLOG里就提到过CSDN的明文密码（在“<a title="你会做Web上的用户登录功能吗？" href="http://coolshell.cn/articles/5353.html">如何设计用户登录功能</a>”一文）和 帐号泄露（“<a title="如何管理并设计你的口令" href="http://coolshell.cn/articles/2428.html">如何设计自己的口令</a>”） 的事（<strong>由此可见，酷壳里的很多文章里的事都应验了</strong>，因为我知道“出来混的，迟早是要还的”）</p>
<p>（<strong>可悲吧？还是程序员的网站呢，明文口令和用户信息泄露有悖于一个程序员网站的称号</strong>）</p>
<h4>泄露的密码分析</h4>
<p>我昨晚下载了<a href="http://www.csdn.net.sql" onclick="pageTracker._trackPageview('/outgoing/www.csdn.net.sql?referer=');">www.csdn.net.sql</a>文件，并分析了一下这个文件，经过各种awk, grep, sort, uniq, sed后，下面是我看到的东西：</p>
<ul>
<li>有近45万的用户使用 123456789 和 12345678 做口令。</li>
<li>有近40万的用户使用自己的生日做口令。</li>
<li>有近15万的用户使用自己的手机号做口令。</li>
<li>有近25万的用户使用自己的QQ号做口令。</li>
<li>设置成弱口令的用户占了590万，也就是那种就算你用MD5或是SHA散列的也能很快就被暴力破解出来的口令。</li>
<li>只有8000多个用户的口令里在8个长度以上，并有大写字母，小写字母，数字，并不在字典表里。</li>
</ul>
<p>（很好，这回泄露的还不单单只是明文用户密码和用户邮件，还有用户的手机号，生日和QQ号。挺好的）</p>
<p>下面，我们来看一下top 100的口令是什么？（第一列是采用这个密码个数，第二列是密码，我擦 dearbook是什么啊）简单地看了一下，top 一万的口令都很SB。比如什么woshishui, 123abc, aaa123456，01010101，haohaoxuexi，msconfig 相当的2B，还有<a href="mailto:P@ssw0rd">P@ssw0rd</a>，q1w2e3r4t5，看似文艺，实际很2的口令&#8230;. （<strong>可悲吧？还是程序员的网站呢，自己设的口令有悖于一个程序员的称号</strong>）</p>
<p><span id="more-6193"></span></p>
<p style="padding-left: 30px;">235033 123456789<br />
212751 12345678<br />
76346 11111111<br />
45902 dearbook<br />
34953 00000000<br />
19986 123123123<br />
17791 1234567890<br />
15033 88888888<br />
6995 111111111<br />
5966 147258369<br />
5553 987654321<br />
5459 aaaaaaaa<br />
5145 1111111111<br />
5025 66666666<br />
4435 a123456789<br />
4096 11223344<br />
3667 1qaz2wsx<br />
3649 xiazhili<br />
3610 789456123<br />
3497 password<br />
3281 87654321<br />
3277 qqqqqqqq<br />
3175 000000000<br />
3143 qwertyuiop<br />
3094 qq123456<br />
3077 iloveyou<br />
3061 31415926<br />
2985 12344321<br />
2886 0000000000<br />
2826 asdfghjkl<br />
2797 1q2w3e4r<br />
2580 123456abc<br />
2578 0123456789<br />
2573 123654789<br />
2540 12121212<br />
2515 qazwsxedc<br />
2396 abcd1234<br />
2380 12341234<br />
2348 110110110<br />
2298 asdasdasd<br />
2243 22222222<br />
2166 123321123<br />
2160 abc123456<br />
2145 123456<br />
2138 a12345678<br />
2113 123456123<br />
2106 a1234567<br />
2100 1234qwer<br />
1989 qwertyui<br />
1986 123456789a<br />
1971 aa123456<br />
1918 asdfasdf<br />
1891 99999999<br />
1859 999999999<br />
1859 123456aa<br />
1854 123456123456<br />
1699 520520520<br />
1656 963852741<br />
1652 741852963<br />
1652 55555555<br />
1589 33333333<br />
1480 qwer1234<br />
1384 asd123456<br />
1339 77777777<br />
1316 qweasdzxc<br />
1285 code8925<br />
1273 11112222<br />
1268 ms0083jxj<br />
1245 zzzzzzzz<br />
1214 111222333<br />
1206 qweqweqwe<br />
1200 3.1415926<br />
1183 123456qq<br />
1148 147852369<br />
1136 521521521<br />
1121 asdf1234<br />
1111 123698745<br />
1109 1123581321<br />
1058 asdfghjk<br />
1054 q1w2e3r4<br />
1038 12345678a<br />
1003 woaini1314<br />
991 1234abcd<br />
988 123qweasd<br />
975 1qazxsw2<br />
967 woaiwojia<br />
920 321321321<br />
910 05962514787<br />
894 123456987<br />
892 kingcom5<br />
882 zxcvbnm123<br />
882 5845201314<br />
853 0987654321<br />
847 wwwwwwww<br />
835 11111111111111111111<br />
805 12345600<br />
783 11235813<br />
777 1q2w3e4r5t<br />
772 10101010<br />
770 123456asd</p>
<h4>老生长谈安全问题</h4>
<p>从酷壳出现开始我就在老生长谈用户安全的东西了，今天借着这个事，大家再去重温一下酷壳的文章吧：</p>
<ul>
<li><a title="Twitter的禁用口令" href="http://coolshell.cn/articles/2451.html">Twitter禁用的口令</a>。看看去吧，一个好的网站应该如何引导用户设置强口令。Apple ID也是这样，需要你输入的口令有大小写，数字，非数字和字母，等等。<strong>今天CSDN的这个列表应该成为各大网站“口令禁用列表”。</strong></li>
</ul>
<ul>
<li>有朋友说，明文口令是巨2的一件事，是的。我可以告诉你，这个明文口令有可能存在于所有国内的网站上，比如：QQ，新浪，人人，开心，天涯……。<strong>对于安全问题，你要做最坏的假设，鲁迅先生说过：“不惮以最坏的恶意来推测中国人”，所以，对于中国的网站你要做如下最坏假设：1）其以明文存我的口令，2）其内部不良员工会把我的信息泄露出去</strong>。不信你可以看看下面的某QQ群里的截图：（<a href="http://weibo.com/1494759712/xDa7tah7E?type=repost" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/1494759712/xDa7tah7E?type=repost&amp;referer=');">看看多玩网明文口令的消息吧</a>，<a href="http://weibo.com/1642471052/xDaC1dEhP?type=repost" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/1642471052/xDaC1dEhP?type=repost&amp;referer=');">再看看这个消息吧</a> QQ邮箱和QQ号的）<img class="aligncenter" title="国内网站的数据库" src="http://ww4.sinaimg.cn/large/63071edagw1doah4id8l4j.jpg" alt="" width="333" height="756" /></li>
</ul>
<ul>
<li>你可能会说用MD5和SHA散列口令就好了，这个只比明文好一点点，因为有rainbow table，国外的号称达到99%覆盖，国内的达到93%覆盖。你加salt也没有用。就算我只能拿得到你的被散列的密码，没有rainbow和salt，我一样可以使用暴力破解，甚至就是尝试一下字典里的密码就可以了。这会非常快的，你可以看看本站的这篇文章“<a title="破解你的口令" href="http://coolshell.cn/articles/3801.html" target="_blank">破解你的口令</a>”，<strong>现在暴力破解MD5和SHA的口令很快的，因为MD5和SHA性能太好了。</strong>所以，你需要看看“<a title="如何防范密码被破解" href="http://coolshell.cn/articles/2078.html" target="_blank">如何防范密码被破解</a>”，其会告诉你加密口令要用一个性能差的算法——bcrypt。（也可以参看<a title="Web开发中需要了解的东西" href="http://coolshell.cn/articles/6043.html">Web开发中需要了解的东西</a>中的<a href="http://codahale.com/how-to-safely-store-a-password/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/codahale.com/how-to-safely-store-a-password/?referer=');">如何安全保存口令一文</a>）</li>
</ul>
<ul>
<li>所以，你有必要地读一读我的这篇“<a title="如何管理并设计你的口令" href="http://coolshell.cn/articles/2428.html">如何管理和设计自己的口令</a>”，不要在同一网站上使用相同的口令，把口令的级别分好的组。自己管理好自己的口令。</li>
</ul>
<ul>
<li> 对于Web用户的安全问题，程序员们一定要看一下 这两篇文章，你要是不看的话，你没有资格开发Web项目。</li>
<ul>
<li><a title="你会做Web上的用户登录功能吗？" href="http://coolshell.cn/articles/5353.html">如何设计用户登录功能</a></li>
<li><a title="Web开发中需要了解的东西" href="http://coolshell.cn/articles/6043.html">Web开发中需要了解的东西</a></li>
</ul>
</ul>
<ul>
<li>当你看过 <a title="你会做Web上的用户登录功能吗？" href="http://coolshell.cn/articles/5353.html">如何设计用户登录功能</a> 一文后，你一定会头晕的，所以，我想告诉你，<strong>这种事情最好不要自己干，使用OpenID 和 OAuth吧，人家把这事干到了极致了</strong>。而且这样会带来两个好处：</li>
<ul>
<li><strong>用户不需要自己维护和管理一套新的帐号</strong>。</li>
<li><strong>用户的资料放在国外，从政治上来说是安全的</strong>。（八卦一下：Google总部要求中国谷歌所有开发团队不得在本地保存用户的信息）</li>
</ul>
</ul>
<ul>
<li>再说一点，再说说如何让自己内部的用户数据不会被不良员工外泄。<strong>所有的开发团队都不允许直接操作用户的数据库，只允许通过安全的接口来验证用户，用户信息的数据库中需要对操作者有审计功能，永远不允许不受信的人或操作进行全库扫描</strong>。当然，我相信，国内的开发团队绝对达不到这一步（包括某些银行）。</li>
</ul>
<ul>
<li>再说一下，<strong><span style="color: #000000;">真正的安全系统是协同整个社会的安全系统做出来的一道安全长城，而不是什么都要自己搞</span>。</strong>比如：通过很多方法“耦合”和银行和电信其是别的第三方的安全策略，比如，让用户绑定邮箱，绑定手机，绑定信用卡等。</li>
</ul>
<p>最后说一下，CSDN在这次事件的表现看上去还是很不错的，道歉也很诚恳，<strong>但是，我还是希望CSDN反思一下为什么数据库会泄露了？内部有不良员工？还是系统不安全被黑？不要只是诚恳道歉，还要找自己的原因。其它的网站可能就很恶劣了。包括新浪，人人，开心等，最恶心的就是腾讯，你说他的安全有问题，他还找一堆人来骂你。</strong></p>
<p style="text-align: center;"><span style="color: #cc0000; font-size: 16pt; font-family: 'Microsoft YaHei';"><strong>祝大家新年快乐！</strong></span></p>
<p>（全文完）</p>
<table class="wumii-related-items" cellspacing="0" cellpadding="2" border="0" width="100%" style="clear: both;">
    
    <tr>
        <td ><b><font size="-1"  style="display: block !important; padding: 20px 0 5px !important;">您可能也喜欢：</font></b></td>
    </tr>
    
            <tr>
                <td style="margin: 0 !important; padding: 0 !important; line-height: 20px !important;">
                    <img border="0" src="http://static.wumii.com/images/widget/widget_solidPoint.gif">
                    <a target="_blank" style="text-decoration: none !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2428.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6193.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2428.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6193.html&amp;referer=');">
                        <font size="-1" color="#333333" style="line-height: 1.65em; font-size: 12px !important;">如何管理并设计你的口令</font>
                    </a>
                </td>
            </tr>
            <tr>
                <td style="margin: 0 !important; padding: 0 !important; line-height: 20px !important;">
                    <img border="0" src="http://static.wumii.com/images/widget/widget_solidPoint.gif">
                    <a target="_blank" style="text-decoration: none !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3801.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6193.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3801.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6193.html&amp;referer=');">
                        <font size="-1" color="#333333" style="line-height: 1.65em; font-size: 12px !important;">破解你的口令</font>
                    </a>
                </td>
            </tr>
            <tr>
                <td style="margin: 0 !important; padding: 0 !important; line-height: 20px !important;">
                    <img border="0" src="http://static.wumii.com/images/widget/widget_solidPoint.gif">
                    <a target="_blank" style="text-decoration: none !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2451.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6193.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2451.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6193.html&amp;referer=');">
                        <font size="-1" color="#333333" style="line-height: 1.65em; font-size: 12px !important;">Twitter的禁用口令</font>
                    </a>
                </td>
            </tr>
            <tr>
                <td style="margin: 0 !important; padding: 0 !important; line-height: 20px !important;">
                    <img border="0" src="http://static.wumii.com/images/widget/widget_solidPoint.gif">
                    <a target="_blank" style="text-decoration: none !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3877.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6193.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3877.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6193.html&amp;referer=');">
                        <font size="-1" color="#333333" style="line-height: 1.65em; font-size: 12px !important;">另类UX让你输入强口令</font>
                    </a>
                </td>
            </tr>
            <tr>
                <td style="margin: 0 !important; padding: 0 !important; line-height: 20px !important;">
                    <img border="0" src="http://static.wumii.com/images/widget/widget_solidPoint.gif">
                    <a target="_blank" style="text-decoration: none !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2078.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6193.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2078.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6193.html&amp;referer=');">
                        <font size="-1" color="#333333" style="line-height: 1.65em; font-size: 12px !important;">如何防范密码被破解</font>
                    </a>
                </td>
            </tr>
    
    <tr>
        <td  align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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年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><li>2011年03月02日 -- <a href="http://coolshell.cn/articles/3801.html" title="破解你的口令">破解你的口令</a></li><li>2010年05月20日 -- <a href="http://coolshell.cn/articles/2451.html" title="Twitter的禁用口令">Twitter的禁用口令</a></li><li>2010年05月18日 -- <a href="http://coolshell.cn/articles/2428.html" title="如何管理并设计你的口令">如何管理并设计你的口令</a></li><li>2010年02月01日 -- <a href="http://coolshell.cn/articles/2078.html" title="如何防范密码被破解">如何防范密码被破解</a></li><li>2011年01月27日 -- <a href="http://coolshell.cn/articles/3595.html" title="如何“加密”你的email地址">如何“加密”你的email地址</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/6193.html/feed</wfw:commentRss>
		<slash:comments>132</slash:comments>
		</item>
		<item>
		<title>三个事和三个问题</title>
		<link>http://coolshell.cn/articles/6142.html</link>
		<comments>http://coolshell.cn/articles/6142.html#comments</comments>
		<pubDate>Tue, 20 Dec 2011 00:39:41 +0000</pubDate>
		<dc:creator>陈皓</dc:creator>
				<category><![CDATA[职场生涯]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[Job]]></category>
		<category><![CDATA[Programmer]]></category>
		<category><![CDATA[程序员]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=6142</guid>
		<description><![CDATA[从9月份开始，是很多在校毕业生的择业时期，有很多很多朋友写邮件给我让我帮他们参考如何选择工作（对不起我无法在第一时间回信，因为实在是太多了，我那繁忙工作和生活都没办法让我能即时回复），并且还有一个已经工作了多年的技术很强的朋友因为跳槽没有跳好，也和我说了很多他 的感受。从这个过程中让我有了很多感触和想法想和大家分享，本来这篇文章1个月前就想写的，只是要写下来时不知道如何整理这么多的东西和思绪。今天也不知道，但是一定要写了，不然，我的这些感触和想法就会越来越不新鲜了。 注：这篇文章里的所有的故事都是真实的，其不可避免地会加上我强烈的个人情怀和个人色彩，叙述的过程可能比较乱，但我能确保这些都是我的肺腑之言。 第一个事：网友的来信 第一个故事是一个杭州的学生的故事，其有两个offer，一个是北京的（雅虎研发中心），另一个是杭州的一个做商业智能软件的公司，也是美国的上市公司。他在给我的来信内心纠结地说： 雅虎其实很想去，虽然这几年雅虎走下坡，但还是大公司，牌子硬，里面牛人也多，有助于自己水平的提升。但感觉北京环境不好，生活不是那么舒坦，也搞不定户口，所以我去的话也只能干个三五年就得考虑跳槽到别的城市安家落户了。这么一跳，在北京积累的各种资源却又带不走 。 杭州，比北京更适合生活，户口不是问题，朋友多，这个公司也比较宽松，有较多的业余时间跟朋友们一起搞点东西。而且这些年这个公司上升的势头，在国内设研发中心也才4年，规模不大，公司本身规模也还不大，我觉得机会还不错。再加上离家近，对家人大概可以多些照应。 关于未来换工作，雅虎做的是搜索，广告，移动互联这几个方面的，东西在互联网企业里面都比较通用，以后跳槽的话，面相对比较宽。杭州的那个做商业智能的公司，据了解其他做的比较好的也就几个大公司如SAP，IBM有这方面的业务。 我和这个同学发了邮件，也打了长途电话，我基本上是这样回复的—— 1）户口，离家近，安逸的生活，相比起你的人生经历，你的眼界，你的发展，什么都不是。千万不要让户口限制了你的人生，如果要过安逸轻松的生活，最佳方案是进政府部门，既然要活在体制外，就一定是靠能力，靠经历，一定要有好的经历和能力。 2）眼界，眼界，眼界。这是我们这个国家里的人最需要的东西了，你的眼界决定了你的人生。我对杭州的这家公司一无所知，但是我知道雅虎的一些好处：a）互联网企业，其天地明显要比BI广阔很多，b）技术强，能人多（看雅虎的面试的难度以及一些产品就知道了），c）外企，可以练英语。d) 跨国公司，可以开眼界，或许会有出国机会。e）北京，几乎所有的知名公司都在这里有基地，这里的技术氛围在全国数一数二。为了经历和眼界，辛苦几年又有何妨？！人生还是需要有激情的。 3）经历，经历，经历。问自己一下，我们会在毕业的第一份工作呆上一辈子吗？不会吧。就算不喜欢北京，就算雅虎这个公司并不完美，但是雅虎的经历，能为你开启一个更为广阔的天地。 4）我认为一个有过几乎失败经历的公司会更牛。Apple被打趴下过，Amazon也被打趴下过，只有被打趴下过而又能站起来的公司和人才是真正伟大的。如果Yahoo还能站起来，它一定会是一个伟大的公司。 小伙子是个很聪明的人，也是个对生活有激情的人，所以，最后毁了“三方”选择了雅虎。他说： 最终选择雅虎的原因是，我觉得趁早年轻先出去看看，北京还是一个开阔视野的好地方。我要是一开始就选择杭州，以后估计不太会出去了，人生短暂，我还是希望多经历一些多体会一些。我从不畏惧在北京是否有户口，那里的房价是否承受的起，我觉得一个刚毕业的学生没必要太多的考虑这些问题，最重要的是考虑自己的发展。 而我的心情却有些复杂，一方面，我觉得一个人的一生可能就此被我改变了，我的心里很复杂。另一方面，万一他来北京不是很顺怎么办？会不会说我骗了他？在这里，我想对这个朋友说——“保持你的热情，努力开你的眼界，努力提高你的能力，你不可能走得不好的，就算雅虎有一天倒下了，也会有很多个更好机会等着你的，我会一直在你身边帮助你的”。 这样的来信还有很多很多，户口，薪资，是否去大城市，几乎都成了大家考虑的重点。这个年代实在是太浮躁了。我在此想告诉大家，对于你的人生你应该把“和什么样的人做什么样的事”提到你择业优先级最高的地位，没有之一。我的答案是，“和有激情能做事的人做有意义的事”。 生活在如此刺激的年代，一定要去经历那些最刺激最有意义的东西，这样人生才会变得有意义。 第二个事：Amazon的校园招聘 在Amazon校招的其间发生了一些有意思的事，比如： 1）在哈尔滨校招过后，我被公司里的一些同事亲切地称为“体型魁梧的男子”，呵呵。希望这位同学毕业的时候还能来Amazon面试，这样，我就能再“虐你一次”。哈哈。 2）这次Amazon的校招在北京，天津，西安，武汉，哈尔滨等地进行了招聘，大家知道我们用什么面试题来面这些快毕业的学生吗？我们用面试高级程序员的问题来面试这些刚毕业的学生（我和我的团队里的那些高级程序员说：“你们应该庆幸你们面试的时候没有被回这些问题”）。你知道我们有什么样的收获？主要有两点收获： 武汉的学生太给力了。你们的能力超出了所有其它城市的学生，包括北京。这让我们很诧异，搞得我们几个经理都在思考是不是要去武汉建Amazon的研发分部去了。我个人的分析是：武汉属于中心城市和北京等大城市的沟通相当地好，在这里的学生和在北京的学生有一样的眼界和技术氛围，但却没有在大城市的同学们的浮燥，能踏下心来专研技术。 学C++的同学比学Java的同学解决问题的能力更强。因为两个原因，a) C++需要了解系统知识，b) C++的程序员几乎什么事都得自己干。（参看我的《如何学好C语言》和《如何学好C++语言》，当然，Java还是很牛的，比如OO方面） 3）有一个同学接受了Amazon的offer后，给我来信诉说，给他打电话的经理告诉他要做的是测试为主的工作。然后，他给我发邮件来和倾诉，我说，如果你不喜欢，你就要说出来，不要将就，将就出来的人生只会平添许多烦恼和后悔。在此，我想在这里澄清两个事： Amazon不会强行把你分配到团队中，只要你有想去的团队，你就应该说出来。我们一开始会内部做分配，这样做只是为了效率，但是这并不代表你已经被最终分配到那个团队中去了，无法再调整了。只要你提出来你想做什么。我们会把你的要求放在第一位，并尽最大的可能满足你的要求。相信经理们给你们电话的时候都说过这样的内容了。 Amazon所有的“蓝卡员工”（在Amazon工作5年以内的员工）在工作满一年后，可以有条件地在Amazon内部transfer。条件只有一个：你的工作业绩要很不错，在相同级别的员工中是中坚力量。你可以直接申请其它团队的招聘职位（这个其它团队包括了美国总部在内的全世界的团队），经过流程简单的面试就可以正式transfer。没有人可以阻止你，那怕是Jeff Bezos也无权阻止你。（这个政策要比北京户口更有价值吧？！Think it Big!） 4）最后一个有关校园招聘的事发生在我的团队。我觉得我可能要失去这个获得offer的学生了。他在腾讯和亚马逊之间更倾向于腾讯，因为他在腾讯实习过。他一开始的理由主要是，一个是户口问题，腾讯可以解决户口，另一个是他想做底层的C/C++，而不是Java。后面的理由又转变为腾讯的团队文化，等等。 我已经给他打过两次电话了，也和他说过许多，和第一个故事里说得差不多。对于是否做C/C++还是Java这方面的事，他和我说，他想在某一个领域成为一个专家。我对他说的这个专家有些模糊，我只是和他说——“软件的精髓不在于你对系统底层有多了解，也不在语言层面，而是在于设计和架构，而设计和架构这种东西只能靠多想多看”，我和他说，Amazon不是一个喜欢分享的公司，Amazon内部很多技术和设计水平可能是外部的人无法想像的。我希望他能来我的团队和大家工作一段时间真正感受一下，再做打算。（当然，要是他不明白这些事，我也觉得他不来也没有什么可惜的） 另外，我想对所有的人说：“这个世界上有两种公司，一种是“劳动密集型”的公司，另一种是“知识密集型”的公司，很多公司把软件做成了一种“劳动密集型”的活动，在那里永远无法做出能够让业界所震撼的东西，而有的公司才能把其做成“知识密集型”的公司，在那里，你会看到世界因为他们而改变”。如果你不能理解这句话的话，你不妨想像一个网上卖书的的公司干出连Google都赶不上的“平台”（参看“Steve Y的Amazon和Google平台论”），你不妨想像一个做MP3播放器的公司可以改变唱片业乃至改变世界。 不管这位同学最终能不能成选择我的团队的一员，我都会送你一本《Steve Jobs》，额外，我还会送你一件我团队自己制作的T恤（见下图，谢谢我的HR Recruiter当模特）。 第三个事：朋友的跳槽 我有一个普通朋友，几个月前跳槽去了一家正在高薪挖人的国内的快要准备IPO的公司。他们开出的薪水和条件非常地诱人。给我这个朋友的开出薪水和那个职位诱惑力太大了。一般人都很难拒绝。但是，当他入职了以后，他发现了这个公司内有很多东西是相当恶心和让他无法接受的，这个公司就可能连“劳动密集型”的公司都不算，非常发不重视技术，在技术上做的东西相当地不规范，在那里的技术人员不但相当地苦逼，而且干的事相当的垃圾，出了问题，所有的团队都在互相推诿，管理非常混乱。这让我的那个朋友非常地难受，在那里的每一天都是一种煎熬，而且他无法改变，高管也很难改变这种局面。整个公司在一种疯狂地暗无天日的状态下工作。我对这个朋友目前的善感到担忧。 但是，我想借这个事来谈谈我的想法。我承认薪水和职位是一种价值，但是，人生的价值只有这个吗？你一年少了那几万块钱，你也穷不了，你多了那几万块钱，你也富不了，为什么不去追求那些比那几万块钱更有价值的东西呢？对于我来说，我觉得，最有价值的东西就是——能和那些有梦想有追求有能力的人一起去经历那些最有意义的事情，那些能够造福社会、改变世界、创造历史的事情。 我从我的上一份工作到现在的工作，我的薪水不但没怎么涨，只是执平，而我的职位还比上一家公司降了一级（而且我还放弃两年内职位还可能再次晋升的机会），我管的团队从4个团队减到了一个很小的5个人左右的团队（现在我坚持小的团队做大事）。我来Amazon之前，这个事让我整整思考了2个多月。最终我发现，职位和薪水这些对我来说都无所谓，因为我是做事的人，而只有有意义的经历才能真正喂饱我。而我目前在Amazon里做的这个事，是可能改变历史的事，是那种可以让我一想起来就会兴奋的事。 我知道，价值并不仅仅只是名利权，对此我只想说，不要把自己给卖了。 三个问题 其实，我还有很多故事可以讲，只不过我写得太多了，差不多到文章该结束的时候了。那些事改天再说吧。我经历的这些事让我思考了很多很多。每年年底都是我情绪比较低沉的时候，因为，这个时候是我反思一年中的得失的时候，在这个时间段里，我会有一些不安，那种我害怕已经虚度了这一年的那种不安。 2011年的年底，我问了我自己三个问题： 1）每天早上醒过来的时候，我会为什么感到兴奋？是什么在驱动着我去开始新的一天？ 2）现在的经历有没有让我有这种兴奋的感觉？这种让我充满力量和期待的感觉？ 3）有没有浮燥，有没有得到认可？身边的人的认可？但更重要的是自己是否对自己认可？ 我把我自己的这三个问题共享给大家，我有我的答案，相信你也有你的答案。 在2011年的年底，我希望大家的2011年没有虚度，而2012年能经历那些有意义的的事。 提前祝大家新年快乐！ 相关文章2011年11月15日 [...]<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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F340.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6142.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F340.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6142.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1103.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6142.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1103.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6142.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="程序员惯用的解释(Top 25)" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1174.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6142.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1174.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6142.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;">程序员惯用的解释(Top 25)</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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F511.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6142.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F511.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6142.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F222.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6142.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F222.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6142.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.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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>从9月份开始，是很多在校毕业生的择业时期，有很多很多朋友写邮件给我让我帮他们参考如何选择工作（对不起我无法在第一时间回信，因为实在是太多了，我那繁忙工作和生活都没办法让我能即时回复），并且还有一个已经工作了多年的技术很强的朋友因为跳槽没有跳好，也和我说了很多他 的感受。从这个过程中让我有了很多感触和想法想和大家分享，本来这篇文章1个月前就想写的，只是要写下来时不知道如何整理这么多的东西和思绪。今天也不知道，但是一定要写了，不然，我的这些感触和想法就会越来越不新鲜了。</p>
<p><strong>注：这篇文章里的所有的故事都是真实的</strong>，<strong>其不可避免地会加上我<strong><strong><strong>强烈的</strong></strong></strong>个人情怀和个<strong><strong>人色彩</strong></strong></strong>，<strong>叙述的过程可能比较乱，但我能确保这些都是我的肺腑之言</strong>。</p>
<h4>第一个事：网友的来信</h4>
<p>第一个故事是一个杭州的学生的故事，其有两个offer，一个是北京的（雅虎研发中心），另一个是杭州的一个做商业智能软件的公司，也是美国的上市公司。他在给我的来信内心纠结地说：</p>
<blockquote><p>雅虎其实很想去，虽然这几年雅虎走下坡，但还是大公司，牌子硬，里面牛人也多，有助于自己水平的提升。但感觉北京环境不好，生活不是那么舒坦，也搞不定户口，所以我去的话也只能干个三五年就得考虑跳槽到别的城市安家落户了。这么一跳，在北京积累的各种资源却又带不走 。</p>
<p>杭州，比北京更适合生活，户口不是问题，朋友多，这个公司也比较宽松，有较多的业余时间跟朋友们一起搞点东西。而且这些年这个公司上升的势头，在国内设研发中心也才4年，规模不大，公司本身规模也还不大，我觉得机会还不错。再加上离家近，对家人大概可以多些照应。</p>
<p>关于未来换工作，雅虎做的是搜索，广告，移动互联这几个方面的，东西在互联网企业里面都比较通用，以后跳槽的话，面相对比较宽。杭州的那个做商业智能的公司，据了解其他做的比较好的也就几个大公司如SAP，IBM有这方面的业务。</p></blockquote>
<p>我和这个同学发了邮件，也打了长途电话，我基本上是这样回复的——</p>
<p><span id="more-6142"></span></p>
<p style="padding-left: 30px;">1）<strong>户口，离家近，安逸的生活，相比起你的人生经历，你的眼界，你的发展，什么都不是</strong>。千万不要让户口限制了你的人生，如果要过安逸轻松的生活，最佳方案是进政府部门，既然要活在体制外，就一定是靠能力，靠经历，一定要有好的经历和能力。</p>
<p style="padding-left: 30px;">2）<strong>眼界，眼界，眼界</strong>。这是我们这个国家里的人最需要的东西了，你的眼界决定了你的人生。我对杭州的这家公司一无所知，但是我知道雅虎的一些好处：a）互联网企业，其天地明显要比BI广阔很多，b）技术强，能人多（看雅虎的面试的难度以及一些产品就知道了），c）外企，可以练英语。d) 跨国公司，可以开眼界，或许会有出国机会。e）北京，几乎所有的知名公司都在这里有基地，这里的技术氛围在全国数一数二。<strong>为了经历和眼界，辛苦几年又有何妨？！人生还是需要有激情的。</strong></p>
<p style="padding-left: 30px;">3）<strong>经历，经历，经历</strong>。问自己一下，我们会在毕业的第一份工作呆上一辈子吗？不会吧。就算不喜欢北京，就算雅虎这个公司并不完美，但是雅虎的经历，能为你开启一个更为广阔的天地。</p>
<p style="padding-left: 30px;">4）我认为一个有过几乎失败经历的公司会更牛。Apple被打趴下过，Amazon也被打趴下过，<strong>只有被打趴下过而又能站起来的公司和人才是<strong>真正伟大的</strong></strong>。如果Yahoo还能站起来，它一定会是一个伟大的公司。</p>
<p>小伙子是个很聪明的人，也是个对生活有激情的人，所以，最后毁了“三方”选择了雅虎。他说：</p>
<blockquote><p>最终选择雅虎的原因是，我觉得趁早年轻先出去看看，北京还是一个开阔视野的好地方。我要是一开始就选择杭州，以后估计不太会出去了，人生短暂，我还是希望多经历一些多体会一些。我从不畏惧在北京是否有户口，那里的房价是否承受的起，我觉得一个刚毕业的学生没必要太多的考虑这些问题，最重要的是考虑自己的发展。</p></blockquote>
<p>而我的心情却有些复杂，一方面，我觉得一个人的一生可能就此被我改变了，我的心里很复杂。另一方面，万一他来北京不是很顺怎么办？会不会说我骗了他？在这里，我想对这个朋友说——“保持你的热情，努力开你的眼界，努力提高你的能力，你不可能走得不好的，就算雅虎有一天倒下了，也会有很多个更好机会等着你的，我会一直在你身边帮助你的”。</p>
<p>这样的来信还有很多很多，户口，薪资，是否去大城市，几乎都成了大家考虑的重点。这个年代实在是太浮躁了。我在此想告诉大家，对于你的人生你应该把“<strong>和什么样的人做什么样的事</strong>”提到你择业优先级最高的地位，没有之一。我的答案是，“<strong>和有激情能做事的人做有意义的事</strong>”。</p>
<p><strong>生活在如此刺激的年代，一定要去经历那些最刺激最有意义的东西，这样人生才会变得有意义。</strong></p>
<h4>第二个事：Amazon的校园招聘</h4>
<p>在Amazon校招的其间发生了一些有意思的事，比如：</p>
<p>1）在哈尔滨校招过后，我被公司里的一些同事亲切地称为“<a href="http://blog.sina.com.cn/s/blog_65f386930100ytgc.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/blog.sina.com.cn/s/blog_65f386930100ytgc.html?referer=');">体型魁梧的男子</a>”，呵呵。希望这位同学毕业的时候还能来Amazon面试，这样，我就能再“虐你一次”。哈哈。</p>
<p>2）这次Amazon的校招在北京，天津，西安，武汉，哈尔滨等地进行了招聘，大家知道我们用什么面试题来面这些快毕业的学生吗？我们用面试高级程序员的问题来面试这些刚毕业的学生（我和我的团队里的那些高级程序员说：“你们应该庆幸你们面试的时候没有被回这些问题”）。你知道我们有什么样的收获？主要有两点收获：</p>
<ul>
<li><strong>武汉的学生太给力了</strong>。你们的能力超出了所有其它城市的学生，包括北京。这让我们很诧异，搞得我们几个经理都在思考是不是要去武汉建Amazon的研发分部去了。我个人的分析是：<strong>武汉属于中心城市和北京等大城市的沟通相当地好，在这里的学生和在北京的学生有一样的眼界和技术氛围，但却没有在大城市的同学们的浮燥，能踏下心来专研技术</strong>。</li>
</ul>
<ul>
<li><strong>学C++的同学比学Java的同学解决问题的能力更强</strong>。因为两个原因，a) C++需要了解系统知识，b) C++的程序员几乎什么事都得自己干。（参看我的《<a title="如何学好C语言" href="http://coolshell.cn/articles/4102.html" target="_blank">如何学好C语言</a>》和《<a title="如何学好C++语言" href="http://coolshell.cn/articles/4119.html" target="_blank">如何学好C++语言</a>》，当然，Java还是很牛的，比如OO方面）</li>
</ul>
<p>3）有一个同学接受了Amazon的offer后，给我来信诉说，给他打电话的经理告诉他要做的是测试为主的工作。然后，他给我发邮件来和倾诉，我说，<strong>如果你不喜欢，你就要说出来，不要将就，将就出来的人生只会平添许多烦恼和后悔</strong>。在此，我想在这里澄清两个事：</p>
<ul>
<li>Amazon不会强行把你分配到团队中，只要你有想去的团队，你就应该说出来。我们一开始会内部做分配，这样做只是为了效率，但是这并不代表你已经被最终分配到那个团队中去了，无法再调整了。只要你提出来你想做什么。我们会把你的要求放在第一位，并尽最大的可能满足你的要求。相信经理们给你们电话的时候都说过这样的内容了。</li>
</ul>
<ul>
<li>Amazon所有的“蓝卡员工”（在Amazon工作5年以内的员工）在工作满一年后，可以有条件地在Amazon内部transfer。条件只有一个：你的工作业绩要很不错，在相同级别的员工中是中坚力量。你可以直接申请其它团队的招聘职位（这个其它团队包括了美国总部在内的全世界的团队），经过流程简单的面试就可以正式transfer。没有人可以阻止你，那怕是Jeff Bezos也无权阻止你。（这个政策要比北京户口更有价值吧？！Think it Big!）</li>
</ul>
<p>4）最后一个有关校园招聘的事发生在我的团队。我觉得我可能要失去这个获得offer的学生了。他在腾讯和亚马逊之间更倾向于腾讯，因为他在腾讯实习过。他一开始的理由主要是，一个是户口问题，腾讯可以解决户口，另一个是他想做底层的C/C++，而不是Java。后面的理由又转变为腾讯的团队文化，等等。</p>
<p>我已经给他打过两次电话了，也和他说过许多，和第一个故事里说得差不多。对于是否做C/C++还是Java这方面的事，他和我说，他想在某一个领域成为一个专家。我对他说的这个专家有些模糊，我只是和他说——“<strong>软件的精髓不在于你对系统底层有多了解，也不在语言层面，而是在于设计和架构，而设计和架构这种东西只能靠多想多看</strong>”，我和他说，Amazon不是一个喜欢分享的公司，Amazon内部很多技术和设计水平可能是外部的人无法想像的。我希望他能来我的团队和大家工作一段时间真正感受一下，再做打算。（当然，要是他不明白这些事，我也觉得他不来也没有什么可惜的）</p>
<p>另外，我想对所有的人说：“<strong>这个世界上有两种公司，一种是“劳动密集型”的公司，另一种是“知识密集型”的公司，很多公司把软件做成了一种“劳动密集型”的活动，在那里永远无法做出能够让业界所震撼的东西，而有的公司才能把其做成“知识密集型”的公司，在那里，你会看到世界因为他们而改变</strong>”。如果你不能理解这句话的话，你不妨想像一个网上卖书的的公司干出连Google都赶不上的“平台”（参看“<a title="SteveY对Amazon和Google平台的长篇大论" href="http://coolshell.cn/articles/5701.html" target="_blank">Steve Y的Amazon和Google平台论</a>”），你不妨想像一个做MP3播放器的公司可以改变唱片业乃至改变世界。</p>
<p>不管这位同学最终能不能成选择我的团队的一员，我都会送你一本《Steve Jobs》，额外，我还会送你一件我团队自己制作的T恤（见下图，谢谢我的HR Recruiter当模特）。</p>
<p style="text-align: center;"><img class="aligncenter  wp-image-6145" title="Amazon Global Selling" src="http://coolshell.cn/wp-content/uploads/2011/12/amazon_global_selling.jpg" alt="" width="336" height="441" /></p>
<h4>第三个事：朋友的跳槽</h4>
<p>我有一个普通朋友，几个月前跳槽去了一家正在高薪挖人的国内的快要准备IPO的公司。他们开出的薪水和条件非常地诱人。给我这个朋友的开出薪水和那个职位诱惑力太大了。一般人都很难拒绝。但是，当他入职了以后，他发现了这个公司内有很多东西是相当恶心和让他无法接受的，这个公司就可能连“劳动密集型”的公司都不算，非常发不重视技术，在技术上做的东西相当地不规范，在那里的技术人员不但相当地苦逼，而且干的事相当的垃圾，出了问题，所有的团队都在互相推诿，管理非常混乱。这让我的那个朋友非常地难受，在那里的每一天都是一种煎熬，而且他无法改变，高管也很难改变这种局面。整个公司在一种疯狂地暗无天日的状态下工作。我对这个朋友目前的善感到担忧。</p>
<p>但是，我想借这个事来谈谈我的想法。我承认薪水和职位是一种价值，但是，人生的价值只有这个吗？你一年少了那几万块钱，你也穷不了，你多了那几万块钱，你也富不了，为什么不去追求那些比那几万块钱更有价值的东西呢？对于我来说，我觉得，最有价值的东西就是——<strong>能和那些有梦想有追求有能力的人一起去经历那些最有意义的事情，那些能够造福社会、改变世界、创造历史的事情</strong>。</p>
<p>我从我的上一份工作到现在的工作，我的薪水不但没怎么涨，只是执平，而我的职位还比上一家公司降了一级（而且我还放弃两年内职位还可能再次晋升的机会），我管的团队从4个团队减到了一个很小的5个人左右的团队（现在我坚持小的团队做大事）。我来Amazon之前，这个事让我整整思考了2个多月。最终我发现，<strong>职位和薪水这些对我来说都无所谓，因为我是做事的人，而只有有意义的经历才能真正喂饱我</strong>。而我目前在Amazon里做的这个事，是可能改变历史的事，是那种可以让我一想起来就会兴奋的事。</p>
<p><strong>我知道，价值并不仅仅只是名利权，对此我只想说，不要把自己给卖了</strong>。</p>
<h4>三个问题</h4>
<p>其实，我还有很多故事可以讲，只不过我写得太多了，差不多到文章该结束的时候了。那些事改天再说吧。我经历的这些事让我思考了很多很多。每年年底都是我情绪比较低沉的时候，因为，这个时候是我反思一年中的得失的时候，在这个时间段里，我会有一些不安，那种我害怕已经虚度了这一年的那种不安。</p>
<p>2011年的年底，我问了我自己三个问题：</p>
<p style="padding-left: 30px;"><strong>1）每天早上醒过来的时候，我会为什么感到兴奋？是什么在驱动着我去开始新的一天？</strong></p>
<p style="padding-left: 30px;"><strong>2）现在的经历有没有让我有这种兴奋的感觉？这种让我充满力量和期待的感觉？</strong></p>
<p style="padding-left: 30px;"><strong>3）有没有浮燥，有没有得到认可？身边的人的认可？但更重要的是自己是否对自己认可？</strong></p>
<p style="text-align: left;">我把我自己的这三个问题共享给大家，我有我的答案，相信你也有你的答案。</p>
<p style="text-align: center;"><strong>在2011年的年底，我希望大家的2011年没有虚度，而2012年能经历那些有意义的的事。</strong></p>
<p style="text-align: center;"><span style="color: #cc0000; font-size: 16pt; font-family: 'Microsoft YaHei';"><strong>提前祝大家新年快乐！</strong></span></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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F340.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6142.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F340.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6142.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1103.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6142.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1103.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6142.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="程序员惯用的解释(Top 25)" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F1174.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6142.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F1174.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6142.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;">程序员惯用的解释(Top 25)</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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F511.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6142.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F511.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6142.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F222.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6142.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F222.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6142.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.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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年11月15日 -- <a href="http://coolshell.cn/articles/5815.html" title="来信， 创业 和 移动互联网">来信， 创业 和 移动互联网</a></li><li>2010年10月26日 -- <a href="http://coolshell.cn/articles/3231.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><li>2011年12月30日 -- <a href="http://coolshell.cn/articles/6312.html" title="一个女程序员的故事">一个女程序员的故事</a></li><li>2011年10月25日 -- <a href="http://coolshell.cn/articles/5686.html" title="多些时间能少写些代码">多些时间能少写些代码</a></li><li>2011年10月20日 -- <a href="http://coolshell.cn/articles/5651.html" title="Stay Hungry, Stay Foolish ！！">Stay Hungry, Stay Foolish ！！</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/6142.html/feed</wfw:commentRss>
		<slash:comments>239</slash:comments>
		</item>
		<item>
		<title>Web开发中需要了解的东西</title>
		<link>http://coolshell.cn/articles/6043.html</link>
		<comments>http://coolshell.cn/articles/6043.html#comments</comments>
		<pubDate>Wed, 07 Dec 2011 00:29:49 +0000</pubDate>
		<dc:creator>陈皓</dc:creator>
				<category><![CDATA[Web开发]]></category>
		<category><![CDATA[杂项资源]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[SEO]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[安全]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=6043</guid>
		<description><![CDATA[在StackExchange上有人问了这样一个问题：What should every programmer know about web development?（关于Web开发，什么是所有程序员需要知道的？）里面给出的答案非常不错，所以，我翻译转载过来。 顺便说一下，StackExchange真是非常好，大家可以对同一个答案做贡献和修订，看看这个问题的修订过程你就知道了——专业的问答网站应该怎么去做。这就是我在这篇文章中也说过真正的用户体验是什么样的。 好了，下面是正文（我对原文做了一些批注，也许不对或有误导，请大家指正） 下面的这些东西可能对于大多数人并不陌生，但是可能会有些东西你以前并没有看过，或是没有完全搞懂，甚至都没有听说过。（陈皓注：我相信当你看完这个列表后，你会觉得对于我国的Web开发有点弱了，还是那句话，表面上的东西永远是肤浅的） 接口和用户体验 小心浏览器的实现标准上的不一致，确信让你的网站能够适当地跨浏览器。至少，你的网站需要测试一下下面的浏览器： 最新的 Gecko 引擎 (Firefox)， 一个 Webkit 引擎 (Safari, Chrome, 或是其它的移动设备上的浏览器)  IE 浏览器 (测试IE的兼容性你可以使用微软IE的 Application Compatibility VPC Images)  Opera 浏览器。 最后，你可以使用一下这个工具 来看看你的网页在不同的浏览器下是怎么被显示出来的（陈皓注：这个工具就是以前本站介绍过的在不同浏览器和平台上检查你的网站的兼容性） 多考虑一下人们是怎么来访问你的网站而不是那些主流的浏览器：手机，读屏软件和搜索引擎，例如：一些Accessibility的东西： WAI 和  Section508, 移动设备开发：MobiForge. 部署Staging：怎么部署网站的更新而不会影响用户的访问。 Ed Lucas的答案 可以让你了解一些（陈皓注：Ed说了一些如版本控制，自动化build，备份，回滚等机制）。 千万不要直接给用户显示不友好的错误信息。 千万不要把用户的邮件地址以明文显示出来，这样会被爬虫爬走并被让用户的邮箱被垃圾邮件搞死。 为用户的链接加上 rel="nofollow" 的属性以 避免垃圾网站的干扰。（陈皓注：nofollow是HTML的一个属性，用于通知搜索引擎“这个链接所指向的网页非我所能控制，对其内容不予置评”，或者简单地说，该链接不是对目标网站或网页的“投票”，这样搜索引擎不会再访问这个链接。这个是用来减少一些特定垃圾页面对原网站的影响，从而可以改善搜索结果的质量，并且防止垃圾链接的蔓延。） 为网站建立一些的限制 - 这个属于安全性的范畴。（陈皓注：比如你在Google注册邮箱时，你一口气注册超过两个以上的邮箱，gmail要求给你发短信或是给你打电话认证，比如Discuz论坛的会限制你发贴或是搜索的间隔时间等等，更多的网站会用CAPTCHA来确认是人为的操作。 这些限制都是为了防止垃圾和恶意攻击） 学习如何做 Progressive Enhancement. （陈皓注：Progressive Enhancement是一个Web Design的理念，如：1）基础的内容和功能应该可以被所有的浏览器存取，2）页面布局的应该使用外部的CSS链接，3）Javascript也应该是外部链接还应该是 unobtrusive 的，4）应该让用户可以设置他们的偏好） 如果POST成功，要在POST方法后重定向网址，这样可以阻止用户通过刷新页面重复提交。 严重关注Accessibility。因为这是法律上的需求（陈皓注：Section 508是美国的508法案，其是美国劳工复健法的改进，它是一部联邦法律，这个法律要求所有技术要考虑到残障人士的应用，如果某个大众信息传播网站，如果某些用户群体（如残疾人）浏览该网站获取信息时，如果他们无法正常获得所期望的信息（如无法正常浏览），那可以依据相关法规，可以对该网站依法起诉）。 WAI-ARIA 为这方面的事提供很不错的资源. 安全 在网上有很多关于安全的文章，但是 OWASP 开发指导 涵盖了几乎所有关于Web站点安全的东西。（陈皓注：OWASP(开放Web应用安全项目- Open Web Application Security Project)是一个开放的非营利性组织，目前全球有130个分会近万名会员，其主要目标是研议协助解决Web软体安全之标准、工具与技术文件，长期 致力于协助政府或企业了解并改善网页应用程式与网页服务的安全性。OWASP被视为Web应用安全领域的权威参考。2009年下列发布的美国国家和国际立法、标准、准则、委员会和行业实务守则参考引用了OWASP。美国联邦贸易委员会(FTC)强烈建议所有企业需遵循OWASP十大WEB弱点防护守则） 了解什么是 SQL [...]<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="开源中最好的Web开发的资源" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F4795.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6043.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F4795.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6043.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>
                <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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3684.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6043.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3684.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6043.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/28/26059387.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;">Web开发人员速查卡</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+ Web下拉菜单" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3207.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6043.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3207.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6043.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/13665743.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+ Web下拉菜单</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="50套Web开发图标" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6043.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6043.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;">50套Web开发图标</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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2574.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6043.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2574.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6043.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/13669111.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;">如何在低速率网络中测试 Web 应用</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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>在StackExchange上有人问了这样一个问题：<a href="http://programmers.stackexchange.com/questions/46716/what-should-every-programmer-know-about-web-development" target="_blank" onclick="pageTracker._trackPageview('/outgoing/programmers.stackexchange.com/questions/46716/what-should-every-programmer-know-about-web-development?referer=');">What should every programmer know about web development?</a>（关于Web开发，什么是所有程序员需要知道的？）里面给出的答案非常不错，所以，我翻译转载过来。 顺便说一下，StackExchange真是非常好，大家可以对同一个答案做贡献和修订，看看这个问题的<a href="http://programmers.stackexchange.com/posts/46760/revisions" target="_blank" onclick="pageTracker._trackPageview('/outgoing/programmers.stackexchange.com/posts/46760/revisions?referer=');">修订过程</a>你就知道了——专业的问答网站应该怎么去做。这就是我在这篇文章中也说过<a title="腾讯，竞争力 和 用户体验" href="http://coolshell.cn/articles/5901.html" target="_blank">真正的用户体验是什么样的</a>。</p>
<p>好了，下面是正文（我对原文做了一些批注，也许不对或有误导，请大家指正）</p>
<p>下面的这些东西可能对于大多数人并不陌生，但是可能会有些东西你以前并没有看过，或是没有完全搞懂，甚至都没有听说过。（陈皓注：我相信当你看完这个列表后，你会觉得对于我国的Web开发有点弱了，还是那句话，表面上的东西永远是肤浅的）</p>
<h4><strong>接口和用户体验</strong></h4>
<ul>
<li>小心浏览器的实现标准上的不一致，确信让你的网站能够适当地跨浏览器。至少，你的网站需要测试一下下面的浏览器：</li>
<ul>
<li>最新的 <a href="http://en.wikipedia.org/wiki/Gecko_%28layout_engine%29" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Gecko_28layout_engine_29?referer=');">Gecko</a> 引擎 (<a href="http://firefox.com/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/firefox.com/?referer=');">Firefox</a>)，</li>
<li>一个 Webkit 引擎 (<a href="http://www.apple.com/safari/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.apple.com/safari/?referer=');">Safari</a>, <a href="http://www.google.com/chrome" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.google.com/chrome?referer=');">Chrome</a>, 或是其它的移动设备上的浏览器)</li>
<li> <a href="http://en.wikipedia.org/wiki/Internet_Explorer" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Internet_Explorer?referer=');">IE 浏览器</a> (测试IE的兼容性你可以使用微软IE的 <a href="http://www.microsoft.com/Downloads/details.aspx?FamilyID=21eabb90-958f-4b64-b5f1-73d0a413c8ef&amp;displaylang=en" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.microsoft.com/Downloads/details.aspx?FamilyID=21eabb90-958f-4b64-b5f1-73d0a413c8ef_amp_displaylang=en&amp;referer=');">Application Compatibility VPC Images</a>)</li>
<li> <a href="http://www.opera.com/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.opera.com/?referer=');">Opera</a> 浏览器。</li>
</ul>
</ul>
<p style="padding-left: 30px;">最后，你可以使用一下<a href="http://www.browsershots.org/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.browsershots.org/?referer=');">这个工具</a> 来看看你的网页在不同的浏览器下是怎么被显示出来的（陈皓注：这个工具就是以前本站介绍过的<a title="如何检查网页浏览器的兼容性" href="http://coolshell.cn/articles/757.html" target="_blank">在不同浏览器和平台上检查你的网站的兼容性</a>）</p>
<ul>
<li>多考虑一下人们是怎么来访问你的网站而不是那些主流的浏览器：手机，读屏软件和搜索引擎，例如：一些Accessibility的东西： <a href="http://www.w3.org/WAI/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.w3.org/WAI/?referer=');">WAI</a> 和  <a href="http://www.section508.gov/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.section508.gov/?referer=');">Section508</a>, 移动设备开发：<a href="http://mobiforge.com/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/mobiforge.com/?referer=');">MobiForge</a>.</li>
</ul>
<ul>
<li>部署Staging：怎么部署网站的更新而不会影响用户的访问。 <a href="http://programmers.stackexchange.com/questions/46716/what-should-a-developer-know-before-building-a-public-web-site/46738#46738" onclick="pageTracker._trackPageview('/outgoing/programmers.stackexchange.com/questions/46716/what-should-a-developer-know-before-building-a-public-web-site/46738_46738?referer=');">Ed Lucas的答案</a> 可以让你了解一些（陈皓注：Ed说了一些如版本控制，自动化build，备份，回滚等机制）。</li>
</ul>
<ul>
<li>千万不要直接给用户显示不友好的错误信息。</li>
</ul>
<div><span id="more-6043"></span></div>
<ul>
<li>千万不要把用户的邮件地址以明文显示出来，这样会被爬虫爬走并被让用户的邮箱被垃圾邮件搞死。</li>
</ul>
<ul>
<li>为用户的链接加上 <code>rel="nofollow"</code> 的属性以 <a href="http://en.wikipedia.org/wiki/Nofollow" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Nofollow?referer=');">避免垃圾网站的干扰</a>。（陈皓注：<strong>nofollow</strong>是HTML的一个属性，用于通知搜索引擎“这个链接所指向的网页非我所能控制，对其内容不予置评”，或者简单地说，该链接不是对目标网站或网页的“投票”，这样搜索引擎不会再访问这个链接。这个是用来减少一些特定垃圾页面对原网站的影响，从而可以改善搜索结果的质量，并且防止垃圾链接的蔓延。）</li>
</ul>
<ul>
<li><a href="http://www.codinghorror.com/blog/archives/001228.html" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.codinghorror.com/blog/archives/001228.html?referer=');">为网站建立一些的限制</a> - 这个属于安全性的范畴。（陈皓注：比如你在Google注册邮箱时，你一口气注册超过两个以上的邮箱，gmail要求给你发短信或是给你打电话认证，比如Discuz论坛的会限制你发贴或是搜索的间隔时间等等，更多的网站会用CAPTCHA来确认是人为的操作。 这些限制都是为了防止垃圾和恶意攻击）</li>
</ul>
<ul>
<li>学习如何做 <a href="http://en.wikipedia.org/wiki/Progressive_enhancement" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Progressive_enhancement?referer=');">Progressive Enhancement</a>. （陈皓注：<a href="http://en.wikipedia.org/wiki/Progressive_enhancement" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Progressive_enhancement?referer=');">Progressive Enhancement</a>是一个Web Design的理念，如：1）基础的内容和功能应该可以被所有的浏览器存取，2）页面布局的应该使用外部的CSS链接，3）Javascript也应该是外部链接还应该是 <a title="Unobtrusive JavaScript" href="http://en.wikipedia.org/wiki/Unobtrusive_JavaScript" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Unobtrusive_JavaScript?referer=');">unobtrusive</a> 的，4）应该让用户可以设置他们的偏好）</li>
</ul>
<ul>
<li>如果POST成功，要<a href="http://en.wikipedia.org/wiki/Post/Redirect/Get" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Post/Redirect/Get?referer=');">在POST方法后重定向网址</a>，这样可以阻止用户通过刷新页面重复提交。</li>
</ul>
<ul>
<li>严重关注Accessibility。因为这是<a href="http://www.section508.gov/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.section508.gov/?referer=');">法律上的需求</a>（陈皓注：Section 508是美国的508法案，其是美国劳工复健法的改进，它是一部联邦法律，这个法律要求所有技术要考虑到残障人士的应用，如果某个大众信息传播网站，如果某些用户群体（如残疾人）浏览该网站获取信息时，如果他们无法正常获得所期望的信息（如无法正常浏览），那可以依据相关法规，可以对该网站依法起诉）。 <a href="http://www.w3.org/WAI/intro/aria" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.w3.org/WAI/intro/aria?referer=');">WAI-ARIA</a> 为这方面的事提供很不错的资源.</li>
</ul>
<h4><strong>安全</strong></h4>
<ul>
<li>在网上有很多关于安全的文章，但是 <a href="http://www.owasp.org/index.php/Category%3aOWASP_Guide_Project" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.owasp.org/index.php/Category_3aOWASP_Guide_Project?referer=');">OWASP 开发指导</a> 涵盖了几乎所有关于Web站点安全的东西。（陈皓注：OWASP(开放Web应用安全项目- Open Web Application Security Project)是一个开放的非营利性组织，目前全球有130个分会近万名会员，其主要目标是研议协助解决Web软体安全之标准、工具与技术文件，长期 致力于协助政府或企业了解并改善网页应用程式与网页服务的安全性。OWASP被视为Web应用安全领域的权威参考。2009年下列发布的美国国家和国际立法、标准、准则、委员会和行业实务守则参考引用了OWASP。美国联邦贸易委员会(FTC)强烈建议所有企业需遵循OWASP十大WEB弱点防护守则）</li>
</ul>
<ul>
<li>了解什么是 <a href="http://en.wikipedia.org/wiki/SQL_injection" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/SQL_injection?referer=');">SQL 注入攻击</a> 并知道怎么阻止这种攻击。</li>
</ul>
<ul>
<li>永远不要相信用户的输入（包括Cookies，因为那也是用户的输入）</li>
</ul>
<ul>
<li>对用户的口令进行Hash，并使用salt，以防止Rainbow 攻击（陈皓注：Hash算法可用MD5或SHA1等，对口令使用salt的意思是，user 在设定密码时，system 产生另外一个random string(salt)。在datbase 存的​​是与salt + passwd 产的md5sum 及salt。 当要验证密码时就把user 输入的string 加上使用者的salt，产生md5s​​um 来比对。 理论上用salt 可以大幅度让密码更难破解，相同的密码除非刚好salt 相同，最后​​存在database 上的内容是不一样的。google一下md5+salt你可以看到很多文章。关于<a href="http://en.wikipedia.org/wiki/Rainbow_table" target="_blank" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Rainbow_table?referer=');">Rainbow 攻击</a>，其意思是很像密码字典表，但不同的是，Rainbow Table存的是已经被Hash过的密码了，而且其查找密码的速度更快，这样可以让攻击非常快）。使用慢一点的Hash算法来保存口令，如 bcrypt (被时间检证过了) 或是 scrypt (更强，但是也更新一些) (<a href="http://www.tarsnap.com/scrypt.html" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.tarsnap.com/scrypt.html?referer=');">1</a>, <a href="http://it.slashdot.org/comments.pl?sid=1987632&amp;cid=35149842" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/it.slashdot.org/comments.pl?sid=1987632_amp_cid=35149842&amp;referer=');">2</a>)。你可以阅读一下 <a href="http://codahale.com/how-to-safely-store-a-password/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/codahale.com/how-to-safely-store-a-password/?referer=');">How To Safely Store A Password</a>（陈皓注：酷壳以前曾介绍过<a title="如何防范密码被破解" href="http://coolshell.cn/articles/2078.html" target="_blank">bcrypt这个算法</a>，这里，我更建议我们应该让用户输入比较强的口令，比如Apple ID注册的过程需要用户输入超过8位，需要有大小写和数字的口令，或是做出类似于<a title="另类UX让你输入强口令" href="http://coolshell.cn/articles/3877.html" target="_blank">这样的用户体验的东西</a>）。</li>
</ul>
<ul>
<li><a href="http://stackoverflow.com/questions/1581610/how-can-i-store-my-users-passwords-safely/1581919#1581919" onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/questions/1581610/how-can-i-store-my-users-passwords-safely/1581919_1581919?referer=');">不要试图自己去发明或创造一个自己的fancy的认证系统</a>，你可能会忽略到一些不容易让你查觉的东西而导致你的站点被hack了。（陈皓注：我在<a title="如何设计“找回用户帐号”功能" href="http://coolshell.cn/articles/5987.html" target="_blank">腾讯那坑爹的申诉系统</a>中说过这个事了，我说过这句话——“真正的安全系统是协同整个社会的安全系统做出来的一道安全长城，而不是什么都要自己搞”，当然，很遗憾不是所有的人都能看懂这个事，包括一些资深的人）</li>
</ul>
<ul>
<li>了解 <a href="https://www.pcisecuritystandards.org/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.pcisecuritystandards.org/?referer=');">处理信用卡的一些规则 </a>. (<a href="http://stackoverflow.com/questions/51094/payment-processors-what-do-i-need-to-know-if-i-want-to-accept-credit-cards-on-m" onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/questions/51094/payment-processors-what-do-i-need-to-know-if-i-want-to-accept-credit-cards-on-m?referer=');">这里也有一个问题你可以查看一下</a>) （陈皓注：有两上vendor可以帮助你，一个是 <a href="http://www.authorize.net/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.authorize.net/?referer=');">Authorize.Net</a> 另一个是 <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_payflow-pro-overview-outside" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.paypal.com/cgi-bin/webscr?cmd=_payflow-pro-overview-outside&amp;referer=');">PayFlow Pro</a>）</li>
</ul>
<ul>
<li>使用 <a href="http://www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt?referer=');">SSL</a>/<a href="http://en.wikipedia.org/wiki/Https" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Https?referer=');">HTTPS</a> 来加密传输登录页面或是任可有敏感信息的页面，比如信用卡号等。</li>
</ul>
<ul>
<li>知道如何对付session 劫持。（陈皓注：请参看wikipedia的这<a href="http://en.wikipedia.org/wiki/Session_hijacking" target="_blank" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Session_hijacking?referer=');">Session Hijacking</a>，）</li>
</ul>
<ul>
<li>避免 <a href="http://en.wikipedia.org/wiki/Cross-site_scripting" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Cross-site_scripting?referer=');">跨站脚本攻击</a>(XSS)。（陈皓注：参看酷壳站前几天发的《<a title="新浪微博的XSS攻击" href="http://coolshell.cn/articles/4914.html" target="_blank">新浪微博的XSS攻击事件</a>》）</li>
</ul>
<ul>
<li>避免 <a href="http://en.wikipedia.org/wiki/Cross-site_request_forgery" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Cross-site_request_forgery?referer=');">跨站</a><a href="http://en.wikipedia.org/wiki/Cross-site_request_forgery" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Cross-site_request_forgery?referer=');">伪造</a><a href="http://en.wikipedia.org/wiki/Cross-site_request_forgery" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Cross-site_request_forgery?referer=');">请求攻击 cross site request forgeries</a> (XSRF).</li>
</ul>
<ul>
<li>保持你的系统里的所有软件更新到最新的patch。</li>
</ul>
<ul>
<li>确保你的数据库连接是安全的。</li>
</ul>
<ul>
<li>确保你能了解最新的攻击技术，以及你系统的脆弱处。</li>
</ul>
<ul>
<li>请读一下 <a href="http://code.google.com/p/browsersec/wiki/Main" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/code.google.com/p/browsersec/wiki/Main?referer=');">The Google Browser Security Handbook</a>.</li>
</ul>
<ul>
<li>请读一下 <a href="http://rads.stackoverflow.com/amzn/click/0470170778" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/rads.stackoverflow.com/amzn/click/0470170778?referer=');">The Web Application Hacker&#8217;s Handbook</a>.</li>
</ul>
<ul>
<li>（陈皓注：之前本站的“<a title="一些文章资源和趣闻" href="http://coolshell.cn/articles/5537.html" target="_blank">一些资源</a>”提到过<a href="https://wiki.mozilla.org/WebAppSec/Secure_Coding_Guidelines" target="_blank" onclick="pageTracker._trackPageview('/outgoing/wiki.mozilla.org/WebAppSec/Secure_Coding_Guidelines?referer=');">Mozilla的安全编程规范</a>，还有Ruby on Rails的<a href="http://guides.rubyonrails.org/security.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/guides.rubyonrails.org/security.html?referer=');">Web安全的开发教程</a>）</li>
</ul>
<h4><strong>性能</strong></h4>
<ul>
<li>只要需要，请实现cache机制，了解并合理地使用 <a href="http://www.mnot.net/cache_docs/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.mnot.net/cache_docs/?referer=');">HTTP caching</a> 以及 <a href="http://www.w3.org/TR/html5/offline.html" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.w3.org/TR/html5/offline.html?referer=');">HTML5 Manifest</a>.</li>
</ul>
<ul>
<li>优化页面 —— 不要使用20KB图片来平铺网页背景。（陈皓注：还有很多网页页面优化性的文章，你可以STFG &#8211; Search The Fucking Google一下。如果你要调试的话，你可以使用firebug或是chrome内置的开发人员的工具来查看网页装载的性能）</li>
<li>学习如何 <a title="gzip content" href="http://developer.yahoo.com/performance/rules.html#gzip" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/developer.yahoo.com/performance/rules.html_gzip?referer=');">gzip/deflate 网页</a> (<a href="http://stackoverflow.com/questions/1574168/gzip-vs-deflate-zlib-revisited" onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/questions/1574168/gzip-vs-deflate-zlib-revisited?referer=');">deflate 更好</a>).</li>
</ul>
<ul>
<li>把多个CSS文件和Javascript文件合并成一个，这样可以减少浏览器的网络连数，并且使用gzip压缩被反复用到的文件。</li>
</ul>
<ul>
<li>学习一下 <a href="http://developer.yahoo.com/performance/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/developer.yahoo.com/performance/?referer=');">Yahoo Exceptional Performance</a> 这个网站上的东西，上面有很多非常不错的改善前端性能的指导，以及 <a href="http://developer.yahoo.com/yslow/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/developer.yahoo.com/yslow/?referer=');">YSlow</a> 这个工具。 <a href="http://code.google.com/speed/page-speed/docs/rules_intro.html" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/code.google.com/speed/page-speed/docs/rules_intro.html?referer=');">Google page speed</a> 是另一个用来做性能采样的工具。这两个工具都需要安装 <a href="http://getfirebug.com/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/getfirebug.com/?referer=');">Firebug</a> 。</li>
</ul>
<ul>
<li>为那些小的图片使用 <a href="http://alistapart.com/articles/sprites" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/alistapart.com/articles/sprites?referer=');">CSS Image Sprites</a>，就像工具条一样。 (参看 “最小化 HTTP 请求” ) （陈皓注：把所有的小图片合并成一个图片，然后用CSS把显示其中的一块，这样，这些小图片只用传输一次，酷壳的Wordpress样式的那个RSS订阅列表中的小图标就是这样做的）</li>
</ul>
<ul>
<li>繁忙的网络应该考虑<a href="http://developer.yahoo.com/performance/rules.html#split" target="_blank" onclick="pageTracker._trackPageview('/outgoing/developer.yahoo.com/performance/rules.html_split?referer=');">把网页的内容分开存放</a>在不同的域名下。（陈皓注：比如有专门的图片服务器——图片相当耗带宽，或是专门的Ajax服务器）</li>
</ul>
<ul>
<li>静态网页 (如，图片，CSS，JavaScript，以及一些不需要访问cookies的网页) 应该放在一个<a href="http://blog.stackoverflow.com/2009/08/a-few-speed-improvements/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/blog.stackoverflow.com/2009/08/a-few-speed-improvements/?referer=');">不使用cookies</a>的独立的域名下，因为所有在同一个域名或子域名下的cookie会被这个域名下的请求一同发送。另一个好的选择是使用 Content Delivery Network (CDN).</li>
</ul>
<ul>
<li>使用单个页面的HTTP请求数最小化。</li>
</ul>
<ul>
<li>为Javascript使用 <a href="http://code.google.com/closure/compiler/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/code.google.com/closure/compiler/?referer=');">Google Closure Compiler</a> 或是 <a href="http://developer.yahoo.com/yui/compressor/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/developer.yahoo.com/yui/compressor/?referer=');">其它压缩工具</a>（陈皓注：压缩Javascript代码可以让你的页面减少网络传输从而可以得到很快的喧染。注意，并不是所有的工具都可以正确压缩Javascript的，Google的这个工具甚至还可以帮你优化你的代码）</li>
</ul>
<ul>
<li>确认你的网站有一个 <code>favicon.ico</code> 文件放在网站的根下，如 <code>/favicon.ico</code>. <a href="http://mathiasbynens.be/notes/rel-shortcut-icon" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/mathiasbynens.be/notes/rel-shortcut-icon?referer=');">浏览器会自动请求这个文件</a>，就算这个图标文件没有在你的网页中明显说明，浏览器也会请求。如果你没有这个文件，就会出大量的404错误，这会消耗你的服务器带宽。（陈皓注：服务器返回404页面会比这个ico文件可能还大）</li>
</ul>
<h4><strong>SEO (搜索引擎优化)</strong></h4>
<ul>
<li>使用 “搜索引擎喜欢的” URL，如：使用 <code>example.com/pages/45-article-title</code> 而不是 <code>example.com/index.php?page=45 </code>(陈皓注：这里的URL是说Wordpress的，后者是默认的)</li>
</ul>
<ul>
<li>如果你的动态页面要使用 <code>#</code> ，那么请把其改成 <code>#!</code> ，而在服务端，你需要处理<code>$_REQUEST["_escaped_fragment_"]</code> 这是Google搜索引擎需要的。换句话说，<code>./#!page=1</code> 会被Google搜索引擎转成 <code>./?_escaped_fragments_=page=1。</code> （陈皓注：通常来说URL中的#后的东西都不会被传到服务器上，所以，为了要让Google可以抓取AJAX的东西，你需要使用#!，而Google会把“#!”转成“_escaped_fragment_”来向服务器发请求，Twitter的大量的链接者是#!的，比如：<a href="https://twitter.com/#!/your_activity" onclick="pageTracker._trackPageview('/outgoing/twitter.com/_/your_activity?referer=');">https://twitter.com/#!/your_activity</a>）。另外，用户也许会使用Firefox 或 Chromium， <code>history.pushState({"foo":"bar"}, "About", "./?page=1");</code> 是一个很不错的命令。所以，就算是我们的地址栏上的地址改变了，页面也不会重新装载。这可以让你使用 <code>?</code> 而不是 <code>#!</code> 也能无刷地保住当前的动态的页面，这可以让AJAX的请求被浏览器记住。</li>
</ul>
<ul>
<li>别使用 “click here” 这样的链接。这样一来，无法SEO，而且对于一些需要使用读屏人来说很不友好（陈皓注：关于读屏软件，可参看本站的“<a title="如果你看不见你还能编程吗？" href="http://coolshell.cn/articles/5514.html" target="_blank">如果看不见你还能编程吗</a>”）</li>
</ul>
<ul>
<li>做一个 <a href="http://www.sitemaps.org/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.sitemaps.org/?referer=');">XML sitemap</a>，并放在网端的根下 <code>/sitemap.xml</code>. （陈皓注：这个文件可以让搜索引擎了解你的网站图）</li>
<li>当你有多个URL指向同一个网页的使用，使用 <a href="http://googlewebmastercentral.blogspot.com/2009/02/specify-your-canonical.html" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/googlewebmastercentral.blogspot.com/2009/02/specify-your-canonical.html?referer=');"><code>&lt;link rel="canonical" ... /&gt;</code></a> 你可以使用 <a href="http://www.google.com/webmasters/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.google.com/webmasters/?referer=');">Google Webmaster Tools</a> 来查看相关的问题。</li>
</ul>
<ul>
<li>使用 <a href="http://www.google.com/webmasters/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.google.com/webmasters/?referer=');">Google Webmaster Tools</a> 和 <a href="http://siteexplorer.search.yahoo.com/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/siteexplorer.search.yahoo.com/?referer=');">Yahoo Site Explorer</a>.</li>
</ul>
<ul>
<li>安装 <a href="http://www.google.com/analytics/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.google.com/analytics/?referer=');">Google Analytics</a>  (或是别的开源的网站分析工具，如： <a href="http://piwik.org/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/piwik.org/?referer=');">Piwik</a>).</li>
</ul>
<ul>
<li>了解 <a href="http://en.wikipedia.org/wiki/Robots_exclusion_standard" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Robots_exclusion_standard?referer=');">robots.txt</a> 和搜索引擎爬虫是如何工作的。</li>
</ul>
<ul>
<li>重定向请求 (使用 <code>301 重定向网站</code>) ，如果你要把 <code>www.example.com</code> 定向到 <code>example.com</code>(或是其它的变更) 这样可以防止Google的rank因为域名的变化发生改变。（陈皓注：301重定向一般用作域名变更）</li>
</ul>
<ul>
<li>知道并不是所有的爬虫都是好的，有些爬虫的行为并不好。（陈皓注：比如向你的网站发大量的请求导致服务器性能低下）</li>
</ul>
<ul>
<li>如果你有一些非文本的内容需要在 Google&#8217;s sitemap  中，比如视频什么的。<a href="http://stackoverflow.com/questions/72394/what-should-a-developer-know-before-building-a-public-web-site#167608" onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/questions/72394/what-should-a-developer-know-before-building-a-public-web-site_167608?referer=');">Tim Farley的答案</a>，可以让你看到很多有价值的东西。</li>
</ul>
<h4><strong>技术</strong></h4>
<ul>
<li>理解什么是 <a href="http://www.ietf.org/rfc/rfc2616.txt" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.ietf.org/rfc/rfc2616.txt?referer=');">HTTP</a> 比如 GET, POST, sessions, cookies等，了解什么是 “stateless” 无状态。</li>
</ul>
<ul>
<li>让你的 <a href="http://www.w3.org/TR/xhtml1/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.w3.org/TR/xhtml1/?referer=');">XHTML</a>/<a href="http://www.w3.org/TR/REC-html40/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.w3.org/TR/REC-html40/?referer=');">HTML</a> 和 <a href="http://www.w3.org/TR/CSS2/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.w3.org/TR/CSS2/?referer=');">CSS</a> 符合 <a href="http://www.w3.org/TR/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.w3.org/TR/?referer=');">W3C 规范</a>，并确认他们都是 <a href="http://validator.w3.org/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/validator.w3.org/?referer=');">合格的</a>。我们的目标是避免浏览器的 “quirks mode”，并且可以让其更容易地能和非标准的浏览器工作，比如读屏器或移动设备。</li>
</ul>
<ul>
<li>理解浏览器是怎么处理 JavaScript 的。（陈皓：你会看到有些Javascript代码在页面上前面，有些则是在后面，所以你需要对其了解清楚为什么是这样）</li>
</ul>
<ul>
<li>了解浏览器是怎么装载 JavaScript，CSS和其它资源的，了解其对视觉上的影响。（陈皓注：10年前我做网页的时候因为HTML还很弱，所以只能使用table来布局，使用table布局的问题就是整个table读完后页面才会显示，用户的视觉体验并不好）。在某些情况下，你可能需要<a href="http://developer.yahoo.net/blog/archives/2007/07/high_performanc_5.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/developer.yahoo.net/blog/archives/2007/07/high_performanc_5.html?referer=');">把你的脚本放在页面的后面</a>。</li>
</ul>
<ul>
<li>理解 JavaScript 的 sandbox 是怎么怎么工作的，尤其是你想使用iframes。</li>
</ul>
<ul>
<li>请注意 JavaScript 可能会被禁止，这样会让你的AJAX失效。就算是大多数用户都开启了Javascript功能，但是也可能在一些情况下脚本是不被运行的，比如移动终端上，搜索引擎抓网页的时候也并不会执行你的脚本。</li>
</ul>
<ul>
<li>学习 <a href="http://www.bigoakinc.com/blog/when-to-use-a-301-vs-302-redirect/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.bigoakinc.com/blog/when-to-use-a-301-vs-302-redirect/?referer=');">301 和 302 转向的区别</a> (这也是一个SEO的问题).</li>
</ul>
<ul>
<li>尽可能多地学习你的部署平台。（比如：操作系统，Web Server：Apache/Nginx，防火墙，数据库，等等）</li>
</ul>
<ul>
<li>考虑使用一个 <a href="http://stackoverflow.com/questions/167531/is-it-ok-to-use-a-css-reset-stylesheet" onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/questions/167531/is-it-ok-to-use-a-css-reset-stylesheet?referer=');">Reset Style Sheet</a>.</li>
</ul>
<ul>
<li>考虑使用 JavaScript 框架(如： <a href="http://jquery.com/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/jquery.com/?referer=');">jQuery</a>, <a href="http://mootools.net/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/mootools.net/?referer=');">MooTools</a>, <a href="http://www.prototypejs.org/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/www.prototypejs.org/?referer=');">Prototype</a>, <a href="http://dojotoolkit.org/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/dojotoolkit.org/?referer=');">Dojo</a> 或 <a href="http://developer.yahoo.com/yui/3/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/developer.yahoo.com/yui/3/?referer=');">YUI 3</a>)，它们会很好的兼容于不同的浏览器。（陈皓注：强烈推荐你看一下本站的<a title="开源中最好的Web开发的资源" href="http://coolshell.cn/articles/4795.html" target="_blank">开源中最好的WEB开发资源</a>一文）</li>
</ul>
<ul>
<li>把视觉效果和JS框架合在一起讨论，考虑使用一个Service，如：<a href="http://code.google.com/apis/libraries/devguide.html" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/code.google.com/apis/libraries/devguide.html?referer=');">Google Libraries API</a> 来装载框架，这样可以让浏览器可能早就把这个JS框架已经cache了而不需要再从你的网站上下载了。</li>
</ul>
<h4><strong>Bug fixing</strong></h4>
<ul>
<li>明白你会花20%的时间写代码，而80%的时候在维护，所以你要小心编码。（陈皓注：参看本站的“<a title="多些时间能少写些代码" href="http://coolshell.cn/articles/5686.html" target="_blank">多些时间可以少些代码</a>”一文）</li>
</ul>
<ul>
<li>设计一个好的错误报告机制。</li>
</ul>
<ul>
<li>设计一个入口可以让人们联系到你并给你建议和批评。</li>
</ul>
<ul>
<li>为你开发的东西形成文档，这样可以让后来的人容易维护你的软件和系统。</li>
</ul>
<ul>
<li>频繁备份（也可确保你的这些备份功能正常） <a href="http://stackoverflow.com/questions/72394/what-should-a-developer-know-before-building-a-public-web-site#73970" onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/questions/72394/what-should-a-developer-know-before-building-a-public-web-site_73970?referer=');">Ed Lucas 的回答</a> 有一些忠告。你还需要有一个恢复策略，而不只是一个备份策略。</li>
</ul>
<ul>
<li>使用一个版本控制系统来保存你的代码，如： <a href="http://subversion.apache.org/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/subversion.apache.org/?referer=');">Subversion</a> 或 <a href="http://git-scm.org/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/git-scm.org/?referer=');">Git</a>.</li>
</ul>
<ul>
<li>别忘了做Acceptance Testing，使用 <a href="http://seleniumhq.org/" rel="nofollow" onclick="pageTracker._trackPageview('/outgoing/seleniumhq.org/?referer=');">Selenium</a> 能帮到你。</li>
</ul>
<ul>
<li>确保你有足够的日志，你可以使用 log4j, log4n 或 log4r。如果出了问题，这是可以让你快速找到问题的方式。</li>
</ul>
<ul>
<li>当你写日志的时候，确保你记录了你捕获了处理和未处理异常。报告和分析日志可以让你知道你网站的问题。</li>
</ul>
<p>这里有多的东西被省略了，并不是因为那些可能不是有帮助的答案，而是因为那些东西都太细节了，超出了这个问题的范围，因为这本来就是一个Web开发需要了解东西的Overview。我想你可以去看一下其它人的答案，我有时间，我也会补充别人的答案进来。请随意编辑这个答案，因为可能有些东西忘了，也有可能有些东西不对。</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="开源中最好的Web开发的资源" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F4795.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6043.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F4795.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6043.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>
                <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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3684.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6043.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3684.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6043.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/28/26059387.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;">Web开发人员速查卡</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+ Web下拉菜单" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3207.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6043.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3207.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6043.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/13665743.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+ Web下拉菜单</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="50套Web开发图标" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6043.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6043.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;">50套Web开发图标</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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2574.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6043.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2574.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6043.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/13669111.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;">如何在低速率网络中测试 Web 应用</font>
                    </a>
                </td>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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年02月16日 -- <a href="http://coolshell.cn/articles/3684.html" title="Web开发人员速查卡">Web开发人员速查卡</a></li><li>2011年11月28日 -- <a href="http://coolshell.cn/articles/5987.html" title="如何设计“找回用户帐号”功能">如何设计“找回用户帐号”功能</a></li><li>2011年11月24日 -- <a href="http://coolshell.cn/articles/5537.html" title="一些文章资源和趣闻">一些文章资源和趣闻</a></li><li>2011年08月25日 -- <a href="http://coolshell.cn/articles/5353.html" title="你会做Web上的用户登录功能吗？">你会做Web上的用户登录功能吗？</a></li><li>2011年06月08日 -- <a href="http://coolshell.cn/articles/4795.html" title="开源中最好的Web开发的资源">开源中最好的Web开发的资源</a></li><li>2011年03月04日 -- <a href="http://coolshell.cn/articles/3903.html" title="一些有意思的贴子和工具">一些有意思的贴子和工具</a></li><li>2010年10月20日 -- <a href="http://coolshell.cn/articles/3207.html" title="30+ Web下拉菜单">30+ Web下拉菜单</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/6043.html/feed</wfw:commentRss>
		<slash:comments>64</slash:comments>
		</item>
		<item>
		<title>一些有意思的算法代码</title>
		<link>http://coolshell.cn/articles/6010.html</link>
		<comments>http://coolshell.cn/articles/6010.html#comments</comments>
		<pubDate>Tue, 29 Nov 2011 03:11:07 +0000</pubDate>
		<dc:creator>陈皓</dc:creator>
				<category><![CDATA[C/C++语言]]></category>
		<category><![CDATA[Java语言]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[技术读物]]></category>
		<category><![CDATA[杂项资源]]></category>
		<category><![CDATA[编程语言]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=6010</guid>
		<description><![CDATA[Keith Schwarz是一个斯坦福大学计算机科学系的讲师。他对编程充满了热情。他的主页上他自己正在实现各种各样的有意思的算法和数据结构，http://www.keithschwarz.com/interesting/， 目前这个网页上有88个（见下面的列表），但这位大哥要干135个，你可以看看他的To-Do List。 从这个列表上，我们可以看到，他从去年7月份就在自己实现这些东西了，我把他实现的这些算法转过来， 一方面我们可以学习一下这些算法和代码，因为很多东西对我来说都比较新，我以前列举过一些经典的算法，算法和数据结构词典，还有可视化的数据结构和算法， 不过感觉都没有这个全。 另一方面我希望这个事可以影响到一些正在学习编程的人。看看别人是怎么学习编程的，希望对你有借鉴作用。 Name Link Date Added Language Description Binomial Heap (link) 7‑24‑2010 C++ An implementation of a binomial heap data structure for use as a priority queue. Bounded Priority Queue (link) 7‑24‑2010 C++ An implementation of a priority queue with a fixed upper limit to its size.. Matrix (link) 7‑24‑2010 C++ A collection of classes for [...]<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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F399.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F399.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6010.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/2675820.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="Why C++ ? 王者归来" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6548.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6548.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6010.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/03/14687960.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;">Why 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="C++和JAVA传统中积极的一面" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F209.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F209.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6010.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/10434907.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;">C++和JAVA传统中积极的一面</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.htm?url=http%3A%2F%2Fcoolshell.cn%2F%3Fp%3D2583&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2F_3Fp_3D2583_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6010.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F4671.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F4671.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6010.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.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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>Keith Schwarz是一个斯坦福大学计算机科学系的讲师。他对编程充满了热情。他的主页上他自己正在实现各种各样的有意思的算法和数据结构，<a href="http://www.keithschwarz.com/interesting/" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/?referer=');">http://www.keithschwarz.com/interesting/</a>， 目前这个网页上有88个（见下面的列表），但这位大哥要干135个，你可以看看他的<a href="http://www.keithschwarz.com/interesting/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/?referer=');">To-Do List</a>。</p>
<p>从这个列表上，我们可以看到，他从去年7月份就在自己实现这些东西了，我把他实现的这些算法转过来，</p>
<ul>
<li>一方面我们可以学习一下这些算法和代码，因为很多东西对我来说都比较新，我以前<a href="http://coolshell.cn/articles/2583.html" target="_blank">列举过一些经典的算法</a>，<a title="链接：算法和数据结构词典" href="http://coolshell.cn/articles/1499.html" rel="bookmark">算法和数据结构词典</a>，还有<a title="链接：可视化的数据结构和算法" href="http://coolshell.cn/articles/4671.html" rel="bookmark">可视化的数据结构和算法</a>， 不过感觉都没有这个全。</li>
</ul>
<ul>
<li>另一方面我希望这个事可以影响到一些正在学习编程的人。看看别人是怎么学习编程的，希望对你有借鉴作用。</li>
</ul>
<table width="100%" border="0" cellspacing="0" cellpadding="6">
<thead>
<tr>
<th>Name</th>
<th>Link</th>
<th>Date Added</th>
<th>Language</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>Binomial Heap</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=binomial-heap" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=binomial-heap&amp;referer=');">(link)</a></td>
<td>7‑24‑2010</td>
<td>C++</td>
<td>An implementation of a <a href="http://en.wikipedia.org/wiki/Binomial_heap" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Binomial_heap?referer=');">binomial heap</a> data structure for use as a priority queue.</td>
</tr>
<tr>
<td>Bounded Priority Queue</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=bounded-pqueue" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=bounded-pqueue&amp;referer=');">(link)</a></td>
<td>7‑24‑2010</td>
<td>C++</td>
<td>An implementation of a <a href="http://en.wikipedia.org/wiki/Priority_queue" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Priority_queue?referer=');">priority queue</a> with a fixed upper limit to its size..</td>
</tr>
<tr>
<td>Matrix</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=matrix" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=matrix&amp;referer=');">(link)</a></td>
<td>7‑24‑2010</td>
<td>C++</td>
<td>A collection of classes for manipulating <a href="http://en.wikipedia.org/wiki/Matrix_%28mathematics%29" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Matrix_28mathematics_29?referer=');">matrices</a>.</td>
</tr>
<tr>
<td>VList</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=vlist" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=vlist&amp;referer=');">(link)</a></td>
<td>8‑16‑2010</td>
<td>Java</td>
<td>An implementation of the <tt>List</tt> abstraction backed by a <a href="http://en.wikipedia.org/wiki/VList" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/VList?referer=');">VList</a>.</td>
</tr>
<tr>
<td>Function Wrapper</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=function" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=function&amp;referer=');">(link)</a></td>
<td>8‑16‑2010</td>
<td>C++</td>
<td>A C++ wrapper class around unary functions.</td>
</tr>
<tr>
<td>String</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=string" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=string&amp;referer=');">(link)</a></td>
<td>8‑17‑2010</td>
<td>C++</td>
<td>An implementation of a <a href="http://en.wikipedia.org/wiki/String_(computer_science)" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/String_computer_science?referer=');">string</a> abstraction that uses the small string optimization.</td>
</tr>
</tbody>
</table>
<p><span id="more-6010"></span></p>
<table>
<tbody>
<tr>
<td>nstream</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=nstream" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=nstream&amp;referer=');">(link)</a></td>
<td>8‑31‑2010</td>
<td>C++</td>
<td>An stream class that sends and receives data over a network.</td>
</tr>
<tr>
<td>Snake</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=snake" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=snake&amp;referer=');">(link)</a></td>
<td>8‑31‑2010</td>
<td>C++</td>
<td>An implementation of the game <a href="http://en.wikipedia.org/wiki/Snake_(video_game)" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Snake_video_game?referer=');"><em>Snake</em></a> with a rudimentary AI.</td>
</tr>
<tr>
<td>Mergesort</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=mergesort" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=mergesort&amp;referer=');">(link)</a></td>
<td>9‑14‑2010</td>
<td>C++</td>
<td>An implementation of the <a href="http://en.wikipedia.org/wiki/Mergesort" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Mergesort?referer=');">mergesort</a> algorithm.</td>
</tr>
<tr>
<td>Next Permutation</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=next-permutation" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=next-permutation&amp;referer=');">(link)</a></td>
<td>10‑6‑2010</td>
<td>C++</td>
<td>An implementation of the <a href="http://www.cplusplus.com/reference/algorithm/next_permutation/" onclick="pageTracker._trackPageview('/outgoing/www.cplusplus.com/reference/algorithm/next_permutation/?referer=');"><tt>next_permutation</tt></a> STL algorithm.</td>
</tr>
<tr>
<td>Interval Heap</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=interval-heap" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=interval-heap&amp;referer=');">(link)</a></td>
<td>10‑17‑2010</td>
<td>Java</td>
<td>An implementation of a <a href="http://en.wikipedia.org/wiki/Double-ended_priority_queue" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Double-ended_priority_queue?referer=');">double-ended priority queue</a> using an <a href="http://www.mhhe.com/engcs/compsci/sahni/enrich/c9/interval.pdf" onclick="pageTracker._trackPageview('/outgoing/www.mhhe.com/engcs/compsci/sahni/enrich/c9/interval.pdf?referer=');">interval heap</a>.</td>
</tr>
<tr>
<td>Linear-Time Selection</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=median-of-medians" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=median-of-medians&amp;referer=');">(link)</a></td>
<td>10‑18‑2010</td>
<td>C++</td>
<td>A deterministic, linear-time <a href="http://en.wikipedia.org/wiki/Selection_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Selection_algorithm?referer=');">selection algorithm</a> using the <a href="http://en.wikipedia.org/wiki/Selection_algorithm#Linear_general_selection_algorithm_-_Median_of_Medians_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Selection_algorithm_Linear_general_selection_algorithm_-_Median_of_Medians_algorithm?referer=');">median-of-medians</a> algorithm.</td>
</tr>
<tr>
<td>Heapsort</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=heapsort" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=heapsort&amp;referer=');">(link)</a></td>
<td>10‑18‑2010</td>
<td>C++</td>
<td>An implementation of the <a href="http://en.wikipedia.org/wiki/Heapsort" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Heapsort?referer=');">heapsort</a> algorithm.</td>
</tr>
<tr>
<td>Union-Find</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=union-find" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=union-find&amp;referer=');">(link)</a></td>
<td>10‑19‑2010</td>
<td>Java</td>
<td>An implementation of a <a href="http://en.wikipedia.org/wiki/Disjoint-set_data_structure" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Disjoint-set_data_structure?referer=');">disjoint-set data structure</a> using a disjoint set forest.</td>
</tr>
<tr>
<td>Radix Sort</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=radix-sort" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=radix-sort&amp;referer=');">(link)</a></td>
<td>10‑19‑2010</td>
<td>C++</td>
<td>An implementation of the <a href="http://en.wikipedia.org/wiki/Radix_sort" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Radix_sort?referer=');">radix sort</a> algorithm.</td>
</tr>
<tr>
<td>Rational</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=rational" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=rational&amp;referer=');">(link)</a></td>
<td>10‑23‑2010</td>
<td>C++</td>
<td>A data structure representing a <a href="http://en.wikipedia.org/wiki/Rational_number" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Rational_number?referer=');">rational number</a>.</td>
</tr>
<tr>
<td>DPLL</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=dpll" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=dpll&amp;referer=');">(link)</a></td>
<td>10‑23‑2010</td>
<td>Haskell</td>
<td>An implementation of the <a href="http://en.wikipedia.org/wiki/DPLL_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/DPLL_algorithm?referer=');">DPLL algorithm</a> for solving <a href="http://en.wikipedia.org/wiki/Boolean_satisfiability_problem" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Boolean_satisfiability_problem?referer=');">CNF-SAT</a>.</td>
</tr>
<tr>
<td>Smoothsort</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=smoothsort" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=smoothsort&amp;referer=');">(link)</a></td>
<td>10‑27‑2010</td>
<td>C++</td>
<td>An implementation of the <a href="http://www.keithschwarz.com/smoothsort/" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/smoothsort/?referer=');">smoothsort algorithm</a>, an adaptive heapsort variant.</td>
</tr>
<tr>
<td>Extendible Array</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=extendible-array" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=extendible-array&amp;referer=');">(link)</a></td>
<td>10‑28‑2010</td>
<td>Java</td>
<td>A <a href="http://en.wikipedia.org/wiki/Dynamic_array" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Dynamic_array?referer=');">dynamic array</a> class with O(1) worst-case runtime lookup and append.</td>
</tr>
<tr>
<td>In-Place Merge</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=inplace-merge" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=inplace-merge&amp;referer=');">(link)</a></td>
<td>10‑29‑2010</td>
<td>C++</td>
<td>An implementation of a <a href="http://en.wikipedia.org/wiki/Merge_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Merge_algorithm?referer=');">merge algorithm</a> that runs <a href="http://en.wikipedia.org/wiki/In-place_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/In-place_algorithm?referer=');">in-place</a>.</td>
</tr>
<tr>
<td>Random Shuffle</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=random-shuffle" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=random-shuffle&amp;referer=');">(link)</a></td>
<td>10‑29‑2010</td>
<td>C++</td>
<td>An algorithm for generating a <a href="http://en.wikipedia.org/wiki/Random_permutation" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Random_permutation?referer=');">random permutation</a> of a set of elements.</td>
</tr>
<tr>
<td>Random Sample</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=random-sample" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=random-sample&amp;referer=');">(link)</a></td>
<td>10‑29‑2010</td>
<td>C++</td>
<td>An O(n) time, O(1) space algorithm for randomly choosing k elements out of a stream with uniform probability.</td>
</tr>
<tr>
<td>Natural Mergesort</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=natural-mergesort" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=natural-mergesort&amp;referer=');">(link)</a></td>
<td>10‑30‑2010</td>
<td>C++</td>
<td>An implementation of <a href="http://www.algorithmist.com/index.php/Merge_sort#Natural_mergesort" onclick="pageTracker._trackPageview('/outgoing/www.algorithmist.com/index.php/Merge_sort_Natural_mergesort?referer=');">natural mergesort</a>, an <a href="http://en.wikipedia.org/wiki/Adaptive_sort" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Adaptive_sort?referer=');">adaptive</a> variant of <a href="http://en.wikipedia.org/wiki/Merge_sort" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Merge_sort?referer=');">mergesort</a>.</td>
</tr>
<tr>
<td>Interpolation Search</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=interpolation-search" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=interpolation-search&amp;referer=');">(link)</a></td>
<td>10‑31‑2010</td>
<td>C++</td>
<td>An implementation of the <a href="http://en.wikipedia.org/wiki/Interpolation_search" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Interpolation_search?referer=');">interpolation search</a> algorithm.</td>
</tr>
<tr>
<td>Introsort</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=introsort" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=introsort&amp;referer=');">(link)</a></td>
<td>10‑31‑2010</td>
<td>C++</td>
<td>An implementation of the <a href="http://en.wikipedia.org/wiki/Introsort" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Introsort?referer=');">introsort</a> algorithm, a fast hybrid of <a href="http://en.wikipedia.org/wiki/Quicksort" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Quicksort?referer=');">quicksort</a>, <a href="http://en.wikipedia.org/wiki/Heapsort" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Heapsort?referer=');">heapsort</a>, and<a href="http://en.wikipedia.org/wiki/Insertion_sort" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Insertion_sort?referer=');">insertion sort</a>.</td>
</tr>
<tr>
<td>Hashed Array Tree</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=hashed-array-tree" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=hashed-array-tree&amp;referer=');">(link)</a></td>
<td>11‑3‑2010</td>
<td>Java</td>
<td>An implementation of a dynamic array backed by a <a href="http://en.wikipedia.org/wiki/Hashed_array_tree" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Hashed_array_tree?referer=');">hashed array tree</a>.</td>
</tr>
<tr>
<td>Recurrence Solver</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=recurrence" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=recurrence&amp;referer=');">(link)</a></td>
<td>11‑13‑2010</td>
<td>C++</td>
<td>A fast algorithm for generating terms of a sequence defined by a <a href="http://en.wikipedia.org/wiki/Recurrence_relation#Linear_homogeneous_recurrence_relations_with_constant_coefficients" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Recurrence_relation_Linear_homogeneous_recurrence_relations_with_constant_coefficients?referer=');">linear recurrence relation</a>.</td>
</tr>
<tr>
<td>Fibonacci Heap</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=fibonacci-heap" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=fibonacci-heap&amp;referer=');">(link)</a></td>
<td>11‑15‑2010</td>
<td>Java</td>
<td>An implementation of a priority queue backed by a <a href="http://en.wikipedia.org/wiki/Fibonacci_heap" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Fibonacci_heap?referer=');">Fibonacci heap</a>.</td>
</tr>
<tr>
<td>Dijkstra&#8217;s Algorithm</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=dijkstra" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=dijkstra&amp;referer=');">(link)</a></td>
<td>11‑16‑2010</td>
<td>Java</td>
<td>An implementation of <a href="http://en.wikipedia.org/wiki/Dijkstra's_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Dijkstra_s_algorithm?referer=');">Dijkstra&#8217;s algorithm</a> for single-source shortest paths.</td>
</tr>
<tr>
<td>Prim&#8217;s Algorithm</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=prim" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=prim&amp;referer=');">(link)</a></td>
<td>11‑17‑2010</td>
<td>Java</td>
<td>An implementation of <a href="http://en.wikipedia.org/wiki/Prim's_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Prim_s_algorithm?referer=');">Prim&#8217;s algorithm</a> for computing <a href="http://en.wikipedia.org/wiki/Minimum_spanning_tree" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Minimum_spanning_tree?referer=');">minimum spanning trees</a>.</td>
</tr>
<tr>
<td>Kruskal&#8217;s Algorithm</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=kruskal" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=kruskal&amp;referer=');">(link)</a></td>
<td>11‑17‑2010</td>
<td>Java</td>
<td>An implementation of <a href="http://en.wikipedia.org/wiki/Kruskal's_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Kruskal_s_algorithm?referer=');">Kruskal&#8217;s algorithm</a> for computing <a href="http://en.wikipedia.org/wiki/Minimum_spanning_tree" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Minimum_spanning_tree?referer=');">minimum spanning trees</a>.</td>
</tr>
<tr>
<td>Majority Element</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=majority-element" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=majority-element&amp;referer=');">(link)</a></td>
<td>11‑17‑2010</td>
<td>C++</td>
<td>A fast, linear-time algorithm for finding the <a href="http://www.cs.utexas.edu/~moore/best-ideas/mjrty/" onclick="pageTracker._trackPageview('/outgoing/www.cs.utexas.edu/_moore/best-ideas/mjrty/?referer=');">majority element</a> of a data set.</td>
</tr>
<tr>
<td>Haar Transform</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=haar" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=haar&amp;referer=');">(link)</a></td>
<td>11‑17‑2010</td>
<td>C++</td>
<td>A set of functions to decompose a sequence of values into a sum of <a href="http://en.wikipedia.org/wiki/Haar_wavelet" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Haar_wavelet?referer=');">Haar wavelets</a>.</td>
</tr>
<tr>
<td>Argmax</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=argmax" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=argmax&amp;referer=');">(link)</a></td>
<td>11‑19‑2010</td>
<td>C++</td>
<td>A pair of functions to compute the <a href="http://en.wikipedia.org/wiki/Arg_max" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Arg_max?referer=');">arg min or max</a> of a function on some range.</td>
</tr>
<tr>
<td>Derivative</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=derivative" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=derivative&amp;referer=');">(link)</a></td>
<td>11‑19‑2010</td>
<td>C++</td>
<td>A <a href="http://en.wikipedia.org/wiki/Function_object" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Function_object?referer=');">function object</a> that approximates the <a href="http://en.wikipedia.org/wiki/Derivative" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Derivative?referer=');">derivative</a> of a function.</td>
</tr>
<tr>
<td>Levenshtein Distance</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=levenshtein" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=levenshtein&amp;referer=');">(link)</a></td>
<td>11‑19‑2010</td>
<td>C++</td>
<td>An algorithm for computing the <a href="http://en.wikipedia.org/wiki/Levenshtein_distance" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Levenshtein_distance?referer=');">Levenshtein distance</a> between two sequences.</td>
</tr>
<tr>
<td>Skiplist</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=skiplist" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=skiplist&amp;referer=');">(link)</a></td>
<td>11‑20‑2010</td>
<td>C++</td>
<td>An implementation of a <a href="http://en.wikipedia.org/wiki/Skip_list" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Skip_list?referer=');">skip list</a>, a randomized data structure for maintaining a sorted collection.</td>
</tr>
<tr>
<td>van Emde Boas Tree</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=van-emde-boas-tree" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=van-emde-boas-tree&amp;referer=');">(link)</a></td>
<td>11‑26‑2010</td>
<td>C++</td>
<td>An implementation of a sorted associative array backed by a <a href="http://en.wikipedia.org/wiki/Van_Emde_Boas_tree" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Van_Emde_Boas_tree?referer=');">van Emde Boas tree</a>.</td>
</tr>
<tr>
<td>Cuckoo HashMap</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=cuckoo-hashmap" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=cuckoo-hashmap&amp;referer=');">(link)</a></td>
<td>11‑27‑2010</td>
<td>Java</td>
<td>An implementation of a <a href="http://en.wikipedia.org/wiki/Hash_table" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Hash_table?referer=');">hash table</a> using <a href="http://en.wikipedia.org/wiki/Cuckoo_hashing" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Cuckoo_hashing?referer=');">cuckoo hashing</a>.</td>
</tr>
<tr>
<td>Needleman-Wunsch Algorithm</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=needleman-wunsch" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=needleman-wunsch&amp;referer=');">(link)</a></td>
<td>11‑28‑2010</td>
<td>C++</td>
<td>An implementation of the <a href="http://en.wikipedia.org/wiki/Needleman%E2%80%93Wunsch_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Needleman_E2_80_93Wunsch_algorithm?referer=');">Needleman-Wunsch</a> algorithm for optimal string alignment.</td>
</tr>
<tr>
<td>Treap</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=treap" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=treap&amp;referer=');">(link)</a></td>
<td>11‑28‑2010</td>
<td>C++</td>
<td>An implementation of a sorted associative array backed by a <a href="http://en.wikipedia.org/wiki/Treap" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Treap?referer=');">treap</a>.</td>
</tr>
<tr>
<td>Floyd-Warshall Algorithm</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=floyd-warshall" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=floyd-warshall&amp;referer=');">(link)</a></td>
<td>12‑10‑2010</td>
<td>Java</td>
<td>An implementation of the <a href="http://en.wikipedia.org/wiki/Floyd-Warshall_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Floyd-Warshall_algorithm?referer=');">Floyd-Warshall algorithm</a> for all-pairs shortest paths in a graph.</td>
</tr>
<tr>
<td>Power Iteration</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=power-iteration" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=power-iteration&amp;referer=');">(link)</a></td>
<td>12‑10‑2010</td>
<td>C++</td>
<td>An implementation of the <a href="http://en.wikipedia.org/wiki/Power_iteration" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Power_iteration?referer=');">power iteration</a> algorithm for finding dominant eigenvectors.</td>
</tr>
<tr>
<td>Edmonds&#8217;s Matching Algorithm</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=edmonds-matching" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=edmonds-matching&amp;referer=');">(link)</a></td>
<td>12‑15‑2010</td>
<td>Java</td>
<td>An implementation of <a href="http://en.wikipedia.org/wiki/Edmonds's_matching_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Edmonds_s_matching_algorithm?referer=');">Edmonds&#8217;s matching algorithm</a> for finding <a href="http://en.wikipedia.org/wiki/Matching_(graph_theory)#Maximum_matchings" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Matching_graph_theory_Maximum_matchings?referer=');">maximum matchings</a> in undirected graphs.</td>
</tr>
<tr>
<td>Kosaraju&#8217;s Algorithm</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=kosaraju" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=kosaraju&amp;referer=');">(link)</a></td>
<td>12‑15‑2010</td>
<td>Java</td>
<td>An implementation of <a href="http://en.wikipedia.org/wiki/Kosaraju's_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Kosaraju_s_algorithm?referer=');">Kosaraju&#8217;s algorithm</a> algorithm for finding <a href="http://en.wikipedia.org/wiki/Strongly_connected_component" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Strongly_connected_component?referer=');">strongly connected components</a> of a directed graph.</td>
</tr>
<tr>
<td>2-SAT</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=2sat" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=2sat&amp;referer=');">(link)</a></td>
<td>12‑15‑2010</td>
<td>Java</td>
<td>A linear-time algorithm for solving <a href="http://en.wikipedia.org/wiki/2-satisfiability" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/2-satisfiability?referer=');">2-SAT</a>.</td>
</tr>
<tr>
<td>Bellman-Ford Algorithm</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=bellman-ford" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=bellman-ford&amp;referer=');">(link)</a></td>
<td>12‑17‑2010</td>
<td>Java</td>
<td>An implementation of the <a href="http://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Bellman_E2_80_93Ford_algorithm?referer=');">Bellman-Ford</a> algorithm for single-source shortest paths.</td>
</tr>
<tr>
<td>Topological Sort</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=topological-sort" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=topological-sort&amp;referer=');">(link)</a></td>
<td>12‑17‑2010</td>
<td>Java</td>
<td>An algorithm for computing a <a href="http://en.wikipedia.org/wiki/Topological_sorting" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Topological_sorting?referer=');">topological sort</a> of a directed acyclic graph.</td>
</tr>
<tr>
<td>Graham Scan</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=graham-scan" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=graham-scan&amp;referer=');">(link)</a></td>
<td>12‑19‑2010</td>
<td>C++</td>
<td>An implementation of the <a href="http://en.wikipedia.org/wiki/Graham_scan" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Graham_scan?referer=');">Graham scan</a> for finding convex hulls in 2D space.</td>
</tr>
<tr>
<td>Bipartite Testing</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=bipartite-verify" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=bipartite-verify&amp;referer=');">(link)</a></td>
<td>12‑19‑2010</td>
<td>Java</td>
<td>A linear-time algorithm for checking whether a directed graph is <a href="http://en.wikipedia.org/wiki/Bipartite_graph" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Bipartite_graph?referer=');">bipartite</a>.</td>
</tr>
<tr>
<td>Johnson&#8217;s Algorithm</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=johnson" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=johnson&amp;referer=');">(link)</a></td>
<td>12‑19‑2010</td>
<td>Java</td>
<td>An implementation of <a href="http://en.wikipedia.org/wiki/Johnson's_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Johnson_s_algorithm?referer=');">Johnson&#8217;s algorithm</a> for all-pairs shortest paths.</td>
</tr>
<tr>
<td>Strassen Algorithm</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=strassen" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=strassen&amp;referer=');">(link)</a></td>
<td>12‑20‑2010</td>
<td>C++</td>
<td>An implementation of the <a href="http://en.wikipedia.org/wiki/Strassen_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Strassen_algorithm?referer=');">Strassen algorithm</a> for fast matrix multiplication.</td>
</tr>
<tr>
<td>Cartesian Tree Sort</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=cartesian-tree-sort" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=cartesian-tree-sort&amp;referer=');">(link)</a></td>
<td>12‑21‑2010</td>
<td>C++</td>
<td>An implementation of <a href="http://en.wikipedia.org/wiki/Cartesian_tree#Application_in_sorting" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Cartesian_tree_Application_in_sorting?referer=');">Cartesian tree sort</a>, an adaptive, out-of-place heapsort variant.</td>
</tr>
<tr>
<td>Ford-Fulkerson Algorithm</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=ford-fulkerson" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=ford-fulkerson&amp;referer=');">(link)</a></td>
<td>12‑21‑2010</td>
<td>Java</td>
<td>An implementation of the <a href="http://en.wikipedia.org/wiki/Ford%E2%80%93Fulkerson_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Ford_E2_80_93Fulkerson_algorithm?referer=');">Ford-Fulkerson</a> maximum-flow algorithm.</td>
</tr>
<tr>
<td>Scaling Ford-Fulkerson</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=ford-fulkerson-scaling" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=ford-fulkerson-scaling&amp;referer=');">(link)</a></td>
<td>12‑22‑2010</td>
<td>Java</td>
<td>An modification of the <a href="http://en.wikipedia.org/wiki/Ford%E2%80%93Fulkerson_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Ford_E2_80_93Fulkerson_algorithm?referer=');">Ford-Fulkerson</a> maximum-flow algorithm that uses scaling to achieve polynomial time..</td>
</tr>
<tr>
<td>Splay Tree</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=splay-tree" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=splay-tree&amp;referer=');">(link)</a></td>
<td>12‑27‑2010</td>
<td>C++</td>
<td>An implementation of a sorted associative array backed by a <a href="http://en.wikipedia.org/wiki/Splay_tree" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Splay_tree?referer=');">splay tree</a>.</td>
</tr>
<tr>
<td>Ternary Search Tree</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=ternary-search-tree" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=ternary-search-tree&amp;referer=');">(link)</a></td>
<td>12‑28‑2010</td>
<td>C++</td>
<td>An implementation of a sorted set of strings backed by a <a href="http://en.wikipedia.org/wiki/Ternary_search_tree" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Ternary_search_tree?referer=');">ternary search tree</a>.</td>
</tr>
<tr>
<td>Ring Buffer</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=ring-buffer" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=ring-buffer&amp;referer=');">(link)</a></td>
<td>12‑30‑2010</td>
<td>Java</td>
<td>An implementation of a FIFO queue using a <a href="http://en.wikipedia.org/wiki/Circular_buffer" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Circular_buffer?referer=');">ring buffer</a>.</td>
</tr>
<tr>
<td>AVL Tree</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=avl-tree" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=avl-tree&amp;referer=');">(link)</a></td>
<td>12‑30‑2010</td>
<td>C++</td>
<td>A sorted associative container backed by an <a href="http://en.wikipedia.org/wiki/AVL_tree" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/AVL_tree?referer=');">AVL tree</a>.</td>
</tr>
<tr>
<td>Rabin-Karp Algorithm</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=rabin-karp" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=rabin-karp&amp;referer=');">(link)</a></td>
<td>1‑1‑2011</td>
<td>C++</td>
<td>An implementation of the <a href="http://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_string_search_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Rabin_E2_80_93Karp_string_search_algorithm?referer=');">Rabin-Karp algorithm</a> for string matching.</td>
</tr>
<tr>
<td>RPN Evaluator</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=rpn-evaluate" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=rpn-evaluate&amp;referer=');">(link)</a></td>
<td>1‑18‑2011</td>
<td>C++ / strain</td>
<td>A library to tokenize and evaluate simple arithmetic expressions in <a href="http://en.wikipedia.org/wiki/Reverse_Polish_notation" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Reverse_Polish_notation?referer=');">reverse Polish notation</a>.</td>
</tr>
<tr>
<td>Shunting-Yard Algorithm</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=shunting-yard" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=shunting-yard&amp;referer=');">(link)</a></td>
<td>1‑18‑2011</td>
<td>C++ / strain</td>
<td>An implementation of Dijkstra&#8217;s <a href="http://en.wikipedia.org/wiki/Shunting-yard_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Shunting-yard_algorithm?referer=');">shunting-yard algorithm</a> for converting infix expressions to reverse-Polish notation.</td>
</tr>
<tr>
<td>Skew Binomial Heap</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=skew-binomial-heap" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=skew-binomial-heap&amp;referer=');">(link)</a></td>
<td>1‑20‑2011</td>
<td>C++</td>
<td>An implementation of a priority queue backed by a <a href="http://en.wikipedia.org/wiki/Skew_binomial_heap" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Skew_binomial_heap?referer=');">skew binomial heap</a>.</td>
</tr>
<tr>
<td>2/3 Heap</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=two-three-heap" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=two-three-heap&amp;referer=');">(link)</a></td>
<td>3‑1‑2011</td>
<td>C++</td>
<td>An implementation of a priority queue whose branching factor alternates at different levels to maximize performance.</td>
</tr>
<tr>
<td>Zeckendorf Logarithm</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=zeckendorf-logarithm" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=zeckendorf-logarithm&amp;referer=');">(link)</a></td>
<td>3‑10‑2011</td>
<td>C++</td>
<td>An algorithm based on <a href="http://en.wikipedia.org/wiki/Zeckendorf's_theorem" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Zeckendorf_s_theorem?referer=');">Zeckendorf representations</a> that efficiently computes logarithms.</td>
</tr>
<tr>
<td>Factoradic Permutations</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=factoradic-permutation" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=factoradic-permutation&amp;referer=');">(link)</a></td>
<td>3‑17‑2011</td>
<td>C++</td>
<td>A set of algorithms for generating <a href="http://en.wikipedia.org/wiki/Permutation" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Permutation?referer=');">permutations</a> using the <a href="http://en.wikipedia.org/wiki/Factorial_number_system" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Factorial_number_system?referer=');">factoradic number system</a>.</td>
</tr>
<tr>
<td>Binary Cyclic Subsets</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=binary-subset" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=binary-subset&amp;referer=');">(link)</a></td>
<td>3‑20‑2011</td>
<td>C++</td>
<td>A set of algorithms for generating <a href="http://en.wikipedia.org/wiki/Subset" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Subset?referer=');">subsets</a> in <a href="http://en.wikipedia.org/wiki/Lexicographical_order" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Lexicographical_order?referer=');">lexicographical order</a> using <a href="http://www.keithschwarz.com/binary-subsets" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/binary-subsets?referer=');">binary numbers and cyclic shifts</a>.</td>
</tr>
<tr>
<td>Fibonacci Iterator</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=fibonacci-iterator" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=fibonacci-iterator&amp;referer=');">(link)</a></td>
<td>3‑22‑2011</td>
<td>C++</td>
<td>An STL-style iterator for iterating over the <a href="http://en.wikipedia.org/wiki/Fibonacci_number" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Fibonacci_number?referer=');">Fibonacci numbers</a>.</td>
</tr>
<tr>
<td>Fibonacci Search</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=fibonacci-search" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=fibonacci-search&amp;referer=');">(link)</a></td>
<td>3‑22‑2011</td>
<td>C++</td>
<td>An implementation of the <a href="http://en.wikipedia.org/wiki/Fibonacci_search_technique" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Fibonacci_search_technique?referer=');">Fibonacci search</a> algorithm.</td>
</tr>
<tr>
<td>Euclid&#8217;s Algorithm</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=euclid" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=euclid&amp;referer=');">(link)</a></td>
<td>4‑18‑2011</td>
<td>Haskell</td>
<td>An implementation of <a href="http://en.wikipedia.org/wiki/Euclidean_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Euclidean_algorithm?referer=');">Euclid&#8217;s algorithm</a> and applications to <a href="http://en.wikipedia.org/wiki/Continued_fraction" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Continued_fraction?referer=');">continued fractions</a> and <a href="http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Extended_Euclidean_algorithm?referer=');">the extended Euclidean algorithm</a>.</td>
</tr>
<tr>
<td>Find Duplicate</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=find-duplicate" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=find-duplicate&amp;referer=');">(link)</a></td>
<td>4‑18‑2011</td>
<td>Python</td>
<td>An algorithm to find a repeated element in an array using <a href="http://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Cycle_detection_Tortoise_and_hare?referer=');">Floyd&#8217;s cycle-finding algorithm</a>.</td>
</tr>
<tr>
<td>Permutation Generator</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=permutation-generator" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=permutation-generator&amp;referer=');">(link)</a></td>
<td>4‑19‑2011</td>
<td>Python</td>
<td>A <a href="http://en.wikipedia.org/wiki/Generator_(computer_programming)" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Generator_computer_programming?referer=');">generator</a> for producing all <a href="http://en.wikipedia.org/wiki/Permutation" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Permutation?referer=');">permutations</a> of a list of elements.</td>
</tr>
<tr>
<td>Matrix Find</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=matrix-find" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=matrix-find&amp;referer=');">(link)</a></td>
<td>4‑19‑2011</td>
<td>Python</td>
<td>A solution to the classic interview question of searching a sorted matrix for a particular value.</td>
</tr>
<tr>
<td>Binary GCD</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=binary-gcd" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=binary-gcd&amp;referer=');">(link)</a></td>
<td>4‑23‑2011</td>
<td>Scheme</td>
<td>An implementation of the <a href="http://en.wikipedia.org/wiki/Binary_GCD_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Binary_GCD_algorithm?referer=');">binary GCD algorithm</a> for computing greatest common divisors of nonnegative integers.</td>
</tr>
<tr>
<td>Knuth-Morris-Pratt Algorithm</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=knuth-morris-pratt" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=knuth-morris-pratt&amp;referer=');">(link)</a></td>
<td>5‑3‑2011</td>
<td>Python</td>
<td>An implementation of the <a href="http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Knuth_E2_80_93Morris_E2_80_93Pratt_algorithm?referer=');">Knuth-Morris-Pratt algorithm</a> for fast string matching.</td>
</tr>
<tr>
<td>Kadane&#8217;s Algorithm</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=kadane" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=kadane&amp;referer=');">(link)</a></td>
<td>5‑7‑2011</td>
<td>C++</td>
<td>An implementation of Kadane&#8217;s algorithm for solving the <a href="http://en.wikipedia.org/wiki/Maximum_subarray_problem" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Maximum_subarray_problem?referer=');">maximum-weight subarray problem</a>.</td>
</tr>
<tr>
<td>Karatsuba&#8217;s Algorithm</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=karatsuba" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=karatsuba&amp;referer=');">(link)</a></td>
<td>8‑15‑2011</td>
<td>Python</td>
<td>An implementation of <a href="http://en.wikipedia.org/wiki/Karatsuba_algorithm" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Karatsuba_algorithm?referer=');">Karatsuba&#8217;s algorithm</a> for fast integer multiplication.</td>
</tr>
<tr>
<td>Min-Stack</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=min-stack" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=min-stack&amp;referer=');">(link)</a></td>
<td>8‑15‑2011</td>
<td>C++</td>
<td>An implementation of a <a href="http://en.wikipedia.org/wiki/Stack_(data_structure)" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Stack_data_structure?referer=');">LIFO stack</a> that supports O(1) push, pop, and find-minimum.</td>
</tr>
<tr>
<td>Random Bag</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=random-bag" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=random-bag&amp;referer=');">(link)</a></td>
<td>8‑15‑2011</td>
<td>Python</td>
<td>A data structure that supports insertion and removal of a uniformly-random element.</td>
</tr>
<tr>
<td>Min-Queue</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=min-queue" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=min-queue&amp;referer=');">(link)</a></td>
<td>8‑15‑2011</td>
<td>C++</td>
<td>An implementation of a <a href="http://en.wikipedia.org/wiki/Queue_(data_structure)" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Queue_data_structure?referer=');">FIFO queue</a> that supports O(1) push, pop, and find-minimum.</td>
</tr>
<tr>
<td>Lights-Out Solver</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=lights-out" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=lights-out&amp;referer=');">(link)</a></td>
<td>8‑29‑2011</td>
<td>C++</td>
<td>A solver for the game <a href="http://en.wikipedia.org/wiki/Lights_Out_(game)" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Lights_Out_game?referer=');">Lights Out</a> using <a href="http://en.wikipedia.org/wiki/Gaussian_elimination" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Gaussian_elimination?referer=');">Gaussian elimination</a> over <a href="http://en.wikipedia.org/wiki/GF(2)" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/GF_2?referer=');">GF(2)</a>.</td>
</tr>
<tr>
<td>Maximum Single-Sell Profit</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=single-sell-profit" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=single-sell-profit&amp;referer=');">(link)</a></td>
<td>11‑9‑2011</td>
<td>Python</td>
<td>Four algorithms for the <a href="http://stackoverflow.com/q/7086464/501557" onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/q/7086464/501557?referer=');">maximum single-sell profit problem</a>, each showing off a different algorithmic technique.</td>
</tr>
<tr>
<td>Generalized Kadane&#8217;s Algorithm</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=generalized-kadane" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=generalized-kadane&amp;referer=');">(link)</a></td>
<td>11‑10‑2011</td>
<td>C++</td>
<td>A generalization of <a href="http://en.wikipedia.org/wiki/Maximum_subarray_problem" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Maximum_subarray_problem?referer=');">Kadane&#8217;s algorithm</a> for solving the maximum subarray problem subject to a <a href="http://stackoverflow.com/q/7861387/501557" onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/q/7861387/501557?referer=');">length restriction</a>.</td>
</tr>
<tr>
<td>Longest Range</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=longest-range" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=longest-range&amp;referer=');">(link)</a></td>
<td>11‑19‑2011</td>
<td>Java</td>
<td>An algorithm for solving the <a href="http://stackoverflow.com/q/5415305/501557" onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/q/5415305/501557?referer=');">longest contiguous range</a> problem.</td>
</tr>
<tr>
<td>Egyptian Fractions</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=egyptian-fraction" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=egyptian-fraction&amp;referer=');">(link)</a></td>
<td>11‑20‑2011</td>
<td>Python</td>
<td>An implementation of the <a href="http://en.wikipedia.org/wiki/Greedy_algorithm_for_Egyptian_fractions" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Greedy_algorithm_for_Egyptian_fractions?referer=');">greedy algorithm</a> for finding <a href="http://en.wikipedia.org/wiki/Egyptian_fraction" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Egyptian_fraction?referer=');">Egyptian fractions</a>.</td>
</tr>
<tr>
<td>LL(1) Parser Generator</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=ll1" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=ll1&amp;referer=');">(link)</a></td>
<td>11‑21‑2011</td>
<td>Java</td>
<td>An <a href="http://en.wikipedia.org/wiki/LL_parser" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/LL_parser?referer=');">LL(1) parser generator</a>.</td>
</tr>
<tr>
<td>LR(0) Parser Generator</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=lr0" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=lr0&amp;referer=');">(link)</a></td>
<td>11‑23‑2011</td>
<td>Java</td>
<td>An <a href="http://en.wikipedia.org/wiki/LR_parser" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/LR_parser?referer=');">LR(0) parser generator</a>.</td>
</tr>
<tr>
<td>Word Ladders</td>
<td><a href="http://www.keithschwarz.com/interesting/code/?dir=word-ladder" onclick="pageTracker._trackPageview('/outgoing/www.keithschwarz.com/interesting/code/?dir=word-ladder&amp;referer=');">(link)</a></td>
<td>11‑27‑2011</td>
<td>JavaScript</td>
<td>A program for finding <a href="http://en.wikipedia.org/wiki/Word_ladder" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Word_ladder?referer=');">word ladders</a> between two words.</td>
</tr>
</tbody>
</table>
<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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F399.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F399.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6010.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/2675820.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="Why C++ ? 王者归来" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6548.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6548.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6010.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/03/14687960.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;">Why 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="C++和JAVA传统中积极的一面" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F209.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F209.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6010.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/10434907.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;">C++和JAVA传统中积极的一面</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.htm?url=http%3A%2F%2Fcoolshell.cn%2F%3Fp%3D2583&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2F_3Fp_3D2583_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6010.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F4671.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F4671.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6010.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.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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年04月06日 -- <a href="http://coolshell.cn/articles/4220.html" title="一些有意思的文章和资源">一些有意思的文章和资源</a></li><li>2011年05月04日 -- <a href="http://coolshell.cn/articles/4671.html" title="可视化的数据结构和算法">可视化的数据结构和算法</a></li><li>2011年03月18日 -- <a href="http://coolshell.cn/articles/3933.html" title="可视化的排序过程">可视化的排序过程</a></li><li>2011年02月28日 -- <a href="http://coolshell.cn/articles/3738.html" title="打印质数的各种算法">打印质数的各种算法</a></li><li>2010年07月12日 -- <a href="http://coolshell.cn/articles/2583.html" title="一些重要的算法">一些重要的算法</a></li><li>2009年04月15日 -- <a href="http://coolshell.cn/articles/536.html" title="一个显示排序过程的Python脚本">一个显示排序过程的Python脚本</a></li><li>2009年04月10日 -- <a href="http://coolshell.cn/articles/399.html" title="一个排序算法比较的网站">一个排序算法比较的网站</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/6010.html/feed</wfw:commentRss>
		<slash:comments>36</slash:comments>
		</item>
		<item>
		<title>如何设计“找回用户帐号”功能</title>
		<link>http://coolshell.cn/articles/5987.html</link>
		<comments>http://coolshell.cn/articles/5987.html#comments</comments>
		<pubDate>Mon, 28 Nov 2011 00:34:30 +0000</pubDate>
		<dc:creator>陈皓</dc:creator>
				<category><![CDATA[杂项资源]]></category>
		<category><![CDATA[程序设计]]></category>
		<category><![CDATA[网络安全]]></category>
		<category><![CDATA[QQ]]></category>
		<category><![CDATA[UX]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[安全]]></category>
		<category><![CDATA[帐号]]></category>
		<category><![CDATA[腾讯]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=5987</guid>
		<description><![CDATA[因为《腾讯帐号申诉的用户体验》一文中好多人觉得腾讯申诉是世界级先进的，并让我拿出一个找回用户的帐号的功能来。本来不想写的，因为大家看看其它系统的就行的，但是，很明显有些人就是很懒，也不会思考，而且不会观察，所以，我就只好写下这篇科普性常识性的文章。 在行文之前，我得先感谢腾讯公司的至少30名员工在《腾讯帐号申诉的用户体验》一文后的回帖（我STFG（Search The Fucking Google）看到了你们使用的那个固定IP在各个大学论坛上的腾讯的招聘广告），我感谢你们主要有两点： 你们有半数以上的人留下的是gmail而不是QQMail/Foxmail的电子邮件，这点让我感到很欣慰。 你们在加班到晚上11点的时候都能在本站回复，的确如你们的Andy Pan所说，你们的核心竞争力很强，包括水军方面。 好了，让我正式谈谈这个设计。找回用户帐号通常就用三个事就可以了：邮箱，安全问答，手机。 邮箱，安全问答，手机 大多数的系统都会使用邮箱和安全问答，这足够了，很多系统直接用邮箱做帐号名（Apple ID，Facebook，新浪微博 &#8230;.），这样一来，就算你的系统口令被盗，帐号的是改不掉的，于是你可以用邮箱找回（注：这些系统都会验证你的邮箱是否正确）。但是，如果用邮箱做帐号，会导致你的邮箱暴露了，这样为成为垃圾邮件的受害者，而且如果你还比较2的把邮箱的口令和帐号的口令设置成一样的，那么就相当坑爹了（你可以看看本站的这篇文章——如何设计你的口令）。所以，但凡是用邮箱用为帐号的系统都不会让人看到你的注册邮箱，比如，大家就不知道我新浪微博帐号注册的邮箱，就算是知道也应该是受信的人知道（新浪微博帐号的邮箱地址的默认可见度是“你关注的人”）。 这里要说一下，Google Mail使用的是电子邮件，安全问答 和 手机。你可以使用其中一种找回口令。gmail最漂亮的用户体验是其会提示你，你绑写的邮箱（哪家公司的邮箱和帐号名的第一个字母）和手机（3个尾号）。MSN和gmail相似，也会提示你绑定的邮箱，也可以使用手机，还可以使用你设置好的受信PC，以及通过客户支持（通过客户支持——收集你注册时用的名字，生日，国家地区，安全问题，使用过的口令，最近发送过的邮箱标题，联系人等，或是你绑定过的信用卡信息，但是不会有身份证）。 使用手机的一般是安全性比较高的网站，比如：淘宝、Gmail等。这样，使用手机找回口令也不错。因为你注册的安全问答你可能会忘了，你的绑定的邮箱也可能忘了口令，而很多木马可以盗取你的这些电脑上的安全问答或邮箱口令，但是这些木马程序盗不走你的手机（注：在移动互联网时代很可能会盗取你的手机上的信息，但是也盗不走你的手机号——无法像邮箱那样改个口令就盗走了）。你会说，手机还不是会丢失，但是你要明白，你丢失的手机，你是可以停机的，可以通过你的手机密码卡或是身份证恢复你的手机号的。另外，使用手机的好处还在于，我的系统不需要收信你的真实信息（如：姓名，身份证，住址等），这些真实信息的验证交给移动运营商验证就好了。在程序设计的里，我们把这种事叫“解耦”。Amazon就一种通过电子邮件，然后通过你使用过的信用卡后四位，以及帐单的邮寄的邮政编码，如果你的邮箱变了，没问题，打电话给客服吧，客服会问你的钱行卡号和帐单地址，电子商务的好处就是可以有信用卡或银行卡来恢复号。，因为这——把用户的真实信息“解耦”到了银行，并“耦合”和银行方面的安全策略。很明显，银行和移动公司的安全级别更高，而且用户也更信任他们。最好不要自己收集用户的真实信息，要是丢失了，你就麻烦了（在国外你就要被起诉了） 在这里，你可能会有疑问，如果我的帐号口令丢失了，那么盗取者会进入我的系统改我的邮箱，改我的手机，改我的信用卡等，那不也一样吗？我想说，对于邮箱和手机，其和密码的级别一样，你改密码的时候，你都要输入旧密码，所以，你改邮箱和手机的时候也要使用旧的邮箱和手机。关于你绑定的银行卡或信用卡号，就算是自己也看不见的（只能看见四个尾号），这就就可以防盗了。当然，盗电子商务帐号的人一般会用你一帐号买东西，但是其会遇到另一个麻烦，那就是要面对银行方面的审计工作——1）对于银行卡通过银行的网银，银行的安全系统会帮你审计。2）对于信用卡则要受到信用卡验证和签名的验证，还能让商家会帮你检查信用卡签名是否正确。 一些人说，QQ的帐号申诉过程的“美妙”在于其他尽可能多的收集你的信息，这样一来，反而是安全的，因为密码容易被盗，而你的那么多的信息则不容易被盗。这样认识只对了一半。真正的安全系统是协同整个社会的安全系统做出来的一道安全长城，而不是什么都要自己搞（当然，我们都知道腾讯的DNA就是什么都要自己搞，连FBI和CIA的事也已经在搞了），什么自己都搞反而不安全了。 其它讨论Q&#38;A 问题一：通过申诉找回帐号靠不靠谱？ 明显不靠谱，而且还很愚蠢。这反而成了恶意者的温床。他人可以通过申诉让正常人的帐号失效，这是一件多么愚蠢的事啊！（我的QQ帐号前两天不就被这样攻击了吗？） 问题二：通过联系人恢复帐号靠不靠谱？ 不全然靠谱，因为你的QQ总是会有陌生人加你，你的邮箱联系人也会有一些你不受信的人。那些人可能就是攻击者的小号。所以，如果你要通过联系人的话，就不要像QQ或MSN那样坑爹的做法，让用户自己来选。而是要像Facebook那样的做法——系统随机挑些人来让你认。 问题三：在注册时设置受信的联系人靠不靠谱？ 看似靠谱，但是个人觉得还是还一点问题。因为受信者通过电子信息无法分辨是本人还是盗号者，还要受信者实际联系一下对方。这就好像我们在手机号存电话号码的时候，写上了爸爸，妈妈这样的字眼，这样当恶意者拿了你的手机后，就可以向你的家人敲诈了，因为其直接就可以叫出对方那头的人和被攻击者的关系。 问题四：恢复帐号的时候收集用户的真实信息靠不靠谱？ 这要看是什么情况了。如果用户在注册时提供了这些真实信息，就靠谱，如果没有就相当不靠谱。试想：你去银行开户存钱的时候，银行没有让你出示身份证，只让你设了个口令。然后我就可以用我的身份证去重置你的口令。你觉得这个事是不是相当的坑爹？！ 问题五：小白不懂邮件，不懂安全问题，不懂绑定手机啊？ 那就用耐心地客服教导这些小白（可参看银行等机构的做法——强制用户输入8位以上的口令，强制使用U盾才能进行大额转帐），提高他们的能力和对安全的认识，当有一天这套东西形成社会标准的时候，安全才会真的到来。安全的问题本来就是双方的事，只有大家都有安全意识，才能做得好。而不是迁就用户。还是Henry Ford的那名话——“如果我问用户要什么，用户会说他要一匹更快的马”，所以这世上也就不会有汽车了。QQ不应该为降低用户安全意识起推动性作用。 问题六：我的经历是什么样的？ 我基本不上QQ，我上QQ都是被朋友和同学逼的。因为上周四我想写点关于腾读用户体验的东西，所以我才上QQ想看看，结果发现上不去了，说是帐号被投诉了，让我申诉，我猜想估计和我最早发布的关于腾讯的文章有关系。我1999年来注册的这个QQ号根本没有提交过什么身份证或是地址系统之类的东西，我曾经绑定过手机，大概在5年前绑定过。 于是在走申诉流程的过程中，腾讯说的绑定的手机没有被验证过，我还记得曾经我使用我的hotmail邮箱代替过我的QQ号，不过这些在被投诉的面前都不能用了。而我感到腾讯无法知道我提交的这些信息是否真实，又因为我以前曾经帮朋友注册过QQ号(我这些朋友就是腾讯员工说的小白用户)，所以，我就用一些看上去比较真实的但实际是假的信息，并用帮人注册的这些QQ号成功申诉回来了。 有的网友说我不分不清找回密码和申诉的差别，我在这里想说，你分明绑定了手机，但是当你发了短信后却被告诉你的手机没有被验证过。这个就很扯了。 于是，我才意识到QQ的这个申诉过程相当的不安全。关于一些细节问题，还请我们的我们腾讯的员工@larry同学给大家更多的细节。 问题七：QQ还有什么样的坑爹的Use Case? 有两个朋友在回复中说到了两个有意思的比较坑爹的Use Case。 @gqjjqg  说，他有个朋友被恶意申诉，有段时间和这个恶意申诉者来来回回地申诉这个QQ号，搞了一个多月都没有搞定。最后只得和那个恶意申诉者达成和解才解决了这个事。 @Jack Yang说，他有个朋友在网上买了一个QQ号，没过几天就被申诉回去了（毕竟那是别人用过的），然后人家再接着卖，怎么申诉都申诉不回来。欲哭无泪。 可见，在QQ的申诉流程下，什么密保，什么手机绑定，都成了浮云。 &#160; （如果你还有什么样的问题，我可以在继续更新并回答你的问题） —————————— 希望你现在明白，关于腾讯的帐号申诉过程，看上去相那么回事，实际上漏洞百出。当然，我不能说腾讯是愚蠢的，因为人家搞得那么大的企业，我只能说人家是在下一盘很大的棋…… 相关文章2011年11月25日 -- 腾讯帐号申诉的用户体验2011年12月07日 -- Web开发中需要了解的东西2011年11月22日 [...]<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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5966.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5987.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5966.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5987.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5901.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5987.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5901.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5987.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="101个设计模式" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F21.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5987.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F21.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5987.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3142.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5987.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3142.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5987.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/28/19288528.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6043.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5987.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6043.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5987.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.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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://coolshell.cn/articles/5966.html" target="_blank">腾讯帐号申诉的用户体验</a>》一文中好多人觉得腾讯申诉是世界级先进的，并让我拿出一个找回用户的帐号的功能来。本来不想写的，因为大家看看其它系统的就行的，但是，很明显有些人就是很懒，也不会思考，而且不会观察，所以，我就只好写下这篇科普性常识性的文章。</p>
<p>在行文之前，我得先感谢腾讯公司的至少30名员工在《<a title="腾讯帐号申诉的用户体验" href="http://coolshell.cn/articles/5966.html" target="_blank">腾讯帐号申诉的用户体验</a>》一文后的回帖（我STFG（Search The Fucking Google）看到了你们使用的那个固定IP在各个大学论坛上的腾讯的招聘广告），我感谢你们主要有两点：</p>
<ol>
<li>你们有半数以上的人留下的是gmail而不是QQMail/Foxmail的电子邮件，这点让我感到很欣慰。</li>
<li>你们在加班到晚上11点的时候都能在本站回复，的确如你们的Andy Pan所说，你们的核心竞争力很强，包括水军方面。</li>
</ol>
<p>好了，让我正式谈谈这个设计。找回用户帐号通常就用三个事就可以了：<strong>邮箱</strong>，<strong>安全问答</strong>，<strong>手机</strong>。</p>
<h4><strong>邮箱</strong>，<strong>安全问答</strong>，<strong>手机</strong></h4>
<p>大多数的系统都会使用邮箱和安全问答，这足够了，很多系统直接用邮箱做帐号名（Apple ID，Facebook，新浪微博 &#8230;.），这样一来，就算你的系统口令被盗，帐号的是改不掉的，于是你可以用邮箱找回（注：这些系统都会验证你的邮箱是否正确）。但是，如果用邮箱做帐号，会导致你的邮箱暴露了，这样为成为垃圾邮件的受害者，而且如果你还比较2的把邮箱的口令和帐号的口令设置成一样的，那么就相当坑爹了（你可以看看本站的这篇文章——<a title="如何管理并设计你的口令" href="http://coolshell.cn/articles/2428.html" target="_blank">如何设计你的口令</a>）。所以，但凡是用邮箱用为帐号的系统都不会让人看到你的注册邮箱，比如，大家就不知道我新浪微博帐号注册的邮箱，就算是知道也应该是受信的人知道（新浪微博帐号的邮箱地址的默认可见度是“你关注的人”）。</p>
<p><span id="more-5987"></span></p>
<p>这里要说一下，Google Mail使用的是电子邮件，安全问答 和 手机。你可以使用其中一种找回口令。gmail最漂亮的用户体验是其会提示你，你绑写的邮箱（哪家公司的邮箱和帐号名的第一个字母）和手机（3个尾号）。MSN和gmail相似，也会提示你绑定的邮箱，也可以使用手机，还可以使用你设置好的受信PC，以及通过客户支持（通过客户支持——收集你注册时用的名字，生日，国家地区，安全问题，使用过的口令，最近发送过的邮箱标题，联系人等，或是你绑定过的信用卡信息，但是不会有身份证）。</p>
<p>使用手机的一般是安全性比较高的网站，比如：淘宝、Gmail等。这样，使用手机找回口令也不错。因为你注册的安全问答你可能会忘了，你的绑定的邮箱也可能忘了口令，而很多木马可以盗取你的这些电脑上的安全问答或邮箱口令，但是这些木马程序盗不走你的手机（注：在移动互联网时代很可能会盗取你的手机上的信息，但是也盗不走你的手机号——无法像邮箱那样改个口令就盗走了）。你会说，手机还不是会丢失，但是你要明白，你丢失的手机，你是可以停机的，可以通过你的手机密码卡或是身份证恢复你的手机号的。另外，<strong>使用手机的好处还在于，我的系统不需要收信你的真实信息（如：姓名，身份证，住址等），这些真实信息的验证交给移动运营商验证就好了</strong>。<strong>在程序设计的里，我们把这种事叫“解耦”</strong>。Amazon就一种通过电子邮件，然后通过你使用过的信用卡后四位，以及帐单的邮寄的邮政编码，如果你的邮箱变了，没问题，打电话给客服吧，客服会问你的钱行卡号和帐单地址，电子商务的好处就是可以有信用卡或银行卡来恢复号。，因为这<strong>——把用户的真实信息“解耦”到了银行，并“耦合”和银行方面的安全策略</strong>。很明显，银行和移动公司的安全级别更高，而且用户也更信任他们。最好不要自己收集用户的真实信息，要是丢失了，你就麻烦了（在国外你就要被起诉了）</p>
<p>在这里，你可能会有疑问，如果我的帐号口令丢失了，那么盗取者会进入我的系统改我的邮箱，改我的手机，改我的信用卡等，那不也一样吗？我想说，对于邮箱和手机，其和密码的级别一样，你改密码的时候，你都要输入旧密码，所以，你改邮箱和手机的时候也要使用旧的邮箱和手机。关于你绑定的银行卡或信用卡号，就算是自己也看不见的（只能看见四个尾号），这就就可以防盗了。当然，盗电子商务帐号的人一般会用你一帐号买东西，但是其会遇到另一个麻烦，那就是要面对银行方面的审计工作——1）对于银行卡通过银行的网银，银行的安全系统会帮你审计。2）对于信用卡则要受到信用卡验证和签名的验证，还能让商家会帮你检查信用卡签名是否正确。</p>
<p>一些人说，QQ的帐号申诉过程的“美妙”在于其他尽可能多的收集你的信息，这样一来，反而是安全的，因为密码容易被盗，而你的那么多的信息则不容易被盗。这样认识只对了一半。<span style="color: #cc0000;"><strong>真正的安全系统是协同整个社会的安全系统做出来的一道安全长城，而不是什么都要自己搞</strong></span>（当然，我们都知道腾讯的DNA就是什么都要自己搞，连FBI和CIA的事也已经在搞了），什么自己都搞反而不安全了。</p>
<h4>其它讨论Q&amp;A</h4>
<p><strong>问题一：通过申诉找回帐号靠不靠谱？</strong></p>
<p>明显不靠谱，而且还很愚蠢。这反而成了恶意者的温床。他人可以通过申诉让正常人的帐号失效，这是一件多么愚蠢的事啊！（我的QQ帐号前两天不就被这样攻击了吗？）</p>
<p><strong>问题二：通过联系人恢复帐号靠不靠谱？</strong></p>
<p>不全然靠谱，因为你的QQ总是会有陌生人加你，你的邮箱联系人也会有一些你不受信的人。那些人可能就是攻击者的小号。所以，如果你要通过联系人的话，就不要像QQ或MSN那样坑爹的做法，让用户自己来选。而是要像Facebook那样的做法——系统随机挑些人来让你认。</p>
<p><strong>问题三：在注册时设置受信的联系人靠不靠谱？</strong></p>
<p>看似靠谱，但是个人觉得还是还一点问题。因为受信者通过电子信息无法分辨是本人还是盗号者，还要受信者实际联系一下对方。这就好像我们在手机号存电话号码的时候，写上了爸爸，妈妈这样的字眼，这样当恶意者拿了你的手机后，就可以向你的家人敲诈了，因为其直接就可以叫出对方那头的人和被攻击者的关系。</p>
<p><strong>问题四：恢复帐号的时候收集用户的真实信息靠不靠谱？</strong></p>
<p>这要看是什么情况了。如果用户在注册时提供了这些真实信息，就靠谱，如果没有就相当不靠谱。试想：你去银行开户存钱的时候，银行没有让你出示身份证，只让你设了个口令。然后我就可以用我的身份证去重置你的口令。你觉得这个事是不是相当的坑爹？！</p>
<p><strong>问题五：小白不懂邮件，不懂安全问题，不懂绑定手机啊？</strong></p>
<p>那就用耐心地客服教导这些小白（可参看银行等机构的做法——强制用户输入8位以上的口令，强制使用U盾才能进行大额转帐），提高他们的能力和对安全的认识，当有一天这套东西形成社会标准的时候，安全才会真的到来。安全的问题本来就是双方的事，只有大家都有安全意识，才能做得好。而不是迁就用户。还是Henry Ford的那名话——“如果我问用户要什么，用户会说他要一匹更快的马”，所以这世上也就不会有汽车了。QQ不应该为降低用户安全意识起推动性作用。</p>
<p><strong>问题六：我的经历是什么样的？</strong></p>
<p>我基本不上QQ，我上QQ都是被朋友和同学逼的。因为上周四我想写点关于腾读用户体验的东西，所以我才上QQ想看看，结果发现上不去了，说是帐号被投诉了，让我申诉，我猜想估计和我最早发布的关于腾讯的文章有关系。我1999年来注册的这个QQ号根本没有提交过什么身份证或是地址系统之类的东西，我曾经绑定过手机，大概在5年前绑定过。</p>
<p>于是在走申诉流程的过程中，腾讯说的绑定的手机没有被验证过，我还记得曾经我使用我的hotmail邮箱代替过我的QQ号，不过这些在被投诉的面前都不能用了。而我感到腾讯无法知道我提交的这些信息是否真实，又因为我以前曾经帮朋友注册过QQ号(我这些朋友就是腾讯员工说的小白用户)，所以，我就用一些看上去比较真实的但实际是假的信息，并用帮人注册的这些QQ号成功申诉回来了。</p>
<p>有的网友说我不分不清找回密码和申诉的差别，我在这里想说，你分明绑定了手机，但是当你发了短信后却被告诉你的手机没有被验证过。这个就很扯了。</p>
<p>于是，我才意识到QQ的这个申诉过程相当的不安全。关于一些细节问题，还请我们的我们腾讯的员工@larry同学给大家更多的细节。</p>
<p><strong>问题七：QQ还有什么样的坑爹的Use Case?</strong></p>
<p>有两个朋友在回复中说到了两个有意思的比较坑爹的Use Case。</p>
<p>@gqjjqg  说，他有个朋友被恶意申诉，有段时间和这个恶意申诉者来来回回地申诉这个QQ号，搞了一个多月都没有搞定。最后只得和那个恶意申诉者达成和解才解决了这个事。</p>
<p>@Jack Yang说，他有个朋友在网上买了一个QQ号，没过几天就被申诉回去了（毕竟那是别人用过的），然后人家再接着卖，怎么申诉都申诉不回来。欲哭无泪。</p>
<p>可见，在QQ的申诉流程下，什么密保，什么手机绑定，都成了浮云。</p>
<p>&nbsp;</p>
<p>（如果你还有什么样的问题，我可以在继续更新并回答你的问题）</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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5966.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5987.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5966.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5987.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5901.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5987.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5901.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5987.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="101个设计模式" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F21.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5987.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F21.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5987.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3142.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5987.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3142.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5987.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/28/19288528.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6043.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5987.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F6043.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5987.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.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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年11月25日 -- <a href="http://coolshell.cn/articles/5966.html" title="腾讯帐号申诉的用户体验">腾讯帐号申诉的用户体验</a></li><li>2011年12月07日 -- <a href="http://coolshell.cn/articles/6043.html" title="Web开发中需要了解的东西">Web开发中需要了解的东西</a></li><li>2011年11月22日 -- <a href="http://coolshell.cn/articles/5901.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><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></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/5987.html/feed</wfw:commentRss>
		<slash:comments>255</slash:comments>
		</item>
		<item>
		<title>腾讯帐号申诉的用户体验</title>
		<link>http://coolshell.cn/articles/5966.html</link>
		<comments>http://coolshell.cn/articles/5966.html#comments</comments>
		<pubDate>Fri, 25 Nov 2011 00:27:09 +0000</pubDate>
		<dc:creator>陈皓</dc:creator>
				<category><![CDATA[杂项资源]]></category>
		<category><![CDATA[网络安全]]></category>
		<category><![CDATA[QQ]]></category>
		<category><![CDATA[UX]]></category>
		<category><![CDATA[安全]]></category>
		<category><![CDATA[腾讯]]></category>

		<guid isPermaLink="false">http://coolshell.cn/?p=5966</guid>
		<description><![CDATA[前面写过一篇“腾讯，竞争力 和 用户体验”批评了腾讯，于是在我的微博上和博客上收到了一些反对意见，基本上是说腾讯产品的用户体验做得很好，很方便，等等，还列举了N多的例子，以及说过什么用户数量为王的言论，让我感到我应该写一篇博客。当然，如果我们只看某个技术层面的东西的话，我同意，QQ的一些产品还是很易用的。但是我们还是要看得更深一些。Effective C++的作者Scott Meyers 在《More Effective C++》中说过——“美丽的是肤浅的表现”。   我借用一下这句话，认为QQ是好的产品的观点是肤浅的认识。 网上有大量的文章说QQ扫描硬盘啊，说QQ收集用户信息啊，你可能忘了这些。前段时间的3Q大战的那个“艰难的决定”，你好像也忘了。还有狗日的腾讯，你也忘了。包括QQ可以预防犯罪的新闻，你可能也忘（这本就是一个容易忘事的民族）。你已经被QQ的用户体验迷住你的双眼，觉得QQ无敌于天下，就像这个微博 以及微博里的回复一样在赞叹QQ注重细节一样，那些人在看到QQ的Mac版上向Steve Jobs感谢的字样激动不已。我感到你被一块红布蒙住了双眼也蒙住了天，我问你看见了什么，你说你看见了幸福 ，这个感觉真让你舒服……（对不起，一不小心我就在唱歌了，So So Sorry） 回到正题，你会说，我们在谈技术，不谈这些非技术的。好吧，我们来看看技术上的东西。我和大家说一下这两天我的真实经历。 两天前，我的QQ号被“恶意投诉”，封了号。腾讯让我走申诉流程，于是我看到了下面这些步骤： 填入我的真实姓名，身份证号，地址等我的真实信息。 （盗号者也可以填） 填入我的手机号，并要用这个手机号向腾讯发个短信以收取验证码。（盗号者的手机） 填入我以前曾经使用过的QQ密码 （盗号者盗到的密码） 填入我是什么时候，在哪里注册的QQ （盗号者可以填忘记了） 填入最近3年来，我在哪里使用过QQ （盗号者也可以填忘 记了） 邀请QQ好友来帮助申诉，越多越好，需要填号好友的QQ号和真实姓名。 （盗号者也可以用自己的小号，这些小号可以加你为好友） 这已经是非同寻常的流程了…… 从这个申请过程中你看到了什么？你是否看到了这些东西： 收集你的用户信息，从姓名，地址，身份证到手机号，包括你好友的真实姓名。 收集并验证我过去使用过的密码，以及我在哪里使用QQ的。 这个过程无法确保安全性。没有一点技术含量。 这些意味着什么？你会说，因为我不知道QQ盗号有多严重，所以他们才有这样的措施。那么我不禁要反问一下了—— 这个世上还有什么产品是可以让别人通过申诉来让你的帐号失效的？ 又有哪个产品是通过收集真实的用户信息和朋友的信息来找回密码的？ 这个世上还有什么产品是在注册的时候不要真实信息，而在找回密码的时候要真实信息？ 要收信就应该在注册的时候收集，你见过哪家银行在开户的时候不要你身份证，而你取钱，挂失的时候需要身份证的？只要腾讯愿意，弹个窗，于是就可以一点一点地让所有的人都走申诉流程以收集真实信息。我看这个过程并不是想看上去的那么简单啊。这就是用户体验？你可能还依然坚持你对这一做法的理解，那么，我真心希望你看看别的系统和软件是怎么做的。（老实说，一个手机号，另一个邮箱就可以搞定了） 我的朋友在微博上回复到—— //@真谛419：。。。qq是一个伟大的企业，一步步微创新走到了创新横扫CIA，FBI的浪潮之巅 //@chengxi_: CIA弱到爆，QQ knows it all. 这个获取所有实名社交网络的创新不亚于 reCaptcha ，用QQ的和裸奔的区别在于“裸奔”是自愿的。 你也许会说，这是腾讯因为不可抗力不得已这样做的，我们都应该理解腾讯。我想了一想，我觉得你说得有道理，你无非就是想让我说——腾讯不SB，SB的是用户。好吧，我承认你有一定的道理。 既然这样，那么我就不得不加粗朋友的这句话了——用QQ的和裸奔的区别在于“裸奔”是自愿的！！ 而且，我仿佛、似乎、好像，隐约还听到有人在欢快地呻吟着：“在QQ上裸奔的用户体验太~~好~~啦~~，让我高潮不断啊~~~啊~~~啊~~~啊~~~~~~~~”。行了行了，你可以裸奔，但是没有必要那么爽吧。 （对不起，我本不应该骂人的，更不应该还骂的那么低俗，重要的是，这本来应该在新浪微博上骂的，因为那里的骂人用户体验最好的地方……） 结尾了，你会会说我是一个喷子，呵呵。我想说，腾讯是一个天使和魔鬼的混合体，东西还是要一分为二的看，用么还是可以适当用用的，但是我们的头脑还是要清楚一些明白那是怎么一回事。 相关文章2011年11月28日 -- 如何设计“找回用户帐号”功能2011年11月22日 -- 腾讯，竞争力 和 用户体验2011年03月03日 -- 另类UX让你输入强口令2012年01月06日 -- Hash [...]<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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5987.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5966.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5987.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5966.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5901.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5966.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5901.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5966.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3142.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5966.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3142.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5966.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/28/19288528.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="另类UX让你输入强口令" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3877.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5966.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3877.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5966.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;">另类UX让你输入强口令</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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2305.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5966.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2305.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5966.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>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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/articles/5901.html" rel="bookmark" target="_blank">腾讯，竞争力 和 用户体验</a>”批评了腾讯，于是在<a href="http://weibo.com/haoel" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/haoel?referer=');">我的微博</a>上和<a href="http://coolshell.cn" target="_blank">博客</a>上收到了一些反对意见，基本上是说腾讯产品的用户体验做得很好，很方便，等等，还列举了N多的例子，以及说过什么用户数量为王的言论，让我感到我应该写一篇博客。当然，如果我们只看某个技术层面的东西的话，我同意，QQ的一些产品还是很易用的。但是我们还是要看得更深一些。Effective C++的作者Scott Meyers 在《More Effective C++》中说过——“美丽的是肤浅的表现”。   我借用一下这句话，认为QQ是好的产品的观点是肤浅的认识。</p>
<p>网上有大量的文章说<a href="http://handsome4215.blog.sohu.com/154141629.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/handsome4215.blog.sohu.com/154141629.html?referer=');">QQ扫描硬盘</a>啊，说<a href="http://hi.baidu.com/kernone/blog/item/db7218d9c1756f3933fa1cb5.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/hi.baidu.com/kernone/blog/item/db7218d9c1756f3933fa1cb5.html?referer=');">QQ收集用户信息</a>啊，你可能忘了这些。前段时间的3Q大战的那个“艰难的决定”，你好像也忘了。还有狗日的腾讯，你也忘了。包括<a href="http://www.cnr.cn/newscenter/kjxw/201111/t20111103_508725677.shtml" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.cnr.cn/newscenter/kjxw/201111/t20111103_508725677.shtml?referer=');">QQ可以预防犯罪的新闻</a>，你可能也忘（这本就是一个容易忘事的民族）。你已经被QQ的用户体验迷住你的双眼，觉得QQ无敌于天下，就像<a href="http://weibo.com/1577826897/xyZ6vpv2y" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/1577826897/xyZ6vpv2y?referer=');">这个微博</a> 以及微博里的回复一样在赞叹QQ注重细节一样，那些人在看到QQ的Mac版上向Steve Jobs感谢的字样激动不已。我感到你被一块红布蒙住了双眼也蒙住了天，我问你看见了什么，你说你看见了幸福 ，这个感觉真让你舒服……（对不起，一不小心我就在唱歌了，So So Sorry）</p>
<p>回到正题，你会说，我们在谈技术，不谈这些非技术的。好吧，我们来看看技术上的东西。我和大家说一下这两天我的真实经历。</p>
<p>两天前，我的QQ号被“恶意投诉”，封了号。腾讯让我走申诉流程，于是我看到了下面这些步骤：</p>
<ol>
<li>填入我的真实姓名，身份证号，地址等我的真实信息。 （盗号者也可以填）</li>
<li>填入我的手机号，并要用这个手机号向腾讯发个短信以收取验证码。（盗号者的手机）</li>
<li>填入我以前曾经使用过的QQ密码 （盗号者盗到的密码）</li>
<li>填入我是什么时候，在哪里注册的QQ （盗号者可以填忘记了）</li>
<li>填入最近3年来，我在哪里使用过QQ （盗号者也可以填忘 记了）</li>
<li>邀请QQ好友来帮助申诉，越多越好，需要填号好友的QQ号和真实姓名。 （盗号者也可以用自己的小号，这些小号可以加你为好友）</li>
</ol>
<p><strong>这已经是非同寻常的流程了…… 从这个申请过程中你看到了什么？</strong>你是否看到了这些东西：</p>
<p><span id="more-5966"></span></p>
<ul>
<li>收集你的用户信息，从姓名，地址，身份证到手机号，包括你好友的真实姓名。</li>
<li>收集并验证我过去使用过的密码，以及我在哪里使用QQ的。</li>
<li>这个过程无法确保安全性。没有一点技术含量。</li>
</ul>
<p>这些意味着什么？你会说，因为我不知道QQ盗号有多严重，所以他们才有这样的措施。那么我不禁要反问一下了——</p>
<ul>
<li><strong>这个世上还有什么产品是可以让别人通过申诉来让你的帐号失效的？</strong></li>
<li><strong>又有哪个产品是通过收集真实的用户信息和朋友的信息来找回密码的？</strong></li>
<li><strong>这个世上还有什么产品是在注册的时候不要真实信息，而在找回密码的时候要真实信息？</strong></li>
</ul>
<p>要收信就应该在注册的时候收集，你见过哪家银行在开户的时候不要你身份证，而你取钱，挂失的时候需要身份证的？只要腾讯愿意，弹个窗，于是就可以一点一点地让所有的人都走申诉流程以收集真实信息。我看这个过程并不是想看上去的那么简单啊。这就是用户体验？你可能还依然坚持你对这一做法的理解，那么，我真心希望你看看别的系统和软件是怎么做的。（老实说，一个手机号，另一个邮箱就可以搞定了）</p>
<p>我的朋友在微博上回复到——</p>
<blockquote><p>//<a href="http://weibo.com/zhendi419" target="_blank" onclick="pageTracker._trackPageview('/outgoing/weibo.com/zhendi419?referer=');">@真谛419</a>：。。。qq是一个伟大的企业，一步步微创新走到了创新横扫CIA，FBI的浪潮之巅 //<a href="http://weibo.com/n/chengxi_" onclick="pageTracker._trackPageview('/outgoing/weibo.com/n/chengxi?referer=');">@chengxi_</a>: CIA弱到爆，QQ knows it all. 这个获取所有实名社交网络的创新不亚于 <a href="http://t.cn/h5kPIK" target="_blank" onclick="pageTracker._trackPageview('/outgoing/t.cn/h5kPIK?referer=');">reCaptcha </a>，用QQ的和裸奔的区别在于“裸奔”是自愿的。</p></blockquote>
<p>你也许会说，这是腾讯因为不可抗力不得已这样做的，我们都应该理解腾讯。我想了一想，我觉得你说得有道理，你无非就是想让我说——腾讯不SB，SB的是用户。好吧，我承认你有一定的道理。</p>
<p>既然这样，那么我就不得不加粗朋友的这句话了——<strong>用QQ的和裸奔的区别在于“裸奔”是自愿的！！</strong> 而且，我仿佛、似乎、好像，隐约还听到有人在欢快地呻吟着：“在QQ上裸奔的用户体验太~~好~~啦~~，让我高潮不断啊~~~啊~~~啊~~~啊~~~~~~~~”。行了行了，你可以裸奔，但是没有必要那么爽吧。</p>
<p>（对不起，我本不应该骂人的，更不应该还骂的那么低俗，重要的是，这本来应该在新浪微博上骂的，因为那里的骂人用户体验最好的地方……）</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="如何设计“找回用户帐号”功能" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5987.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5966.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5987.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5966.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5901.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5966.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5901.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5966.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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3142.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5966.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3142.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5966.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/28/19288528.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="另类UX让你输入强口令" style="text-decoration: none !important; cursor: pointer !important;" href="http://app.wumii.com/ext/redirect.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F3877.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5966.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F3877.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5966.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;">另类UX让你输入强口令</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.htm?url=http%3A%2F%2Fcoolshell.cn%2Farticles%2F2305.html&from=http%3A%2F%2Fcoolshell.cn%2Farticles%2F5966.html" onclick="pageTracker._trackPageview('/outgoing/app.wumii.com/ext/redirect.htm?url=http_3A_2F_2Fcoolshell.cn_2Farticles_2F2305.html_from=http_3A_2F_2Fcoolshell.cn_2Farticles_2F5966.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>
        </tr>
    
    <tr>
        <td colspan="5" align="right">
            <a style="text-decoration: none !important;" href="http://www.wumii.com/widget/relatedItems.htm" target="_blank" title="无觅相关文章插件" onclick="pageTracker._trackPageview('/outgoing/www.wumii.com/widget/relatedItems.htm?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年11月28日 -- <a href="http://coolshell.cn/articles/5987.html" title="如何设计“找回用户帐号”功能">如何设计“找回用户帐号”功能</a></li><li>2011年11月22日 -- <a href="http://coolshell.cn/articles/5901.html" title="腾讯，竞争力 和 用户体验">腾讯，竞争力 和 用户体验</a></li><li>2011年03月03日 -- <a href="http://coolshell.cn/articles/3877.html" title="另类UX让你输入强口令">另类UX让你输入强口令</a></li><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年08月25日 -- <a href="http://coolshell.cn/articles/5353.html" title="你会做Web上的用户登录功能吗？">你会做Web上的用户登录功能吗？</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://coolshell.cn/articles/5966.html/feed</wfw:commentRss>
		<slash:comments>150</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 5.256 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-02-05 23:47:51 -->
<!-- Compression = gzip -->
