﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>博客园-tmfc's .net cabin</title><link>http://www.cnblogs.com/tmfc/</link><description /><language>zh-cn</language><lastBuildDate>Wed, 10 Feb 2010 08:14:46 GMT</lastBuildDate><pubDate>Wed, 10 Feb 2010 08:14:46 GMT</pubDate><ttl>60</ttl><item><title>LightCloud设计特点</title><link>http://www.cnblogs.com/tmfc/archive/2009/03/08/1406421.html</link><dc:creator>tmfc</dc:creator><author>tmfc</author><pubDate>Sun, 08 Mar 2009 12:32:00 GMT</pubDate><guid>http://www.cnblogs.com/tmfc/archive/2009/03/08/1406421.html</guid><description><![CDATA[<p>阅读: 259 评论: 0 作者: <a href="http://www.cnblogs.com/tmfc/" target="_blank">tmfc</a> 发表于 2009-03-08 20:32 <a href="http://www.cnblogs.com/tmfc/archive/2009/03/08/1406421.html" target="_blank">原文链接</a></p><h4>Hash环</h4> <p>LightCloud使用一致性Hash算法（Consistent Hashing），好处就是当添加新节点的时候不用移动大量数据了。还不知道为什么？<a href="http://blog.csdn.net/barfoo/archive/2009/01/11/3753426.aspx">Consistent Hashing介绍</a>。</p> <p>一致性Hash算法也不算什么新鲜玩意儿了，凡是分布式系统都不免能见到它的身影，那LightCloud特别之处在哪里呢？好，我们广告之后告诉你……</p> <p>（可恶的广告）</p> <p>好，广告之后精彩继续</p> <p>为了提高可用性，LightCloud使用了数据复制，在正角上场之前，先上一个暖场的，这个暖场的来头还挺大<a href="http://s3.amazonaws.com/AllThingsDistributed/sosp/amazon-dynamo-sosp2007.pdf">Amazon's Dynamo</a>，先看大屏幕，</p> <p><img src="http://opensource.plurk.com/uploads/dynamo_replication.png"> </p> <p>图上说了，Key A对应的值会复制三份，分布放在A，B，C节点上（原因不用说了吧），这样做的后果就是系统比较复杂，特别是加入新节点之后，由于<a href="http://s3.amazonaws.com/AllThingsDistributed/sosp/amazon-dynamo-sosp2007.pdf">Amazon's Dynamo</a>系统本身就设计的比较复杂，这里就不细展开了，有兴趣的同学可以参考链接地址中的论文。</p> <p>主角上场，主角本身设计的比较简单，还是先看大屏幕</p> <p><img src="http://opensource.plurk.com/uploads/lc_replc.png"> </p> <p>怎么样，有没有看出什么道道来，节点本身复制了，这里是复制了两份，当然你也可以复制三份，第三份甚至可以放在另外的数据中心以提供更高的可靠性。LightCloud的复制用得是底层TokyoTyrant的复制功能，很环保。</p> <p>解决了复制的问题，还有一个问题就是加入新节点是数据转移的问题，这张图困扰了我很久，大家先仔细品味一下</p> <p><img src="http://opensource.plurk.com/uploads/storage_lookup.png"> </p> <p>本来挺简单的一个环，现在变成了两个，上面那个环呢只保存地址，下面那个环才是保存了真正的数据，这样做有什么好处呢？文档也比较简略，没有说清楚，我和作者amix沟通之后，他答应在后续的文档中详细加以说明，留待以后再来分析吧。</p> <h4>和TokyoTyrant通讯</h4> <p>可以通过两种方式和TokyoTyrant通讯：</p> <ul> <li>&nbsp; <ul> <li>使用Tyrant的二进制协议  <li>使用Memcached的协议 </li></ul></li></ul> <p>默认使用前者，因为是二进制的，而且支持调用Lua扩展，当然如果你愿意，也可以使用Memcached的协议。</p><img src="http://www.cnblogs.com/tmfc/aggbug/1406421.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/tmfc/archive/2009/03/08/1406421.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/tmfc/archive/2009/03/08/1406421.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56852/" target="_blank">淘宝网通过索引模式涉足网络文学</a><span style="color:gray">(2010-02-10 15:59)</span><br/>· <a href="http://news.cnblogs.com/n/56851/" target="_blank">苹果发布 iPhone/iPad SDK 3.2 beta2 开发包</a><span style="color:gray">(2010-02-10 15:37)</span><br/>· <a href="http://news.cnblogs.com/n/56850/" target="_blank">“谷姐”：披着“谷歌”羊皮的悲哀？</a><span style="color:gray">(2010-02-10 15:32)</span><br/>· <a href="http://news.cnblogs.com/n/56849/" target="_blank">2010，奇虎的本命年</a><span style="color:gray">(2010-02-10 15:26)</span><br/>· <a href="http://news.cnblogs.com/n/56847/" target="_blank">微软赢得Windows XP WGA诉讼</a><span style="color:gray">(2010-02-10 15:23)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/news/tag/Buzz/" target="_blank">Google Buzz相关新闻</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>有怪兽，有怪兽 - 通过MONSTER OF COMPRESSION选择压缩算法</title><link>http://www.cnblogs.com/tmfc/archive/2009/03/08/1406355.html</link><dc:creator>tmfc</dc:creator><author>tmfc</author><pubDate>Sun, 08 Mar 2009 10:52:00 GMT</pubDate><guid>http://www.cnblogs.com/tmfc/archive/2009/03/08/1406355.html</guid><description><![CDATA[<p>阅读: 1376 评论: 3 作者: <a href="http://www.cnblogs.com/tmfc/" target="_blank">tmfc</a> 发表于 2009-03-08 18:52 <a href="http://www.cnblogs.com/tmfc/archive/2009/03/08/1406355.html" target="_blank">原文链接</a></p><p>去年由于工作关系，需要给Memcached选择一种数据压缩算法，参考了2008版的MONSTER OF COMPRESSION，现在2009年度的又新鲜出炉了，有需要的朋友可以去下面看看</p>
<blockquote>
<p><b><span style="text-decoration: underline;"><a href="http://heartofcomp.altervista.org/MOC/MOC.htm">MONSTER OF COMPRESSION 2009</a></span></b></p>
</blockquote>
<p>由于用于压缩缓存数据，所以重要指标是压缩速度和解压速度，直接参考<b><span style="text-decoration: underline;">Ranked on Time of Compression</span></b>表和<b><span style="text-decoration: underline;">Ranked on Time of Decompression </span></b>表  </p>
<p>可以发现排在前列的算法就这么几个，而且基本上都是LZ帮派的，其中又以LZ77分舵的气焰最盛，那个速度叫一个块，比<b>7Zip</b>要快15倍，比压缩比最高的<b>NANOZIP</b>要快70多倍。由于MONSTER OF COMPRESSION的压缩测试数据包括非压缩的图片，二进制文件（包括exe和dll），压缩音频，视频等等，LZ帮派基本上压缩率是比较惨的（1G的数据压缩到700多M），但是Memcached缓存的都是什么，都是序列化后的对象，那不就是XML文件吗（当然也可以使用二进制序列化，不在讨论之列）。于是本着认真负责的态度，本人决定测试一下LZ帮的文本压缩能力。  </p>
<p>找来找去，去年排名前几的算法，只有<a href="http://www.quicklz.com/">QuickLZ</a>（07年还是排名第五的大怪兽今年不知道由于什么原因，没有测试数据）提供了可执行程序（最重要是还有C#版本的库），那就用QuickLZ粗略测试了一下，测试使用了对象序列化后产生的XML文件，具体的成绩已经有些模糊，压缩比应该是在50%左右，这个成绩还真不错，完全可以满足要求。不过最后由于种种原因，没能应用到项目中，所以没法提供更多资料了，大家有兴趣可以自己测试一下实际效果到底如何。</p><img src="http://www.cnblogs.com/tmfc/aggbug/1406355.html?type=1" width="1" height="1" alt=""/><p>评论: 3　<a href="http://www.cnblogs.com/tmfc/archive/2009/03/08/1406355.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/tmfc/archive/2009/03/08/1406355.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56852/" target="_blank">淘宝网通过索引模式涉足网络文学</a><span style="color:gray">(2010-02-10 15:59)</span><br/>· <a href="http://news.cnblogs.com/n/56851/" target="_blank">苹果发布 iPhone/iPad SDK 3.2 beta2 开发包</a><span style="color:gray">(2010-02-10 15:37)</span><br/>· <a href="http://news.cnblogs.com/n/56850/" target="_blank">“谷姐”：披着“谷歌”羊皮的悲哀？</a><span style="color:gray">(2010-02-10 15:32)</span><br/>· <a href="http://news.cnblogs.com/n/56849/" target="_blank">2010，奇虎的本命年</a><span style="color:gray">(2010-02-10 15:26)</span><br/>· <a href="http://news.cnblogs.com/n/56847/" target="_blank">微软赢得Windows XP WGA诉讼</a><span style="color:gray">(2010-02-10 15:23)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/news/tag/Buzz/" target="_blank">Google Buzz相关新闻</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>LightCloud -- 分布式键-值数据库</title><link>http://www.cnblogs.com/tmfc/archive/2009/03/07/1405669.html</link><dc:creator>tmfc</dc:creator><author>tmfc</author><pubDate>Sat, 07 Mar 2009 13:45:00 GMT</pubDate><guid>http://www.cnblogs.com/tmfc/archive/2009/03/07/1405669.html</guid><description><![CDATA[<p>阅读: 2057 评论: 8 作者: <a href="http://www.cnblogs.com/tmfc/" target="_blank">tmfc</a> 发表于 2009-03-07 21:45 <a href="http://www.cnblogs.com/tmfc/archive/2009/03/07/1405669.html" target="_blank">原文链接</a></p><p><a href="http://opensource.plurk.com/Overview/">Plurk.com</a>在今年2月28日开源了LightCloud这个分布式的键-值数据库，根据官方网站的信息，有以下特性</p>
<ul>
<li>&nbsp; 
<ul>
<li>基于<a href="http://tokyocabinet.sourceforge.net/tyrantdoc/">Tokyo Tyrant</a>（这个项目貌似又是另一个名叫Tokyo Cabinet的数据库系统的网络接口）。<a href="http://tokyocabinet.sourceforge.net/tyrantdoc/">Tokyo Tyrant</a>是最快的键-值数据库之一[<a href="http://tokyocabinet.sourceforge.net/benchmark.pdf">性能测试</a>]，并且已经开发了好几年并且在n个网站中被应用。 </li>
<li>性能非常好（可以和memcached进行对比） </li>
<li>在很少的服务器上面可以存储百万级的数据量 </li>
<li>简单的通过添加节点来扩展 </li>
<li>节点可以通过master-master复制来进行备份。很容易添加自动错误恢复和负载均衡功能 </li>
<li>使用<a href="http://lua.org">Lua</a>语言进行扩展 </li>
<li>备份和恢复数据时不需要关机 </li>
<li>LightCloud Manager工具可以很方便的管理节点，备份节点，查看状态 </li>
<li>非常小巧（客户端大约500行，Manager大约400行） </li>
<li>纯python开发，但是很容易移植到其他语言</li>
</ul>
</li>
</ul>
<h4>和Memcached以及MySql的区别</h4>
<p>Memcached是缓存服务器，而LightCloud内存储的数据是持久的（到底是数据库嘛）。</p>
<p>MySql和其他关系数据库服务器存储键-值对时效率不高（肯定没LightCloud这种专用的高）。</p>
<h4>和Memcached性能对比</h4>
<p>对LightCloud和Memcached做10,000次set和get</p>
<div class="cnblogs_code">
<pre>Elapsed for 10000 gets: 1.74538516998 seconds [memcache]
Elapsed for 10000 gets: 3.57339096069 seconds [lightcloud]

