﻿<?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>BlogJava-Java Stop Here-文章分类-Design</title><link>http://www.blogjava.net/faithwind/category/14485.html</link><description>Love Java ,because you are my first lady !^_^</description><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 03:21:14 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 03:21:14 GMT</pubDate><ttl>60</ttl><item><title>用XML和SQL 2000来管理存储过程调用</title><link>http://www.blogjava.net/faithwind/articles/65800.html</link><dc:creator>黑咖啡</dc:creator><author>黑咖啡</author><pubDate>Fri, 25 Aug 2006 06:42:00 GMT</pubDate><guid>http://www.blogjava.net/faithwind/articles/65800.html</guid><wfw:comment>http://www.blogjava.net/faithwind/comments/65800.html</wfw:comment><comments>http://www.blogjava.net/faithwind/articles/65800.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/faithwind/comments/commentRss/65800.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/faithwind/services/trackbacks/65800.html</trackback:ping><description><![CDATA[
		<p>创建多个带有不同参数的存储过程（stored procedure）来完成同一个任务总是一个很大的负担。利用XML字符串向你的存储过程发送参数就能够简化这个任务；这也让COM组件的设计更简单。</p>
		<p>实现这个目的的方法是将你的参数作为一个XML字符串来传递，并剖析XML来取回你所需要的数据，然后继续实现你所需要集成的功能。你不仅可以通过XML来获取一些参数，你还可以对XML所创建的DOM文档运行查询，以此来封装多个存储过程。我会提供一些例子，告诉你如果实现这个目的，并简要地描述每个例子。</p>
		<p>在本例里，为了更新一个Customer表格里的姓名字段，我会传递几个参数。为了获得<i>customerid</i>（身份列）和新的姓名字段，XML会被剖析。我传递给过程的XML字串就像下面的这样：</p>
		<p>
				<font color="#0066ff">&lt;root&gt;&lt;Customer&gt;&lt;customerid&gt;3&lt;/customerid&gt;&lt;name&gt;Acme<br /> Inc.&lt;/name&gt;&lt;/Customer&gt;&lt;/root&gt;</font>
		</p>
		<p>要被创建的存储字段就像下面的这样：</p>
		<p>
				<font color="#0066ff">
						<br />CREATE PROCEDURE update_Customer (@xmldatavarchar(8000)) AS<br />DECLARE @customeridint<br />DECLARE @customernamevarchar(50)<br />DECLARE @xmldata_idint<br /><br />EXEC sp_xml_preparedocument @xmldata_id OUTPUT, @xmldata, ''<br /><br />SELECT @customerid = customerid, @customername = [name] FROM<br /> OPENXML(@xmldata_id, '//Customer', 2) WITH (customeridint, [name]<br /> varchar(50))<br /><br />EXEC sp_xml_removedocument @xmldata_id<br /><br />UPDATE Customer SET Customer.[name] = ISNULL(@customername, Customer.[name])<br />WHERE Customer.tblID = @customerid</font>
				<br />
				<br />
		</p>
		<p>这个过程首先就声明我们将要用到的变量会保存相关信息。在此之后，DOM文档被打开，一个“句柄（handle）”会被返回到<i>sp_xml_preparedocument</i>调用的第一参数里。</p>
		<p>这个调用的第二个参数是用于新DOM文档的XML源文件。这个“句柄”是在进行OPENXML调用的时候用来从DOM里查询信息的。OPENXML调用的第二个参数是父节点的一个Xpath映射，这些父节点包含有要被执行的数据。</p>
		<p>第三个参数（2）指明，以元素为中心的映射会被使用。WITH子句为被剖析的数据提供了数据列集（rowset）格式，<i>sp_xml_removedocument</i>调用会删掉DOM文档的源文件。</p>
		<p>在下面这个例子里，我会传递一系列用户ID，用以删除多个数据列。下面就是XML字符串的内容：</p>
		<p>
				<br />
				<font color="#0066ff">&lt;root&gt;&lt;Customer&gt;&lt;customerid&gt;1&lt;/customerid&gt;&lt;/Customer&gt;&lt;Customer&gt;&lt;customerid&gt;<br />2&lt;/customerid&gt;&lt;/Customer&gt;&lt;Customer&gt;&lt;customerid&gt;3&lt;/customerid&gt;&lt;/Customer&gt;<br />&lt;/root&gt;</font>
				<br />
				<br />
		</p>
		<p>相应的存储过程看起来就像下面这样：<br /><font color="#0066ff">. . .<br /><br />EXEC sp_xml_preparedocument @xml_id OUTPUT, @xmldata, ''<br /><br />DELETE FROM Customer WHERE Customer.tblID IN (SELECT customerid FROM<br /> OPENXML(@xmldata_id, '//Customer', 2) WITH (customeridint))<br /><br />. . .</font><br /></p>
		<p>有了这个存储过程就不再需要创建一个冗长的SQL查询字符串，用以在ADO里传递或者多次调用一个存储过程了。这也会消除多次调用对网络流量所造成的影响。</p>
		<p>正如你能够看到的，微软的SQL 2000让整个过程稍稍简单了一点。要记住，这一方法的不足之处在于：在SQL 2000进行XML任务的时候，将XML作为一个参数发送会被限制到8,000字符。和以往一样，不要忽视了精心策划的好处。</p>
		<p>访问MSDN库能够获得更多关于<a href="http://clickthru.online.com/Click?q=31-V_YRIjMoD08KqaPyEAGgqV1--DdR" target="_blank"><font color="#002c99">OPENXML</font></a>、<a href="http://clickthru.online.com/Click?q=46-19zwInpuSNNCjsXa2Z5M53GkJkPR" target="_blank"><font color="#002c99">sp_xml_preparedocument</font></a>以及<a href="http://clickthru.online.com/Click?q=5b-5LOwIBKuUX91bmbxREGSDSVbMvyR" target="_blank"><font color="#002c99">sp_xml_removedocument</font></a>的信息。</p>
		<p> </p>
<img src ="http://www.blogjava.net/faithwind/aggbug/65800.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/faithwind/" target="_blank">黑咖啡</a> 2006-08-25 14:42 <a href="http://www.blogjava.net/faithwind/articles/65800.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据库设计中的敏捷方法</title><link>http://www.blogjava.net/faithwind/articles/65796.html</link><dc:creator>黑咖啡</dc:creator><author>黑咖啡</author><pubDate>Fri, 25 Aug 2006 06:41:00 GMT</pubDate><guid>http://www.blogjava.net/faithwind/articles/65796.html</guid><wfw:comment>http://www.blogjava.net/faithwind/comments/65796.html</wfw:comment><comments>http://www.blogjava.net/faithwind/articles/65796.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/faithwind/comments/commentRss/65796.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/faithwind/services/trackbacks/65796.html</trackback:ping><description><![CDATA[
		<strong>0 引言</strong>
		<p>在过去几年中，我们将敏捷方法应用于数据库设计中。我们总结出一些技巧，使得当应用程序发展时，数据库也能够进化，这是敏捷方法的一个重要属性。我们的方法是通过持续集成以及自动重构，通过数据库管理人员（DBA）和应用开发人员的紧密合作。这些技巧在应用开发的各个时期都有效。<br /><br /><b>1敏捷方法学</b></p>
		<p>近年来，出现了一种新的软件开发方法学—敏捷方法学。这给数据库设计提出了一些新的、巨大的需求。这些需求的一个中心就是进化设计。在一个敏捷项目中，需要假定我们并不能事先确定系统的需求。因此在项目的初期有一个详细设计阶段的想法是不现实的。系统的设计必须随着软件的变化而进化。敏捷方法，尤其是极限编程（XP），通过一些实践使这种进化设计成为可能。在数据库设计采用敏捷方法，反复迭代。 <br /><br />许多人会怀疑敏捷方法能否用于有大型数据库组件的系统。但我们的确使用了许多敏捷和XP技巧，用于解决基于大型数据库的项目中的进化与迭代问题。<br /><br />本文将介绍一些在数据库设计采用敏捷方法的实践。当然，这并不是说我们已经完全解决了数据库进化的问题，但是我们想提供一些行之有效的方法。<br /><br /><b>2 积极应对变化<br /></b>敏捷编程的一个显著特点就是它面对变化的态度。对软件过程的一般解释是尽早理解需求，停止需求的变动，将这些需求作为设计的基础，停止设计的变动，然后开始构筑体系。这就是瀑布方法--基于计划的生命周期。<br /><br />这种方法通过大量的前期工作来减少变化。一旦前期工作完成，需求变化会引起很大的问题。因此当需求变化时，这样的方法就会有很大的问题，因此需求变动是这种过程的一个很大的问题。<br /><br />而敏捷编程却以另外一种方式来面对变化。拥抱变化，甚至允许在项目开发的后期发生变化。尽管变化会被控制，但是这种态度会允许尽可能多的变化。变化部分来自于项目需求的不稳定，部分来自于要支持变化的商业环境来面对竞争压力。<br /><br />为了做到这样，必须采取不同的设计态度。设计不仅仅是一个阶段—-在开始建筑之前就大部分完成的一个阶段；设计是一个持续的过程，与编码、测试甚至发布相关。这是计划设计与进化设计的不同之处。敏捷方法的一个重要贡献是提出了在可控制方式下的进化设计。因此不是由于设计没有预先计划好，产生了混乱。敏捷方法提供了控制进化设计和使其可行的技巧。<br /><br />敏捷方法的一个重要特点就是迭代式开发，即整个项目生命周期中运行多个完整的软件生命周期循环。敏捷过程在每次迭代中都会度过一个完整的生命周期。迭代可以完成最终产品的需求子集中编码、测试以及集成代码。敏捷方法迭代时间较短，通常是一周到两个月之间，而且我们更倾向于更短的迭代周期。<br /><br />当使用敏捷方法时，最大的问题就是数据库如何进行进化设计。许多人认为数据库设计是前期计划的工作，而在后期改变数据库设计计划会引起应用软件的崩溃；在配置以后改变数据库设计计划会导致数据迁移问题。<br /><br />在过去三年我们参加了一个大型的项目，其中用到了切实可行的进化设计的方法。该项目包括100人的项目组， 200多张表格，数据库在一年半的最初开发中一直在进化，甚至在为多用户分发的过程中也在进化。一开始我们一个月迭代一次，过了几个月之后变为2周迭代一次。<br /><br />随着我们将这些经验推广到项目中越来越多的部分，从越来越多的案例中获得经验。同时，我们也从其他敏捷项目中吸收了一些经验。<br /><br /><b>2.1限制条件<br /></b>在讲述实践方法之前，必须指出我们并没有解决所有的数据库进化设计问题，特别是：<br /><br />* 我们是为单独的应用设计一个应用数据库，而不是试图集成多个数据库；<br /><br />* 我们没有做到24*7的数据库更新。<br /><br />虽然很多人认为我们无法解决这个问题，但其实这些问题是可以解决的。当然这需要进一步的工作，光说是不能解决问题的。<br /><br /><b>3 实践<br /></b>我们有关于数据库进化设计的方法依赖于一些重要的实践。<br /><br /><b>3.1数据库管理人员与开发人员紧密合作<br /></b>敏捷方法的一个重要原则就是拥有不同技能和背景的人能够紧密合作。正式的会议和文档不能达到交流效果，因此他们需要一直一起工作，亲密合作。所有的项目组成员都需要紧密合作：系统分析人员，项目经理，行业专家，开发人员以及数据库管理人员（DBA）<br /><br />开发人员的每项工作可能都需要DBA的帮助。开发人员和DBA需要考虑是否需要对数据库计划做很大的改变。开发人员向DBA咨询如何应对变化：开发人员知道需要什么新的功能，而DBA对应用中的数据有全局的观念。<br /><br />为了达到亲密合作的效果，DBA必须使自己易于接近。DBA需要留出几分钟的时间，让开发人员来提问。必须确保DBA和开发人员坐在一起，这样他们就很容易沟通。同时必须确保应用设计会议是公开的，这样DBA可以随时加入进来。在很多情况下我们发现人们在DBA和应用开发人员之间建立屏障，这些屏障必须去除，这样进化数据库设计才有可能。<br /><br /><b>3.2每个项目组成员都有自己的数据库实例<br /></b>进化设计认为人们通过尝试来进行学习。在编程期间开发人员在如何实施某个特征，应用某个首选的方案之前做一些试验。数据库设计也是如此。因此，每个开发人员都有自己用来试验的实例，而不必影响其它人，这一点很重要。这样每个人都可以根据自己的需要进行试验。<br /><br />许多DBA专家认为多个数据库是一种麻烦，不易于实际应用，但我们发现操作一百个左右的数据库是很容易的。当然其中很重要的是拥有便利的工具，使你像操作文件一样操作数据库。<br /><br /><b>3.3开发人员数据库经常集成到共享主数据库<br /></b>尽管开发人员可以在他们自己的空间频繁试验，但是将不同的工作定期汇合也是很重要的。应用开发需要一个共享主数据库，所有的工作都汇集于此。当开发人员开始工作时他们从主数据库获取拷贝到自己的工作空间，进行操作和修改，然后将变化反馈进入主数据库。我们的规定是每个开发人员要每天提交汇合一次。<br /><br />假设开发人员上午10点开始一项开发任务，这项任务的一部分是改变数据库计划。如果这种改变很简单，如增加一个字段，他就可以自己决定。通过数据字典的帮助，开发人员还必须确保他想增加的字段数据库中没有。但是如果他与DBA讨论这种可能的变化，那么工作就要简单的多。<br /><br />当他准备开始时，先从主数据库中获取一份拷贝，这样就可以自由地改变数据库计划和代码。因为他使用的是自己的数据库实例，所以不会影响别人。在某个时候，如下午3点，他很清楚需要什么样的数据库变化，甚至此时他还没有完全做完他的编码工作。这时他找到DBA，告诉他想要的变化。这时DBA可以提出开发人员没有考虑到的问题。当然大多数时候都很好，DBA同意这种变化（通过一个或多个数据库重构）。DBA使变化马上发生（除非他们是破坏性的变化），这样开发人员可以继续他的工作，在任何时候提交代码，因为DBA已经将这些变化发送给主数据库。<br /><br />可以将这个原则看作类似于持续集成，持续集成常用于源码管理。实际上这就是将数据库看作是另一种源代码。因为配置管理系统象控制源代码一样控制主数据库。只要我们构建成功，数据库和源代码一起被送入配置管理系统，这样我们就有两者完整和同步的版本历史。<br /><br />对于源代码来说，集成中的问题被源代码控制系统处理。对于数据库来说，要做的工作稍微多一些。所有数据库的变化都需要妥善处理，如自动化数据库重构。此外DBA需要审视任何数据库变化，保证其符合整个数据库的计划。为了使这项工作做的比较平稳，在集成的过程中不应该出现大的变化--因此需要DBA与开发人员紧密合作。<br /><br />我们强调经常性的小集成，因为它比非经常性的大集成容易得多。集成的复杂度会随着集成的规模呈几何级度增加。因此做许多小的变化在实践中更易于实现，当然这看上去与直觉相抵触。<br /><br /><b>3.4数据库包含计划和测试数据<br /></b>当提到数据库的时候，我们并不仅仅指数据库计划，而且还包括相当规模的数据。这些数据包括应用所需的标准数据，如全国所有的省份名，以及一些样本客户的样本数据。<br /><br />数据的作用：<br /><br />1、 易于测试<br /><br />使用大量的自动化测试可以帮助稳定应用的发展。这样的测试在敏捷方法里是常用的方法。为了使这些测试有效进行，很理智的方法是在一个有样本测试数据的基础上工作，这样所有的测试可以在程序正式进行之前完成。<br /><br />2、测试数据库的迁移<br /><br />除了测试代码之外，样本测试数据允许我们测试数据库的迁移，当改变了数据库的计划后，我们还必须保证所有的计划变更也能够处理样本数据。<br /><br />在大多数项目中这些样本数据是虚构的。然而在某些项目中人们使用实际数据作为例子。在这些情况下，数据从先前由自动化数据迁移代码的系统中提取出来。很明显不能马上迁移所有的数据，因为在早期迭代中数据库只有小部分建立起来。但是我们希望当应用和数据库发展时，改变迁移代码。这样不仅能够尽早解决迁移问题，也使行业专家易于处理这个正在开发的系统。因为有他们熟悉的数据，所以他们会指出可能给数据库和应用设计带来问题的地方。因此我们建议在项目的早期迭代中引入实际数据。<br /><br /><b>3.5所有的变化应该数据库重构<br /></b>重构技术就是应用所有可控技术来改变现有的代码基础。与此类似我们定义了数据库重构也给数据库的改变提供了类似的控制。<br /><br />数据库重构的不同之处在于它必须将三种不同的变化同时完成： <br /><br />* 改变数据库计划<br /><br />* 进行数据迁移<br /><br />* 改变数据库存取代码<br /><br />于是当描述数据库重构时，我们必须描述变化的三个方面，并确保在应用另一个重构之前完成了这三种变化。<br /><br />我们必须文档化不同的数据库重构，因此我们还不能详细描述他们。然而这里有几点需要指出：像代码重构一样，数据库重构非常微小。概念链一系列微小的变化，数据库和代码很相似。变化的三个属性使保持小的变化更加重要。<br /><br />许多数据库重构，如增加一个字段，可以不必更新所有存取系统的代码来完成。但是如果在使用新计划之前并不了解它，该字段将会无用，因为新计划不知道其变化之处。许多变化，没有考虑整个系统计划，我们称之为破坏性变化，如将一个已经存在的空值列设置为非空。破坏性变化需要多加留心，留心的程度依赖于包含破坏性的程度。一个小破坏性的例子是将一个已经存在的空值列设置为非空，在这种情况下你可以蒙着头做。<br /><br />而重构将考虑数据库中空值数据。开发人员将更新数据库映射代码，因此更新不会破坏其它人的代码；如果偶然会破坏，开发人员将在建立和使用测试时发现问题。<br /><br />将一个经常使用的表分成两个是一种更复杂的破坏。在这种情况中提前让所有人知道变化到来很重要，这样他们可以有所准备。此外应该在一个更安全的时刻来实施变化。<br /><br />这里面很重要的一点是选择适用于你做出的变化的过程。<br /><br /><b>3.6自动重构<br /></b>在代码世界中许多语言能够实现自动重构。在计划变化和数据迁移过程中，这种自动化对于数据库也非常重要。因此每个数据库重构都可以通过编写SQL DDL（对于计划变化）和DML（对于数据迁移）来完成。这些变化不是通过手工实现，而是通过一些SQL语句来自动实现变化。<br /><br />一旦完成代码，我们保存这些代码文件来产生数据库变化的完整的变化记录，作为数据库重构的结果。我们于是可以更新任何实例到最新的主数据库，通过运行在我们拷贝主数据库来产生更早的数据库实例的变化记录。<br /><br />自动化变化的序列化是对于持续集成和迁移产品数据库的一个基本功能。<br /><br />为了最后产品数据库我们并不在常规迭代周期中实施变化。我们在每一个发布之间建立完整的数据库重构变化日志。毫无疑问，这是一个巨大的变化，我们必须离线实施该变化。在实际应用之前先测试迁移计划绝对是明智之举。迄今为止，这项技术相当管用。通过将大变化分解为小的简单的变化，我们可以对产品数据进行大的变化，同时又不会给我们太多的麻烦。套用兵法中的一句话，就是“化整为零”。<br /><br />除了自动化向前的变化，我们也要考虑重构时向后的变化。如果能够做到这样就可以回到以前的数据库状态。在我们的项目中并没有这样做，因为没有这个需求，但这同样是很重要的基本原则。<br /><br /><b>3.7自动地更新所有开发人员的数据库<br /></b>人们变化和更新主数据库，但是如何发现主数据库已经发生变化？在传统的持续集成有源代码的环境中，开发人员在提交变化之前先更新主数据库。这样他们就可以在提交变化给共享主数据库之前，解决他们自己的机器上的问题。<br /><br />每次主数据库发生改变时，我们都要更新开发人员的数据库。当主数据库发生变化时，我们自动化更新所有项目成员的数据库。相同的重构代码更新主数据库上的同时，自动更新成员数据库。也许有人认为在开发人员不知情的情况下，更新开发人员数据库会产生很多问题，但在实践中我们没发现什么问题。当然，这只在人们联网时管用。所以当开发人员离线时，必须尽快与主数据库重新保持同步。 <br /><br /><b>3.8清晰地分离所有的数据库获取代码<br /></b>为了理解数据库重构的结果，了解应用程序如何使用数据库也非常重要。如果SQL语句分布在代码基础周围，则很难这样去做。因此一个清晰的数据库获取层很重要，它用来显示数据库如何被使用，在哪里被使用。<br /><br />清晰的数据库层有很多好处。它减少了开发人员操纵数据库时需要使用SQL知识的地方，这样使对SQL语句不太熟悉的开发人员更易开发。对于DBA来说，给他提供了清晰的代码，可以清楚地了解数据库将如何使用。这也帮助准备索引、数据库优化，优化SQL语句，使DBA更好地理解数据库如何被使用。<br /><br /><b>4 变化法则<br /></b>如同任何实践一样，这些原则必须根据你特殊的环境变化。没有一成不变的项目，我们必须要应对变化。<br /><br /><b>4.1保持多个数据库在一个系统中<br /></b>简单项目也许只需要一个主数据库。但是复杂项目需要有多个数据库，即数据库系。如果在投入生产之前数据库必须分支，那么我们可以创建新的数据库系。数据库系类似于代码的分支，需要不同测试数据集来进行测试。<br /><br />当开发人员从主数据库中获取了一份拷贝，必须注册他们在修改哪个数据库系。当DBA更新主数据库某个数据库系时，同时更新了所有注册这个数据库系的开发人员的数据库。<br /><br /><b>4.2不需要专职的DBA<br /></b>所有这些听上去好像需要大量的工作，但它并不需要大量的人力资源。在最大的项目中，我们有30个开发人员，项目组规模100人（包括质量评价、分析人员和管理人员），我们大概有100多个不同系列的产品分布在各工作站上。但所有这些工作只需要一个专职DBA，只有两个编程人员业余帮忙。<br /><br />在小项目中甚至不需要专职DBA。当我们将这些技巧用于更小的项目--12人左右的小项目时，发现该项目不需要一个专职的DBA。与此相反，我们依靠两个对数据库感兴趣的开发人员业余处理DBA任务。<br /><br />这是自动化的功劳。如果对每项任务进行自动化处理，就可以用更少的人来完成更多的工作。<br /><br /><b>5辅助工具<br /><br /></b>数据库进化需要大量的重复性工作，我们可以开发一些简单工具来帮助我们解决大量的重复性工作。<br /><br />自动化的最有价值的地方就是有一个通用数据库任务简单代码集。自动化的任务包括：<br /><br />* 用户资料与现在管理员的资料一致<br /><br />* 创建新用户<br /><br />* 复制数据库计划并协同修改<br /><br />* 移动并合成数据库<br /><br />* 删除用户<br /><br />* 导出用户，这样项目组成员可以分发离线数据库备份。<br /><br />* 导入用户，这样项目组成员可以拥有数据库备份，导入数据库，创建新计划。<br /><br />* 导出基线，将主数据库进行备份，这是导出用户的一个特例。 <br /><br />* 创建不同计划的报告，以便比较。<br /><br />* 将计划与主计划作比较，这样开发人员就可以将他们本地拷贝与主数据库作比较<br /><br />* 列出所有的用户<br /><br />分析人员和质量评价人员常常会去看测试数据，并且需要改变他们。因此我们用VBA语句开发一个Excel应用程序，从数据库里面提取数据到Excel文件中，允许用户修改这个文件，修改后又返回到数据库中去。当然，也可以使用其他工具来浏览和编辑数据库的内容，但是我们使用excel，因为很多人熟悉它。<br /><br />项目组的所有成员应该很容易获取数据库设计的详细内容，从而发现什么表格可以获得，以及如何使用这些表格。我们建立了基于HTML的工具，使用servlets来查询数据库元数据。因此开发人员在添加字段之前，可以先通过搜索表和字段的元数据来看一看数据库中有没有这个字段。我们使用Erwin建模，将数据从Erwin提取到我们的元数据表中。<br /><br /><b>6 结束语<br /><br /></b>当然，这并不是敏捷方法在数据库设计中的全部应用，也不是数据库进化设计的全部，还有集成数据库和24*7小时实施以及其他一些没有解决的问题，数据库进化设计还需要进行进一步的研究工作。<br /></p>
