<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Leechael's Weblog</title>
 <link href="http://yan-yan.info/atom.xml" rel="self"/>
 <link href="http://yan-yan.info/"/>
 <updated>2011-08-01T11:08:57-07:00</updated>
 <id>http://yan-yan.info/</id>
 <author>
   <name>Leechael Yim</name>
   <email>yanleech@gmail.com</email>
 </author>


 
 <entry>
   <title>在 Mac OS 10.7 上安装 MySQL 5.5.15 及 mysql-python</title>
   <link href="http://yan-yan.info/2011/install-mysql-5.5-on-mac-os-10.7-with-python-support.html"/>
   <updated>2011-08-02T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2011/install-mysql-5.5-on-mac-os-10.7-with-python-support</id>
   <content type="html">&lt;p&gt;首先，你需要下载 MySQL 5.5.15 的安装包：&lt;a href=&quot;http://dev.mysql.com/downloads/mysql/&quot; target=&quot;_blank&quot; title=&quot;MySQL :: Download MySQL Community Server&quot;&gt;http://dev.mysql.com/downloads/mysql/&lt;/a&gt; 。请选择 64-bit 的 DMG 版本下载。我这边是广州电信，选择 &lt;a href=&quot;mysql.ntu.edu.tw&quot; target=&quot;_blank&quot;&gt;mysql.ntu.edu.tw&lt;/a&gt; 这一镜像下载，基本上是跑满速的。&lt;/p&gt;

&lt;p&gt;除了安装基本的 MySQL 服务以后，另外的两个文件 MySQLStartupItem.pkg 及 MySQL.prefPane 也依次打开进行安装，这样 MySQL 便会跟随系统启动而启动，并且会在系统设置面板添加一个管理面板。&lt;/p&gt;

&lt;p&gt;安装完毕后，可以通过命令行简单测试键入 &lt;code&gt;mysql&lt;/code&gt;，在我这里，是能够进入 MySQL 命令行的交互窗口，整个安装过程是十分顺畅的。&lt;/p&gt;

&lt;p&gt;然后是 mysql-python：&lt;code&gt;sudo easy_install MySQL-python&lt;/code&gt;。这一过程理应也是顺畅无助的，除非你遭遇和我类似的情况，在安装完成后，&lt;code&gt;import MySQLdb&lt;/code&gt; 时提示 &lt;q&gt;Reason: image not found&lt;/q&gt;。&lt;/p&gt;

&lt;p&gt;在这篇 &lt;a href=&quot;http://stackoverflow.com/questions/4559699/python-mysqldb-and-library-not-loaded-libmysqlclient-16-dylib&quot; target=&quot;_balnk&quot;&gt;Python: MySQLdb and “Library not loaded: libmysqlclient.16.dylib”&lt;/a&gt; 中，有人提及了一个办法，修改环境变量 &lt;code&gt;DYLD_LIBRARY_PATH&lt;/code&gt;。在这里，我是把以下这行代码加入至 &lt;code&gt;~/.profile&lt;/code&gt; 中，修复这一问题：&lt;/p&gt;

&lt;pre lang=&quot;bash&quot;&gt;
export DYLD_LIBRARY_PATH=&quot;$DYLD_LIBRARY_PATH:/usr/local/mysql/lib&quot;
&lt;/pre&gt;

&lt;p&gt;至此，我这里是能够正常使用 python 和 MySQL 进行开发的了。整个过程中，参考了以下文章，如果上述文字未能解决你的问题，不妨看看这些文章：&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;
		&lt;a href=&quot;http://www.djangoapp.com/blog/2011/07/24/installation-of-mysql-server-on-mac-os-x-lion/&quot; target=&quot;_blank&quot;&gt;Installation of MySQL server on Mac OS X Lion&lt;/a&gt;
	&lt;/li&gt;
	&lt;li&gt;
		&lt;a href=&quot;http://hearrain.com/2011/01/494&quot; target=&quot;_blank&quot;&gt;Mac下MySql安装经历（含安装错误排查、卸载多种折腾）&lt;/a&gt;
	&lt;/li&gt;
	&lt;li&gt;
		&lt;a href=&quot;http://stackoverflow.com/questions/4559699/python-mysqldb-and-library-not-loaded-libmysqlclient-16-dylib&quot; target=&quot;_blank&quot;&gt;Python: MySQLdb and “Library not loaded: libmysqlclient.16.dylib”&lt;/a&gt;
	&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 

 
 <entry>
   <title>parchive（par2)：类似 RAID 的数据校验和修复工具</title>
   <link href="http://yan-yan.info/2011/introduction-to-par2.html"/>
   <updated>2011-05-09T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2011/introduction-to-par2</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://myzsyweb.blogspot.com/2009/01/parchivepar2.html&quot; title=&quot;校验及恢复工具Parchive(Par2)&quot;&gt;先来一段简介：&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;h4&gt;Parchive: Parity Archive Volume Set&lt;/h4&gt;
&lt;p&gt;这个项目背后最初的想法是提供一个工具把类独立磁盘冗余阵列(RAID-like)系统的数据恢复能力思想应用到新闻组上多部分文档的发布和恢复。我们实现了那个目标。对这个规范的2.0版本我们的新目标是改善。&lt;/p&gt; 
&lt;p&gt;The technology is based on a 'Reed-Solomon Code' implementation that allows for recovery of any 'X' real data-blocks for 'X' parity data-blocks present. (Data-blocks referring to files OR much smaller virtual slices of files).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;我的理解，就是通过软件实现类似 RAID 的冗余方案，避免因为传输过程中的出错，通过适量的冗余文件添加数据恢复的功能。&lt;/p&gt;

&lt;p&gt;安装和使用都很简单，Debian/Ubuntu 下常规的 &lt;code&gt;sudo apt-get install par2&lt;/code&gt;，Mac OS X 下通过 homebrew 安装即可：&lt;code&gt;sudo brew install par2&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;由于 parchive 只是&lt;strong&gt;对单一文件提供冗余和校验的功能&lt;/strong&gt;，因此并不生成新的文件，只是增加数个文件用于检验和恢复（增加的文件数目视乎 &lt;var&gt;-r&lt;/var&gt; 这个参数的值；针对文件夹的话，肯定要结合 &lt;var&gt;tar&lt;/var&gt; 确立方案了。&lt;/p&gt;

&lt;p&gt;我这里使用这个小东西的场景很简单，一个是服务器备份，本机机器每天跑 &lt;var&gt;rsync&lt;/var&gt; 拉备份，每天做一份 snapshot，保留最新的三个 snapshot；snapshot 简单使用 &lt;var&gt;tar&lt;/var&gt; 打包，然后使用 parchive 做检验和冗余。&lt;/p&gt;

&lt;p&gt;其实不排除某些信任不足的人，要求提供备份文件，这个时候就会使用 7z 分卷造成 DVD 大小，每个分卷文件造一份用于校验及修复的 parchive 文件。这个使用场景有点无语，不过也算是合适吧。&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>译文：网络设计师应该知道的事情</title>
   <link href="http://yan-yan.info/2011/chinese-translated-what-every-web-designer-should-know.html"/>
   <updated>2011-05-04T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2011/chinese-translated-what-every-web-designer-should-know</id>
   <content type="html">原文地址：&lt;a href=&quot;http://www.lukew.com/ff/entry.asp?1311&quot; target=&quot;_blank&quot;&gt;What Every Web Designer Should Known&lt;/a&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;随着网络世界的扩张，任何人都可以创建内容并且通过社交网络进行分享。在人们可以控制内容在你的设计中如何展示的时候，设计者应该如何开展设计？&lt;/li&gt;
&lt;li&gt;这并不只是你不能掌控的视觉体验。通过类似 Instapaper 或者 Readability 这样的工具，人们可以随时随地转换如何消费内容的体验。&lt;/li&gt;
&lt;li&gt;这并非新近出现的体验。人们总是能够通过不同的设备、浏览器甚至自定义的页面样式决定他们的网络体验。对此我们早已进行评估（译注：不同浏览器下的兼容性，易用性 accessibility），但现况是，这需求更为明显了。&lt;/li&gt;
&lt;li&gt;这不仅是我们如何让站点的体验更为平滑化， 更是我们如何定义我们该干点什么。每一年 AEA （美国经济学会）的调查都显示，对于同样的工作，人们有不同的称呼：网络管理员和创意总监都在干着同样的工作。这些专业人士热衷于讨论怎么称呼他们。&lt;/li&gt;
&lt;li&gt;不为服务于人们的设计也不会服务于商业。当你所干的事情是反用户的，你正在制造反用户模式。例如，在你不知道的情况下，向你地址簿中的联系人发送电邮的服务。&lt;/li&gt;
&lt;li&gt;内容先于设计。离开内容，设计只是装点。过去我们经常在了解内容之前进行外观和体验的设计。实际上，脱离内容的设计是十分困难的。&lt;/li&gt;
&lt;li&gt;当 Blogger （一个在线博客服务） 团队向我们索要模板，缺乏内容时是很难创造任何合适的设计。Doug Bowman 创建的统一模板至少应用在 20 万个博客上。这是为未知内容进行设计的最佳解决方案。但这是到目前为止唯一成功的例子，这也能说明脱离内容进行设计是如何的困难。&lt;/li&gt;
&lt;li&gt;网站是最简单的内容分发系统。即使页面上任何细节都需要通过实际内容测试在布局上的效果。&lt;/li&gt;
&lt;li&gt;你不能在清晰定义问题之前解决问题。你也不能独自解决这一问题。让用户参与到设计效果测试是有所帮助的，而想法往往来自于此。创新并不意味着需要去问人们的想法。&lt;/li&gt;
&lt;li&gt;我们都需要去研究如何建立网站。广告行业中的人有自家的独门秘笈，但网络中，人们往往分享他们得知的事情。我们对其他人使用的技艺感兴趣，我们也有法子去研究这些东西。&lt;/li&gt;
&lt;li&gt;现在正是建立站点和应用的最佳时机。Webkit 和移动设备，HTML5 和 CSS3，用户体验（UX）和内容策略（content strategy）带来了新的机会。&lt;/li&gt;
&lt;li&gt;过往我们说到移动设备都仅是在说那小屏幕。小屏幕的设计往往通过调整布局和媒介对更小的视觉范围进行适应。如果你是内容为主的站点，你会是需要一个针对小屏幕优化的策略而非面向移动设备优化的完整策略。&lt;/li&gt;
&lt;li&gt;真正的网络设计师会参与代码编写。一直都是这样。你至少需要了解语义化标记，以及通过 HTML 和 CSS 可以能得到点什么。&lt;/li&gt;
&lt;li&gt;渐进增强是唯一明智的缺省选项。业界中大部分人都赞同这是让任何人都能够获得体验的最佳实践。&lt;/li&gt;
&lt;li&gt;HTML5 的设计准则也能应用至网络设计之中。Pave the cowpaths = 让一切如人们预想中的那样运作。寻找人们出错时一切也能运作的方法。错误是可预料的。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 

 
 <entry>
   <title>让 redmine_gitosis 允许自定义账户访问的方法</title>
   <link href="http://yan-yan.info/2011/working-with-local-redmine-gitosis.html"/>
   <updated>2011-03-17T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2011/working-with-local-redmine-gitosis</id>
   <content type="html">&lt;p&gt;工作环境使用 Redmine 作为项目管理软件，装上 redmine_gitosis 与 Git 进行交互。由于作为 Codebase 的机器拥有多个功用，例如自动构建（我这边打算做这个……），这个时候发现无法在机器中取出通过代码；在这里，作为 codebase 的机器和需要取出代码进行自动化行为的机器是同一个机器，假设是 &lt;em&gt;box&lt;/em&gt;，自动化取出代码干活的帐号是 &lt;em&gt;bot&lt;/em&gt;。&lt;/p&gt;

&lt;p&gt;问题的根源在于， redmine_gitosis 每一次的修改都会重新生成 &lt;var&gt;memebers&lt;/var&gt; 的值。&lt;code&gt;bot@box&lt;/code&gt; 这个帐号可以取出 gitosis-admin.git 修改配置文件，但是不能访问其他项目。&lt;/p&gt;

&lt;p&gt;经过摸索，解决方案是修改 redmine_redmine。打开 &lt;var&gt;vendor/plugins/redmine_gitosis/lib/gitosis.rb&lt;/var&gt; 文件，将 57 行的：&lt;/p&gt;