Elapsed for 10000 sets: 1.88236999512 seconds [memcache]
Elapsed for 10000 sets: 9.23674893379 seconds [lightcloud]
</pre>
</div>
<p>值得注意的一点是Memcached是完全在内存中操作的，而LightCloud是会读写硬盘的。</p>
<p>而Tokyo Tyrant官网提供的数据更加惊人（LightCloud在Tokyo Tyrant上增加了网络和Python语言执行开销）</p>
<div class="cnblogs_code">
<p>1 million GETS in &lt; 0.5 seconds </p>
<p>1 million SETS in &lt; 0.5 seconds</p>
</div>
<h4>使用Lua进行扩展</h4>
<p>Lua扩展貌似是由Tokyo Tyrant提供的</p>
<p>下面是一个简单的扩展，扩展出一个incr命令</p>
<div class="cnblogs_code">
<pre>function incr(key, value)
   value = tonumber(value)
   if not value then
      return nil
   end
   local old = tonumber(_get(key))
   if old then
      value = value + old
   end
   if not _put(key, value) then
      return nil
   end
   return value
end
</pre>
</div><img src="http://www.cnblogs.com/tmfc/aggbug/1405669.html?type=1" width="1" height="1" alt=""/><p>评论: 8　<a href="http://www.cnblogs.com/tmfc/archive/2009/03/07/1405669.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/tmfc/archive/2009/03/07/1405669.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56852/" target="_blank">淘宝网通过索引模式涉足网络文学</a><span style="color:gray">(2010-02-10 15:59)</span><br/>· <a href="http://news.cnblogs.com/n/56851/" target="_blank">苹果发布 iPhone/iPad SDK 3.2 beta2 开发包</a><span style="color:gray">(2010-02-10 15:37)</span><br/>· <a href="http://news.cnblogs.com/n/56850/" target="_blank">“谷姐”：披着“谷歌”羊皮的悲哀？</a><span style="color:gray">(2010-02-10 15:32)</span><br/>· <a href="http://news.cnblogs.com/n/56849/" target="_blank">2010，奇虎的本命年</a><span style="color:gray">(2010-02-10 15:26)</span><br/>· <a href="http://news.cnblogs.com/n/56847/" target="_blank">微软赢得Windows XP WGA诉讼</a><span style="color:gray">(2010-02-10 15:23)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/news/tag/Buzz/" target="_blank">Google Buzz相关新闻</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>[翻译]更有效的使用垃圾收集&amp;ndash; 第一部分</title><link>http://www.cnblogs.com/tmfc/archive/2008/07/29/1216384.html</link><dc:creator>tmfc</dc:creator><author>tmfc</author><pubDate>Tue, 29 Jul 2008 05:53:00 GMT</pubDate><guid>http://www.cnblogs.com/tmfc/archive/2008/07/29/1216384.html</guid><description><![CDATA[<p>阅读: 1121 评论: 5 作者: <a href="http://www.cnblogs.com/tmfc/" target="_blank">tmfc</a> 发表于 2008-07-29 13:53 <a href="http://www.cnblogs.com/tmfc/archive/2008/07/29/1216384.html" target="_blank">原文链接</a></p><p><strong><em><font color="#0080c0" size="1">翻译自Maoni's WebLog 文章</font></em></strong><a href="http://blogs.msdn.com/maoni/archive/2004/06/15/156626.aspx" target="_blank"><strong><em><font color="#0080c0" size="1">Using GC Efficiently – Part 1</font></em></strong></a><font color="#0080c0"><strong><em><font size="1">，Maoni是微软CLR Performance组的成员</font></em></strong> </font> <p>本文的目标是解释一些东西的代价好让你可以更好使用托管内存-而不是解释GC本身-只是解释如何使用它而已。我假设绝大多数人对于使用垃圾收集感兴趣，而不想自己实现一个。本文假设读者对GC有基础的了解，如果你需要一些关于GC的背景知识，Jeff Richter写了两篇非常好的MSDN文章，<a href="http://msdn.microsoft.com/zh-cn/magazine/bb985010(en-us).aspx">1</a>和<a href="http://msdn.microsoft.com/zh-cn/magazine/bb985011(en-us).aspx">2</a>。  <p>首先我会关注工作站类型的GC（Wks GC），然后我会解释服务器类型的GC（Svr GC）与前者的区别和你该用哪个（但是通常情况下你不需要选择，而我也会解释为什么你不需要）。  <h4>代龄<strong> （<strong>Generations</strong>）</strong></h4> <p>有三个代龄的原因是：我们希望一个经过良好优化的软件，大部分的对象在Gen0中就失效了，在一个服务器程序中，和每个请求（Request）关联的内存分配都应该在请求结束后失效。And the in flight allocation requests will make into Gen1 and die there（这句没能理解，请高手指点）。 实际上Gen1就是年轻的对象和年长的对象之间的缓冲而已。当你在性能监视器中查看每一代中的对象集合数量时，你应该希望看到Gen2和Gen0的比率非常低。Gen1的集合数量相对并不重要。收集Gen1的对象并不比收集Gen0的代价昂贵许多。  <h4>GC段<strong>（<strong>GC segments </strong>）</strong></h4> <p>首先我们看看GC怎么从操作系统获取内存吧。GC按段来保留（reserve）内存。每个段16M。当执行引擎（EE，Execution Engine）开始执行时，我们保留初始段--一个用于小对象堆，另一个用于大对象堆（LOH，large object heap）。  <p>内存按需进行调拨（commit）和释放（decommit）。当我们用完了保留的内存段会调拨。每次完全收集之后如果某个段没有被使用，就会被删除。  <p>LOH始终在它自己的段中存在-大对象和小对象被区分对待，这样它们就不和小对象共享段了。  <h4><strong>分配（Allocation）</strong></h4> <p>当你从GC堆中分配内存时，它到底消耗什么资源呢?如果我们不需要进行GC，分配就是1）将指针前移2）为新对象清除内存。对于可终结对象（finalizable object），还有一步额外的操作，它们还会被加入一个GC需要监视的队列。</p> <p>注意我说了“如果我们不需要进行GC”-这意味着分配的消耗和分配的大小成比例。你分配的越少，GC需要做的工作越少。如果你需要15个字节，它就请求15个字节；不要像使用malloc的时候那样进位到32个字节或者更大的块大小。这里有一个阀值，当阀值被超过时，GC操作被触发。你应该尽力使这种触发发生的越少越好。</p> <p>另一个GC堆和NT堆的区别是：一起分配的对象位置始终保持在一起。</p> <p>每个在GC堆中分配的对象有一个8字节的头（同步块+方法表指针）。</p> <p>就像我提到的一样，大对象的对待方式不一样，所以你应该使用不同的模式来分配它们。我会在大对象那一节讨论它。</p> <h4><strong>收集（Collection）</strong></h4> <p>首先，（垃圾）收集到底是什么时候发生的（换句话说，GC是什么时候被触发的）？当下面三种情况中的一种发生是，GC被触发</p> <p>1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 内存分配导致Gen0的阀值被超出;  <p>2)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.GC.Collect被调用;  <p>3)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 系统处于低内存状态;</p> <p>通常情况下都是由于1)引起的。当你分配了足够的内存之后，就触发了一次GC。分配只会在Gen0中发生。每次GC完成之后，Gen0就变成空的了。新的分配会再度填满Gen0，然后下一次GC就发生了，以此循环往复。</p> <p>你可以避免2)的情况，只要不调用CG.Collect就行了-如果你在写应用，通常情况下你永远都不需要调用它。BCL(Base Class Libraries)是唯一的需要显式调用它的地方（也是在非常有限的地方）。当你在应用程序中调用它的时候，问题在于它比你期望的要更加频繁的被调用（很容易发生），性能将会降低，由于GC在它们预期的时间之前被调用，而本来GC的调用是为最佳性能调优过的。</p> <p>3) 的情况是被系统中的其他进程影响，所以你不能做过多的控制，除了优化自己的程序之外没什么可以做的。</p> <p>我们来讨论一下上面这些都意味着什么。首先，GC堆是你的工作集的一部分。它消耗私有内存页。在理想状态下，分配出来的对象永远都是在Gen0就变得无用（意味着它们都在Gen0被回收而且没有任何完全收集会发生），这样你的GC堆永远不会超出Gen0的大小。实际情况几乎永远都不可能如此完美。所以你真的需要控制你的GC堆尺寸。</p> <p>其次，你希望控制花在GC上的时间。这意味着1)更少的GC次数和2)更少的高代龄GC次数。收集高代龄的对象比收集低代龄对象的代价要昂贵的多，因为收集高代龄的对象包括该代龄以及所有低于该代龄的所有对象。你分配的对象要么是临时的对象（很快就无用了，在Gen0就被收集，收集的代价非常低），要么是属于Gen2的，非常长命的对象。对于后者来说，常见的场景是程序启动时预分配的对象--例如，在订单系统中，你会为所有的分类目录分配内存而且它们在整个应用的生命周期中都会存活。</p> <p><a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=86CE6052-D7F4-4AEB-9B7A-94635BEEBDDA&amp;displaylang=en">CLRProfiler</a>是查看GC堆非常好的工具，可以看到里面有什么对象和哪个对象保持有它的引用，使它成为活的对象。</p> <h4><strong>如何组织你的数据（How to organize your data）</strong></h4> <h5>1) 值类型 vs 引用类型</h5> <p>就像你知道的那样，值类型是分配在栈上的，而引用类型是分配在GC堆上的。所以人们会问，你如何决定什么时候使用值类型，什么时候使用引用类型。在性能方面来说的话，答案通常是“看情况”。值类型不会触发GC但是如果你的值类型经常被包装（box）的话，包装操作比从头创建一个引用类型的实例要昂贵的多；另外当值类型被作为参数传递的时候，它们需要被复制。另一方面，如果你有一个类型成员不多，使它成为引用类型增加了一个指针大小的内存占用（加上引用类型本身多占的内存）。我们看到过很多内部代码，使用值类型来提高性能，同时减小工作集大小。所以这个决定依赖于你的类型的使用模式。</p> <h5>2) 引用丰富的对象（Reference rich objects）</h5> <p>如果一个对象引用了太多其他对象，它给分配和收集都增加了压力。每个内嵌的对象需要8个字节的额外空间。由于分配的代价和分配的大小成比例，分配的代价就变高了。在收集时，构建对象图时也会消耗更多的时间。</p> <h5>3) 可终结对象</h5> <p>我会单独用一节来谈论更多的细节，但是现在，我们需要知道的最重要的事情是当一个可终结对象被终结时，它所引用的所有对象都是存活的，这也增加了GC的开销。所以你需要把可终结对象和其他对象分得越开越好。</p> <h5>4) 对象位置</h5> <p>当你分配对象的子对象时，如果子对象的生存时间和父对象基本相同，他们应该被同时分配以使他们在GC堆中的位置也是相近的。</p> <h4><strong>大对象（Large Objects ）</strong></h4> <p>当你要去生成一个85000字节（85k）的对象时，它会被分配在LOH（Large Object Heap）上。LOH段永远不会被压缩-只会被清扫（使用空闲列表）。但是这是一个编程时不应该依赖的底层实现细节-如果你分配了一个你不希望被移动的大对象，你应该自己来钉住它（而不是依赖于GC的实现）。</p> <p>大对象只会在全面垃圾收集时被回收，所以回收它们是昂贵的。有时你会发现在一次全面收集之后Gen2的堆大小没有大的变化。那就意味着这次收集是由LOH触发的（你可以在性能监视器里面查看LOH的大小来判断是否如此）。</p> <p>使用大对象的一个好的方法是，分配一个对象，然后重用它，这样你就不会触发更多的全面垃圾收集。如果你希望一个大对象既能保存100k的数据，又能保存120k的数据，那就先分配120k的，然后重用它。分配大量的临时大对象是一个坏主意，因为你会在全面垃圾收集上花费大量的时间。</p> <p>第一部分就到此告一段落。在后面的文章里面我会介绍关于Pinning，终结（finalization），GCHandles，服务器类型的GC（Svr GC）和其他的内容。</p><img src="http://www.cnblogs.com/tmfc/aggbug/1216384.html?type=1" width="1" height="1" alt=""/><p>评论: 5　<a href="http://www.cnblogs.com/tmfc/archive/2008/07/29/1216384.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/tmfc/archive/2008/07/29/1216384.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56852/" target="_blank">淘宝网通过索引模式涉足网络文学</a><span style="color:gray">(2010-02-10 15:59)</span><br/>· <a href="http://news.cnblogs.com/n/56851/" target="_blank">苹果发布 iPhone/iPad SDK 3.2 beta2 开发包</a><span style="color:gray">(2010-02-10 15:37)</span><br/>· <a href="http://news.cnblogs.com/n/56850/" target="_blank">“谷姐”：披着“谷歌”羊皮的悲哀？</a><span style="color:gray">(2010-02-10 15:32)</span><br/>· <a href="http://news.cnblogs.com/n/56849/" target="_blank">2010，奇虎的本命年</a><span style="color:gray">(2010-02-10 15:26)</span><br/>· <a href="http://news.cnblogs.com/n/56847/" target="_blank">微软赢得Windows XP WGA诉讼</a><span style="color:gray">(2010-02-10 15:23)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/news/tag/Buzz/" target="_blank">Google Buzz相关新闻</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>企业架构应用模式读书笔记（四）</title><link>http://www.cnblogs.com/tmfc/archive/2006/12/25/603413.html</link><dc:creator>tmfc</dc:creator><author>tmfc</author><pubDate>Mon, 25 Dec 2006 12:55:00 GMT</pubDate><guid>http://www.cnblogs.com/tmfc/archive/2006/12/25/603413.html</guid><description><![CDATA[<p>阅读: 2147 评论: 3 作者: <a href="http://www.cnblogs.com/tmfc/" target="_blank">tmfc</a> 发表于 2006-12-25 20:55 <a href="http://www.cnblogs.com/tmfc/archive/2006/12/25/603413.html" target="_blank">原文链接</a></p><h3>Web展现</h3> <p>最近几年企业应用中最大的改变无疑是基于Web浏览器的用户界面的崛起。优势在于：不需要部署任何客户端软件，一致的UI使用方法，便利的全球访问。</p> <p>通常Web服务器上有着各种各样的配置文件来确定哪些URL该由那个程序处理，一个Web服务器可以支持多种程序。它的工作只是解释请求（request）的URL并把控制交给服务器端程序。</p> <p>服务器端程序基本上可以分为两种基本的类型：script和server page</p> <p>script形式是一个程序，通常拥有处理请求的方法。如CGI和Java servlet。它们能做任何一个程序可以做的事情，可以分解成子程序，可以创建并使用其他的服务（service）。它通过分析HTTP请求对象来获取网页上的数据。由于HTTP请求对象是一个字符串，所以在某些环境中，如Perl，使用正则表达式来分析它，这也使得Perl成为了流行的CGI编程语言。另一些环境，如Java servlet，环境本身为程序员做了这些事情。输出是另一个称为HTTP响应（response）的字符串，只需用语言支持的write stream操作来写出就可以了。</p> <p>通过流命令来输出HTML格式的响应是很不舒服的，对于非程序员来说更是不可能的，他们更乐意准备HTML页面。这导致了server page的诞生，用HTML格式来写输出页面，并在HTML中嵌入语言的小脚本，这些小脚本可以执行，并生成对应的HTML段落。包括PHP，ASP和JSP在内的技术都属于server page。</p> <p>&nbsp;server page方法在对响应只需要做一点点处理的时候工作的很好，但是更复杂的逻辑就会使它变得很复杂。</p> <p>因为script形式用来处理输入很好，server page处理输出是强项，很明显可以用script来解释输入并用server page来处理输出。这样分割来源于<em>Model View Controller</em>模式。</p> <p><em>Model View Controller</em>模式是一个被广泛参考的，但也是最常被误解的模式。造成混乱的主要原因是"Controller"这个词的使用。Controller在很多语境中被使用，而且通常和<em>Model View Controller</em>中的意义不同。所以作者使用术语<strong>input controller</strong>来表示<strong>Model View Controller</strong>中的Controller。</p> <p>input controller接收到一个请求，它从请求中取出信息，交给适当的领域类来处理。领域类从数据源中取出数据并处理请求中的信息，形成响应的数据。完成后将控制权交还给input controller，它检查结果并决定使用那个view来显式结果。然后它把控制权连同响应数据一起交给view。通常响应数据不是直接交给view的，而是放在类似HTTP session这种被input controller和view共享的地方。</p> <p>使用<em>Model View Controller</em>模式的最主要的原因是要确保展现被完全分割。这样做使得修改展现和以后添加展现更加容易。将处理过程放进单独的<em>Transaction Script</em>或者<em>Domain Model</em>对象可以使得测试也更加容易。这点在你使用server page作为view的时候特别的重要。</p> <p>第二种"controller":许多用户界面设计把展现对象和领域对象用一个中间层隔离开，这个中间层称为<em>Application Controller。Applicaton Controller</em>的主要功能是管理应用的流程。可以看作展现层的一部分，也可以看作是展现层和领域层的中间层。只有在你的系统有许多关于出现顺序和导航的逻辑的时候，才需要<em>Application Controller</em>。<em>Application Coltroller</em>在你的页面和领域中的动作映射关系比较复杂是也有用。一个好的测试你是否需要<em>Application Controller</em>的方法：如果是机器控制流程，你需要它；如果是用户控制流程，你不需要它。</p> <h4>View模式</h4> <p>在view这边有三种模式需要考虑：<em>Transform View</em>，<em>Template View</em>和<em>Two Step View</em>。你必须做两个选择，１：使用<em>Transform View</em>还是<em>Template View</em>。２：是否使用<em>Two Step View</em>。</p> <p><em>Template View</em>允许你拥页面的结构来写展现并且嵌入占位符来表示哪儿需要动态内容。许多平台基于这种模式，它们中的许多使用server page技术（ASP，JSP，PHP），允许你在页面中放入完整的编程语言。这提供了灵活性和强大性，但是会不可避免的产生难以维护的代码。为了将你的程序逻辑和页面分开，经常需要使用helper object。</p> <p><em>Transform View</em>使用转换的方法，最常见的就是XSLT。如果你的领域数据是XML格式的，它会非常有效，非常容易转换。input controller使用适合的XLST样式表并把它应用到从领域类中得到的数据上。</p> <p>如果你使用过程脚本作为你的view，你可以使用Transform View和Temlpate View中的任何一个，或者混合使用。</p> <p>单步的View通常对于每一个场景有一个对应的View。有相似逻辑的场景可能共享View。</p> <p>Two-stage view分为两步，第一步从领域数据中得到罗技场景，第二步把它渲染成HTML。对于每个场景有一个对于的first-stage view，但是总共只有一个second-stage view。优势在于它把决定使用什么HTML的工作放在单一的地方（second-stage）。这也如果需要修改HTML，只需修改一个地方就可以对所有的场景生效。</p> <p>对于不同的客户使用相同的服务（如不同的航空公司，页面除了logo等之外大体都是相同的），two-stage view能工作的很好。对于不同的设备（如普通的web浏览器和移动设备的浏览器）使用不同的second-stage view也是一种可能的应用。</p> <h4>Input Controller模式</h4> <p>对于input controller有两种模式，最常见的就是每个页面有一个input controller对象。最简单的情况下<em>Page Controller</em>对象可以作为server page，把view和input controller合二为一。在很多环境中可以很简单的把input controller分离到单独的对象中。<em>Page controller</em> 和view也不一定是一对一的关系，page controller更可能是和动作一一对应。</p> <p>Input controller有两种职责-接受HTTP请求并决定怎么处理它-分割它们是有意义的。一个server page可以接受请求，委托一个单独的助手对象来决定怎么处理它。<em>Front Controller</em>对象接受所有的请求，并创建对象来处理它。</p><img src="http://www.cnblogs.com/tmfc/aggbug/603413.html?type=1" width="1" height="1" alt=""/><p>评论: 3　<a href="http://www.cnblogs.com/tmfc/archive/2006/12/25/603413.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/tmfc/archive/2006/12/25/603413.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56852/" target="_blank">淘宝网通过索引模式涉足网络文学</a><span style="color:gray">(2010-02-10 15:59)</span><br/>· <a href="http://news.cnblogs.com/n/56851/" target="_blank">苹果发布 iPhone/iPad SDK 3.2 beta2 开发包</a><span style="color:gray">(2010-02-10 15:37)</span><br/>· <a href="http://news.cnblogs.com/n/56850/" target="_blank">“谷姐”：披着“谷歌”羊皮的悲哀？</a><span style="color:gray">(2010-02-10 15:32)</span><br/>· <a href="http://news.cnblogs.com/n/56849/" target="_blank">2010，奇虎的本命年</a><span style="color:gray">(2010-02-10 15:26)</span><br/>· <a href="http://news.cnblogs.com/n/56847/" target="_blank">微软赢得Windows XP WGA诉讼</a><span style="color:gray">(2010-02-10 15:23)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/news/tag/Buzz/" target="_blank">Google Buzz相关新闻</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>企业架构应用模式读书笔记（三）下</title><link>http://www.cnblogs.com/tmfc/archive/2006/12/19/597154.html</link><dc:creator>tmfc</dc:creator><author>tmfc</author><pubDate>Tue, 19 Dec 2006 11:54:00 GMT</pubDate><guid>http://www.cnblogs.com/tmfc/archive/2006/12/19/597154.html</guid><description><![CDATA[<p>阅读: 2001 评论: 4 作者: <a href="http://www.cnblogs.com/tmfc/" target="_blank">tmfc</a> 发表于 2006-12-19 19:54 <a href="http://www.cnblogs.com/tmfc/archive/2006/12/19/597154.html" target="_blank">原文链接</a></p><p></p> <h4>结构映射模式</h4> <p>当人们谈论对象-关系映射时，大部分的人都是在讨论结构映射模式，大部分模式都和<em>Table Data Gateway</em>无关,某些可以用在<em>Row Data Gateway</em>或<em>Active Record</em>上，大部分都需要用在<em>Data Mapper</em>上。</p> <h5>映射关系</h5> <p>关键点是联系对象和关系的不同的方法，这会引出两个问题。第一个问题在表现（representation）上，对象保持引用而关系数据库保持的是键的关联。第二个问题是，对象可以很容易的使用集合来保持多个与它有关的其他对象的引用，但是关系数据库却正好相反，相关对象会有一个到主对象的反向的引用。比如一个部门有多个员工，部门对象持有多个员工的引用，但是再关系数据库中，每个员工的数据行中会有一个到部门表的外键连接，而不是在部门表中引用多个员工（因为关系数据库不支持这样做）。</p> <p>解决表现问题的方法是在对象中保持一个<em>Identity Field</em>，使用它来作为关系数据库的键。当你访问数据库中的外键时，你使用的是<em>Foreign Key Mapping</em>来连接适当的对象间的连接。如果你没有在<em>Identity Map</em>中保存键，你需要回到数据库中去查找或者使用<em>Lazy Load</em>。每次保存对象的时候，你也要使用适当的键来保存它，对象间的连接也被目标对象的<em>Identity Field</em>替代。</p> <p>在这个基础上处理集合需要更加复杂的<em>Foreign Key Mapping</em>。如果一个对象有一个其他对象的集合，你需要额外的查询来找出所有相关的数据（你也可以使用<em>Lazy Load</em>来将这个过程放到以后来做），每个相关的数据都成为对象并被加到集合中。保存这个集合需要一个个的保持，并且确保它们的外键都正确的指向目标对象。这将会很混乱，特别是你将不得不检测被加入和移除出集合的对象。这个处理方法显得很啰嗦，这也是为什么许多形式的基于元数据的方法成为大型系统中一个显著的改进。如果集合对象只在拥有集合的对象中使用，可以用<em>Dependent Mapping</em>来简化映射。</p> <p>多对多的关系的情况与上面截然不同，关系数据库无法直接处理，所以你必须使用<em></em>来创建一个新的关联表。</p> <p>某些情况下关系的完整性使得更新变得更加复杂了。现代的系统允许你将关系完整性的检查推迟到事务的最后。另外数据库也会在每次写入的时候检查，这样你就需要特别注意更新顺序。一个可选的方法是硬编码更新表的顺序，这样也可以减少死锁的几率，避免事务频繁的回滚。</p> <p><em>Identity Field</em>通常用来讲内部对象引用转换成外键关联上，但是并不是所有的对象关系都必须以它来实现。小的<em>Value Objects</em>，如时间范围和金钱对象很明显不应该作为一个单独的表来存放。可以将所有的的子段取出并它们做为<em>Embedded Value</em>嵌入到链接对象中，读取和保存都将非常方便。</p> <p>你也可以在一个大的范围中使用它，将对象序列化并当成<em>Serialized LOB</em>保存到表的一个列中。将一组对象序列化成XML文档时获得对象层次结构的一个好办法，这样你可以在一次查询中获取所有互相关联的小对象。通查数据库在查询小的互相有着高度关联的对象方面表现非常差--因为在这里你做了小而多的数据库查询。缺点是数据库不知道发生了什么，所以你不能在这个结构上做查询。又一次，XML发挥了作用，允许你在SQL查询中嵌入XPath查询表达式（虽然现在还没有标准）。通常Serialized LOB是最好的保存孤立对象在一起的方法。但是如果你过度的使用他，你的数据库就只比一个事务文件系统强那么一点点了。</p> <h5>继承</h5> <p>&nbsp;除了上面提到的结构化对象，如树状机构，这种关系数据库比较处理的东西之外，还有一个OO中非常常见，但是关系数据库并不擅长处理的东西--继承。和上面一样，我们又要进行映射了，通常有三种映射方式：<em>Single Table Inheritance</em>，使用一张表来保存继承体系中所有的类；<em>Concrete Table Inheritance</em>，每个具体类使用一张表；<em>Class Table Inheritance</em>，每个类一张表。</p> <p>选择那种方式通常需要在重复数据的数量和访问速度之间做平衡，<em>Class Table Inheritance</em>在类和表的关系上是最简单的，但是在读取数据的时候需要很多Join字句，这降低了效率。<em>Concrete Table Inheritance</em>避免了Join，可以从一张表中找出你要的对象，但是它对更改来说比较脆弱，对父类进行的修改必须反应到所有的子类中（当然映射代码也需要修改），修改继承结构本身更是会带来巨大的修改，而且，由于缺少抽象类，对于主键的管理会变得很奇怪并且没有数据库检查的保证（但是也有好处，减少了在抽象表中主键的锁冲突）。在许多数据库中，<em>Single Table Inheritance</em>最大的缺点是浪费了大量的空间，因为每一行都能容纳所有可能的子类，这样会有很多空闲的列，但是数据库在压缩空间方面做的很不错。另一个问题是他的大小，成为了访问的瓶颈，优点是把所有东西放在一起使得更新操作很方便。</p> <p>这三种模式也并不是排外的，完全可以混合使用。如，常用的类可以用<em>Single Table Inheritance</em>，不常用的可以用<em>Class Table Inheritance</em>。当然，混合使用增加了复杂性。</p> <p>这三者并不存在孰优孰劣的问题，根据你项目的需求来选择。作者的第一选择可能会是<em>Single Table Inheritance</em>，因为它比较简单而且更容易重构。更好的方法是讨教你的DBA，他们对于如何在数据库中存放数据更有发言权。</p> <h4>建立映射</h4> <p>映射到数据库时通常存在以下几种情况：</p> <ul> <li>你自己决定结构  <li>你必须映射到一个已存在的结构，并且不能修改  <li>你必须映射到一个已存在的结构，但是修改是可以商量的</li></ul> <p>最简单的情况是自己决定映射并且领域逻辑不是非常复杂，可能会是<em>Transaction Script</em>或者<em>Table Module</em>的设计。在这种情况下可以使用经典的数据库设计技术围绕数据来设计表，并使用<em>Row Data Gateway</em>或者<em>Table Data Gateway</em>来从领域逻辑中分隔SQL。</p> <p>如果使用<em>Domain Model</em>，小心那些看上去像数据库设计的那些设计。因为如果你建立<em>Domain Model</em>时不考虑数据库的话，你可以最大程度上简化领域逻辑。把数据库设计当成持久化对象数据的方法。<em>Data Mapper</em>给予你最大的灵活性，但是也更复杂。如果数据库设计和<em>Domain Model</em>的设计是同构的，可以考虑使用<em>Active Record</em>来替代。</p> <p>花六个月的时间建立一个独立于数据库的<em>Domain Model</em>，再持久化它是一个高风险的行为。危害在于设计可能会导致性能原因，修正它会花费相当长的时间。以更短的周期来建立数据库，这样你会得到更频繁且持续的反馈。</p> <p>如果结构已经存在，你的选择就更少了，但是过程是多样的。对于简单的领域逻辑，你可以使用<em>Row Data Gateway</em> 或者<em>Table Data Gateway</em>类来模仿数据库，并在其上建立领域逻辑。如果领域逻辑更复杂一点，你需要<em>Domain Model</em>，它并不需要迎合数据库设计。只需逐步的建立<em>Domain Model</em>并用<em>Data Mapper</em>来把数据存储到已经存在的数据库中。</p> <h5>双重映射</h5> <p>有时我们会遇到需要从不同的数据源中获取数据的情况。可能是多个数据库，有着相同的数据，但是在结构上稍不同。另一种可能性是使用了不同的存储机制，如你可能需要从XML消息，CICS事务和关系表中读取数据。</p> <p>最简单的方法是为不同的数据源使用多个映射层，然而，如果数据很相似的话会有很大的重复。这是你可能要考虑一种两步的映射结构。第一步将内存中的结构映射到一个逻辑的数据存储结构，第二步将逻辑的数据结构映射到真实的物理结构，第二步是根据不同的数据源而不同的。</p> <p>&nbsp;</p> <h4>使用元数据</h4> <p>简单而重复的映射会导致简单而重复的代码--闻到味道了，不是吗？用继承和委托把相同的行为提取出去才是好的OO实践，但是更好的方法是使用元数据映射--<em>Metadata Mapping</em>。</p> <p><em>Metadata Mapping</em>将映射的细节放在了元数据文件中，如那个列对应那个对象的那个字段。这样就可以使用代码生成或者反射编程来避免了重复的编码。</p> <p>当你使用<em>Metadata Mapping</em>，你需要有必要的基础设施，以便在内存中建立查询<em>。Query Object</em>允许你这样做而开发人员不需要知道SQL和关系数据库结构的细节。<em>Query Object</em>使用<em>Metadata Mapping</em>来转换相应的查询语句。</p> <p>在这之后,你可以组成一个仓库(<em>Repository</em>),它把数据库很好的隐藏了起来.开发人员甚至不知道这个对象是不是从数据库中查询得到的。<em>Repository</em>和复杂的<em>Domain Model</em>系统一起工作的很好。</p> <p>&nbsp;</p> <h4>数据库连接</h4> <p>许多数据库接口依赖于某种形式的数据库连接对象来作为程序和数据库直接的连接。一个连接通常必须在你在数据库上执行命令之前被打开。事实上，你通常需要一个显式的连接来创建和执行命令，你执行命令的时候这个连接也是打开着的。查询返回一个<em>Record Set</em>，有些接口提供了断开连接的<em>Record Sets</em>，在连接被关闭之后仍然有效。另外一些接口只提供了连接着的<em>Record Sets</em>，就是说操作<em>Record Sets</em>时连接也必须被打开着。如果你在一个事务中运行，事务通常也是和特定的连接绑定的，当事务发生的时候连接叶必须被打开。</p> <p>在许多环境中创建一个连接是昂贵的，所以建立一个连接池是有必要的。这时开发人员从连接池中请求一个连接并在用完之后释放回去，代替了打开和关闭连接的操作。当前的许多平台都提供了连接池，所以如果你真的必须自己创建一个，考虑一下是不是真的对性能有提高，在当前环境下，创建新连接变得越来越快，导致可能并不需要池了。</p> <p>提供连接池的环境通常把它放在一个接口后面，看上去就像是创建一个新连接一样。这样你并不知道是得到了一个新创建的连接还是从池中得到的，这样做很好，是否使用池都被很好的封装了起来。接近的，关闭连接是真的关闭还是返回池中也被这样封装起来了。</p> <p>不论创建连接是否昂贵，连接都必须被很好的管理起来。因为它们是昂贵的资源，必须在使用完之后尽快的被关闭。当使用事务的时候，确保所有的命令都是在同一个连接上执行的。</p> <p>最常见的建议是显式的得到一个连接（通过池或者连接管理器），并用它来执行你想要执行的所有数据库命令，一旦用完，久关闭它。这个建议带来很多问题：所有需要连接的地方，确保你拥有它，并且确保你每次用完都要关闭它。</p> <p>确保你在需要连接的地方都能得到它的方法有两种。一种是把连接作为显式的参数到处传递。令一种方法是在<em>Registry</em>中取出连接，既然你不想在多个线程中使用同一个连接，你可能会使用线程范围的<em>Registry</em>。</p> <p>如果你有我一半的健忘，显式关闭连接不是一个好办法。像连接一样，内存也是当用完之后需要关闭的资源，现代环境提供了自动内存管理和垃圾收集，所以确保连接被关闭的一个方法是使用垃圾收集器。这样的话连接本身以及引用它的其他对象都会在垃圾收集过程中关闭连接。坏处是连接只有在垃圾收集器启动的时候才会被关闭，也就是说没有被引用的连接在关闭之前会闲置一段时间。</p> <p>我不喜欢依靠垃圾收集，其他的方案--甚至是显式关闭--都要更好。然而，在常规方案失效时，垃圾收集提供了一个很好的后备方案。不管怎么说，在挂起一段时间之后被关闭总比永远挂起要好。</p> <p>既然连接和事务是如此紧密的联系在一起的，管理他们的好办法是开始事务的时候打开连接，结束事务的时候关闭连接。让事务知道它该使用哪个连接，这样你就可以完全忽略连接了。<em>Unit of Work</em>很适合用来管理事务和连接。</p> <p>如果你在事务外做一些事情，比如读取不变的数据，使用一个新的连接，连接池可以很好的处理创建短生命周期的连接带来的问题。</p><img src="http://www.cnblogs.com/tmfc/aggbug/597154.html?type=1" width="1" height="1" alt=""/><p>评论: 4　<a href="http://www.cnblogs.com/tmfc/archive/2006/12/19/597154.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/tmfc/archive/2006/12/19/597154.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56852/" target="_blank">淘宝网通过索引模式涉足网络文学</a><span style="color:gray">(2010-02-10 15:59)</span><br/>· <a href="http://news.cnblogs.com/n/56851/" target="_blank">苹果发布 iPhone/iPad SDK 3.2 beta2 开发包</a><span style="color:gray">(2010-02-10 15:37)</span><br/>· <a href="http://news.cnblogs.com/n/56850/" target="_blank">“谷姐”：披着“谷歌”羊皮的悲哀？</a><span style="color:gray">(2010-02-10 15:32)</span><br/>· <a href="http://news.cnblogs.com/n/56849/" target="_blank">2010，奇虎的本命年</a><span style="color:gray">(2010-02-10 15:26)</span><br/>· <a href="http://news.cnblogs.com/n/56847/" target="_blank">微软赢得Windows XP WGA诉讼</a><span style="color:gray">(2010-02-10 15:23)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/news/tag/Buzz/" target="_blank">Google Buzz相关新闻</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>企业架构应用模式读书笔记（三）上</title><link>http://www.cnblogs.com/tmfc/archive/2006/12/18/596130.html</link><dc:creator>tmfc</dc:creator><author>tmfc</author><pubDate>Mon, 18 Dec 2006 12:29:00 GMT</pubDate><guid>http://www.cnblogs.com/tmfc/archive/2006/12/18/596130.html</guid><description><![CDATA[<p>阅读: 2765 评论: 7 作者: <a href="http://www.cnblogs.com/tmfc/" target="_blank">tmfc</a> 发表于 2006-12-18 20:29 <a href="http://www.cnblogs.com/tmfc/archive/2006/12/18/596130.html" target="_blank">原文链接</a></p><p></p> <h3>第三章：映射到关系数据库</h3> <h4>架构模式</h4> <p>架构模式的选择对后续的程序开发有着深远的影响并且难以切换（难以从一种模式重构到另一种），所以必须仔细的选择架构模式。</p> <p>将SQL语句嵌在逻辑代码中会显得非常的丑陋，DBA也希望能够通过了解SQL语句来决定怎样对数据库进行索引，所有这一切的原因让我们倾向于将访问数据库的SQL语句从领域逻辑中分离出来。</p> <p>以数据表结构来组织类的结构是一个好主意，这样类和数据表可以一一对应。这些类组成了一个数据表的<em>Gateway</em>，<em>Gateway</em>主要分为两种，<em>Row Data Gateway</em>和<em>Table Data Gateway</em>。</p> <p><em>Row Data Gateway</em>中，数据表中的每一行对应于一个对象实例，比较自然的符合了面向对象的思想。</p> <p><em>Table Data Gateway</em>中，整个数据表只需要一个对应的对象实例。而用来储存数据的则是<em>Record Set</em>，一个通用的数据结构，适合于任何一张表。</p> <p>即使是非常简单的应用，作者也倾向于使用这两种<em>Gateway</em>中的一种。</p> <p><em>Table Data Gateway</em>也适合用来包装存储过程。</p> <p>如果你使用了<em>Domain Model</em>，当然也可以使用<em>Row Data Gateway</em>和<em>Table Data Gateway</em>，但是对作者而言，这两者显然不够用了。在简单的应用中，<em>Domain Model</em>的复杂度非常有限，它们的逻辑和数据库非常接近，通常只是一些增删改查的操作，这时，可以将数据库的操作放入，形成<em>Active Record</em>模式。你也可以这样来理解<em>Active Record</em>模式，从使用<em>Row Data Gateway</em>开始，一旦在<em>Transaction Script</em>中看到重复的代码，将这些逻辑加进来。</p> <p>但是当领域逻辑变得越来越复杂的时候，<em>Active Record</em>开始变得不适合了。当你吧领域类分割成更小的部分，领域类和表的一对一关系变得失败。因为关系数据库不支持继承，所以使用策略和其他一些OO的模式非常的困难。并且对测试的支持也不是很好。更好的分隔领域逻辑和数据库表的方法是将它们完全的分开。<em>Data Mapper</em>模式负责所有的数据库操作，这样就让领域层和数据库完全的分开了，这也让它成为了最复杂的数据库映射架构。</p> <p>作者建议使用<em>Gateway</em>模式来作为<em>Domain Model</em>的主要的持久化模式，如果领域逻辑很简单，可以使用<em>Active Record</em>，如果很复杂，则可以使用<em>Data Mapper</em>。</p> <p>这些模式并非必须完全孤立的使用，很多时候是以一种为主要的持久化模式。但是人们通常不愿意同时使用几种，因为这样会搞混。</p> <p>处理视图时，查询会很容易，但是更新的时候就会有麻烦，可能会导致数据不一致。</p> <p>虽然本书讲述的模式足够告诉你怎样搭建一个<em>Data Mapper</em>，但是这项工作还是很昂贵的，所以，如果可能的话，买一个O/R mapping工具。这些工具都会提供很多选项，要想知道该怎么配置它们吗，你还是需要了解相关的模式。</p> <h4>行为问题</h4> <p>当人们谈起O/R mapping的时候，通常都会关注结构方面（如何关联表和对象）。然后，作者更关注架构和行为方面。</p> <p>行为问题是：怎么把不同的对象从数据库中取出和放回。初看好像并没有什么问题，使用<em>Active Record</em>时这是很明显的。但是如果你将一系列的对象载入到内存中并修改了它们，你必须跟踪并记录哪些是你改过的，并确保把它们更新到数据库中。而且当你新建了一些行还修改了另外一些，你需要有相应的关键字段（keys）来修改那些引用它们的行。当你读取了一些对象，并开始修改它们时，你必须保证数据库里的这些数据不被修改，不然就会产生不一致的问题。这个问题将放在第五章中详细的来讲。</p> <p>主要用来解决上面两个问题的模式是<em>Unit of Work</em>。它跟踪所有从数据库中读出的对象和所有修改过的对象。它还负责更新数据库，这样程序员就不用显示的调用保存方法，只需要提交（Commit）这个unit of work就可以了。<em>Unit of Work</em>可以看成一个和数据库映射层打交道的控制器对象（object&nbsp;that acts as the controller of the database mapping），没有<em>Unit of Work</em>，领域层担当了控制器的角色，决定什么时候读写数据库。使用了<em>Unit of Work</em>将控制器从领域逻辑中抽了出来。</p> <p>当载入对象时，小心应付一个对象被载入两次的情况。如果你这样做，你会有两个对应于同一个数据库行的对象。这样的话你就要保持它们的同步，这将会很混乱。为了处理这种情况，你必须在<em>Identity Map</em>中保持每个读进内存对象的记录，每次读取数据时，先检查<em>Identity Map</em>。<em>Identity Map</em>也起了数据库缓存的作用，但是记住，<em>Identity Map</em>并不是用来改善性能的。</p> <p>当你使用<em>Domain Model</em>时，你可能会想一次读入多个相关对象，如，读入一个订单对象时将用户对象也一并读进来。然而</p> <p>对象的关系是如此之多，以至于读入一个对象会牵涉到很多相关的对象。为了避免这点，可以使用<em>Lazy Load</em>,它为关联对象使用一个占位符。这个主题有很多的变体，但是都是使用占位符的方法来实现的。只有当你想要使用这个对象时，才会从数据库中读取这个对象。</p> <h4>读取数据</h4> <p>作者倾向于使用<strong>finder方法</strong>来读取数据，如find(id),findForCustomer(customer)，这些方法包装了一个Sql查询语句。</p> <p>这些finder方法放在哪里是由模式来决定的，如果你使用的是基于表的模式--对于每个表都有一个对象的实例与它对应--你可以把这些方法和插入/更新方法放在一起；如果你使用的时基于行的模式，你可以将finder函数作为静态函数，但是这样你就无法替换它们了，这也就意味着你无法用存根类（<em>Service Stub</em>）替换它们来进行测试了。为了解决这个问题，你可以使用一个独立的finder对象，查询时返回一个对象的列表。</p> <p>finder方法一个值得注意的地方是它们以数据库状态为准，而不是对象状态，这就是说你查询出来的结果不会包含你已经在内存中加入，但是还没有保存到数据库中的对象。</p> <p>读取数据时，性能都是一个会显现的话题。这儿有一些简单的规则。</p> <p>一次查询多条，而不是分多次查询，多查通查比少查好（当然还得看实际情况）。</p> <p>使用join，可以一次查询更多的记录，这样做的时候你通常需要一个<em>Gateway</em>或者<em>Data Mapper</em>。使用join的时候，记住数据库是为三或四个join做优化的，更多的join只能降低性能。当然使用视图来代替常用的join是很好的办法。</p> <p>对数据库来说，可做的优化很多，如将相关的数据组织在一起，小心的使用索引，使用好数据库的缓存功能，更多的方法，可以询问DBA。</p> <p>优化时一定要以你的数据库和数据为基准进行测试，上面这些只是一些通常是有效的指导规则，引导你思考而已。</p><img src="http://www.cnblogs.com/tmfc/aggbug/596130.html?type=1" width="1" height="1" alt=""/><p>评论: 7　<a href="http://www.cnblogs.com/tmfc/archive/2006/12/18/596130.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/tmfc/archive/2006/12/18/596130.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56852/" target="_blank">淘宝网通过索引模式涉足网络文学</a><span style="color:gray">(2010-02-10 15:59)</span><br/>· <a href="http://news.cnblogs.com/n/56851/" target="_blank">苹果发布 iPhone/iPad SDK 3.2 beta2 开发包</a><span style="color:gray">(2010-02-10 15:37)</span><br/>· <a href="http://news.cnblogs.com/n/56850/" target="_blank">“谷姐”：披着“谷歌”羊皮的悲哀？</a><span style="color:gray">(2010-02-10 15:32)</span><br/>· <a href="http://news.cnblogs.com/n/56849/" target="_blank">2010，奇虎的本命年</a><span style="color:gray">(2010-02-10 15:26)</span><br/>· <a href="http://news.cnblogs.com/n/56847/" target="_blank">微软赢得Windows XP WGA诉讼</a><span style="color:gray">(2010-02-10 15:23)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/news/tag/Buzz/" target="_blank">Google Buzz相关新闻</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>企业应用架构模式读书笔记（二）</title><link>http://www.cnblogs.com/tmfc/archive/2006/10/10/525391.html</link><dc:creator>tmfc</dc:creator><author>tmfc</author><pubDate>Tue, 10 Oct 2006 09:09:00 GMT</pubDate><guid>http://www.cnblogs.com/tmfc/archive/2006/10/10/525391.html</guid><description><![CDATA[<p>阅读: 2575 评论: 1 作者: <a href="http://www.cnblogs.com/tmfc/" target="_blank">tmfc</a> 发表于 2006-10-10 17:09 <a href="http://www.cnblogs.com/tmfc/archive/2006/10/10/525391.html" target="_blank">原文链接</a></p><h3>第二章：管理领域逻辑</h3> <p>三个主要的模式：<em>Transaction Script，Domain Model，Table Model</em></p> <p>最简单的方法是使用<em>Transaction Script,Transaction Script</em>本质上就是从表现层接受输入，进行验证和计算，保存进数据库，调用其他外部操作并且返回更多的信息，帮助计算并组织数据给表现层的过程。基本上就是将用户可能做的事情组织成一个个的函数，所以可以将其想象成动作的脚本，或者一个个事务。</p> <p><em>Transaction Script</em>的优势：</p> <ul> <li>是几乎每个开发者都了解的简单的过程模式  <li>配合使用简单的数据库层模式，如<em>Row Data Gateway，Table Data Gateway</em>时工作的很好  <li>非常明显的边界:以打开事务开始，关闭事务结束。</li></ul> <p>但是，在领域逻辑变得越来越复杂时，<em>Transaction Script</em>也会有很多劣势，会出现很多难以消除的重复代码，子方法越来越多后，缺乏清晰的结构。</p> <p>这个时候，就该以面向对象方式处理逻辑的<em>Domain Model</em>模式登场了。我们主要围绕着领域中的<strong>名词</strong>来建立<em>Domain Model</em>模式，验证和计算的逻辑会放在<em>Domain Model</em>中。与<em>Transaction Script</em>将所有逻辑放在一个函数里不同，在<em>Domain Model</em>中，每个对象只负责自己相关的那一部分逻辑。<em>Domain Model</em>的价值是一旦你掌握了它，它提供了很多种管理不断增长的复杂逻辑的方法，如增加不同的策略对象。<em>Domain Model</em>的复杂性来源于使用上的复杂（新手需要学习的时间，思维的转换）以及数据源层的复杂（领域逻辑越复杂，数据库映射也越复杂）。</p> <p>第三种选择是使用<em>Table Model</em>模式。<em>Table Model</em>模式适合与<em>Record Set</em>一起使用。<em>Table Model</em>看起来像是上面两者的一个折中，围绕着数据表来组织领域逻辑比起<em>Transaction Script</em>来说更为结构化，也更容易找出并排除重复代码，并且可以使用Domain Model中用来得到更好的结构的方法，如继承，策略等OO的模式。最大的好处就是它可以和系统的其他部分很好的进行配合，很多GUI的环境都建立在SQL查询的结果之上，这些结果通常用<em>Record Set</em>保存（如.NET中的数据绑定），而<em>Table Model</em>也是在<em>Record Set</em>上工作的。</p> <h4>做出抉择</h4> <p>对于简单的领域逻辑，<em>Domain Model</em>没什么吸引力，因为理解它的成本和数据源层点的成本显得太高了，然而，随着领域逻辑的复杂性的增加，其他的几个模式的成本程指数上升，而<em>Domain Model</em>是线性上升的。</p> <p>对<em>Domain Model</em>熟悉的开发团队可以降低初始的成本，但不会降到和其他两个一样低，因为它的数据源层比较复杂。</p> <p><em>Table Model</em>吸引力的强弱很大程度上取决于你使用的开发环境对<em>Record Set</em>基本架构的支持程度，如.NET就支持非常好。</p> <p>这三种模式并不是排他的，事实上，混合使用的情况是很常见的。</p> <h4>服务层（Service Layer）</h4> <p>常见的管理领域逻辑的方法是将它分成两层。服务层建立在<em>Domain Model</em>或<em>Table Model</em>之上，<em>Transaction Script</em>因为太简单了而不需要服务层。表现层完全通过服务层与领域层交互，这使它显得像是一组API。</p> <p>服务层也是放置事务管理，安全管理的好地方。通常使用文件来配置这些信息，但是在.NET中使用自定义熟悉也是一个非常好的方法。</p> <p>当你想到服务层的时候，一个关键的问题是在里面放多少的逻辑。最少的情况下，服务层就是一个<em>facade</em>模式的体现，提供了一组易于使用的API，并可以提供了事务管理和安全管理。另一个极端的情况下，大部分的逻辑都放置在服务层中，下次的领域对象非常的简单，如果下层是<em>Domain Model</em>，你将可以使用一个简单的数据源层，如<em>Active Record</em>。两者的折中，<strong>controller-entity</strong>，这里的关键点是将特定的事务或者用例放到<em>Transaction Script</em>中（通常将其称为controller，注意controller有很多种，如后面会说到的<em>Model View Controller</em>和<em>Application Controller</em>），这里作者将其称为<strong>user-case controller</strong>，相对于那些用于多个用例的方法，它们在领域对象中，称为entities。</p> <p>作者建议，如果需要的话，就使用一个最“瘦”的服务层。</p><img src="http://www.cnblogs.com/tmfc/aggbug/525391.html?type=1" width="1" height="1" alt=""/><p>评论: 1　<a href="http://www.cnblogs.com/tmfc/archive/2006/10/10/525391.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/tmfc/archive/2006/10/10/525391.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56852/" target="_blank">淘宝网通过索引模式涉足网络文学</a><span style="color:gray">(2010-02-10 15:59)</span><br/>· <a href="http://news.cnblogs.com/n/56851/" target="_blank">苹果发布 iPhone/iPad SDK 3.2 beta2 开发包</a><span style="color:gray">(2010-02-10 15:37)</span><br/>· <a href="http://news.cnblogs.com/n/56850/" target="_blank">“谷姐”：披着“谷歌”羊皮的悲哀？</a><span style="color:gray">(2010-02-10 15:32)</span><br/>· <a href="http://news.cnblogs.com/n/56849/" target="_blank">2010，奇虎的本命年</a><span style="color:gray">(2010-02-10 15:26)</span><br/>· <a href="http://news.cnblogs.com/n/56847/" target="_blank">微软赢得Windows XP WGA诉讼</a><span style="color:gray">(2010-02-10 15:23)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/news/tag/Buzz/" target="_blank">Google Buzz相关新闻</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>企业应用架构模式读书笔记（一）</title><link>http://www.cnblogs.com/tmfc/archive/2006/09/26/515587.html</link><dc:creator>tmfc</dc:creator><author>tmfc</author><pubDate>Tue, 26 Sep 2006 13:33:00 GMT</pubDate><guid>http://www.cnblogs.com/tmfc/archive/2006/09/26/515587.html</guid><description><![CDATA[<p>阅读: 4039 评论: 6 作者: <a href="http://www.cnblogs.com/tmfc/" target="_blank">tmfc</a> 发表于 2006-09-26 21:33 <a href="http://www.cnblogs.com/tmfc/archive/2006/09/26/515587.html" target="_blank">原文链接</a></p><h3>第一章：分层</h3> <p>分层是用来分割复杂软件系统的最常用手段之一。如：操作系统建立在设备驱动和CPU指令上；FTP建立在TCP层之上，TCP建立在IP层上，IP建立在以太网上。</p> <p>把分层结构想像成蛋糕，每一层都建立在它下一层上。意味着上层使用下层的服务，但是对更底层的服务一无所知。如，第四层使用第三层定义的服务，第三层使用第二层的服务，但是第四层并不了解第二层的服务。</p> <p>分层的优势：</p> <ul> <li>可以单独了解一层的东西，而不用管其他层</li> <li>可以替换某一层的实现</li> <li>最小化层之间的依赖</li> <li>为建立标准做好准备</li> <li>一个低层可以被很多高层使用（提高复用率）</li></ul> <p>分层的劣势：</p> <ul> <li>分层对部分东西，而不是全部东西，有一个良好的封装。有时会引起连锁的更改，如，为了在用户界面上多显示一个属性，必须更改从数据库到UI之间的所有层。</li> <li>额外的层会降低性能</li></ul> <h4>企业应用中层次的进化</h4> <p>很久以前是没有分层的概念的，在90年代，随着C/S架构系统的兴起，层的概念变得明显起来。客户端通常包括UI和其他程序，服务器端通常是关系数据库。如果应用程序只是简单的显示数据和简单的更新数据，前面的结构可以很好的应付，但是随着领域逻辑（业务逻辑，验证，计算以及其他）的越来越复杂，把领域逻辑直接放在UI层中的做法使得程序非常复杂并且难以开发和维护，并且导致代码重复。另一种做法是把领域逻辑放在数据库的存储过程中，但是，存储过程提供的结构化机制有限，导致了一些非常古怪的代码。</p> <p>在C/S结构变普及的同时，面对对象的世界也开始茁壮成长了。面对对象社区对这个问题有一个答案：转移到三层结构。一个展示层为UI服务，领域层为领域逻辑服务，和一个数据源层。但是面对对象的浪潮并没有很好的推进三层架构的应用，因为很多系统非常简单，不原意使用复杂的三层结构。</p> <p>真正的冲击来自于Web领域。似乎是非常突然的，大家都原意用浏览器来取代C/S的应用。三层结构正好可以适应Web应用中只有一个瘦客户端的现实。另外，Java在其中也起了很大的作用。</p> <p>layer和tier，作者把物理上应该分开的称为tier，把物理上可以不分开的称为layer。</p> <h4>三个主要的层</h4> <p><strong>展示层</strong>：展示层的逻辑都是关于如何和用户交互的。主要职责是向用户显示信息，获取用户命令并提交到领域层和数据源层。</p> <p><strong>领域逻辑层</strong>：也被称为业务逻辑层。需要负责这个程序需要处理的领域中真正的工作。如基于输入进行计算并保存数据，验证数据的正确性等等。</p> <p><strong>数据源层</strong>：主要的逻辑是和其他系统交互，如数据库，消息系统，事物管理系统，等等。</p> <p>分层并不是完全的，有时展示层也会直接访问数据源层，虽然看上去好像破坏了分层，但是实际中确工作的更好。</p> <p>一个应用中相同职责的层可能有好几个，如多个展示层，多个数据源层。</p> <p>对称VS非对称：Hexagonal Architecture认为外部的任何东西都是一个接口，作者认为接口分为两种，对外提供服务的，一种是向外获取服务的。</p> <p>如何分层：一个简单的程序，可以在函数级别上分层；再复杂一点，可以在类级别上分层；足够复杂后可以在包，项目级别上分层。</p> <p>不管如何分层的，都必须单向的依赖，不能出现依赖环。</p> <p>有时很难分清什么是领域逻辑，什么不是。作者的做法是想像加入一个不同的层，如在一个web程序中加入一个命令行的展示层，如果加入这个层时需要复制什么代码，这就意味着领域逻辑被混入了展示层。相同的，可以用一个XML文件来替换关系数据库来从数据源层中取出领域逻辑。</p> <h4>层都在哪里运行</h4> <p>最简单的是都在服务器运行，如Web应用。</p> <p>如果需要Web界面很难展示，操作的UI，就需要把展示层放在客户端运行。</p> <p>领域逻辑层可以完全放在客户端，也可以完全放在服务器端，也可以分开放置。</p> <p>数据源层最好放在服务器端。</p><img src="http://www.cnblogs.com/tmfc/aggbug/515587.html?type=1" width="1" height="1" alt=""/><p>评论: 6　<a href="http://www.cnblogs.com/tmfc/archive/2006/09/26/515587.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/tmfc/archive/2006/09/26/515587.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56852/" target="_blank">淘宝网通过索引模式涉足网络文学</a><span style="color:gray">(2010-02-10 15:59)</span><br/>· <a href="http://news.cnblogs.com/n/56851/" target="_blank">苹果发布 iPhone/iPad SDK 3.2 beta2 开发包</a><span style="color:gray">(2010-02-10 15:37)</span><br/>· <a href="http://news.cnblogs.com/n/56850/" target="_blank">“谷姐”：披着“谷歌”羊皮的悲哀？</a><span style="color:gray">(2010-02-10 15:32)</span><br/>· <a href="http://news.cnblogs.com/n/56849/" target="_blank">2010，奇虎的本命年</a><span style="color:gray">(2010-02-10 15:26)</span><br/>· <a href="http://news.cnblogs.com/n/56847/" target="_blank">微软赢得Windows XP WGA诉讼</a><span style="color:gray">(2010-02-10 15:23)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/news/tag/Buzz/" target="_blank">Google Buzz相关新闻</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>对[解耦的故事]的一些补充</title><link>http://www.cnblogs.com/tmfc/archive/2006/09/18/507264.html</link><dc:creator>tmfc</dc:creator><author>tmfc</author><pubDate>Mon, 18 Sep 2006 03:45:00 GMT</pubDate><guid>http://www.cnblogs.com/tmfc/archive/2006/09/18/507264.html</guid><description><![CDATA[<p>阅读: 679 评论: 0 作者: <a href="http://www.cnblogs.com/tmfc/" target="_blank">tmfc</a> 发表于 2006-09-18 11:45 <a href="http://www.cnblogs.com/tmfc/archive/2006/09/18/507264.html" target="_blank">原文链接</a></p><p>&nbsp;&nbsp;&nbsp; 我的前两篇blog原意是想通过一个故事说明委托的来龙去脉，但是后来的主题却变成了解耦的一些方法介绍，对于委托本身的关注反而少了，加上编故事的水平不高，有点虎头蛇尾的感觉，大家见谅，以后有机会再来好好整理以下。</p> <p>在网上找几篇好文来补充一下委托的内容：</p> <p>台湾msdn的大内高手专栏，蔡学镛先生的好文（繁体+台湾术语，希望大家看得懂）：</p> <p><a href="http://www.microsoft.com/taiwan/msdn/columns/DoNet/FunctionPointer_1.htm">函数指针进化论（上）</a></p> <p><a href="http://www.microsoft.com/taiwan/msdn/columns/DoNet/FunctionPointer_2.htm">函数指针进化论（下）</a></p><img src="http://www.cnblogs.com/tmfc/aggbug/507264.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/tmfc/archive/2006/09/18/507264.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/tmfc/archive/2006/09/18/507264.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56852/" target="_blank">淘宝网通过索引模式涉足网络文学</a><span style="color:gray">(2010-02-10 15:59)</span><br/>· <a href="http://news.cnblogs.com/n/56851/" target="_blank">苹果发布 iPhone/iPad SDK 3.2 beta2 开发包</a><span style="color:gray">(2010-02-10 15:37)</span><br/>· <a href="http://news.cnblogs.com/n/56850/" target="_blank">“谷姐”：披着“谷歌”羊皮的悲哀？</a><span style="color:gray">(2010-02-10 15:32)</span><br/>· <a href="http://news.cnblogs.com/n/56849/" target="_blank">2010，奇虎的本命年</a><span style="color:gray">(2010-02-10 15:26)</span><br/>· <a href="http://news.cnblogs.com/n/56847/" target="_blank">微软赢得Windows XP WGA诉讼</a><span style="color:gray">(2010-02-10 15:23)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/news/tag/Buzz/" target="_blank">Google Buzz相关新闻</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item></channel></rss>