<img src ="http://www.blogjava.net/faithwind/aggbug/65796.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/faithwind/" target="_blank">黑咖啡</a> 2006-08-25 14:41 <a href="http://www.blogjava.net/faithwind/articles/65796.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据库设计中的14个技巧</title><link>http://www.blogjava.net/faithwind/articles/65798.html</link><dc:creator>黑咖啡</dc:creator><author>黑咖啡</author><pubDate>Fri, 25 Aug 2006 06:41:00 GMT</pubDate><guid>http://www.blogjava.net/faithwind/articles/65798.html</guid><wfw:comment>http://www.blogjava.net/faithwind/comments/65798.html</wfw:comment><comments>http://www.blogjava.net/faithwind/articles/65798.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/faithwind/comments/commentRss/65798.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/faithwind/services/trackbacks/65798.html</trackback:ping><description><![CDATA[
		<p>
				<b>1. 原始单据与实体之间的关系</b>
				<br />
				<br />　　可以是一对一、一对多、多对多的关系。在一般情况下，它们是一对一的关系：即一张原始单据对应且只对应一个实体。在特殊情况下，它们可能是一对多或多对一的关系，即一张原始单据对应多个实体，或多张原始单据对应一个实体。这里的实体可以理解为基本表。明确这种对应关系后，对我们设计录入界面大有好处。 <br /><br />　　〖例1〗：一份员工履历资料，在人力资源信息系统中，就对应三个基本表：员工基本情况表、社会关系表、工作简历表。这就是“一张原始单据对应多个实体”的典型例子。 <br /><br />　　<b>2. 主键与外键</b><br /><br />　　一般而言，一个实体不能既无主键又无外键。在E－R 图中, 处于叶子部位的实体, 可以定义主键，也可以不定义主键(因为它无子孙), 但必须要有外键(因为它有父亲)。 <br /><br />　　主键与外键的设计，在全局数据库的设计中，占有重要地位。当全局数据库的设计完成以后，有个美国数据库设计专家说：“键，到处都是键，除了键之外，什么也没有”，这就是他的数据库设计经验之谈，也反映了他对信息系统核心(数据模型)的高度抽象思想。因为：主键是实体的高度抽象，主键与外键的配对，表示实体之间的连接。 <br /><br />　　<b>3. 基本表的性质</b><br /><br />　　基本表与中间表、临时表不同，因为它具有如下四个特性： <br /><br />　　(1) 原子性。基本表中的字段是不可再分解的。 <br /><br />　　(2) 原始性。基本表中的记录是原始数据（基础数据）的记录。 <br /><br />　　(3) 演绎性。由基本表与代码表中的数据，可以派生出所有的输出数据。 <br /><br />　　(4) 稳定性。基本表的结构是相对稳定的，表中的记录是要长期保存的。 <br /><br />　　理解基本表的性质后，在设计数据库时，就能将基本表与中间表、临时表区分开来。 <br /><br />　　<b>4. 范式标准</b><br /><br />　　基本表及其字段之间的关系, 应尽量满足第三范式。但是，满足第三范式的数据库设计，往往不是最好的设计。为了提高数据库的运行效率，常常需要降低范式标准：适当增加冗余，达到以空间换时间的目的。 <br /><br />　　〖例2〗：有一张存放商品的基本表，如表1所示。“金额”这个字段的存在，表明该表的设计不满足第三范式，因为“金额”可以由“单价”乘以“数量”得到，说明“金额”是冗余字段。但是，增加“金额”这个冗余字段，可以提高查询统计的速度，这就是以空间换时间的作法。 <br /><br />　　在Rose 2002中，规定列有两种类型：数据列和计算列。“金额”这样的列被称为“计算列”，而“单价”和“数量”这样的列被称为“数据列”。 <br /><br />　　表1 商品表的表结构 <br /><br />　　商品名称 商品型号 单价 数量 金额 <br /><br />　　电视机 29吋 2,500 40 100,000 <br /><br />　　<b>5. 通俗地理解三个范式</b><br /><br />　　通俗地理解三个范式，对于数据库设计大有好处。在数据库设计中，为了更好地应用三个范式，就必须通俗地理解三个范式(通俗地理解是够用的理解，并不是最科学最准确的理解)： <br /><br />　　第一范式：1NF是对属性的原子性约束，要求属性具有原子性，不可再分解； <br /><br />　　第二范式：2NF是对记录的惟一性约束，要求记录有惟一标识，即实体的惟一性； <br /><br />　　第三范式：3NF是对字段冗余性的约束，即任何字段不能由其他字段派生出来，它要求字段没有冗余。 <br /><br />　　没有冗余的数据库设计可以做到。但是，没有冗余的数据库未必是最好的数据库，有时为了提高运行效率，就必须降低范式标准，适当保留冗余数据。具体做法是：在概念数据模型设计时遵守第三范式，降低范式标准的工作放到物理数据模型设计时考虑。降低范式就是增加字段，允许冗余。 <br /><br />　　<b>6. 要善于识别与正确处理多对多的关系</b><br /><br />　　若两个实体之间存在多对多的关系，则应消除这种关系。消除的办法是，在两者之间增加第三个实体。这样，原来一个多对多的关系，现在变为两个一对多的关系。要将原来两个实体的属性合理地分配到三个实体中去。这里的第三个实体，实质上是一个较复杂的关系，它对应一张基本表。一般来讲，数据库设计工具不能识别多对多的关系，但能处理多对多的关系。 <br /><br />　　〖例3〗：在“图书馆信息系统”中，“图书”是一个实体，“读者”也是一个实体。这两个实体之间的关系，是一个典型的多对多关系：一本图书在不同时间可以被多个读者借阅，一个读者又可以借多本图书。为此，要在二者之间增加第三个实体，该实体取名为“借还书”，它的属性为：借还时间、借还标志(0表示借书，1表示还书)，另外，它还应该有两个外键(“图书”的主键，“读者”的主键)，使它能与“图书”和“读者”连接。 <br /><br />　　<b>7. 主键PK的取值方法</b><br /><br />　　PK是供程序员使用的表间连接工具，可以是一无物理意义的数字串, 由程序自动加1来实现。也可以是有物理意义的字段名或字段名的组合。不过前者比后者好。当PK是字段名的组合时，建议字段的个数不要太多，多了不但索引占用空间大，而且速度也慢。</p>
		<p>
				<b>8. 正确认识数据冗余</b>
				<br />
				<br />　　主键与外键在多表中的重复出现, 不属于数据冗余，这个概念必须清楚，事实上有许多人还不清楚。非键字段的重复出现, 才是数据冗余！而且是一种低级冗余，即重复性的冗余。高级冗余不是字段的重复出现，而是字段的派生出现。 <br /><br />　　〖例4〗：商品中的“单价、数量、金额”三个字段，“金额”就是由“单价”乘以“数量”派生出来的，它就是冗余，而且是一种高级冗余。冗余的目的是为了提高处理速度。只有低级冗余才会增加数据的不一致性，因为同一数据，可能从不同时间、地点、角色上多次录入。因此，我们提倡高级冗余(派生性冗余)，反对低级冗余(重复性冗余)。 <br /><br />　　<b>9. E－R图没有标准答案</b><br /><br />　　信息系统的E－R图没有标准答案，因为它的设计与画法不是惟一的，只要它覆盖了系统需求的业务范围和功能内容，就是可行的。反之要修改E－R图。尽管它没有惟一的标准答案，并不意味着可以随意设计。好的E－图的标准是：结构清晰、关联简洁、实体个数适中、属性分配合理、没有低级冗余。 <br /><br /><b>　　10. 视图技术在数据库设计中很有用</b><br /><br />　　与基本表、代码表、中间表不同，视图是一种虚表，它依赖数据源的实表而存在。视图是供程序员使用数据库的一个窗口，是基表数据综合的一种形式, 是数据处理的一种方法，是用户数据保密的一种手段。为了进行复杂处理、提高运算速度和节省存储空间, 视图的定义深度一般不得超过三层。 若三层视图仍不够用, 则应在视图上定义临时表, 在临时表上再定义视图。这样反复交迭定义, 视图的深度就不受限制了。 <br /><br />　　对于某些与国家政治、经济、技术、军事和安全利益有关的信息系统，视图的作用更加重要。这些系统的基本表完成物理设计之后，立即在基本表上建立第一层视图，这层视图的个数和结构，与基本表的个数和结构是完全相同。并且规定，所有的程序员，一律只准在视图上操作。只有数据库管理员，带着多个人员共同掌握的“安全钥匙”，才能直接在基本表上操作。请读者想想：这是为什么？ <br /><br />　　<b>11. 中间表、报表和临时表</b><br /><br />　　中间表是存放统计数据的表，它是为数据仓库、输出报表或查询结果而设计的，有时它没有主键与外键(数据仓库除外)。临时表是程序员个人设计的，存放临时记录，为个人所用。基表和中间表由DBA维护，临时表由程序员自己用程序自动维护。 <br /><br />　　<b>12. 完整性约束表现在三个方面</b><br /><br />　　域的完整性：用Check来实现约束，在数据库设计工具中，对字段的取值范围进行定义时，有一个Check按钮，通过它定义字段的值城。 <br /><br />　　参照完整性：用PK、FK、表级触发器来实现。 <br /><br />　　用户定义完整性：它是一些业务规则，用存储过程和触发器来实现。 <br /><br />　　<b>13. 防止数据库设计打补丁的方法是“三少原则”</b><br /><br />　　(1) 一个数据库中表的个数越少越好。只有表的个数少了，才能说明系统的E－R图少而精，去掉了重复的多余的实体，形成了对客观世界的高度抽象，进行了系统的数据集成，防止了打补丁式的设计； <br /><br />　　(2) 一个表中组合主键的字段个数越少越好。因为主键的作用，一是建主键索引，二是做为子表的外键，所以组合主键的字段个数少了，不仅节省了运行时间，而且节省了索引存储空间； <br /><br />　　(3) 一个表中的字段个数越少越好。只有字段的个数少了，才能说明在系统中不存在数据重复，且很少有数据冗余，更重要的是督促读者学会“列变行”，这样就防止了将子表中的字段拉入到主表中去，在主表中留下许多空余的字段。所谓“列变行”，就是将主表中的一部分内容拉出去，另外单独建一个子表。这个方法很简单，有的人就是不习惯、不采纳、不执行。 <br /><br />　　数据库设计的实用原则是：在数据冗余和处理速度之间找到合适的平衡点。“三少”是一个整体概念，综合观点，不能孤立某一个原则。该原则是相对的，不是绝对的。“三多”原则肯定是错误的。试想：若覆盖系统同样的功能，一百个实体(共一千个属性) 的E－R图，肯定比二百个实体(共二千个属性)的E－R图，要好得多。 <br /><br />　　提倡“三少”原则，是叫读者学会利用数据库设计技术进行系统的数据集成。数据集成的步骤是将文件系统集成为应用数据库，将应用数据库集成为主题数据库，将主题数据库集成为全局综合数据库。集成的程度越高，数据共享性就越强，信息孤岛现象就越少，整个企业信息系统的全局E—R图中实体的个数、主键的个数、属性的个数就会越少。 <br /><br />　　提倡“三少”原则的目的，是防止读者利用打补丁技术，不断地对数据库进行增删改，使企业数据库变成了随意设计数据库表的“垃圾堆”，或数据库表的“大杂院”，最后造成数据库中的基本表、代码表、中间表、临时表杂乱无章，不计其数，导致企事业单位的信息系统无法维护而瘫痪。 <br /><br />　　“三多”原则任何人都可以做到，该原则是“打补丁方法”设计数据库的歪理学说。“三少”原则是少而精的原则，它要求有较高的数据库设计技巧与艺术，不是任何人都能做到的，因为该原则是杜绝用“打补丁方法”设计数据库的理论依据。 <br /><br />　　<b>14. 提高数据库运行效率的办法</b><br /><br />　　在给定的系统硬件和系统软件条件下，提高数据库系统的运行效率的办法是： <br /><br />　　(1) 在数据库物理设计时，降低范式，增加冗余, 少用触发器, 多用存储过程。 <br /><br />　　(2) 当计算非常复杂、而且记录条数非常巨大时(例如一千万条)，复杂计算要先在数据库外面，以文件系统方式用C++语言计算处理完成之后，最后才入库追加到表中去。这是电信计费系统设计的经验。 <br /><br />　　(3) 发现某个表的记录太多，例如超过一千万条，则要对该表进行水平分割。水平分割的做法是，以该表主键PK的某个值为界线，将该表的记录水平分割为两个表。若发现某个表的字段太多，例如超过八十个，则垂直分割该表，将原来的一个表分解为两个表。 <br /><br />　　(4) 对数据库管理系统DBMS进行系统优化，即优化各种系统参数，如缓冲区个数。 <br /><br />　　(5) 在使用面向数据的SQL语言进行程序设计时，尽量采取优化算法。 <br /><br />　　总之，要提高数据库的运行效率，必须从数据库系统级优化、数据库设计级优化、程序实现级优化，这三个层次上同时下功夫。 <br /><br />　　上述十四个技巧，是许多人在大量的数据库分析与设计实践中，逐步总结出来的。对于这些经验的运用，读者不能生帮硬套，死记硬背，而要消化理解，实事求是，灵活掌握。并逐步做到：在应用中发展，在发展中应用。</p>
		<p>
		</p>
		<p>
		</p>
		<!--Here is the bottom-->
		<p> </p>
