﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Read Sean</title><link>http://www.blogjava.net/sean/</link><description>Read me, read Sean.</description><language>zh-cn</language><lastBuildDate>Tue, 09 Feb 2010 21:15:05 GMT</lastBuildDate><pubDate>Tue, 09 Feb 2010 21:15:05 GMT</pubDate><ttl>60</ttl><item><title>2010年1月31日 阵雨</title><link>http://www.blogjava.net/sean/archive/2010/01/31/311418.html</link><dc:creator>大胃</dc:creator><author>大胃</author><pubDate>Sun, 31 Jan 2010 13:25:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2010/01/31/311418.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/311418.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2010/01/31/311418.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/311418.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/311418.html</trackback:ping><description><![CDATA[<br /><em>这篇日记写给自己，发散式+意识流，赶时间的朋友请放心略过。</em><br /><br />进入2010年，头1个月，到今天是最后1天，家里的事暂不去提，这个月是我参加工作以来感觉最累的1个月。<br /><br />加入现在的这支创业团队4年，我们的产品，从无到有(1.0)，到现在的2.x，倾注了很多人的心血，我们的团队，在后面的这2年多，也经历和见证了很多伤感的离别，"元老"级的人物，已经屈指可数。万事不能尽如人意，能有今天的结果，也许应该庆幸而不是哀伤，至少产品还在，至少团队还在运转。但未来会如何，谁也无法预知，我也不敢多想，我只知道，工作带给我的幸福感，正在不停的创造新低。<br /><br />创业型团队的一大特点，就是一个人要同时承担多个角色的职能，而且比其他团队更容易受到外部环境的冲击。为了生存，有时不得不做一些不相关的项目、不相关的事，活下来比什么都重要，你东西再好，技术再牛逼，没人要就是没人要，没资源就是没资源，哭爹喊娘，没人理你。<br /><br />去年年底，我们的老板带着我们一起，并入了现在这家集团公司，一个比我们大得多的团队。按说这应该是好事，我们也不必像原来那样担惊受怕，但事实证明这个想法非常天真，外部环境的冲击比以前更加真实的发生在我们身边，无时无刻不在提醒我们它的存在。以前我们卖力做事，一狠心一咬牙一跺脚，创业嘛，为整个团队付出，咱认了；现在我们卖力做事，不知道是在为谁付出：累的是你自己，收获的是别人。从创业的角度来说，我们失败了，我们为创业比别人多付出的那些汗水，除了回忆，现在看，也只有回忆了。对我们这个小团队来说，情形依然是：为了生存，有时不得不做一些不相关的项目、不相关的事，活下来比什么都重要，你东西再好，技术再牛逼，没人要就是没人要，没资源就是没资源，哭爹喊娘，没人理你。<br /><br />有人说，其实哪里都一样。这样想可能会让人更快乐，不那么痛苦，但我很清楚，这是精神毒药，如果事实果真如此，那就不仅仅是令人伤感苦闷，而是彻彻底底的让人绝望了。<br /><br />物以类聚，人以群分。我的群在哪儿？<br /><br /><br /><img src ="http://www.blogjava.net/sean/aggbug/311418.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">大胃</a> 2010-01-31 21:25 <a href="http://www.blogjava.net/sean/archive/2010/01/31/311418.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ubuntu Karmic安装手记 - T400s</title><link>http://www.blogjava.net/sean/archive/2009/12/26/307346.html</link><dc:creator>大胃</dc:creator><author>大胃</author><pubDate>Sat, 26 Dec 2009 03:14:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2009/12/26/307346.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/307346.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2009/12/26/307346.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/307346.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/307346.html</trackback:ping><description><![CDATA[<br />
周二的时候拿到了新的T400s，安装Linux(64位Karmic)的过程比预想的要曲折，趁周末有时间，整理记录于此，希望对遇到同样问题的人有所帮助。<br />
<br />
T400s送到之前，我先简单的在网上查了查基本的配置信息，同时也看到有很多网友十分顺利的安装了Linux，不论是Ubuntu Karmic还是Arch Linux，基本都是除了指纹都是out-of-box就可直接工作的，这也符合我的预期。于是，拿着amd64版的Karmic盘，开始在T400s上安装。<br />
<br />
基本系统的安装很顺利，跟着提示一路走完，Karmic就能够boot并正常login了，so far so good。不过登录进去之后，无线网卡不工作，只有有线连接，这是怎么回事？用lspci一看：<br />
<ul>
    <li>00:00.0 Host bridge: Intel Corporation Mobile 4 Series Chipset Memory Controller Hub (rev 07)</li>
    <li>00:02.0 VGA compatible controller: Intel Corporation Mobile 4 Series Chipset Integrated Graphics Controller (rev 07)</li>
    <li>00:02.1 Display controller: Intel Corporation Mobile 4 Series Chipset Integrated Graphics Controller (rev 07)</li>
    <li>00:03.0 Communication controller: Intel Corporation Mobile 4 Series Chipset MEI Controller (rev 07)</li>
    <li>00:03.3 Serial controller: Intel Corporation Mobile 4 Series Chipset AMT SOL Redirection (rev 07)</li>
    <li>00:19.0 Ethernet controller: Intel Corporation 82567LM Gigabit Network Connection (rev 03)</li>
    <li>00:1a.0 USB Controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #4 (rev 03)</li>
    <li>00:1a.1 USB Controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #5 (rev 03)</li>
    <li>00:1a.2 USB Controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #6 (rev 03)</li>
    <li>00:1a.7 USB Controller: Intel Corporation 82801I (ICH9 Family) USB2 EHCI Controller #2 (rev 03)</li>
    <li>00:1b.0 Audio device: Intel Corporation 82801I (ICH9 Family) HD Audio Controller (rev 03)</li>
    <li>00:1c.0 PCI bridge: Intel Corporation 82801I (ICH9 Family) PCI Express Port 1 (rev 03)</li>
    <li>00:1c.1 PCI bridge: Intel Corporation 82801I (ICH9 Family) PCI Express Port 2 (rev 03)</li>
    <li>00:1c.2 PCI bridge: Intel Corporation 82801I (ICH9 Family) PCI Express Port 3 (rev 03)</li>
    <li>00:1c.3 PCI bridge: Intel Corporation 82801I (ICH9 Family) PCI Express Port 4 (rev 03)</li>
    <li>00:1d.0 USB Controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #1 (rev 03)</li>
    <li>00:1d.1 USB Controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #2 (rev 03)</li>
    <li>00:1d.2 USB Controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #3 (rev 03)</li>
    <li>00:1d.7 USB Controller: Intel Corporation 82801I (ICH9 Family) USB2 EHCI Controller #1 (rev 03)</li>
    <li>00:1e.0 PCI bridge: Intel Corporation 82801 Mobile PCI Bridge (rev 93)</li>
    <li>00:1f.0 ISA bridge: Intel Corporation ICH9M-E LPC Interface Controller (rev 03)</li>
    <li>00:1f.2 SATA controller: Intel Corporation ICH9M/M-E SATA AHCI Controller (rev 03)</li>
    <li>00:1f.3 SMBus: Intel Corporation 82801I (ICH9 Family) SMBus Controller (rev 03)</li>
    <li>03:00.0 Network controller: Realtek Semiconductor Co., Ltd. Device 8172 (rev 10)</li>
    <li>04:00.0 Memory controller: Intel Corporation Turbo Memory Controller (rev 11)</li>
    <li>05:00.0 SD Host controller: Ricoh Co Ltd Device e822 (rev 01)</li>
    <li>05:00.1 System peripheral: Ricoh Co Ltd Device e230 (rev 01)</li>
