<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>BTMao</title>
	<atom:link href="http://btmao.org/feed/" rel="self" type="application/rss+xml" />
	<link>http://btmao.org</link>
	<description>B小T的幸福生活</description>
	<lastBuildDate>Thu, 11 Feb 2010 03:09:06 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Time changes everything&#8230;.</title>
		<link>http://btmao.org/2010/02/10/time-changes-everything/</link>
		<comments>http://btmao.org/2010/02/10/time-changes-everything/#comments</comments>
		<pubDate>Wed, 10 Feb 2010 05:12:25 +0000</pubDate>
		<dc:creator>BTMao</dc:creator>
				<category><![CDATA[小东西]]></category>
		<category><![CDATA[时间]]></category>

		<guid isPermaLink="false">http://btmao.org/?p=189</guid>
		<description><![CDATA[　　这两天注意到一个新闻，AOL要出售ICQ的消息，腾讯可能会得到收购权。时间真的可以改变一切。
　　当我习惯于随口讲出还记得某某年的时候，当年轻的记忆慢慢变得稀薄，当我发现小时候喜欢的歌星都在渐渐的老去，当我的长辈浮现出白发和皱纹，还有当年那首同桌的你，女主角或许已经成为一名高中学生的母亲。时间真的在改变这一切。
　　当我不得不为我的未来做最好的打算，当我不得不迈向三十而立之年，当我不得不面对事业的起起伏伏，当我不得不想到我还会有后代，他们会有什么样的前途。时间将如何改变现在的我。
　　长大。这是一个多么敏感的词汇。长大意味着越来越少的胡思乱想，长大意味着越来越多的曾经往事。当那些梦想被我抛在身后，当我意识到现实的生活，当我开始思考应该怎么为事业而努力。长大意味着越来越少的奇迹，长大意味着越来越多的抱怨。当我开始埋怨这个社会的不公，当我开始放弃改造社会，当我开始尝试改造自己，当我不再会梦想一夜的成功，当我渐渐懂得什么是脚踏实地。长大意味着越来越少的玩耍嬉戏，长大意味着越来越多的责任动力。当我开始独立，当我开始抱怨少壮的不努力，当我变得有点喜欢说教，当我有些厌倦曾经喜欢的游戏，当我的笑点越来越高，也许哭点会变得越来越低。
　　三十难立，四十迷惑，五十听天由命。我从不认为我会成为这样的人，直到现在。可是我却不得不担心，或许忧郁也是一个长大的标记。
　　小时候，我总是想，长大了会是个什么样子。那时候的我总是以为我会穿一件白大褂，拿了各种各样的试管容器，在一个充满科幻趣味的房间里，摆弄着各种各样颜色的液体。又或者是站在一面黑板前，四周一定会是近乎发亮的白色墙壁，我拿着各种颜色的粉笔，涂画着各式各样奇怪的公式和图形。我以为我会有一个机器人的助手，半球形的脑袋，圆柱形的身体，钳子一样的手，我会吩咐他各种事情比如让他拿给我什么器具又或者一杯橙汁。这个时候我一定是住在一个透亮的房子里，有院子，有花园，有一堆机器仆人。我会步入各种各样的会场，在讲台上说得眉飞色舞。或许我还会拿奖，我想是诺贝尔奖，那一定又是一个透亮的场所，圆形的玻璃屋顶就像是中世纪的教堂，我已经老了，老得一头白发，我颤颤的走出来，向与会的各位回忆我的际遇，一定会是雷鸣般的掌声。
　　现在的我真的好想再做这个梦，可惜怎么都梦不到了。
2010年26岁生日记
后记，感谢国足在我生日这一天让我真正感动了一把，3个进球，谢谢。
]]></description>
			<content:encoded><![CDATA[<p>　　这两天注意到一个新闻，AOL要出售ICQ的消息，腾讯可能会得到收购权。时间真的可以改变一切。<br />
　　当我习惯于随口讲出还记得某某年的时候，当年轻的记忆慢慢变得稀薄，当我发现小时候喜欢的歌星都在渐渐的老去，当我的长辈浮现出白发和皱纹，还有当年那首同桌的你，女主角或许已经成为一名高中学生的母亲。时间真的在改变这一切。<br />
　　当我不得不为我的未来做最好的打算，当我不得不迈向三十而立之年，当我不得不面对事业的起起伏伏，当我不得不想到我还会有后代，他们会有什么样的前途。时间将如何改变现在的我。<br />
　　长大。这是一个多么敏感的词汇。长大意味着越来越少的胡思乱想，长大意味着越来越多的曾经往事。当那些梦想被我抛在身后，当我意识到现实的生活，当我开始思考应该怎么为事业而努力。长大意味着越来越少的奇迹，长大意味着越来越多的抱怨。当我开始埋怨这个社会的不公，当我开始放弃改造社会，当我开始尝试改造自己，当我不再会梦想一夜的成功，当我渐渐懂得什么是脚踏实地。长大意味着越来越少的玩耍嬉戏，长大意味着越来越多的责任动力。当我开始独立，当我开始抱怨少壮的不努力，当我变得有点喜欢说教，当我有些厌倦曾经喜欢的游戏，当我的笑点越来越高，也许哭点会变得越来越低。<br />
　　三十难立，四十迷惑，五十听天由命。我从不认为我会成为这样的人，直到现在。可是我却不得不担心，或许忧郁也是一个长大的标记。<br />
　　小时候，我总是想，长大了会是个什么样子。那时候的我总是以为我会穿一件白大褂，拿了各种各样的试管容器，在一个充满科幻趣味的房间里，摆弄着各种各样颜色的液体。又或者是站在一面黑板前，四周一定会是近乎发亮的白色墙壁，我拿着各种颜色的粉笔，涂画着各式各样奇怪的公式和图形。我以为我会有一个机器人的助手，半球形的脑袋，圆柱形的身体，钳子一样的手，我会吩咐他各种事情比如让他拿给我什么器具又或者一杯橙汁。这个时候我一定是住在一个透亮的房子里，有院子，有花园，有一堆机器仆人。我会步入各种各样的会场，在讲台上说得眉飞色舞。或许我还会拿奖，我想是诺贝尔奖，那一定又是一个透亮的场所，圆形的玻璃屋顶就像是中世纪的教堂，我已经老了，老得一头白发，我颤颤的走出来，向与会的各位回忆我的际遇，一定会是雷鸣般的掌声。<br />
　　现在的我真的好想再做这个梦，可惜怎么都梦不到了。</p>
<p style="text-align: right;">2010年26岁生日记</p>
<p style="text-align: left;">后记，感谢国足在我生日这一天让我真正感动了一把，3个进球，谢谢。</p>
]]></content:encoded>
			<wfw:commentRss>http://btmao.org/2010/02/10/time-changes-everything/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>缓存，缓存，缓存（二）—— 言归正传说twitter</title>
		<link>http://btmao.org/2009/09/22/cacheandcache_2/</link>
		<comments>http://btmao.org/2009/09/22/cacheandcache_2/#comments</comments>
		<pubDate>Tue, 22 Sep 2009 15:43:24 +0000</pubDate>
		<dc:creator>BTMao</dc:creator>
				<category><![CDATA[写程序]]></category>
		<category><![CDATA[系统架构]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[comet]]></category>
		<category><![CDATA[kestrel]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[varnish]]></category>

		<guid isPermaLink="false">http://btmao.org/?p=175</guid>
		<description><![CDATA[上一篇我们花了大部分的口水去说MQ，现在我们要言归正传说说twitter的架构了。
我们说到我们要应付的事情出了大量的消息要转发要处理，还有突然爆发的流量等等。解决这样的问题，思路应该是要提高服务器每秒对请求的响应数。通常我们是将Memcached作为Fragment Cache放在我们前端服务器上。当收到用户请求的时候我们的Router会去判断这样的Fragment Cache是否存在，如果存在的话则直接返回。这样的做法是有效率的，而且就memcahced而言，命中率很高，我们很难去确定请求的来源位置，所以我们不如把预先计算好的数据放在网络前端的RAM上面。
当然在这个之后我们还会有很多的问题，并且在twitter向我们展示的宏大架构中我们找到了一些有用的东西。
首先我们看看twitter用到的这些中间件。

memcached，这个就不说了。
Varnish，是取代Squid的一个HTTP缓存，也就是一个Page Cache，据说性能至少是Squid的四倍。这个数据来源也是据说挪威的在线报纸vg.no，用三台Varnish替代了12台Squid，效果还比之前要好。
Kestrel，是twitter团队开发的一个开源的MQ，持久存储效果不错，听说代码写得也很漂亮1200来行，Kestrel是基于Memcached的文本协议，并对这些协议有所优化和完善。这个东西最初是用Ruby搞的后来又在Scala上实现了一遍。Ruby下的那个版本伸缩性不强，特别是Ruby的GC（垃圾处理）不是分代的，这意味这GC在处理完一个队列之后就会把自己给kill掉，然后MQ就崩溃了。后来移植到Scala上，它有成熟的JVM GC这个机制，而且代码还可以更简要。
Comet，一种服务器push的技术，之前facebook貌似也在用。简单的说，就是Client发送一条请求，然后Server接收到之后进入一个无限循环，将Client需要的数据push到一个response里面并且刷新它，这个response并不会被关闭，而是不断的被push数据然后刷新。知道Client断开连接之后才跳出这个循环。正是这样，我们可以说，Ajax解决了单用户的响应，而Comet则在保障性能的前提下，解决了协同多用户的响应。Comet的优点是它可以随时向客户端发送数据而不是仅仅响应用户的输入请求。而且这个数据是在现有的一个单连接上面进行，所以大大降低了发送数据的延迟时间（建立链接的开销和用户发送请求的开销）。

按照twitter自己的说法，最初他cache的策略简单到无敌，有点让人蛋疼，除了在API那里有一个Page Cache之外，然后啥都没有了。不过还好他80%的流量是来自API的。后来随着发展，twitter进行了强有力的架构的建设，其中cache策略的发展也是飞速。
一、Vector Cache，直接放在Data Pool的上面。存放了tweetID和tweetID之间的关系，tweetID是序列化的64位整数。而直写式的设计保证了极高的命中率，使得程序在Data Pool中工作的效率大大的提高，并且极大程度上加大了Data Pool和上层Cache的关联。
二、再往上是一个Row Cache，存放了数据库信息，主要是用户和tweet详细信息的相互对应。同样是直写式，并且使用了一个叫做Cache-money的程序，这是一个针对rail的ActiveRecord的直写式缓存实现。Rail的ActiveRecord具有很强的灵活性，完全不亚于hibernate，而且使用简单，效率也很高。
三、接着往上依次便是用memcached做的Fragment Cache和用Varnish做的Page Cache。其中Fragment Cache是直接消费Row甚至是Vector中的数据，打包成JSON或者XML。虽然这是一个直读式的Cache，但是由于特殊的层级关系和工作特性，他的命中率依然能达到95%以上。
这样的缓存策略下，数据库的大部分压力都被转到了后端程序中，而后端程序对资源的占用较为平滑，可预估性也比较强。
另外twitter还提到要为Page Cache提供一个独立的池，理由很简单，他们希望能够为Page Cache提供一个永远不会自毁的Cache的，而是一种按时间来划分的键值模式，以致于可以根据HTTP的协议头来对数据进行切片。我不喜欢这样的方式，虽然它应该会很有用，但是当所有的流过的页面都要在留下痕迹时，情况也许就会变得不太可控。
这样的Cache的架构也有他的问题，因为底层的两个直写式的Cache总是要去修补上面直读式Cache中的数据，这必然会造成MQ的压力。但毕竟有舍才有得，或许这才是架构的魅力吧。
]]></description>
			<content:encoded><![CDATA[<p><a href="http://btmao.org/2009/09/22/cacheandcache_1/">上一篇</a>我们花了大部分的口水去说MQ，现在我们要言归正传说说twitter的架构了。</p>
<p>我们说到我们要应付的事情出了大量的消息要转发要处理，还有突然爆发的流量等等。解决这样的问题，思路应该是要提高服务器每秒对请求的响应数。通常我们是将Memcached作为Fragment Cache放在我们前端服务器上。当收到用户请求的时候我们的Router会去判断这样的Fragment Cache是否存在，如果存在的话则直接返回。这样的做法是有效率的，而且就memcahced而言，命中率很高，我们很难去确定请求的来源位置，所以我们不如把预先计算好的数据放在网络前端的RAM上面。</p>
<p>当然在这个之后我们还会有很多的问题，并且在twitter向我们展示的宏大架构中我们找到了一些有用的东西。</p>
<p>首先我们看看twitter用到的这些中间件。</p>
<ol>
<li><strong>memcached</strong>，这个就不说了。</li>
<li><strong>Varnish</strong>，是取代Squid的一个HTTP缓存，也就是一个Page Cache，据说性能至少是Squid的四倍。这个数据来源也是据说挪威的在线报纸vg.no，用三台Varnish替代了12台Squid，效果还比之前要好。</li>
<li><strong>Kestrel</strong>，是twitter团队开发的一个开源的MQ，持久存储效果不错，听说代码写得也很漂亮1200来行，Kestrel是基于Memcached的文本协议，并对这些协议有所优化和完善。这个东西最初是用Ruby搞的后来又在Scala上实现了一遍。Ruby下的那个版本伸缩性不强，特别是Ruby的GC（垃圾处理）不是分代的，这意味这GC在处理完一个队列之后就会把自己给kill掉，然后MQ就崩溃了。后来移植到Scala上，它有成熟的JVM GC这个机制，而且代码还可以更简要。</li>
<li><strong>Comet</strong>，一种服务器push的技术，之前facebook貌似也在用。简单的说，就是Client发送一条请求，然后Server接收到之后进入一个无限循环，将Client需要的数据push到一个response里面并且刷新它，这个response并不会被关闭，而是不断的被push数据然后刷新。知道Client断开连接之后才跳出这个循环。正是这样，我们可以说，Ajax解决了单用户的响应，而Comet则在保障性能的前提下，解决了协同多用户的响应。Comet的优点是它可以随时向客户端发送数据而不是仅仅响应用户的输入请求。而且这个数据是在现有的一个单连接上面进行，所以大大降低了发送数据的延迟时间（建立链接的开销和用户发送请求的开销）。</li>
</ol>
<p>按照twitter自己的说法，最初他cache的策略简单到无敌，有点让人蛋疼，除了在API那里有一个Page Cache之外，然后啥都没有了。不过还好他80%的流量是来自API的。后来随着发展，twitter进行了强有力的架构的建设，其中cache策略的发展也是飞速。</p>
<p>一、<strong>Vector Cache</strong>，直接放在Data Pool的上面。存放了tweetID和tweetID之间的关系，tweetID是序列化的64位整数。而直写式的设计保证了极高的命中率，使得程序在Data Pool中工作的效率大大的提高，并且极大程度上加大了Data Pool和上层Cache的关联。</p>
<p>二、再往上是一个<strong>Row Cache</strong>，存放了数据库信息，主要是用户和tweet详细信息的相互对应。同样是直写式，并且使用了一个叫做Cache-money的程序，这是一个针对rail的ActiveRecord的直写式缓存实现。Rail的ActiveRecord具有很强的灵活性，完全不亚于hibernate，而且使用简单，效率也很高。</p>
<p>三、接着往上依次便是用memcached做的<strong>Fragment Cache</strong>和用Varnish做的<strong>Page Cache</strong>。其中Fragment Cache是直接消费Row甚至是Vector中的数据，打包成JSON或者XML。虽然这是一个直读式的Cache，但是由于特殊的层级关系和工作特性，他的命中率依然能达到95%以上。</p>
<p>这样的缓存策略下，数据库的大部分压力都被转到了后端程序中，而后端程序对资源的占用较为平滑，可预估性也比较强。</p>
<p>另外twitter还提到要为Page Cache提供一个独立的池，理由很简单，他们希望能够为Page Cache提供一个永远不会自毁的Cache的，而是一种按时间来划分的键值模式，以致于可以根据HTTP的协议头来对数据进行切片。我不喜欢这样的方式，虽然它应该会很有用，但是当所有的流过的页面都要在留下痕迹时，情况也许就会变得不太可控。</p>
<p>这样的Cache的架构也有他的问题，因为底层的两个直写式的Cache总是要去修补上面直读式Cache中的数据，这必然会造成MQ的压力。但毕竟有舍才有得，或许这才是架构的魅力吧。</p>
]]></content:encoded>
			<wfw:commentRss>http://btmao.org/2009/09/22/cacheandcache_2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>缓存，缓存，缓存（一）—— MQ</title>
		<link>http://btmao.org/2009/09/22/cacheandcache_1/</link>
		<comments>http://btmao.org/2009/09/22/cacheandcache_1/#comments</comments>
		<pubDate>Tue, 22 Sep 2009 14:28:03 +0000</pubDate>
		<dc:creator>BTMao</dc:creator>
				<category><![CDATA[写程序]]></category>
		<category><![CDATA[系统架构]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[MQ]]></category>

		<guid isPermaLink="false">http://btmao.org/?p=158</guid>
		<description><![CDATA[今天看了twitter关于cache的策略，领略了cache的威力，抒发了一下情感。
Everything runs from memory in Web 2.0.
优化Cache的策略是为了什么，不外乎三点：

减少IO，减少传输，减少CPU计算，减少同时工作的服务器的数量。
对结果进行共享，比如搜索，通常我们将关键词和结果串化进行Cache，然后在时间范围内使用Cache来对分享服务器工作结果。
更快。这永远都是终极的目标。


通常的架构，对于Cache而言，我们有两层，最前端是一个Page Cache，然后是Memcached，最下来就是Data Pool。

这样的架构下我们能够解决大部分的问题，特别是在处理更多常态化的需求时，访问量平稳，数据提交远小于数据读取。但是这么做有瓶颈特别是对于2.0的网站，我们要应付越来越多的用户数据，要不断的缩短Page Cache的有效时间，我们还得应付更多的异常的流量爆发，于是这样的简单的策略就不顶用了。除非我们不计成本的增加我们的服务器，加大我们的带宽，但也许你的老板会说找你还不如请IDC的人吃饭。我们是架构师嘛，为了不让老板这么说，那我们就得找出策略来。
对于无穷无尽的用户数据的提交，我们通常会想到MQ。说说MQ是个什么东西。他是一种消息队列的处理方式，消息列队是分布式应用间交换数据的一种技术，队列被存在磁盘或者RAM里，队列里面是消息，消息直到它被app读走才被删除。这种机制使得app可以独立的运行，它们不必知道各自的位置和状态，执行过程中也不需要等待其他app的响应。
MQ的最上层是一个消息管理器，下面是队列，队列里存放消息。中间是通道，这里是通道是消息传递的管道，是建立在物理网络中的概念，可以说通道MQ整个概念的精华。通道通常被分为三种，消息通道，MQI，Cluster通道。消息通道是一个单向的通道，有Post, Get, Request, Server等不同的类型，一般是建立在MQ服务器与其他事务服务器之间；MQI是建立在app与MQ之间的，是双向的通道；而Cluster通道则是建立在不同的MQ服务器或者同一MQ集群下的不同消息管理器之间。
MQ的工作原理差不多可以来说。

我们先看看单个系统的情况。app1发送一条消息到MQ，并告诉它消息属于队列1，于是MQ则将消息放到队列1里面，app2便可以读取这个消息然后MQ等待app2读取后把这条消息del掉。
下面这个便要复杂一些。app1发送一条消息到MQ，并告诉它消息属于队列2，然而MQ将消息放到队列2之后发现，这个队列其实是在sysB里面的，这时候MQ会把消息放到一个特殊的传输队列中，然后我们建立一个cluster通道，这个通道更像是一个代理app，这个代理app读到数据并传输到sysB，而在确认sysB真正获取到消息之后MQ才释放掉这条消息。在这里我们意识到MQ在确保消息的准确传输，并且一条消息只有一次这样的传输。
移步：缓存，缓存，缓存（二）—— 言归正传说twitter
]]></description>
			<content:encoded><![CDATA[<p>今天看了twitter关于cache的策略，领略了cache的威力，抒发了一下情感。</p>
<blockquote><p>Everything runs from memory in Web 2.0.</p></blockquote>
<p>优化Cache的策略是为了什么，不外乎三点：</p>
<blockquote><ol>
<li>减少IO，减少传输，减少CPU计算，减少同时工作的服务器的数量。</li>
<li>对结果进行共享，比如搜索，通常我们将关键词和结果串化进行Cache，然后在时间范围内使用Cache来对分享服务器工作结果。</li>
<li>更快。这永远都是终极的目标。</li>
</ol>
</blockquote>
<p>通常的架构，对于Cache而言，我们有两层，最前端是一个Page Cache，然后是Memcached，最下来就是Data Pool。<br />
<img src="http://btmao.org/wp-content/2009/09/未标题-1.jpg" alt="simple cache" title="simple cache" width="192" height="343" class="alignnone size-full wp-image-165" /><br />
这样的架构下我们能够解决大部分的问题，特别是在处理更多常态化的需求时，访问量平稳，数据提交远小于数据读取。但是这么做有瓶颈特别是对于2.0的网站，我们要应付越来越多的用户数据，要不断的缩短Page Cache的有效时间，我们还得应付更多的异常的流量爆发，于是这样的简单的策略就不顶用了。除非我们不计成本的增加我们的服务器，加大我们的带宽，但也许你的老板会说找你还不如请IDC的人吃饭。我们是架构师嘛，为了不让老板这么说，那我们就得找出策略来。</p>
<p>对于无穷无尽的用户数据的提交，我们通常会想到MQ。说说MQ是个什么东西。他是一种消息队列的处理方式，消息列队是分布式应用间交换数据的一种技术，队列被存在磁盘或者RAM里，队列里面是消息，消息直到它被app读走才被删除。这种机制使得app可以独立的运行，它们不必知道各自的位置和状态，执行过程中也不需要等待其他app的响应。</p>
<p>MQ的最上层是一个消息管理器，下面是队列，队列里存放消息。中间是通道，这里是通道是消息传递的管道，是建立在物理网络中的概念，可以说通道MQ整个概念的精华。通道通常被分为三种，消息通道，MQI，Cluster通道。消息通道是一个单向的通道，有Post, Get, Request, Server等不同的类型，一般是建立在MQ服务器与其他事务服务器之间；MQI是建立在app与MQ之间的，是双向的通道；而Cluster通道则是建立在不同的MQ服务器或者同一MQ集群下的不同消息管理器之间。</p>
<p>MQ的工作原理差不多可以来说。<br />
<img src="http://btmao.org/wp-content/2009/09/mq1.jpg" alt="mq" title="mq" width="528" height="379" class="alignnone size-full wp-image-169" /><br />
我们先看看单个系统的情况。app1发送一条消息到MQ，并告诉它消息属于队列1，于是MQ则将消息放到队列1里面，app2便可以读取这个消息然后MQ等待app2读取后把这条消息del掉。</p>
<p>下面这个便要复杂一些。app1发送一条消息到MQ，并告诉它消息属于队列2，然而MQ将消息放到队列2之后发现，这个队列其实是在sysB里面的，这时候MQ会把消息放到一个特殊的传输队列中，然后我们建立一个cluster通道，这个通道更像是一个代理app，这个代理app读到数据并传输到sysB，而在确认sysB真正获取到消息之后MQ才释放掉这条消息。在这里我们意识到MQ在确保消息的准确传输，并且一条消息只有一次这样的传输。</p>
<p>移步：<a href="http://btmao.org/2009/09/22/cacheandcache_2/">缓存，缓存，缓存（二）—— 言归正传说twitter</a></p>
]]></content:encoded>
			<wfw:commentRss>http://btmao.org/2009/09/22/cacheandcache_1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>php的Socket</title>
		<link>http://btmao.org/2009/08/10/php_socket/</link>
		<comments>http://btmao.org/2009/08/10/php_socket/#comments</comments>
		<pubDate>Mon, 10 Aug 2009 13:56:28 +0000</pubDate>
		<dc:creator>BTMao</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[socket]]></category>

		<guid isPermaLink="false">http://btmao.org/?p=146</guid>
		<description><![CDATA[当我们需要在不同服务器或者不同的语言之间做数据交换，我们有一种方法是用Socket做数据代理。Socket是源于UNIX的套接字，基于TCP/IP协议，是从UNIX早期的命令集中演化而来的，基础的模式是“连接-读写-关闭”。Socket可以应用于B/S和C/S两种不同的网络软件架构上，现在已经被广泛的引用。
php的Socket模块虽然相对比较简陋，一些复杂的应用会出现一些莫名奇妙的问题，但是单单作为基础的数据代理来讲还是经受了人们的检验。
一、Socket传输的是什么
Socket传输的是字节流，没有定义边界。只是通过调节缓冲区的大小来完成流的截断，当然设置缓冲区的大小都是必须的，否则Socket也许会一直工作下去。Socket传输的数据很容易被截取并且会直接展示出来，所以你通常需要对你的数据进行加密，比如AES，就是很好的加密算法，不要用MD5这样的散列表，否则你会死得很惨。
PHP似乎想要get字节流加上边界，在它的socket_write这个函数中声明的三个参数，它的文档里面说如果你将第三个参数设置为PHP_NORMAL_READ，那么将会读取到/r或者/n，可惜，当我这样做的时候，程序溢出了。原因至今不明。
二、用php做一个SocketServer
我们先抛弃类，这篇将没有一个类定义出现。
前面我们已经说了Socket的工作模式是“连接-读写-关闭”。作为服务器，我们要做的事情是建立一个socket，绑定一个端口，然后监视每一个连接，读取他们传来的消息，并给予他们反馈，然后将这个连接毙掉。现在我们开始

&#60; ?php
//===================
//SockServ.php
//===================
define&#40;'SOCKIP', 'localhost'&#41;;
define&#40;'SOCKPORT', '12345'&#41;;
&#160;
/**
 * Set up our socket
 */
$sock = socket_create&#40;AF_INET, SOCK_STREAM, SOL_TCP&#41;; //创建一个socket
printf&#40;&#34;Socket created.\r\n&#34;&#41;;
socket_bind&#40;$sock, SOCKIP, SOCKPORT&#41;; //绑定一个端口
socket_listen&#40;$sock&#41;; //开始监视了
printf&#40;&#34;Socket has set up.\r\n\r\n&#34;&#41;;
&#160;
while&#40;true&#41; &#123;
	$conn = socket_accept&#40;$sock&#41;; //抓到一个，允许它的连接
	if &#40;$conn&#41; &#123;
		printf&#40;&#34;==========================================\r\n&#34;&#41;;
		printf&#40;&#34;Socket connected.\r\n&#34;&#41;;
		while&#40;$data = socket_read&#40;$conn, 1024&#41;&#41; &#123; 
		//千万不能加上PHP_NORMAL_READ啊
			$buffer = $data;
			printf&#40;&#34;Data Received.\r\n&#34;&#41;;
			print_r&#40;&#34;Buffer: &#34;.$buffer.&#34;\r\n&#34;&#41;;
			socket_write&#40;$conn, &#34;OK&#34;&#41;; //告诉客户端，OK，我收到了
			printf&#40;&#34;Successed!\r\n&#34;&#41;;
		&#125;
		socket_close&#40;$conn&#41;; //工作完成，你可以去了
		printf&#40;&#34;Closed the socket\r\n&#34;&#41;;
		printf&#40;&#34;==========================================\r\n\r\n&#34;&#41;;
	&#125;
&#125;
?&#62;

上面这段程序，你最好别用浏览器来跑，你可能会得到一个超时，你应该在命令行里面跑。在服务器上，让它跑在后台，然后就让它呆在那里吧，没事的。
三、还有客户端呢
我们当然还需要一个客户端，不然你执行上面程序时会一直停在“Socket has set up.”。客户端的任务就是在浏览器里打开一张页面程序，向服务器端发送那么一个字符串，然后接受服务器返回的“OK”。我们开始吧

&#60; ?php
//===================
//SockClient.php
//===================
define&#40;'SOCKIP', 'localhost'&#41;;
define&#40;'SOCKPORT', '12345'&#41;;
&#160;
$sock = socket_create&#40;AF_INET, SOCK_STREAM, SOL_TCP&#41;; //创建一个socket
$connStat [...]]]></description>
			<content:encoded><![CDATA[<p>当我们需要在不同服务器或者不同的语言之间做数据交换，我们有一种方法是用Socket做数据代理。Socket是源于UNIX的套接字，基于TCP/IP协议，是从UNIX早期的命令集中演化而来的，基础的模式是“连接-读写-关闭”。Socket可以应用于B/S和C/S两种不同的网络软件架构上，现在已经被广泛的引用。<br />
php的Socket模块虽然相对比较简陋，一些复杂的应用会出现一些莫名奇妙的问题，但是单单作为基础的数据代理来讲还是经受了人们的检验。</p>
<p><strong>一、Socket传输的是什么</strong></p>
<p>Socket传输的是字节流，没有定义边界。只是通过调节缓冲区的大小来完成流的截断，当然设置缓冲区的大小都是必须的，否则Socket也许会一直工作下去。Socket传输的数据很容易被截取并且会直接展示出来，所以你通常需要对你的数据进行加密，比如AES，就是很好的加密算法，不要用MD5这样的散列表，否则你会死得很惨。<br />
PHP似乎想要get字节流加上边界，在它的socket_write这个函数中声明的三个参数，它的文档里面说如果你将第三个参数设置为PHP_NORMAL_READ，那么将会读取到/r或者/n，可惜，当我这样做的时候，程序溢出了。原因至今不明。</p>
<p><strong>二、用php做一个SocketServer</strong></p>
<blockquote><p>我们先抛弃类，这篇将没有一个类定义出现。</p></blockquote>
<p>前面我们已经说了Socket的工作模式是“连接-读写-关闭”。作为服务器，我们要做的事情是建立一个socket，绑定一个端口，然后监视每一个连接，读取他们传来的消息，并给予他们反馈，然后将这个连接毙掉。现在我们开始</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #339933;">&lt;</span> ?php
<span style="color: #666666; font-style: italic;">//===================</span>
<span style="color: #666666; font-style: italic;">//SockServ.php</span>
<span style="color: #666666; font-style: italic;">//===================</span>
<span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'SOCKIP'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'localhost'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'SOCKPORT'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'12345'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * Set up our socket
 */</span>
<span style="color: #000088;">$sock</span> <span style="color: #339933;">=</span> <span style="color: #990000;">socket_create</span><span style="color: #009900;">&#40;</span>AF_INET<span style="color: #339933;">,</span> SOCK_STREAM<span style="color: #339933;">,</span> SOL_TCP<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//创建一个socket</span>
<span style="color: #990000;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Socket created.<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">socket_bind</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sock</span><span style="color: #339933;">,</span> SOCKIP<span style="color: #339933;">,</span> SOCKPORT<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//绑定一个端口</span>
<span style="color: #990000;">socket_listen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sock</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//开始监视了</span>
<span style="color: #990000;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Socket has set up.<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$conn</span> <span style="color: #339933;">=</span> <span style="color: #990000;">socket_accept</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sock</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//抓到一个，允许它的连接</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$conn</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #990000;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;==========================================<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #990000;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Socket connected.<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> <span style="color: #990000;">socket_read</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$conn</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1024</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> 
		<span style="color: #666666; font-style: italic;">//千万不能加上PHP_NORMAL_READ啊</span>
			<span style="color: #000088;">$buffer</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$data</span><span style="color: #339933;">;</span>
			<span style="color: #990000;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Data Received.<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #990000;">print_r</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Buffer: &quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$buffer</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #990000;">socket_write</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$conn</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;OK&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//告诉客户端，OK，我收到了</span>
			<span style="color: #990000;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Successed!<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #990000;">socket_close</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$conn</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//工作完成，你可以去了</span>
		<span style="color: #990000;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Closed the socket<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #990000;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;==========================================<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>上面这段程序，你最好别用浏览器来跑，你可能会得到一个超时，你应该在命令行里面跑。在服务器上，让它跑在后台，然后就让它呆在那里吧，没事的。</p>
<p><strong>三、还有客户端呢</strong></p>
<p>我们当然还需要一个客户端，不然你执行上面程序时会一直停在“Socket has set up.”。客户端的任务就是在浏览器里打开一张页面程序，向服务器端发送那么一个字符串，然后接受服务器返回的“OK”。我们开始吧</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #339933;">&lt;</span> ?php
<span style="color: #666666; font-style: italic;">//===================</span>
<span style="color: #666666; font-style: italic;">//SockClient.php</span>
<span style="color: #666666; font-style: italic;">//===================</span>
<span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'SOCKIP'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'localhost'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'SOCKPORT'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'12345'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$sock</span> <span style="color: #339933;">=</span> <span style="color: #990000;">socket_create</span><span style="color: #009900;">&#40;</span>AF_INET<span style="color: #339933;">,</span> SOCK_STREAM<span style="color: #339933;">,</span> SOL_TCP<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//创建一个socket</span>
<span style="color: #000088;">$connStat</span> <span style="color: #339933;">=</span> <span style="color: #990000;">socket_connect</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sock</span><span style="color: #339933;">,</span> SOCKIP<span style="color: #339933;">,</span> SOCKPORT<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//连接到服务器</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$connStat</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #666666; font-style: italic;">//连接成功</span>
	<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'&lt;p&gt;连接成功！'</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$buffer</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Hi, Server!'</span><span style="color: #339933;">;</span>
	<span style="color: #990000;">socket_write</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sock</span><span style="color: #339933;">,</span> <span style="color: #000088;">$buffer</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> <span style="color: #990000;">socket_read</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sock</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1024</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #666666; font-style: italic;">//依然切记不要PHP_NORMAL_READ</span>
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'OK'</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'&lt;p&gt;OK，搞定！&lt;/p&gt;'</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #990000;">socket_close</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sock</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//你可以安心的去了</span>
<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span> <span style="color: #666666; font-style: italic;">//连接失败啦 </span>
	<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'&lt;p&gt;连接居然失败了，是不是服务器没开啊！&lt;/p&gt;'</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>这个程序是跑在浏览器上面的，通常呢，我们会写成一个类这个类独立在系统的架构之外，将这个类文件交给负责不同app的程序员，让他们来调用，从而实现和服务器的通信。</p>
<p><strong>四、当然这是个很简单的例子</strong></p>
<p>实际上，我们通常有更复杂的事情去做，但是并不代表对于socket来说我们要做更多的事情，我们只需要在客户端的数据开源（现在是直接定义的），服务器端的数据处理（现在只是打印到屏幕上），还有服务器根据客户端数据进行不同的反馈以及客户端对反馈的处理，这几个方面进行扩展，便可以完成几乎所有的需求。<br />
Socket作为一种有效的数据代理方式，还能够为更好的程序架构提供帮助，比如我们提供更多的服务器数据交换来降低前段服务器的计算压力，Socket本身有很好的栈策略也能在服务器的部署上带来帮助。</p>
]]></content:encoded>
			<wfw:commentRss>http://btmao.org/2009/08/10/php_socket/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>谈谈互联网应用的本地化问题</title>
		<link>http://btmao.org/2009/07/30/web_app_local/</link>
		<comments>http://btmao.org/2009/07/30/web_app_local/#comments</comments>
		<pubDate>Thu, 30 Jul 2009 02:51:07 +0000</pubDate>
		<dc:creator>BTMao</dc:creator>
				<category><![CDATA[互联网]]></category>
		<category><![CDATA[本地化]]></category>

		<guid isPermaLink="false">http://btmao.org/?p=139</guid>
		<description><![CDATA[好久没写了，这里换了一个主机空间，免费的还是不靠谱说停就停了。回来这么久，还算是安定了下来。先说件很无奈的事情，我离开北京之后，Eason又去开了一场演唱会，还有过段时间的张北草原音乐节，张悬、Tizzy Bac，真是早不来晚不来，呆在北京真好。
和在北京时不一样，回到重庆，我们考虑得更多的是怎么为重庆本地市场做互联网，这段时间说到一个很多的问题是互联网应用的本地化应该怎么来做，谈得太多了，所以我决定写下来。
一、什么样的应用需要本地化
在回答这个问题之前我们要弄明白本地化的优势在哪里。当我们在一个地区拥有一定影响力的时候，我们能更好的吸引当地用户的目光，能够更好的了解当地用户的习惯，能够对地方性事件作出最快的反应，能够更好的聚集当地用户，另外我们能够更好的进行与当地商家的商务合作。不管怎么说，其实本地化的优势一句话表达就是我们在这里，我们能够激发各方面的地域感情。所以如果你有大量的用户来源，并且你致力于做一个地方性站点，那么你是存在优势的，而且这种优势在一些方面将会表现得很突出。
那么我们现在来回答什么样的应用需要本地化。或者说是回答什么样的应用做本地化是在浪费时间和金钱。互联网和网站一直在为了消除地域限制而努力，并在这个基础上建立起了不少成功的产品。

比如各种网上购物，在消除地域限制之后为用户带来了真正的便利而且拓宽了用户的需求。
再比如一些类型的社区，这些社区里面我们尽可能的希望和更多的来源更广泛的用户进行交流，在这样的社区里面我们发现仅仅是一个地区的人是不够的，这样的社区比如豆瓣，虾米，twitter&#8230;等等。
还有一种不适合用来做本地化的产品就是产品本身已经形成了一个个相对封闭的团体，本地化可能只是这个产品的一个部分，这样的产品做本地化优势是不明显的，比如facebook似的SNS，必须要针对一个更大的群体再将群体细分才有可能增强群体与群体之间的联系。

当然还有一些，本地化可能本身就是打破互联网的一个更自由更开放的性质。但还有有一些产品具有本地化的价值：

本地化资讯快报，因为我们在当地能对当地事件作出最快速的反应。在这一点上和其他的本地媒体的性质是一样的。当然互联网媒体相较于传统媒体的优势在何处，而资讯的长尾在哪里这是另一个问题，是如何做互联网新闻媒体的问题。
当地生活指南，结合我们的商业优势和我们对当地用户以及当地情况的了解来做地域性的生活指南。这是一个具有商业价值并且能够为用户创造更多的价值，能够最终提高网站在当地的影响力。
本地化社区，这种社区和上述的一些类型的社区刚好相反，这种社区的讨论更具有地方性，更能聚集地域情感，更容易讲线上活动转移到线下，能够增强用户之前的情感因素。

还有更多产品需要我们不断去寻找。
二、本地化要怎么做
本地化要怎么做才能做好，还是一句话，如何更好的提现我们的优势就是最好方法。

内容应该更加本地，更加纯粹。
加强商务合作，做本地用户与本地商家之间的杠杆。
强调地域性，增强基于地域的情感价值。
产品线要向用户的本地价值倾斜，将资源集中到更能体现我们价值的地方。

]]></description>
			<content:encoded><![CDATA[<p>好久没写了，这里换了一个主机空间，免费的还是不靠谱说停就停了。回来这么久，还算是安定了下来。先说件很无奈的事情，我离开北京之后，Eason又去开了一场演唱会，还有过段时间的张北草原音乐节，张悬、Tizzy Bac，真是早不来晚不来，呆在北京真好。</p>
<p>和在北京时不一样，回到重庆，我们考虑得更多的是怎么为重庆本地市场做互联网，这段时间说到一个很多的问题是互联网应用的本地化应该怎么来做，谈得太多了，所以我决定写下来。</p>
<p><strong>一、什么样的应用需要本地化</strong></p>
<p>在回答这个问题之前我们要弄明白本地化的优势在哪里。当我们在一个地区拥有一定影响力的时候，我们能更好的吸引当地用户的目光，能够更好的了解当地用户的习惯，能够对地方性事件作出最快的反应，能够更好的聚集当地用户，另外我们能够更好的进行与当地商家的商务合作。不管怎么说，其实本地化的优势一句话表达就是我们在这里，我们能够激发各方面的地域感情。所以如果你有大量的用户来源，并且你致力于做一个地方性站点，那么你是存在优势的，而且这种优势在一些方面将会表现得很突出。</p>
<p>那么我们现在来回答什么样的应用需要本地化。或者说是回答什么样的应用做本地化是在浪费时间和金钱。互联网和网站一直在为了消除地域限制而努力，并在这个基础上建立起了不少成功的产品。</p>
<ol>
<li>比如各种网上购物，在消除地域限制之后为用户带来了真正的便利而且拓宽了用户的需求。</li>
<li>再比如一些类型的社区，这些社区里面我们尽可能的希望和更多的来源更广泛的用户进行交流，在这样的社区里面我们发现仅仅是一个地区的人是不够的，这样的社区比如豆瓣，虾米，twitter&#8230;等等。</li>
<li>还有一种不适合用来做本地化的产品就是产品本身已经形成了一个个相对封闭的团体，本地化可能只是这个产品的一个部分，这样的产品做本地化优势是不明显的，比如facebook似的SNS，必须要针对一个更大的群体再将群体细分才有可能增强群体与群体之间的联系。</li>
</ol>
<p>当然还有一些，本地化可能本身就是打破互联网的一个更自由更开放的性质。但还有有一些产品具有本地化的价值：</p>
<ol>
<li>本地化资讯快报，因为我们在当地能对当地事件作出最快速的反应。在这一点上和其他的本地媒体的性质是一样的。当然互联网媒体相较于传统媒体的优势在何处，而资讯的长尾在哪里这是另一个问题，是如何做互联网新闻媒体的问题。</li>
<li>当地生活指南，结合我们的商业优势和我们对当地用户以及当地情况的了解来做地域性的生活指南。这是一个具有商业价值并且能够为用户创造更多的价值，能够最终提高网站在当地的影响力。</li>
<li>本地化社区，这种社区和上述的一些类型的社区刚好相反，这种社区的讨论更具有地方性，更能聚集地域情感，更容易讲线上活动转移到线下，能够增强用户之前的情感因素。</li>
</ol>
<p>还有更多产品需要我们不断去寻找。</p>
<p><strong>二、本地化要怎么做</strong></p>
<p>本地化要怎么做才能做好，还是一句话，如何更好的提现我们的优势就是最好方法。</p>
<ol>
<li>内容应该更加本地，更加纯粹。</li>
<li>加强商务合作，做本地用户与本地商家之间的杠杆。</li>
<li>强调地域性，增强基于地域的情感价值。</li>
<li>产品线要向用户的本地价值倾斜，将资源集中到更能体现我们价值的地方。</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://btmao.org/2009/07/30/web_app_local/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>难道价值和规模不应该是正比的吗？</title>
		<link>http://btmao.org/2009/05/27/weneedvalue/</link>
		<comments>http://btmao.org/2009/05/27/weneedvalue/#comments</comments>
		<pubDate>Wed, 27 May 2009 06:51:28 +0000</pubDate>
		<dc:creator>BTMao</dc:creator>
				<category><![CDATA[小东西]]></category>
		<category><![CDATA[价值]]></category>
		<category><![CDATA[规模]]></category>

		<guid isPermaLink="false">http://www.btmao.org/?p=127</guid>
		<description><![CDATA[今天上午，我的twhirl告诉我有如此一推，“digitalboy：Twitter的用户数已经从一年前的160万增加到了3,210万人左右，但这家旧金山公司的员工数仅从1月份时的21人增加到了45人。”（从twitter的网站看来应该是54个）
于是我开始想到价值与规模的问题。我看到的很多公司，迅速的膨胀，人数越来越多，效率却越来越低。难道价值和规模不应该是正比的吗？也许有几件事情是我们应该搞清楚的。
一、我们要做多大的事？
我们要做很大的事么，其实不然，创造价值不代表你要做出惊天动地的大事，我们要弄清楚的事情是我们到底要做什么，我们更要弄清楚不是非要几千万美金来能真正作出事情来。创造价值最根本是知道价值在哪里，而且做排场。
二、我们到底需要多少人？
一个精良的技术团队，通常只需要那么一两个产品，一两个前端工程师，两三个后端工程师，一个架构师同时还可以作为团队的管理人员。有时候我们就是应该这样苛刻，因为我们可能并不需要更多的人，精简的团队能带给我们更高的沟通效率和更高的执行力。当我们发现这样的团队人数不够用时，我们就要思考是不是我们的schedule或者任务不合理，或者是我们的流程有问题，要不然就是我们的人员工作效率太过低下。当我想到要去招新人的时候应该先尝试提高整个团队的素质，改良我们的工作模式。
三、我们真的要扩张吗？
我们希望有一家大公司，几千号人，一个庞大的官僚机构，我们可以高高在上，掌管了员工的命运。但从此，公司就会走上一条不归路，庞大的组织将拖垮这台机器，一些人多而引发的问题就开始出现了。我并不是说我们不能把一个公司做大，做大当然是好的，但是在做大之前，我们要想想是否有必要这样做，也许光是现在这些业务我还需要裁员呢，公司里面可能有30%的人是不做事情的。
那么新业务呢，我们需要不断的开展新的业务么？我这里说的是一个公司，并不是一个集团，你有足够的钱，你再开一家公司去做另一件事情这个当然是好的。但是对于一个公司而言，我们应该拥有一个核心业务，比如twitter的碎碎念，google的搜索，microsoft的个人软件，Oracle的数据库，SOHO的房子，Nokia的手机……而且任何的业务扩展，应该是围绕这个核心业务来做。不做不相关的事情，少做只有一点相关的事情。要记得，用户大多是冲着你的核心业务而来的，你要做的事情应该是服务的核心业务，让你的核心业务增值，这样才能给用户创造更多的价值，从而给自己带来更多的价值。尊重用户，尊重股东就是我们要选择新业务选择扩张的前提。
四、我们还有需要注意的么？
作为一个管理着来说，工作模式的改良，团队自身的提高，才是我们工作的重中之重。我一直在说我们需要有克制的扩张，我们需要在大多数时间学会控制自己的团队规模。可是这样显然是不够的。我们需要进步，公司需要进步，我需要做更多更困难的事情，这个时候，我们就需要一个更好的团队了。所以我们平时一直要做的便是总结、学习、进步。
]]></description>
			<content:encoded><![CDATA[<p>今天上午，我的twhirl告诉我有如此一推，“digitalboy：Twitter的用户数已经从一年前的160万增加到了3,210万人左右，但这家旧金山公司的员工数仅从1月份时的21人增加到了45人。”（从twitter的网站看来应该是54个）<br />
于是我开始想到价值与规模的问题。我看到的很多公司，迅速的膨胀，人数越来越多，效率却越来越低。难道价值和规模不应该是正比的吗？也许有几件事情是我们应该搞清楚的。</p>
<p><strong>一、我们要做多大的事？</strong></p>
<p>我们要做很大的事么，其实不然，创造价值不代表你要做出惊天动地的大事，我们要弄清楚的事情是我们到底要做什么，我们更要弄清楚不是非要几千万美金来能真正作出事情来。创造价值最根本是知道价值在哪里，而且做排场。</p>
<p><strong>二、我们到底需要多少人？</strong></p>
<p>一个精良的技术团队，通常只需要那么一两个产品，一两个前端工程师，两三个后端工程师，一个架构师同时还可以作为团队的管理人员。有时候我们就是应该这样苛刻，因为我们可能并不需要更多的人，精简的团队能带给我们更高的沟通效率和更高的执行力。当我们发现这样的团队人数不够用时，我们就要思考是不是我们的schedule或者任务不合理，或者是我们的流程有问题，要不然就是我们的人员工作效率太过低下。当我想到要去招新人的时候应该先尝试提高整个团队的素质，改良我们的工作模式。</p>
<p><strong>三、我们真的要扩张吗？</strong></p>
<p>我们希望有一家大公司，几千号人，一个庞大的官僚机构，我们可以高高在上，掌管了员工的命运。但从此，公司就会走上一条不归路，庞大的组织将拖垮这台机器，一些人多而引发的问题就开始出现了。我并不是说我们不能把一个公司做大，做大当然是好的，但是在做大之前，我们要想想是否有必要这样做，也许光是现在这些业务我还需要裁员呢，公司里面可能有30%的人是不做事情的。<br />
那么新业务呢，我们需要不断的开展新的业务么？我这里说的是一个公司，并不是一个集团，你有足够的钱，你再开一家公司去做另一件事情这个当然是好的。但是对于一个公司而言，我们应该拥有一个核心业务，比如twitter的碎碎念，google的搜索，microsoft的个人软件，Oracle的数据库，SOHO的房子，Nokia的手机……而且任何的业务扩展，应该是围绕这个核心业务来做。不做不相关的事情，少做只有一点相关的事情。要记得，用户大多是冲着你的核心业务而来的，你要做的事情应该是服务的核心业务，让你的核心业务增值，这样才能给用户创造更多的价值，从而给自己带来更多的价值。尊重用户，尊重股东就是我们要选择新业务选择扩张的前提。</p>
<p><strong>四、我们还有需要注意的么？</strong></p>
<p>作为一个管理着来说，工作模式的改良，团队自身的提高，才是我们工作的重中之重。我一直在说我们需要有克制的扩张，我们需要在大多数时间学会控制自己的团队规模。可是这样显然是不够的。我们需要进步，公司需要进步，我需要做更多更困难的事情，这个时候，我们就需要一个更好的团队了。所以我们平时一直要做的便是总结、学习、进步。</p>
]]></content:encoded>
			<wfw:commentRss>http://btmao.org/2009/05/27/weneedvalue/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>从海底捞的服务流程想起的</title>
		<link>http://btmao.org/2009/03/13/from-haidilao-service/</link>
		<comments>http://btmao.org/2009/03/13/from-haidilao-service/#comments</comments>
		<pubDate>Fri, 13 Mar 2009 15:45:43 +0000</pubDate>
		<dc:creator>BTMao</dc:creator>
				<category><![CDATA[系统架构]]></category>
		<category><![CDATA[敏捷开发]]></category>
		<category><![CDATA[模式]]></category>
		<category><![CDATA[流程]]></category>

		<guid isPermaLink="false">http://www.btmao.org/?p=118</guid>
		<description><![CDATA[这是经过我的观察得出的海底捞的服务流程

从某种程度上说海底捞的服务模式是高效的。
固定服务（Fixed Service）：前端服务，用Listener来侦听事务的数据变化，请求并且在与后台通信后返回一个回馈。后台对于该事务的反馈通常都是这一个模块来处理的。另外这个模块还担负着执行事务的创建和销毁的流程。总之这个模块就是和事务直接进行接触的基础服务模块。
临时服务（Interim Service）：后台服务，该部门是处理系统底层数据的。当它收到前端服务的请求是会进行反馈供前端服务使用。
循环服务（Loop Service）：该部分通常是服务器脚本，它们有明确的智能，比如加水，加糖，换毛巾。它们循环侦听每一个事务的数据变化然后做出处理。
在整个流程中，还有一个部分是例外的请求。当固定服务忙，或者被死锁时，事务提交一个请求，这时候请求或许会被某些其他模块侦听到，应该放入一个缓冲区中最终交给固定服务去处理，以致不破坏流程
]]></description>
			<content:encoded><![CDATA[<p>这是经过我的观察得出的海底捞的服务流程</p>
<p><a href="http://www.btmao.org/wp-content/uploads/2009/03/hdl-service.png"><img src="http://www.btmao.org/wp-content/uploads/2009/03/hdl-service.png" alt="hdl-service" title="hdl-service" class="alignnone size-full wp-image-119" /></a></p>
<p>从某种程度上说海底捞的服务模式是高效的。</p>
<p><strong>固定服务（Fixed Service）</strong>：前端服务，用Listener来侦听事务的数据变化，请求并且在与后台通信后返回一个回馈。后台对于该事务的反馈通常都是这一个模块来处理的。另外这个模块还担负着执行事务的创建和销毁的流程。总之这个模块就是和事务直接进行接触的基础服务模块。</p>
<p><strong>临时服务（Interim Service）</strong>：后台服务，该部门是处理系统底层数据的。当它收到前端服务的请求是会进行反馈供前端服务使用。</p>
<p><strong>循环服务（Loop Service）</strong>：该部分通常是服务器脚本，它们有明确的智能，比如加水，加糖，换毛巾。它们循环侦听每一个事务的数据变化然后做出处理。</p>
<p>在整个流程中，还有一个部分是例外的请求。当固定服务忙，或者被死锁时，事务提交一个请求，这时候请求或许会被某些其他模块侦听到，应该放入一个缓冲区中最终交给固定服务去处理，以致不破坏流程</p>
]]></content:encoded>
			<wfw:commentRss>http://btmao.org/2009/03/13/from-haidilao-service/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>关于JS——架构的设计</title>
		<link>http://btmao.org/2009/03/09/jscodemodel/</link>
		<comments>http://btmao.org/2009/03/09/jscodemodel/#comments</comments>
		<pubDate>Mon, 09 Mar 2009 12:38:24 +0000</pubDate>
		<dc:creator>BTMao</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[系统架构]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[模式]]></category>

		<guid isPermaLink="false">http://www.btmao.org/?p=79</guid>
		<description><![CDATA[随着web技术的发展，web2.0开始成为主流，JS在整个系统中的地位越来越重要，而对于JS的优化和架构的建立也越来越受到重视。
一、为自己的系统选择一个合适的框架
prototype和Jquery都是很好的框架。

prototype是一个完全存在于底层的代码，他优化了JS的面向对象的扩展，封装了DOM操作API，很好的处理了事件，AJAX等，体积也很小。要说他的缺点，恐怕就是它本身并没有实现太多的功能。
JQuery，本身实现了很多特效，能帮助工程师完成很多工作，即便是工程师对JS并不那么熟悉。它很重视代码的简介与高效。是一个很不错的库类，鼎鼎大名的YUI都复用了很多他的代码。

选好了一个框架，之后就应该要求工程师按照框架的要求去进行开发。否则，这个框架的选择还有什么意义呢。
二、不要把只有单独的子项目才会使用的JS放在全站都会引用的.js文件里
这个几乎是毋庸置疑的。但是有时候我们需要去减少一张页面的JS文件请求数，这时候我们通常会把子类的代码直接放在基类的文件中，然后随着项目的增多，继承该基类的子类也增多，我们在下载页面的时候需要去加载的无关代码量也开始增大。于是我们在控制JS文件请求数的同时也要考虑到，我们应该如何去规划JS的目录结构。
通常我们把js放在www的js目录下或者是将站点的所有静态文件都放于http://static.yourdomain.com，其中js文件的目录是http://static.yourdomain.com/js。
而我们通常把一些全站都会用到的函数，或者一些简单的极其常用的基类定义在一个类似于global.js的文件里，然后把其他的一些跨应用的基类放在以类名为文件里并放在class/目录下，如class/ajaxlist.js，这个文件是处理ajax下生成和操作数据列表的类的代码。而对不同应用则应该有一个文件是对这些基类的实例化和逻辑处理的相关代码便放在属于他们自己的文件里然后存放于app目录，比如app/album.js是关于相册的代码。
于是，我们的HTML里面应该是这样的。

&#60;script src=&#34;http://static.yourdomain.com/js/prototype.js?124&#34;&#62;&#60;/script&#62;
&#60;script src=&#34;http://static.yourdomain.com/js/global.js?326&#34;&#62;&#60;/script&#62;
&#60;script src=&#34;http://static.yourdomain.com/js/class/ajaxlist.js?178&#34;&#62;&#60;/script&#62;
&#60;script src=&#34;http://static.yourdomain.com/js/app/album.js?768&#34;&#62;&#60;/script&#62;

而这样的代码是很符合优化策略的
三、在HTML里为你的JS加上版本号
这是很必要的。这将利用浏览器的缓存或SQUID等来减少浏览器像服务器进行请求的次数，也将节省用户的下载时间。只要版本号不变化，浏览器就不会重新下载。
四、在用户操作前为用户做好准备工作
有一些过度的结构化的代码反而会造成负担。特别是在IE的JS执行效率还不算很高的现在看来。有时候用服务器端去处理那些没必要交给JS的数据，将完整的初始状态留给用户对用户来说可能是更好的体验。
]]></description>
			<content:encoded><![CDATA[<p>随着web技术的发展，web2.0开始成为主流，JS在整个系统中的地位越来越重要，而对于JS的优化和架构的建立也越来越受到重视。</p>
<p><strong>一、为自己的系统选择一个合适的框架</strong></p>
<p>prototype和Jquery都是很好的框架。</p>
<ol>
<li>prototype是一个完全存在于底层的代码，他优化了JS的面向对象的扩展，封装了DOM操作API，很好的处理了事件，AJAX等，体积也很小。要说他的缺点，恐怕就是它本身并没有实现太多的功能。</li>
<li>JQuery，本身实现了很多特效，能帮助工程师完成很多工作，即便是工程师对JS并不那么熟悉。它很重视代码的简介与高效。是一个很不错的库类，鼎鼎大名的YUI都复用了很多他的代码。</li>
</ol>
<p>选好了一个框架，之后就应该要求工程师按照框架的要求去进行开发。否则，这个框架的选择还有什么意义呢。</p>
<p><strong>二、不要把只有单独的子项目才会使用的JS放在全站都会引用的.js文件里</strong></p>
<p>这个几乎是毋庸置疑的。但是有时候我们需要去减少一张页面的JS文件请求数，这时候我们通常会把子类的代码直接放在基类的文件中，然后随着项目的增多，继承该基类的子类也增多，我们在下载页面的时候需要去加载的无关代码量也开始增大。于是我们在控制JS文件请求数的同时也要考虑到，我们应该如何去规划JS的目录结构。</p>
<p>通常我们把js放在www的js目录下或者是将站点的所有静态文件都放于http://static.yourdomain.com，其中js文件的目录是http://static.yourdomain.com/js。</p>
<p>而我们通常把一些全站都会用到的函数，或者一些简单的极其常用的基类定义在一个类似于global.js的文件里，然后把其他的一些跨应用的基类放在以类名为文件里并放在class/目录下，如class/ajaxlist.js，这个文件是处理ajax下生成和操作数据列表的类的代码。而对不同应用则应该有一个文件是对这些基类的实例化和逻辑处理的相关代码便放在属于他们自己的文件里然后存放于app目录，比如app/album.js是关于相册的代码。</p>
<p>于是，我们的HTML里面应该是这样的。</p>

<div class="wp_syntax"><div class="code"><pre class="html">&lt;script src=&quot;http://static.yourdomain.com/js/prototype.js?124&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;http://static.yourdomain.com/js/global.js?326&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;http://static.yourdomain.com/js/class/ajaxlist.js?178&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;http://static.yourdomain.com/js/app/album.js?768&quot;&gt;&lt;/script&gt;</pre></div></div>

<p>而这样的代码是很符合优化策略的</p>
<p><strong>三、在HTML里为你的JS加上版本号</strong></p>
<p>这是很必要的。这将利用浏览器的缓存或SQUID等来减少浏览器像服务器进行请求的次数，也将节省用户的下载时间。只要版本号不变化，浏览器就不会重新下载。</p>
<p><strong>四、在用户操作前为用户做好准备工作</strong></p>
<p>有一些过度的结构化的代码反而会造成负担。特别是在IE的JS执行效率还不算很高的现在看来。有时候用服务器端去处理那些没必要交给JS的数据，将完整的初始状态留给用户对用户来说可能是更好的体验。</p>
]]></content:encoded>
			<wfw:commentRss>http://btmao.org/2009/03/09/jscodemodel/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>说说JAVA的接口</title>
		<link>http://btmao.org/2009/03/09/javainterface/</link>
		<comments>http://btmao.org/2009/03/09/javainterface/#comments</comments>
		<pubDate>Mon, 09 Mar 2009 09:58:15 +0000</pubDate>
		<dc:creator>BTMao</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[写程序]]></category>
		<category><![CDATA[interface]]></category>
		<category><![CDATA[抽象]]></category>
		<category><![CDATA[接口]]></category>

		<guid isPermaLink="false">http://www.btmao.org/?p=72</guid>
		<description><![CDATA[学习JAVA的过程中，最让我郁闷的恐怕就是接口这个东西了。这个Interface，一度让我觉得是个鸡肋，看清楚，是鸡肋不是基类。在我一直的意识中，OO就是抽象，继承，再抽象，再继承。而这个接口在我看来无非是一个继承的替代品，一个多重继承的替代品。
可以为什么，我们要做接口而不是直接实现多重继承呢，JAVA开发组毕竟不是傻的。我带着疑问询问了google和还有一些前辈。
interface，可以说是class的类别，也可以说是对class的定义的一种规范。把不同的对象放到不同的接口里面，然后更好的管理它们。是一种对对象的抽象。
抽象这个词在这里额外的重要。其实对于继承来说，继承的意义也并不是完全在于我想要复用代码，而是在抽象。假设我们有类A里面有一函数run，类B也想用这个方法。于是有些人就class B extends A，这样的做法是不经过大脑的。其实我们有办法来实现而不造成更大的负担，比如：

class B &#123;
	function run&#40;&#41; &#123;
		A a = new A&#40;&#41;;
		A.run&#40;&#41;;
	&#125;
&#125;

这种想要靠继承来完成代码复用的思想可以说是对继承的滥用，而Java取缔多重继承实际上也是在制止这样的滥用继承，体现更好的设计模式。实际上，当我们想要去抽象对象的行为，而不考虑对象的本身属性的时候，我们就应该使用接口来处理对象与对象直接的通信。
另外，接口还能帮助我们更快的开发，而不用在父类与父类之上在建立一个父类，从而面对多级继承带来的负担。比如我们这时候要描述一个吃东西的行为。我们只需要有这样的一个接口。

interface eat &#123;
	function go&#40;&#41; &#123;&#125;
&#125;

这时候我们就不用去考虑是人还是狗，是黑人还是白人，吃东西前会做祈祷还是会先喝汤，即便他是个火星人，即便他吃饭前会玩一次躲猫猫，只要你觉得它要吃东西，那么你就让他使用这个接口，然后具体的实现它。这样如果我们把这些类的实例化放到一个工厂里，就能更好的体现出一个接口的抽象化。
]]></description>
			<content:encoded><![CDATA[<p>学习JAVA的过程中，最让我郁闷的恐怕就是接口这个东西了。这个Interface，一度让我觉得是个鸡肋，看清楚，是鸡肋不是基类。在我一直的意识中，OO就是抽象，继承，再抽象，再继承。而这个接口在我看来无非是一个继承的替代品，一个多重继承的替代品。</p>
<p>可以为什么，我们要做接口而不是直接实现多重继承呢，JAVA开发组毕竟不是傻的。我带着疑问询问了google和还有一些前辈。</p>
<p>interface，可以说是class的类别，也可以说是对class的定义的一种规范。把不同的对象放到不同的接口里面，然后更好的管理它们。是一种对对象的抽象。</p>
<p>抽象这个词在这里额外的重要。其实对于继承来说，继承的意义也并不是完全在于我想要复用代码，而是在抽象。假设我们有类A里面有一函数run，类B也想用这个方法。于是有些人就class B extends A，这样的做法是不经过大脑的。其实我们有办法来实现而不造成更大的负担，比如：</p>

<div class="wp_syntax"><div class="code"><pre class="java"><span style="color: #000000; font-weight: bold;">class</span> B <span style="color: #009900;">&#123;</span>
	function run<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		A a <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> A<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		A.<span style="color: #006633;">run</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>这种想要靠继承来完成代码复用的思想可以说是对继承的滥用，而Java取缔多重继承实际上也是在制止这样的滥用继承，体现更好的设计模式。实际上，当我们想要去抽象对象的行为，而不考虑对象的本身属性的时候，我们就应该使用接口来处理对象与对象直接的通信。</p>
<p>另外，接口还能帮助我们更快的开发，而不用在父类与父类之上在建立一个父类，从而面对多级继承带来的负担。比如我们这时候要描述一个吃东西的行为。我们只需要有这样的一个接口。</p>

<div class="wp_syntax"><div class="code"><pre class="java"><span style="color: #000000; font-weight: bold;">interface</span> eat <span style="color: #009900;">&#123;</span>
	function go<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>这时候我们就不用去考虑是人还是狗，是黑人还是白人，吃东西前会做祈祷还是会先喝汤，即便他是个火星人，即便他吃饭前会玩一次躲猫猫，只要你觉得它要吃东西，那么你就让他使用这个接口，然后具体的实现它。这样如果我们把这些类的实例化放到一个工厂里，就能更好的体现出一个接口的抽象化。</p>
]]></content:encoded>
			<wfw:commentRss>http://btmao.org/2009/03/09/javainterface/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>弱弱的说一下敏捷开发</title>
		<link>http://btmao.org/2009/03/04/smartdev/</link>
		<comments>http://btmao.org/2009/03/04/smartdev/#comments</comments>
		<pubDate>Wed, 04 Mar 2009 15:10:39 +0000</pubDate>
		<dc:creator>BTMao</dc:creator>
				<category><![CDATA[写程序]]></category>
		<category><![CDATA[敏捷开发]]></category>
		<category><![CDATA[模式]]></category>

		<guid isPermaLink="false">http://www.btmao.org/?p=65</guid>
		<description><![CDATA[关于敏捷开发，这已经不是一个新词了，我第一次听到敏捷开发这个名词的时候已经是好几年前。可是最近我才真正的开始关注和学习敏捷开发的思想。
首先，敏捷开发是一种针对人的以人为核心的开发模式，这是一种循序渐进的开发模式。他强调的是人与人之间的交互，而不是工具或者其他的流程。它有完整的开发团队，扁平式的，工程师与工程师之间，工程师与项目经理之间直接进行沟通。它把系统划分为若干个尽量小而简单的模块。它要求团队所有成员所做的事情都只是恰到好处。它甚至觉得我们应该拥有一个更好的沟通模式和流程控制，然后抛弃文档，因为文档会耗费大量的时间。
我们需要持续的向客户或者产品设计人员提交版本来让它了解进度并随时给出修改意见，这样做能避免更大程度的返工，也更能在不停的使用中进行测试，找出不尽人意的地方。
进度的控制很重要。进度是保持开发持续性的一个重要因素。而开发持续性是敏捷开发在代码质量控制的过程中的重中之重。
我们需要更好的架构和需求设计。更好的架构能保证模块与模块之间的解耦性，能减低模块之间的影响。而需求设计的完整能让工程师更清楚自己该做什么。
只做到恰到好处。完成所有客户提出的或者是产品设计人员提出的需求，然后仅此而已。保持开发速度，增强单位时间工作的实用性。
我们还需要，经常在一起开开小会，说说遇到的问题，然后改进。
总之我们的目标就是要刚刚好。
同时敏捷开发也存在他自身的不足：
1. 对于那些优先级不明确或者需求不明确的项目难以开展。
2. 团队的建设成本较高。这一点大部分来自于人的问题。人是有缺点的。比如人容易疏忽，犯错误，人宁愿自己写而不愿意改(我就是这样的人)，人有时候还难以保持一个优良的状态。于是我们要对团队进行不断的培训，培养，有时候还要设立很多规矩，比如不要随便打扰别人。
3. 当团队有新人进入或者有老人退出时，这一切都将变得很艰难。
其实敏捷开发，就像是一个美好的许愿，无论是公司老总，项目经理，还是工程师，对于敏捷开发都抱有不同程度的幻想，但是它真的那么容易实现吗？
]]></description>
			<content:encoded><![CDATA[<p>关于敏捷开发，这已经不是一个新词了，我第一次听到敏捷开发这个名词的时候已经是好几年前。可是最近我才真正的开始关注和学习敏捷开发的思想。</p>
<p>首先，敏捷开发是一种针对人的以人为核心的开发模式，这是一种循序渐进的开发模式。他强调的是人与人之间的交互，而不是工具或者其他的流程。它有完整的开发团队，扁平式的，工程师与工程师之间，工程师与项目经理之间直接进行沟通。它把系统划分为若干个尽量小而简单的模块。它要求团队所有成员所做的事情都只是恰到好处。它甚至觉得我们应该拥有一个更好的沟通模式和流程控制，然后抛弃文档，因为文档会耗费大量的时间。</p>
<p>我们需要持续的向客户或者产品设计人员提交版本来让它了解进度并随时给出修改意见，这样做能避免更大程度的返工，也更能在不停的使用中进行测试，找出不尽人意的地方。</p>
<p>进度的控制很重要。进度是保持开发持续性的一个重要因素。而开发持续性是敏捷开发在代码质量控制的过程中的重中之重。</p>
<p>我们需要更好的架构和需求设计。更好的架构能保证模块与模块之间的解耦性，能减低模块之间的影响。而需求设计的完整能让工程师更清楚自己该做什么。</p>
<p>只做到恰到好处。完成所有客户提出的或者是产品设计人员提出的需求，然后仅此而已。保持开发速度，增强单位时间工作的实用性。</p>
<p>我们还需要，经常在一起开开小会，说说遇到的问题，然后改进。</p>
<p>总之我们的目标就是要刚刚好。</p>
<p>同时敏捷开发也存在他自身的不足：</p>
<p>1. 对于那些优先级不明确或者需求不明确的项目难以开展。</p>
<p>2. 团队的建设成本较高。这一点大部分来自于人的问题。人是有缺点的。比如人容易疏忽，犯错误，人宁愿自己写而不愿意改(我就是这样的人)，人有时候还难以保持一个优良的状态。于是我们要对团队进行不断的培训，培养，有时候还要设立很多规矩，比如不要随便打扰别人。</p>
<p>3. 当团队有新人进入或者有老人退出时，这一切都将变得很艰难。</p>
<p>其实敏捷开发，就像是一个美好的许愿，无论是公司老总，项目经理，还是工程师，对于敏捷开发都抱有不同程度的幻想，但是它真的那么容易实现吗？</p>
]]></content:encoded>
			<wfw:commentRss>http://btmao.org/2009/03/04/smartdev/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