<img src ="http://www.blogjava.net/faithwind/aggbug/65798.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/faithwind/" target="_blank">黑咖啡</a> 2006-08-25 14:41 <a href="http://www.blogjava.net/faithwind/articles/65798.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>面向对象的关系数据库设计</title><link>http://www.blogjava.net/faithwind/articles/65792.html</link><dc:creator>黑咖啡</dc:creator><author>黑咖啡</author><pubDate>Fri, 25 Aug 2006 06:40:00 GMT</pubDate><guid>http://www.blogjava.net/faithwind/articles/65792.html</guid><wfw:comment>http://www.blogjava.net/faithwind/comments/65792.html</wfw:comment><comments>http://www.blogjava.net/faithwind/articles/65792.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/faithwind/comments/commentRss/65792.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/faithwind/services/trackbacks/65792.html</trackback:ping><description><![CDATA[北京市公路局系统使用的是Oracle 7.3关系数据库，即RDBMS。由于我们对整个工程使用了面向对象的软件工程(OOSE)开发方法学，所以数据库设计也是面向对象的。 <br /><br />一、 概念的区分 <br />　　有些人把面向对象的数据库设计（即数据库模式）思想与面向对象数据库管理系统(OODBMS) 理论混为一谈。其实前者是数据库用户定义数据库模式的思路，后者是数据库管理程序的思路。用户使用面向对象方法学可以定义任何一种DBMS数据库，即网络型、层次型、关系型、面向对象型均可，甚至文件系统设计也照样可以遵循面向对象的思路。 <br /><br />　　面向对象的思路或称规范可以用于系统分析、系统设计、程序设计，也可以用于数据结构设计、数据库设计。OOSE自上至下、自始至终地贯彻面向对象思路，是一个一气呵成的统一体。面向对象的数据库设计只是 OOSE 的一个环节。 <br /><br />二、 数据库设计的重要性 <br />　　一般数据库设计方法有两种，即属性主导型和实体主导型。属性主导型从归纳数据库应用的属性出发，在归并属性集合(实体)时维持属性间的函数依赖关系。实体主导型则先从寻找对数据库应用有意义的实体入手，然后通过定义属性来定义实体。一般现实世界的实体数在属性数 1/10 以下时，宜使用实体主导型设计方法。面向对象的数据库设计是从对象模型出发的，属于实体主导型设计。 <br /><br />　　一般数据库应用系统都遵循以下相关开发步骤：1设计应用系统结构；2 选择便于将应用程序与 DBMS 结合的DBMS体系结构，如RDBMS；3 根据应用程序使用的环境平台，选择适宜的DBMS(如Oracle)和开发工具(如PB)；4 设计数据库，编写定义数据库模式的SQL程序；5 编写确保数据正确录入数据库的用户接口应用程序；6 录入数据库数据；7 运行各种与数据库相关的应用程序，以确认和修正数据库的内容。 <br /><br />　　对以上各步骤，有几点需要说明： <br /><br />　　(1)这不是瀑布模型，每一步都可以有反馈。 <br /><br />　　在公路局系统中，以上各步不仅有反馈、有反复，还有并行处理。比如一些库表在数据录入时，另一些库表设计还在修改。这与我们的递增式开发方法有关，也与面向对象的特征有关。 <br /><br />　　(2)上述顺序不是绝对的，大多数场合是从第三步开始的。 <br /><br />　　(3)对大多数数据库应用系统来说，上述各步中最重要、最困难的不是应用系统设计而是数据库设计。 <br /><br />三、 DBMS的支持和数据库设计 <br />　　很多数据库应用系统开发者不重视数据库设计的原因是：他们太迷信DBMS，认为购入一个功能强大的 DBMS后数据库设计就不困难、不重要了。一些国内外的数据库教材常常是在为DBMS的开发厂商做宣传，而很少站在数据库用户角度，从数据库应用系统出发介绍数据库设计方法。结果往往使读者搞不清书中介绍的是数据库管理程序的设计思想，还是应用这种 DBMS 进行数据库设计的思想。 <br /><br />　　其实，DBMS只是给用户为已采用的数据库提供一个舞台，而是否使用这个舞台上的道具以及唱什么戏，则完全取决于用户的戏剧脚本和导演(开发者)的安排。例如，公路局系统所使用的数据库管理系统，是以二维表为基本管理单元、支持所有关系代数操作、支持实体完整性与实体间参照完整性的全关系型 RDBMS，而我们要在这个舞台上利用上述“道具”设计一个面向对象的关系数据库。 <br /><br />四、 应用对象模型与RDBMS模型的映射 <br />　　数据库设计(模式)是否支持应用系统的对象模型，这是判断是否是面向对象数据库系统的基本出发点。由于应用系统设计在前，数据库设计随后，所以应用系统对象模型向数据库模式的映射是面向对象数据库设计的关键。 <br /><br />　　1.三层数据库模式面向对象模型的扩展 <br /><br />　　一般数据库设计多参照ANSL/SPARC关于数据库模式的3层标准结构提案。最接近物理数据库的内部模式由 DBMS 提供的SQL来描述。概念模式可以由若干个内部模式聚集而成，它是由数据库用户规范的一些表的集合。例如，公路局计划处数据库模式、机务处数据库模式等，它们是逻辑数据库，常常通过库表 ID来界定库边界。一般的概念模式是数据库物理模式作用域的边界，它能实现数据库的物理意义、特定DBMS 的特殊操作对外部应用程序的信息隐蔽。外部模式是从特定用户应用角度看待的数据库模式，从不同的应用出发对同一概念模式可以给出多种不同的外部模式。例如：公路绿化情况查询应用看到的数据库是公路上的树木种类、数量、分布比率等，桥梁隧道状况查询应用看到的是公路上的桥梁、隧道长度、个数、路段等，但是它们可能访问的是同一个库表的不同子集。 <br /><br />　　当外部应用系统以对象模型进行抽象时，从各个应用出发抽象出的对象模型可以映射到外部模型上，对此我们不妨称之为外部对象模型。但是，外部模型只是概念模型的子集，所以面向对象的数据库设计核心在于系统对象模型(不妨称之为概念对象模型) 向数据库概念模型的映射(参见图1) 。 <br /><br />　　2.对象模型向数据库表的映射规则 <br /><br />　　由于 RDBMS 是以二维表为基本管理单元的，所以对象模型最终是由二维表及表间关系来描述的。换言之，对象模型向数据库概念模型的映射就是向数据库表的变换过程。有关的变换规则简单归纳如下： <br /><br />　　（1）一个对象类可以映射为一个以上的库表，当类间有一对多的关系时，一个表也可以对应多个类。 <br /><br />　　　图1 三层数据库模式面向对象模型的扩展 <br /><br />　　（2）关系(一对一、一对多、多对多以及三项关系)的映射可能有多种情况，但一般映射为一个表，也可以在对象类表间定义相应的外键。对于条件关系的映射，一个表至少应有3个属性。 <br /><br />　　（3）单一继承的泛化关系可以对超类、子类分别映射表，也可以不定义父类表而让子类表拥有父类属性；反之，也可以不定义子类表而让父类表拥有全部子类属性。 <br /><br />　　（4）对多重继承的超类和子类分别映射表，对多次多重继承的泛化关系也映射一个表。 <br /><br />　　（5）对映射后的库表进行冗余控制调整，使其达到合理的关系范式。 <br /><br />　　3.数据库模式要面向应用系统 <br /><br />　　我们选择面向对象的系统设计也好，面向对象的数据库设计也好，根本目的是服务于应用系统的需要。 <br /><br />　　以公路局计划处子系统为例。计划处的最大工作量就是处理成堆的报表，因此如何有效地存取这些报表是计划处数据库设计的关键。考虑到每月上交的报表是同构的，我们可以创建一张库表去存储同一种报表，例如公路工程月报表。但是又产生另一个问题，当用户想查询某个月的公路工程月报表时，如何从库表中取出数据呢?按照数据库的思想应该有一个主键来标识这张报表。在公路局的报表里，区别月报表靠上报时间和上报单位，但如果为每条记录都加上这两个字段，无疑会加大库表冗余，增加查询时间，降低效率。更何况每张报表都有单位负责人、填表人的属性，那么怎样解决这个问题呢？我们设计了超类对象 X3 表和流水号表。X3 表和流水号表的表结构如下。 <br /><br />　　表1 X3表和流水号表的表结构： <br /><br />　　将它们加入由应用对象模型映射出的数据库概念模型后，得到图2所示的结构。 <br /><br />　　每一个应用模块对象对应建立一张流水号表，同一类的报表属同一流水号表，由流水号表统一管理。流水号表对各分局、处室提交和建立的每一张报表分配一个流水号，该流水号在整个数据库中是唯一的，因此在库中存放任何一张报表都是明确的。流水号的数据类型为 Char(10)，前4位为表号，后6位为序列号，其中序列号取自 X3表中最大序列号。也就是说，流水号就是对象标识符，报表是一个对象，一个对象标识符唯一决定一个对象。流水号一旦被分配出去后，在这张报表的生存期内就具有了永久不变性。无论报表的内容及结构怎么变化，它都不变，直到报表被删除，流水号才会消失。流水号表是父类，报表是子类，流水号表之间的联系只能通过 X3 表。5个应用模块对象完全映射到数据库概念模型中，形成应用对象与数据库对象的一一对应，保持了5个应用对象在目标系统设计中原有的独立性，具有很好的封装性和信息隐蔽性。尽管流水号表会有一些冗余，但它是值得的。 <br /><br />　　图2 超类对象间关系示意图 <br /><br />五、 面向对象关系数据库设计效果 <br />　　在公路局系统设计中，从某种意义上讲，是数据库设计的面向对象特征最终奠定了整个系统的面向对象性，才使面向对象方法在程序开发阶段全面开花。其效果归纳如下： <br /><br />　　1.数据库结构清晰，便于实现OOP <br /><br />　　由于实现了应用模块对象对数据库对象的完全映射，数据库逻辑模型可以自然且直接地模拟现实世界的实体关系。公路局用户所处的当前物理世界、系统开发者所抽象的系统外部功能，与支持系统功能的内部数据库 (数据结构)一一对应，所以用户、开发者和数据库维护人员可以用一致的语言进行沟通。 特别是对多数不了解公路局业务的程序开发人员来说，这种将应用对象与相应的数据对象封装在对象统一体中的设计方法，大大减轻了程序实现的难度，使他们只要知道加工的数据及所需的操作即可，而且应用程序大多雷同，可以多处继承由设计人员抽象出来的、预先开发好的各种物理级超类。 <br /><br />　　2.数据库对象具有独立性，便于维护 <br /><br />　　除了数据库表对象与应用模块对象一一对应外，在逻辑对象模型中我们没有设计多重继承的泛化关系，所以这样得到的数据库结构基本上是由父表类和子表类构成的树型层次结构，表类间很少有继承以外的复杂关系，是一个符合局部化原则的结构，从而使数据库表数据破坏的影响控制在局部范围且便于修复，给公路局系统开通后的数据库日常维护工作带来便利。 <br /><br />　　3.需求变更时程序与数据库重用率高，修改少 <br /><br />　　在映射应用对象时，除关系映射规范化后可能出现一对多的表映射外，大多数应用对象与表对象是一一对应的。我们可以把规范化处理后的、由一个应用对象映射出来的多个表看成一个数据库对象。因此当部分应用需求变更时，首先，系统修改可以不涉及需求不变更的部分。其次，变更部分的修改可以基本上只限于追加或删除程序模块或追加新库表，而基本上不必修改原有程序代码或原有库表定义，从而大大减少了工作量，降低了工作难度。 <br /><br />六、 最简单的就是最好的 <br />　　客观世界是错综复杂的，计算机科学理论的发展也越来越高深、复杂。然而，人类探索理论和技术的最终目的是：让客观世界的复杂变简单，最简单的就是最好的。为此我们给出以下几点忠告： <br /><br />　　1. 慎用外键 <br /><br />　　RDBMS 支持复杂关系的能力很强，无论用户怎么在逻辑上设定外键，它基本上都能从物理上帮用户实现。但是外键把许多独立的实体牵连在一起，不仅使 RDBMS 维持数据一致性负担沉重，也使数据库应用复杂化，加重了程序开发负担。这样的数据库很难理解，很难实现信息隐蔽性设计，往往把简单问题复杂化。 <br /><br />　　2. 适当冗余 <br /><br />　　减少数据库冗余的设计思路产生于70年代，它是促使 DBMS 进步的重要动力之一。然而，犹如为了节省2个字节的存储空间而酿成了如今全球为之头痛的2000年问题一样，它是计算机硬件主导时代的产物。以今天国内计算机市场价格为例，6G服务器硬盘的价格不过2000元，而上海物价局 1996 年颁发的一个人月软件开发的指导价约8000元，即一个人月的软件价格就可以购买20G左右的硬盘。即使有5万行数据的库表，每个记录压缩40字符的冗余，单纯计算合计也不足2M，即节省0.6元钱的磁盘空间。 <br /><br />　　今天的世界已进入软件主导的计算机时代。因此，最容易理解、应用开发工作量最少、维护最简单的数据库结构才是最好的。只要数据完整性、一致性不受威胁，有些冗余，不足为虑。换言之，最节省软件成本 (而不是硬件成本) 的是最好的。 <br /><br />　　3. 信息隐蔽 <br /><br />　　这是软件工程最重要的基本原则之一。简言之即信息的作用域越小越好，数据库的透明度越大越好，因为应用程序需要知道得越多就越复杂。使数据库黑盒化 (透明度高) 的方法很多，除了设计上的局部化处理外，还可以利用 DBMS 的触发器、存储过程、函数等，把数据库中无法简化的复杂表关系封装到黑盒子里，隐藏起来，特别是放到服务器端，其优越性更是多方面的。 <br /><img src ="http://www.blogjava.net/faithwind/aggbug/65792.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/faithwind/" target="_blank">黑咖啡</a> 2006-08-25 14:40 <a href="http://www.blogjava.net/faithwind/articles/65792.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据仓库设计的21条原则--7个步骤，7个禁忌和7种思路</title><link>http://www.blogjava.net/faithwind/articles/65793.html</link><dc:creator>黑咖啡</dc:creator><author>黑咖啡</author><pubDate>Fri, 25 Aug 2006 06:40:00 GMT</pubDate><guid>http://www.blogjava.net/faithwind/articles/65793.html</guid><wfw:comment>http://www.blogjava.net/faithwind/comments/65793.html</wfw:comment><comments>http://www.blogjava.net/faithwind/articles/65793.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/faithwind/comments/commentRss/65793.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/faithwind/services/trackbacks/65793.html</trackback:ping><description><![CDATA[
		<p>
				<b>
						<font size="3">
								<font color="#ff0000">高效实现数据仓库的七个步骤</font> </font>
				</b>
				<br />
				<br />数据仓库和我们常见的RDBMS系统有些亲缘关系，但它又有所不同。如果你没有实施过数据仓库，那么从设定目标到给出设计，从创建数据结构到编写数据分析程序，再到面对挑剔的用户的评估，整个过程都会带给你一种与以往的项目完全不同的体验。一句话，如果你试图以旧有的方式创建数据仓库，那你所面对的不是预算超支就是所建立的数据仓库无法良好运作。 <br /><br />在处理一个数据仓库项目时需要注意的问题很多，但同时也有很多有建设性的参考可以帮助你更顺利的完成任务。开放思维，不断尝试新的途径，对于找到一种可行的数据仓库实现方法来说也是必需的。 <br /><br /><b><font size="3">1. 配备一个全职的项目经理或你自己全面负责项目管理</font></b><br />在通常情况下，项目经理都会同时负责多个项目的实施。这么做完全是出于资金和IT资源方面的考虑。但是对于数据仓库项目的管理，绝对不能出现一人身兼数个项目的情况。由于你所处的领域是你和你的团队之前没有进入过的领域，有关数据仓库的一切－数据分析、设计、编程、测试、修改、维护－全都是崭新的，因此你或者你指派的项目经理如果能全心投入，对于项目的成功会有很大帮助。 <br /><br /><b><font size="3">2. 将项目管理职责推给别的项目经理</font></b><br />由于数据仓库实现过程实在是太困难了，为了避免自虐，你可以在当前阶段的项目完成后就将项目管理职责推给别的项目经理。当然，这个新的项目经理一定要复合第一条所说的具有全职性。为什么要这么做呢？首先，从项目经理的角度看，数据仓库实施过程的任何一个阶段都足以让人身心疲惫。从物理存储设备的开发到Extract-Transform-Load的实现，从设计开发模型到OLAP，所有阶段都明显的比以前接触的项目更加困难。每个阶段不但需要新的处理方法、新的管理方法，还需要创新性的观点。所以将管理职责推给别的项目经理不但不会对项目有损害，还可以起到帮助作用。<br /><b><font size="3"><br />3.与用户进行沟通</font></b><br />这里所讲的内容远比一篇文章本身要重要的多。你必须明白，在数据仓库的设计阶段，那些潜在用户自己也不清楚他们到底需要数据仓库为他们做什么。他们在不断的探索和发现自己的需求，而你的开发团队也在和客户的接触中做着同样的事情。更加频繁的与客户接触，多做记录，并让你的团队更关注于项目需求讨论的结果而不是讨论的过程本身。<br /><br />既然你和客户的交流是为了了解存储的数据是何种类型以及如何有效存储数据，你也许需要（和你的用户一起）采用一种新的方法观察数据，而不是直接处理数据。你可以尝试从中找出隐藏的信息，比如在一段时期内的数字涨落等。不要试图追寻项目需求的答案，而是要让答案找上门来。<br /><b><font size="3"><br />4. 以技术/信息库作为领导</font></b><br />由于数据仓库实施的各个阶段都有很大不同，因此你需要有人能起到维持整个项目的连续进行的作用，不过这个职责并不需要那种全职性。项目实施有三个重要方面：架构、技术和业务。将架构作为重点可以保证在整个项目中，数据仓库的架构从物理层往上，都会受到良好的维护。而我们应该将技术作为重点，因为开发团队和关键用户都在使用他们以前从未用过的工具，必须有人监督开发过程以及工具使用的一致性。<br /><br />最后，在数据仓库的应用过程中浮现出来的业务需求必须被详细分析和记录，以促机开发过程持续下去。如果用户不能很好的开发人员以及其它用户沟通，那么数据分析和度量方面的开发进程就会延期，所以必须有人关注业务方面的开发，推动开发进入更高级别。<br /><br /><b><font size="3">5. 跳出反复修改程序的陷阱</font></b><br />第一次实现的数据仓库肯定不会是最终交付的版本。为什么呢？实际上在真正见到产品前，你无法确定的知道自己的目标是什么。或者说，最终用户只有在使用数据仓库产品一段时间后，才能明确告诉你这个产品是不是他所希望的。与你以往处理的项目不同，业务智能还处于发展的初期，每个公司对业务智能都有不同的解释，因此你的项目决不会一次成功。<br /><br />为了以正确的格式获得数据，你需要在不断变化的状况中摸索前进。BI具有很强的个性，不同的环境、不同的市场以及不同的企业都有不同的BI。这又代表什么呢？这表示你需要把数据库管理员放在一个消息相对封闭的环境中，不要让他知道数据仓库的数据结构以及ETL程序在不断的改变。对此没有别的办法。这样可以减轻你和DBA所承受的压力。<br /><br /><b><font size="3">6. 对大量的前端资源进行数据源分析</font></b><br />在数据仓库实现过程中，你不得不在旧有的数据中艰难跋涉，这些数据来自老的数据库、老的磁带机以及远程的数据。它们中的大部分都凌乱不堪，并且难以获取。你要对这些数据进行大量处理，并且还要设计ETL程序来寻找其中的有用信息。如果你希望整个项目做起来比较顺利，并且找到一种方法能够一次成功，那就需要你的开发人员必须花费足够的时间来充分研究这些旧有数据，将凌乱的数据规则化，并尽力设计和实现强壮的数据采集和转换过程。数据仓库的ETL部分会占用整个项目资源的百分之八十，所以一定要确定你的资源都用在刀刃上了。<br /><br /><b><font size="3">7. 将人际关系处理放在首位</font></b><br />在数据仓库实现过程中真正的地狱不是来自技术或者开发方面，而是来自你周围的人。你也许会遇到一个对项目并不乐观而又没时间听你陈述的领导。你也许会遇到一些开发人员将进度拖延太长时间还抱怨为什么不能用老方法实施。你也许还会遇到一些抱有不切实际的幻想的用户，他们希望轻点鼠标就能实现想象中的功能，但却不愿在他们那边多做些智力投资，更好的培训他们自己的员工。而你也已经疲惫不堪，鼓励投资，以及在开发团队和用户（甚至老板）中推广新的开发技巧。<br /><br />总之你要保持微笑。当一切搞定，你的烦恼也就一扫而空了，笑到最后才笑得最轻松。<br /><br /><br /><br /><font color="#ff0000" size="3"><b>数据仓库开发过程中的七个禁忌 </b></font><br /><br />过去我们一直使用的OLTP技术也许隐藏着许多严重的缺陷。数据仓库的实现并不是一个简单的任务，你会发现以前积累下来的丰富经验，并不适合处理每个数据仓库的独特需求。 <br /><br />下面列出的条款是你在实现数据仓库过程中一定会面对的问题，其中一些看起来并没有想象中那么严重，但是你还是应该尽量避免出现类似问题。数据仓库并不是一个事务处理系统，它没有一定的标准也不会实现某个特定的应用，但它本质上是非常有组织性的。总之，每个公司所建立的数据仓库都是唯一的，并且每一次数据仓库的实现方法都不是一成不变的。在实现数据仓库时需要注意的不单是"应该如何作"，更要注意"不该如何做"。下面就是我们总结的七点"不该如何作"。 <br /><br /><b><font size="3">1.不要编写自己无法快速修改的代码</font></b><br />你所要编写的程序主要用于数据分析，而不是处理事务。而你的用户也并不真正知道他们自己真正想要一个什么样的程序。因此你不得不反复修改代码好几次，才会明白用户到底需要一个什么样的程序。如果你编写的程序具有良好的结构和灵活性，就算需要修改也不会太浪费力气。反之，你会被自己累死。 <br /><br /><b><font size="3">2. </font></b><font size="3"><b>不要使用无法修改的数据库访问API</b></font><br />在过去，你的数据库可以为大量的客户提供稳定的数据查询服务。而如今，你的程序必须能够应付更多的数据查询。这使得重新改写程序以使得每个查询请求能得到最大的数据量成为势在必行的工作，而一般来说这种代码修改都不会一次成功，所以只有选择合适的可以修改的API，才能使程序尽快适应新的需求。 <br /><br /><b><font size="3">3. 不要设计任何无法扩展的东西</font></b><br />在联机处理过程（OLTP）应用中，数据分析并不是一个真正的应用程序。实际上，数据分析的关键是获取大量旧的数据，从中提取数据模型，并以此模型推断出新的信息。而你所编写的访问潜在信息的代码应该具有可扩展性，可以附加新的数据。千万别在支持数据分析的代码中假定数据都是固定格式的。 </p>
		<p>
				<b>
						<font size="3">4. 不要附加不必要的功能</font>
				</b>
				<br />一个仓库要做的是恰到好处的服务，用户走进仓库，从货架上取得自己所需得信息，仅此而已。由于业务智能、分析以及规律性的问题都有各自的处理程序，因此你的客户唯一的需要就是获取信息。他们需要一种应用环境，可以让他们快速的从数据仓库中取得分析过程所需的数据，而不论这个数据是什么样子的。也许你想帮助他们精炼一下获得的数据，但最好不要这么做。一定要记住，不要给客户的数据分析程序添加任何会影响数据访问性能的功能。<br /><br /><b><font size="3">5. 不要简化数据清除和数据源分析的步骤</font></b><br />在实现数据仓库过程中最应该注意的地方就是为Extract-Transform-Load机制分析数据源，以及为优化负载而清除数据。安全的做法是假设项目经理在这个阶段会需要整个项目资源的一半以上。相反，如果你在这方面进行了简化，稍后肯定会后悔。所以就算系统工作缓慢，也不要简化清理旧的数据的过程。<br /><br /><b><font size="3">6. 不要避免颗粒度和分区问题</font></b><br />在数据仓库设计过程中有两个最大的数据存储问题，第一是如何给转换数据定位一个恰当的颗粒度等级，第二是如何将数据绝对的分区。为什么这两点问题如此重要呢？因为整个数据仓库的响应能力受颗粒度影响，并且数据访问的效率直接与数据分区性能有关。因此这是具有关键性的工作，不要试图避免面对这些问题。<br /><br /><b><font size="3">7. 不要在没</font></b><font size="3"><b>考虑业务问题前就使用OLAP</b></font><br />用户在亲眼见到程序前通常都不知道自己到底想要个什么样的程序。因此他们的观点有不少错误，比如他们希望分析结果会忠实反应性能度量，或者希望程序会使他们部门或公司的业务工作有所不同。而你必须跳出自己的职责范围，从IT管理者的角度考虑用户部门直至整个企业的运行方式，才能在开发过程中避免这类问题。在通常的OLTP开发中，你可以比较方便的理解业务流程。而在联机分析处理（OLAP）领域，任何事情都需要亲自考察，而在你周围工作的人也许并不会发现你对业务方面存在的误解。因此，不要自以为已经了解了足够的信息。不断的询问才能使你真正了解"业务智能"中的"业务"到底是什么样子的<br /><br /><b><font color="#ff0000" size="3"><br />顺利开发数据仓库的七种思路</font></b> <br /><br /><br />对于大多数IT顾问来说，实现一个数据仓库的难度比以前做过的任何项目难度都要大。考虑到不同的数据结构、用途以及应用程序开发方法，以前所积累的经验和技巧大部分都无用武之地了。但是只要在你的前进道路上稍加修正，你就会发现实现一个数据仓库并不是难事，就算你是第一次实现数据仓库也没问题。 <br /><br />下面列出了数据仓库实施过程需要考虑的步骤，有一些你可能从来没有意识到，而另一些可能已经在实施过程中使用到了，但是重新思考一番也许你会有更多的领悟。开放思维，不断尝试新的途径，找到一种可行的数据仓库实现方法。 <br /><br /><b><font size="3">1. 再三考虑应用程序的实现方法</font></b><br />数据仓库并不涉及事务处理，并且在报表方面也仅占一小部分。而数据仓库应用程序的本质是分析，尤其是针对业务智能的分析。BI并不是通常所说的数据：它是一种从旧有数据中,模型化得到的新的数据。那么如何才能从旧有数据中挖出这些新数据呢？事实上，这个工作不是让你来完成的，而是你的客户所要完成的。从项目主管的角度看，应该有一个经验丰富的数据表格设计师与你合作，进而决定如何将各类程序融合在一起。其中所遇到的最主要的挑战将是如何用新的方法观察数据，这也是你的客户正在试图使用的方法。 <br /><br /><b><font size="3">2. 创建抽象的、良好部署的数据库访问组件</font></b><br />在过去你接触过的数据库项目和现在的数据仓库之间，有一点绝对不同，那就是：在Online Transaction Processing （OLTP）环境中，用户数量非常大，但使用到的数据却比较少；而在Online Analytical Processing （OLAP）环境中情况却正好相反，少量的用户在使用大量的数据。而你的工作就是编写一个应用程序来优化这种不同。这里有一个线索：在你所有的分析程序中，都要能抓取连续的数据项，这样在以后建立和访问的数据结构中才能存放与原数据物理结构类似的数据。具体如何实现呢？首先不要规格化数据。第二将其放入数组中最小化读取请求数。按照这种方法，DBA会很乐意与你合作。<br /><br /><b><font size="3">3. 保持松散</font></b><br />现在回头看看第一步，你应该可以理解定义一个分析程序不是件简单事了，而且一般情况下，很难在第一次就实现符合要求的最终产品。而在你将要进行分析的数据结构上同样存在这种问题。一句话，实现过程会有很多变数，你需要不断的改动你的程序。通常我们都希望将改动次数降到最低。在一个数据仓库实现过程中，本质是要分析过程毫无差错，这也需要DBA的参与。不要死抓住你的程序设计、代码、框图，或你建立的其它什么东西不放手，要根据这种变化而不断进行调整。<br /><br /><b><font size="3">4. 将管理放在首位</font></b><br />在分析数据源方面你做的如何呢？你是否认为清理垃圾数据的工作非常困难？并不是只有你一个人这样想，做过类似工作的人都有这种看法。在一个一般规模的机构中，作为数据仓库实现过程的一部分，会有大量的旧有数据必须进行一致性处理。所以分析数据源并花费数个小时编写转换程序将旧有数据导入数据仓库是整个数据仓库实现过程中最艰难的一部分。并且这也是整个项目中最重要的一环，可以占到整个项目周期和预算的四分之三。所以一定要小心对待。<br /><br /><b><font size="3">5. 从字里行间发现问题</font></b><br />与用户交流是个很麻烦的事情，为什么这么说呢？因为很多用户在见到最终产品前都不知道自己想要什么样的产品。定义数据仓库应用程序是一个探索的过程，而且这个过程要反复进行。记住所谓的"业务智能"是用户自己定义的，他们按照自己的理解来处理业务流程。因此这些用户就是连接数据和业务处理过程间的桥梁。他们所要的并不是数据本身，而是隐藏在数据后面的智能性。你可以让他们讨论、思考并给出建设性的意见。但千万不要让他们解决或让他们任意想象和发表那些"有可能"的观点。最后，一定要随时留意用户得出的结论。<br /><br /><b><font size="3">6. 保持领先</font></b><br />数据仓库看起来没有传统的OLTP模式根深蒂固，事实如此。虽然很多人投身数据仓库的开发中，但由于其框架与以前的系统大相径庭，因此在开始的一段时间数据仓库的实现看上去相当混乱。但是坚持下去是很重要的。它具有两方面重要的作用。<br /><br />第一，技术的领先性。它可以跟踪项目中任何阶段的软件工具的部署和正确使用，以及开发过程。如果这复合你的背景，你可以对此多加留意。<br /><br />第二，体系结构的领先性。它使得项目在各个阶段转换时，数据仓库和它所支持的系统的物理以及逻辑架构都具有持续性，不会发生改变。这也是你能提供的。<br /><br /><b><font size="3">7. 发出警告</font></b><br />最后你要记住，你并不是唯一登上新大陆的人。你周围的每一个人都会有下面一点或几点问题：不现实的期望、对技术的误解、旧习惯或坏习惯、竞争行为，或缺乏对项目的信任度。虽然交流沟通等任务应该是项目经理负责的，但实际上你也要担负起相同的责任。那么作为技术总监你该怎么作呢？首先当然是要真诚的对待周围的人，但一定要竖立威信，适当的发出警告。当你发现项目进度缓慢、资源流失，或者员工失去目标，就要直言不讳的说出来。快速明确的给予警告在大部分情况下都是明智之举。匆忙上马的数据仓库项目也许会出轨，但不要让失败的项目把你拉下马。</p>