</ul>
注意03:00.0这一行，竟然是Realtek的8172，对应Windows下的型号是8192，Lenovo什么时候把T400s原本的无线芯片配置(Intel WiMAX/WiFi Link 5xxx)换成了Realtek 8172的？难怪没有无线，这块网卡的驱动还没有被Linux内核直接支持，需要手工安装。网上搜到很多方案，比如ndiswrapper+win版驱动等等，但这个Ubuntu LaunchPad上的方案[1]看上去最靠谱，还等什么，开工吧。<br />
<ul>
    <li>首先下载驱动: http://launchpadlibrarian.net/34090404/rtl8192se_linux_2.6.0010.1012.2009_64bit.tar.gz</li>
    <li>解压后进入rtl8192se_linux_2.6.0010.1020.2009_64bit子目录，make</li>
    <li>成功后在HAL/rtl8192下能够找到r8192se_pci.ko文件，cp至/lib/modules/`uname -r`/kernel/drivers/net/wireless/</li>
    <li>然后将固件相关文件，即firmware/RTL8192SE目录，cp至/lib/firmware/`uname -r`/</li>
    <li>执行命令depmod -a重新扫描module依赖关系</li>
    <li>执行命令modprobe r8192se_pci加载该module，这一步完成以后NetworkManager就可以搜到无线网络并进行连接了</li>
</ul>
好了，到此最大的拦路虎已经消灭，开始装别的软件吧。就在这时，新的问题出现了，dmesg可以看到重复出现的如下报错/警告信息：<br />
<ul>
    <li>[ 483.431670] DMA: Out of SW-IOMMU space for 9100 bytes at device 0000:0e:00.0</li>
    <li>[ 483.435783] DMA: Out of SW-IOMMU space for 9100 bytes at device 0000:0e:00.0</li>
    <li>[ 483.439867] DMA: Out of SW-IOMMU space for 9100 bytes at device 0000:0e:00.0</li>
    <li>...</li>