&lt;pre class=&quot;code&quot; lang=&quot;ruby&quot;&gt;
conf[&quot;group #{name}&quot;]['members'] = write_users.map{|u| u.gitosis_public_keys.active}.flatten.map{ |key| &quot;#{key.identifier}&quot; }.join(' ')
&lt;/pre&gt;

&lt;p&gt;改为：&lt;/p&gt;

&lt;pre class=&quot;code&quot; lang=&quot;ruby&quot;&gt;
conf[&quot;group #{name}&quot;]['members'] = write_users.map{|u| u.gitosis_public_keys.active}.flatten.map{ |key| &quot;#{key.identifier}&quot; }.push('bot@box').join(' ')
&lt;/pre&gt;

&lt;p&gt;添加的 &lt;code&gt;push&lt;/code&gt; 中的参数为 &lt;strong&gt;gitosis/keydir&lt;/strong&gt; 目录中对应的 public key 文件名；在我这里，这一文件名是 &lt;em&gt;bot@box.pub&lt;/em&gt;。&lt;/p&gt;

&lt;p&gt;保存后重启 mongrel 的 redmine 进程（我这边是 apache2 + mongrel），随便禁用/启用一个 public key 迫使更新 gitosis-admin 配置，如无意外的话，修改成功。&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>《SEO实战密码》</title>
   <link href="http://yan-yan.info/2011/seo-in-practice.html"/>
   <updated>2011-02-26T00:00:00-08:00</updated>
   <id>http://yan-yan.info/2011/seo-in-practice</id>
   <content type="html">&lt;div class=&quot;hreview&quot;&gt;
  &lt;p class=&quot;illustration&quot;&gt;
  	&lt;a href=&quot;http://book.douban.com/subject/5348144/&quot; class=&quot;fn&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://img3.douban.com/lpic/s4525618.jpg&quot; alt=&quot;SEO实战密码&quot; width=&quot;283&quot; height=&quot;380&quot; /&gt;&lt;/a&gt;
  &lt;/p&gt;

  &lt;p class=&quot;summary&quot;&gt;&lt;b class=&quot;reviewer vcard nickname&quot;&gt;Leechael&lt;/b&gt;于 &lt;abbr class=&quot;dtreviewed&quot; title=&quot;2011-02-26&quot;&gt;2011/02/26&lt;/abbr&gt; 给《SEO实战密码》评分为&lt;abbr class=&quot;rating&quot; title=&quot;3&quot;&gt;3分（满分为5分）&lt;/abbr&gt;。&lt;a target=&quot;_blank&quot; rel=&quot;license&quot; href=&quot;http://creativecommons.org/licenses/by/2.5/cn/&quot;&gt;本文基于创作共用协议——署名条例&lt;/a&gt;发布。&lt;/p&gt;

  &lt;div class=&quot;description&quot;&gt;
    &lt;p&gt;这应该是国内最好的一本SEO相关的书了；鉴于作者在网上的名望，我也读了这本书。&lt;/p&gt;

    &lt;p&gt;书很厚，500多页。很适合初学者阅读；但价格让人却步。这本书值得扫读一番，但若说最有价值的章节，那分别是 SEOMoz Search Ranking Factors 2009 的译文、SEO案例分析这两个章节。Search Ranking Factors 2009 的译文虽然迟来了，但仍是有很高的价值。&lt;/p&gt;

    &lt;p&gt;对于SEO从业者，这书应该算是必看的。本来这书的评分可以再高一些，但《了解搜索引擎》一章质量不行，与我在 SEOMoz 看的 &lt;a href=&quot;http://guides.seomoz.org/beginners-guide-to-search-engine-optimization&quot;&gt;The Beginners Guide To SEO&lt;/a&gt; 在质量上相距甚远，后者描述让我觉得更为精确。&lt;/p&gt;

    &lt;p&gt;后面贴上我在看的时候在微博上记下的笔记。&lt;/p&gt;
  &lt;/div&gt;

  &lt;blockquote&gt;&lt;p&gt;Indented listing, sitelinks, mini sitelinks, one-box, rich snippet, breadcrumb, link in description, 都是搜索引擎(google)在搜索结果显示方面的尝试，而好的站点/页面信息架构可以帮助搜索引擎提取相应信息、以更好的方式显示搜索结果。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;常用词的极致就是停止词。停止词因为使用频繁，对搜索结果排名意义不大。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;没有做竞者分析、没有规划好目标关键字，是seo效果不佳的原因之一。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;流量本身并不一定是资产，很可能是浪费带宽、客服的无谓付出，只有能转化的有效流量才是资产。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;你的网站能为用户解决什么问题？用户遇到这些问题时，会搜索什么样的关键字？如果你是用户，你会怎么进行搜索？用户搜索你的产品时会搜索什么关键字？这些问题有助于(从现有的竞者分析和关键字研究结果中)挑选核心关键字。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;Google AdWords提供了帮助选择关键字的工具(百度的凤巢系统理论上也有相应的工具)。此外，搜索建议，相关搜索，或者一些在线工具(免费或收费的)都可以作为选择关键字时的辅助工具。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;站点关键字布局需要和站点的信息架构紧密相连，站点分类能够和关键字逻辑分组对应更佳。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;单个页面关键字不能过多，两到三个为适宜，这样在页面写作能更有针对性。同时每个页面针对的关键字，不要重复出现在网站的多个页面上，这会造成不必要的内部竞争。关键字研究决定内容策划。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;根据搜索目的，关键字可分为导航类，交易类和信息类。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;预计流量和排名并非关键字研究的必要步骤。在我看来( @leechael )，对比预期结果和实际结果是改进的一部分。所以粗略预计流量和排名还是有必要的。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;竞者分析的对象是核心关键词前十到前二十名的站点。需要注意的数据包括域名年龄，PR，快照日期，收录页面数，外链情况，主要目录收录情况，社会化媒体出现情况。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;现时的竞者分析，应该加重了在社会化媒体中调查的力度了吧。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;页面标题，网站栏目，url，link structure，目的页到首页的点击距离，是否有实质内容，是否有flash、js，语义标签(原文为h1、h2标签)是否正确使用，都是竞者分析的一部分。竞者分析也适合用于作为快速网站诊断。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;快速网站诊断还应该包括页面收录比例的评估。注意，抓取量、收录量是两个不同的概念，100%的抓取率不等于100%的收录率。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;各大搜索引擎提供的 web master工具是不可缺少的辅助工具。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;闭卷休息。才100多页，读得有点慢。关键字分析这章质量最高，对搜索引擎原理的介绍不如seomoz的beginner guide质量好和精准。今晚读完三分之一应该不是问题。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;标题标签是优化重点，描述标签对排名权重无影响，但能够帮助用户快速了解页面内容。关键字标签作用几近于零。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;正文中的词频和密度无关紧要。关键词有出现过即可，但首段文字必须出现关键词，正文中亦可出现关键词的变体。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;X-Robots-Tag header 和 Robots meta tag，哪个优先级更高？&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;网站目标要非常明确，具有可操作性。对：网站营销人员来说，想让浏览用户在网站上做的那件具体的事就是网站目标。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;网站收录(索引量)不充分一般都是因为下面的原因之一：域名权重不高；网站结构有问题；内链分布不均；页面并非搜索引擎友好；内容原创度不足。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;关键字排名和流量的直接关系不大。近年搜索引擎引入个性化排序和地域化排序，关键字排名不具有绝对性。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;网站内部优化就算做到极致，所能获得的排名分数也是有限的。而外部链接只要自然成长，潜力却是无限的。把时间、精力放在创造高质量内容和吸引多种多样的链接上，比把时间花在页面细节上要有效得多，也安全得多。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;公司名称、口号、广告语等品牌元素应该与 SEO 完美配合。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;网络危机公关亦是 SEO 可以发挥作用的地方。删帖不是有效的方法，利用高权重的发布渠道发布正面新闻挤兑负面新闻、使其在结果排名页只能获得较差的排名是一个可用的手段。社会化媒体站点的日常活跃程度有助于出现危机时进行危机公关处理。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;用户喜欢的，搜索引擎就会喜欢。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;SEO是网络营销的一个手段，时间成本高、乃至人力成本高，则失败风险较高。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;95%的SEO问题可以通过以下手段解决：至少整体方向的关键词研究；网站结构及内部链接、解决收录问题；页面标题标签、H1标签等数处最重要代码；文章出现关键词两到三次；内容原创性、避免复制内容；有趁手的外链建设方法。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;非基本问题如关键词密度、关键词位置、链接锚文字、URL设计等，若需花费时间过多，倒不如暂时搁浅。解决这些问题的贡献不过5%。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;SEO效果的比较基准可以选取SEO执行前站点的收录、排名、流量等数字，以及主要竞争对手站点的收录、排名、流量等数字。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;技术部门的规范可包括：URL命名系统，页面title、H1、图片替代文字规范和格式、站点地图、导航、css/js使用规范、内链及栏目设置规范。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;内容编辑部门的规范可包括：关键词研究流程、文章标题写作规范和举例、文章关键词分布要求、正文内部链接生成方法和规范、检测热门关键词及建立专题流程、用户贡献内容审核编辑规范。&lt;/p&gt;&lt;/blockquote&gt;

  &lt;blockquote&gt;&lt;p&gt;搜索引擎的爬虫会因为内容质量的高低调整对一个网站的爬行频率和爬行覆盖率。&lt;/p&gt;&lt;/blockquote&gt;
&lt;/div&gt;
</content>
 </entry>
 

 
 <entry>
   <title>摊贩</title>
   <link href="http://yan-yan.info/2011/yatai.html"/>
   <updated>2011-02-19T00:00:00-08:00</updated>
   <id>http://yan-yan.info/2011/yatai</id>
   <content type="html">&lt;p&gt;洗澡的时候忽然想《What The Dog Saw》中的这个故事；然后把书翻出来重读了一遍这文。&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;他们娶了漂亮的女人，积累了巨额财富，盗用彼此的产品创意和理念，在晚上睡不着觉时琢磨切洋葱而不被呛得流眼泪的方法，而人们夺眶而出的则是欢喜的眼泪。他们认为让产品研发与市场营销各行其道是个错误，而同时代的绝大多数商家都在延续这个错误，因为对他们而言二者是密不可分的：卖得好的东西一定是本身品质好的东西。&lt;/p&gt;&lt;/blockquote&gt;

&lt;blockquote&gt;&lt;p&gt;“你吃过多少次熏火鸡三明治？也许你六个月才会吃一次熏火鸡或熏鸡三明治。六个月啊！你吃过多少次熏鲑鱼？哈，也许更久才能吃一次。我要对你说的是你每三个月才将熏鲑鱼作为正餐前的开胃食品或者第一道菜。小肋排？这要看你在哪家餐馆点肋排了。和熏肠一样的做法，你喜欢熏烤食品。”他碰了一下我的胳膊，着重强调道——“不过我晓得，马尔科姆。你没有熏烤机。”&lt;/p&gt;&lt;/blockquote&gt;

&lt;blockquote&gt;&lt;p&gt;你可以从一名摊贩身上挖掘出出色演员才具备的天赋，但是你不可能从一位演员身上总能挖掘出出色的摊贩的禀赋。&lt;/p&gt;&lt;/blockquote&gt;

&lt;blockquote&gt;&lt;p&gt;那么你如何说服人们打乱既有的秩序呢？不单单是讨好逢迎或者真诚的态度，即使名声再大和人长得再漂亮也无济于事。你必须向消费者解释这种新事物——不是一次两次就行的，要三次四次不厌其烦。你必须向他们准确演示它的工作原理以及为什么会这样切东西，在用它切肝时要让切片机服从手的指令，然后准确地告诉消费者如何才能让切片机符合他们的使用习惯，最后还要让他们明白这个自相矛盾的事实，即工具上的革命和创新不是以操作复杂为代价的。&lt;/p&gt;&lt;/blockquote&gt;

&lt;blockquote&gt;&lt;p&gt;艾伦·巴克斯说在最初版本的“烧烤秀”播出后，罗恩开始专注于肉变色的质量和均匀度，确信烤肉叉的旋转速率会导致烤肉略有差别。样机每分钟旋转四圈。罗恩在他的厨房里进行过对比实验，以不同速率烤了一只又一只鸡，一直持续到他断定最佳速率是每分钟六圈。人们可以想象一位目光敏锐的MBA在阅读了一大摞小组讨论报告后，争辩说龙科实际上卖的是便利性和健康生活理念，为了烤成金黄色在设备改进方面投入数万美元实际上是愚蠢之举。但是，罗恩明白烤出来的东西泛出金黄色之所以很重要，同倾斜的玻璃进料口之所以很重要如出一辙：因为产品设计的方方面面必须确保演示过程的透明性和效率。它在舞台上表现得越好，摊贩就越容易大获其利。&lt;/p&gt;&lt;/blockquote&gt;

&lt;blockquote&gt;&lt;p&gt;是罗恩·波佩尔，那位在自己厨房里发明了更好的烧烤方式，然后走出去亲自推销的人。&lt;/p&gt;&lt;/blockquote&gt;
</content>
 </entry>
 

 
 <entry>
   <title>说说小团队开发(2)</title>
   <link href="http://yan-yan.info/2010/talk-about-team-working-part-2.html"/>
   <updated>2010-12-31T00:00:00-08:00</updated>
   <id>http://yan-yan.info/2010/talk-about-team-working-part-2</id>
   <content type="html">&lt;p&gt;从年初到现在，大概做了好几个项目：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;始于去年年末的企业站，基于 Drupal 的二次开发。&lt;/li&gt;
&lt;li&gt;企业站，基于 Joolma 的二次开发。&lt;/li&gt;
&lt;li&gt;某个微博客服务的 Firefox 插件。&lt;/li&gt;
&lt;li&gt;一个静态页面为主的小企业站。&lt;/li&gt;
&lt;li&gt;一个简易 CMS 的开发；两个基于这个简易 CMS 的小站点。&lt;/li&gt;
&lt;li&gt;一个 iPhone 相关的项目。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;也不一一列数每个项目的经验教训了，毕竟失败的多（低于我的期望值）。只简单说说我所得的。&lt;/p&gt;
&lt;h3&gt;需求管理&lt;/h3&gt;
&lt;p&gt;对于项目管理者和开发者，这都是一个重要的课题。因为有需求，所以才有项目，而在项目开发过程中，闲着的项目管理者或多或少会继续思考整个项目，继而新的需求产生了。&lt;/p&gt;
&lt;p&gt;在《敏捷迭代开发管理者指南》中的《时间箱迭代开发》一节，说到一个项目里面有四个变量：资源（人员），范围（任务），时间，质量。以时间盒的方式固定一个变量，然后在一定时间内（一个迭代中）的任务是相对固定的；新任务将会在下一个迭代中再进行考虑。&lt;/p&gt;
&lt;p&gt;在开始之时，我期望项目管理者能够给出&lt;em&gt;详尽的文档&lt;/em&gt;，然后再开始进行开发；然而这不现实，瀑布式开发不适合于 Web Development。继而，我希望项目管理者（或者，产品负责人）能够提出明确的需求。然而需求总会是模糊的，因为他们都不知道真正需要的是什么。&lt;strong&gt;他们需要可以在业务上支撑探索试错的代码。 &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;另一方面来说，目标要明确：能运行是一个目标。兼容性问题是一个目标，稳定性问题是一个目标。一个阶段的目标必须要清晰明确解决哪些问题。&lt;/p&gt;
&lt;h3&gt;项目管理与团队&lt;/h3&gt;
&lt;p&gt;项目管理者有一个职责是，帮助团队成员的成长。优秀的开发者总是短缺的。那么，怎么帮助一个经验不足的开发者成长也算是项目管理者的一个责任了。对于项目管理者而言，有两个东西是必须的：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;em&gt;Bug Tracking System&lt;/em&gt; – 需求管理也可以这个系统开展。&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Test Driven Development&lt;/em&gt; – 将需求转化为可测试的描述。单元测试、&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;我不敢说或者这才是让开发者快速开发符合业务需求的最佳良方；我正在尝试这两个东西，别人说有效，但自己也得进行尝试。当然，更多的 Best Practices 包括版本化管理、持续集成、自动构建、学习使用更好的工具（例如，vim）、每个迭代后的自省和改进、重构，也列数不出来了。若然项目管理者关注开发者是否有良好的编码习惯，是否已经将重复的工作尽可能地自动化，是否从这些习惯中获得更高的编码效率和代码质量——我想这样比单纯的给他们分享技术文档、教程来得更好。&lt;/p&gt;
&lt;h3&gt;开发&lt;/h3&gt;
&lt;p&gt;在前文引用的文章中，有一篇谈及使用 VMware 统一开发平台，对此我深有感触。开发平台是铁定需要统一的，特别是对于我这种有代码洁癖的人而言。统一的开发环境配置，统一的编辑器配置，这些都有助于开发。&lt;/p&gt;
&lt;p&gt;至于统一开发平台配置这点，我计划进行尝试，或者届时我会写点什么。&lt;/p&gt;
&lt;h3&gt;部署、运维和监控&lt;/h3&gt;
&lt;p&gt;Google Analytics，awstats，监控宝都是好东西。或者还存在更多我暂时说不上的或者我不知道的好东西。&lt;/p&gt;
&lt;p&gt;部署一定要自动化。自动化有什么好处呢？例如你运行 &lt;code&gt;rake deploy production&lt;/code&gt;，整个运行环境就已经完成初始化了，你说这省事不省事？&lt;/p&gt;
&lt;p&gt;写得有点乱，差点不好意思发了。&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>safari mobile 如何处理页面中的电话号码</title>
   <link href="http://yan-yan.info/2010/how-safari-mobile-process-with-tel-number-on-page.html"/>
   <updated>2010-12-28T00:00:00-08:00</updated>
   <id>http://yan-yan.info/2010/how-safari-mobile-process-with-tel-number-on-page</id>
   <content type="html">&lt;p&gt;在 &lt;a href=&quot;http://microformats.org/wiki/mobile&quot; target=&quot;_blank&quot;&gt;MicroFormats的报告&lt;/a&gt; 中，其实已经知道，&lt;strong&gt;iOS4 中的 mobile safari 不支持 &lt;a href=&quot;http://microformats.org/wiki/hCard&quot; target=&quot;_blank&quot;&gt;hCard&lt;/a&gt;&lt;/strong&gt;。但此前的试验中，我误认为 iOS4 中的 mobile safari 是支持 hCard 的；经过试验后，结论是误判：原因是 mobile safari 会自动将页面中的电话号码自动转换成为可以拨打的电话号码（format-detection header）。&lt;/p&gt;
&lt;p&gt;format-detection 会在页面载入后，转化页面上的电话号码为可拨打电话的链接。对于后续通过 JavaScript 插入的内容而言，format-detection 无效。&lt;/p&gt;
&lt;p&gt;但是苹果提供了另一个解决方案：&lt;a href=&quot;http://developer.apple.com/library/safari/#featuredarticles/iPhoneURLScheme_Reference/Articles/PhoneLinks.html&quot; target=&quot;_blank&quot;&gt;URL Scheme 中的 phone link&lt;/a&gt;。实际上也不算是一个 apple-only 的解决方案，&lt;a href=&quot;http://tools.ietf.org/html/rfc2806&quot; target=&quot;_blank&quot;&gt;RFC2806&lt;/a&gt; 和 &lt;a href=&quot;http://tools.ietf.org/html/rfc3966&quot;&gt;RFC3966&lt;/a&gt; 是描述 Tel URI 的标准。从苹果文档中看到，它只简单实现了 RFC2806 中的支持。&lt;/p&gt;
&lt;p&gt;而 Tel URI 在关闭 format-detection 后是仍然可用的。&lt;/p&gt;
&lt;p&gt;BTW，总结文果然很水的感觉。&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>重构 rsync 备份脚本小记</title>
   <link href="http://yan-yan.info/2010/refactor-rsync-based-backup-script.html"/>
   <updated>2010-12-22T00:00:00-08:00</updated>
   <id>http://yan-yan.info/2010/refactor-rsync-based-backup-script</id>
   <content type="html">&lt;p&gt;用于备份服务器的脚本坏了，猜测原因有二：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;登录服务器时验证失败了，&lt;/li&gt;
  &lt;li&gt;输出重定向有误。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;对于第一个问题，给脚本加上 &lt;code&gt;sudo -u USERNAME&lt;/code&gt;，事实证明这是很笨而且无效的方法。 &lt;span class=&quot;emotion&quot;&gt;:(&lt;/span&gt; &lt;/p&gt;

&lt;p&gt;直接运行脚本是能够正常工作的。再看 &lt;code&gt;rsync&lt;/code&gt; 的参数，我是这样写的：&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;rsync REMOTE_ALIAS:/path/to/somewhere/ /local/dir&lt;/pre&gt;

&lt;p&gt;用了 &lt;code&gt;ssh&lt;/code&gt; 的 alias。笨方法是 &lt;code&gt;cp&lt;/code&gt; 一份 &lt;var&gt;.ssh&lt;/var&gt; 的设置到 &lt;var&gt;/root&lt;/var&gt;目录下，另一个解决方案是使用 &lt;code&gt;rsync&lt;/code&gt; 的 &lt;var&gt;-e&lt;/var&gt; 参数：&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;rsync -e &quot;ssh -i /home/MY_USERNAME/.ssh/id_rsa -p 333&quot; REMOTE_USERNAME@IP:/path/to/somewher/ /local/dir&lt;/pre&gt;

&lt;p&gt;通过 &lt;var&gt;-i&lt;/var&gt; 指定 rsa 文件，通过 &lt;var&gt;-p&lt;/var&gt; 指定端口(你不更改远程服务器的登录端口？)。&lt;/p&gt;

&lt;p&gt;至于输出重定向，主要是用于记录 rsync 的输出，主要是手误，改掉就好了。&lt;/p&gt;

&lt;p&gt;当然，折腾开了，也就多加点什么进去吧：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code&gt;nice&lt;/code&gt;，减低备份工作的优先级。&lt;/li&gt;
  &lt;li&gt;对 &lt;code&gt;rsync&lt;/code&gt; 的 exit status 进行判断，错误则给我发 Email。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;对于第一个需求，使用 &lt;var&gt;–rsync-path&lt;/var&gt; 参数：&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;rsync --rsync-path=&quot;nice -n 19 rsync&quot;&lt;/pre&gt;

&lt;p&gt;至于第二个需求，用 &lt;code&gt;sendemail&lt;/code&gt; 解决这个需求：&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;sudo apt-get install sendemail libio-socket-ssl-perl libnet-ssleay-perl&lt;/pre&gt;

&lt;p&gt;然后加入脚本中：&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;
sendemail -f bot@domain -t admin@domain \
    -u &quot;[&quot;`date +'%F'`&quot;] Backup fails&quot; \
    -m &quot;See log for more information.&quot; \
    -s smtp.gmail.com:587 \
    -o &quot;tls=yes&quot; \
    -xu your_account \
    -xp your_password
&lt;/pre&gt;

&lt;p&gt;这里使用 Gmail 发送邮件，这个似乎可以抽离做第二个脚本（发送预警邮件），暂时也就这个样子好了。&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>说说小团队开发(1)</title>
   <link href="http://yan-yan.info/2010/talk-about-team-working.html"/>
   <updated>2010-12-01T00:00:00-08:00</updated>
   <id>http://yan-yan.info/2010/talk-about-team-working</id>
   <content type="html">&lt;p&gt;从看到的一篇东西说起吧： &lt;a href=&quot;http://1-byte.jp/2010/11/30/team_development&quot; target=&quot;_blank&quot;&gt;少人数開発に役立つ5つのまとめ&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;不会日文的用机器翻译，我也是这样看完的（不想看日文的就不要点击了）。因为这篇东西是对几篇文章的总结，我就简单总结和列出一些要点。&lt;/p&gt;

&lt;h3&gt;&lt;a href=&quot;http://blog.madoro.org/mn/84&quot; target=&quot;_blank&quot;&gt;スタートアップ企業で8年間Webの開発をしてみての反省点いろいろ&lt;/a&gt;&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;谨慎考虑究竟要做的是什么（YAGNI）
&lt;ol&gt;
  &lt;li&gt;关系型数据库的使用
&lt;ol&gt;
  &lt;li&gt;是否需要使用事务&lt;/li&gt;
  &lt;li&gt;锁的范围：是什么导致了数据库死锁(deadlock)&lt;/li&gt;
  &lt;li&gt;遵循范式的设计；谨慎考虑反范式的设计&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
  &lt;li&gt;切忌在服务器配置上铺张浪费，够用则好&lt;/li&gt;
  &lt;li&gt;HTTP头是否被正确地设置？&lt;/li&gt;
  &lt;li&gt;浏览器缓存/中转代理服务器缓存是否被正确利用？&lt;/li&gt;
  &lt;li&gt;Log rorating 是否正确地运作？&lt;/li&gt;
  &lt;li&gt;对全部log文件进行监控&lt;/li&gt;
  &lt;li&gt;是否进行了测试？测试结果是否正常？&lt;/li&gt;
  &lt;li&gt;测试是否经常被进行？结果是否正常？&lt;/li&gt;
  &lt;li&gt;服务器出现问题时，是否能够在最短时间内收到通知？&lt;/li&gt;
  &lt;li&gt;重复的工作是否已经全部自动化？&lt;/li&gt;
  &lt;li&gt;把握好文档的粒度：现有文档是否最新？&lt;/li&gt;
  &lt;li&gt;有没有多余的文档？&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
  &lt;li&gt;考虑使用现有的产品
&lt;ol&gt;
  &lt;li&gt;不要重复制作 framework&lt;/li&gt;
  &lt;li&gt;自行开发：性能问题及扩展性问题——尽可能使用现有的解决方案&lt;/li&gt;
  &lt;li&gt;新人的培训问题：考虑现有资源，Google it.&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
  &lt;li&gt;模块化开发：松耦合&lt;/li&gt;
  &lt;li&gt;技术负债需要尽早还清&lt;/li&gt;
  &lt;li&gt;购买合适的服务器：服务器要易于扩展。&lt;/li&gt;
  &lt;li&gt;要有专职的服务器维护人员&lt;/li&gt;
  &lt;li&gt;考虑云服务&lt;/li&gt;
  &lt;li&gt;创建好的公司文化&lt;/li&gt;
  &lt;li&gt;新人员：在完成一个阶段的任务后再考虑补入新人员&lt;/li&gt;
  &lt;li&gt;晨会：每天？每周？或是公司内部研讨会？这些都尽可能避免&lt;/li&gt;
  &lt;li&gt;公司人员间的距离&lt;/li&gt;
  &lt;li&gt;人才储备：考虑内部推荐&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;&lt;a href=&quot;http://engineer.blog.reet.co.jp/2010/10/knack_of_multiple_developing/&quot; target=&quot;_blank&quot;&gt;複数人(2-3人)でウェブサービスを開発するコツ&lt;/a&gt;&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;开发环境
&lt;ol&gt;
  &lt;li&gt;使用 VMware ESXi 构建开发环境&lt;/li&gt;
  &lt;li&gt;Bug Tracking System + VCS: redmine/trac + git/subversion&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
  &lt;li&gt;规范化
&lt;ol&gt;
  &lt;li&gt;有约定的编码规范，例如 Zend Framework 的编码规范&lt;/li&gt;
  &lt;li&gt;一分钟晨会：昨天干了什么，今天打算干什么&lt;/li&gt;
  &lt;li&gt;即使坐在隔壁也使用 Skype 或 IRC 通话：工作的状态被打断了是一件很困扰的事情。&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
  &lt;li&gt;开发
&lt;ol&gt;
  &lt;li&gt;使用 tickets 进行任务分配&lt;/li&gt;
  &lt;li&gt;测试驱动开发&lt;/li&gt;
  &lt;li&gt;灵活使用 VCS 的 hooks&lt;/li&gt;
  &lt;li&gt;灵活使用 redmine 的 code review 插件&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
  &lt;li&gt;结束开发以后
&lt;ol&gt;
  &lt;li&gt;文档化&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;还有一篇译文（当然是英文翻译到日文的），直接给出英文版链接： &lt;a href=&quot;http://nvie.com/posts/a-successful-git-branching-model&quot; target=&quot;_blank&quot;&gt;A successful Git Branching model&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;自动化测试&lt;/h3&gt;

&lt;p&gt;单元测试，Selenium，PHPUnit。有这几个关键字足矣（资料自己找去 &lt;code class=&quot;emotion&quot;&gt;:D&lt;/code&gt;  ）。&lt;/p&gt;

&lt;h3&gt;这篇完了&lt;/h3&gt;

&lt;p&gt;当然也有好部分内容没有翻译过来，原文链接已经给出，不做传声筒。&lt;/p&gt;

&lt;p&gt;这是第一篇，所以肯定也有第二篇，下一篇再写点自己的东西。（这篇水分太多了？）&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>一次灾难恢复后小记</title>
   <link href="http://yan-yan.info/2010/note-on-arecovery.html"/>
   <updated>2010-10-11T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2010/note-on-arecovery</id>
   <content type="html">&lt;p&gt;最近做了一次灾难恢复，记下点什么吧。&lt;/p&gt;
&lt;p&gt;备份不应仅是 cron + rsync。整个 /var/www 都备份下来，数据库则是 mysqldump 再压缩，每天凌晨 cron 跑rsync。没有备份配置文件，mysql 的用户权限表也没有备份。&lt;/p&gt;
&lt;p&gt;在恢复时还有一个需求，就是某些站点已经不再运作，因此也不需要再恢复到服务器上，有一个 archive&lt;br&gt;
即可。另一方面则是，某些站点用户上传的静态文件（图片、Flash）等数据有点多，备份机在公司，通过一条 6M 的宽带将 2G 的东西上传到服务器，花费的时间确实有点久。&lt;/p&gt;
&lt;p&gt;fcicq 说过使用 git 做备份，既是增量备份的同时，也进行了版本化，随时可以回溯到过往版本。对于版本化，考虑到的是，假设某个文件出现了错误，而备份机也把错误作了备份，那么恢复的文件也是出错了的。这个问题亦是在使用 rsync 时想到的。而 git 对二进制文件进行版本化的能力，我还是有所保留的。也设想 git &amp;amp; rsync 并用，具体怎么做可能得摸索摸索。&lt;/p&gt;
&lt;p&gt;另一个问题是配置文件。一般来说扔 /etc 中就不理会的了，整个文件夹备份似乎也有点多余了，一个考虑中的方案是利用 ln，版本化 + 初始化导入脚本。&lt;/p&gt;
&lt;p&gt;对于 mysql 的备份，此前没有对用户权限表进行备份实在不该，假设一个站点建立一个帐号的，恢复时的工作量也是挺可观的。而另一方面，此前我是不会把项目的配置文件和项目源码混合在一个数据仓库中进行版本化的，但现在看来，似乎这样做也有这样的优势。&lt;/p&gt;
&lt;p&gt;然后对上海×畅发点牢骚：单硬盘，没 RAID，也没有做备份（备份是宣传的噱头？），提供这样的 VPS 服务实在让人感觉有点悬。申请资金租另一个公司/机房的 VPS 做双机方案好点（至少可用性多点保证，利用 DNSPod 的 API 做个切换脚本）。&lt;/p&gt;
&lt;p&gt;这次也有决策的错误，判断磁盘出错的时候居然还使用 fsck，我真是秀逗了。 :-\&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>使用 PIL 修改图片大小</title>
   <link href="http://yan-yan.info/2010/quick-resize-image-with-pli.html"/>
   <updated>2010-10-02T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2010/quick-resize-image-with-pli</id>
   <content type="html">&lt;p&gt;速记一个使用 Python Imaging Library (PIL) 修改图片的方法。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sudo apt-get install python-imaging&lt;/code&gt;&lt;/p&gt;
&lt;p&gt; 打开终端，&lt;/p&gt;
&lt;p&gt;&lt;code&gt;import Image&lt;br&gt;
img = Image.open('origin.jpg')&lt;br&gt;
cropped = img.crop((x0, y0, x1, y1))&lt;br&gt;
resized = cropped.resize((target_x, target_y), Image.ANTIALIAS)&lt;br&gt;
resized.save('resized.jpg', quality=100)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;resize 时要加入 Image.ANTIALIAS 作为参数，保存时 quality 的值高一点也不是问题（我填了 100 才感觉满意），85或者90都比较差强人意。&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>Two patches for Lithium (li3)</title>
   <link href="http://yan-yan.info/2010/two-patches-for-lithium-li3.html"/>
   <updated>2010-07-07T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2010/two-patches-for-lithium-li3</id>
   <content type="html">&lt;p&gt;First, added method &lt;code&gt;_toBoolean&lt;/code&gt; to &lt;em&gt;Lithium\data\source\database\adapter\MySql&lt;/em&gt;:&lt;/p&gt;
&lt;pre&gt;    protected function _toBoolean($value) {
        return (int) parent::_toBoolean($value);
    }
&lt;/pre&gt;
&lt;p&gt;Now Lithium treat tinyint(1) in MySQL as boolean type, but when you insert/update with a field has been defined as tinyint(1), Lithium will try insert boolean type, then an SQL error will throws.&lt;/p&gt;
&lt;p&gt;The second patch is for &lt;em&gt;Lithium\data\source\Database&lt;/em&gt;. Try this:&lt;/p&gt;
&lt;pre&gt;class User extends Lithium\data\Model {}

$user = User::create();
$user-&amp;gt;name = 'Leechael';
$user-&amp;gt;email = 'blah@blah.blah';
$user-&amp;gt;blah = 'Field that NOT exists in schema';
$user-&amp;gt;save();
&lt;/pre&gt;
&lt;p&gt;Than you will got an SQL error, said &lt;q&gt;unknown column `blah`&lt;/q&gt;. The solution is add a few lines in method Database::create() and Database::update(). First one, go to line 190:&lt;/p&gt;
&lt;pre&gt;while (list($field, $value) = each($data['fields'])) { // This line is what we looking for!
    // Insert following block!
    if (!isset($schema[$field])) {
        continue;
    }
// other codes ....
&lt;/pre&gt;
&lt;p&gt;Second, go to line line 274 (after previous patched):&lt;/p&gt;
&lt;pre&gt;while (list($field, $value) = each($data['fields'])) { // You looking for this!
    if (!isset($schema[$field])) {
        continue;
    }
// other codes ....
&lt;/pre&gt;
&lt;p&gt;Done.&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>PHP Snippet: ip4_in_range</title>
   <link href="http://yan-yan.info/2010/php-codes-ip4_in_range.html"/>
   <updated>2010-06-30T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2010/php-codes-ip4_in_range</id>
   <content type="html">&lt;p&gt;ip 范围检测函数，老生常谈了，贴一下自己造的轮子：&lt;/p&gt;
&lt;pre&gt;function ip4_in_range ($ip, $start, $end = null) {
    if (func_num_args() === 2) {
        if (strpos($start, '*') !== false) {
            $end = str_replace('*', '255', $start);
            $start = str_replace('*', 0, $start);
        } elseif (strpos($start, '/') !== false) {
            $ip_dec = ip2long($ip);
            list($range, $netmask) = explode('/', $start);
            $netmask_dec = ~ (pow(2, (32 - intval($netmask))) - 1);
            $range_dec = ip2long($range);
            return (($ip_dec &amp;amp; $netmask_dec) === ($range_dec &amp;amp; $netmask_dec));
        } else {
            trigger_error('ip4_in_range: Parameter $start maybe in invalid format.');
            return false;
        }
    }
    extract(array_map(function ($ip) {
        return (float) sprintf(&quot;%u&quot;, ip2long($ip));
    }, compact('ip', 'start', 'end')));
    if ($start &amp;gt; $end) {
        list($start, $end) = array($end, $start);
    }
    return ($ip &amp;gt;= $start &amp;amp;&amp;amp; $ip &amp;lt;= $end);
}
&lt;/pre&gt;
&lt;p&gt;只简单的做了几个小测试，都通过了。用法：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ip4_in_range('10.0.1.13', '10.0.1.0/24');&lt;/li&gt;
&lt;li&gt;ip4_in_range('10.0.1.13', '10.0.1.*');&lt;/li&gt;
&lt;li&gt;ip4_in_range('10.0.1.13', '10.0.1.10', '10.0.1.20');&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 

 
 <entry>
   <title>Ubuntu Installing Note</title>
   <link href="http://yan-yan.info/2010/installing-ubuntu-via-netboot.html"/>
   <updated>2010-06-29T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2010/installing-ubuntu-via-netboot</id>
   <content type="html">&lt;ol&gt;
  &lt;li&gt;首先保证两个机器位于同一网段。&lt;/li&gt;
  &lt;li&gt;下载必须的文件：&lt;a href=&quot;http://archive.ubuntu.com/ubuntu/dists/maverick/main/installer-i386/current/images/netboot/&quot; target=&quot;_blank&quot;&gt;http://archive.ubuntu.com/ubuntu/dists/maverick/main/installer-i386/current/images/netboot/&lt;/a&gt; 中的 mini.iso，netboot.tar.gz，pxelinux.0， pxelinux.cfg 文件夹及其下的 default 文件。解压 netboot.tar.gz，注意不要给 netboot.tar.gz 中的 pxelinux.0 和 pxelinux.cfg 覆盖下载回来的同名文件。这里是下载 Ubuntu Maverick，时间不同了可能选择的版本也不同了。&lt;/li&gt;
  &lt;li&gt;下载 TFTPD32 的最新版本：&lt;a href=&quot;http://tftpd32.jounin.net/tftpd32.html&quot; target=&quot;_blank&quot;&gt;http://tftpd32.jounin.net/tftpd32.html&lt;/a&gt;。&lt;/li&gt;
  &lt;li&gt; TFTPD32 与前述下载的文件必须存于同一文件夹中。打开后点击 DHCP Server 的选项卡，IP Pool starting address 填入通过 netboot 安装 ubuntu 的机器(Target PC)的 IP，Boot File 填 pxelinux.0，WING/DNS Server、Default Router、Mask 按照实际情况填写，保存。&lt;/li&gt;
  &lt;li&gt;启动 Target PC，注意打开并设定网络启动，然后看看 TFTPD32 中显示的机器 MAC 地址是否 Target PC 的 MAC 地址。多看 Log viewer 中的信息。在文件复制完毕后，在 Target PC 上开始安装 Ubuntu。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;务必&lt;/strong&gt;使用 LVM。这次安装的 500GB 硬盘分区方案：
    &lt;ul&gt;
      &lt;li&gt;/boot – 250M, ext2(还会选择其他 filesystem 么？)&lt;/li&gt;
      &lt;li&gt;/swap – 3G&lt;/li&gt;
      &lt;li&gt;/ – 30G, btrfs&lt;/li&gt;
      &lt;li&gt;/home – 200G, /ext4&lt;/li&gt;
      &lt;li&gt;/var – 分配所有的剩余空间，/ext4&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;修改 /etc/apt/sources.list，&lt;code&gt;sudo apt-get update &amp;amp;&amp;amp; sudo apt-get upgrade&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;sudo apt-get install openssh-server&lt;/code&gt;. See also: &lt;a href=&quot;http://www.cyberciti.biz/tips/linux-unix-bsd-openssh-server-best-practices.html&quot; target=&quot;_blank&quot;&gt;Top 20 OpenSSH Server Best Security Practices&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;sudo apt-get install mysql-server apache2 libapache2-mod-php5 php5 php5-cli php5-mcrypt php5-curl php5-gd php5-mysql php5-sqlite php-pear&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;sudo apt-get install dnsmasq sysstat&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 

 
 <entry>
   <title>PHP Framework，以及团队</title>
   <link href="http://yan-yan.info/2010/php-framework-and-team.html"/>
   <updated>2010-06-12T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2010/php-framework-and-team</id>
   <content type="html">&lt;p&gt;这一次选 Framework 的过程比较简单。Zend Framework 直接忽略，个人感觉它更像一个 toolkits 或者 library。Symfony 的感觉就是 Model 太臃肿，做 ORM 的 Propel 和 Doctrine 实际上都不讨我喜欢，此外通过脚本实现 duplicated 的代码还是放弃罢了。个人感觉写脚本做 script generator 的 framework 就有点过了。考虑 Kohana，但 Singleton 使用过度了，感觉这就不利于做 Unit Test，写 Mock 也会比较困难的感觉；或者可能是自己没有通读 Kohana 源码的关系。暂时用着 Lithium，可能也有不便于测试，或者 Singleton 过多的问题，但目前感觉还是不错的。Lithium 缺少文档，下一步大概就是读一读源码了，不过得看看工作怎么安排是好了。&lt;/p&gt;
&lt;p&gt;目前的团队有三个人——忽略“鸡”这个角色。对于实践 Scrum，我并没有底，毕竟自己也是半吊子的水平，对 scrum 的认识仅限于《&lt;a href=&quot;http://www.infoq.com/cn/minibooks/scrum-xp-from-the-trenches&quot; target=&quot;_blank&quot;&gt;硝烟中的Scrum和XP&lt;/a&gt;》一书。也经过好一段子日子的思考了，打算在接下来的日子，&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先把使用 Google Calendar 和 Gmail 这两个使用习惯培养起来，&lt;/li&gt;
&lt;li&gt;然后实践 Daily Scrum Meeting，先从交流和每人能确定自己的工作目标做起。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;由于端午节假期，我与另一位团队成员也得回学校处理毕业相关事宜，所以一口气吃成胖子也是不现实的。或者在接下来做的一个外包单子中实践上述的两点。&lt;/p&gt;
&lt;p&gt;《Get Things Done》的重读还没有完成。这个星期奔波在旅途中就去了两天（再次来回肇庆-广州），回广州后的第二天就是病了的感觉，也是有气无力地混了一天多。感觉这一周没完成了点什么，看来对产出物的定义还是需要有的。&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>Setup a helper for Lithium (a.k.a. li3)</title>
   <link href="http://yan-yan.info/2010/setup-a-helper-for-lithium-a-k-a-li3.html"/>
   <updated>2010-06-05T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2010/setup-a-helper-for-lithium-a-k-a-li3</id>
   <content type="html">&lt;p&gt;Save your helper class under &lt;code&gt;app/extensions/helper/&lt;/code&gt;, like &lt;em&gt;Navigator.php&lt;/em&gt;, than calls &lt;code&gt;$this-&amp;gt;Navigator&lt;/code&gt; in your template.&lt;/p&gt;
&lt;p&gt;It’s fucking easy but leaks document. Hope this helps you.&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>哲学家的追求</title>
   <link href="http://yan-yan.info/2010/chase-of-philosophers.html"/>
   <updated>2010-04-08T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2010/chase-of-philosophers</id>
   <content type="html">&lt;blockquote&gt;&lt;p&gt;
觊觎真理需要独特的热情。每个哲学家都说他在追求真理，但事实并非如此。正如一个哲学家所评论的那样，哲学家们往往不能获取真理的一个理由是，他们往往并不渴望获取真理。真正忙于探索真理的人是科学家、博物学家、历史学家……专业哲学家们通常是只会道歉的人，即他们沉迷于为某些被赋予的假象或者某些有鼓动性的思想而辩解。就像律师或侦探，他们受人雇用，分析案情，以确定他们能搜集多少辩护所需的证据或疑似证据以及能举出多少支持控告的反证；因为他们知道，他们正在为嫌犯辩护，人们怀疑，也许他们自己的良知也怀疑，此人犯有伪造罪。他们并不觊觎真理，只是向往胜利和消除他们的疑虑。他们辩护的是某种体系，即，某种关于事物整体的观点，而实际上人类对此一无所知。假如人们只是对了解事情的真相、事情的来龙去脉感兴趣，就不会建立起任何体系，我们的某种流行的或继承的观点恰当而充分，不理会所有有望成功之士而有意坚持这一点，正是形成体系的因素。一个体系可能包含许多事物，其细节真实可靠；但是作为一个体系──此体系包含无限的可能性，我们的经验和逻辑均无法对此有所影响──它必须是想象力的结晶、人类的独白。它也许表现人类经验，也许富有诗意；然而，真正觊觎真理的人，无论是谁，怎么可能认为这就是真理？
&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;cite&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/George_Santayana&quot; target=&quot;_blank&quot;&gt;George Santayana&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>把 Mac Mini 切换到 64-bits 模式</title>
   <link href="http://yan-yan.info/2010/turn-mac-mini-runs-under-64-bits.html"/>
   <updated>2010-04-07T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2010/turn-mac-mini-runs-under-64-bits</id>
   <content type="html">&lt;p&gt;这是 2009 年 3 月那个版本的 &lt;a href=&quot;http://support.apple.com/kb/SP505&quot; target=&quot;_blank&quot;&gt;Mac Mini&lt;/a&gt;，CPU 为 Intel Core 2 Duo 2.0GHz (P7350)。&lt;/p&gt;
&lt;p&gt;大致原理为修改 &lt;code&gt;/System/Library/CoreServices/&lt;/code&gt; 的 boot.efi。首次尝试时，我试着用 xxd 修改，结果启动不了，幸好翻出一个系统盘，能打开一个 shell 进行恢复。如果你的 Mac Mini 型号和我改掉的这个一样，可以在&lt;a href=&quot;http://www.mediafire.com/file/oyzdznjty5f/boot64.zip&quot; target=&quot;_blank&quot;&gt;这里&lt;/a&gt; 下载已经修改好的 boot.efi。&lt;/p&gt;
&lt;p&gt;至于如何修改可以参考这两篇：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.osxbook.com/blog/2009/08/31/is-your-machine-good-enough-for-snow-leopard-k64/&quot; target=&quot;_blank&quot;&gt;Is Your Machine Good Enough for Snow Leopard K64?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www39.atwiki.jp/macmini/pages/30.html&quot; target=&quot;_blank&quot;&gt;Snow Leopardを64bitカーネルで動作させる&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;步骤不多，也不难。最重要的是要准备用于恢复的光盘。&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>八公</title>
   <link href="http://yan-yan.info/2010/movies-about-hachi.html"/>
   <updated>2010-04-02T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2010/movies-about-hachi</id>
   <content type="html">&lt;p&gt;在看『&lt;a href=&quot;http://movie.douban.com/subject/3011091/&quot; target=&quot;_blank&quot;&gt;忠犬八公的故事&lt;/a&gt;』时，泪腺只是给触动了一下；也怕是并非自己一个人在看，泪腺便无动于衷。这次看了『&lt;a href=&quot;http://movie.douban.com/subject/1959195/&quot; target=&quot;_blank&quot;&gt;忠犬八公物语&lt;/a&gt;』，泪腺终于忍不住了，眼眶里多了点水。&lt;/p&gt;
&lt;p&gt;前者是后者的美版、修改剧本后的重拍版本，八公还是秋田犬，只是怎么去到了美国，这点实在有点唐突。后者虽然是1987年的作品，催泪威力仍不可忽视。后者，或说日版，也许更贴近作为原型的那个真实故事，八公和教授之间情感日益渐深的镜头并没有多少，但那些让人记忆深刻的镜头都在了。美版改得有点离谱，例如教授和八公一起洗澡的原因是得到臭鼬的奖赏，那只能当作一起洗澡一次而已；但日版，教授通常是在为八公捉狗蚤后一起洗澡，这提醒着你，这故事并非童话，狗还是会生狗蚤的。&lt;/p&gt;
&lt;p&gt;教授好友这个角色，美版和日版也不同。美版是一个日本籍的教授，这样也好解释八公是一种秋田犬的事实。而日版，好友在教授离去后，最终收留了八公，直到自己也死去（他的死因似乎是心肌梗塞）。最后都是由车站旁边卖吃的小贩照顾；日版中还多了一段小贩为了八公与人打架的情节，那真是急了。&lt;/p&gt;
&lt;p&gt;美版还不同于日版的一点是，对不同角色照顾八公的目的都假设含有功利性的原因存在，例如车站管理员虽然照顾八公，但克扣别人捐的、让他给八公买吃的钱，当记者来访问时，也拼着想在报纸上露一回面；而小贩喂食八公，也被列车管理员道破是拿过期食品喂养（这点我不太敢确定）。相对来说，日版的角色比美版的可爱多了。&lt;/p&gt;
&lt;p&gt;题外话。今天看了刘德华主演的『&lt;a href=&quot;http://movie.douban.com/subject/3329192/&quot; target=&quot;_blank&quot;&gt;未来警察&lt;/a&gt;』，不得不说那是烂片一部。刘德华只顾得耍帅，效果显得粗糙，剧情经不起推敲；如果要看打斗场景，还不如期待『&lt;a href=&quot;http://movie.douban.com/subject/3578981/&quot; target=&quot;_blank&quot;&gt;叶问2&lt;/a&gt;』，起码甄子丹的武斗场面精彩多了。&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>读『人间失格』后记</title>
   <link href="http://yan-yan.info/2010/notes-on-ningen-shikkaku.html"/>
   <updated>2010-04-01T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2010/notes-on-ningen-shikkaku</id>
   <content type="html">&lt;h3&gt;零&lt;/h3&gt;
&lt;p&gt;我是从轻小说『文学少女』中得知『人间失格』这本书；那时一口气看了五卷『文学少女』，把里面提及的作家及其作品的名字整理下来。那时候 jonko 留言推荐『人间失格』。而我对『人间失格』的了解，仅限于『文学少女』第一卷中的描述，那是以『人间失格』作为主轴的小说。&lt;/p&gt;
&lt;p&gt;第一次完整看完『人间失格』，是从 jonko 处借来的打印件；她居然把整书打印出来了，厚厚的一叠打印纸，单面打印，估计会是环保主义者的讨伐对象。&lt;/p&gt;
&lt;p&gt;好些日子后，jonko 向我讨要书稿，我本是托人交还的，但似乎在某个环节丢失了；而此时看到吉林出版社出售&lt;a href=&quot;http://book.douban.com/subject/4011670/&quot; target=&quot;_blank&quot;&gt;中文版的『人间失格』&lt;/a&gt;，买了两本，送 jonko 一本，自留一本；然后到今天读完第二次。&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
……越是努力去思索，就越搞不懂，自己好像变了个人似的，净是被不安与恐惧所侵袭。我几乎无法和旁人聊天。因此该说些什么才好呢，我不懂。&lt;/p&gt;
&lt;p&gt;此时，我想到的是娱乐他人。&lt;/p&gt;
&lt;p&gt;这是我对人最后的求爱。我，极度恐惧着人的同时，却怎么也无法对人死心。于是，我要讨人欢心，才能与人类保持着一丝的牵连。表面上虽然不断地绽放笑容，内心却紧张万分，这才是成功率渺茫、千钧一发、让人冷汗直流的服务。&lt;/p&gt;
&lt;p&gt;从孩提时代开始，我的家人有多痛苦？脑子里想着什么事而活？这些我一点概念也没有，只是恐惧着，无法忍受这种不舒坦，让自己成为一个讨人欢心的高手。换句话说，不知从何时起，我就成了一个不会说半句真话的孩子。
&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;p&gt;
相互欺瞒而无论哪一方都不可思议地完好无伤，甚至彼此连相互欺骗一事都不可思议地完好无伤，甚至彼此连相互欺骗一事都没发现一般，鲜活、光明磊落、开朗痛快的互不信任，这种案例，我想是处处存在于人们的生活当中。但我个人，对于这种相互欺瞒的事并没有多大的兴趣。我倒是借由娱乐他人一事，从早到晚欺骗着人们。我不大关心伦理课本里所谓的正义或其他道德观。对我来说，那些相互欺瞒之余却能光明磊落、快活地活着，或者说是看起来拥有能够活下去自信的人着实难以理解。
&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;p&gt;
父亲，已经不在了，胸中片刻不离，让人熟悉又可怕的存在感，已经不在了。我感觉到我苦恼的根源空空如也了。甚至还以为，自己苦恼的根源会沉重得那么厉害，该不会都是父亲的缘故吧？我完全失去了干劲了。连苦恼的能力都失去了。
&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;p&gt;
“是他父亲的错。”老板娘无意中说出口，“我们所认识的阿叶非常率直、非常机灵，若是不喝酒，不，就算喝了酒，他也是天神般的大好人。”
&lt;/p&gt;&lt;/blockquote&gt;
&lt;h3&gt;一&lt;/h3&gt;
&lt;p&gt;我本是想写书评的，但写不出一个字，只憋出上文叙述我是怎么得知『人间失格』、又从何读到此书，再加上几段摘录片段。实在苍白。去豆瓣看了看别人的书评，自己实在写不出那样的文字。&lt;/p&gt;
&lt;p&gt;读『人间失格』就是感同身受的过程，就如像对自己抽丝剥茧一样。&lt;/p&gt;
&lt;p&gt;唯一幸好的是，自己没有吃软饭，伸手要钱而不以劳动交换，之于我有痛苦的感觉。但上面这句，怕是我唯一能憋出的书评了。&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>洗衣店</title>
   <link href="http://yan-yan.info/2010/laundry.html"/>
   <updated>2010-03-29T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2010/laundry</id>
   <content type="html">&lt;p&gt;3月29日，凌晨。&lt;/p&gt;
&lt;p&gt;突然想知道公司附近有没有洗衣店，打开 &lt;a href=&quot;http://maps.google.com.hk/&quot; target=&quot;_blank&quot;&gt;Google Map&lt;/a&gt; 便开始搜索；才发现，公司附近还是有好些洗衣店的，但自己没去留意，甚至从旁经过也浑然不知。&lt;/p&gt;
&lt;p&gt;说到洗衣店，想起一部电影和一个画面。&lt;/p&gt;
&lt;p&gt;先说画面：想起的是『&lt;a href=&quot;http://movie.douban.com/subject/1307755/&quot; target=&quot;_blank&quot;&gt;恋爱写真&lt;/a&gt;』中，静流一个不慎把相机摔进了洗衣机的画面。毫无疑问诚人是个好男友，如果忽略掉他妒才乃至偏执的事实。若是我正欢快地写着代码，忽然给拔掉电源——不禁把等同重要程度的时间替换进去，把角色也替换进去，我会怎么处理？真是一个大问题。只是我现在用的是小黑 ThinkPad，我还来得及输入 &lt;abbr title=&quot;Vim  中的保存命令&quot;&gt;&lt;code&gt;:wq&lt;/code&gt;&lt;/abbr&gt; ，或者把 Vim 中的自动保存间距缩短，或者通过冗余来避免给盛怒之下的人给小黑砸上一铁锤……&lt;/p&gt;
&lt;p&gt;电影是『&lt;a href=&quot;http://movie.douban.com/subject/1297428/&quot; target=&quot;_blank&quot;&gt;爱我别走&lt;/a&gt;』，其实不翻译过来的『Laundry』会更合适。然而这故事，也只是由洗衣店开始，男主角后面便换了职业，是个专业放鸽子的。放鸽子专业户，听起来很好玩，但照顾鸽子估计也是一个枯燥痛苦的活儿；但哪个职业不是枯燥繁琐的呢，若是习惯了，做得更好了，这不就是所谓的专业了。不抱怨生活，这能让生活增添多少色彩。&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>一次项目流产的小结</title>
   <link href="http://yan-yan.info/2010/though-on-workflow-of-pinfox-development.html"/>
   <updated>2010-03-23T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2010/though-on-workflow-of-pinfox-development</id>
   <content type="html">&lt;p&gt;由于只得到一个模糊的答复，但我还是得先承认目前的状况：这个项目流产了，我是这个项目流产的最大关系人。&lt;/p&gt;
&lt;p&gt;个人的各种问题和原因，我不多说，我现在只想说技术相关的。&lt;/p&gt;
&lt;p&gt;这是来自 MySpace.cn/9911 的项目，做一个 Firefox 的插件，类似 Twitterfox，现在叫做 Echofon 的那个小东西。&lt;strong&gt;Firefox 的插件所使用的技术难度不大，JavaScript + XUL，再加点 CSS，&lt;/strong&gt;很简单，打包成为 xpi 的时候可能还需要知道怎么用 bash，官方有一个自动打包的脚本，但有问题，需要自己修一修。一个对前端熟悉的开发者，再加点 Linux 平台下工作的经验，大致也有足够的基础开始开发了。&lt;/p&gt;
&lt;h3&gt;单元测试&lt;/h3&gt;
&lt;p&gt;我并非 quick and dirty 类型的开发者，如果我看代码的结构或者架构有点不爽了，我会小部分、甚至重构整个程序。对此，一个有效的 Unit Test 是最重要的保证。可惜，我没有写 Unit Test。JavaScript 有好些 Unit Test 框架，都是针对 Web 项目的，基于 HTML 的，并非 XUL 的。实际上，并没有一个用于单元测试的工具。当时我曾想过自己做一个简陋的，但终究没有做起来。基于浏览器的测试框架，大致可以通过 F5 刷新来完成测试，而基于 XUL 的，似乎只能通过手动点击更新 chrome 的按钮（通过开发辅助插件）。&lt;/p&gt;
&lt;p&gt;我想过一个基于 Python 方案的方案， SpiderMonkey 有 Python 类库的实现。但是这充其量只能算是一个 JavaScript Parser，做语法检测还行，做单元测试是不足够的。&lt;/p&gt;
&lt;p&gt;或者，会存在一个足够好的方案来达到自动化测试的目的，但我没有在项目初期做好一个完整的测试方案，若是想着做一个不断完善的东西，一个不断在重构中成长的软件（姑且算作是吧），&lt;em&gt;没有完善的自动化测试方案，简直是笑话。达到工业级质量的软件，必须有单元测试作为后盾。&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;开发环境、版本控制和自动构建脚本&lt;/h3&gt;
&lt;p&gt;在项目初期，开发环境是 Windows XP，中途曾转换到 Ubuntu，也有短时间地在公司的 Mac 上进行开发（主要是界面的调整），但开发环境的不停变更，对项目开发，铁定是有影响的。先不说开发环境的配置需要大量的时间，光是一个小问题就足够烦恼了：自动构建脚本。&lt;/p&gt;
&lt;p&gt;如果真的存在自动构建脚本，我想，率先需要测试的，肯定是这个东西。而且，这个东西还得能够自动侦测开发环境的不同而出现的差异，自动选择方案。bash shell 我一直觉得是一个很神奇很强大的东西，组合各个小工具写成的 script 可以很强大，可惜，这并不等于迁移到另一机器上就一定能够顺利运行。这也并非说这不好，至少，&lt;strong&gt;需要考虑自动构建脚本的健壮性问题。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;至于版本控制，我认为我是弄得一塌糊涂的，一个像是在进行版本控制的开发过程；由于开发机的不固定，有点像是把 git 当作 svn 使用了。对于个人开发者来说，问题本是不大，但作为中央节点的机器硬盘出现了问题──中央节点的代码仓库坏了。当时最新的代码版本在某个开发机上，问题影响不大，但若真的需要版本回滚，或者其他──问题就出现了。这本是一个小问题，但要&lt;em&gt;把 git 用得像 git，而非 svn&lt;/em&gt; ──这很重要，十分的重要。&lt;/p&gt;
&lt;h3&gt;类库&lt;/h3&gt;
&lt;p&gt;开始之时，XHR 和数据库的封装都是自己实现的。由于我固执地认为，需要把取回的消息本地存一份，所以我曾经有好几天的时间，用于钻研怎么在 Firefox 中用好 SQLite。问题是，在 Firefox 中，SQLite 是一个很奇怪的东西。对于并发的读，SQLite 没有问题。但是对于并发的写，例如多个进程或者线程，以异步的方式，在一个 IO 速度不稳定的设备（互联网）上取回数据，然后写入──这样，SQLite 很容易就会出现 deadlock。另一方面，SQLite API 的使用方法相对怪异（相对于习惯 PHP 所实现的 SQLite 封装的我来说）。虽然最近对于这个东西的开发中，我放弃了使用 SQLite 作为后端储存、甚至说没有储存除了帐号信息以后的数据，实际上也并不需要储存这些数据。&lt;/p&gt;
&lt;p&gt;继续说类库。在中段有一些时候，不知道从哪里看到 jQuery 也可以在 XUL 的环境中使用，但实际上，需要修改很多很多的东西才能正常使用，如上文所属，没有单元测试保证，这样的改动就意味着人工测试，也意味着开发成本的增加、开发时间的增加。我勉强改了点，想着改名叫作 gQuery ── g stand for Gecko ── 但结果，也会随着现在这个东西的流产也流产了。&lt;/p&gt;
&lt;p&gt;开发难度&lt;/p&gt;
&lt;p&gt;可以说，开发这样的浏览器插件，是一个很有趣的挑战，现在回想起来就像跑进一个物种丰富的原始森林中觅食，你没有工具，虽然身边都是丰富的原材料。&lt;/p&gt;
&lt;p&gt;先说界面。苏小雨的 CSS 2.1 手册是划时代的产品，这让我们知道了 CSS 2.1 有哪些属性，作用如何，但是整理这个出来也就是一个巨大的工程了。有这样的一个手册，我们可以知道哪个属性可以干点什么，作用是什么。再看看 developer.mozilla.org 上的这个页面：&lt;a href=&quot;https://developer.mozilla.org/en/CSS_Reference&quot; target=&quot;_blank&quot;&gt;https://developer.mozilla.org/en/CSS_Reference&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;很不错，列出了很多。那么，试试把 -moz-appearance 找出来。Ctrl + F 是找不出来的，得找 Google，然后，你终于找到一个像样的说明了：&lt;a href=&quot;https://developer.mozilla.org/en/CSS/-moz-appearance&quot; target=&quot;_blank&quot;&gt;https://developer.mozilla.org/en/CSS/-moz-appearance&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;这足够吗？&lt;/p&gt;
&lt;p&gt;Firefox 有一点不好：它能保证同样的 HTML 页面、同样的 CSS 代码在不同平台的 Firefox 下有一致的显示效果，却不能保证同样的 XUL + CSS 代码在不同平台的 Firefox 下有一致的显示效果。若非我所在的公司给我配了 Mac Mini 作为开发机，我怕是怎么也不知道，原来还得针对 Mac 的 Firefox 写 hack。对了，前面说的 -moz-appearance ── 这个属性得好好记住，跨平台的样式问题，首先考虑是不是它的问题就好了，摆弄 border、background 什么的，弄不懂按钮的样式，但加一句 &lt;code&gt;-moz-appearance: none&lt;/code&gt; 以后，请随意折腾，像折腾 HTML 一样。&lt;/p&gt;
&lt;p&gt;Firefox 在 Linux 下的效率被人诟病，我想着还有 XUL 的原因。scrollbox 是一个很不错的东西，试试鼠标按着 scrollbox 滚动条的下拉按钮不放，同期看看CPU占用率──无论在 Windows 还是 Ubuntu，在同一机器上，CPU 占用率都轻松突破 90%。或者看官的机器好一点，不会出现这么大的一个数字。&lt;/p&gt;
&lt;p&gt;现在，我会认为这是一个开发难度很大的项目了。看看 &lt;a href=&quot;http://code.google.com/p/zuosafox/&quot; target=&quot;_blank&quot;&gt;zuosafox&lt;/a&gt;，对比它和 Twitterfox 的代码（&lt;strong&gt;我敢说 ZuosaFox 是抄袭和改动 TwitterFox 的源码做出来&lt;/strong&gt;）；细看 Twitterfox，他们的功能也不多，功能增加基本上停止了──请看源码架构，当然，没有好的测试工具怕也是原因之一。&lt;/p&gt;
&lt;h3&gt;小结&lt;/h3&gt;
&lt;p&gt;写了这么多，也不知道还有什么要写了──现已将近六月，这个项目由开始到现在，已经五个月了，我在其中所犯的错误太多，也不一一细数了。大致总结好了。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;别把开发看得太简单。根据项目需求分析功能，然后调研。项目一上来就要求有这个那个的功能──稍等！先试试完成第一步，一个小小的功能，稳定了、符合了，重构，加功能，测试、重构。TDD 是一个良好的开发习惯。&lt;/li&gt;
&lt;li&gt;即使增加一个小小的功能，对整个程序的架构也会有很大的影响。&lt;/li&gt;
&lt;li&gt;良好的封装，完善的测试，是保持持续重构和优化的基础。&lt;/li&gt;
&lt;li&gt;接上，工若善其事，必先礼其器，要甚至考虑，你所用的工具是否足够，例如单元测试框架，例如开发框架，例如文档和社区。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;最后，我想着免不了对 9911 API 说点什么。这是一个有问题的 API，每个 URI，输出的同一个数据集、譬如说，user，都会存在问题，在 URI A 中，user 可能附带了字段 FOO，但在 URI B 的输出中，user 这个数据集就不包含 FOO 这个字段。他们大致没有好好地用 OO 来掩饰他们不良好的封装。试想一个只是写了一条 SQL 语句跑出结果、再扔 json_encode 中、最后把结果返回的脚本。封装不良好的一个问题就是，对测试不良好，但就我的感觉，我认为他们甚至没有单元测试。我希望我这两条推断都是错的。&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>问题解决笔记三则</title>
   <link href="http://yan-yan.info/2010/problem-solving-notes.html"/>
   <updated>2010-03-23T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2010/problem-solving-notes</id>
   <content type="html">&lt;h3&gt;改用 homebrew 作为包管理工具&lt;/h3&gt;
&lt;p&gt;改用了 homebrew 作为包管理工具。 &lt;a href=&quot;http://twitter.com/jjgod&quot; target=&quot;_blank&quot;&gt;@jjgod&lt;/a&gt; 有一篇&lt;a href=&quot;http://blog.jjgod.org/2009/12/21/homebrew-package-management/&quot; target=&quot;_blank&quot;&gt;对 homebrew 的介绍&lt;/a&gt;，不过文中说的安装方法有点繁琐；我本就是想打算用 homebrew 来管理这些工具的。&lt;/p&gt;
&lt;p&gt;官方提供了一个 &lt;a href=&quot;http://gist.github.com/323731&quot; target=&quot;_blank&quot;&gt;Ruby 安装脚本&lt;/a&gt;，因此也可以通过这个方法进行安装：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
&lt;code&gt;ruby -e &quot;$(curl http://gist.github.com/raw/323731/install_homebrew.rb)&quot;&lt;/code&gt;
&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;由于 homebrew 的哲学之一，就是避免使用 sudo，将程序的 owner 更改为 root，所以需要更改默认安装目录的权限来避免因为权限问题而出现的操作失败：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
&lt;code&gt;sudo chown -R `whoami` /usr/local&lt;/code&gt;
&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;我是完整卸载 MacPorts 后才安装的 homebrew 的，自然得把缺的东西的装回来，倒是得先把一些工具装回来：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
    &lt;code&gt;brew install git wget rsync&lt;/code&gt;
&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;至于 Mercurial，homebrew 给出一个提示让我使用 pip 安装：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
    &lt;code&gt;brew install pip &amp;amp;&amp;amp; pip install mercurial&lt;/code&gt;
&lt;/p&gt;&lt;/blockquote&gt;
&lt;h3&gt;MySQL 无法启动&lt;/h3&gt;
&lt;p&gt;由于改用了 homebrew 作为包管理工具，原来 MacPorts 安装的 MySQL 得重新安装，但安装结束后却得到了一个错误，&lt;q&gt;ERROR! Manager of pid-file quit without updating file&lt;/q&gt;，求救于 Google 大神，发现是 MacPorts &lt;a href=&quot;http://nixcraft.com/databases-servers/14483-starting-mysql-error-manager-pid-file-quit-without-updating-file.html#post24524&quot; target=&quot;_blank&quot;&gt;卸载时没有清理干净 MySQL 进程导致的问题&lt;/a&gt;，&lt;code&gt;killall mysql&lt;/code&gt;，然后进行剩余步骤：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
&lt;code&gt;mysql_install_db&lt;/code&gt;&lt;br&gt;
&lt;code&gt;launchctl unload -w ~/Library/LaunchAgents/com.mysql.mysqld.plist&lt;/code&gt;&lt;br&gt;
&lt;code&gt;cp /usr/local/Cellar/mysql/5*/com.mysql.mysqld.plist ~/Library/LaunchAgents&lt;/code&gt;&lt;br&gt;
&lt;code&gt;launchctl load -w ~/Library/LaunchAgents/com.mysql.mysqld.plist&lt;/code&gt;
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;还得给 .profile 文件加上 alias，&lt;q&gt;alias mysqlctl=”/usr/local/Cellar/mysql/5.1.47/share/mysql/mysql.server”&lt;/q&gt;，保存，&lt;code&gt;source ~/.profile&lt;/code&gt;，然后 &lt;code&gt;mysqlctl start&lt;/code&gt;，搞定。&lt;/p&gt;
&lt;h3&gt;MacVim 的配置问题&lt;/h3&gt;
&lt;p&gt;用上了 &lt;a href=&quot;http://www.vim.org/scripts/script.php?script_id=2975&quot; target=&quot;_blank&quot;&gt;fugitive.vim&lt;/a&gt; 才知道 MacVim 的 $PATH 是有问题的，打开 Preferences，激活 Launch Vim processes in a login shell 这个选项，打开一个新的 MacVim 窗口，&lt;code&gt;:!echo $PATH&lt;/code&gt;，问题就这样解决了。&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>Thought on Work</title>
   <link href="http://yan-yan.info/2010/thought-on-work.html"/>
   <updated>2010-03-21T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2010/thought-on-work</id>
   <content type="html">&lt;p&gt;年初接了一个工作，但拖至今天仍未能完成，对方告知，“公司或者会砍掉这个项目”。暂缓说更多在这项工作中出现的问题，或者真的要总结就是一篇长长的东西，只说自己的原因：拖沓，然后受困于架构的问题，事情多了就顾此失彼。&lt;/p&gt;
&lt;p&gt;昨晚一口气读了 IBM DeveloperWorks 上连载的《&lt;a href=&quot;http://www.ibm.com/developerworks/cn/java/j-eaed/&quot; target=&quot;_blank&quot;&gt;演化架构与紧急设计系列&lt;/a&gt;》，似乎略有所悟：自己知道 TDD，却从来没有真正身体力行地实践 TDD，这会不会是一个原因呢？&lt;/p&gt;
&lt;p&gt;再看这篇，《&lt;a href=&quot;http://dyang.github.com/agile/2010/02/09/customization.html&quot; target=&quot;_blank&quot;&gt;懂了才去定制&lt;/a&gt;》，里面说的一段话：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
一个学生如果对要学的东西还没有真正吃透，那么请不要急于寻求突破；一个开发团队如果对将要采用的新方法还没一个完整的认识，那么也请不要盲目定制。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Shu_ha_ri&quot; target=&quot;_blank&quot;&gt;因为你很可能还不懂自己究竟在做什么。&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;虽然自己读了《&lt;a href=&quot;http://book.douban.com/subject/3390446/&quot; target=&quot;_blank&quot;&gt;硝烟中的Scrum和XP&lt;/a&gt;》，如果没有身体力行，没有完整理解，没有尝试，那么这那是在实践敏捷开发呢？&lt;/p&gt;
&lt;p&gt;需要更多反思才是。&lt;/p&gt;
&lt;p&gt;说到Scrum，倒是想到了一个好处，就是把工作都白纸黑字量化了，分成一个个backlog，不能再说因为可见的变化不存在，那么就是没有完成工作。下午公司的每周例会上，自己的低效受到了批评，但另一方面，我在思考当前项目的问题时，所做的都是背后的处理，再多的代码、改了又改，也只是看不到的变化，而业绩多少的定义，怕是更着重表面上看到的。而自己都是把想法在脑里打转，想一点做一点，遇到问题、需要修改大片代码，然后把时间就浪费在重构和手动测试中。一个可演化的架构，一个更快捷的自动化测试，Test-Driven Development——或者是自己需要的。这话我说得不肯定，但至少是目前的一根救命稻草吧。&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>机会成本</title>
   <link href="http://yan-yan.info/2010/opportunity-cost.html"/>
   <updated>2010-03-20T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2010/opportunity-cost</id>
   <content type="html">&lt;blockquote&gt;&lt;p&gt;
琼斯住在榆树街，他生产两种啤酒：淡啤酒和黑啤酒。每个季度他能生产10加仑优质淡啤酒或5加仑优质黑啤酒，或二者的任意线性组合。……&lt;/p&gt;
&lt;p&gt;布朗住在橡树街，他也生产淡啤酒和黑啤酒。按照他的资源和技术，每个季度只能生产3加仑优质淡啤酒或4加仑优质黑啤酒，或者这二者的任意线性组合。……假定琼斯的淡啤酒的口感和布朗的淡啤酒一样好，黑啤酒一样。&lt;/p&gt;
&lt;table colspan=&quot;1&quot; rowspan=&quot;1&quot; border=&quot;1&quot;&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;酿酒商&lt;/th&gt;
&lt;th&gt;黑啤酒（加仑）&lt;/th&gt;
&lt;th&gt;淡啤酒（加仑）&lt;/th&gt;
&lt;th&gt;黑啤酒的机会成本&lt;/th&gt;
&lt;th&gt;淡啤酒的机会成本&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;琼斯&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;2加仑淡啤酒&lt;/td&gt;
&lt;td&gt;1/2加仑黑啤酒&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;布朗&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3/4加仑淡啤酒&lt;/td&gt;
&lt;td&gt;4/3加仑黑啤酒&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;假设琼斯在城里的家庭啤酒作坊供货商那儿遇见了布朗，并交流了酿酒经验。一番商谈之后，他们达成了如下协议：琼斯只生产淡啤酒，布朗只生产黑啤酒，然后进行一对一的交换。琼斯将会用3加仑的淡啤酒向布朗换取3加仑的黑啤酒。&lt;/p&gt;
&lt;p&gt;……当他们完成3加仑淡啤酒对3加仑黑啤酒的贸易后，双方享有的啤酒组合都超出了原先的边界。琼斯得到了更多他想要的东西，他的财富增加了，现在他有7加仑的淡啤酒和3加仑黑啤酒，原先他自己做不到这一点。布朗的财富也增加了，他现在有3加仑淡啤酒和1加仑黑啤酒，原先她自己也做不到这一点。
&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;在『经济学的思维方式(11e)』中，2.6 使用了上面的这个例子说明“从专业化和交换中获益”，而这一例子是在 2.5 的例子上进行深化。这一例子中模型的限制条件，我已将原文相关的文字摘录在上，现在说说没有被提及的限制条件，价值。没有提及的是，淡啤酒和黑啤酒的价格，在例子中假设是一样的。&lt;/p&gt;
&lt;p&gt;做一个证明：黑啤酒的价格是每加仑2元，淡啤酒的价格是每加仑1元。市场价格是稳定不变的。在交换并不发生以前，琼斯只生产淡啤酒或黑啤酒都可卖得10元；布朗只生产淡啤酒可以获得3元，只生产黑啤酒可得8元。若交换成立，双方只专注生产一项产品（琼斯生产淡啤酒，布朗只生产黑啤酒）而进行对等数量的交换：3加仑的黑啤酒交换3加仑的淡啤酒。交换以后，琼斯可以卖得13元（3加仑黑啤酒+7加仑淡啤酒），布朗可以卖得5元（1加仑黑啤酒+3加仑淡啤酒）。对于布朗来说，这并不是利益最大化的方案。&lt;/p&gt;
&lt;p&gt;再进而推算，对于琼斯来说，机会成本还是不变的，但对于布朗来说，机会成本变了，生产黑啤酒的机会成本明显低于生产淡啤酒；而实际上，并不需要使用机会成本来衡量，单纯计算价格和产量的乘积，就知道在上面提及的限制条件下，只生产黑啤酒就能获得最大的利润，那么布朗还需要使用机会成本这一概念来权衡吗？&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>从交换中获益的隐含条件</title>
   <link href="http://yan-yan.info/2010/hidden-codition-of-exchange-benefit.html"/>
   <updated>2010-03-20T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2010/hidden-codition-of-exchange-benefit</id>
   <content type="html">&lt;p&gt;在前文&lt;a href=&quot;/2010/opportunity-cost.html&quot;&gt;机会成本&lt;/a&gt;完事以后，还是有点不妥的感觉。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;前文中我认为，例子中隐含的一个条件是“淡啤酒和黑啤酒的价格是相等的”。&lt;/li&gt;
&lt;li&gt;在换值不等的情况下，原设中的机会成本变了。&lt;/li&gt;
&lt;li&gt;我认为在换值不等的情况下，1加仑黑啤酒换1加仑淡啤酒并不是利益最大化的方案，&lt;em&gt;这也致使这个例子无法解释如何“从专业化和交换中获益”&lt;/em&gt;。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;问题在于机会成本的计算。&lt;/p&gt;
&lt;p&gt;书中对“机会成本”的定义（25页）：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
机会成本一次常被用于强调一项行为的成本是人们赋予次优机会的价值，人们在选择这一行为时以次优机会为代价。
&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;在 &lt;a href=&quot;http://zh.wikipedia.org/wiki/%E6%9C%BA%E4%BC%9A%E6%88%90%E6%9C%AC&quot; title=&quot;wikipedia:机会成本&quot; target=&quot;_blank&quot;&gt;Wikipedia 上的解释&lt;/a&gt;与书中的相近，更明确指出概念中的两个要点：&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;机会必须是决策者可选择的项目。&lt;/li&gt;
&lt;li&gt;机会成本必须指放弃的机会中受益最高的一个项目。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;然后对在换值不等时的机会成本进行计算。若琼斯选择生产5加仑黑啤酒，获利10元，那么他总的机会成本是10加仑淡啤酒 x 每加仑淡啤酒2元 = 10元；相反，生产10加仑淡啤酒，获利10元，总的机会成本是5加仑黑啤酒 x 每加仑黑啤酒2元 = 10元。总的机会成本相等，而每加仑黑啤酒的机会成本是1元（2加仑淡啤酒），每加仑淡啤酒的机会成本是1元（1/2加仑黑啤酒）。与换值相等时相同。&lt;/p&gt;
&lt;p&gt;再看看布朗的情况。若选择生产4加仑黑啤酒，获利8元，那么他总的机会成本是3加仑淡啤酒 x 每加仑淡啤酒1元 = 3元；相反，生产3加仑淡啤酒，获利3元，那么他总的机会成本是4加仑黑啤酒 x 每加仑黑啤酒2元 = 8元。总的机会成本不等，每加仑黑啤酒的机会成本是3/8元（3/8加仑淡啤酒），每加仑淡啤酒的机会成本是8/3元（4/3加仑黑啤酒）。得下表：&lt;/p&gt;
&lt;table colspan=&quot;1&quot; rowspan=&quot;1&quot; border=&quot;1&quot;&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;酿酒商&lt;/td&gt;
&lt;td colspan=&quot;2&quot;&gt;每加仑黑啤酒的机会成本&lt;/td&gt;
&lt;td colspan=&quot;2&quot;&gt;每加仑淡啤酒的机会成本&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;琼斯&lt;/td&gt;
&lt;td&gt;1元&lt;/td&gt;
&lt;td&gt;2加仑淡啤酒&lt;/td&gt;
&lt;td&gt;1元&lt;/td&gt;
&lt;td&gt;1/2加仑黑啤酒&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;布朗&lt;/td&gt;
&lt;td&gt;3/8元&lt;/td&gt;
&lt;td&gt;3/8加仑淡啤酒&lt;/td&gt;
&lt;td&gt;8/3元&lt;/td&gt;
&lt;td&gt;4/3加仑黑啤酒&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;在这里引入价格（元）这个相对单位，是可以方便对比机会成本的。对于琼斯来说，不看价格只看生产量，生产1加仑黑啤酒比生产1加仑淡啤酒的机会成本要高，但折算为中间单位“元”后，可发现在换值不对等的情况下，两者的机会成本已经是一致的了，所以无论琼斯选择生产5加仑黑啤酒或者10加仑淡啤酒都是一样的。对于布朗来说，无论是只看生产量、或者是把换值也考虑进去后的相对单位“元”，生产淡啤酒的机会成本都比生产黑啤酒的机会成本要高，只生产黑啤酒明显地是一个更优的方案。&lt;/p&gt;
&lt;p&gt;接下来可以对书中的例子补上隐含的限制条件。对于 2.5 中的例子来说，隐含条件是1加仑黑啤酒可以交换1加仑淡啤酒，而这一换值是相对恒等的。相对恒等这一限制条件用于保证并不会因为边际的影响而变动换值。&lt;/p&gt;
&lt;p&gt;而对于 2.6 的例子来说，由于也沿用 2.5 的限制条件，所以也有1加仑黑啤酒可以交换1加仑淡啤酒这一隐含条件。将这一隐含条件转化为以相对单位进行描述，就是每加仑黑啤酒和每加仑淡啤酒的价格相等，假设是1元。在两个酿酒商协定等量3加仑的交换时，对琼斯来说，1加仑黑啤酒的机会成本是2加仑淡啤酒，换算成中间单位后，则对琼斯来说，1加仑黑啤酒的机会成本是2元，1加仑淡啤酒的机会成本是1元，以3加仑黑啤酒换取3加仑淡啤酒也即等于用每加仑1元的换值取得3加仑黑啤酒，每加仑黑啤酒在交换中的成本是1加仑淡啤酒、即1元，比机会成本低，所以是获益了的。对布朗来说，1加仑淡啤酒的机会成本是4/3加仑黑啤酒，换算成中间单位，1加仑淡啤酒的机会成本是4/3元，1加仑黑啤酒的机会成本是3/4元，每加仑淡啤酒的换值是1元，低于1加仑淡啤酒的机会成本而高于1加仑黑啤酒的机会成本，也是获益了的。也可见，补上换值这一隐含条件后，再引入一个相对单位“价格（元）”后，是否获益就显得更清晰了。&lt;/p&gt;
&lt;p&gt;再看1加仑黑啤酒换值为2加仑淡啤酒时的情况，以相对单位来说即是1加仑黑啤酒2元，1加仑淡啤酒1元。对于琼斯来说，1加仑淡啤酒换1加仑黑啤酒时明显获益了，因为以相对单位来衡来那个，1加仑黑啤酒是2元，以3元交换得6元——获益了。以此类推，对于布朗来说，他不能在交换中获益，因为换值（以每加仑2元的价格获取每加仑机会成本是3/8元的淡啤酒）低于他的机会成本了。可见 2.6 的例子必须加入限制条件，1加仑黑啤酒可以交换1加仑淡啤酒，这时，双方才能从交换中获益。没有这个限制条件，或者说，在设定换值不等的情况下，交换是否获益，真的需要的重新计算了。例如我假设1加仑黑啤酒换值是2加仑的淡啤酒，这个换值下是无法达到在交换中获益的——对于布朗来说，最低是8/3元、或者说8/3加仑淡啤酒才能等到对等的黑啤酒，换值就必须高于8/3元，但对于琼斯来说，每加仑8/3元的黑啤酒高于他的机会成本。双方是无法通过交换获益的。&lt;/p&gt;
&lt;p&gt;另：前文标题『机会成本』有点不妥，其实用本文的这个标题更好的。&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>在 shell prompt 中显示 git 的变更</title>
   <link href="http://yan-yan.info/2010/git-prompt.html"/>
   <updated>2010-03-20T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2010/git-prompt</id>
   <content type="html">&lt;p&gt;看到这样的一个东西，&lt;a href=&quot;http://github.com/lvv/git-prompt/&quot; target=&quot;_blank&quot;&gt;git-prompt&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;闲话略过不提，大概记下自己应用这东西的笔记。&lt;/p&gt;
&lt;p&gt;首先是 checkout 代码：&lt;code&gt;git clone http://github.com/lvv/git-prompt.git ~/src/&lt;/code&gt;；这里假设你用户根目录下有一个叫做 &lt;em&gt;src&lt;/em&gt; 的文件夹。&lt;/p&gt;
&lt;p&gt;在 Linux 中是 ~/.bashrc，在 Mac OS X 下是 ~/.profile，使用趁手的编辑打开这个文件，我这里是 &lt;code&gt;vim ~/.profile&lt;/code&gt;，加入这句：&lt;code&gt;source ~/src/git-prompt/git-prompt.sh&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;至此，安装完成。需要修改配置的话，把 &lt;strong&gt;git-prompt.conf&lt;/strong&gt; 复制到用户根目录下并改名为 &lt;strong&gt;.git-prompt.conf&lt;/strong&gt;，通过修改这个文件进行配置即可。&lt;/p&gt;
&lt;p&gt;我不喜欢那么长的一行 prompt，而且还会把你自定义的 &lt;code&gt;PS1&lt;/code&gt; 给强制无效化。前一个问题简单修改一下 git-prompt.sh 就可以了，后一个问题就跟整个运作机制有关了。&lt;/p&gt;
&lt;p&gt;我对 git-prompt.sh 的修改很简单，将 601 行的 &lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
&lt;code&gt;head_local=&quot;${head_local+$vcs_color$head_local }&quot;&lt;/code&gt;
&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;改为：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;head_local=&quot;\n${head_local+$vcs_color$head_local }&quot;&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;将 659 行的&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
&lt;code&gt;PS1=&quot;$colors_reset$rc$head_local$color_who_where$dir_color$cwd$tai    l_local$dir_color$prompt_char $colors_reset&quot;&lt;/code&gt;
&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;改为：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
&lt;code&gt;PS1=&quot;\n$color_who_where$dir_color$cwd$tail_local$dir_color$colors_re    set$rc$head_local$colors_reset$prompt_char &quot;&lt;/code&gt;
&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;完事。&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>Buggy IE6, maybe a new IE6 bug</title>
   <link href="http://yan-yan.info/2010/floating-element-make-absolute-one-hide-in-ie6.html"/>
   <updated>2010-03-18T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2010/floating-element-make-absolute-one-hide-in-ie6</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://img.ly/FAv&quot; target=&quot;_blank&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;/images/large_buggy_ie6.jpg&quot; alt=&quot;Did you see the buggy ie6 screenshot?&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you hadn’t see the screenshot above, get it here: &lt;a href=&quot;http://img.ly/FAv&quot; target=&quot;_blank&quot;&gt;http://img.ly/FAv&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the screenshot, from top to bottom: IE6 and IE7 on the left, IE8 and Chromium on the right.&lt;/p&gt;
&lt;p&gt;I’m not sure someone else had been mention this bug before or not. &lt;/p&gt;
&lt;p&gt;Telling whole story may take many hours. In short, I working in a project and I make a layout with &lt;a href=&quot;http://www.alistapart.com/articles/fauxabsolutepositioning/&quot; target=&quot;_blank&quot;&gt;Faux Absolute Positioning&lt;/a&gt;. I need lightbox effect for photos and I choose &lt;a href=&quot;http://leandrovieira.com/projects/jquery/lightbox/&quot; target=&quot;_blank&quot;&gt;jQuery Lightbox plugin&lt;/a&gt;. Than the bug occurs. &lt;em&gt;When I click the photo, the overlay is out, but no photo there&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Let me show you an example: &lt;a href=&quot;/files/buggy-ie6/buggy.html&quot; target=&quot;_blank&quot;&gt;/files/buggy-ie6/buggy.html&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can test the page above, it show up correctly under IE 7, IE 8, and Firefox 3.6, Chromium 5.0.355.0 (41601), and Opera 10.50. ONLY IE 6 rendering it in incorrect way. I’m use same photo here and use it twice.&lt;/p&gt;
&lt;p&gt;I got two solution later on. First one, remove &lt;code&gt;float&lt;/code&gt; property for &lt;code&gt;.row&lt;/code&gt;, but this one maybe broke up Faux Absolute Positioning. The second one it, do float element cleaning before rendering the element in absolute position.&lt;/p&gt;
&lt;p&gt;I’m poor in language,  and here show you my two solutions: &lt;a href=&quot;/files/buggy-ie6/fixed-1.html&quot; target=&quot;_blank&quot;&gt;solution one&lt;/a&gt;, &lt;a href=&quot;/files/buggy-ie6/fixed-2.html&quot; target=&quot;_blank&quot;&gt;solution two&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That’s not whole story. In my case, I fixed this problem by add an CSS rule for &lt;code&gt;.box&lt;/code&gt;: &lt;code&gt;width: auto !important&lt;/code&gt;. I don’t know why and time limit, I can’t do test deeply and find out why.&lt;/p&gt;
</content>
 </entry>
 

 

 

 

 
 <entry>
   <title>人工的计算</title>
   <link href="http://yan-yan.info/2010/the-way-to-calculate-cost.html"/>
   <updated>2010-03-17T00:00:00-07:00</updated>
   <id>http://yan-yan.info/2010/the-way-to-calculate-cost</id>
   <content type="html">&lt;p&gt;把 &lt;a href=&quot;http://kaieconblog.spaces.live.com/Blog/cns!B4C829CC97B9EDD8!13654.entry&quot; target=&quot;_blank&quot;&gt;吃早饭&lt;/a&gt; 花费的时间也换算成可计算的成本，会不会有点算死草的感觉？还记得『少林足球』里面三师兄所说的那句“&lt;a href=&quot;http://zh.wikipedia.org/wiki/%E5%B0%91%E6%9E%97%E8%B6%B3%E7%90%83&quot; target=&quot;_blank&quot;&gt;我一秒鐘幾十萬上落&lt;/a&gt;”？&lt;/p&gt;
&lt;p&gt;另一方面来看，人的效率不可能无止境地增长，大致会是、大致在一个时间段内不断攀升，然后趋向平稳，最后再下降。这段描述没有任何事实根据，实在有点虚。不过就如文中所说，“这顿饭最大的成本是人工”，只是在如何计算人工这点上有点疑问而已。&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>以成功学作为案例的群体如何影响个人的研究报告</title>
   <link href="http://yan-yan.info/2010/review-on-outliers.html"/>
   <updated>2010-03-12T00:00:00-08:00</updated>
   <id>http://yan-yan.info/2010/review-on-outliers</id>
   <content type="html">&lt;p&gt;如果把『异类』褪去故事的外衣，那么就是在阐述成功人士为什么会成功的：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;他们所处于的年代和时间给予他们成功的机会。&lt;/li&gt;
  &lt;li&gt;他们在成功以前，对某一技能的练习和锻炼超过 100000 小时。&lt;/li&gt;
  &lt;li&gt;他们所在的家庭环境给予他们优势。&lt;/li&gt;
  &lt;li&gt;他们所在的群体或种族对他们性格的影响。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;若是祈求在看了这书以后会得到如何成功的启示，恐怕最后只有失望了。再假设你因为这样的原因感到失望，怕是也与成功无缘了。&lt;/p&gt;
&lt;p&gt;上述说了一番成功学，实在很老土。对我来说，在看这书之前的不久才读完『乌合之众』，隐隐有这两书都在研究社会群体的感觉。&lt;/p&gt;
&lt;p&gt;特别是第二部分，“传承”。&lt;/p&gt;
&lt;p&gt;例如『乌合之众』中有一个观点，“影响群众的意见与信念的间接因素，最重要的是民族，此外还有传统、时间、政治和社会制度、以及教育”，而这个观点在『异类』中也隐约可见：“丹麦人和比利时人共同分享欧洲广阔的自由民主贸易，但是他们却有着不同的历史，不同的政治体系，不同的宗教传统以及不同的语言、食物、建筑和文学——这要回溯到几万年以前。以上所有的差异导致在特定的情况下，丹麦人面对风险与不确定性时的反应，与比利时人完全不同。”&lt;/p&gt;
&lt;p&gt;这书摘录下来的句子数量远不及『乌合之众』，原因之一为，后者是偏向纯理论的书，而 Gladwell 像是在讲故事——这一观点我就不再重复了。&lt;/p&gt;
&lt;p&gt;如果看这书，请当作是社科类的研究报告，这是对群体是否会对个人发展有影响的案例研究。若是当作成功学的书籍，倒不如扎扎实实地花 100000 小时专注锻炼一个技能好了。&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>利用 Expression 开展设计</title>
   <link href="http://yan-yan.info/2010/begin-a-new-design-with-expression.html"/>
   <updated>2010-03-11T00:00:00-08:00</updated>
   <id>http://yan-yan.info/2010/begin-a-new-design-with-expression</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://jazzliang.wordpress.com/2010/02/26/%e5%a6%82%e4%bd%95%e7%94%a8-expression-%e9%96%8b%e5%b1%95%e8%a8%ad%e8%a8%88/&quot; target=&quot;_blank&quot;&gt;文中&lt;/a&gt;以门铃为例，给出了两个不同的表达式描述：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
「从门外被启动后，这个设计物能够在屋内的任何地方展示某个特定程式的执行结果。」&lt;/p&gt;
&lt;p&gt;「当我接近某人住家时，能启动让屋内任何地方展示特定运算成果，并且等待屋主启动另一个运算。」&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;如何用 expression 開展設計, &lt;a href=&quot;http://jazzliang.wordpress.com/&quot; target=&quot;_blank&quot;&gt;jazzliang’s thinking&lt;/a&gt;&lt;/cite&gt;
&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;作为练习，我也写了两个描述：&lt;/p&gt;
&lt;p&gt;「当我给出任意时间段或某一时刻的时候，能在恰当的位置展示这个时间段内所有相关事务，并等待我改变这一事务的状态。」&lt;/p&gt;
&lt;p&gt;「在信息接收到更新后，会按照预设的模式进行重新计算，然后在特定区域内汇报节略结果，并等待用户操作在另一个区域内显示完整结果。」&lt;/p&gt;
&lt;p&gt;是否合适的描述没有绝对的判定标准，应该不断反思和修改描述中的词句为好。&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>z3n: web based checklist</title>
   <link href="http://yan-yan.info/2010/z3n-a-web-based-checklist.html"/>
   <updated>2010-03-06T00:00:00-08:00</updated>
   <id>http://yan-yan.info/2010/z3n-a-web-based-checklist</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/images/z3n_2010.02.02.jpg&quot; alt=&quot;early Sreenshot of z3n&quot;&gt;&lt;/p&gt;
&lt;h3&gt;z3n 是什么呢？&lt;/h3&gt;
&lt;p&gt;z3n 是一个可以用作 checklist / to-do list 的小工具。它需要 PHP 5.3.0 或以上版本才能运行。对于 Windows 用户来说，下载一个 &lt;a href=&quot;http://www.wampserver.com/en/&quot; target=&quot;_blank&quot;&gt;WAMP5&lt;/a&gt;，再进行一些简单的设置即可运行。这个小工具并不建议于公共空间中运行——因为这是仅是一个小工具，没有任何对校验用户身份的代码。&lt;/p&gt;
&lt;p&gt;z3n 的安装十分简单，在 MySQL 中创建一个数据库，然后在导入 &lt;strong&gt;z3n.init.sql&lt;/strong&gt; 进行数据库的初始化；这些操作你都可以通过 PHPMyAdmin 完成。然后把 core 目录下的 config.example.php 重命名为 config.php，然后填写相应项进行设置。对于本地运行、例如利用 WAMP5 简单快速部署 z3n 的朋友，只需设置 Z3N_MYSQL_USERNAME，Z3N_MYSQL_PASSWORD，Z3N_MYSQL_SCHEMATA 这三个值就可以了。如果你觉得页面显示 Leechael 的这样的文字很碍眼，你可以把 Z3N_USERNAME 更改为你想要的字眼，例如 “Simpson” 或者 “Mr. Potatohead”；中文也是可以的，只要记得该文件是使用 UTF-8 编码格式保存即可。另一个设置是 Z3N_BACKGROUND_IMAGE，我在压缩包里面放了四张背景图片，根据喜好把图片名字替换 Z3N_BACKGROUND_IMAGE 的值即可。&lt;/p&gt;
&lt;p&gt;输入条目时，可以通过按下 &lt;code&gt;enter&lt;/code&gt; 保存；如果按下的是 &lt;code&gt;ctrl + enter&lt;/code&gt;，则是在保存当前条目的同时创建一个新的条目，以保证你整个输入流程是连续的。&lt;/p&gt;
&lt;p&gt;Z3N 是基于 BSD 协议发布，请随意使用。下载地址：&lt;del&gt;http://yan-yan.info/files/z3n.tar.gz&lt;/del&gt;(文件已移除。)&lt;/p&gt;
&lt;p&gt;Z3N 的原型是 &lt;a href=&quot;http://twitter.com/Livid&quot; target=&quot;_blank&quot;&gt;@Livid&lt;/a&gt; 旧作 Project-Babel 中的 zen，一个很好用的小工具，但我们并不需要 Project-Babel 完整的功能，所以， Z3N 诞生了。&lt;/p&gt;
&lt;p&gt;这是一个利用空余时间制作的小东西，没有进行严谨的调试，如果你在使用中出现莫名其妙的情况，请留言告知。&lt;/p&gt;
&lt;p&gt;对了，你需要一个多人可协作版本的 Z3N 吗？ &lt;code class=&quot;emotion&quot;&gt;;)&lt;/code&gt;&lt;/p&gt;
</content>
 </entry>
 

 
 <entry>
   <title>我怎么才能不做这件事</title>
   <link href="http://yan-yan.info/2010/how-can-i-ignore-that.html"/>
   <updated>2010-03-06T00:00:00-08:00</updated>
   <id>http://yan-yan.info/2010/how-can-i-ignore-that</id>
   <content type="html">&lt;p&gt;很多程序员都有“&lt;a href=&quot;http://en.wikipedia.org/wiki/Eating_one's_own_dog_food&quot; title=&quot;See definition on Wikipedia&quot; target=&quot;_blank&quot;&gt;Eating One’s Own Dog Food&lt;/a&gt;”的习惯， 这事并无好坏，做自己趁手的工具，也算是乐在其中的事儿。&lt;/p&gt;
&lt;p&gt;对于我来说，想编写一个自己趁手的网志系统是一直以来的想法，可这几年下来，代码删了又删，最后垮在了自己的完美主义之下。看 WordPress，也越来越好使了。说有什么不好，一是我对输出的 HTML 有洁癖，&lt;abbr title=&quot;What You See Is What You Get&quot;&gt;WYSIWYG&lt;/abbr&gt; 编辑器一直不喜欢，手写 HTML 代码才是王道；其次我觉得，对于网址系统来说，实在没有输出动态页面的必要。或者动态页面，只能说是为了 &lt;abbr title=&quot;Search Engine Optimization&quot;&gt;SEO&lt;/abbr&gt; 的必要。&lt;/p&gt;
&lt;p&gt;最后一次折腾是在这一年的春节：利用 Python 写命令行工具，储存用的是 buzhug，一个在小型系统开发中挺实用的类库，然后自定义编辑器——我选择了 Vim —— 在键盘上敲 &lt;code&gt;th add&lt;/code&gt; 就打开 Vim，然后啪啦啪啦一阵敲打，&lt;code&gt;:wq&lt;/code&gt; 就自动保存起来，标题、分类、标签什么的，都不需要。东西是出来了，我却没有激情写一个输出页面的脚本，而且自那段时间始、到最近的这几天，一直都在忙，勉强写了一个脚本输出 RSS2 的 Feed 了事，然后挂上新域名，找个免费的静态页面空间——挂上去了就完事。那真是无与伦比的简陋。&lt;/p&gt;
&lt;p&gt;总得有一个网志，我想存放点笔记，写点随笔。所以，现在这个基于 WordPress 的网志出来了。&lt;/p&gt;
&lt;p&gt;废话似乎说多了。而实际上我想去避免“重写一个网志系统”的事情，那么可以做的，只能是选择现有的网志系统进行改造，不喜欢的地方改掉。&lt;/p&gt;
&lt;p&gt;最后放一段最近在 Twitter 上看到的话：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
培養一種“我怎麼才能不做這件事”的心態，而不是“我怎麼做這件事”。這並不是什麼壞事，如果你知道你想要投入時間來做的事情是什麼，其他的所有事情你就應該想想怎麼來回避。 ~Fergus O’Connell, Work Less Archive More&lt;br&gt;
&lt;a href=&quot;http://twitter.com/maisonchen/status/9960618748&quot; target=&quot;_blank&quot;&gt;&lt;cite&gt;maisonchen&lt;/cite&gt;&lt;/a&gt;
&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;对了，原来的域名 &lt;em&gt;leechael.org&lt;/em&gt; 作废，新域名 &lt;em&gt;yan-yan.info&lt;/em&gt;，作废原因和我们伟大的党有关。&lt;/p&gt;
</content>
 </entry>
 

 
</feed>

