<?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>Bookcold&#039;s Blog</title>
	<atom:link href="http://bookcold.com/feed" rel="self" type="application/rss+xml" />
	<link>http://bookcold.com</link>
	<description>Just for pleasure</description>
	<lastBuildDate>Fri, 30 Jul 2010 08:50:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=6496</generator>
		<item>
		<title>Entity Framework查询表达式参考工具</title>
		<link>http://bookcold.com/2010/07/574</link>
		<comments>http://bookcold.com/2010/07/574#comments</comments>
		<pubDate>Fri, 30 Jul 2010 08:50:41 +0000</pubDate>
		<dc:creator>bookcold</dc:creator>
				<category><![CDATA[程序设计]]></category>
		<category><![CDATA[EF]]></category>

		<guid isPermaLink="false">http://bookcold.com/2010/07/574</guid>
		<description><![CDATA[<p>学习Entity Framework经常要写一些Linq to Entity的查询表达式，由微软自个提供的EFQuerySamples就是一个相当不错的参考工具！</p> <p>点此下载</p> <p> <p>下载后简单配置就可以使用了，很方便。</p> <p> </p> <p>展开后，选择感兴趣的查询主题，就可以查看相应代码了！</p> <p> </p> <p>感谢：http://www.dotblogs.com.tw/asdtey/archive/2009/10/02/10889.aspx</p> ]]></description>
			<content:encoded><![CDATA[<p>学习Entity Framework经常要写一些Linq to Entity的查询表达式，由微软自个提供的EFQuerySamples就是一个相当不错的参考工具！</p>
<p><a href="http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=EFQuerySamples&amp;DownloadId=12018" target="_blank">点此下载</a></p>
<p> <span id="more-574"></span>
<p>下载后简单配置就可以使用了，很方便。</p>
<p><a href="http://bookcold.com/wp-content/uploads/2010/07/image2.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://bookcold.com/wp-content/uploads/2010/07/image_thumb2.png" width="634" height="483" /></a> </p>
<p>展开后，选择感兴趣的查询主题，就可以查看相应代码了！</p>
<p><a href="http://bookcold.com/wp-content/uploads/2010/07/image3.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://bookcold.com/wp-content/uploads/2010/07/image_thumb3.png" width="633" height="483" /></a> </p>
<p>感谢：<a href="http://www.dotblogs.com.tw/asdtey/archive/2009/10/02/10889.aspx">http://www.dotblogs.com.tw/asdtey/archive/2009/10/02/10889.aspx</a></p>
]]></content:encoded>
			<wfw:commentRss>http://bookcold.com/2010/07/574/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>infoQ:基于Visual Studio 2010 进行敏捷/Scrum模式开发</title>
		<link>http://bookcold.com/2010/07/568</link>
		<comments>http://bookcold.com/2010/07/568#comments</comments>
		<pubDate>Thu, 29 Jul 2010 04:26:11 +0000</pubDate>
		<dc:creator>bookcold</dc:creator>
				<category><![CDATA[程序设计]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[Scrum]]></category>

		<guid isPermaLink="false">http://bookcold.com/2010/07/568</guid>
		<description><![CDATA[<p>转自：http://www.infoq.com/cn/articles/visual-studio-2010-agile-scrum-development</p> <p>根据Forrester Research今年第二季度的一份研究报告，在超过1000名专业开发人员中，采用敏捷模式进行软件开发的已经有10.9%采用了Scrum模式，在所有的敏捷开发模式中名列首位，而在所有的软件项目管理模式中，敏捷模式更是被35%的开发人员所采用。当然，研究报告为我们呈现的仅仅是一个统计学的观点，到底你的开发团队应该采用什么样的开发模式，这还是要根据各自不同的开发环境，人员构成，公司架构以及文化背景来决定。</p> <p></p> <p>图1：Forrester 关于敏捷模式的调查报告</p> <p>Visual Studio 2010 是微软在2010年4月发布的全新一代的集成开发环境，配合同时发布的Team Foundation Server 2010（TFS——团队服务器） ，为开发团队提供了全面的应用程序生命周期管理（ALM）工具和平台。在2010这个版本中，对于敏捷，或者说Scrum模式的支持是前所未有的。虽然微软的Visual Studio Team System从2005年开始发布的时候就提供了敏捷流程模板（也就是MSF Agile）模板，但是2008版之前的这个敏捷流程模板都是基于MSF（微软解决方案框架）的；这个框架是微软针对自己的研发团队的最佳实践进行抽取总结出来的，与广大敏捷开发社区里面所流行的很多敏捷方法并不是很契合，造成了开发团队在实施的时候有很多不适用的地方。因此，微软在开发2010版本的过程中，大量的听取了敏捷开发社区中的声音，在自己的MSF Agile 5.0的模板中进行很多针对敏捷，更确切的说是Scrum开发模式的改进，使得2010版本中所集成的MSF Agile 5.0的模板非常适合我们来进行Scrum模式的开发组织。当然，微软的产品为了追求通用性，在MSF Agile 5.0的模板中并没有完全采用Scrum模式通行的名称和流程；同时，微软在两周前又发布了一个纯粹的Scrum流程模板以供那些希望完全使用Scrum模式的开发团队使用，当然这个模板现在仍然是Beta版。</p> <p>我个人认为，开发团队采用哪一个模板并不是最重要的，重要的是我们需要在开发过程中不断地改进过程，并对这个模板进行定制，以便适合我们自己的开发流程。这也是为什么TFS所提供的是一个模板，因为它的目的就是希望我们在这个模板的基础上不断的改进，最终找到适合</p> <p>自己开发团队的流程。其实这也很符合Scrum模式的理念；简单一点来说，Scrum模式是一种针对复杂项目的流程组织方式的框架，其目标是为了让我们开发出更高质量的软件产品。围绕的这个目标，Scrum模式为我们提供一个团队模型，一系列工具和一个简单的流程。在这样一个框架之下，Scrum模式要求我们不断地改进流程以达到适合团队的最佳状态，这种对改进的要求也是Scrum模式区别于其他开发流程的重要特点之一。</p> <p> </p> 为什么Scrum模式适合软件开发？ <p>软件行业至今已经有超过40年的历史，很多在软件工程中的管理方法都是在不断摸索中改进而来的。早期的软件行业由于规模有限，绝大多数属于作坊型，几个人在一起靠着自己的聪明才智创造出软件产品；但是当团队规模不断扩大的时候，开发人员开始需要一种模型来组织越来越庞大的团队，满足越来越复杂的需求。因为没有经验可循，软件开发团队将很多传统工业工程的方法借鉴到软件行业，因而出现像“瀑布式”的模型。“瀑布式”模型要求我们在实际的开发工作开始之前进行很多非常细致的设计和计划，力图将不可控的开发过程细化成可以控制的颗粒，以达到对复杂项目的总体控制目的。但是“瀑布式”模型忽视了软件项目的一个本质特点，那就是需求的不确定性；我们不可能像造汽车一样在上生产线之前把所有的零件都设计好，所有的流程都规定好，再进行装配；因为任何软件在实际进行编码之前都没有人知道这些代码应该如何实现，而且每一个开发人员的水平不同，习惯不同，写出的代码也是不同的；再加上客户对于软件的需求也是在不断变化的，一年之前的业务流程很可能在一年之后就产生的变化，如果还按照之前的需求进行开发，那么交付的时候肯定是无法满足要求的；更重要的事，在客户没有看到或者实际操作软件产品之前，他们永远也不能明确地告诉你他们要的到底是什么。因为这种种原因，造成了软件开发不可能采用传统的工程方法进行组织，因为其本身是一种需要依赖于开发人员智慧的探索性行为，也造成了我们的软件项目中有很大一部分是失败的。</p> <p>Scrum模式的出现正是基于对于软件开发行为本质的认识，提供了一种松散的框架，让我们使用一种探索性的流程方法来组织本来就是探索性的开发过程；从根本上满足了软件开发本身对于流程的需求。这种方法论实际上是基于爱德华?戴明所提出的戴明环的管理方法；戴明环理论提出：人类在进行任何复杂活动时，获得成功的最有效过程要经过：Plan 计划– Do执行 – Check 检查– Act改进，四个子过程，并不停的迭代以便找到最佳的方法来解决问题。这个理论不是针对软件开发提出的，但是软件开发本身其实就是最典型的复杂活动。</p> <p></p> <p>图2：Scrum的流程</p> <p>这里我们再回头看看Scrum的流程，Scrum的流程主要包含以下内容：</p> (P) Release/Sprint Planning：发布/迭代计划 (C&#38;P) Daily Scrum：每日回顾 (C&#38;A) Sprint Review：迭代产品检查 (A) Sprint Retrospective ：迭代流程检查 <p>我们可以看到，Scrum模式的流程与戴明环仅仅相扣。有很多认为敏捷模式会弱化计划的作用，其实不然，敏捷模式更加强调计划，而且强调更加频繁的计划，比如：每日回顾这个流程就要求我们的团队每个成员每天早上用15分钟的时间来回答3个问题：</p> [...]]]></description>
			<content:encoded><![CDATA[<p>转自：<a href="http://www.infoq.com/cn/articles/visual-studio-2010-agile-scrum-development">http://www.infoq.com/cn/articles/visual-studio-2010-agile-scrum-development</a></p>
<p>根据Forrester Research今年第二季度的一份研究报告，在超过1000名专业开发人员中，采用敏捷模式进行软件开发的已经有10.9%采用了Scrum模式，在所有的敏捷开发模式中名列首位，而在所有的软件项目管理模式中，敏捷模式更是被35%的开发人员所采用。当然，研究报告为我们呈现的仅仅是一个统计学的观点，到底你的开发团队应该采用什么样的开发模式，这还是要根据各自不同的开发环境，人员构成，公司架构以及文化背景来决定。</p>
<h5>
<p><img alt="" src="http://www.infoq.com/resource/articles/visual-studio-2010-agile-scrum-development/zh/resources/scrum-1.jpg" width="385" height="261" /></p>
</h5>
<p><strong>图1：</strong>Forrester 关于敏捷模式的调查报告</p>
<p>Visual Studio 2010 是微软在2010年4月发布的全新一代的集成开发环境，配合同时发布的Team Foundation Server 2010（TFS——团队服务器） ，为开发团队提供了全面的应用程序生命周期管理（ALM）工具和平台。在2010这个版本中，对于敏捷，或者说Scrum模式的支持是前所未有的。虽然微软的Visual Studio Team System从2005年开始发布的时候就提供了敏捷流程模板（也就是MSF Agile）模板，但是2008版之前的这个敏捷流程模板都是基于MSF（微软解决方案框架）的；这个框架是微软针对自己的研发团队的最佳实践进行抽取总结出来的，与广大敏捷开发社区里面所流行的很多敏捷方法并不是很契合，造成了开发团队在实施的时候有很多不适用的地方。因此，微软在开发2010版本的过程中，大量的听取了敏捷开发社区中的声音，在自己的MSF Agile 5.0的模板中进行很多针对敏捷，更确切的说是Scrum开发模式的改进，使得2010版本中所集成的MSF Agile 5.0的模板非常适合我们来进行Scrum模式的开发组织。当然，微软的产品为了追求通用性，在MSF Agile 5.0的模板中并没有完全采用Scrum模式通行的名称和流程；同时，微软在两周前又发布了一个纯粹的Scrum流程模板以供那些希望完全使用Scrum模式的开发团队使用，当然这个模板现在仍然是Beta版。</p>
<p>我个人认为，开发团队采用哪一个模板并不是最重要的，重要的是我们需要在开发过程中不断地改进过程，并对这个模板进行定制，以便适合我们自己的开发流程。这也是为什么TFS所提供的是一个模板，因为它的目的就是希望我们在这个模板的基础上不断的改进，最终找到适合</p>
<p>自己开发团队的流程。其实这也很符合Scrum模式的理念；简单一点来说，<b>Scrum</b><b>模式是一种针对复杂项目的流程组织方式的框架</b>，其目标是为了让我们开发出更高质量的软件产品。围绕的这个目标，Scrum模式为我们提供一个团队模型，一系列工具和一个简单的流程。在这样一个框架之下，Scrum模式要求我们不断地改进流程以达到适合团队的最佳状态，这种对改进的要求也是Scrum模式区别于其他开发流程的重要特点之一。</p>
<p> <span id="more-568"></span>
</p>
<h4>为什么Scrum模式适合软件开发？</h4>
<p>软件行业至今已经有超过40年的历史，很多在软件工程中的管理方法都是在不断摸索中改进而来的。早期的软件行业由于规模有限，绝大多数属于作坊型，几个人在一起靠着自己的聪明才智创造出软件产品；但是当团队规模不断扩大的时候，开发人员开始需要一种模型来组织越来越庞大的团队，满足越来越复杂的需求。因为没有经验可循，软件开发团队将很多传统工业工程的方法借鉴到软件行业，因而出现像“瀑布式”的模型。“瀑布式”模型要求我们在实际的开发工作开始之前进行很多非常细致的设计和计划，力图将不可控的开发过程细化成可以控制的颗粒，以达到对复杂项目的总体控制目的。但是“瀑布式”模型忽视了软件项目的一个本质特点，那就是需求的不确定性；我们不可能像造汽车一样在上生产线之前把所有的零件都设计好，所有的流程都规定好，再进行装配；因为任何软件在实际进行编码之前都没有人知道这些代码应该如何实现，而且每一个开发人员的水平不同，习惯不同，写出的代码也是不同的；再加上客户对于软件的需求也是在不断变化的，一年之前的业务流程很可能在一年之后就产生的变化，如果还按照之前的需求进行开发，那么交付的时候肯定是无法满足要求的；更重要的事，在客户没有看到或者实际操作软件产品之前，他们永远也不能明确地告诉你他们要的到底是什么。因为这种种原因，造成了软件开发不可能采用传统的工程方法进行组织，因为其本身是一种需要依赖于开发人员智慧的探索性行为，也造成了我们的软件项目中有很大一部分是失败的。</p>
<p>Scrum模式的出现正是基于对于软件开发行为本质的认识，提供了一种松散的框架，让我们使用一种探索性的流程方法来组织本来就是探索性的开发过程；从根本上满足了软件开发本身对于流程的需求。这种方法论实际上是基于爱德华?戴明所提出的戴明环的管理方法；戴明环理论提出：人类在进行任何复杂活动时，获得成功的最有效过程要经过：Plan 计划– Do执行 – Check 检查– Act改进，四个子过程，并不停的迭代以便找到最佳的方法来解决问题。这个理论不是针对软件开发提出的，但是软件开发本身其实就是最典型的复杂活动。</p>
<p><img alt="" src="http://www.infoq.com/resource/articles/visual-studio-2010-agile-scrum-development/zh/resources/scrum-2.jpg" /></p>
<p><strong>图2：</strong>Scrum的流程</p>
<p>这里我们再回头看看Scrum的流程，Scrum的流程主要包含以下内容：</p>
<ul>
<li>(P) Release/Sprint Planning：发布/迭代计划 </li>
<li>(C&amp;P) Daily Scrum：每日回顾 </li>
<li>(C&amp;A) Sprint Review：迭代产品检查 </li>
<li>(A) Sprint Retrospective ：迭代流程检查 </li>
</ul>
<p>我们可以看到，Scrum模式的流程与戴明环仅仅相扣。有很多认为敏捷模式会弱化计划的作用，其实不然，敏捷模式更加强调计划，而且强调更加频繁的计划，比如：每日回顾这个流程就要求我们的团队每个成员每天早上用15分钟的时间来回答3个问题：</p>
<ol>
<li>你昨天做了什么？ </li>
<li>你今天计划做什么？ </li>
<li>有什么问题阻碍你的开发进程？ </li>
</ol>
<p>其实这正是对于之前开发内容的检查，同时也是对后续开发内容的计划过程。</p>
<h4>Scrum模式需要怎样的工具来实现？</h4>
<p>对于使用什么样的工具来实现Scrum模式，现在也有很多不同的观点。其实有很多人认为白板和即时贴就是最好的工具，其实对于小型团队来说这的确是最有效而且最经济的方法。但是如果考虑到软件公司的管理需求（工作量统计等），远程团队，开发工具集成，代码质量控制，发布后期支持等等；我们还是需要一个高度集成的平台和一整套工具来支持我们的开发团队。</p>
<p><img alt="" src="http://www.infoq.com/resource/articles/visual-studio-2010-agile-scrum-development/zh/resources/scrum-3.jpg" /></p>
<p><strong>图3：</strong>白板和即时贴</p>
<p>Visual Studio 2010所提供的集成开发环境可以满足我们以上的一系列需求，帮助我们的开发团队更好组织开发，帮助我们的管理层更好地掌控开发过程，帮助软件公司开发出更高质量的产品。</p>
<p>Scrum模式对于工具的要求，主要集中在以下一个方面：</p>
<ol>
<li><b>团队组织：</b>满足PO （产品经理），Scrum Master （流程经理）和开发团队管理，以不同的权限访问团队项目并对不同角色提供个性化的信息支持的能力。 </li>
<li><b>产品需求记录和跟踪：</b>对于Product Backlog Item （PBI 产品需求列表）的添加，编辑，优先级排序以及交付开发团队以后进行跟踪的能力。 </li>
<li><b>流程管理：</b>满足Sprint Planning, Daily Scrum, Sprint Review和Sprint Retrospective这些流程中对于信息共享，信息转移和跟踪的能力。 </li>
<li><b>产品质量：</b>在整个开发过程中，配合Scrum模式达到产出高质量代码和产品的能力。 </li>
</ol>
<p>下面我们就看看Visual Studio 2010系统在这4个方面如何满足Scrum模式的需求，并协助我们开发出高质量的产品。</p>
<h4>Visual Studio 2010上的Scrum团队组织</h4>
<p>一个完整的Scrum开发团队主要由以下角色组成：</p>
<ol>
<li><b>Product Owner </b><b>（</b><b>PO </b><b>产品经理）：</b>我喜欢把PO翻译为产品经理，因为PO的工作职责就是向客户和干系人收集产品需求，进行排序并保证开发团队按照干系人对需求优先级的要求进行交付。 </li>
<li><b>Scrum Master </b><b>（</b><b>SM </b><b>流程经理）：</b>对于Scrum Master我一直没有更好的翻译，将其译成为流程经理是因为这一角色要保证团队按照Scrum的方式来组织开发，并协助团队和PO进行有效的沟通，解决团队所遇到的问题。Scrum Master和项目经理的区别在于，他更加倾向于保证开发流程的完整性而不是倾向于满足客户/干系人的需求。 </li>
<li><b>开发团队：</b>开发团队在Scrum模式中是作为一个整体出现的，一般来说团队的大小控制在3-7个人的规模；团队作为一个整体向PO负责，而不是每个人对于自己的任务负责。 </li>
</ol>
<p>在Visual Studio 2010 系统中，使用TFS服务器基于角色的权限控制，我们可以很方便地定义出不同的权限范围。当然，最简单的方法是把Scrum团队的角色和TFS的默认角色之间进行映射。</p>
<p><img alt="" src="http://www.infoq.com/resource/articles/visual-studio-2010-agile-scrum-development/zh/resources/scrum-4.jpg" /></p>
<p><strong>图4：</strong>TFS团队项目的默认角色</p>
<p><b></b></p>
<p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="140">
<p><b>Scrum</b><b>团队角色</b></p>
</td>
<td valign="top" width="161">
<p><b>TFS</b><b>团队角色</b></p>
</td>
<td valign="top" width="319">
<p>&#160;</p>
</td>
</tr>
<tr>
<td valign="top" width="140">
<p>Product Owner</p>
</td>
<td valign="top" width="161">
<p>Contributor</p>
</td>
<td valign="top" width="319">&#160;</td>
</tr>
<tr>
<td valign="top" width="140">
<p>Scrum Master</p>
</td>
<td valign="top" width="161">
<p>Project Administrator</p>
</td>
<td valign="top" width="319">&#160;</td>
</tr>
<tr>
<td valign="top" width="140">
<p>开发团队</p>
</td>
<td valign="top" width="161">
<p>Contributor</p>
<p>Builders</p>
<p>Project Administrator</p>
</td>
<td valign="top" width="319">
<p>根据团队不同人员的职责具体分配</p>
</td>
</tr>
<tr>
<td valign="top" width="140">
<p>项目干系人</p>
</td>
<td valign="top" width="161">
<p>Readers</p>
</td>
<td valign="top" width="319">
<p>如果客户愿意更直接的参与项目，可以允许他们直接访问TFS。</p>
</td>
</tr>
</tbody>
</table>
<p><strong>表1：</strong>Scrum团队和TFS团队角色映射</p>
<h4><b>Visual Studio 2010</b><b>系统中对需求记录和跟踪的支持</b></h4>
<p>Scrum模式中的需求主要是采用Product Backlog Item（PBI产品需求列表）和Sprint Backlog Item （SBI 迭代需求列表）来进行管理的，在Visual Studio 2010系统中，直接提供了针对这两个列表的工作项查询，并且还提供了Agile Workbook （敏捷工作簿）帮助我们更好对工作量和任务分配进行调控。</p>
<p><img alt="" src="http://www.infoq.com/resource/articles/visual-studio-2010-agile-scrum-development/zh/resources/scrum-5.jpg" /></p>
<p><strong>图5：</strong>使用MSF Agile 5.0模板创建的TFS团队项目集成了对PBI和SBI的管理功能</p>
<p><img alt="" src="http://www.infoq.com/resource/articles/visual-studio-2010-agile-scrum-development/zh/resources/scrum-6.jpg" /></p>
<p><strong>图6：</strong>Product Backlog 查询结果</p>
<p>上图中就是使用TFS内置的Product Backlog查询获取的产品需求列表，这个列表是PO使用的主要工具，我们可以注意到这个列表已经根据Stack Rank列进行了排序，这也反映了产品需求列表的特性：需要根据客户/干系人对需求项的优先级向团队交付任务；而PO的除了需要不断完善这个列表，还需要不断和客户干系人进行沟通，一边确定这个优先级。</p>
<p>在Scrum模式中，对于优先级的定义决定于两个因素：需求的商业价值和紧迫程度；另外一个重要的指标就是Story Point，这个指标标志着当前需求项的相对大小，注意这里说的相对大小，很多人将这个值理解为人天或者人时，其实是不准确的，因为在PO准备产品需求列表的过程中，仅凭PO的经验是很难准确的判断出以时间为度量的工作量的，但是相对的大小是比较容易判断的。</p>
<p>另外，从State和Iteration Path两个列的值我们可以看到，已经有一些需求在迭代1-2中已经解决。根据这些信息，PO可以很容易的对工作进度和剩余需求进行管理。</p>
<p>另外一个重要的查询就是Iteration Backlog查询：</p>
<p><img alt="" src="http://www.infoq.com/resource/articles/visual-studio-2010-agile-scrum-development/zh/resources/scrum-7.jpg" /></p>
<p><strong>图7：</strong>Iteration Backlog查询结果</p>
<p>Iteration Backlog <a name="_GoBack"></a>中包含了团队在某个迭代中需要完成的需求以及针对这些需求细化出来的具体开发/架构/测试等任务。在Visual Studio 2010中，微软终于开始支持树形结构的工作项关联，从上图可以看出，每一个User Story的下面都挂接着相应Tasks，这些任务是在Sprint Planning Meeting中由团队成员自己根据PO对需求的阐述进行的细化，同时团队成员还需要根据经验对这些Tasks进行估算，给出基线估值（Original Estimate）。在开发过程中，团队成员在每天的Daily Scrum之前需要对前一天的任务更新状态（State），已完成工作量（Completed Work）和剩余工作量（Remaining Work）字段的内容；通过这些信息我们就可以使用TFS自带的燃尽图报表对进度进行查询和预测了。</p>
<p>实际上，纯粹的Scrum模式并不关心已完成工作量（Completed Work）也就是以完成工作量的值，但是对于使用人天/人时等信息来衡量团队工作量，甚至依赖这些数据想客户收取开发费用的咨询类公司来说，这些信息是非常重要的。</p>
<h4>Visual Studio 2010对Scrum流程中重要事件的支持</h4>
<p>Scrum模式中的几个重要的会议包括：</p>
<ol>
<li>Sprint Planning Meeting </li>
<li>Daily Scrum Meeting </li>
<li>Sprint Review Meeting </li>
<li>Sprint Retrospective Meeting </li>
</ol>
<p>这一系列的会议是真正体现Scrum模式对于开发流程控制的核心内容，在Scrum模式中另外一个非常重要的概念是：时间箱（Time Box），它要求我们对于流程中的事件进行非常严格的时间控制。很多人在开始进行Scrum模式开发的时候的一个普遍问题是：一个迭代（Sprint）的长度应该是多少？对于这个问题其实也没有标准答案，而必须根据团队的大小来进行判断。对于之前我所建议的3-7人大小的团队，我会建议采用2周的迭代长度。原因在于1周太短，团队还无法完成真正有商业价值并可以进行交付的需求；而3周的时间则太长，需求的变化所造成的风险会变得比较大。</p>
<p>采用迭代式开发的时候其实长度是越短越好，我们总是尽可能的缩短迭代以便可以通过给客户的交付获得更有价值的反馈以便对后续的开发进行调整，因此这个长度应该是团队刚刚可以完成可交付需求的最短时间。我们需要严格控制的是，迭代的长度应该是一个时间概念儿不是工作量的概念，也就是说如果2周的时间已经耗尽但是团队还没有完成当前迭代中的所有需求，那么也必须结束迭代进行交付，而不能选择延长迭代来完成未尽需求。这样做的结果有两个：1）当前的迭代会以失败告终；2）通过对已经完成需求的交付，我们可以获取客户的反馈。很明显，失败的迭代是我们不愿意看到的，但是客户对于已经完成需求的反馈比保持常胜将军的名誉更加重要，因为后者是保证我们软件质量（符合需求）的重要手段。</p>
<p>当然，这里隐藏着另外一个很重要的问题，在团队无法完全完成需求的情况下如何还能提供可交付的成果，这就要依靠我们对于需求定义方式的变化和Visual Studio 2010 中对持续集成和更加高效的测试支持来实现了。在需求定义上，我们需要采用业务导向的需求定义，保证每一个需求的完成都可以交付一定的商业价值。以往的需求往往是功能导向的，但是功能导向的需求对于用户来说不一定具备商业价值，但是业务导向的需求则可以保证这一点，比如：我们可以这样定义一个User Story，作为市场经理，我希望对客户数据进行查询以便可以找到本市的客户并和他们进行联系。使用这样的需求定义意味着只要我们完成这一需求对客户就是有价值的，因为它不是一个功能碎片，而是一个用户交互用例。如果在一个迭代中我们无法完成所有的需求，只要完成其中一个，那么都是可以向客户交付的。另外，借助Visual Studio 2010对持续集成和测试的支持，我们可以采用每日构建的方式保证所有完成的代码都符合质量要求，也就避免了在迭代后期进行集中测试而拖延交付的可能性。</p>
<h5>Sprint Planning Meeting的支持</h5>
<p>在Visual Studio 2010中提供了一个叫Agile Workbook的Excel模板，可以帮助我们很好地完成Sprint Planning Meeting。在这个会议中，最重要的任务就是将PBI转化成SBI，并且由团队给出完成这些SBI的承诺；团队要做出这样的承诺最重要的依据就是这些需求所涉及的工作量是否可以承受。Agile Workbook正是帮助我们回答这一问题的强大工具。从下图我们可以看到，当我们制定了迭代上的人员配备并将Task分配给每个开发人员以后，模板会给出非常直观的柱状图，帮助团队判断工作量是否可行。</p>
<p><img alt="" src="http://www.infoq.com/resource/articles/visual-studio-2010-agile-scrum-development/zh/resources/scrum-8.jpg" /></p>
<p><strong>图8：</strong>对迭代1-3上的工作量进行横向比较，根据历史数据判断后续迭代是否可行</p>
<p><img alt="" src="http://www.infoq.com/resource/articles/visual-studio-2010-agile-scrum-development/zh/resources/scrum-9.jpg" /></p>
<p><strong>图9：</strong>在当前迭代上对每个开发人员的工作量分配进行比较</p>
<h5>Daily Scrum Meeting支持</h5>
<p>这个会议非常简短，所以我们更加需要非常直观的图表以帮助团队对进度进行审核，在TFS中提供了燃尽图为团队提供这些信息。</p>
<p><img alt="" src="http://www.infoq.com/resource/articles/visual-studio-2010-agile-scrum-development/zh/resources/scrum-10.jpg" /></p>
<p><strong>图10：</strong>迭代燃尽图</p>
<p>根据每个开发人员对于工作量的更新，从上图我们可以很容易对完成时间进行预测，图中黑色实线和横轴的焦点就是当前迭代的可能完成时间。</p>
<h5>Sprint Review &amp; Retrospective Meeting 的支持</h5>
<p>Sprint Review的支持更多地体现于Visual Studio 2010的持续集成能力，因为这个会议是对于需求完成情况的审核，如果我们能够保证需求是业务导向的并充分利用Visual Studio 2010的自动化构建和测试集成能力。那么我们就可以保证在这个会议上交付一定的商业价值。具体如何使用Visual Studio 2010来实现在后面做详细介绍。</p>
<p>Retrospective 会议其实非常简单，需要我们团队成员对当前迭代的运作进行总结，但为了使这些信息可以完整的保存以便后续使用，我们可以利用TFS提供的门户站点，定制一个SharePoint的列表分类的记录这些反馈以便团队查询。</p>
<h4><b>Visual Studio 2010</b><b>对于产品质量的保证</b></h4>
<p>提高产品质量是Visual Studio 2010在设计阶段就确定的重要目标，在2010版本所添加的新特性中，已经想着这个目标形成了一套完整的解决方案。对于Scrum模式来说，交付高质量的产品也同样是其终极目标，而且我们需要在迭代时间很短的情况下仍然保证质量，这就更加需要依赖工具的支持。</p>
<h5>自动化构建</h5>
<p>之所以把自动化构建列在首位，是因为软件工程发展到今天，自动化构建已经是任何一个想要实现高质量的软件开发团队都必须采用的工程方法；另外，对于Visual Studio 2010系统来说，自动化构建也起着承上启下，贯穿全局的重要地位。当开发软件进入第一个迭代的开发时，所要进行的第一项工作并不是开始实际的编码，而是创建出符合团队需求的构建模板。这样做的目的在于团队在后期的实际开发中可以更加专注于需求的开发，而不必花费额外的时间和精力来集成开发人员的代码；开始阶段的代码量很少，团队可以有更加清晰的思路将迁入策略，架构验证，自动化测试列表设置好并保证构建可以正常运行；如果把这个工作放到迭代后期进行，往往会因为代码中的缺陷和不同开发习惯造成构建模板不能正常运行。</p>
<p>在Visual Studio 2010中，提供了更加便捷的模板创建工具，特别是添加了Gated Check-in 构建的触发方式，可以保证所有嵌入源代码库的代码都是经过验证的。</p>
<p><img alt="" src="http://www.infoq.com/resource/articles/visual-studio-2010-agile-scrum-development/zh/resources/scrum-11.jpg" /></p>
<p><strong>图11：</strong>Gated Check-in 构建触发器</p>
<p>Gated Check-in 触发方式和以往的触发方式所不同之处在于，开发人员执行迁入操作的时候代码并不会直接进入源代码库，而必须先经过构建的验证：保证编译成功和定义好的迁入验证测试可以成功运行，然后TFS才会把代码真正嵌入服务器。之前的持续集成（Continuous Integration） 方式也会在迁入的时候进行构建，但是这种构建是将代码先迁入，然后再运行构建，如果代码中已经存在了缺陷，那么在服务器上就会留下缺陷代码；Gated Check-in 借助TFS源代码管理中的“搁置”功能，先把代码搁置到服务器上临时存储中，在构建成功后才会正式迁入，所以缺陷代码不会进入服务器。</p>
<p><img alt="" src="http://www.infoq.com/resource/articles/visual-studio-2010-agile-scrum-development/zh/resources/scrum-12.jpg" /></p>
<p><strong>图12：</strong>构建参数配置</p>
<p>TFS的自动化构建可以集成测试列表，图中的上方的红色区域中就是要求构建从项目文件中的测试列表文件中提取单元测试并自动运行；另外一个在Visual Studio 2010种的重要改进就是下方红色区域中的架构验证参数。如果我们的项目文件中包含了架构层次图（Layer Diagram）的话，那么我们就是添加这个参数让构建自动的验证项目的代码是否符合架构设计的要求。</p>
<p><img alt="" src="http://www.infoq.com/resource/articles/visual-studio-2010-agile-scrum-development/zh/resources/scrum-13.jpg" /></p>
<p><strong>图13：</strong>Visual Studio 2010的层次架构图 Layer Diagram</p>
<p>Scrum模式开发中的架构设计给我们提出了非常大的挑战，由于我们采取业务导向的需求定义，开发人员必须从数据层一直实现到表现层；在这个过程中如何保证项目的架构仍然符合需求非常困难；而Visual Studio 2010的架构验证功能则可以帮助我们在每次迁入代码的时候都进行验证，保证违反架构规范的代码不会进入最终的交付产品。</p>
<h5>消除无法重现的Bug</h5>
<p>无法重现的Bug一直都是困扰开发人员的问题，开发环境，测试环境，生产环境的不同；开发人员，测试人员和最终用户的不同都是造成Bug无法被重现的客观因素。在Visual Studio 2010中，提供了很多强大的调试和测试工具来帮助我们解决这个问题。</p>
<ul>
<li>IntelliTrace（历史数据调试） </li>
<li>协作调试 </li>
<li>测试管理器和手工测试（Test Manager） </li>
<li>实验室管理（Lab Manager） </li>
</ul>
<h4>IntelliTrace——历史数据调试器</h4>
<p>IntelliTrace在开发过程中的名称就叫Historical Debugger （历史数据调试器），后来这个用来进行市场宣传的名称反而不能反映它的实质。IntelliTrace可以把程序运行过程中的所有历史数据都记录下来，使得程序员可以回滚到任何的历史点来查看程序状态，这对于开发人员调试复杂逻辑非常有用；之前我们在做同样工作的时候必须反复运行程序，以便找到问题，而现在则可以让程序反向运行。</p>
<p><img alt="" src="http://www.infoq.com/resource/articles/visual-studio-2010-agile-scrum-development/zh/resources/scrum-14.jpg" /></p>
<p><strong>图14：</strong>IntelliTrace调试器重所记录的程序历史数据</p>
<p>另外，IntelliTrace还可以把这些调试数据另存为tdlog文件；当开发人员A发现了B的一个问题的时候，他可以把自己调试环境中的tdlog发送给B，开发人员B就可以使用这个文件让Visual Studio恢复到开发人员A的调试状态，从而保证B可以有效的重现A所看到的问题。</p>
<h5>协作调试</h5>
<p>协作调试实际上解决多个开发人员在调试过程中的另外一些信息共享问题的方法，上面的IntelliTrace可以共享调试历史数据；但是用过Visual Studio 的开发人员都知道，像“断点”是不能保存到调试数据中，也不会被保存到项目文件中；所以协作调试就提供了开发人员共享断点信息，并且还可以让开发人员在断点信息上添加一些说明，以便帮助其他的开发人员理解问题。</p>
<h5>测试管理器和手工测试（Test Manager）</h5>
<p>测试管理器是Visual Studio 2010系统中为测试人员特意开发的可以独立运行的测试环境，它完全独立，不依赖于Visual Studio IDE，提供非常强大的测试录制等功能。在前面介绍构建的时候我曾经将单元测试集成到构建中去自动运行，但是单元测试只能针对后台逻辑进行，不能解决UI测试，或者叫黑盒测试问题。微软的测试管理器的出现，就是为解决UI测试的问题。</p>
<p>TFS 2010中专门提供测试用例（Test Case）工作项类型，这个工作项允许测试人员对具体的测试步骤进行设计，并且给出预测的结果；同时，借助测试管理器的录制功能，还可以把测试人员换的操作全部都录制下来，一边后来自动播放；或者生成Coded UI 测试，一旦有了Coded UI测试，我们就可以把这些针对UI的测试也集成到自动化构建中去。</p>
<p><img alt="" src="http://www.infoq.com/resource/articles/visual-studio-2010-agile-scrum-development/zh/resources/scrum-15.jpg" /></p>
<p><strong>图15</strong>：测试用例（Test Case）工作项</p>
<p>实际上，真正可以使用单元测试覆盖的测试仅占所有的测试的30%都不到，另外这70%的测试以往都是依赖于测试人员手工的进行；现在借助微软测试管理器的功能，我们可以将这些测试集成到高度自动化的开发流程中。可以帮助我们更加快捷的完成测试，为开发人员提供反馈。</p>
<p>在Scrum模式中，业务导向的需求也要求我们的测试团队可以更加快捷的给出测试结果，前一天完成的需求最好可以在第二天就将测试结果反馈给团队；依赖于每日构建，我们可以在每天晚上将前一天的代码生成一个新版本，共测试团队使用；测试团队在第二天就可以把测试结果反馈给开发团队，同时将可以自动化运行的测试继承到每日构建中；在第三天的时候我们的团队就可以利用这些已经自动化的测试来验证我们的程序了。</p>
<p>由于每天都进行测试，那么新增的代码量就非常有限，也就使得Bug的数量可以得到有效的控制，从这个方面上说，测试管理器所提供的手工测试，自动化测试录制和回放，并且和构建的继承为我们提供了一个非常高效的高质量的开发平台，从流程和工程技术上为质量提供了保证。</p>
<h5>实验室管理（Lab Manager）</h5>
<p>实验室管理是我在Visual Studio 2010系统中见过的最酷的功能，也是微软继承了自己的多项产品为开发团队提供的最完整的测试解决方案。在测试中一个非常难实现的问题，就是对于不同环境的创建，还原和状态的保存。如果同一个用例在不同的环境中运行，结果往往是不同的，而且我们客户的使用环境也往往很复杂，所以就要求我们的测试人员可以搭建很多不同配置的测试环境，以便验证应用程序可以适应他们要求。</p>
<p>微软借助自己的Hyper-V虚拟化平台，为测试团队搭建这样的测试环境提供了非常好的支持，比如：我们可以使用SCVMM和TFS协同工作，当TFS需要测试环境的时候，通过SCVMM部署一台符合要求的虚拟机，并把需要测试应用自动的部署到这个虚拟机中，最终在这个环境中运行指定的测试。这样的测试环境避免了测试人员自己的机器不干净而导致的结果偏差，而且还可以通过环境快照的方式吧虚拟机的某个状态直接交付给开发人员进行检查。</p>
<p>在上面所介绍的这些功能中我们可以看到，实际上我们解决了3个不同测试的不可重现问题：</p>
<ol>
<li>开发人员本机上的不可重现：IntelliTrace </li>
<li>开发人员和开发人员之间的不可重现：IntelliTrace, tdlog和协作调试 </li>
<li>开发和测试环境之间的不可重现：微软测试和实验室管理器，Hyper-V </li>
</ol>
<p>这些功能在工程技术上为团队保证了高质量，同时配合Scrum模式所推行的时间箱管理，业务导向的需求定义以及流程上的保证，Visual Studio 2010系统和Scrum一起帮助我们创建更好的产品和更好的团队。</p>
<h4>结束</h4>
<p>我使用Visual Studio Team System是从2005年开始的，最初的目的只是为了满足远程迁入代码的需要；但随着2008和2010版本的发布，对于流程定制和整体性的质量解决方案的需求越高。幸运的是，这个时候公司为我提供了到澳大利亚接受Scrum Master培训的机会，使我可以体系化的了解了Scrum模式的精髓，回来之后就对我们的开发团队进行了一系列的优化。</p>
<p>同时，作为Scrum Master我也同时获得了提供Professional Scrum Developer培训的机会，PSD课程是微软和scrum.org共同开发的一套基于实践的scrum开发人员培训课程，它使用Visual Studio 2010系统作为平台，将参训人员分为不同的团队，进行实际的开发工作，在开发的过程中让学员体会Scrum的妙处和Visual studio 2010的强大。目前我们已经在澳大利亚墨尔本和意大利米兰成功运作了这个课程。作为在亚洲去唯一向中国提供这一课程的提供商，我也希望能够和更多的开发人员分享这些内容。</p>
]]></content:encoded>
			<wfw:commentRss>http://bookcold.com/2010/07/568/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Art of Separation of Concerns</title>
		<link>http://bookcold.com/2010/07/565</link>
		<comments>http://bookcold.com/2010/07/565#comments</comments>
		<pubDate>Mon, 26 Jul 2010 02:24:14 +0000</pubDate>
		<dc:creator>bookcold</dc:creator>
				<category><![CDATA[系统架构]]></category>
		<category><![CDATA[设计模式]]></category>
		<category><![CDATA[SoC]]></category>

		<guid isPermaLink="false">http://bookcold.com/2010/07/565</guid>
		<description><![CDATA[<p>转自：http://www.aspiringcraftsman.com/2008/01/art-of-separation-of-concerns/</p> Introduction <p>In software engineering, Separation of Concerns refers to the delineation and correlation of software elements to achieve order within a system. Through proper separation of concerns, complexity becomes manageable.</p> <p>The goal of this article is to promote the understanding of the principle of Separation of Concerns and to provide a set of [...]]]></description>
			<content:encoded><![CDATA[<p>转自：<a href="http://www.aspiringcraftsman.com/2008/01/art-of-separation-of-concerns/">http://www.aspiringcraftsman.com/2008/01/art-of-separation-of-concerns/</a></p>
<h4>Introduction</h4>
<p>In software engineering, Separation of Concerns refers to the delineation and correlation of software elements to achieve order within a system. Through proper separation of concerns, complexity becomes manageable.</p>
<p>The goal of this article is to promote the understanding of the principle of Separation of Concerns and to provide a set of foundational concepts to aid software engineers in the development of maintainable systems.</p>
<p> <span id="more-565"></span><br />
<h4>The Principle of Separation of Concerns</h4>
<p>The Principle of Separation of Concerns states that system elements should have exclusivity and singularity of purpose. That is to say, no element should share in the responsibilities of another or encompass unrelated responsibilities.</p>
<p>Separation of concerns is achieved by the establishment of boundaries. A boundary is any logical or physical constraint which delineates a given set of responsibilities. Some examples of boundaries would include the use of methods, objects, components, and services to define core behavior within an application; projects, solutions, and folder hierarchies for source organization; application layers and tiers for processing organization; and versioned libraries and installers for product release organization.</p>
<p>Though the process of achieving separation of concerns often involves the division of a set of responsibilities, the goal is not to reduce a system into its indivisible parts, but to organize the system into elements of non-repeating sets of cohesive responsibilities. As Albert Einstein stated, “Make everything as simple as possible, but not simpler.”</p>
<p>At its essence, Separation of Concerns is about order. The overall goal of Separation of Concerns is to establish a well organized system where each part fulfills a meaningful and intuitive role while maximizing its ability to adapt to change.</p>
<h4>The Value of Separation of Concerns</h4>
<p>Applying the principle of separation of concerns to software design can result in a number of residual benefits. First, the lack of duplication and singularity of purpose of the individual components render the overall system easier to maintain. Second, the system as a whole becomes more stable as a byproduct of the increased maintainability. Third, the strategies required to ensure each component only concerns itself with a single set of cohesive responsibilities often result in natural extensibility points. Forth, the decoupling which results from requiring components to focus on a single purpose leads to components which are more easily reused in other systems, or different contexts within the same system. Fifth, the increase in maintainability and extensibility can have a major impact on the marketability and adoption rate of the system.</p>
<p>The principle of separation of concerns can also be of benefit when applied to business organizations. Within large companies, ensuring that groups and sub-organizations are assigned a unique set of cohesive responsibilities helps to facilitate overall business goals by minimizing the coordination necessary between teams and maximizing the potential of each team to focus on their collective responsibility and center of competency.</p>
<p>The principle of separation of concerns can also improve problem resolution in enterprise wide systems. When responsibilities are properly delineated, problem identification becomes easier, resolution becomes faster, and personal accountability is increased. Each of these areas in turn contributes to an improved quality control process.</p>
<p>Whether organizations of people or software systems are in view, applying the principle of separation of concerns can aid in the management of complexity by eliminating unnecessary duplication and proper responsibility allocation.</p>
<p>In the next sections, various techniques will be discussed for achieving separation of concerns within application design.</p>
<h4>Horizontal Separation</h4>
<p>Horizontal Separation of Concerns refers to the process of dividing an application into logical layers of functionally that fulfill the same role within the application.</p>
<p>One common division for graphical user interface applications is the separation of processes into the layers of Presentation, Business, and Resource Access. These categories encompass the main types of concerns for most application needs, and represent an organization of concerns which minimizes the level of dependencies within an application. Figure 1 depicts a typical three-layered application:</p>
<p><a href="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/horizontalLayers.png"><img title="horizontalLayers" alt="" src="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/horizontalLayers.png" width="382" height="314" /></a></p>
<p>Figure 1</p>
<p>The Presentation Layer encompasses processes and components related to an application’s user interface. This includes components which define the visual display of an application, and may include advanced design concepts such as controllers, presenters, or a presentation model. The primary goal of the Presentation Layer is to encapsulate all user interface concerns in order to allow the application domain to be varied independently. The Presentation Layer should include all components and processes exclusively related to the visual display needs of an application, and should exclude all other components and processes. This allows other layers within the application to vary independently from its display concerns.</p>
<p>The Business Layer encompasses processes and components related to the application domain. This includes components which define the object model, govern business logic, and control the workflow of the system. The business layer may be represented through specialized components which represent the workflow, business processes, and entities used within the application, or through a traditional object-oriented domain model which encapsulates both data and behavior. The primary goal of the Business Layer is to encapsulate the core business concerns of an application exclusive of how data and behavior is exposed, or how data is specifically obtained. The Business Layer should include all components and processes exclusively related to the business domain of the application, and should exclude all other components and processes.</p>
<p>The Resource Access Layer encompasses processes and components related to the access of external information. This includes components which interface with a local data store or remote service. The   <br />goal of the Resource Access Layer is to provide a layer of abstraction around the details specific to data access. This includes tasks such as the establishing of database and service connections, maintaining knowledge about database schemas or stored procedures, knowledge about service protocols, and the marshalling of data between service entities and business entities. The Resource Access Layer should include all components and processes exclusively related to accessing data external to the system, and should exclude all other components and processes.</p>
<p>Another common division used by Service Oriented Applications is the division of the application into the layers of Service Interface, Business, and Resource Access as depicted in Figure 2:</p>
<p><a href="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/horizontalLayers2.png"><img title="horizontalLayers2" alt="" src="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/horizontalLayers2.png" width="382" height="314" /></a></p>
<p>Figure 2</p>
<p>In this division, the Business and Resource Access layers serve the same purposes as previously discussed, with the service exposure concerns encapsulated into a Service Interface Layer. This layer encompasses service interface concerns such as the exposure of business processes through various protocols and the management of service specific contracts and data types. The primary goal of the Service Interface Layer is to encapsulate all service interface concerns in order to allow the application domain to be varied independently. The Service Interface Layer should include all components and processes exclusively related to the exposure of the application as a service, and should exclude all other components and processes.</p>
<p>By grouping processing concerns based on their role within the application, a number of benefits are gained which improve the overall system manageability. These benefits include ease of maintenance through consistent architecture and isolation of process, increased insulation from change impact, increased adaptability to change, and increased potential for reuse.</p>
<h4>Vertical Separation</h4>
<p>Vertical Separation of Concerns refers to the process of dividing an application into modules of functionality that relate to the same feature or sub-system within an application. Vertical separation divides the features of an application holistically, associating any interface, business, and resource access concerns within a single boundary. Figure 3 depicts an application separated into three modules:</p>
<p><a href="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/verticalLayers.png"><img title="verticalLayers" alt="" src="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/verticalLayers.png" width="364" height="311" /></a></p>
<p>Figure 3</p>
<p>Separating the features of an application into modules clarifies the responsibly and dependencies of each feature which can aid in testing and overall maintenance. Boundaries may be defined logically to aid in organization, or physically to enable independent development and maintenance.</p>
<p>Logical boundaries imply the existence of modularity, though the methods used to denote separation may have no bearing on the actual deployment or runtime behavior of an application. This can be useful for improving the maintainability of an application as well easing any future efforts for physically separating features. Figure 4 depicts an application containing logical boundaries:</p>
<p><a href="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/verticalLayers2.png"><img title="verticalLayers2" alt="" src="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/verticalLayers2.png" width="398" height="334" /></a></p>
<p>Figure 4</p>
<p>Physical boundaries are generally used in the context of developing add-ins or composite applications, and can enable features to be managed by disparate development teams. Applications supporting add-in modules often employ techniques such as auto-discovery, or initializing modules based on an external configuration source. Figure 5 depicts a hosting framework containing modules developed by separate development teams:</p>
<p><a href="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/verticalLayers3.png"><img title="verticalLayers3" alt="" src="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/verticalLayers3.png" width="625" height="354" /></a></p>
<p>Figure 5</p>
<p>While vertical separation groups a set of concerns based on their relevance to the total fulfillment of a specific feature within an application, this does not preclude the use of other separation of concerns strategies. For example, each module may itself be designed using layers to delineate the role of components within the module. Figure 6 depicts an application using both horizontal and vertical separation of concerns strategies:</p>
<p><a href="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/horizontalAndVerticalLayers.png"><img title="horizontalAndVerticalLayers" alt="" src="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/horizontalAndVerticalLayers.png" width="364" height="311" /></a></p>
<p>Figure 6</p>
<h4>Aspect Separation</h4>
<p>Aspect Separation of Concerns, better known as Aspect-Oriented Programming, refers to the process of segregating an application’s cross-cutting concerns from its core concerns. Cross-cutting concerns, or aspects, are concerns which are interspersed across multiple boundaries within an application. Logging is one example of an activity performed across many system components.</p>
<p>Figure 7 depicts an application with several cross-cutting concerns:</p>
<p><a href="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/aspect1.png"><img title="aspect1" alt="" src="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/aspect1.png" width="601" height="385" /></a></p>
<p>Figure 7</p>
<p>Cross-cutting concerns can be difficult to maintain due to their widespread placement throughout an application. Their mixture with core concerns also adds complexity, rendering the application more difficult to maintain. By separating these concerns, both core concerns and cross-cutting concerns are made easier to manage.</p>
<p>Aspect separation differs from other separation techniques in that it relies on a pre-processing, compile time, or run-time fusion of cross-cutting concerns with the application. The process of fusing the two concerns back together is referred to as “weaving”. By using various strategies, cross-cutting concerns can be separated and woven back into the application for run time cohesion.&#160; Aspect separation tools are available for a wide range of programming languages. For more information on this topic including a list of available tools for facilitating aspect separation see&#160; <a href="http://en.wikipedia.org/wiki/Aspect-oriented_programming">Aspect-Oriented Programming</a>.</p>
<h4>Dependency Direction</h4>
<p>One characteristic of good Separation of Concerns is the ideal establishment of dependency direction. An ideal dependency direction establishes the roles of consumer and dependency such that the role of dependency is occupied by the entity possessing the highest potential for reuse.</p>
<p>A simple example illustrating the concept of dependency direction is the common relationship between a business component and a utility component. Consider a system which provides an order inquiry process which requires that frequently requested data be cached for greater efficiency. To facilitate the caching of order inquiries, a caching utility component may be developed to separate the concerns of caching from the rest of the order inquiry process. Figure 8 depicts this system with its two components:</p>
<p><a href="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/direction1.png"><img title="direction1" alt="" src="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/direction1.png" width="450" height="216" /></a></p>
<p>Figure 8</p>
<p>Because the function of caching is a more generic behavior than an order inquiry process, the caching component has the higher potential for reuse among the two. Therefore, the best dependency direction in this case would be from the business component to the utility component. This dependency is depicted in Figure 9:</p>
<p><a href="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/direction2.png"><img title="direction2" alt="" src="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/direction2.png" width="413" height="110" /></a></p>
<p>Figure 9</p>
<p>Such a relationship allows the caching component to remain agnostic of the business inquiry process enabling it to be reused by future processes.</p>
<h4>Data Concerns</h4>
<p>Applying the principle of Separation of Concerns to data involves properly modeling information managed by a system. While the aspects of data modeling apply to both object-oriented and database design, this discussion focuses on object-oriented data concerns since the primary needs of a database often require form to follow function.</p>
<p>When organizing data within an object-model, the exposed information should be inherent to the entity being represented. For example, given a system which sells products to customers, an object which defines the product should not contain customer related information. This is because products are not inherently concerned with who may be purchasing the product. A better approach would be the creation of a conceptual order object which composes both customer and product information. This enables the product object to be reused by other processes in the future which may not be concerned with customer information.</p>
<p>In addition to considering the potential reuse of a data model within differing contexts, the   <br />intuitive organization of data is also beneficial when maintaining highly complex systems. For example, if a new developer were tasked with accessing the serial number of a particular part composed by a product object already in memory, the developer would likely first attempt to locate the particular product part and then examine the part for a “SerialNumber” or similarly named property. The developer would probably not think to look for something such as a “product number to serial number” dictionary located on the product object because this would not be a natural representation of the data. This would be similar to considering a person to have a serial number by virtue of their wearing a wrist-watch that possessed a serial number.</p>
<p>There are times, however, when the natural organization of data does not present an efficient mechanism for information inquiry. For example, an exceptionally complex product object which needs to be inspected frequently to derive the total count of all copper elements may not be efficiently handled through the examination or cross-referencing of each of its composed elements. In cases where natural modeling is not itself sufficient, the integrity of an object-model can be maintained by supplementing conceptual types to satisfy the specialized need. For example, if the product’s composition remains static once assembled, a conceptual model representing the product’s precious metal information (e.g. “ProductPreciousMetalManifest”) might be composed at a peer level to the product information. If the product’s composition changes frequently and the composition processes are centralized then the precious metal information might be updated as part of this process. Otherwise, a specialized component could be conceived (e.g. “PreciousMetalDetector”) to dynamically return the product’s precious metal information. As with the first example, the benefits of separating conceptual needs from an otherwise natural model are that other processes may reuse the model without incurring the overhead of non-inherent characteristics, and the model is kept easily maintainable.</p>
<h4>Behavior Concerns</h4>
<p>Separating behavior involves the division of system processes into logical, manageable, and reusable units of code. This represents the most fundamental type of Separation of Concerns. Within object-oriented systems, fine-grained behavior is separated using methods while course-grained behavior is separated using objects, components, applications, and services.</p>
<p>As with the separation of data, encapsulated behavior should be inherent to its containing boundaries. For instance, a method named CreateCustomer() would be expected to only contain behavior relevant to the creation of a new customer. It wouldn’t be expected to, for example, place orders for a new customer. Similarly, a component named ProductAssembler would be expected to contain data and behavior relevant to the assembly of products. Similarly, it wouldn’t be expected to contain data or behavior related to customers.</p>
<p>Achieving good separation of behavior is often an iterative process. The primary behavior of a system is generally conceived during a design phase, but the specific implementation of a system design often requires several iterations of refactoring as fine-grained concerns become more apparent.</p>
<p>When organizing behavior, the following goals should be sought:</p>
<p>* Eliminate the duplication of functionality.   <br />* Restrict the scope of work to a maintainable size.    <br />* Restrict the scope of work to the description of the containing boundary.    <br />* Restrict the scope of work to the inherent behavior of the containing boundary.    <br />* Minimize external dependencies.    <br />* Maximize the potential for reuse.</p>
<h4>Extending Concerns</h4>
<p>Extensions are a separation of concerns strategy which enables the addition of new behavior to an existing set of concerns. Extensions are used to enhance existing concerns where the desired behavior cannot be added to the targeted system, is not an inherent behavior of the system, or is otherwise impractical for inclusion as part of the system’s core set of features. Figure 10 depicts the dependency relationship of an extension to a target system:</p>
<p><a href="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/extensions1.png"><img title="extensions1" alt="" src="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/extensions1.png" width="625" height="365" /></a></p>
<p>Figure 10</p>
<p>Extensions interact with the target system in response to notifications of key events. Examples of behavior provided by extensions would include the display of new views or controls, the alteration of normal processing, or the alteration of data within the target system. Extensions generally take the form of a hosted add-in, and are typically registered through configuration or a dynamic discovery process.</p>
<p>When multiple client applications are maintained within an enterprise, it may be discovered that behavior provided by one client’s extension would be valuable to add to another client as well. If the extension is highly customized to the target application and provides a relatively simplistic behavior, the best course of action would be to reproduce the functionality in the new application. However, if the extension’s behavior is substantial in size and complexity then it may be more appropriate to provide the behavior generically through an enterprise service. If the behavior provided by the service is still inappropriate to include as a core dependency of the host system then a new extension can be developed to interact with the service on behalf of the application.</p>
<h4>Delegating Concerns</h4>
<p>Delegating concerns refers to the process of assigning the responsibility for fulfilling behavior to a subordinate component. This strategy separates the concerns of responsibility from execution, and is beneficial for designing components whose implementation details may vary depending on external conditions. Using this strategy, components proxy some or all data requests and method invocations to another component designed to fulfill the request in a specialized way. For example, a component designed to return a list of roles assigned to the current user may delegate the request to one or more subordinate components designed to retrieve roles from a local XML file, database, and/or a remote service. Figure 11 illustrates the delegation of authorization concerns to components specialized for differing data sources:</p>
<p><a href="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/delegation1.png"><img title="delegation1" alt="" src="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/delegation1.png" width="526" height="535" /></a></p>
<p>Figure 11</p>
<p>Delegation can be facilitated using the <a href="http://en.wikipedia.org/wiki/Strategy_pattern">Strategy Pattern</a>, the <a href="http://en.wikipedia.org/wiki/Plugin_pattern">Plug-in Pattern</a>, the <a href="http://ctrl-shift-b.blogspot.com/2005/10/microsoft-provider-model.html">Microsoft Provider Model</a>, and other variant patterns which enable portions of a component’s behavior to be fulfilled externally.</p>
<h4>Inverting Concerns</h4>
<p>Inverting concerns, better known as Inversion of Control, refers to the process of moving a concern outside of an established boundary. Some uses for inversion of concerns include effecting aspect separation, minimizing non-essential processes, decoupling components from specific abstraction strategies, or relocating responsibilities to infrastructure components. Some specific applications would include alleviating responsibilities pertaining to hardware interaction, work-flow management, registration processes, or obtaining dependencies.</p>
<p>Figure 12 depicts an inversion of concerns process where both a presentation component and a domain component have had concerns moved to infrastructure level components:</p>
<p><a href="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/IoC1.png"><img title="IoC1" alt="" src="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/IoC1.png" width="532" height="314" /></a></p>
<p>Figure 12</p>
<p>One example where inversion of concerns can be seen is in the use of the <a href="http://en.wikipedia.org/wiki/Template_method">Template Method</a> pattern. This pattern is used to generalize the behavior of a process in order to allow variation through inheritance. When applying this pattern to an existing component, the steps performed by the desired process would be generalized and encapsulated in a base class. The existing component would then inherit from the new base class, maintaining only specialized behavior. Other types would then be free to inherit from the base class to provide variant implementations. This would be an example of inverting the concerns of an algorithm sequence.</p>
<p>Another example of inverting concerns can be observed when converting an interactive console application to a GUI application. A typical interactive console application provides a main loop which prompts the user for information and waits for data to be entered. When converted to a GUI application, the main control of the program is generally provided by infrastructure components, and notification of user interaction is accomplished using the <a href="http://en.wikipedia.org/wiki/Observer_Pattern">Observer Pattern</a>. This inverts the main control of the user interaction process by relying on the application infrastructure or hosting environment for these concerns.</p>
<p>Dependency Injection is a term applied to the inversion of concerns which relate to obtaining external dependencies. This term was conceived to more clearly describe the behavior of a class of frameworks concerned with this form of inversion. The goal of dependency injection is to separate the concerns of how a dependency is obtained from the core concerns of a boundary. This improves reusability by enabling components to be supplied with dependencies which may vary depending on context.</p>
<p>The process of dependency injection generally involves the roles of container, dependency, and recipient.</p>
<p>The role of container is occupied by a component responsible for assigning dependencies to a recipient component. Containers are generally implemented using the <a href="http://en.wikipedia.org/wiki/Factory_pattern">Factory Pattern</a>to allow creation of the recipient and dependency components.</p>
<p>The role of dependency is occupied by the resource being provided to the recipient. Containers are often implemented to allow existing objects to be registered for use as a dependency, or to create new instances when required.</p>
<p>The role of recipient is occupied by the component receiving a dependency from the container. Recipients are required to declare dependencies using a strategy supported by the container. Strategies for determining dependency information generally employ the use of reflection to examine one or more of the recipient’s member types, and may require the use of attributes/annotations to implicitly or explicitly specify dependencies. A sequence diagram representing these roles is presented in Figure 13.</p>
<p><a href="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/IoC2.png"><img title="IoC2" alt="" src="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/IoC2.png" width="475" height="463" /></a></p>
<p>Figure 13</p>
<p>One example use of dependency injection would be to abstract caching functionality from a business component in lieu of using the <a href="http://en.wikipedia.org/wiki/Factory_pattern">Factory </a>or <a href="http://en.wikipedia.org/wiki/Factory_method_pattern">Factory Method</a> patterns. By supplying a recipient with a caching component using dependency injection, the recipient remains loosely coupled to the caching component without the added coupling to a specific factory.</p>
<p>Another example would be the use of dependency injection to control the number of caching components created in lieu of using the <a href="http://en.wikipedia.org/wiki/Singleton_pattern">Singleton Pattern</a>. This enables the application to ensure that only a single instance is used throughout the lifetime of an application, or to control which recipients receive which instances of the component. This also increases the ability to test components in isolation of their dependencies by enabling mock dependencies to be supplied rather than requiring singletons to be tested along with their consumers.</p>
<p>Components using patterns such as <a href="http://en.wikipedia.org/wiki/Factory_pattern">Factory</a>, <a href="file:///C:/Users/Derek/Documents/Blog%20Postings/Factory%20Method">Factory Method</a>, <a href="http://en.wikipedia.org/wiki/Abstract_factory_pattern">Abstract Factory</a>, <a href="http://en.wikipedia.org/wiki/Singleton_pattern">Singleton</a>,<a href="http://en.wikipedia.org/w/index.php?title=Plugin_pattern&amp;redirect=no">Plug-in</a>, <a href="http://en.wikipedia.org/wiki/Service_locator_pattern">Service Locator</a> to abstract the concerns of object creation or dependency retrieval are good candidates to consider for supplementing or replacement with dependency injection. By using dependency injection in lieu of, or in cooperation with these and other such patterns, consuming components can be completely abstracted from the particular abstraction strategy.</p>
<h4>The Exaggeration Exercise</h4>
<p>It is often the case that the negative consequences of a design choice, particularly those relating to scalability and reuse, do not become apparent until long after a system has become established. Problems with scalability and reuse are usually rooted in a lack of adherence to the principle of Separation of Concerns. One process that can aid in optimizing concerns is considering the impact of a design when applied under exaggerated circumstances. Through this exercise, the use of a system is hypothetically exaggerated beyond the system’s known expectations in order to reveal potential weaknesses in a design approach. For example, when designing an object model to be used by two existing systems, one might consider what the consequences would be if the object model were shared by fifty systems. By exaggerating the use of a design, poorly organized responsibilities will often become easier to identify.</p>
<p>To demonstrate this exercise, consider the following example concerning the creation of a new composite customer relationship management system:</p>
<p>Within a corporation, an IT department has been requested to create a custom CRM application which will allow disparate development teams to contribute specialized modules of functionality. The main customer related segments within the corporation will be sales, billing, and technical support, though there may be multiple development teams assigned to support the functions of each segment. It has been requested that the application present a main screen allowing customers to be queried by a number of different criteria including name, address, phone number, order number, and any registered product serial numbers. However, the resulting views and workflows should depend upon which business function is being carried out at a given time. For example, upon submitting customer search criteria, sales users may be displayed with a view pertaining to past purchasing trends, credit rating scores, and suggested up-selling scripts; while a billing user may be presented with a view displaying customer payment history, billing dispute history, and outstanding balances. An initial analysis reveals that there will be a total of three workflow variations resulting from a total of five different search criteria fields, and that there will be three backend systems involved in obtaining the information needed by all segments. Because the variations are low, the choice is made to centralize the main view, customer search functionality, and workflow initiation within a search module. It is understood that the addition of new search criteria and workflow needs will require modifications by the search module development team, but it is believed that these needs will be infrequent.</p>
<p>Applying the exaggeration exercise to this design choice might entail considering what consequences might ensue if the number of business segments or number of backend systems were increased to fifty. As a result of centralizing the search functionality and workflow initiation, increasing the scope of these concerns will also increase the responsibility and workload of the search module development team. This would include the scoping, analysis, design, coding, and testing of all new features and change requests related to these concerns. In turn, this would likely result in the need to increase the number of development resources required for the search module team. It is also likely that the same initial assumptions that lead to the consolidation of these concerns also informed other design decisions made for the search module. This may have led to design choices that would not readily accommodate such an increase in responsibilities, requiring some level of internal redesign to handle new concerns.</p>
<p>An outstanding problem that can be observed through this exercise is that the amount of work required by the search team is proportionally related to the number of business segments or workflows supported by the system. The fact that the initial solution doesn’t scale as the need increases can be an indication that concerns may have been inappropriately distributed throughout the system. The decision for consolidating search functionality and the resulting workflow decisions within the search module was the result of recognizing similarities between each use case. What was not given equal consideration was the fact that each use case had to be treated in a specialized way, and the fact that the number of possibilities has no true boundaries. Because the search screen provides a central function for many modules, it can be said to possess inherent infrastructure concerns. It should, therefore, be expected to provide the behavior that is common to all modules. However, the details of each case are not common, and can be considered the inherent concerns of each respective module. Upon recognizing the inherent responsibilities, an alternate approach might include the development of a framework to consolidate the common concerns, but enabling the distribution of each domain specific concern. Such an approach could be accomplished by requiring each module to provide an add-in which registers available search criteria and provides handling capabilities to invoke the corresponding workflow. A framework would then be responsible for presenting a consolidated view of the search criteria, and providing a generic infrastructure for associating each search criteria to its corresponding workflow handler. By using this approach, the search module can be designed to accommodate an unlimited number of use cases.</p>
<p>While the exaggeration exercise can be useful in creating highly scalable designs, this is only a byproduct of its primary goal which is the achievement of optimal Separation of Concerns. The exaggeration exercise might be compared to the medical practice of taking a patient’s temperature to test for symptoms of a possible underlying problem. This exercise attempts to identify problems pertaining to separation of concerns by examining the scalability aspect of a potential design. This might be compared to using a magnifying glass to look at the details of a design as depicted in Figure 14.</p>
<p><a href="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/magnify.jpg"><img title="magnify" alt="" src="http://www.aspiringcraftsman.com/wordpress/wp-content/uploads/2008/01/magnify.jpg" width="362" height="435" /></a></p>
<p>Figure 14</p>
<p>It is through the exaggeration of a design’s actual scope that small problems are magnified for easier identification. Once identified, it may then be determined what course of action should be taken.</p>
<h4>Separation Anxiety</h4>
<p>Applying the principle of separation of concerns often involves advanced concepts and constructs which bring a certain level of complexity to the application beyond that of merely addressing the domain concerns of the application. For developers inexperienced in these programming techniques the reaction falls within the spectrum of enthusiastic excitement over the opportunity to add to one’s repertoire of design skills, and an adverse reaction to the additional amount of complexity involved in getting the job done in the most expedient way possible. These techniques often lead inexperienced or more tactical-minded developers to characterize such designs as “overly-complex” or “over-engineered” based upon their frustrations in first learning, and then maneuvering through such architectures on a day-to-day basis. Furthermore, there is often an ever-present pressure from project managers, product managers, upper level management, marketing, or end users for instant gratification which tends to encourage and reward expediency over thoughtful design. These conditions can present obstacles to developing good designs beyond merely solving the technical problems.</p>
<p>While designs which promote separation of concerns often add complexity to an application, it should be pointed out that they also remove the complexity that is generally associated with a lack of separation of concerns. For many applications, the trade-off is often between ordered complexity and disordered complexity. Applications which do not exhibit an appropriate amount of separation of concerns are often difficult to learn due to the need to understand the whole before understanding the part, and difficult to maintain and extend. Highly complex, yet poorly modularized applications also have the effect of causing high turnover in development staff (which tends to further compound design and implementation problems), or attracting individuals who have an aversion to change and seek to build their career by being the indispensible “master of the maze” within their organization. Development teams should certainly not seek complexity for complexity’s sake (unless entering an obfuscation contest), but the notion that avoiding advanced design concepts equates to avoiding complexity should be dispelled.</p>
<h4>Conclusion</h4>
<p>Put simply, the goal of the principle of separation of concerns is order. By ensuring elements within a system adhere to a single and unique purpose, complex systems can be designed which maximize productivity and maintainability.</p>
]]></content:encoded>
			<wfw:commentRss>http://bookcold.com/2010/07/565/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TechNet:项目管理实践系列文章</title>
		<link>http://bookcold.com/2010/07/564</link>
		<comments>http://bookcold.com/2010/07/564#comments</comments>
		<pubDate>Thu, 22 Jul 2010 06:13:53 +0000</pubDate>
		<dc:creator>bookcold</dc:creator>
				<category><![CDATA[程序设计]]></category>
		<category><![CDATA[每日构建]]></category>
		<category><![CDATA[版本控制]]></category>
		<category><![CDATA[管理]]></category>
		<category><![CDATA[项目]]></category>

		<guid isPermaLink="false">http://bookcold.com/2010/07/564</guid>
		<description><![CDATA[<p>项目管理实践一、工欲善其事，必先利其器</p> <p>项目管理实践二、源代码控制【Source Control Using VisualSVN Server and Tortois】</p> <p>项目管理实践三、每日构建【Daily Build Using CruiseControl.NET and MSBuild】</p> ]]></description>
			<content:encoded><![CDATA[<p><a href="http://technet.microsoft.com/zh-cn/ff806226.aspx" target="_blank">项目管理实践一、工欲善其事，必先利其器</a></p>
<p><a href="http://technet.microsoft.com/zh-cn/ff806292.aspx" target="_blank">项目管理实践二、源代码控制【Source Control Using VisualSVN Server and Tortois】</a></p>
<p><a href="http://technet.microsoft.com/zh-cn/ff806311.aspx" target="_blank">项目管理实践三、每日构建【Daily Build Using CruiseControl.NET and MSBuild】</a></p>
]]></content:encoded>
			<wfw:commentRss>http://bookcold.com/2010/07/564/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>支撑vs2010的MySql连接器</title>
		<link>http://bookcold.com/2010/07/563</link>
		<comments>http://bookcold.com/2010/07/563#comments</comments>
		<pubDate>Mon, 19 Jul 2010 03:10:35 +0000</pubDate>
		<dc:creator>bookcold</dc:creator>
				<category><![CDATA[程序设计]]></category>
		<category><![CDATA[语言]]></category>
		<category><![CDATA[Mysql]]></category>
		<category><![CDATA[Visual Studio 2010]]></category>

		<guid isPermaLink="false">http://bookcold.com/2010/07/563</guid>
		<description><![CDATA[<p>目前官方稳定版本的Connector/Net 6.2.3不支持vs2010，因此需要下载6.3.2 beta版的Connector！</p> <p> </p> <p>下载地址：http://dev.mysql.com/downloads/connector/net/#downloads</p> <p>下载完成后vs2010中就有了Mysql的支持：</p> <p></p> ]]></description>
			<content:encoded><![CDATA[<p>目前官方稳定版本的Connector/Net 6.2.3不支持vs2010，因此需要下载6.3.2 beta版的Connector！</p>
<p><a href="http://bookcold.com/wp-content/uploads/2010/07/image.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://bookcold.com/wp-content/uploads/2010/07/image_thumb.png" width="244" height="55" /></a> </p>
<p>下载地址：<a href="http://dev.mysql.com/downloads/connector/net/#downloads">http://dev.mysql.com/downloads/connector/net/#downloads</a></p>
<p>下载完成后vs2010中就有了Mysql的支持：</p>
<p><a href="http://bookcold.com/wp-content/uploads/2010/07/image1.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://bookcold.com/wp-content/uploads/2010/07/image_thumb1.png" width="303" height="176" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://bookcold.com/2010/07/563/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google MapReduce &amp; Google File System</title>
		<link>http://bookcold.com/2010/07/555</link>
		<comments>http://bookcold.com/2010/07/555#comments</comments>
		<pubDate>Fri, 16 Jul 2010 12:28:42 +0000</pubDate>
		<dc:creator>bookcold</dc:creator>
				<category><![CDATA[数据库系统]]></category>
		<category><![CDATA[NoSQL]]></category>

		<guid isPermaLink="false">http://bookcold.com/?p=555</guid>
		<description><![CDATA[<p>Google Map Reduce</p> <p>英文原文链接: Google Map Reduce 译文原文链接: Google MapReduce中文版</p> <p>Google File System</p> <p>英文原文地址: Google File system 译文原文地址: The Google File System中文版</p> ]]></description>
			<content:encoded><![CDATA[<p><strong>Google Map Reduce</strong></p>
<p>英文原文链接: <a href="http://labs.google.com/papers/mapreduce.html">Google Map Reduce</a><br />
译文原文链接: <a href="http://blademaster.ixiezi.com/2010/03/27/google-mapreduce%E4%B8%AD%E6%96%87%E7%89%88/">Google MapReduce中文版</a></p>
<p><strong>Google File System</strong></p>
<p>英文原文地址: <a href="http://labs.google.com/papers/gfs.html">Google File system</a><br />
译文原文地址: <a href="http://blademaster.ixiezi.com/2010/03/27/the-google-file-system%E4%B8%AD%E6%96%87%E7%89%88/">The Google File System中文版</a></p>
]]></content:encoded>
			<wfw:commentRss>http://bookcold.com/2010/07/555/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>云计算思维导图</title>
		<link>http://bookcold.com/2010/07/554</link>
		<comments>http://bookcold.com/2010/07/554#comments</comments>
		<pubDate>Wed, 14 Jul 2010 06:37:05 +0000</pubDate>
		<dc:creator>bookcold</dc:creator>
				<category><![CDATA[网络]]></category>
		<category><![CDATA[Cloud Computing]]></category>

		<guid isPermaLink="false">http://bookcold.com/2010/07/554</guid>
		<description><![CDATA[<p> </p> </p> <p>&#160;</p> <p>来自：http://broadcast.oreilly.com/2010/06/cloud-computing-mind-map.html</p> ]]></description>
			<content:encoded><![CDATA[<p><a href="http://bookcold.com/wp-content/uploads/2010/07/CloudComputing.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Cloud-Computing" border="0" alt="Cloud-Computing" src="http://bookcold.com/wp-content/uploads/2010/07/CloudComputing_thumb.jpg" width="444" height="398" /></a> </p>
</p>
<p>&#160;</p>
<p>来自：<a href="http://broadcast.oreilly.com/2010/06/cloud-computing-mind-map.html">http://broadcast.oreilly.com/2010/06/cloud-computing-mind-map.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://bookcold.com/2010/07/554/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>超出图灵机的云计算</title>
		<link>http://bookcold.com/2010/07/551</link>
		<comments>http://bookcold.com/2010/07/551#comments</comments>
		<pubDate>Sat, 10 Jul 2010 03:29:24 +0000</pubDate>
		<dc:creator>bookcold</dc:creator>
				<category><![CDATA[网络]]></category>
		<category><![CDATA[Cloud Computing]]></category>

		<guid isPermaLink="false">http://bookcold.com/2010/07/551</guid>
		<description><![CDATA[云计算(李德毅院士) View more presentations from ikewu83. </p> ]]></description>
			<content:encoded><![CDATA[<div style="width: 425px" id="__ss_4680035"><strong style="margin: 12px 0px 4px; display: block"><a title="云计算091124(李德毅院士)" href="http://www.slideshare.net/ikewu83/091124">云计算(李德毅院士)</a></strong><object id="__sse4680035" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=091124-100705030155-phpapp01&amp;stripped_title=091124" /><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><embed name="__sse4680035" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=091124-100705030155-phpapp01&amp;stripped_title=091124" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object>
<div style="padding-bottom: 12px; padding-left: 0px; padding-right: 0px; padding-top: 5px">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/ikewu83">ikewu83</a>.</div>
</p></div>
]]></content:encoded>
			<wfw:commentRss>http://bookcold.com/2010/07/551/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
<!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->