</ul>
通常经过数分钟的积累，系统就死机了，只剩下CapsLock键上的小灯不停闪烁，典型的kernel panic? 根据网友提供的线索[2]，由于Intel的64位实现虽是参考AMD64但细节有差异，所以在实际内存大于等于4G的环境下，某些未考虑到该特性的代码会leak memory，怎么办？增加内核启动参数mem=4G iommu=off，一方面限定内存范围，另一方面关闭IOMMU。<br />
<br />
经过测试，这样的配置下系统和无线网络都能够持续稳定运行。系统安装到此，一个大的里程碑达成，唯一的缺憾是每次kernel升级，可能还需要手工做一些工作，且暂时不能既开无线又开4G以上内存，不过这样总好过没有无线，或者缴枪投降，不是吗？本想多骂几句Lenovo，好好的Intel芯片不用，要换Realtek，但转念一想，这已是既成事实，而且看到很多其他型号的ThinkPad，如R500、SL400等，也有不少用上了Realtek的这款无线芯片，让我们一起期待稳定可靠的驱动最终被Linux内核支持的那一天吧。<br />
<br />
参考链接: <br />
[1] <a href="https://bugs.launchpad.net/ubuntu/+source/linux/+bug/401126" target="_blank">https://bugs.launchpad.net/ubuntu/+source/linux/+bug/401126</a><br />
[2] <a href="http://lwn.net/Articles/91870/" target="_blank">http://lwn.net/Articles/91870/</a><a><br />
<br />
</a>
<img src ="http://www.blogjava.net/sean/aggbug/307346.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">大胃</a> 2009-12-26 11:14 <a href="http://www.blogjava.net/sean/archive/2009/12/26/307346.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用Scala解Hanoi塔</title><link>http://www.blogjava.net/sean/archive/2009/11/23/303374.html</link><dc:creator>大胃</dc:creator><author>大胃</author><pubDate>Mon, 23 Nov 2009 11:20:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2009/11/23/303374.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/303374.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2009/11/23/303374.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/303374.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/303374.html</trackback:ping><description><![CDATA[<p>到处吹嘘Scala很长时间了，却一直没有在自己的blog上增加过任何相关内容，今天就来补一补。当然，Scala的基本特性就不多废话了，网上已经有相当多的资料，如果懒得google，只想看完本文，那么你只需要知道它是一门以JVM为目标运行环境的静态编程语言(当然，Scala官方也有.NET版，但已不是其重点)，同时具备面向对象和函数式编程语言的特点。本文将通过一个简单的示例，展示Scala的FP能力，其中十分heavy的用到了implicit隐式转换和模式匹配。</p>
<p>代码是从guithub的gist上抄的，简单改了改，原始代码见: <a href="http://gist.github.com/66925" target="_blank">http://gist.github.com/66925</a></p>
<p>
</p>
<div style="background-color: #eeeeee; font-size: 13px; border-left-color: #cccccc; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;scala.reflect.Manifest<br />
&nbsp;&nbsp;<br />
def&nbsp;simpleName(m:Manifest[_]):String&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;{<br />
&nbsp;&nbsp;val&nbsp;name&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;m.toString<br />
&nbsp;&nbsp;name.substring(name.lastIndexOf(</span><span style="color: #000000; ">'</span><span style="color: #000000; ">$</span><span style="color: #000000; ">'</span><span style="color: #000000; ">)</span><span style="color: #000000; ">+</span><span style="color: #000000; ">1</span><span style="color: #000000; ">)<br />
}<br />
&nbsp;&nbsp;<br />
trait&nbsp;Num<br />
</span><span style="color: #0000FF; ">final</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Succ[Pre</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">:Num]&nbsp;</span><span style="color: #0000FF; ">extends</span><span style="color: #000000; ">&nbsp;Num<br />
</span><span style="color: #0000FF; ">final</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;_1&nbsp;</span><span style="color: #0000FF; ">extends</span><span style="color: #000000; ">&nbsp;Num<br />
type&nbsp;_2&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;Succ[_1]<br />
type&nbsp;_3&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;Succ[_2]<br />
type&nbsp;_4&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;Succ[_3]<br />
&nbsp;<br />
</span><span style="color: #0000FF; ">case</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Move[N</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">:Num,A,B,C]()<br />
<br />
implicit&nbsp;def&nbsp;move1[A,B,C](implicit&nbsp;a:Manifest[A],&nbsp;b:Manifest[B])&nbsp;:&nbsp;Move[_1,A,B,C]&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;{<br />
&nbsp;&nbsp;System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Move&nbsp;from&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;simpleName(a)&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;to&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;simpleName(b))<br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; "><br />
}<br />
&nbsp;<br />
implicit&nbsp;def&nbsp;moveN[P</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">:Num,A,B,C](implicit&nbsp;m1:Move[P,A,C,B],&nbsp;m2:Move[_1,A,B,C],&nbsp;m3:Move[P,C,B,A])&nbsp;:&nbsp;Move[Succ[P],A,B,C]&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; "><br />
&nbsp;&nbsp;<br />
def&nbsp;run[N</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">:Num,A,B,C](implicit&nbsp;m:Move[N,A,B,C])&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; "><br />
&nbsp;&nbsp;<br />
</span><span style="color: #0000FF; ">case</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Left()<br />
</span><span style="color: #0000FF; ">case</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Center()<br />
</span><span style="color: #0000FF; ">case</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Right()<br />
&nbsp;&nbsp;<br />
run[_3,Left,Right,Center]<br />
</span></div>
<p>&nbsp;</p>
<p>这段代码解决的是经典的汉诺塔问题，通过一根中柱，将左柱上64个大小依次叠加的圆盘全部移动到右柱，要求整个过程中每次只能移动一个圆盘，且每个圆盘只能独立占据一根柱子或是叠加在比自身更大的圆盘上。</p>
<p>简单分析一下就知道，这是一个递归问题(FP的英雄特长)：</p>
<ul>
    <li>当只有1个圆盘时，不用通过中柱，直接可以从左柱移动到右柱；</li>
    <li>当有2个圆盘时，将小盘移动到中柱，剩下的大盘移动到右柱，再从中柱把小盘移动到右柱；</li>
    <li>当有3个圆盘时，先移动2个圆盘到中柱，再移动大盘到右柱，再移动2个圆盘到右柱；</li>
    <li>...</li>
</ul>
<p>很容易发现一个pattern，那就是移动N(N&gt;1)个圆盘，可以通过以下三个步骤：</p>
<ol>
    <li>移动N-1个圆盘，从左柱到中柱；</li>
    <li>移动剩下的1个圆盘，从左柱到右柱；</li>
    <li>移动N-1个圆盘，从中柱到右柱。</li>
</ol>
<p>在解释代码之前，先说说Scala的implicit隐式转换，这是一个非常powerful的idea，当Scala编译器发现类型不匹配，它不会直接fail，而是尝试从代码中指定的，在scope内的implicit转换定义，来替换问题对象或表达式以满足类型要求，当然，为了避免歧义，同一时刻Scala需要找到唯一的一个满足条件的implicit定义。</p>
<p>我们的代码首先定义了一个取得友好类名的方法，不去深究它，然后定义了一个正整数的序列，也不去深究它了，你只需要当作他们是正整数就好，接触过FP的同学应该对此类定义不陌生，接下来定义了如下3个支持implicit传入参数的方法：</p>
<ol>
    <li>implicit def move1[A,B,C](implicit a:Manifest[A], b:Manifest[B]) : Move[_1,A,B,C]</li>
    <li>implicit def moveN[P&lt;:Num,A,B,C]( implicit <br />
    m1:Move[P,A,C,B], <br />
    m2:Move[_1,A,B,C], <br />
    m3:Move[P,C,B,A]<br />
    ) : Move[Succ[P],A,B,C]</li>
    <li>def run[N&lt;:Num,A,B,C](implicit m:Move[N,A,B,C])</li>
</ol>
<p>含义分别是：</p>
<ol>
    <li>当需要Move[_1,A,B,C]值时，可以找我帮忙(我有个side-effect，那就是输出移动指令)；</li>
    <li>当需要Move[Succ[P],A,B,C]时，可以找我帮忙；</li>
    <li>运行我，我接受Move[N,A,B,C]类型的参数。</li>
</ol>
<p>简单说明：Scala用[]表示类型参数，区别于Java的&lt;&gt;，另外，Scala的类型声明在变量/函数定义之后。Move[_,A,B,C]的含义是通过C，从A移动圆盘到B。</p>
<p>我们来模拟运行一下，为了演示效果，用一个中等复杂的数目，3个圆盘，从Left移动到Right。</p>
<p>run[_3,Left,Right,Center]，对应Move[Succ[_2],Left,Right,Center]，于是展开成三个Move：</p>
<p>Move[_2,Left,Center,Right]即Move[Succ[_1],Left,Center,Right]<br />
Move[_1,Left,Right,Center]<br />
Move[_2,Center,Right,Left]即Move[Succ[_1],Center,Right,Left]<br />
</p>
<p>然后继续展开Move[_2,Left,Center,Right]和Move[_2,Center,Right,Left]，得到：</p>
<p>Move[_1,Left,Right,Center]<br />
Move[_1,Left,Center,Right]<br />
Move[_1,Right,Center,Left]<br />
--------------------------<br />
Move[_1,Left,Right,Center]<br />
--------------------------<br />
Move[_1,Center,Left,Right]<br />
Move[_1,Center,Right,Left]<br />
Move[_1,Left,Right,Center]<br />
</p>
<p>这个时候已经全部都匹配Move[_1,A,B,C]，于是我们很容易得到以下输出：</p>
<p>Move from Left to Right<br />
Move from Left to Center<br />
Move from Right to Center<br />
Move from Left to Right<br />
Move from Center to Left<br />
Move from Center to Right<br />
Move from Left to Right<br />
</p>
<p>希望本文能带给Scala初学者一些感性认识和启发。</p>
<p><br />
</p>
<img src ="http://www.blogjava.net/sean/aggbug/303374.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">大胃</a> 2009-11-23 19:20 <a href="http://www.blogjava.net/sean/archive/2009/11/23/303374.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>青花瓷</title><link>http://www.blogjava.net/sean/archive/2009/10/18/298739.html</link><dc:creator>大胃</dc:creator><author>大胃</author><pubDate>Sun, 18 Oct 2009 03:57:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2009/10/18/298739.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/298739.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2009/10/18/298739.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/298739.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/298739.html</trackback:ping><description><![CDATA[<br />
前两天看到网友关于铁观音泡法的留言，接受建议，收了只手绘青花瓷盖碗，和一只公杯：<br />
<br />
<img src="http://www.blogjava.net/images/blogjava_net/sean/DSC_3349cs.JPG" width="640" height="320" alt="" /><br />
<br />
家里还有些去年的秋茶存货，开始练习用盖碗，右手的拇指、食指和中指被烫到不行，据说烫出一层老茧就好了，我觉得应该不至于那么夸张，慢慢来，挺好玩的。<br />
<br />

<img src ="http://www.blogjava.net/sean/aggbug/298739.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">大胃</a> 2009-10-18 11:57 <a href="http://www.blogjava.net/sean/archive/2009/10/18/298739.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于编程语言的typing(一些基本概念)</title><link>http://www.blogjava.net/sean/archive/2009/09/28/296825.html</link><dc:creator>大胃</dc:creator><author>大胃</author><pubDate>Mon, 28 Sep 2009 11:19:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2009/09/28/296825.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/296825.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2009/09/28/296825.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/296825.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/296825.html</trackback:ping><description><![CDATA[<br />
最近围观一本JavaScript的书籍引发的争论，一不小心碰到一篇讲编程语言类型系统划分的帖子，回想起当年还在公司内部的Tech Session上主讲过这个话题，不过只涉及到静态/动态、强类型/弱类型，远没有这位仁兄总结的那么全面。<br />
<br />
原文链接<br />
<a href="http://www.reddit.com/r/programming/comments/63tnv/bruce_eckel_33104_im_over_it_java/c02qx55" target="_blank">http://www.reddit.com/r/programming/comments/63tnv/bruce_eckel_33104_im_over_it_java/c02qx55</a><br />
<br />
不多废话，直入正题：<br />
<br />
[维度一] Static vs Dynamic Typing<br />
静态类型和动态类型，区分的关键点为编译期或运行期确定类型：静态类型在编译期确定，动态类型在运行期确定。<br />
静态类型代表 Java、Scala、Haskell<br />
动态类型代表 Ruby、Python、Erlang<br />
<br />
[维度二] Strong vs Weak Typing <br />
强类型和弱类型，区分的关键点为运行时是否自动转换到与实际类型不符的类型：强类型要求手工类型转换，弱类型自动转换。<br />
强类型代表 Java、Scala、Python<br />
弱类型代表 C、Assembly、JavaScript<br />
<br />
[维度三] Latent (Implicit) vs Manifest (Explicit) Typing<br />
隐式类型和显式类型，区分的关键点为是否要在源码中声明类型：隐式类型不需要，显式类型需要。<br />
隐式类型代表 Haskell、Erlang、Python<br />
显式类型代表 C、C++、Java<br />
<br />
[维度四] Nominal vs Structural Typing<br />
名义类型和结构类型，区分的关键点为类型判定是根据标称还是根据内容：名义类型根据标称，结构类型根据内容。<br />
名义类型代表 C、C++、Java <br />
结构类型代表 Haskell、Erlang、Python<br />
<br />
关于JavaScript书籍的争论，请移步如下网址：<br />
1- 网友Hax的"炮轰"帖 <a href="http://www.javaeye.com/topic/474725" target="_blank">http://www.javaeye.com/topic/474725</a><br />
2- 周爱民(aimingoo)的MSN空间 <a href="http://aimingoo.spaces.live.com/blog/" target="_blank">http://aimingoo.spaces.live.com/blog/</a><br />
3- 火星常驻JE办事处相关帖 <a href="http://mars.group.javaeye.com/group/topic/14325" target="_blank">http://mars.group.javaeye.com/group/topic/14325</a><br />
<br />

<img src ="http://www.blogjava.net/sean/aggbug/296825.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">大胃</a> 2009-09-28 19:19 <a href="http://www.blogjava.net/sean/archive/2009/09/28/296825.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[全家福] 四只紫砂 一字排开</title><link>http://www.blogjava.net/sean/archive/2009/08/30/293169.html</link><dc:creator>大胃</dc:creator><author>大胃</author><pubDate>Sun, 30 Aug 2009 03:58:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2009/08/30/293169.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/293169.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2009/08/30/293169.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/293169.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/293169.html</trackback:ping><description><![CDATA[<br />
<p>这个周末又去收了一只紫砂，这下除了龙井，我平常喝的所有品种的茶，都有了各自专用的壶。贴个"全家福"：</p>
<p><img src="http://www.blogjava.net/images/blogjava_net/sean/DSC_3158csp.JPG" border="0" alt="" /><br />
</p>
<p>从左到右依次为铁观音、高山乌龙、熟普洱和生普洱。目前只有第一只养成了，其余的三只还得多花些时间和心思呢。</p>
<p><br />
</p>
<img src ="http://www.blogjava.net/sean/aggbug/293169.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">大胃</a> 2009-08-30 11:58 <a href="http://www.blogjava.net/sean/archive/2009/08/30/293169.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>当热脸遇上冷屁股</title><link>http://www.blogjava.net/sean/archive/2009/07/06/285706.html</link><dc:creator>大胃</dc:creator><author>大胃</author><pubDate>Mon, 06 Jul 2009 13:15:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2009/07/06/285706.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/285706.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2009/07/06/285706.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/285706.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/285706.html</trackback:ping><description><![CDATA[<br />
我曾经一度是Twitter重度用户，直到上周五，@laogao这个账号，被Twitter无端禁言了。被禁时，我follow 133人，被241人follow，共2260历史推。<br />
<br />
Follow我的推友们，以及我经常@的兄弟姐妹，抱歉了，尤其那些被我"忽悠"上Twitter的朋友。当你访问<a title="http://twitter.com/laogao" target="_blank" href="http://twitter.com/laogao">http://twitter.com/laogao</a>时，暂时只能看到"该用户被suspend"的信息。这并非是因为我是一个spammer，或者有什么所谓的"strange behaviour"，至于被封的具体原因，直到今天，Twitter仍没有给予正面答复。<br />
<br />
作为一个喜欢Twitter的简单、直接的人，我从来都很认真的对待我的每一推，尊重他人的意见，善待每个@我的朋友，也在现实世界的朋友圈中推荐大家使用这个服务。但从今天开始，我将不再向人推荐Twitter，也无法确定什么时候@laogao这个账号能够被reinstate或者再次被suspend，各位关注我的朋友，请移步<a target="_blank" title="https://friendfeed.com/laogao" href="https://friendfeed.com/laogao">https://friendfeed.com/laogao</a>。<br />
<br />
对那些仍然天真的以为Twitter封号肯定是用户自己的问题的朋友，我很理解你们的想法，当初我看到别人被封时，也是这么想的。<br />
<br />
各位推友保重！<br />
<br />
<br />
<img src ="http://www.blogjava.net/sean/aggbug/285706.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">大胃</a> 2009-07-06 21:15 <a href="http://www.blogjava.net/sean/archive/2009/07/06/285706.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>我的第二只紫砂</title><link>http://www.blogjava.net/sean/archive/2009/06/08/280755.html</link><dc:creator>大胃</dc:creator><author>大胃</author><pubDate>Mon, 08 Jun 2009 14:07:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2009/06/08/280755.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/280755.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2009/06/08/280755.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/280755.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/280755.html</trackback:ping><description><![CDATA[<br />
周末去败了只全新的紫砂回来，宜兴红泥的，专门用来泡台湾高山乌龙。用之前，当然少不了开壶的过程，虽然比较耗时，但也挺有趣，在这里做个记录。<br />
<br />
首先将新买的紫砂壶用清水洗净，浸泡一整天，其间换水2~3次，去除掉残余的泥土、灰尘等。然后放入锅内，加入清水煮上1个小时，继续消毒。<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/sean/oolong_001.jpg" height="360" width="480" /><br />
<br />
接下来，放置一边，冷却后，取老豆腐半块，放入清水中，再煮1小时，去火气。<br />
<img src="http://www.blogjava.net/images/blogjava_net/sean/oolong_002.jpg" alt="" border="0" /><br />
<br />
第三步，用清水洗净，根据今后用这个紫砂壶泡什么类型的茶，选用单次用量的2~4倍茶叶，加清水，煮沸后，待茶汁完全浸出，捞起茶叶残渣，继续用茶汤煮上1个小时。<br />
<img src="http://www.blogjava.net/images/blogjava_net/sean/oolong_003.jpg" alt="" border="0" /><br />
<br />
出锅。<br />
<img src="http://www.blogjava.net/images/blogjava_net/sean/oolong_004.jpg" alt="" border="0" /><br />
<br />
这是成品，可以正式开始享用了：<br />
<img src="http://www.blogjava.net/images/blogjava_net/sean/oolong_005.jpg" alt="" border="0" /><br />
<br />
现在开始，从头养我的第二只紫砂，细细体味那份安静和从容，让每日忙碌和疲惫的身心，有一个休息和平复的空间。<br />
<br />
<img src ="http://www.blogjava.net/sean/aggbug/280755.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">大胃</a> 2009-06-08 22:07 <a href="http://www.blogjava.net/sean/archive/2009/06/08/280755.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[Tips] DIY制表符键自动补全(bash)</title><link>http://www.blogjava.net/sean/archive/2009/06/01/279316.html</link><dc:creator>大胃</dc:creator><author>大胃</author><pubDate>Sun, 31 May 2009 16:11:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2009/06/01/279316.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/279316.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2009/06/01/279316.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/279316.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/279316.html</trackback:ping><description><![CDATA[各位童鞋们过节好啊，今天给大家带来的是在bash中DIY制表符键自动补全。<br>
<br>
bash是大多数主流Linux发行版的默认shell，如果你用过bash，那么一定会接触到&lt;tab&gt;键自动补全的这个方便的功能，当你一个命令的头几个字符敲下去，按下&lt;tab&gt;，如果以此开头的命令只有1个， bash会直接帮你补全，如果有多个，则会有相应提示，而在后续的参数输入时，也会带有默认的自动补全文件路径的功能。当你习惯了&lt;tab&gt;，很难想象没有自动补全的日子会是什么样子。<br>
<br>
bash默认支持常见的补全功能，如可执行命令、文件路径等，如果安装了bash-completion包，甚至连chown, man, svn, ssh这些也会带有相应的自动补全提示，而不是单纯的文件路径补全。好奇的你一定想知道是怎么实现的吧，其实很简单，我们举个例子来说：<br>
<br>
假定你有一个命令，叫做abc，它又有自己的子命令，分别是build_all、compile和update，其中compile这个子命令需要的参数必须来自project.list这个文件中列出的值，怎么实现&lt;tab&gt;自动补全，让bash知道abc的合法子命令和compile子命令的合法参数列表呢？<br>
<br>
在你的~/.bashrc或者任何一个启动bash时会被执行的文件中加入下面的代码：<br>
<br>
function _abc() {<br>
&nbsp;&nbsp;&nbsp;&nbsp;COMPREPLY=()<br>
&nbsp;&nbsp;&nbsp;&nbsp;local cur=${COMP_WORDS[COMP_CWORD]};<br>
&nbsp;&nbsp;&nbsp;&nbsp;local com=${COMP_WORDS[COMP_CWORD-1]};<br>
&nbsp;&nbsp;&nbsp;&nbsp;case $com in<br>
&nbsp;&nbsp;&nbsp;&nbsp;'abc')<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;COMPREPLY=($(compgen -W 'build_all compile update' -- $cur))<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;;<br>
&nbsp;&nbsp;&nbsp;&nbsp;'compile')<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local pro=($(awk '{print $1}' project.list))<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;COMPREPLY=($(compgen -W '${pro[@]}' -- $cur))<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;;<br>
&nbsp;&nbsp;&nbsp;&nbsp;*)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;;<br>
&nbsp;&nbsp;&nbsp;&nbsp;esac<br>
&nbsp;&nbsp;&nbsp;&nbsp;return 0<br>
}<br>
<br>
complete -F _abc abc<br>
<br>
手动载入一下，或者重启bash，再敲abc命令，即可自动补全子命令，如果子命令是compile，还能自动补全相应的参数值。我们来简单分析一下这段代码。首先我们定义一个function _abc，这个函数先清空自动补全列表，根据当前输入位置前一个token判断目前需要自动补全的语境，如果是abc，则将自动补全内容设置为'build_all'、'compile'和'update'，如果是'compile'，则将project.list文件内容输出到补全列表，当然，这里我们也可以换成其他任何必要的方式。最后我们通过complete -F _abc abc将这段自动补全逻辑注册到abc这个主词上。这样当我们敲abc时，后续内容就能自动补全了。<br>
<br>
Enjoy!<br>
<br><img src ="http://www.blogjava.net/sean/aggbug/279316.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">大胃</a> 2009-06-01 00:11 <a href="http://www.blogjava.net/sean/archive/2009/06/01/279316.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>"已"是如何变成"å·²"的？小记UTF-8编码</title><link>http://www.blogjava.net/sean/archive/2009/05/05/269045.html</link><dc:creator>大胃</dc:creator><author>大胃</author><pubDate>Tue, 05 May 2009 11:24:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2009/05/05/269045.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/269045.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2009/05/05/269045.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/269045.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/269045.html</trackback:ping><description><![CDATA[
		<br />本来是手写的一张草稿，清理台面的时候，正要扔，发现内容还有点意思，干脆吧，开个随笔记录一下，备忘，说不定还能帮到别人。<br /><br />在我们日常生活和工作中，尤其浏览含有中文的网站，时常会为乱码问题犯愁，一些天生Unicode支持不到位的编程语言和软件更是加重了这个现象。虽说已经是2009年了，我们时不时还是能碰到一些明显脑残的code，吐出一堆乱码，不论你用选什么字符集，似乎都无法还原最初的中文。比如"å·²"，或者同一个页面，无法用同一个字符集显示，任何一种字符都至少有一部分显示不正确，不是这儿就是那儿。<br /><br />首先科普一下UTF-8。UTF-8是Unicode所有字符编码实现中，应用范围最广的一个，最大的特点是兼容ASCII码，在此基础上，通过1..4个byte来表示每一个Unicode字符。它是怎么做到的？其实很简单，看首个byte：<br />00000000 ~ 01111111 : 0~127 (ASCII, 单个byte) 表示Unicode范围\u0000 ~ \u007F<br />11000000 ~ 11011111 : (2个1打头，所以2个byte) 表示Unicode范围\u0080 ~ \u07FF<br />11100000 ~ 11101111 : (3个1打头，所以3个byte) 表示Unicode范围\u0800 ~ \uFFFF<br />11110000 ~ 11110111 : (4个1打头，所以4个byte) 表示Unicode范围\u10000 ~ \u10FFFF<br /><br />除了单个byte这个case，其他情况下，后续的byte均以10打头。这些打头的bit：10、110、1110、11110，都不作为具体编码的一部分参与真正Unicode编码的计算。所以1..4个byte，其有效位数分别为：7、11、16、21，因此才有了\u007F、\u07FF、\uFFFF这样的临界值，且4个byte的空间还有富余。<br /><br />有了这个基础知识，我们就来具体看看这个"已"字，是怎么被UTF-8表示的，以及为什么处理不当的代码会最终输出"å·²"。<br /><br />"已"字，用Unicode表示法，是\u5DF2，按照2个byte拆开成二进制表示：<br />01011101 11110010<br />如果用UTF-8编码，采用1110???? 10?????? 10??????这个格式，?号部分填入上述01011101 11110010，得到<br />11100101 10110111 10110010 这样3个byte。<br /><br />好了，这个时候脑残代码出现，假如它不认识UTF-8，那么他会看到这样3个前后没有关联的byte，在西欧Latin-1字符集(即ISO 8859-1)中，它们分别表示"å"、"·"、"²"这3个字符。如果把它们分别再按照UTF-8编码，就成了：<br />11000011 10100101 11000010 10110111 11000010 10110010<br />完美的UTF-8编码，只不过，这完全是假象，只能通过非常规手段才能恢复它原本的样子。<br /><br /><br /><img src ="http://www.blogjava.net/sean/aggbug/269045.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">大胃</a> 2009-05-05 19:24 <a href="http://www.blogjava.net/sean/archive/2009/05/05/269045.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>QCon 2009 北京之行</title><link>http://www.blogjava.net/sean/archive/2009/04/17/266060.html</link><dc:creator>大胃</dc:creator><author>大胃</author><pubDate>Thu, 16 Apr 2009 16:36:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2009/04/17/266060.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/266060.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2009/04/17/266060.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/266060.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/266060.html</trackback:ping><description><![CDATA[
		<br />上周在北京参加QCon大会，回来以后一直没有成块的时间，把一些之前只是通过Twitter分享出来的信息汇总整理出来。已经有不少朋友都在各自的博客上记录了大会感闻，所以我还是抓紧些吧，不然真要成没有营养的废话了。<br /><br />QCon这次是首次进入中国，我有幸得以抽身参加。大会为期三天，由InfoQ中文站组织策划，包括 <a target="_blank" title="http://twitter.com/taiwen" href="http://twitter.com/taiwen">@taiwen</a> 在内InfoQ中文站只有3个人，这是我之前没有想到的，感谢他们和志愿者的辛勤劳动，使得这次大会得以顺利举行。大会嘉宾包括了国内外许多大名鼎鼎的牛人，比如前TSS和后来InfoQ的主创Floyd Marinescu、ThoughtWorks首席科学家Martin Fowler、Spring之父Rod Johnson、eBay架构师Randy Shoup、《硝烟中的Scrum和XP》作者Henrik Kniberg、《大道至简》作者周爱民、支付宝数据库架构师冯大辉 <a target="_blank" title="http://twitter.com/Fenng" href="http://twitter.com/Fenng">@Fenng</a> 等。<br /><br />大会第一天，上午和下午都安排了Martin Fowler的session，分别是DSL和Ruby，虽然内容算不上特别新，但幻灯片准备很到位，而大师就是大师，思路清晰，言简意赅，尺度分寸拿捏的很好。唯一感觉可能是大家都比较含蓄，或者热身不够，沟通和对话的环节显得不是很活跃，除了买书签名的，到后面Dojo的创始人Dylan Schiemann讲Open Web，气氛就开始暖和一些了。至于Amazon的Jeff Barr，不少朋友也都说了，基本上就是来打广告的，可惜QCon北京的赞助商中，没有发现Amazon。晚上的沙龙，国际讲师唱主角，分享关于软件开发趋势的见解。<br /><br />大会第二天，可能是最精彩的一天，尤其是下午 <a target="_blank" title="http://twitter.com/Fenng" href="http://twitter.com/Fenng">@Fenng</a> 主持的网站架构这个Track。上午的大戏是Rod Johnson，不过也许是大家期望比较高，反倒是没觉出特别出彩的地方，Rod特别强调Simplicity和Lean，同时通批了一顿Java EE，不过把Tomcat作为simplicity和lean的代表举例，似乎大家都不是特别买账。后来才知道原来Tomcat 90%的commit都来自SpringSource，而稍后SpringSource会在此基础上推出功能更丰富的Spring tc server，以及(我猜)Spring 3.0。接下来eBay的Randy Shoup，带来了一场颇为精彩的演讲。下午来自支付宝、豆瓣网、网易有道和优酷网的架构师们共同创造了本次QCon大会最受欢迎的半天，尤其是豆瓣的 <a target="_blank" title="http://twitter.com/hongqn" href="http://twitter.com/hongqn">@hongqn</a> ，内容相当务实、精彩、有货。说到这，插句题外话，如果没记错， <a target="_blank" title="http://twitter.com/hongqn" href="http://twitter.com/hongqn">@hongqn</a> 是这次大会中唯一一位使用Mac的国内讲师，国际讲师用Mac的好像也只有Martin Fowler (如果说的不对还请同学们指正)。到了这个时候，国际讲师们渐渐淡出，场子交给了国内的讲师们，会场气氛也更加热闹和随意起来，包括晚上的沙龙。<br /><br />大会第三天，从日程上看，并没有特别重量级的session，似乎除了云还是云，不过如果因此选择不参加的话，可能就会错过了两场很不错的演讲，分别是高焕堂的"提高架构质量的10个观点"和周爱民的"我之于架构的主要观点"。高焕堂的演讲让人耳目一新，明显感觉来自台湾的专家，比大陆的专家，对中国传统文化，有更深的理解和思考，他的"序"、"容"、"易"三角，让人印象深刻，另外他还对目前我们软件产业的结构性问题提出了批评。而周爱民的演讲同样很有深度，尤其是后面说到架构师的决策作用时，很引起我的共鸣："<span id="msgtxt1482228993" class="msgtxt zh">架构师不需要让所有人都理解你的每一个决定和这些决定最终要达成的目标，去做就是了。</span>"(可能原话不是这么说的，但意思是这样) 也许有些朋友觉得这两个session虚幻的成分比较重，但对我来说，收益颇丰，因为很多观点，都能够在我之前经历的一些项目和设计中找到支撑。至于其他几讲，关于云计算的，确实提不起什么兴趣，尤其是Azure，干的要命(小插曲: 现场演示一段ASP.NET代码，至少修改和重编译了3次才搞定)。大公司带着推销产品/服务的目的来参加开发会议，有点浪费大家的时间和银子啊。<br /><br />最后说说大会的组织相对还有待提高的地方：<br />1- 第一天入场时，志愿者的引导不是很到位，报到的地方和其他展台秩序稍显混乱。<br />2- 同声传译据说质量不高，白天没用，但是周围的朋友在用，耳机漏音比较严重，稍影响一些效果，晚上直接通过扩音设备翻译，就很明显的感觉到脱节了。<br />3- 午餐和沙龙的地方，显得还是小了些，而且中午所有人都集中在一个时间去，不论排队打饭还是找位置，都比较吃力，以至于第二天中午有一小撮脑筋比较活络的同学，提前下课去打饭吃。<br />4- 现场网络环境比较差，害我只能用手机上twittai。<br /><br />总的来说，这次的QCon还是挺不错的，希望明年的QCon会继续在中国举办，更多的嘉宾，更丰富的内容，更有深度的主题，更加精彩。<br /><br /><br /><img src ="http://www.blogjava.net/sean/aggbug/266060.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">大胃</a> 2009-04-17 00:36 <a href="http://www.blogjava.net/sean/archive/2009/04/17/266060.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[Tips] Wake-on-LAN</title><link>http://www.blogjava.net/sean/archive/2009/03/18/260576.html</link><dc:creator>大胃</dc:creator><author>大胃</author><pubDate>Wed, 18 Mar 2009 12:03:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2009/03/18/260576.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/260576.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2009/03/18/260576.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/260576.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/260576.html</trackback:ping><description><![CDATA[
		<br />其实很早就听说有这个东东，只是一直没玩过，最近公司调整PC服务器，正好找个空闲实战了一把。基本的配置步骤如下(时间有限，挑简单的说，假定你要Wake-on-LAN的机器是Windows，控制服务器是Linux)：<br /><br /><b>[被控制方]</b><br />1- 正常开机进入BIOS设置<br />2- 找到Wake-on-LAN的选项enable它(如果是Dell的机器这个选项叫Remote Wake Up)<br />3- 进入OS，在需要配置Wake-on-LAN的网络端口的配置项中(网络连接属性-&gt;配置-&gt;电源管理)，选择允许此设备使计算机脱离待机状态<br />4- 记录网卡的MAC地址<br />5- 正常关机<br />// 如果被控制方是Linux/Ubuntu，OS的配置方法参考链接[4]<br /><br /><b>[控制方]</b><br />1- 安装wakeonlan，可以选择(如果有的选) apt-get install wakeonlan，或者从链接[3]获取源码手工安装（是Perl写的）<br />2- 通过wakeonlan+MAC地址的命令行方式控制需要wake up的机器，如 wakeonlan 01:23:45:67:89:AB<br />// 更高级的用法包括编写脚本，添加到cron，以及通过-f指定一个包含多个MAC地址的文件同时操作等<br /><b><br />[基本原理]</b><br />Wake-on-LAN的相关通信协议位于OSI七层模型中的数据链路层，比IP需要的网络层还要低一层，在局域网范围发送广播，数据包格式为：<br />FF FF FF FF FF FF $MAC*16<br />即 FF FF FF FF FF FF然后重复16次对方的MAC地址，被戏称为"magic packet"。<br /><br />配置成功后，只要被控制方正常关机、挂起、休眠，且环境始终不掉电，任何时候在局域网中广播"magic packet"，指定网卡的机器就可以被唤醒。<br /><i><br />链接:</i><br />[1] <a target="_blank" title="http://en.wikipedia.org/wiki/Wake-on-LAN" href="http://en.wikipedia.org/wiki/Wake-on-LAN">http://en.wikipedia.org/wiki/Wake-on-LAN</a><br />[2] <a target="_blank" title="http://en.wikipedia.org/wiki/OSI_model" href="http://en.wikipedia.org/wiki/OSI_model">http://en.wikipedia.org/wiki/OSI_model</a><br />[3] <a target="_blank" title="http://gsd.di.uminho.pt/jpo/software/wakeonlan/" href="http://gsd.di.uminho.pt/jpo/software/wakeonlan/">http://gsd.di.uminho.pt/jpo/software/wakeonlan/<br /></a>[4] <a target="_blank" title="http://ubuntuforums.org/showthread.php?t=234588" href="http://ubuntuforums.org/showthread.php?t=234588">http://ubuntuforums.org/showthread.php?t=234588<br /></a><br /><br /><img src ="http://www.blogjava.net/sean/aggbug/260576.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">大胃</a> 2009-03-18 20:03 <a href="http://www.blogjava.net/sean/archive/2009/03/18/260576.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Dreaming in Code 是本好书</title><link>http://www.blogjava.net/sean/archive/2009/03/02/257268.html</link><dc:creator>大胃</dc:creator><author>大胃</author><pubDate>Sun, 01 Mar 2009 16:44:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2009/03/02/257268.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/257268.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2009/03/02/257268.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/257268.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/257268.html</trackback:ping><description><![CDATA[
		<br />周末花了一个下午和一个晚上把Scott Rosenberg的Dreaming in Code从头到尾看了一遍。最直接的感受是这本书把我之前很多记忆碎片串在了一起，成为一个生动而"完整"的故事，虽然书的内容本身组织的多少还是有点散。<br /><br /><img src="http://www.blogjava.net/images/blogjava_net/sean/dreaming_in_code.jpg" alt="dreaming_in_code.jpg" border="0" width="240" height="240" /><br /><br />我本人对Chandler这个项目并不陌生：之前出于对Python/wxWidget和开源本身的兴趣，陆续用过几个0.x的版本，一开始并不是十分友好，性能上也有问题，甚至会莫名的吃掉我机器上的数百兆（或者上G?）空间。后来的版本在性能和可用性上确实提高了不少，但一直感觉这个项目缺少必要的、以及许多开源项目应有的momentum。Phillip J. Eby对Chandler开发人员不懂Python的批评，当时我的印象也很深。而项目中出现的人物，包括Mitchell Kapor、Ted Leung，也都在Chandler这个范畴之外follow过。其他细节包括：Chandler和Cosmo这两个名称的由来、Chandler项目组中女性成员相对高的比例、一些熟悉的人物及其观点（Alan Kay, Bill Joy, Frederick Brooks, Donald Knuth、Linus Torvalds, Ward Cunningham, Larry Wall, Guido van Rossum, Joel Spolsky, etc.）、一些公司的分分和和以及人员流动等等。感觉挺亲切的。<br /><br />可能更重要、也更深刻的原因是：尽管书中一再提到"There's no such thing as a typical software project, every project is different"，我仍然深深的感觉到，Chandler遇到的这些问题，其实也是我亲历的很多项目的种种问题的一个缩影。对这些问题，作者并没有给出解决方案，其实谁也没有标准答案。软件开发是一项非常具有挑战性的工作，也正是像我们这样有热情、有涵养的专业人士生存的空间和价值所在。<br /><br /><img src ="http://www.blogjava.net/sean/aggbug/257268.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">大胃</a> 2009-03-02 00:44 <a href="http://www.blogjava.net/sean/archive/2009/03/02/257268.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Debt Metaphor</title><link>http://www.blogjava.net/sean/archive/2009/02/22/256062.html</link><dc:creator>大胃</dc:creator><author>大胃</author><pubDate>Sun, 22 Feb 2009 09:50:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2009/02/22/256062.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/256062.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2009/02/22/256062.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/256062.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/256062.html</trackback:ping><description><![CDATA[
		<br />以下是一段视频，Ward Cunningham针对Debt Metaphor这个隐喻的由来和人们对它的一些误解进行了澄清：<br /><br /><object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/pqeJFYwnkjE&amp;hl=zh_CN&amp;fs=1" /><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><embed src="http://www.youtube.com/v/pqeJFYwnkjE&amp;hl=zh_CN&amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object><br /><br />我最感兴趣的是Burden这一段：Cunningham解释说，经常看到有些开发团队，他们快速的开发出软件产品推向市场，不断的往里面添加新的特性，在这个过程中，不断的学习，但从不把学到的东西、总结的经验教训应用回去，这就像是从银行借贷，但从不想着有一天需要偿还（是不是有点像是在说引发这次次贷危机的美国人的消费习惯和观念？），到最后，你所有的收入都将用于偿还利息，你的购买力也将降为零。映射回软件开发的语境，如果我们在一个较长的时间跨度内，开发一个软件，不断的增加feature，但从不回过头去整理和重构，把对这个软件和这些特性的新的理解和认知写回去，那么最终这个软件、这些feature将不再会有任何实际的价值，对它们做任何事，都将花费越来越多的时间和精力，开发进度也就因此下降为零。<br /><br /><br /><img src ="http://www.blogjava.net/sean/aggbug/256062.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">大胃</a> 2009-02-22 17:50 <a href="http://www.blogjava.net/sean/archive/2009/02/22/256062.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>开始"养"紫砂</title><link>http://www.blogjava.net/sean/archive/2009/02/21/255991.html</link><dc:creator>大胃</dc:creator><author>大胃</author><pubDate>Sat, 21 Feb 2009 14:49:00 GMT</pubDate><guid>http://www.blogjava.net/sean/archive/2009/02/21/255991.html</guid><wfw:comment>http://www.blogjava.net/sean/comments/255991.html</wfw:comment><comments>http://www.blogjava.net/sean/archive/2009/02/21/255991.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.blogjava.net/sean/comments/commentRss/255991.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sean/services/trackbacks/255991.html</trackback:ping><description><![CDATA[
		<br />经历了有史以来最忙碌的一周，当然要好好放松一下，除了听上乘的古典音乐，沏上一壶上等的乌龙细细品味，也是一种享受。乌龙茶和紫砂壶可是绝配，如果是安溪的铁观音，加上做工精良的宜兴紫砂壶，那滋味，唇齿留香，别提多惬意了。<br /><br />好的紫砂壶是需要"养"的，今天专程去茶城败了一只回来，开始"喂"铁观音，哈哈。<br /><br /><img src="http://www.blogjava.net/images/blogjava_net/sean/DSC_1768s.JPG" alt="DSC_1768s.JPG" border="0" width="532" height="354" /><br /><br /><br /><img src ="http://www.blogjava.net/sean/aggbug/255991.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sean/" target="_blank">大胃</a> 2009-02-21 22:49 <a href="http://www.blogjava.net/sean/archive/2009/02/21/255991.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>