<img src ="http://www.blogjava.net/faithwind/aggbug/65793.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/faithwind/" target="_blank">黑咖啡</a> 2006-08-25 14:40 <a href="http://www.blogjava.net/faithwind/articles/65793.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于SQLServer的若干注意事项</title><link>http://www.blogjava.net/faithwind/articles/65794.html</link><dc:creator>黑咖啡</dc:creator><author>黑咖啡</author><pubDate>Fri, 25 Aug 2006 06:40:00 GMT</pubDate><guid>http://www.blogjava.net/faithwind/articles/65794.html</guid><wfw:comment>http://www.blogjava.net/faithwind/comments/65794.html</wfw:comment><comments>http://www.blogjava.net/faithwind/articles/65794.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/faithwind/comments/commentRss/65794.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/faithwind/services/trackbacks/65794.html</trackback:ping><description><![CDATA[
		<p style="FONT-SIZE: 9pt">如果你正在负责一个基于SQL Server的项目，或者你刚刚接触SQL Server，你都有可能要面临一些数据库性能的问题，这篇文章会为你提供一些有用的指导（其中大多数也可以用于其它的DBMS）。 
</p>
		<p>        在这里，我不打算介绍使用SQL Server的窍门，也不能提供一个包治百病的方案，我所做的是总结一些经验----关于如何形成一个好的设计。这些经验来自我过去几年中经受的教训，一直来，我看到许多同样的设计错误被一次又一次的重复。</p>
		<p>
				<strong>
						<font size="4">你了解你的工具吗？</font>
				</strong>
		</p>
		<p>        不要轻视这一点，这是我在这篇文章中讲述的最关键的一条。也许你也看到有很多的SQL Server程序员没有掌握全部的T-SQL命令和SQL Server提供的那些有用的工具。</p>
		<p>        “什么？我要浪费一个<font size="2">月</font>的时间来学习那些我永远也不会用到的SQL命令？？？”，你也许会这样说。对的，你不需要这样做。但是你应该用一个周末浏览所有的T-SQL命令。在这里，你的任务是了解，将来，当你设计一个查询时，你会记起来：“对了，这里有一个命令可以完全实现我需要的功能”，于是，到MSDN查看这个命令的确切语法。</p>
		<p>
				<strong>
						<font size="4">不要使用游标</font>
				</strong>
		</p>
		<p>       让我再重复一遍：不要使用游标。如果你想破坏整个系统的性能的话，它们倒是你最有效的首选办法。大多数的初学者都使用游标，而没有意识到它们对性能造成的影响。它们占用内存，还用它们那些不可思议的方式锁定表，另外，它们简直就像蜗牛。而最糟糕的是，它们可以使你的DBA所能做的一切性能优化等于没做。不知你是否知道每执行一次FETCH就等于执行一次SELECT命令？这意味着如果你的游标有10000条记录，它将执行10000次SELECT！如果你使用一组SELECT、UPDATE或者DELETE来完成相应的工作，那将有效率的多。</p>
		<p>       初学者一般认为使用游标是一种比较熟悉和舒适的编程方式，可很不幸，这会导致糟糕的性能。显然，SQL的总体目的是你要实现什么，而不是怎样实现。</p>
		<p>       我曾经用T-SQL重写了一个基于游标的存储过程，那个表只有100,000条记录，原来的存储过程用了40分钟才执行完毕，而新的存储过程只用了10秒钟。在这里，我想你应该可以看到一个不称职的程序员究竟在干了什么！！！</p>
		<p>       我们可以写一个小程序来取得和处理数据并且更新数据库，这样做有时会更有效。记住：对于循环，T-SQL无能为力。</p>
		<p>        我再重新提醒一下：使用游标没有好处。除了DBA的工作外，我从来没有看到过使用游标可以有效的完成任何工作。</p>
		<p>
				<strong>
						<font size="4">规范化你的数据表</font>
				</strong>
		</p>
		<p>       为什么不规范化数据库？大概有两个借口：出于性能的考虑和纯粹因为懒惰。至于第二点，你迟早得为此付出代价。而关于性能的问题，你不需要优化根本就不慢的东西。我经常看到一些程序员“反规范化”数据库，他们的理由是“原来的设计太慢了”，可结果却常常是他们让系统更慢了。DBMS被设计用来处理规范数据库的，因此，记住：按照规范化的要求设计数据库。</p>
		<p>
				<strong>
						<font size="4">不要使用SELECT *</font>
				</strong>
		</p>
		<p>        这点不太容易做到，我太了解了，因为我自己就经常这样干。可是，如果在SELECT中指定你所需要的列，那将会带来以下的好处：</p>
		<p>1 减少内存耗费和网络的带宽</p>
		<p>2 你可以得到更安全的设计</p>
		<p>3 给查询优化器机会从索引读取所有需要的列</p>
		<p>
				<strong>
						<font size="4">了解你将要对数据进行的操作</font>
				</strong>
		</p>
		<p>       为你的数据库创建一个健壮的索引，那可是功德一件。可要做到这一点简直就是一门艺术。每当你为一个表添加一个索引，SELECT会更快了，可INSERT和DELETE却大大的变慢了，因为创建了维护索引需要许多额外的工作。显然，这里问题的关键是：你要对这张表进行什么样的操作。这个问题不太好把握，特别是涉及DELETE和UPDATE时，因为这些语句经常在WHERE部分包含SELECT命令。</p>
		<p>
				<strong>
						<font size="4">不要给“性别”列创建索引</font>
				</strong>
		</p>
		<p>       首先，我们必须了解索引是如何加速对表的访问的。你可以将索引理解为基于一定的标准上对表进行划分的一种方式。如果你给类似于“性别”这样的列创建了一个索引，你仅仅是将表划分为两部分：男和女。你在处理一个有1,000,000条记录的表，这样的划分有什么意义？记住：维护索引是比较费时的。当你设计索引时，请遵循这样的规则：根据列可能包含不同内容的数目从多到少排列，比如：姓名+省份+性别。</p>
		<p>
				<strong>
						<font size="4">使用事务</font>
				</strong>
		</p>
		<p>       请使用事务，特别是当查询比较耗时。如果系统出现问题，这样做会救你一命的。一般有些经验的程序员都有体会-----你经常会碰到一些不可预料的情况会导致存储过程崩溃。</p>
		<p>
				<strong>
						<font size="4">小心死锁</font>
				</strong>
		</p>
		<p>       按照一定的次序来访问你的表。如果你先锁住表A，再锁住表B，那么在所有的存储过程中都要按照这个顺序来锁定它们。如果你（不经意的）某个存储过程中先锁定表B，再锁定表A，这可能就会导致一个死锁。如果锁定顺序没有被预先详细的设计好，死锁是不太容易被发现的。</p>
		<p>
				<strong>
						<font size="4">不要打开大的数据集</font>
				</strong>
		</p>
		<p>       在CSDN技术论坛中 :），一个经常被提出的问题是：我怎样才能迅速的将100000条记录添加到ComboBox中？这是不对的，你不能也不需要这样做。很简单，你的用户要浏览100000条记录才能找到需要的记录，他一定会诅咒你的。在这里，你需要的是一个更好的UI，你需要为你的用户显示不超过100或200条记录。</p>
		<p>
				<strong>
						<font size="4">不要使用服务器端游标</font>
				</strong>
		</p>
		<p>       与服务器端游标比起来，客户端游标可以减少服务器和网络的系统开销，并且还减少锁定时间。</p>
		<p>
				<strong>
						<font size="4">使用参数查询</font>
				</strong>
		</p>
		<p>       有时，我在CSDN技术论坛看到类似这样的问题：“SELECT * FROM  a WHERE a.id='A'B，因为单引号查询发生异常，我该怎么办？”，而普遍的回答是：用两个单引号代替单引号。这是错误的。这样治标不治本，因为你还会在其他一些字符上遇到这样的问题，更何况这样会导致严重的bug，除此以外，这样做还会使SQL Server的缓冲系统无法发挥应有的作用。使用参数查询， 釜底抽薪，这些问题统统不存在了。</p>
		<p>
				<strong>
						<font size="4">在程序编码时使用大数据量的数据库</font>
				</strong>
		</p>
		<p>       程序员在开发中使用的测试数据库一般数据量都不大，可经常的是最终用户的数据量都很大。我们通常的做法是不对的，原因很简单：现在硬盘不是很贵，可为什么性能问题却要等到已经无可挽回的时候才被注意呢？</p>
		<p>
				<strong>
						<font size="4">不要使用INSERT导入大批的数据</font>
				</strong>
		</p>
		<p>       请不要这样做，除非那是必须的。使用UTS或者BCP，这样你可以一举而兼得灵活性和速度。</p>
		<p>
				<strong>
						<font size="4">注意超时问题</font>
				</strong>
		</p>
		<p>       查询数据库时，一般数据库的缺省都比较小，比如15秒或者30秒。而有些查询运行时间要比这长，特别是当数据库的数据量不断变大时。</p>
		<p>
				<strong>
						<font size="4">不要忽略同时修改同一记录的问题</font>
				</strong>
		</p>
		<p>       有时候，两个用户会同时修改同一记录，这样，后一个修改者修改了前一个修改者的操作，某些更新就会丢失。处理这种情况不是很难：创建一个timestamp字段，在写入前检查它，如果允许，就合并修改，如果存在冲突，提示用户。</p>
		<p>
				<strong>
						<font size="4">在细节表中插入纪录时，不要在主表执行SELECT MAX(ID)</font>
				</strong>
		</p>
		<p>       这是一个普遍的错误，当两个用户在同一时间插入数据时，这会导致错误。你可以使用<font face="宋体">SCOPE_IDENTITY，<code>IDENT_CURRENT</code>和<code>@@IDENTITY。如果可能，不要使用<font face="宋体">@@IDENTITY，因为在有触发器的情况下，它会引起一些问题（详见这里的<a href="http://expert.csdn.net/Expert/topic/1147/1147612.xml?temp=.3728754"><font color="#002c99">讨论</font></a>）。</font></code></font></p>
		<p>
				<code>
						<font face="宋体" size="4">
								<strong>避免将列设为NULLable</strong>
						</font>
				</code>
		</p>
		<p>
				<code>
						<font face="宋体">    如果可能的话，你应该避免将列设为NULLable。系统会为NULLable列的每一行分配一个额外的字节，查询时会带来更多的系统开销。另外，将列设为NULLable使编码变得复杂，因为每一次访问这些列时都必须先进行检查。</font>
				</code>
		</p>
		<p>
				<code>
						<font face="宋体">    我并不是说NULLS是麻烦的根源，尽管有些人这样认为。我认为如果你的业务规则中允许“空数据”，那么，将列设为NULLable有时会发挥很好的作用，但是，如果在类似下面的情况中使用NULLable，那简直就是自讨苦吃。</font>
				</code>
		</p>
		<p>
				<code>CustomerName1<br />CustomerAddress1<br />CustomerEmail1<br />CustomerName2<br />CustomerAddress2<br />CustomerEmail3<br />CustomerName1<br />CustomerAddress2<br />CustomerEmail3</code>
		</p>
		<p>
				<code>   如果出现这种情况，你需要规范化你的表了。</code>
		</p>
		<p>
				<code>
						<strong>
								<font size="4">尽量不要使用TEXT数据类型</font>
						</strong>
				</code>
		</p>
		<p>
				<code>   除非你使用TEXT处理一个很大的数据，否则不要使用它。因为它不易于查询，速度慢，用的不好还会浪费大量的空间。一般的，VARCHAR可以<font face="新宋体">更好的</font>处理你的数据。</code>
		</p>
		<p>
				<code>
						<strong>
								<font size="4">尽量不要使用临时表</font>
						</strong>
				</code>
		</p>
		<p>
				<code>   尽量不要使用临时表，除非你必须这样做。一般使用子查询可以代替临时表。使用临时表会带来系统开销，如果你是用COM+进行编程，它还会给你带来很大的麻烦，因为COM+使用数据库连接池而临时表却自始至终都存在。SQL Server提供了一些替代方案，比如Table数据类型。</code>
		</p>
		<p>
				<code>
						<strong>
								<font size="4">学会分析查询</font>
						</strong>
				</code>
		</p>
		<p>
				<code>SQL Server查询分析器是你的好伙伴，通过它你可以了解查询和索引是如何影响性能的。</code>
		</p>
		<p>
				<code>
						<strong>
								<font size="4">使用参照完整性</font>
						</strong>
				</code>
		</p>
		<p>
				<code>定义主健、唯一性约束和外键，这样做可以节约大量的时间。</code>
		</p>
		<p>
		</p>
		<!--Here is the bottom-->
		<p> </p>
