<?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 &#187; 写程序</title>
	<atom:link href="http://btmao.org/category/coding/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>缓存，缓存，缓存（二）—— 言归正传说twitter</title>
		<link>http://btmao.org/2009/09/22/cacheandcache_2/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=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/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=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>说说JAVA的接口</title>
		<link>http://btmao.org/2009/03/09/javainterface/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=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/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=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>
		<item>
		<title>打台球与写程序</title>
		<link>http://btmao.org/2009/03/03/billiardsandcoding/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=billiardsandcoding</link>
		<comments>http://btmao.org/2009/03/03/billiardsandcoding/#comments</comments>
		<pubDate>Tue, 03 Mar 2009 13:29:31 +0000</pubDate>
		<dc:creator>BTMao</dc:creator>
				<category><![CDATA[写程序]]></category>
		<category><![CDATA[台球]]></category>
		<category><![CDATA[程序]]></category>

		<guid isPermaLink="false">http://www.btmao.org/?p=59</guid>
		<description><![CDATA[我是个十足的台球爱好者。而自认为技术不错只是状态不稳定，嘿嘿。我也很喜欢写程序，至少以前是，虽然现在我更多把他看作是一种工作。但是我窃以为打台球与写程序是有相同相通之处的，如下。
架构思维
我们都知道打台球的时候要注意下颗球的走位，而且这个过程中你通常还得让这个走位更适合你在击打下一个颗球之后的连续击打。对于美式黑八，高手们通常都在开球之后就观察局面，布置战术流程，每颗球怎么走走到哪里。
在写程序的时候这个通常叫做架构思维。实际上在一个团队里，架构思维是很重要的。当你处在一个team work，你的每一个工作每一个项目都在不同程度的为你的团队、团队的其他成员以及你开发的系统服务。在一个较大系统的开发中，如果不注重架构，便会出现以下情况：1. 牵一发而动全身，当你要改动你的代码的时候你不得不去关注其他各种系统的异常，加大其他开发工程师和测试工程师的工作量，严重时可能会引起众怒。2. 一处不干净的代码可能拖慢整个系统，往往是这样，在你coding的过程中出现了一些状态，比如太困，昨天喝太多，晚上有个多年不见的美女约你心神不定盼着加班，你提交的代码可能会有那么一点两点不太干净的地方，他会消耗一些不应该被消耗的系统资源，增加了那么一点点的系统压力，这时候也许只有良好的架构才能稍微的暂时解救你，以致你在manager发现之前有足够时间完成修改。3. 架构的好处还有很多很多，它还会帮助你减少你的代码量，它有时还会帮助你处理进程的异常跳出，让你把更多的时间放在Controller层，去实现更多的功能。总之，好的架构就能带你上天堂，不好的架构就只能带你去住套房了。
稳定的心态
我说我自己经常觉得自己的状态不好，丁小晖在之前也经历了一个状态低迷期。某高人说，实际是央视的台球解说说，从业余高手到职业高手的一道重要的标准就是稳定的状态。而这个稳定的状态来自于心态。
程序员也需要稳定的心态，程序员有时候是需要高强度工作的，如果没有良好的心态，往往会觉得厌倦，特别是当你遇到一个不算难但是很繁杂的问题的时候，心态就发挥作用了。所以我觉得，平静的面对每一个问题，平静的处理每一个问题，是有技术的程序员到有经验且有技术的程序员的一道重要的标准。不急不躁就能写出更多优秀的代码而不至于出一堆人品问题，也会减少第一部分第二条所描述的问题的出现几率。

保持自己的技术领先
打台球是需要不断的学习技术和保持自己的技术领先的，即便你是个职业高手，打台球保持自己的精准度以及不断提高处理出杆时角度把握的精确是最重要的，只有你做到了才能赢得更多的胜利。
程序员在这一点上也是毋庸置疑的。就一个web程序员而言，从最初的CGI到Perl/PHP，到Java，再到Ruby等，各个时期都在流行的不同的技术。而且这个时期都很短。虽然基础是相当重要的，但是保持自己的技术革新也是相当重要的。不光是语言上的更新，还有自己的思维能力。有经验的程序员之所以能成为有经验，不应该是因为做过更多事情，遇到过更多异常情况，处理过更多的报错，而应该是比菜鸟们更懂得思维的诀窍，能更快更周密的进行思维。说到提高，程序员应该提高的还有与人交往的能力，与人交往并不是市场部门才有的专利，它对于技术人员也相当重要，与同事更好的交流能够协助你在工作中更好的与各部门进行协作，降低工作的难度，与其他人交流能够帮助你得到更多的信息，听到更多对事情的看法，学到更多能让你飞跃的知识。
]]></description>
			<content:encoded><![CDATA[<p>我是个十足的台球爱好者。而自认为技术不错只是状态不稳定，嘿嘿。我也很喜欢写程序，至少以前是，虽然现在我更多把他看作是一种工作。但是我窃以为打台球与写程序是有相同相通之处的，如下。</p>
<p><strong>架构思维</strong></p>
<p>我们都知道打台球的时候要注意下颗球的走位，而且这个过程中你通常还得让这个走位更适合你在击打下一个颗球之后的连续击打。对于美式黑八，高手们通常都在开球之后就观察局面，布置战术流程，每颗球怎么走走到哪里。</p>
<p>在写程序的时候这个通常叫做架构思维。实际上在一个团队里，架构思维是很重要的。当你处在一个team work，你的每一个工作每一个项目都在不同程度的为你的团队、团队的其他成员以及你开发的系统服务。在一个较大系统的开发中，如果不注重架构，便会出现以下情况：1. 牵一发而动全身，当你要改动你的代码的时候你不得不去关注其他各种系统的异常，加大其他开发工程师和测试工程师的工作量，严重时可能会引起众怒。2. 一处不干净的代码可能拖慢整个系统，往往是这样，在你coding的过程中出现了一些状态，比如太困，昨天喝太多，晚上有个多年不见的美女约你心神不定盼着加班，你提交的代码可能会有那么一点两点不太干净的地方，他会消耗一些不应该被消耗的系统资源，增加了那么一点点的系统压力，这时候也许只有良好的架构才能稍微的暂时解救你，以致你在manager发现之前有足够时间完成修改。3. 架构的好处还有很多很多，它还会帮助你减少你的代码量，它有时还会帮助你处理进程的异常跳出，让你把更多的时间放在Controller层，去实现更多的功能。总之，好的架构就能带你上天堂，不好的架构就只能带你去住套房了。</p>
<p><strong>稳定的心态</strong></p>
<p>我说我自己经常觉得自己的状态不好，丁小晖在之前也经历了一个状态低迷期。某高人说，实际是央视的台球解说说，从业余高手到职业高手的一道重要的标准就是稳定的状态。而这个稳定的状态来自于心态。</p>
<p>程序员也需要稳定的心态，程序员有时候是需要高强度工作的，如果没有良好的心态，往往会觉得厌倦，特别是当你遇到一个不算难但是很繁杂的问题的时候，心态就发挥作用了。所以我觉得，平静的面对每一个问题，平静的处理每一个问题，是有技术的程序员到有经验且有技术的程序员的一道重要的标准。不急不躁就能写出更多优秀的代码而不至于出一堆人品问题，也会减少第一部分第二条所描述的问题的出现几率。<br />
<strong><br />
保持自己的技术领先</strong></p>
<p>打台球是需要不断的学习技术和保持自己的技术领先的，即便你是个职业高手，打台球保持自己的精准度以及不断提高处理出杆时角度把握的精确是最重要的，只有你做到了才能赢得更多的胜利。</p>
<p>程序员在这一点上也是毋庸置疑的。就一个web程序员而言，从最初的CGI到Perl/PHP，到Java，再到Ruby等，各个时期都在流行的不同的技术。而且这个时期都很短。虽然基础是相当重要的，但是保持自己的技术革新也是相当重要的。不光是语言上的更新，还有自己的思维能力。有经验的程序员之所以能成为有经验，不应该是因为做过更多事情，遇到过更多异常情况，处理过更多的报错，而应该是比菜鸟们更懂得思维的诀窍，能更快更周密的进行思维。说到提高，程序员应该提高的还有与人交往的能力，与人交往并不是市场部门才有的专利，它对于技术人员也相当重要，与同事更好的交流能够协助你在工作中更好的与各部门进行协作，降低工作的难度，与其他人交流能够帮助你得到更多的信息，听到更多对事情的看法，学到更多能让你飞跃的知识。</p>
]]></content:encoded>
			<wfw:commentRss>http://btmao.org/2009/03/03/billiardsandcoding/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PHP的魔术函数们</title>
		<link>http://btmao.org/2009/02/26/magicfuncofphp/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=magicfuncofphp</link>
		<comments>http://btmao.org/2009/02/26/magicfuncofphp/#comments</comments>
		<pubDate>Thu, 26 Feb 2009 14:58:00 +0000</pubDate>
		<dc:creator>BTMao</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[写程序]]></category>
		<category><![CDATA[OO]]></category>
		<category><![CDATA[面向对象]]></category>
		<category><![CDATA[魔术函数]]></category>

		<guid isPermaLink="false">http://www.btmao.org/?p=37</guid>
		<description><![CDATA[PHP5带给我们的面向对象的变化是伟大的是空前的是胜利的，就像所有的两会一样。尤其是它提供给我们的那些魔术函数，更是像桂林山水一样令人流连忘返。
1. __construct() 构造函数

这是PHP默认的构造函数，它并不能主动被程序调用只能是在对象创建的时候被自动调用。同时为了向下兼容，PHP5也支持与类同名的构造函数，值得一提的是当两种构造函数同时存在的时候，__construct()将不会被调用。
2. __destruct() 析构函数
3. __get($key)
当读取一个不存在的属性时调用。

&#60; ?php
class Obj &#123;
	public function __get&#40;$key&#41; &#123;
		echo $key.' is not exsit';
	&#125;
&#125;
$obj = new Obj&#40;&#41;;
echo $obj-&#62;varnotexist;
?&#62;

上面的这段程序将会输出：varnotexist is not exist。
4. __set($key, value)
与__get($key)类似，而它是在修改一个不存在的属性时被调用。
5. __call($key, $args)
与__get($key)类似，而它是在调用一个不存在的方法时被调用。
6. __toString()
在试图打印一个对象时被调用

&#60; ?php
class Obj &#123;
	private $a;
	private $b;
	public function __construct&#40;&#41; &#123;
		$this-&#62;a = 'a';
		$this-&#62;b = 'b';
	&#125;
	public function __toString&#40;&#41; &#123;
		echo $this-&#62;a.'&#124;'.$this-&#62;b;
	&#125;
&#125;
$obj = new Obj&#40;&#41;;
echo $obj;
?&#62;

此时程序会打印：a&#124;b
7. __clone()
当对象被克隆的时候被打印。

&#60; ?php
class Obj &#123;
	public function __clone&#40;&#41; &#123;
		echo [...]]]></description>
			<content:encoded><![CDATA[<p>PHP5带给我们的面向对象的变化是伟大的是空前的是胜利的，就像所有的两会一样。尤其是它提供给我们的那些魔术函数，更是像桂林山水一样令人流连忘返。</p>
<p><strong>1. __construct() 构造函数<br />
</strong></p>
<p>这是PHP默认的构造函数，它并不能主动被程序调用只能是在对象创建的时候被自动调用。同时为了向下兼容，PHP5也支持与类同名的构造函数，值得一提的是当两种构造函数同时存在的时候，__construct()将不会被调用。</p>
<p><strong>2. __destruct() 析构函数</strong></p>
<p><strong>3. __get($key)</strong></p>
<p>当读取一个不存在的属性时调用。</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #339933;">&lt;</span> ?php
<span style="color: #000000; font-weight: bold;">class</span> Obj <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __get<span style="color: #009900;">&#40;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$key</span><span style="color: #339933;">.</span><span style="color: #0000ff;">' is not exsit'</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000088;">$obj</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Obj<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$obj</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">varnotexist</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>上面的这段程序将会输出：varnotexist is not exist。</p>
<p><strong>4. __set($key, value)</strong></p>
<p>与__get($key)类似，而它是在修改一个不存在的属性时被调用。</p>
<p><strong>5. __call($key, $args)</strong></p>
<p>与__get($key)类似，而它是在调用一个不存在的方法时被调用。</p>
<p><strong>6. __toString()</strong></p>
<p>在试图打印一个对象时被调用</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #339933;">&lt;</span> ?php
<span style="color: #000000; font-weight: bold;">class</span> Obj <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$a</span><span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$b</span><span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">a</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'a'</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">b</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'b'</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __toString<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">a</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'|'</span><span style="color: #339933;">.</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">b</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000088;">$obj</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Obj<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$obj</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>此时程序会打印：a|b</p>
<p><strong>7. __clone()</strong></p>
<p>当对象被克隆的时候被打印。</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #339933;">&lt;</span> ?php
<span style="color: #000000; font-weight: bold;">class</span> Obj <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __clone<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'another me'</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000088;">$obj</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Obj<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$obj1</span> <span style="color: #339933;">=</span> clone <span style="color: #000088;">$obj</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>程序输入：another me</p>
<p><strong>8. __sleep()</strong></p>
<p>该函数在对象进行序列化之前调用，它可以清除对象，并返回一个将被用于序列化的变量的数组。通常被用来做一些无需存储的数据和一些数据库连接的清理工作。</p>
<p><strong>9. __wakeup()</strong></p>
<p>与__sleep()正好相反，他在unserialize()之前被调用，通常用来重建一些变量和资源，或者用来初始化。</p>
<p><strong>10. __isset()</strong></p>
<p>在isset()函数执行前调用。</p>
<p><strong>11. __unset()</strong></p>
<p>在unset()函数执行前调用。</p>
<p><strong>12. __set_state()</strong></p>
<p>在var_export()前被调用，var_export()是一个被我忽视的函数，他和var_dump()一样返回的是一个变量的结构，不同的是他返回的是一个合法的PHP代码。比如：</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span style="color: #339933;">&lt;</span> ?php
<span style="color: #000000; font-weight: bold;">class</span> Obj<span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$a</span><span style="color: #339933;">=</span><span style="color: #0000ff;">'apple'</span><span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$b</span><span style="color: #339933;">=</span><span style="color: #0000ff;">'banana'</span><span style="color: #339933;">;</span>
	static <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __set_state<span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$key</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$item</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$key</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'=&gt;'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$item</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'&lt;br /&gt;'</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000088;">$obj</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Obj<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">eval</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">var_export</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$obj</span><span style="color: #339933;">,</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">';'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>程序将会输出：</p>

<div class="wp_syntax"><div class="code"><pre class="php">a<span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">'apple'</span>
b<span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">'banana'</span></pre></div></div>

<p>这有什么用呢，它可以让我们缓存或保存一个变量的结构并且随时使用。</p>
<p><strong>13. __autoload($key)</strong></p>
<p>在实例一个对象时，如果找不到相应的类的定义，则会调用。</p>
<p><strong>最后</strong></p>
<p>以上函数中__get(), __set(), __call(), __autoload()之类的函数也许会消耗相当多的系统资源，并不推荐使用。</p>
]]></content:encoded>
			<wfw:commentRss>http://btmao.org/2009/02/26/magicfuncofphp/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