<img src ="http://www.blogjava.net/faithwind/aggbug/65794.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/faithwind/" target="_blank">黑咖啡</a> 2006-08-25 14:40 <a href="http://www.blogjava.net/faithwind/articles/65794.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>实施数据仓库的建议</title><link>http://www.blogjava.net/faithwind/articles/65791.html</link><dc:creator>黑咖啡</dc:creator><author>黑咖啡</author><pubDate>Fri, 25 Aug 2006 06:39:00 GMT</pubDate><guid>http://www.blogjava.net/faithwind/articles/65791.html</guid><wfw:comment>http://www.blogjava.net/faithwind/comments/65791.html</wfw:comment><comments>http://www.blogjava.net/faithwind/articles/65791.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/faithwind/comments/commentRss/65791.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/faithwind/services/trackbacks/65791.html</trackback:ping><description><![CDATA[你知道你需要一个数据仓库，而且已经下定决心了：你的竞争对手比你更早的预测到了市场趋势，其它公司也在Web驱动的市场上比你反应得更迅速，而你没有足够得能力赶上它们。另外，你的各个部门的数据查询和报表请求几乎要拖垮了你的业务系统。这一切都表明你真的需要一个数据仓库。 <br /><br />而当你走进老板的办公室，面对企业的决策者，你知道该对他们说些什么吗？如何才能向决策者推销自己的想法？怎样才能让他们接受你的观点，对这个无形的、没有明确预算也没有明确受益程度的项目进行投资呢？下面是我给你的几个建议。 <br /><br /><b>投资回报</b><p>当你向决策者们陈述自己对于数据仓库的实施计划时，不要将投资回报作为争取投资的筹码。因为你没有测定过数据仓库会对生产效率或者市场了解度的增长起到什么作用，因此你无法提供一个投资回报计划。由于没有任何数据仓库的经验，因此你也就无法量化其带来的好处。事实上，实施数据仓库的首要原因是要开发企业的业务智能能力，它会教给你如何明确的测量市场了解度的增长。也就是说，你在申请时间和经费来开发一个可以测定自身价值的工具。 <br /><br />就算你已经开发出了具有数据分析和性能监测能力的产品，也还是无法说明你最终要测量的是什么。为什么这么说呢？因为高级别的业务性能度量是基于更详细的更低级的度量的，而这些是你将要在部门级培养的数据分析所负责的领域。而在产品成形前他们自己也不知道所要做的是什么。<br /><br />这一切听起来是那么神秘，但是这些神秘的数字确实有用。下面这几点内容你可以大胆的说出来，并且我会告诉你如何说。虽然没有附带具体数据，但其逻辑性很强，不容反驳。<br /><br /><b>数据仓库的优势</b></p><p>1.多级的趋势分析。你的财务人员、销售人员以及市场人员将有能力对市场趋势进行多等级的定义和分析，所包括的范围大到整个市场，小到一个地区的市场或任意定义的范围。而且他们可以控制预测的精度，因为数据来源的品质和测量精度都是可以控制的。<br /><br />2.企业范围的性能监测。同等级别的分析能力可以应用于部门级、业务单元级，以及整个企业范围。你可以开发，并且不断的改进，度量整个企业的性能。<br /><br />3.用户定义的，用户控制的报表。这一点尤其需要强调，因为它听起来有种紧随世界趋势的意思。实际上我们一点也没有夸大它的能力，而且这也正是你需要的能力。<br /><br /><b>你的案例</b></p><p>现在考虑一下你的报告系统。以订货量为例，系统会将大量的报表发送到不同部门的不同人员手中。这里出现的状况是没有人能够处理包括订单、来自订单历史记录的数据，以及来自不同数据库的数据（如客户表格等），因此无法汇总所需的信息。问题出在哪里呢？首先，由于报表很大程度上是静态的，并且所需信息多来自不同的数据库，需要多次请求才能得到，操作起来开销很大。<br /><br />现在你可以让决策者选择逐一的投资实现单独的功能或者一次投资实现所有功能。你必须让他们清楚的知道，数据仓库实施的最终目的是给你的用户群一个唯一的应用程序，而它可以代替以往的数个程序。在一个大程序上的投资足够投资实现一个数据仓库了，而它所带来的功能将更强大。这才是企业所追求的效益。<br /><br />数据仓库的另一个好处是它可以实现一个叫做总经理信息系统（EIS）的系统。EIS是一个应用程序，它可以按照分类形式提供经理在决策报告中所需的任何信息。由于一般情况下经理不会面对其它用户所遇到的分析数据的问题，他们不会处理四五个数据源的数据汇总工作。他们只是需要用最简单的方法获得最精确的信息。对于这类用户来说，数据仓库可以令他们梦想成真。<br /><br /><b>谁是受益者？</b></p><p>如果你无法明确的说明这一点，决策者们是不会为你掏腰包的。数据仓库是一个强大的战略性工具，它可以大大加强企业的竞争力。如果你无法提出具体的投资数目，那么可以说一个很保守的数字10万美元，而最高投资肯定不会到七位数。<br /><br />那么你需要购买什么设备呢？如果你目前使用的是某种ERP平台（SAP R/3, Oracle, PeopleSoft），你可以购买相应的开发工具包，其中的工具可以帮助你实现数据提取和载入程序，以及开发数据挖掘和分析程序。如果目前还没有ERP平台，你需要购买存储设备、用于将数据导入数据仓库的extract-transform-load （ETL）软件，以及用于数据挖掘和分析的软件（Online Analytical Processing, or OLAP）。除此之外，你还需要对员工进行业务培训，使他们能够胜任数据分析工作，还要帮助员工转变事务处理思想模式，使他们能顺利进行报表开发工作（后续的文章会对此做更深入的讨论）。<br /><br />最后你需要总结一下，这也是各位决策者需要听到的：通过数据仓库，你的用户团队可以实现少花钱多办事的目的。<br /></p><img src ="http://www.blogjava.net/faithwind/aggbug/65791.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/faithwind/" target="_blank">黑咖啡</a> 2006-08-25 14:39 <a href="http://www.blogjava.net/faithwind/articles/65791.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>系统构架设计应考虑的因素</title><link>http://www.blogjava.net/faithwind/articles/65789.html</link><dc:creator>黑咖啡</dc:creator><author>黑咖啡</author><pubDate>Fri, 25 Aug 2006 06:38:00 GMT</pubDate><guid>http://www.blogjava.net/faithwind/articles/65789.html</guid><wfw:comment>http://www.blogjava.net/faithwind/comments/65789.html</wfw:comment><comments>http://www.blogjava.net/faithwind/articles/65789.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/faithwind/comments/commentRss/65789.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/faithwind/services/trackbacks/65789.html</trackback:ping><description><![CDATA[
		<strong>摘要：<br /></strong>本文从程序的运行时结构和源代码的组织结构两个方面探讨了系统构架设计应考虑的各种因素，列举了系统构架设计文档应考虑的一些问题。 <br /><b>关键字：<br /></b>系统构架、设计、考虑、因素<br /><b>正文：<br /></b>约公元前25年，古罗马建筑师维特鲁威说：“理想的建筑师应该既是文学家又是数字家，他还应通晓历史，热衷于哲学研究，精通音乐，懂得医药知识，具有法学造诣，深谙天文学及天文计算。”（好难哪，软件构架设计师的要求呢？大家好好想想吧。）<br /><b>本文目录<br /></b>一、与构架有关的几个基本概念；<br />二、构架设计应考虑的因素概揽；<br />三、程序的运行时结构方面的考虑；<br />四、源代码的组织结构方面的考虑；<br />五、写系统构架设计文档应考虑的问题<br />六、结语 
<p><b>一、与构架有关的几个基本概念：<br /></b>1、模块（module）：一组完成指定功能的语句，包括：输入、输出、逻辑处理功能、内部信息、运行环境（与功能对应但不是一对一关系）。<br />2、组件（component）：系统中相当重要的、几乎是独立的可替换部分，它在明确定义的构架环境中实现确切的功能。<br />3、模式（pattern）：指经过验证，至少适用于一种实用环境（更多时候是好几种环境）的解决方案模板（用于结构和行为。在 UML 中：模式由参数化的协作来表示，但 UML 不直接对模式的其他方面（如使用结果列表、使用示例等，它们可由文本来表示）进行建模。存在各种范围和抽象程度的模式，例如，构架模式、分析模式、设计模式和代码模式或实施模式。模式将可以帮助我们抓住重点。构架也是存在模式的。比如，对于系统结构设计，我们使用层模式；对于分布式系统，我们使用代理模式（通过使用代理来替代实际的对象，使程序能够控制对该对象的访问）；对于交互系统，我们使用MVC（M模型(对象)／V视图(输出管理)／C控制器(输入处理)）模式。模式是针对特定问题的解，因此，我们也可以针对需求的特点采用相应的模式来设计构架。<br />4、构架模式（architectural pattern）：表示软件系统的基本结构组织方案。它提供了一组预定义的子系统、指定它们的职责，并且包括用于组织其间关系的规则和指导。<br />5、层（layer）：对模型中同一抽象层次上的包进行分组的一种特定方式。通过分层，从逻辑上将子系统划分成许多集合，而层间关系的形成要遵循一定的规则。通过分层，可以限制子系统间的依赖关系，使系统以更松散的方式耦合，从而更易于维护。（层是对构架的横向划分，分区是对构架的纵向划分）。<br />6、系统分层的几种常用方法：<br />1） 常用三层服务：用户层、业务逻辑层、数据层；<br />2） 多层结构的技术组成模型：表现层、屑洳恪⑹莶悖?br&gt; 3） 网络系统常用三层结构：核心层、汇聚层和接入层；<br />4） RUP典型分层方法：应用层、专业业务层、中间件层、系统软件层；<br />5） 基于Java的B/S模式系统结构：浏览器端、服务器端、请求接收层、请求处理层；<br />6） 某六层结构：功能层（用户界面）、模块层、组装层（软件总线）、服务层（数据处理）、数据层、核心层；<br />7、构架（Architecture，愿意为建筑学设计和建筑物建造的艺术与科学）: 在RUP中的定义：软件系统的构架（在某一给定点）是指系统重要构件的组织或结构，这些重要构件通过接口与不断减小的构件与接口所组成的构件进行交互；《软件构架实践》中的定义：某个软件或者计算系统的软件构架即组成该系统的一个或者多个结构，他们组成软件的各个部分，形成这些组件的外部可见属性及相互间的联系；IEEE 1471-2000中的定义：the fundamental organization of a system emboided in its components,their relationships to each other,and to the enviroment and the principles guiding its design and evolution，构架是系统在其所处环境中的最高层次的概念。软件系统的构架是通过接口交互的重要构件（在特定时间点）的组织或结构，这些构件又由一些更小的构件和接口组成。（“构架”可以作为名词，也可作为动词，作为动词的“构架”相当于“构架设计”）<br />8、构架的描述方式：“4＋1”视图（用例视图、设计视图、实现视图、过程视图、配置视图）是一个被广为使用的构架描述的模型；RUP过程的构架描述模板在“4＋1”视图的基础上增加了可选的数据视图（从永久性数据存储方面来对系统进行说明）；HP公司的软件描述模板也是基于“4＋1”视图。<br />9、结构：软件构架是多种结构的体现，结构是系统构架从不同角度观察所产生的视图。就像建筑物的结构会随着观察动机和出发点的不同而有多种含义一样，软件构架也表现为多种结构。常见的软件结构有：模块结构、逻辑或概念结构、进程或协调结构、物理结构、使用结构、调用结构、数据流、控制流、类结构等等。 </p><p><b>二、构架设计应考虑的因素概揽：<br /></b>模块构架设计可以从程序的运行时结构和源代码的组织结构方面考虑。<br />1、程序的运行时结构方面的考虑：<br />1） 需求的符合性：正确性、完整性；功能性需求、非功能性需求；<br />2） 总体性能（内存管理、数据库组织和内容、非数据库信息、任务并行性、网络多人操作、关键算法、与网络、硬件和其他系统接口对性能的影响）；<br />3） 运行可管理性：便于控制系统运行、监视系统状态、错误处理；模块间通信的简单性；与可维护性不同；<br />4） 与其他系统接口兼容性；<br />5） 与网络、硬件接口兼容性及性能；<br />6） 系统安全性；<br />7） 系统可靠性；<br />8） 业务流程的可调整性；<br />9） 业务信息的可调整性<br />10） 使用方便性<br />11） 构架样式的一致性<br />注：运行时负载均衡可以从系统性能、系统可靠性方面考虑。<br />2、源代码的组织结构方面的考虑：<br />1） 开发可管理性：便于人员分工（模块独立性、开发工作的负载均衡、进度安排优化、预防人员流动对开发的影响）、利于配置管理、大小的合理性与适度复杂性；<br />2） 可维护性：与运行可管理性不同；<br />3） 可扩充性：系统方案的升级、扩容、扩充性能；<br />4） 可移植性：不同客户端、应用服务器、数据库管理系统；<br />5） 需求的符合性（源代码的组织结构方面的考虑）。 <br /><br /><b>三、程序的运行时结构方面的考虑：<br /></b>1、 需求的符合性：正确性、完整性；功能性需求、非功能性需求<br />软件项目最主要的目标是满足客户需求。在进行构架设计的时候，大家考虑更多的是使用哪个运行平台、编成语言、开发环境、数据库管理系统等问题，对于和客户需求相关的问题考虑不足、不够系统。如果无论怎么好的构架都无法满足客户明确的某个功能性需求或非功能性需求，就应该与客户协调在项目范围和需求规格说明书中删除这一需求。否则，架构设计应以满足客户所有明确需求为最基本目标，尽量满足其隐含的需求。（客户的非功能性需求可能包括接口、系统安全性、可靠性、移植性、扩展性等等，在其他小节中细述）<br />一般来说，功能需求决定业务构架、非功能需求决定技术构架，变化案例决定构架的范围。需求方面的知识告诉我们，功能需求定义了软件能够做些什么。我们需要根据业务上的需求来设计业务构架，以使得未来的软件能够满足客户的需要。非功能需求定义了一些性能、效率上的一些约束、规则。而我们的技术构架要能够满足这些约束和规则。变化案例是对未来可能发生的变化的一个估计，结合功能需求和非功能需求，我们就可以确定一个需求的范围，进而确定一个构架的范围。（此段From林星）<br />这里讲一个前几年因客户某些需求错误造成构架设计问题而引起系统性能和可靠性问题的小小的例子：此系统的需求本身是比较简单的，就是将某城市的某业务的全部历史档案卡片扫描存储起来，以便可以按照姓名进行查询。需求阶段客户说卡片大约有20万张，需求调研者出于对客户的信任没有对数据的总量进行查证。由于是中小型数据量，并且今后数据不会增加，经过计算20万张卡片总体容量之后，决定使用一种可以单机使用也可以联网的中小型数据库管理系统。等到系统完成开始录入数据时，才发现数据至少有60万，这样使用那种中小型数据库管理系统不但会造成系统性能的问题，而且其可靠性是非常脆弱的，不得不对系统进行重新设计。从这个小小的教训可以看出，需求阶段不仅对客户的功能需求要调查清楚，对于一些隐含非功能需求的一些数据也应当调查清楚，并作为构架设计的依据。<br />对于功能需求的正确性，在构架设计文档中可能不好验证（需要人工、费力）。对于功能需求完整性，就应当使用需求功能与对应模块对照表来跟踪追溯。对于非功能需求正确性和完整性，可以使用需求非功能与对应设计策略对照表来跟踪追溯评估。<br />“软件设计工作只有基于用户需求，立足于可行的技术才有可能成功。”<br />2、 总体性能<br />性能其实也是客户需求的一部分，当然可能是明确的，也有很多是隐含的，这里把它单独列出来在说明一次。性能是设计方案的重要标准，性能应考虑的不是单台客户端的性能，而是应该考虑系统总的综合性能；<br />性能设计应从以下几个方面考虑：内存管理、数据库组织和内容、非数据库信息、任务并行性、网络多人操作、关键算法、与网络、硬件和其他系统接口对性能的影响；<br />几点提示：算法优化及负载均衡是性能优化的方向。经常要调用的模块要特别注意优化。占用内存较多的变量在不用时要及时清理掉。需要下载的网页主题文件过大时应当分解为若干部分，让用户先把主要部分显示出来。<br />3、 运行可管理性<br />系统的构架设计应当为了使系统可以预测系统故障，防患于未然。现在的系统正逐步向复杂化、大型化发展，单靠一个人或几个人来管理已显得力不从心，况且对于某些突发事件的响应，人的反应明显不够。因此通过合理的系统构架规划系统运行资源，便于控制系统运行、监视系统状态、进行有效的错误处理；为了实现上述目标，模块间通信应当尽可能简单，同时建立合理详尽的系统运行日志，系统通过自动审计运行日志，了解系统运行状态、进行有效的错误处理；（运行可管理性与可维护性不同）<br />4、 与其他系统接口兼容性（解释略）<br />5、 与网络、硬件接口兼容性及性能（解释略）<br />6、 系统安全性<br />随着计算机应用的不断深入和扩大，涉及的部门和信息也越来越多，其中有大量保密信息在网络上传输，所以对系统安全性的考虑已经成为系统设计的关键，需要从各个方面和角度加以考虑，来保证数据资料的绝对安全。<br />7、 系统可靠性<br />系统的可靠性是现代信息系统应具有的重要特征，由于人们日常的工作对系统依赖程度越来越多，因此系统的必须可靠。系统构架设计可考虑系统的冗余度，尽可能地避免单点故障。系统可靠性是系统在给定的时间间隔及给定的环境条件下，按设计要求，成功地运行程序的概率。成功地运行不仅要保证系统能正确地运行，满足功能需求，还要求当系统出现意外故障时能够尽快恢复正常运行，数据不受破坏。<br />8、 业务流程的可调整性<br />应当考虑客户业务流程可能出现的变化，所以在系统构架设计时要尽量排除业务流程的制约，即把流程中的各项业务结点工作作为独立的对象，设计成独立的模块或组件，充分考虑他们与其他各种业务对象模块或组件的接口，在流程之间通过业务对象模块的相互调用实现各种业务，这样，在业务流程发生有限的变化时（每个业务模块本身的业务逻辑没有变的情况下），就能够比较方便地修改系统程序模块或组件间的调用关系而实现新的需求。如果这种调用关系被设计成存储在配置库的数据字典里，则连程序代码都不用修改，只需修改数据字典里的模块或组件调用规则即可。<br />9、 业务信息的可调整性<br />应当考虑客户业务信息可能出现的变化，所以在系统构架设计时必须尽可能减少因为业务信息的调整对于代码模块的影响范围。<br />10、 使用方便性<br />使用方便性是不须提及的必然的需求，而使用方便性与系统构架是密切相关的。WinCE（1.0）的失败和后来改进版本的成功就说明了这个问题。WinCE（1.0）有太多层次的视窗和菜单，而用户则更喜欢简单的界面和快捷的操作。失败了应当及时纠正，但最好不要等到失败了再来纠正，这样会浪费巨大的财力物力，所以在系统构架阶段最好能将需要考虑的因素都考虑到。当然使用方便性必须与系统安全性协调平衡统一，使用方便性也必须与业务流程的可调整性和业务信息的可调整性协调平衡统一。“满足用户的需求，便于用户使用，同时又使得操作流程尽可能简单。这就是设计之本。”<br />11、构架样式的一致性<br />软件系统的构架样式有些类似于建筑样式（如中国式、哥特式、希腊复古式）。软件构架样式可分为数据流构架样式、调用返回构架样式、独立组件构架样式、以数据为中心的构架样式和虚拟机构架样式，每一种样式还可以分为若干子样式。构架样式的一致性并不是要求一个软件系统只能采用一种样式，就像建筑样式可以是中西结合的，软件系统也可以有异质构架样式（分为局部异质、层次异质、并行异质），即多种样式的综合，但这样的综合应该考虑其某些方面的一致性和协调性。每一种样式都有其使用的时机，应当根据系统最强调的质量属性来选择。  </p><p><br /><b>四、源代码的组织结构方面的考虑：<br /></b>1、 开发可管理性<br />便于人员分工（模块独立性、开发工作的负载均衡、进度安排优化、预防人员流动对开发的影响：一个好的构架同时应有助于减少项目组的压力和紧张，提高软件开发效率）、利于配置管理、大小的合理性、适度复杂性；<br />1）便于人员分工－模块独立性、层次性<br />模块独立性、层次性是为了保证项目开发成员工作之间的相对独立性，模块联结方式应该是纵向而不是横向, 模块之间应该是树状结构而不是网状结构或交叉结构，这样就可以把开发人员之间的通信、模块开发制约关系减到最少。同时模块独立性也比较利于配置管理工作的进行。现在有越来越多的的软件开发是在异地进行，一个开发组的成员可能在不同城市甚至在不同国家，因此便于异地开发的人员分工与配置管理的源代码组织结构是非常必要的。<br />2）便于人员分工－开发工作的负载均衡<br />不仅仅是开发出来的软件系统需要负载均衡，在开发过程中开发小组各成员之间工作任务的负载均衡也是非重要的。所谓工作任务的负载均衡就是通过合理的任务划分按照开发人员特点进行分配任务，尽量让项目组中的每个人每段时间都有用武之地。这就需要在构架设计时应当充分考虑项目组手头的人力资源，在实现客户需求的基础上实现开发工作的负载均衡，以提高整体开发效率。<br />3）便于人员分工－进度安排优化；<br />进度安排优化的前提是模块独立性并搞清楚模块开发的先后制约关系。利用工作分解结构对所有程序编码工作进行分解，得到每一项工作的输入、输出、所需资源、持续时间、前期应完成的工作、完成后可以进行的工作。然后预估各模块需要时间，分析各模块的并行与串行（顺序制约），绘制出网络图，找出影响整体进度的关键模块，算出关键路径，最后对网络图进行调整，以使进度安排最优化。<br />有个家喻户晓的智力题叫烤肉片策略：约翰逊家户外有一个可以同时烤两块肉片的烤肉架，烤每块肉片的每一面需要10分钟，现要烤三块肉片给饥肠辘辘急不可耐的一家三口。问题是怎样才能在最短的时间内烤完三片肉。一般的做法花20分钟先烤完前两片，再花20分钟烤完第三片。有一种更好的方法可以节省10分钟，大家想想。<br />4）便于人员分工－预防员工人员流动对开发的影响<br />人员流动在软件行业是司空见惯的事情，已经是一个常见的风险。作为对这一风险的有效的防范对策之一，可以在构架设计中考虑到并预防员工人员流动对开发的影响。主要的思路还是在模块的独立性上（追求高内聚低耦合），组件化是目前流行的趋势。<br />5）利于配置管理（独立性、层次性）<br />利于配置管理与利于人员分工有一定的联系。除了逻辑上的模块组件要利于人员分工外，物理上的源代码层次结构、目录结构、各模块所处源代码文件的部署也应当利于人员分工和配置管理。（尽管现在配置管理工具有较强大的功能，但一个清楚的源码分割和模块分割是非常有好处的）。<br />6）大小的合理性与适度复杂性<br />大小的合理性与适度复杂性可以使开发工作的负载均衡，便于进度的安排，也可以使系统在运行时减少不必要的内存资源浪费。对于代码的可阅读性和系统的可维护性也有一定的好处。另外，过大的模块常常是系统分解不充分，而过小的模块有可能降低模块的独立性，造成系统接口的复杂。<br />2、 可维护性<br />便于在系统出现故障时及时方便地找到产生故障的原因和源代码位置，并能方便地进行局部修改、切割；（可维护性与运行可管理性不同）<br />3、 可扩充性：系统方案的升级、扩容、扩充性能<br />系统在建成后会有一段很长的运行周期，在该周期内，应用在不断增加，应用的层次在不断升级，因此采用的构架设计等方案因充分考虑升级、扩容、扩充的可行性和便利<br />4、 可移植性<br />不同客户端、应用服务器、数据库管理系统：如果潜在的客户使用的客户端可能使用不同的操作系统或浏览器，其可移植性必须考虑客户端程序的可移植性，或尽量不使业务逻辑放在客户端；数据处理的业务逻辑放在数据库管理系统中会有较好的性能，但如果客户群中不能确定使用的是同一种数据库管理系统，则业务逻辑就不能数据库管理系统中；<br />达到可移植性一定要注重标准化和开放性：只有广泛采用遵循国际标准，开发出开放性强的产品，才可以保证各种类型的系统的充分互联，从而使产品更具有市场竞争力，也为未来的系统移植和升级扩展提供了基础。<br />5、 需求的符合性<br />从源代码的组织结构看需求的符合型主要考虑针对用户需求可能的变化的软件代码及构架的最小冗余（同时又要使得系统具有一定的可扩展性）。 </p><p><br /><b>五、写系统构架设计文档应考虑的问题<br /></b>构架工作应该在需求开发完成约80％的时候开始进行，不必等到需求开发全部完成，需要项目经理以具体的判断来评估此时是否足以开始构建软件构架。<br />给出一致的轮廓：系统概述。一个系统构架需要现有概括的描述，开发人员才能从上千个细节甚至数十个模块或对象类中建立一致的轮廓。<br />构架的目标应该能够清楚说明系统概念，构架应尽可能简化，最好的构架文件应该简单、简短，清晰而不杂乱，解决方案自然。<br />构架应单先定义上层的主要子系统，应该描述各子系统的任务，并提供每个子系统中各模块或对象类的的初步列表。<br />构架应该描述不同子系统间相互通信的方式，而一个良好的构架应该将子系统间的通信关系降到最低。<br />成功构架的一个重要特色，在于标明最可能变更的领域，应当列出程序中最可能变更的部分，说明构架的其他部分如何应变。<br />复用分析、外购：缩短软件开发周期、降低成本的有效方案未必是自行开发软件，可以对现有软件进行复用或进行外购。应考虑其对构架的影响。<br />除了系统组织的问题，构架应重点考虑对于细节全面影响的设计决策，深入这些决策领域：外部软件接口（兼容性、通信方式、传递数据结构）、用户接口（用户接口和系统层次划分）、数据库组织和内容、非数据库信息、关键算法、内存管理（配置策略）、并行性、安全性、可移植性、网络多人操作、错误处理。<br />要保证需求的可追踪性，即保证每个需求功能都有相应模块去实现。<br />构架不能只依据静态的系统目标来设计，也应当考虑动态的开发过程，如人力资源的情况，进度要求的情况，开发环境的满足情况。构架必须支持阶段性规划，应该能够提供阶段性规划中如何开发与完成的方式。不应该依赖无法独立运行的子系统构架。将系统各部分的、依赖关系找出来，形成一套开发计划。 </p><p><br /><b>六、结语<br /></b>系统构架设计和千差万别的具体的开发平台密切相关，因此在此无法给出通用的解决方案，主要是为了说明哪些因素是需要考虑的。对于每个因素的设计策略和本文未提到的因素需要软件构架设计师在具体开发实践中灵活把握。不同因素之间有时是矛盾的，构架设计时需要根据具体情况进行平衡。 </p><p><b>参考文献<br /></b>《软件构架实践》SEI软件工程译丛，林·巴斯著<br />《微软项目：求生法则》Steve McConnell著，余孟学译<br />《实用软件工程》第二版，郑人杰、殷人昆、陶永雷等著<br />《软件工程：实践者的研究方法》（第5版）Roger S.Pressman著<br />《软件开发的科学与艺术》陈宏刚等著<br />本文作者邮箱：luls@dragonsoft.com.cn或lulsnet@21cn.com<br /></p><img src ="http://www.blogjava.net/faithwind/aggbug/65789.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/faithwind/" target="_blank">黑咖啡</a> 2006-08-25 14:38 <a href="http://www.blogjava.net/faithwind/articles/65789.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>客户关系管理 数据库设计案例</title><link>http://www.blogjava.net/faithwind/articles/65790.html</link><dc:creator>黑咖啡</dc:creator><author>黑咖啡</author><pubDate>Fri, 25 Aug 2006 06:38:00 GMT</pubDate><guid>http://www.blogjava.net/faithwind/articles/65790.html</guid><wfw:comment>http://www.blogjava.net/faithwind/comments/65790.html</wfw:comment><comments>http://www.blogjava.net/faithwind/articles/65790.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/faithwind/comments/commentRss/65790.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/faithwind/services/trackbacks/65790.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: [序言]				自从上一文发表于www.sawin.cn之后,一直就想续完发此文与大家一起探讨学习数据库应用系统中的设计与实现.其实此文的发出源于我的构想由于种种原因未能得以实践,实为憾之.此次实乃挥泪而贴.想借此一角以慰我心,如有意实现者可与我QQ联系.278871578														[客户关系管理]																				...&nbsp;&nbsp;<a href='http://www.blogjava.net/faithwind/articles/65790.html'>阅读全文</a><img src ="http://www.blogjava.net/faithwind/aggbug/65790.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/faithwind/" target="_blank">黑咖啡</a> 2006-08-25 14:38 <a href="http://www.blogjava.net/faithwind/articles/65790.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>软件测试的革命</title><link>http://www.blogjava.net/faithwind/articles/65788.html</link><dc:creator>黑咖啡</dc:creator><author>黑咖啡</author><pubDate>Fri, 25 Aug 2006 06:37:00 GMT</pubDate><guid>http://www.blogjava.net/faithwind/articles/65788.html</guid><wfw:comment>http://www.blogjava.net/faithwind/comments/65788.html</wfw:comment><comments>http://www.blogjava.net/faithwind/articles/65788.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/faithwind/comments/commentRss/65788.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/faithwind/services/trackbacks/65788.html</trackback:ping><description><![CDATA[
		<p>爱因斯坦在1915年发表了广义相对论，当时这还只是一项伟大的科学猜想。4年后，Arthur Eddington和一个英国科学家组成的小组完成了一项重要的实验，在实验中他们拍摄了在日蚀过程中Hyades星云的图片，该实验表明，因受日蚀影响，图片中产生了很大的误差幅度，由此证明了爱因斯坦关于空间的弯曲和光的重力效应的预测。大众媒体随即给予爱因斯坦和Eddington很高的荣誉。同时也因为他们两人都是和平主义者，所以被一起推崇为在这个饱受战争沧桑的世界上的英雄。<br />虽然媒体显得急不可待，但值得注意的是，广义相对论在当时的科学界仍受到广泛的争议。直到半个世纪以后，人们才终于迎来了具有决定性的实验结果。当时Thomas Kuhn写下了《科学革命的结构（The Structure of Scientific Revolutions）》一书，相对论被作为是革命性变革的完美例子-- 一种新的观念完全替代了一整套旧的信仰。<br />今年7月，我代表Rational Edge采访了Cem Kaner。当时他借用了Kuhn的结构对目前软件测试领域盛行的各种争议和尚未确证的理论进行了分类。</p>
		<p>后来，Rational Edge发表了我和软件测试方面的其他专家的一些访谈。有些读者却质疑我的选择，他们会问：“这和我现在做的主要工作有什么关系？”<br />因此，在本文中，我想把所有这些课题放在一起，并对自己关于未来测试领域的发展的前瞻进行阐述。我可以断言的是，测试人员、开发人员、项目管理人员、公司管理人员和最终用户们都期待着看到在这10年里软件测试实践方面将要发生的大变革。其原因很简单，--软件质量的低下已经使美国经济蒙受巨大损失，NIST估计[注1]，每年损失约600亿美元，而Standish组织的数据则是2000亿美元。所以改进软件质量已成为取得高投资回报率（ROI）的直接途径，只有那些把握了软件质量的企业才会赢得胜利，其余的则将被人们所遗忘。<br />这些实践和工具又是什么呢？我认为随着时间的发展，以下五种趋势会得到发展和应用。<br />1. 测试驱动型的软件开发。在软件生命周期的各个阶段中，这些阶段包括测试、需求分析、使用形象化符号进行的规格说明，以及基于UML和其它新标准的实践；<br />2. 探索性学习和发现，这将成为迭代开发过程的一个组成部分；<br />3. 组件测试和易测试性设计，这将成为软件开发不可分割的组成部分；<br />4. 更加重视适当的技能的应用，减少预先写好的文档，这将成为优秀软件过程的基本原则之一；<br />5. 使用自动化测试来取代目前严重影响测试效率的冗余繁复的人工过程。<br />下面让我来对这些趋势进行说明。</p>
		<p>
				<b>测试驱动型开发</b>
		</p>
		<p>这一实践在RUP过程中又称为“测试第一的设计（test-first design）”，而在很多XP( eXtreme Programming)文章中则称之为“测试第一的开发（test-first programming）”。这一设想的提出至今已有近十年了，但是直到最近才得以在开发这一层次上取得很大的支持，这要在很大程度上感谢敏捷方法组织。他们的核心思想是，在你写一行代码之前，你要先写一行对其失效所进行的测试。在该测试的描述中应包含一个程序代码实际运行的实例。Martin Fowler将这样的测试称为“带实例的规格说明（specification by example）”。<br />Brain Marick和其他一些敏捷测试的支持者已经提出建议，要把测试驱动开发的概念扩展到所有的层次，包括系统测试和产品级测试[注2]。Marick很清晰地表述了他的观点：“我并不想写出一套用于捕捉用户愿望的需求，取而代之的是，我要写出一套测试，一旦这些测试能够通过，产品就能使她满意。所以我放弃需求编写的步骤，而直接把需求分析加入到测试的创建过程中去。”[注3]这些测试脚本就象是可执行的规格说明，当程序代码通过了测试，那么这些程序代码也将和规格说明保持一致。<br />如果你的代码是使用Java，而且你的测试也在Java中测试，那么测试很可能会基于JUnit，你可能要么是一个人，要么是编写的两人组中的一个，不管是哪一种情况，都很容易看到，这时Marick的方法是可行的。Marick相信这是可伸缩的，可以适合于小团体，或者在有一个用户在场的条件下进行“交谈式测试的创建（conversational test creation）”的实践。但是，如果有人要了解需求，这些需求却是在测试设计中被捕捉的，而你并不在场，无法直接为他们进行解释，这样就存在明显的问题。在这种前提下，我并不认为测试一定要在程序语言中体现。即使对需求有了“精确”的表达，也不足以解决可理解性的问题。对于这一问题，Leffingwell和Widrig有很好的描述[注4]，下图即是基于他们的观点。</p>
		<p align="center">
				<img height="317" src="http://www.sawin.cn/doc/SoftMethod/TDD/Revolution1.gif" width="449" border="0" />
		</p>
		<p align="center">图1：可理解性问题（基于Leffingwell和Widrig的观点）</p>
		<p>
				<br />实际上，Leffingwell和Widrig并没有真正地考虑到测试的问题。他们的主要目的是想让需求具备很高的可理解性，以便于让用户和投资者能够充分理解。他们没有解决这样的问题，即如何把规格说明提交给其他投资者和生命周期的其它阶段。作为一种争议，他们认为有必要保留一部分不明确性。而实际上，不明确的需求显然会让测试人员发疯。<br />Marick提出的测试驱动型开发方法则走向另一个极端：测试代表了需求，测试的表现形式是一些可编译、可执行的代码。但是，如果测试（需求）的唯一表现形式是代码的话，你就很难和商务人员/投资者/客户进行有效沟通，甚至也很难和其他测试人员及开发人员进行沟通。所有这些人都认为测试的形式本该是数据和流程，所以如果要以那种方式来做的话，你的测试必须变得非常容易进行交流。<br />一些公司正致力于为这种隔阂提供解决之道。Rational正积极参与一个OMG团体关于UML测试预定义项目，该项目可以把测试表示为数据和可视化的流程，例如顺序图和活动图。我们正在开发一些工具来对待以下三种表示方法，代码，数据和流程，并取代类似的测试视图。<br />在过去，我们制作了这些“实例化规格说明”，按照RUP的命名方法，可称之为“用例实现”。“实例化规格说明”和“用例实现”的相似性可以通过援引最近的一个使用Agile方法的工作团体的报告来说明：<br />[一个参与者]提到，和他一起工作的人都很喜欢使用“测试第一”的开发方式。当测试框架被开发好以后，特别是当用于组织运行的测试脚本被定义好时，他们的工作变得更为容易。而用例在组织起来开发脚本时会有所帮助。他们的测试可以捕捉到用户的需要。人们之所以喜欢这样的方法，其原因是它提供了他们工作所需的结构。在Agile方法中，需求以“案例(story)”的形式存在。于是，测试脚本将以接口已明确定义好的形式把这些“案例”编织在一起。这意味着结对编程的人可以根据他们需要的顺序相互测试接口[注5]。<br />类似地，OMG测试预定义工作组发现，将UML排列起来也很容易。你可以将一个用例实现转成为测试，这只需增加两件东西：验证工作（例如，“现在用测试来检查这个软件中的条件。”）以及裁决（例如，通过、失败，或者暂不决定）。这样的信息在规格说明中随处可以捕捉到，所以UML符号可以让我们测试人员有了表达的手段。<br />于是，只需要额外做一点点努力，就可以使测试对客户来说变得很容易理解：数据表和可视化流程。然后，当有软件需要测试的时候，测试已准备就绪。这一实践使测试驱动型开发在系统级测试上也具有实用的价值，因为在设计工件和测试设计工件之间确实没有什么区别。仅仅只要增加验证的注解以及进行裁决就可以了。在比较容易理解的可视化流程和数据的帮助下，你不再需要把系统设计从测试设计中分离出来。而且由于这些流程具有一个可执行的形式（生成的代码），因此可以把每一次创建作为测试来执行。这使整个团队得到了解放，并成为Kent Beck和Erich Gamma所说的"受影响的测试（test infected）":<br />“...这是一种测试的类型，只要使用非常小的投入即可使你成为一个更快的、更多产的、更具预见性的、压力更小的开发者。”<br />-Kent Beck和Erich Gamma《Test Infected: Programmers Love Writing Tests》[注6]</p>
		<p>
				<b>探索性学习</b>
		</p>
		<p>这第二种趋势认识到了这样的现实，即我们通常很难把问题描述得十分正确：需求在演变，我们需要简化（扁平化）或者把著名的“错误-代价”曲线颠倒过来。这里的核心思想是：我所说的每一项，不管是在产品、测试或者跟踪排错的第一步，都在运行软件时通过探索性发现，才使得可视化-可执行-设计-测试的整个过程和结果变得更为真实。<br />实时分析工具，例如Rational PurifyPlus就带有制作精良的非常明确的实例，例如发现内存错误和性能上的瓶颈。你还可以用它们来支持更广泛的探索，尤其是在由各种不同组件所构成的系统中。80%的企业级行为都是对某些组件的重新组装，包括对遗留下来的成分进行更新或补充等等，而不是从头开始设计。<br />在软件运行时你会发现很多新的信息，至少和设计时一样多。这也是RUP强调要把可运行的软件作为每一次迭代的组成部分的缘故。你发现的每一样东西都应该是可视的，并且放在你用于设计的同样的工件中。对运行着的系统的跟踪是一种UML的迭代，经过验证和裁决，可以转化为一种可复用的测试。数据也值得进行概括，并形成新的等价类的基础，等等。<br />当前，大多数探索性测试的提倡者，尤其是Kaner和Bach，都把这作为使用后即可放弃的行为[注7]。但我认为，我们一旦把所探索到的内容无缝地加入到设计中去后，就会发现，这是高度可重用的。事实上，这是实时分析的一个新的应用：通过探索而发现的有价值的东西的捕获和利用。</p>
		<p>
				<b>组件测试和易测试性设计</b>
		</p>
		<p>第三种趋势是关于理解测试人员和开发人员的相对角色，并为每种角色分配合适的工具。Rational把提供组件测试和易测试性设计作为一种最佳实践，这已有很长的历史。我认为对这些做法的采纳源自于对质量的基本理解。当前，太多的测试人员的行为都受限于规格说明的模式，其中有很多浪费。其实开发人员才有责任去保证所开发出来的软件和规格要求相一致，他们应该使用合适的工具和过程来达到这样的目的。<br />Boris Beizer描述了2种不同角色的区别：<br />独立测试的目的是提供一种不同的观察点，由此产生了不同的测试，并且在比开发人员所采用的开发环境更丰富的环境中执行测试。自我测试（self-testing）的目的是消除那些bug，这可以在相对更简单、更明确的单元/组件环境，或者低层次的系统测试中进行，并且只需花费较低的代价。[注8]<br />测试驱动型开发提供更大的能力。如果规格说明就是可执行的测试，而测试进行没有产生别的问题，那么就可以认为软件和规格说明相符。其它的单元测试过程也只是为了保证同样的事情：就规格说明而言，不管它们是什么内容，代码总是与之相符合的。如果不符合，那么就是开发人员的问题。Kent Beck非常清楚测试驱动型开发所带来的效果：<br />如果测试驱动编码的缺陷密度达到足够低的话，那么专业测试的角色将不可避免地发生改变。以前的是“成人监护”方式，而现在更类似于一种扩音器，它宣称测试要更多地验证的是系统必须做什么。[注9]<br />这需要整个团队接受这样的一个前提，即保证软件符合规格说明是开发人员的职责。这使得测试者可以有更多精力用于发现和避免一些别的问题，从客户或者用户的角度来看，这些问题的存在可能会使软件所应有的价值有所降低。Brian Marick针对这些冗长烦琐做法的错误性写过一篇很著名的文章[注10]。那些文档通常已说明了一个系统中的多于一半的错误，他声称，因此你就需要专门有一个过程来让你的测试人员用来发现这些问题。<br />易测试性的设计在这里具有重要的意义。现在很多软件已改用基于服务的构架，这种构架是基于组件的构架的一种扩展，随之而来的是新增加的复杂性，即组件可以在没有警告的情况下发生改变，其可靠性的问题是极为严重的。大多数IT经理会接受99%的可靠性，我敢打赌，他们会认为这一标准甚至已经高于他们所用的买来或构建的组件。但是，如果你构建的系统有超过100个组件，每个组件具有99%的可靠性，那么整个系统的可靠性是0.99的100次方，实际上仅有37%。顺便提一下，这也是为什么那些有高可靠性要求的市场，例如电信业，会要求“5个9”的可靠性，即99.999%。在这样的情况下，你就可以使用100个组件，综合起来仍有99.9%的可靠性。<br />这一基本原理实际上要求软件进行易测试性的设计，就象30年前市场形成时硬件所做的一样。 Bertrand Meyer是这一领域研究的领先者，他提出了按合约设计，其意思是把对类及调用该类的客户端之间的关系的检视作为一种正式的协议，这表达了每个团体的权利和义务[注11]。Meyer的概念已被广泛接受，其标志之一就是合约设计的规格语言WSDL的诞生，该语言是Web Service标准的核心[注12]。<br />我认为人们正越来越多地接受易测试性设计。易测试性已成为诸如Web Service等框架和标准的一个补充的组成部分。接口也正成为技术平台和操作系统的一部分。一个比较简单的例子是，J2EE和.NET 中预定义开放式接口和API映射，可以允许工具来检查在运行时刻环境中发生了什么。另一个真实而有益的趋势是人们正使用象Rational  XDETM这样的工具，通过设计模式的方法来构建应用--而易测试性已被置入在设计模式中。模式所构造的组件包括外在的用于测试的接口 -- 即组件的一些适当的getter和setter方法。<br />易测试性设计的一个实用的法则是，你已在GUI和表示层的后面对业务逻辑或软件的行为进行了访问。Bret Pettichord主张，易测试性设计应该是关于可见性和控制的设计[注13]。你通过较低层获得其外在接口，从而得到所需要的可见性，在测试的时候，通过很多开放的接口来允许你直接看到软件中的声明。同样地，你需要接口来让你能够控制应用，由此你才可以避免使用GUI，而是通过自动化框架来驱动应用。</p>
		<p>
				<b>重视技能</b>
		</p>
		<p>第四种趋势是增进软件测试专业技术知识的水准。在.com流行的年代中有这样的误解，即使没有很深的测试技术知识、业务应用方面的领域知识以及充分的培训，你也能有效地进行测试。但当你面对一个分布式的应用--例如，一个特别的基于Web的应用，就会发生问题。Hung Nguyen关于基于Web应用的测试论著是这种观点最好的代表[注14]。Nguyen认为，测试人员应该知道技术是如何对他们所看到的各种错误产生影响的。他们需要对技术问题有所理解，例如配置的问题，以及他们所检查的技术本身内含的问题。各种细节上的理解，例如了解应用服务器中Bean和Container管理的持续性之间的区别，可以直接影响到你发现特定缺陷的能力。<br />所以，现在的测试人员除了测试本身的技术以外，还需要理解开发技术和领域知识。例如，假设你在浏览器中看到一个错误：“404 - Page not found”这样的错误可能是错误的链接所引起，也可能是因为某些服务失效而产生。一个好的测试人员并不会在出错页上就停下来，他会进一步诊断出错的原因。他不仅需要对该失效的服务具备足够多的认识和理解，而且他要通过查看其它使用该服务的页面来验证自己的猜测。这就是一种Bug隔离的重要技能。<br />另一种技能是成为一个很好的探索者。以前，测试方面的很多论述对计划和脚本有很多要求，但现实情况下，一个好的测试人员就是一个好的探索者。他们喜欢在测试过程中发现一些暗示，并知道怎么来进行跟踪。这样的暗示有时很简单，例如一个页面要很长时间才能加载。那么对于一个好的测试人员来说，他可能会想，这其中发生了什么？然后继续了解要通过什么路径可以进一步发现答案。James Bach所写的一些内容可能是在探索性测试方面最好的材料[注15]，其中有该课题的最佳练习。我认为这显然也是一个重要的技能，每个团队都需要这样的技能。<br />我们在Rational学院的课程中已经非常重视如何去应用基本的软件测试技术。可以和Florida Tech的Cem Kaner一起开始那些专为测试人员提供的软件测试基本原理的新课程[注16]。该课程并不专注于测试工具，而是专注于如何成为一名很好的软件测试人员，尤其是当你正在应用迭代开发过程的时候。最后，测试人员的生产能力和开发人员的生产能力是同样重要的，只有富有经验的测试人员才能使产品让客户获得很高的投资回报率（ROI）。Rational已经发现，一个更快、更经济、更高质量的开发过程的关键就是迭代式开发过程。迭代式过程可以使测试在整个开发周期中得以提前，从而可以更早地发现错误，修改错误也相对更加容易，其成本也相对更低。<br />但是，我认为现在的测试人员还没有得到很好的训练以胜任迭代开发过程中的测试工作要求，项目经理也没有得到很好的训练以正确地认识测试在迭代项目中所扮演的角色，开发人员也没有得到很好的训练以得到他们需要了解的测试相关技术，例如基础等价类划分。因此我们在RUP(Rational Unified Process)和Rational学院中增加了大量关于测试的材料。而且我们还将继续扩充这些材料以帮助测试人员、开发人员和项目经理们在迭代过程的协同工作中做得更好。</p>
		<p>
				<b>自动化测试</b>
		</p>
		<p>第五种趋势是关于测试自动化方面。目前，为了实行测试自动化，测试人员和开发人员要花费80%的精力来使（自动化）测试成为可能，而只有20%被用于使（自动化）测试变得更有意义。这一可怕的事实使很多人最终放弃了测试自动化。同样，目前的自动化软件质量(ASQ) 工具提供商正花费80%的精力用于重复工作，他们必须重新创建一个基础平台来支持相应的测试和排错工作，而仅有20%的精力来为测试和开发人员提供可见的有价值的功能。<br />最近，Rational、IBM和其它一些公司开展了一个开发源码的项目，其目标就是要把这两个百分数颠倒过来。该项目被命名为Hyades，取自Eddington用来校验爱因斯坦理论的星云的名字，并由Eclipse.org负责。它的目标也包括加强实验性观察，测试过程及软件度量，最终实现更具实用性的测试自动化。<br /><br />对于使用Eclipse的开发人员和测试人员来说，Hyades既是一种集成测试及跟踪，也是环境监控程序。Eclipse为整个测试过程提供了标准、工具和互操作性，以使测试能更早地移植到应用生命周期中去。对ASQ提供商和集成商来说，Hyades为自动化测试、跟踪、预定义、监控和资源管理提供了一个可扩展的架构和平台。和目前的测试与跟踪工具所不同的是，Hyades将提供一个统一数据模型（实现了UML测试预定义），这是一种标准的用户工作的流程，包括一套统一的API及相关工具，可以在排列的目标项之间连续地工作。</p>
		<p>
				<b>总结：测试实践的大变革</b>
		</p>
		<p>Rational和一些竞争对手尽管自己也提供商业测试工具，为什么还要加入到象Hyades这样的开放源码项目中去呢？ 我的很多同事也问过这样的问题。其核心理由就是上面所说的80/20比例。所有人都很想改变这个比例。<br />80%的基础平台对用户来说是不可见的，它难以分辨，也难以维护。每当测试所用软件的环境条件更新的时候，(新的编译器，新的库文件，新的操作系统补丁，等等），测试工具就必须随之更新。如果你是一位富有经验的实时分析或自动化工具的用户，你可能早已感受到这种脆弱。你也许已经不止一次在考虑要更换开发环境，因为有些工具不支持一些新的版本。这一维护成本给工具提供商带来了巨大的压力，因此工具商们决定无偿地为新的引擎工作，并分享其成果，进而满足用户的需要。Hyades项目必将为我们的用户提供其价值。 </p>
		<p>对Hyades来说，它是由一系列分散的努力所组成。在我所归纳的五种趋势中，Hyades是其中的一个组成部分，它将同时为测试人员和开发人员提供新的测试支持方式。这是一种技术，它可以在生命周期的一开始就推动测试，带来工具方面更好的协同性，通过改进测试，新的效果会明显地加入到软件中去。它将为这10年里我能所能看到的在测试实践上的改革提供有力的支持。我相信这种技术，以及其它有类似目标和基础的技术，代表着我们产业的未来。我们这些已被卷入到Hyades项目中的人都有一种使命感，我们不能辜负Hyades这一名称：<br />让我们描画出金牛座的头部--Hyades星云中的恒星，这对我们来说意义重大，这将带给我们快乐，并使我们能够测量整个宇宙！<br />--Anthony G. A. Brown, Universidad Nacional Autýnoma de Mýxico.<br /></p>
		<p>
				<b>备注：</b>
				<br />1 http://www.nist.gov/director/prog-ofc/report02-3.pdf<br />2 Kent Beck作了一个限定，把Marick的想法改称为"Application-Test-Driven Development"，可参考Kent Beck《Test-Driven Development》， Addison- Wesley, 2002, 第199页。<br />3 http://www.therationaledge.com/content/oct_02/f_testFirstDesign_sg.jsp<br />4 Dean Leffingwell和Don Widrig《Managing Software Requirements》 Addison-Wesley, 2000,第273页。<br />5 http://fc-md.umd.edu/projects/Agile/3rd-eWorkshop/topic4.html<br />6 http://junit.sourceforge.net/doc/testinfected/testing.htm<br />7 他们的教程材料已在以下网址中公开：http://www.testingeducation.org/<br />另外，Bach的网站www.satisfice.com也是很有价值的资源。<br />8 Boris Beizer 《Black-Box Testing》， Wiley, 1995, 第13页。<br />9 Beck《Test-Driven Development》，Addison Wesley, 2002, 第86页。<br />10 http://www.testing.com/writings/omissions.pdf<br />11 Meyer《 Object-Oriented Software Construction》第2版，Prentice Hall, 1997, 第331页<br />12 参见http://www.w3.org/2002/ws/ 和http://www.ws-i.org/<br />13 参见诸如http://www.therationaledge.com/content/nov_02/f_pettichordInterview_sg.jsp中的讨论<br />14 Hung Q. Nguyen《Testing Applications on the Web》， Wiley, 2001。<br />15 http://www.satisfice.com/articles/what_is_et.htm 可以作为一个很好的起点。<br />16 http://www.therationaledge.com/content/jul_02/f_interviewWithKaner_sg.jsp中可以找到很有价值的相关讨论。</p>
		<p>
				<b>对照：</b>
				<br />以下是翻译时所做的部分词汇处理，以资对照：</p>
		<p>Test-driven development   测试驱动型开发<br />exploratory testing       探索性测试<br />Design for testability    易测试性的设计<br />Design by Contract        合约设计<br />artifact                  工件<br />interaction               迭代<br />stackholder               （项目）投资者<br />Profile                   预定义，概况</p>
		<script language="javascript" src="../../../share/bottom.js">
		</script>
<img src ="http://www.blogjava.net/faithwind/aggbug/65788.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/faithwind/" target="_blank">黑咖啡</a> 2006-08-25 14:37 <a href="http://www.blogjava.net/faithwind/articles/65788.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>项目管理成功之道：做好简单的事情</title><link>http://www.blogjava.net/faithwind/articles/65786.html</link><dc:creator>黑咖啡</dc:creator><author>黑咖啡</author><pubDate>Fri, 25 Aug 2006 06:36:00 GMT</pubDate><guid>http://www.blogjava.net/faithwind/articles/65786.html</guid><wfw:comment>http://www.blogjava.net/faithwind/comments/65786.html</wfw:comment><comments>http://www.blogjava.net/faithwind/articles/65786.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/faithwind/comments/commentRss/65786.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/faithwind/services/trackbacks/65786.html</trackback:ping><description><![CDATA[
		<p style="TEXT-INDENT: 2em">通常任何人对新奇玄妙的理论都抱有特殊的爱好，所以当有人只用朴素的概念进行讲解时，会使那些充满期待的眼神略感失望。 
</p>
		<p style="TEXT-INDENT: 2em">项目管理有时也遇到过同样的现象。 
</p>
		<p style="TEXT-INDENT: 2em">项目的管理出了问题，自然会去咨询专家，可是在听过专家意见后，可能感到颇为失望，以为人家讲授的东西并不深奥，不相信项目管理就是如此简单。 
</p>
		<p style="TEXT-INDENT: 2em">殊不知世界上的事情有时就是很简单，我们不妨介绍几个关于“简单”的故事： 
</p>
		<p style="TEXT-INDENT: 2em">
				<b>“简单”一：如何练习角球</b>
		</p>
		<p style="TEXT-INDENT: 2em">米卢的名字在中国球迷的口中叫得很响，但国家队球员似乎更欣赏英国人霍顿，觉得是霍顿让自己明白了该怎么踢球。 
</p>
		<p style="TEXT-INDENT: 2em">以罚角球为例，原先的教练一般只会说诸如“盯紧了，别让他顶着，拉住了……”等套话，但是霍顿却能明确告诉队员“谁应该在哪，第一点在哪，第二点在哪。” 
</p>
		<p style="TEXT-INDENT: 2em">这些东西虽然简单，但原先没有人告诉大家。 
</p>
		<p style="TEXT-INDENT: 2em">郝海东感叹到：这才叫懂啊！原先就知道去踢。其实这也不是什么高深的事情，但是原来没有人告诉我们。 
</p>
		<p style="TEXT-INDENT: 2em">
				<b>“简单”二：如何服从指挥</b>
		</p>
		<p style="TEXT-INDENT: 2em">史迪威担任过抗战时期中国战区的参谋长，他上任不久就发现中国军队的指挥系统存在严重问题。 
</p>
		<p style="TEXT-INDENT: 2em">欧美军队对上级的命令绝对服从，不管是谁，只要有指挥权就能指挥；中国则不然，上下级关系由个人恩惠决定，军官只听从某个人的命令，其它人即使有指挥权也指挥不动军队。 
</p>
		<p style="TEXT-INDENT: 2em">例如当远征军回国的退路被日军切断时，其直接上司史迪威命令部队撤往印度，但蒋介石却命令撤回国。 
</p>
		<p style="TEXT-INDENT: 2em">最高指挥部的不统一使远征军的军官们十分为难，有两个师撤往印度，其他的撤回云南。在退回云南途中，远征军迂回穿越人迹未至的原始森林，饥饿和疾病导致士兵大量死亡，１０部队最后只剩下４万人，倒是撤往印度的两个师后来成为了中国最精锐的部队。</p>
		<p style="TEXT-INDENT: 2em">根据欧美国家的军法，军官不服从命令要受到严惩。史迪威要求处分那些不听命的将军，要枪毙四个师长。但蒋介石却息事宁人，只将第五军军长杜聿明调任，五十五师师长陈吾勉处分了事。 
</p>
		<p style="TEXT-INDENT: 2em">史迪威对此非常不满，认为必须对中国军队进行结构上的改造，他说：“如果给予正确的指导，中国军队不逊于任何国家的军队。” 
</p>
		<p style="TEXT-INDENT: 2em">
				<b>“简单”三：如何遵守程序</b>
		</p>
		<p style="TEXT-INDENT: 2em">看日本人干活是很烦琐的。 
</p>
		<p style="TEXT-INDENT: 2em">拿收拾床铺来说，在中国是很简单的事情，连五星级宾馆都规定，客人没有动过的被褥不用拆洗和重新叠。而在日本，首先不管客人用没有用过，床单被罩都要剥下来，一趟一趟送到洗衣房去，而且是每个屋子送一次。 
</p>
		<p style="TEXT-INDENT: 2em">能不能把所有房间的床单被罩都剥下来，一起送到洗衣服房，这样工作效率不是大大提高了吗？ 
</p>
		<p style="TEXT-INDENT: 2em">日本人这样回答：作业书就是这样写的，我们按照作业书上做。 
</p>
		<p style="TEXT-INDENT: 2em">日本的管理体制要求工作不必带热情，只能严格按照作业书的指示做，即便出了错，自己也不必担责任。 
</p>
		<p style="TEXT-INDENT: 2em">
				<b>“简单”四：如何划分权责</b>
		</p>
		<p style="TEXT-INDENT: 2em">项目管理首先要解决的是一些初级的东西。 
</p>
		<p style="TEXT-INDENT: 2em">比如你要项目成员尽义务，你就要明确地告诉他有什么权利，凡是劳动保护法规定的权利都要告诉他，连项目提成奖金如何分配都要和他们讲清楚，还要让他们知道，“你们是国家的主人，但这个项目的主人是我，你们没有选举项目经理的权利”。 
</p>
		<p style="TEXT-INDENT: 2em">“我现在购买了你的劳动力，你必须负责。你不负责，你将失去你的权利。” 
</p>
		<p style="TEXT-INDENT: 2em">从项目管理的角度讲，这就是效率，不把精力浪费在与项目无关的事情上。 
</p>
		<p style="TEXT-INDENT: 2em">罚角球时如何占位是简单的事情，指挥信号要统一是简单的道理，按照条例操作属于常识性的规矩，员工责权利的界定是基本的前提，管理就是由这些看似简单的东西构成。 
</p>
		<p style="TEXT-INDENT: 2em">项目组制定项目管理战略当然重要，但更重要的是要把日常的管理细节做好。 
</p>
		<p style="TEXT-INDENT: 2em">战场上所有胜利的基础都是治军有方，带兵小到宿营时战士烫脚穿泡，鞋合不合脚，绑腿扎得松紧程度等等，都关系到战斗力，而这些都是“简单”的事情，并不高深。 
</p>
		<p style="TEXT-INDENT: 2em">世间事物无不普通而玄妙，玄妙而普通。许多事情看起来很高深，实际很普通，管理也是这样。</p>
		<p>
		</p>
		<!--Here is the bottom-->
		<p> </p>
<img src ="http://www.blogjava.net/faithwind/aggbug/65786.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/faithwind/" target="_blank">黑咖啡</a> 2006-08-25 14:36 <a href="http://www.blogjava.net/faithwind/articles/65786.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>纵论现实中的软件工程</title><link>http://www.blogjava.net/faithwind/articles/65784.html</link><dc:creator>黑咖啡</dc:creator><author>黑咖啡</author><pubDate>Fri, 25 Aug 2006 06:35:00 GMT</pubDate><guid>http://www.blogjava.net/faithwind/articles/65784.html</guid><wfw:comment>http://www.blogjava.net/faithwind/comments/65784.html</wfw:comment><comments>http://www.blogjava.net/faithwind/articles/65784.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/faithwind/comments/commentRss/65784.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/faithwind/services/trackbacks/65784.html</trackback:ping><description><![CDATA[
		<p style="FONT-SIZE: 9pt">1.大公司手中的算盘<br />　　从最早仅仅关注于软件开发工具到现在，软件行业中的巨头们已经在层出不穷的思想中涅槃了一回又一回。<br />　　Rational被IBM并购的真实原因在于IBM需要构建一个完整的软件工程体系，有了Rational的IBM会变成这个样子(见表1)。<br /><br />　　<img src="http://www.uml.org.cn/UMLForum/image/051641.bmp" /><br /><br />　　<img src="http://www.uml.org.cn/UMLForum/image/051642.bmp" /><br /><br />　　对于Borland来说，对软件开发语言(C、Java、Delphi)把握是其自身优势，所以Borland一直保持在语言上的中立，以寻求一种在不同平台上的开发者社群的支持最大化。Borland积极的推动UML的标准化，一方面可以使得Borland有机会在模型语言标准的制定上有机会制造影响，另一方面也可以快速地与IBM/Rational构成对抗Mircosoft的战线。<br /><br />　　作为工具开发商，Borland快速地拥有了实现ALM(Application Lifecycle Management)所需的绝大多数软件产品。然而Borland也很快意识到，(当前的)ALM是一个产品体系而不是一个理论体系：Borland没有在ALM作为工程理论方面上的任何优势。于是Borland开始并购与实现ALM体系相关的公司，其中收购过程改进咨询公司TeraQuest并组建流程优化实务部，以及收购TogetherSoft为开发工具增强模型构建能力，都是相当大的一些举措。通过这些努力，Borland快速地补全了ALM作为一个工程体系在理论方面的不足。　<br />　<br />　　对于IBM来说，RUP和UML是优疲訧BM用来削弱Borland在开发语言上的优势的最佳手段，就是支持开源的Eclipse，以及用UML的标准化来确立其规范制定者的地位。然而你会惊斓姆⑾郑珺orland一方面在支持UML的标准化，另一方面还在支持着Eclipse的开发并协助其快速成为一个完整的、具有商业品质的开发平台。这似乎是极其怪异的战略：帮对手磨剑。<br /><br />　　如果Borland只为一个对手磨剑，那他可能是一个傻子。但问题是，Borland几乎为他所有既已成为（或者终将成为）对手的人磨剑：Kylix是Linux平台上的产品；C++ Builder、C# Builder、CBX、Delphi是Win 32和.NET平台上的产品；JBuilder则是Sun平台上的产品—— 一切正如Borland自己说的那样，他是“(语言、平台和技术)中立的软件厂商”。<br /><br />　　Borland走在钢丝绳的中间，对他的考验是平衡的艺术和技术：如果他倒下，钢丝绳两端的任一方都来不及施以援手；然而如果他存在，那么他向哪边迈出的一步，就给对方以最大的压力。<br /><br />　　“敌人的敌人就是自己的朋友”，聪明的战略家总是能看到这一点。然而Borland却力图使这个敌我都分不清的战场呈现出一种古怪的格局：一方面Microsoft是Borland的股东之一，另一方面Borland在做Sun、IBM以及Linux平台上的软件提供商。<br /><br />　　与Borland和IBM通过通过并购来达到目的方式，Microsoft有足够的力量全方位出击，因此你看到的体系如表3所示。<br /><br />　 <img src="http://www.uml.org.cn/UMLForum/image/051643.bmp" /><br /><br />　　Microsoft在工具、方法和过程方面都有具体的实现。而IBM在方法和过程层面上大都停留在理论阶段，Borland在这些方面上虽有丰富的产品实现，却又相对缺乏理论基础。<br /><br />　　Microsoft并不仅停留于此。从.NET Framework提出开始，Microsoft就试图在开发语言和基础框架上实现大统一，希望能达到UML在模型语言中的地位。因此出现了CLR+CTS通用语言体系以及其具体的实现：.NET CLR+IAsm。.NET上的代码要求最终被实现成中间代码，可以反汇编到IAsm，这意味着任何其它公司在开发语言层面上的优势丧失殆尽，所以开发者们看到C#、Jscript .NET和VB .NET同期实现的“壮举”。<br />而Mono的出现，对于Microsoft而言是绝对的福音。Microsoft把.NET Framework中的C#、公共语言架构(CLI)以及通用类型系统(CTS)等做成ECMA标准，最期望看到的就是类似Mono这样的第三方产品的出现。事实上，Mono做了Microsoft从来都想做而不敢做的事——解决了Microsoft产品的跨平台问题，进而削弱了Sun相关语言的跨平台优势。Microsoft一方面不想放弃自己的平台优势，另一方面又为Sun的跨平台优势所制肘。而Mono的出现以及它适度的影响力，正好成为Microsoft平衡这种微妙的、相对优劣形势的棋子。<br /><br />　　接下来Microsoft开始向模型语言发难。领域专用语言（Domain-Specific Language，DSL）的提出绝非偶然，那是在硝烟未尽的战场上重新燃起的战火。<br /><br />　　软件业界如今的局面，不是一些人(例如程序员或者评论家们)争争吵吵的结果，而是大公司们相互制衡的结果。Borland与IBM、IBM与Sun以及Sun与Apple都在做着相同的事， 又都有各自的算盘。他们一边压制对手的优势，一边又借助对手和同盟的力量来削弱自己的劣势或者补充实力。<br /><br />　　跳到局外来看，并不是说Microsoft是他们的共同对手，而只是因为Microsoft占在了峰头浪尖，便成了众矢之的。所有人面对的并不是Microsoft的名字，而只是它的地位，无论谁成就了这个地位，都将承受相同的风险与压力——当然也包括机会。<br /><br />　　众多大公司在标准、理论、语言上的争来夺去，未必全部出于“软件实现”的考虑。对统一理论、统一工具、统一过程的企图，其最终目的是在整个软件工程体系中的全面胜出。算盘上的绝大多数人，只是用于计算胜负的一枚算子。<br /><br />　　2.回到工程的关键点<br />　　除了软件本质力量的推动之外，商业因素也推动着软件工程体系的发展。大公司之间的争夺战的最终结果，已经开始把软件工程从原始的“自生演进”状态，逐渐推进到“他激发展”的状态上了。<br /><br />　　这种他激发展可能会影响到软件工程发展的速度，然而在各个工程层面上的关注点并不会发生变化。在前面的模型图中，每一条纵向的细线用于定义一个关注点①。我在另一次培训中为这些关注点加上了标注：<br /><br />　　<img height="205" src="http://www.sawin.cn/DOC/share/516975.jpg" width="317" /><br />　<br />　　上图标示的模型被我命名为软件工程层状模型(EHM, Engineering Hiberarchy Model)。与“牛屎图”所代表的“软件工程体系层次”不一样的是，EHM不描述工程元素间的关系，甚至在试图割裂这些元素以使得工程角色定位以及各自的视角更加清晰明确。<br /><br />　　从这个模型中可以看到，在“程序”与“方法”层面，是关注于“(具体的)实现”的；而在“过程”和“工程”层面，首要考虑的是团队问题。从角色的角度上来说：开发经理思考项目的实施方案和管理具体的开发行为；而项目经理则保障团队的稳定性和一致性。<br />然而这只是基本模式，或者说，是理想模式。<br /><br />　　3.思考项目成本的经理<br />　　在标注关注点时，如下的问题引起了我的思考：<br />　　项目的管理到底是组织管理还是成本管理？<br />　　项目的计划到底是组织规划还是成本计划？<br />　　一言以蔽之：项目管理要不要考虑成本问题？<br />　　现在，从一个细节跳出来，进而分析我们的角色。这个细节就是：如何完成今天的工作。<br /><br />　　正如前面所说，如果你是一个软件公司里的项目经理，你今天的工作可能是写一份项目计划案或者听测试部的报告，亦或安排会议来听取和分析一个新的产品需求。然而，我需要说的是：这是细节。<br /><br />　　细节就是你使用的Project 2003，或者你正在公司内部署和推广的ClearCase。如果它们正好是你今天要完成的工作或者是你明天要用来工作的工具，那么，做为项目经理的你，现在就要立即跳出来。<br /><br />　　理想状况下，“软件工程=过程+方法+工具”。然而，工程成功的真正关键并不在于你把你的团队“组织”得有多好。即使在团队中他们都显示出有条不紊，你一样会面临失败。<br /><br />　　蚂蚁的团队总是被本能地组织得非常好。然而如果一个蚂蚁的群体中有了流行疾病，致使蚂蚁死去，而新生蚂蚁不能跟上其死亡的速度，那么这个团队很快就溃散了。<br /><br />　　这是因为蚂蚁用于维护团队运作的“资本”在流失。如果资本没有了，就没了运作，团队的存在就没有了必要性和可能性。项目就死亡了。<br />　　埋头于画甘特图的项目经理犯下了与挖山不止的愚公同样的错误：忽略了成本。<br /><br />　　如果愚公真的可以成功，那么可能是300年之后。然而如果一个工程要300年才能做成，那么在做成之前，客户就选择了放弃。<br />如果有机会，项目经理可以选择向另一家公司购买一个产品来卖给客户，从“为客户开发”变成“为客户定制”以及“为客户服务”，这样就在没有任何开发成本的前提下完成了工程。与另一个同样极端的例子相比，你会发现它与前面那个“做过场”的项目全然不同。后者是做完了工程，却没有做成工程。而现在这个项目经理却做成了工程，但是在许多的过程环节上他根本就没有开始。<br /><br />　　然而，现在除了跃跃欲试的技术经理之外，没有人会不满意这个结果。<br />　　技术经理最常说的话是：我们可以开发出来；开发人员最常说的话是：我可以开发出来；愚公最常说的话是：何苦而不平？<br />　　还记得那句话吗——不要栽进蚂蚁洞里！<br />　　愚公如果停下来，思考的问题可能是碎石的“方法”。而项目经理从细节中跳出来，思考的问题就应当是完成工程的“方法”。评价这个　　方法的好坏的标准只有一个：节约成本。<br />　　Y公司由K公司过渡而来的时候带来了一个市场前景非常看好的产品。而存在的问题则是两方面的，一是扩大市场占有率，二是继续技术投入。<br />　　于是，Y公司请来了专家D。他是一个在行业中摸爬滚打了多年的顾问型专家：做过公司，也在无数个公司做过。D先生的项目计划可能是无可挑剔的，但其投资规模决定了它无法实施；D先生在一些产品计划上的思考上也是切近市场的，然而他没有学会如何为团队争取到两名以上的开发人员；D先生在部门管理上的方法也是适当的，然而他忘记了训练部门人员以使他们与自己保持一致的步调和方向(组织和管理一个松散的团队比照顾一群蚂蚁难得多)。<br />　　于是在Y公司建立到倒掉的四年时间里，D先生三进三出，营销计划一再被否决，而产品的再研发计划也数度被搁置。很快，这个并不生动的故事终结于我跟他的最后一次会谈：三年之后，产品彻底从市场中退出。<br />　　“思考成本”，这是D先生给我的教训：<br />　　不计成本的项目计划不会得到经营者的支持；<br />　　毫无目的地消耗成本是项目中的慢性毒药；<br />　　最致命的风险是成本的枯竭②。<br /><br />===================================================================================================================<br />===================================================================================================================<br />　　4.审视AOP<br />　　我读到的第一篇关于AOP的文章居然说它是“新一代的java语言”。正如文章的标题所表现的那样，作者大概是在学习如何向方格子里填写“错误”：其结果当然是每一个格子都是“错误”——如果他象小学生一样勤奋的话。<br /><br />　　AOP不是语言。AOP首先是方法论，这就像OOP是“面向对象的编程方法”的方法论一样。而Delphi／C++才是语言，是对这个方法论的一个实现工具。<br /><br />　　很好，有了这个基础，我们再来讨论相似性的问题。我们提到过开发方法是基于一种数据结构的编程实践的结果。很显然，OOP所基于的数据结构是对象(Object)，而AOP所基于的数据结构就是方面(Aspect) ③。落足到开发工具的实现上，Delphi将Object表现为一组有(继承)关系的“记录(Record)④” 。相对应的，Java将用类(Class)来实现Aspect。<br />===================================================================================================================<br />　　③人们在争论Aspect到底应该译成“切面”还是“方面”这件事上花了很多功夫。其实，就如同讨论前面的“关注点”究竟是“点”还是“线”的问题一样，他们陷入了细节。如果这些细节被作为问题持续下去，那么可能有一天台海战争将不是发生在军队之间，而是在程序员之间：到底是“物件”，还是“对象”？<br /><br />　　④在C中，这个名词是“结构(Struct)”。很多人不会承认“对象是有继承关系的记录”这样的观点。是的，所有的教科书上都不会这样写。但是从数据结构本身以及数据结构在语言中的实现来看，对象终究是记录。记录是平板化的内存存储体系中所能表达的最复杂的单一数据体。<br />===================================================================================================<br />　　 Aspect在定义时没有确定的对象模块，Aspect本身只是对一个“对象模块群体”的观察视角，因此它更易于表现成接口——只有描述而没有实现。<br /><br />　　在Object一层的抽象上，Object关注于“有继承关系的考察对象”的个体特征；而在Aspect一层的抽象上，Aspect关注于“有相似需求的考察对象”的群体特性。其相似性在群体中表现得越广泛，则AOP的优势也就越明显。例如在Delphi的VCL框架中，以下两个需求就可以用AOP的思想来实现：<br />　　使Delphi中的全部对象具有多线程特性(即线程安全)；<br />　　实现助手工具类以观察、控制Delphi对象的运行期特性或表现。<br />　　到现在为止，我们弄清楚了AOP作为“思想、方法、工具”的一些基本知识，以及它的应用范围：至少你要明白，它是用来考察对象(而不是设计对象)的思想方法。<br />　　所以接下来AOP的三个概念我们就明白了：<br />　　指示(Advice)/拦截器(Interceptor)：考察这些对象以“达到什么样的目的”(即需求)。<br />　　引导(Introduction)：在目标上实现这些需求时，目标所需要表现出来的公共特性。引导特性可能需要配合编译器来实现。<br />　　元数据(Metadata)：如果需要，为即有对象实体再补充一些参考数据。<br />　　确切地说，切分点(Pointcut)并不是AOP编程方法所需要的概念，而是AOP作为一个框架时所需要的一个工具：一组辨识Acpects和Objects的索引。<br />　　现在你已经会用Acpect的思想来编程了，而无论它是用Java来实现的，或者是用C#、Delphi，乃至于FORTRAN或COBOL。你需要做的是，回到工程最核心的那个环节：编程＝算法＋结构＋方法。<br /><br />　　5.审视MDA/MDD<br />　　MDA(Model Driven Architecture)也是一个方法论层面上的名词。它讨论的是“创建出机器可读和高度抽象的模型”的方法。受MDA影响的开发活动被称为MDD(Model Driven Development)。<br />　　与MDD在同一个层面上的概念是：<br />　　TDD(Test Driven Development) <br />　　FDD(Feature Driven Development) <br />　　BDD(Business Driven Development) <br />　　R-TDD(Rapid Template-Driven Development) <br />　　CDD(Contract Driven Development) <br />　　RDD(Requirements Driven Development) <br />　　... ... <br />　　我不厌其烦地罗列这些名词，只想告诉读者一个事实：什么都可以“驱动开发”。<br />　　不同的方案提供商基于自己的产品构架和当前的理论倾向，随时都在准备改变他们“驱动开发”的方式。在这种形势下的 “xDD”或“xDA”，已经成为他们促销产品的保留用词。<br />　　<br />　　回到软件工程的过程环节中来吧，你会看到，“以什么驱动开发”只是一个“以哪个环节为中心(或导引)”的问题。所以你会看到TDD中的X模型(也可参考V模型)是这样的：<br /></p>
		<p>　<img height="283" src="http://www.sawin.cn/DOC/share/516921.jpg" width="400" /><br /><br />　　如果你仍旧不能明白为什么会有这么多被神秘力量所“驱动着的开发”，那么你就干脆去厨房找个平底锅烧点热油，然后敲下一个鸡蛋，很快，你就体悟“以蛋黄驱动开发”的真谛了。<br />　　<br />　　抛开实现的技术细节不论，在工程中，“以什么驱动开发”其实是一个过程问题。而你应该明白，过程的选择(或制定)取决于你的工程需要，以及它在相关应用领域的适用性、过程工具的充备性和这个过程理论的完善程度，而不是大公司们的鼓吹。<br /><br />　　过程模型决定了工程的实施步骤和组织方式。但是Object Management Group (OMG) 尽管对MDA提出了一套完备的技术和方法体系，工程实施者却无法在这个体系中找到一个可以适用的软件过程模型——MDA不讨论过程。<br /><br />　　也就是说，MDA架构作为一个新的软件开发方法的架构，即使在技术研究、底层协议和软件实现方面经过了持续地完善而渐至成熟，然而如果没有同样成熟的软件过程理论支持，那么它在工程中的实用价值也就有限。<br /><br />　<img height="313" src="http://www.sawin.cn/DOC/share/5161048.jpg" width="323" /><br />　　仔细审视一下这个MDA，如果你现在就决定将下一个工程项目建立在这个构架的基础上，或者用MDD的方式来开发BIOS，那么你离精神病就不远了。<br />　　①我画出的的确是线而不是点，“关注点”只是一个概念。如果你非要去发现一个“点”，那么你可以用几何的目光，关注于弧线与直线的切点。然而，这样的结果将是你彻底的忽视了“关注点”的本质含义。<br />　　②我经常注意到的成本因素包括时间、人力、资金和客户成本。而大多数情况下，人们不会把客户的数量以及耐心当做(客户)成本来计算。而在我的项目规划中，这是成本。</p>
		<p>
		</p>
		<p>
		</p>
		<!--Here is the bottom-->
		<p> </p>
<img src ="http://www.blogjava.net/faithwind/aggbug/65784.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/faithwind/" target="_blank">黑咖啡</a> 2006-08-25 14:35 <a href="http://www.blogjava.net/faithwind/articles/65784.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>