﻿<?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精髓</title><link>http://www.blogjava.net/jhyan/</link><description /><language>zh-cn</language><lastBuildDate>Sat, 11 Oct 2008 06:14:55 GMT</lastBuildDate><pubDate>Sat, 11 Oct 2008 06:14:55 GMT</pubDate><ttl>60</ttl><item><title>超越SOA：动态业务应用的新企业应用框架（2）转载</title><link>http://www.blogjava.net/jhyan/archive/2008/10/06/232644.html</link><dc:creator>Joshua Yan</dc:creator><author>Joshua Yan</author><pubDate>Mon, 06 Oct 2008 05:08:00 GMT</pubDate><guid>http://www.blogjava.net/jhyan/archive/2008/10/06/232644.html</guid><wfw:comment>http://www.blogjava.net/jhyan/comments/232644.html</wfw:comment><comments>http://www.blogjava.net/jhyan/archive/2008/10/06/232644.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jhyan/comments/commentRss/232644.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jhyan/services/trackbacks/232644.html</trackback:ping><description><![CDATA[<h3>第二部分：动态业务应用构建实践——两个自适应系统的故事</h3>
<p>生产力提高是生活水平提高的基本组成。美国的经验表明，长期的生产力强劲增长表现为伴随组织结构和企业资金安排变化的技术革新，以及人力资本的投
入。但是，支撑这些生产力增长的决定因素的是一个更基本的因素：社会对其自身进行重大转变的意志，以及对技术进步和随那个进步而来的经济机会将使人们改善
其生活的信心。<a href="http://www.infoq.com/infoq/url.action?i=272&amp;t=f" target="_blank"></a><br />
</p>
<p>&#8211;Roger W. Ferguson Jr.和William L. Wascher，美国经济学会在政府中做的经济专题演讲：过去生产力大爆炸的教训，《经济学展望杂志》，2004年春季18卷，第2期</p>
<p>&#8220;一旦着手自动化这些[企业]流程，技术实现大约占10%，其余90%都是变更和流程管理&#8221;</p>
<p>&#8211;Mark Evans，Tesoro Petroleum的CIO，管理自动化，2004年3月</p>
<h4>第一部分总结</h4>
<p>在<a href="http://www.infoq.com/cn/articles/dynamic-business-applications">本文的第一部分</a>，
我们介绍了一种构建新型IT系统的企业架构，我们称之为动态业务架构（DBA）。这些DBA非常适合支持具有动态操作（包含最新业务的一个分类）的企业。
第一部分还指出，用例是当前系统架构和设计的基本输入，并描述了依赖通过它收集的需求对当前企业架构方法的种种制约。这一新提出的新框架使用企业事件模型
作为起点，并将企业视为一个具有清晰信息架构的自适应系统。以新的自适应系统和信息理论为基础，在基础层级，该框架同时捕捉企业流程和业务变更。用例仅在
设计过程的后期作为一种需求细化方法被引入。这种框架优先的方式受到了传统工程方法学的启发，但针对像企业这样的自适应系统进行了修改。</p>
<h4>介绍</h4>
<p>告别手工作坊并向软件工程加入正确工程技术的时候到了。这是将复杂软件应用（尤其是在企业领域中）构建成高度可靠、易于改变和方便调试的公共标准的
唯一方法。选择并执行正确的系统架构是使这种方法发挥作用的最重要因素。我们建议的解决方案使得围绕唯一一个系统架构进行标准化（不考虑软件应用）并避免
成本高昂的重新构架成为可能。</p>
<p>正如本文第一部分提到的，构架软件应用和设计其它工程产品之间有一个根本性的区别。因为软件是和信息打交道，而信息是变更的&#8220;载体&#8221;，那么必须在最
基础的级别将变更构建到信息架构之中。此外，业务操作变更的方式和技术团体将变更引入系统的方式走得是完全不同的路径。它们各自都是对变更反应不同并具有
不同操作的组织（一个是业务和一个是技术）。在构架过程中，可以把这两个组织作为两个不同的自适应系统对待。这正是我们选择&#8220;两个自适应系统的故事&#8221;作为
本文第二部分副标题的原因。</p>
<p>在设计企业应用的过程中涉及两个自适应系统。</p>
<p>本文第一部分提到，能成功应对构建DBA复杂性的唯一方法是使用架构先行的方法论。几个世纪以来，工程师们一直在使用这种方法论——但总是设计&#8220;静
态&#8221;架构。一旦要应用变更，系统极可能必须先停止工作再进行修改。例如，要改变由装配线组装的产品必须先停止装配线，然后应用变更，最后重新启动装配线。</p>
<p>当今为业务构建IT系统的软件工程师们很可能就是遵循的同样套路。当业务变化提出了修改应用的需求时，它很可能就触发了一个成本高昂的升级。开发者
必须从头开始一个新业务需求，并且旧的设计常常经受大量的重新构架。这种升级周期可能需要几个月。如果企业应用是由外部开发商按照自己的日程构建的，那么
整个过程可能耗时更长而且结果可能达不到业务预期。Mark Evans说得好，超过90%的努力只直接和应用变更相关。</p>
<p>籍由新的自适应系统理论和它们信息架构（参见局外人观点）的帮助，我们建议的企业应用设计解决方案引入了两个互补但唯一的框架。这两个框架让我们可
以有效地处理和协调业务操作和技术团体操作中的变更。对设计过程而言，业务操作和技术团体操作可以被视为两个截然不同的自适应系统，它们各自都有自己的需
求。</p>
<p>业务操作可由基础动态业务平台的通用概念来表示。根据自适应系统理论，任何企业业务功能均有3类基础流程。主流程类型支持正常操作，而其他两个则负
责引入变化：内部决策制订流程处理管理和其他企业变更决策；业务环境变更流程处理客户决策和变更的其他外部来源。因此，我们提出的业务流程框架（基本动态
业务平台）是围绕着业务操作或价值循环构建起来的，它包含的两类变更由两个不同的变更管理平台来处理。从信息处理观点来看，实现这些操作的系统可以比作围
绕事件模型构建的&#8220;信息装配线&#8221;（参见第一部分）。企业的业务操作可以按照类似源自丰田精益制造最佳实践的价值流程图（Value Stream
Mapping）方法论的方法来识别。结果是，生命周期/事件模型成为系统设计和架构的主要驱动力，不可靠的用例集合不再是系统架构的主要输入。</p>
<p>技术操作有其自身的挑战和独特的动态性。技术操作的主要目标是如何使不同的团队在引入变更的过程中能最大限度的合作。基础动态业务应用是具有两类流程的自适应系统：操作和操作变更。这两个流程将技术支持（操作）和技术开发（操作变更）与业务用户联系在了一起。</p>
<img alt="" _href="img://Fig1.jpg" src="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig1.jpg" />
<p>图1. 构建和维护基础业务动态平台既需要业务流程框架，也需要业务系统变更管理框架。</p>
<p>两个框架必须合并到一个既考虑技术团队操作，又考虑业务用户活动的独特系统设计中。这个系统是围绕服务器端架构设计的。虽然仿效了它们的结构和控制层次，但是这是为不同类型用户合作提供支持的唯一方法。</p>
<h4>设计服务器端基础设施的复杂性比桌面应用的要高几个数量级</h4>
<p>每个企业软件的设计者都认识到，实现完整的企业客户/服务器应用要比构建桌面应用更复杂。对于桌面应用，接口是围绕一个角色、一个主要任务和一个清
晰接口构建的，整个应用运行在单独一台机器之上。接口可以通过一系列函数实现来构建。对于服务器端应用，实现要复杂得多。复杂性的来源之一就是，服务器端
应用要实现包括管理员在内的多个角色。管理员不可能扮演一个被动角色，他需要一个可以在必要时改变操作参数的界面。此外，为了保证正常使用，技术支持必须
对应用进行监测。</p>
<p>要更好地理解实现桌面应用和实现客户/服务器应用之间的区别，我们可以看看将一个桌面应用变成客户/服务器应用需要经过哪些步骤。假设我们需要使用
作为服务器端应用实现的MS
Word写信。首先，你需要一个技术支持负责设置字体、页面和所有其他设置。每当你需要不同设置的时候，你都必须请求这个技术支持完成变更。在你写信时，
管理员必须审定字体，信头等等。一旦完成这些，同一管理员可能还需在它发送前对其进行审核。这个例子虽然看起来简单，但是它可以帮助我们理解当试图将桌面
开发过程中获得的知识外推到客户/服务器应用时，软件架构师面临的挑战。</p>
<p>事实上，当多个用户在使用同一个应用时（业务上或技术上），它需要完全不同的方法。架构必须是分布式（用户可能在不同地点、使用不同机器）、有状态
（状态不再由硬编码到应用中的下一个窗口来定义）、动态性（管理员或外部用户可能需要一个业务实体能在运行时被改变，类似经理可能要求一个产品或服务不能
再以相同价格出售或客户可能要求订单改变的方式）和层次性（所有组织有一个控制层级，这样不同用户就能对流程进行不同控制）的任务或流程提供支持。所有这
些新性质都必须被内嵌至应用的基础之中，否则它就必须在每次进行变更时被重写。</p>
<p>但是这并非设计服务器端应用的唯一区别。当桌面应用崩溃时，用户只需重启它就行了。因为它实现的是简单任务，重新做一遍即可，即便丢失了大部分数
据。用户并不需要一个专门的技术团队来帮助他运行应用程序。对于客户/服务器应用而言，情况就完全不一样了。由于多个用户同时工作，一旦出现问题，只有具
有技术知识和有权使用工具监测应用的技术支持团队能够制定如何使应用恢复正常操作的决策。并且技术团队自己的操作蓝图完全不同于业务操作蓝图。技术团队有
自己的流程控制层次、自己的分布式环境、自己实现变更的方法和自己的状态。</p>
<p>结果是，构架一个能在企业级运行的客户/服务器应用要比构架一个桌面应用复杂几个数量级。服务器端的主要复杂度源于它必须支持两个自适应系统，一个
是技术团体，另一个是业务团队，他们各自又都有自己的操作和控制层次。在构架同时支持管理和技术支持两个自适应系统的应用时，需要遵守应用于自适应系统及
其相关信息的法则。</p>
<p>在构架这类复杂系统的过程中，如果有一个理想的架构，那么就用不着在每次业务或技术引入变更时重新返工了。理想情形是拥有一个标准组件集合，它具有
用事件模型实现的定义良好的行为。在不同控制级别实现的事件模型将这些组件链接到一个控制层次中。在桌面中，一组自身具有事件模型的定义良好的组件由一个
清晰的控制层级链接到了一起。服务器端就要落后得多了。使用中的J2EE、.NET或其它现存专有架构都缺少为分布式、动态性、有状态和层次性环境提供支
持的基本组件。由于Web标准是无状态、扁平、静态和只针对单服务器的，它们对单个自适应系统都无法提供很大帮助，更别提两个了。</p>
<p>根据自适应系统及其关联信息的法则，一个控制层次总是符合3个模式：</p>
<ul>
    <li>初始化过程总是相同的自顶向下顺序 </li>
    <li>层级之间的信息传播总是遵照确定的规则：命令流自顶向下，反馈流自底向上 </li>
    <li>每个层级有其自身的正常操作，它们在收到一个反馈或命令之前不会改变。处理命令或反馈总是需要变更管理的能力。并且由于有两类交互——命令和反馈——因而需要两类不同的变更管理</li>
</ul>
<p>我们将展示如何使用标准组件（它们一起被链接在一个动态、有状态且分布式的控制层次中）为服务器端应用实现一个标准架构。但是首先，我们将先给出另一个任何计算机使用者都熟悉的以事件为中心的平台。</p>
<h4>微软将它的未来建立在了针对GUI的一系列组件和一个静态事件模型之上</h4>
<p>微软之所以如此成功有许多原因，但是其中一点非常突出。他们不顾来自Apple和IBM的诸多批评和竞争，将Windows操作系统构建成了一个桌
面标准。一种解释可能是，微软是第一家不仅提供与Apple利用Mac完成的工作类似的操作环境，而且还拥有一组最方便的OS和GUI组件的公司。这些组
件被实现成了可供调用的API。利用这个组件模型，包括微软在内的软件公司就能够构建数据库、办公应用和类似Visual
Basic这样的开发工具。这些应用都能利用被构建成结构体和控件的Windows内置层次事件模型。</p>
<p>在开发Windows时，微软拥有的优势在于，大多数OS和GUI的主要组件，连同它们的事件模型一起，要么已经是现成的，要么就是可以凭直觉方便
地构建。对于任何桌面应用来说，控制层次看起来异乎寻常的简单。在GUI栈的顶端是扮演其余GUI组件容器的各个窗口。打开窗口，内嵌的控件也就自动地被
初始化。关闭窗口，每个组件也跟着一起关闭。用API捕获那些事件以及Windows应用的开发都和一个插件架构十分相称。</p>
<a _href="resource://Fig2_lg.jpg" href="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig2_lg.jpg"><img alt="" _href="img://Fig2.jpg" src="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig2.jpg" /></a>
<p>图2. 微软Windows控制层次模型——一个用户、一个应用、一个位置、一组静态功能</p>
<p>这些API的实现就是Windows操作系统自身。它是控制初始化过程的那个层级，也是最终必须处理错误而不是崩溃或丢失数据的层级。在服务器端，
组件、它们的事件和控制层次被一个需求搞复杂了，那就是为有状态、动态、分布式和层次性任务提供本地支持。这正是自适应企业操作平台（AEOP）的主要目
标。</p>
<h4>围绕动态结构和控制进行设计，AEOP提高了生产力</h4>
<p>一些年前，IBM招募了上千名企业架构师决心降低它们各垂直行业的客户化解决方案个数。一年多之后，他们将它们的数目由超过60个降低到了不到20
个。付出巨大的努力和不算优秀的结果显示了问题的巨大。尽管投入了庞大的资源，但IBM确实难以创建能对他们客户都适用的通用解决方案，不管他们在行业的
深度和公司大小。一种可能令他们努力复杂化的一件事是，他们是以一组不完善的遗留解决方案开始的。</p>
<p>我们的目标是相同的：创建一个几乎普遍适用于所有行业的通用解决方案。如果有从一个新鲜想法开始的自由，我们一开始就会关注那些我们认为最重要的基
本原则。大多数企业架构虽然依赖现有技术、组件或象SOA这样的趋势，但是AEOP架构要优于它们。它从一开始就认识到技术在企业中扮演的根本角色就是提
高生产力。这个角色对所有技术解决方案（不论它是否是IT）都是有效的。在IT情形下，由于业务的动态性和存在于企业系统各用户之间的复杂关系，架构需要
围绕企业流程的结构、控制和动态性来构建。</p>
<p>这种方法还提供了一种手段来解决由Nicholas Carr的《IT没什么大不了的（IT doesn't
matter）》产生的讨论，该文发表于2003年5月的《哈佛商业评论》。询问IT是否是业务相关的，就好像询问装配线是否是业务相关的一样。它不仅对
诸如通用或丰田这样的公司至关重要，而且是任何一家制造业公司的一部分，包括象Intel这样的高科技行业明星。装配线的影响力对那些定制产品或服务无处
不在的行业（如食品或保健领域）来说要小得多。虽然在象通用这样的公司看来装配线是重要的，但是它不过是高生产力的促成因素。相同的事实也适用于IT，它
可能对那些依赖信息处理运营的公司来说是一回事，但是对其他公司可能就无关紧要了。IT唯一的不同之处在于，它远没有装配线技术成熟。</p>
<p>要分析IT如何能提高生产力，就要了解那些决定了技术如何被交付和使用的基本商业机制。我们必须看看信息处理的基本角色，并询问驱动企业运营的核心
信息元素是什么。在工程领域，这一过程得到了相当好的理解，可以从几个例子看出这一点。当一个工程师开始设计一架飞机时，他从来不会把飞机看作一个诸如螺
母、螺钉、电线、连接器、泵、电动发动机、杠杆、面板等这样零件的集合。他查看连接它们的方式和它们在交付功能过程中扮演的角色。一架飞机的结构是围绕机
翼、引擎、座舱和主机身建造的，并采用一种能够最大化不同参与者间交互的控制层级。建筑师在设计一栋房子时也是这样。在建筑师清楚房中需要的卧室数目和生
活的家庭人员个数之前，待安装的空调、器具或电线型号都不重要。</p>
<p>在当今的方法中，企业软件大多都是围绕技术组件和标准被构架/设计的。需求是一种评估生产力增长或企业软件结构、控制和动态性的一种补救方法。事实
上，高级别架构推荐只以表现层、业务层和持久层为中心。当前还没有一种架构方法提供一个解决方案来支持现实中的动态、分布式、有状态和层次的业务流程架
构。</p>
<p>为了更好地类比，不妨让我们看看工程师是如何设计装配线的。首先，它们以易于维护和维修为设计目标。这就是为什么装配线架构和设计是围绕可交换性、
模块化和标准化组件建造的原因。由于装配线不会动态变化，那么第二个标准就是要易于针对新模型重新进行配置。这正是机器人在装配线上如此流行的原因。不管
任务有多复杂，都可以方便地针对范围广泛的当前和将来任务重新编程。只有在这两个标准被满足之后，设计工程师才会着手努力最优化每个特殊的任务。</p>
<p>为了构架/设计一个通用的AEOP，我们识别出了3个需要在设计中被解决的基本因素，它们对生产力的提高有重大影响。它们几乎对所有企业都是相同的，不论这些企业涉及的领域或生产规模：</p>
<p><strong>1）通过为技术支持、开发人员和业务用户之间的合作操作提供支持，提高技术团队操作的生产力</strong></p>
<p>对整个架构影响最大的是不同技术团队和业务用户之间的关系以及需求变更引入的方式。由于IT团队是在应用上花费时间最多的一个团队，提高它的生产力应该是架构的首要任务。</p>
<p>在这一背景下，技术团队正常操作的结构与控制并不复杂。业务用户打开一个触发业务事件的应用。这些事件使应用处理信息。技术支持团队监测应用。应用虽然处于生产环境，但是开发团队常常要计划下次升级并实现新的需求变更。</p>
<p>整个处理的控制遵循相同的层次架构：在控制金字塔的顶端是开发者团队。因为是他们实现未来的功能，他们对实现拥有所有控制权。接下来是技术支持团
队，因为他们可以停止和重启服务器或改变部分系统配置。对应用拥有最小控制权的团队包括业务用户、经理或工人。他们对应用脚本只能唯命是从。</p>
<p>由于企业是动态的，功能变更的请求可能出现得非常早，甚至在应用安装和运转之前。事实上，需求只有在下次开会的时候才生效。结果，在我们查看什么对
生产力有驱动作用的时候就会发现，如何将变更转换为代码是一个重要因素。在AEOP中，当发生变更时，你会发现总是存在同样的用户组。开发团队是接受变更
请求的团队，监测应用的团队安装它并接受配置来支持它，接着是业务团队接受培训来使用新功能。</p>
<p>作为这个结构和控制层级的结果，企业应用的顶层总是围绕3个平台构建的：一个为开发团队实现功能、一个为技术支持团队实施它和一个支持业务用户。它们每个都有自己的主生命周期和驱动设计的事件模型。</p>
<p>因为AEOP主要是支持技术团队操作的动态性，所以这种&#8220;3个平台&#8221;的结构、它们的组件和事件模型都是围绕变更请求的生命周期而构建的。</p>
<p><strong>2）通过为3类基本业务用户之间的合作事件提供支持，提高业务操作的生产力</strong> </p>
<p>不同类型基本业务用户间合作是生产力的第二大影响因素。在任何企业流程中最多有3类基本用户，分别代表了自适应系统的3个方面：代表操作的工人、代
表决策制定流程的经理和代表经济环境（它使价值循环成为闭环）的客户。价值循环的其他业务参与者，如供应商和政府代理，都扮演次要角色，并且它们的流程都
可以使用这3种基本流程（操作、管理和环境）中的一个标识。</p>
<p>业务是动态的。业务中最大的生产力杠杆之一是变更引入流程的效率。业务中有两类变更：经理引入的内部变更和消费者引入的外部变更。这些变更在某个时
间作为更新被引入到企业应用中。一个有效的架构/设计必须解决这种动态性。一种理想的企业应用架构能够只需最少的代码和配置改变就能适应大多数变更。由于
业务日益依赖支持它们运营的技术，一个快速而有效的更新应用方法对整个生产力十分重要。</p>
<p>基于这一点，AEOP针对业务操作中的高级合作只定义了3类企业架构：</p>
<ul>
    <li>静态架构：纯操作性的——目前所有的企业软件都属于此类。除了最简单的配置变更之外，完成业务流程变更通常都至少要求IT部门停止应用的运转。静态架构的行为类似于汽车制造商在引入新模型时停止装配线。</li>
    <li>仅
    内部（内部决策）驱动的动态架构：提供了对动态操作的支持并实现了经理和工人之间的关系。在这种情况下，在正常操作期间，以及在变更动态应用于当前所有实
    例时，经理决策是被自动考虑到的。因为经理和工人在不同的时间线上操作，他们需要处理内部决策的变更管理平台来嫁接他们的活动。客户在其中不扮演指导角色
    的那些流程都属于这个类别。</li>
    <li>扩展的（内部和外部决策）动态架构：提供了对动态操作的支持并使全部3类基本用户（工人、经理
    和客户）之间的合作自动化。这是最复杂的业务操作架构。它有两个不同的变更管理平台，一个针对正常操作应用于内部决策的方式，另一个针对那些希望改变订单
    在正常操作时的执行方式的客户。</li>
</ul>
<p>注意，在任何企业中，不论什么类型的业务流程，它总是与管理&#8220;命令和控制&#8221;的结构和客户反馈&#8220;相连&#8221;的。结果，不论应用的目标业务流程是什么，每个应用都属于&#8220;全动态类别&#8221;。</p>
<p>操作平台架构的动态性是以业务变更生命周期为中心的。它们受内部决策（经理制定内部决策）和外部变更（客户可以决定给进行中的已有订单和服务施加变化）驱动。</p>
<p><strong>3）通过提供在生命周期/事件级别完全解耦的架构，提高开发团队的生产力</strong> </p>
<p>前一个生产力因素跟业务变更对架构/设计的影响息息相关。理想情况下，架构/设计中的业务变更可以通过变更管理模块的界面来完成。该界面使经理和客户有权自动向工作中所有操作应用变更。</p>
<p>有时，变更需要开发团队实现新功能。在实现新功能时，应用的架构/设计应该支持高生产力。</p>
<p>当前方法是将一系列组件归到有数据库访问权限的&#8220;业务层&#8221;上。这种设计有一个基本错误。在这一设计中的数据库很可能是关系数据库，它保存层次性信息或有状态信息的能力很差。它们很可能依赖缓存机制，它们需要消耗惊人的计算资源，在后台持续更新大量数据。</p>
<p>无论怎样，企业中的所有业务流程都会链接到主业务实体（一个产品或一个服务）。对于一个链接到主业务实体的业务流程来说，现有历史是最重要的方面。
即使对最简单的交易来说也是如此。去一个商店买东西的前提是，你的金融资源将为你提供购买产品所需的足够金融&#8220;资源&#8221;，而且商店有&#8220;待售&#8221;的产品。一个实
体的历史由最终描述它整个生命周期的事件组成。由于可能改变实体状态的事件可以在业务结构内的任何位置和多个控制级别被触发，围绕这个业务实体动态构建的
AEOP架构必须是有状态、层次性和分布式的。</p>
<p>由于生命周期围绕事件而构建，围绕它们可以构建整个AEOP。任何事件实现都可以按照同一种通用方法完成：整个生命周期可以被认为是反映主业务实体
转换信息的&#8220;装配线&#8221;。因此，可以用相同的结构来实现事件，并装配：1）从各需要位置（分布式）检索出来的信息元素；2）在某一时刻瞬间存在的（如，检索
一张信用卡交易的账户信息必须以实时方式完成）信息元素；3）可由一定的业务流程实现的信息元素；4）已经应用了一定的业务规则的信息元素。</p>
<p>AEOP的另一个优势是能够围绕同一个事件模型设计两类变更管理。最终，这个操作平台的实现可以在事件级别解耦。操作平台可以作为一个插件API基础设施来构建，就像Windows API是围绕着桌面集成事件模型构建的一样。</p>
<p>需要注意的是，文献中记载的EDA（事件驱动架构）跟AEOP事件模型是不一样的。EDA是围绕非结构化事件流构建的，而AEOP是围绕由一组生命周期模板链接在一起的结构化事件流构建的。</p>
<a _href="resource://Fig3_lg.jpg" href="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig3_lg.jpg"><img alt="" _href="img://Fig3.jpg" src="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig3.jpg" /></a>
<p>图3. AEOP控制层次模型——按变更类型分组的多个用户、多个客户端应用、多个分布地点、多个静态功能</p>
<p>组件及其事件的AEOP层级包含5级：</p>
<ul>
    <li>OS级：在这里可以找到所有OS组件，如内核、文件系统、网络和I/O。OS可能还有GUI组件，运行监测各种应用及其活动的图形化工具时会用到它们。 </li>
    <li>技
    术级：在这里可以找到所有传统的基于服务器的组件，如应用服务器、BPM引擎、业务规则引擎、数据库。这儿还有实现了Web和Web服务、消息传递等标准
    的组件。它们或多或少扮演了和飞机设计中标准零部件相同的角色。螺母、螺钉、电动发动机、液压泵、电线、连接器、座椅、电子面板、马达对许多其他工业设备
    都是通用的，不只限于飞机。可是它们在尽可能简化和标准化设计的过程中扮演了一个关键角色。</li>
    <li>AEOP技术操作级：这是拥有
    特定于AEOP组件的顶级级别。这里有3种组件——安装/启动/持久化/恢复平台、系统平台和操作平台。它们分别代表了合作运行客户/服务器应用的3个小
    组：业务用户团队、技术支持团队和开发团队。每个组件实现了特定的事件，如技术支持团队能监测错误和重启应用。对于那些需要和外部系统合作的应用，还存在
    被称为外部系统监督者平台的第4类组件。这个组件管理与外部系统交互的初始化、正常操作和错误翻译。</li>
    <li>AEOP业务操作级：它是业务实现的顶级级别，在操作平台之下的一级。它也包含了3个主要组件：正常操作、内部决策管理变更和外部环境交互（即客户决策）管理变更。这里包括许多其他组件，如外部系统操作翻译器、系统Map、许可证管理器等。 </li>
    <li>AEOP事件处理级：这是实现的插件级。在这一级实现了被激活业务流程的整个正常操作。由于每个功能被分解成了事件级的函数，整个架构围绕事件模型被解耦了。这可以包括操作错误、操作变更，以及甚至安全访问。</li>
</ul>
<p>显然，在这个AEOP的简短描述中还有很多组件和事件没有被覆盖到。在下一节我们将围绕这3个组件进一步分析其细节。</p>
<p>AEOP事件模型和事件驱动架构（EDA）之间存在着差异。EDA是一种提倡产生事件、检测事件、消费事件、对事件做出反应的软件架构模式（来自维
基百科）。EDA缺失的是如何捕捉业务流程的结构和控制。此外，AEOP区别了3类事件，一个针对正常操作、一个驱动内部变更和一个针对外部变更。它们负
责不同的待处理模块，而EDA则使用相同的方法处理所有模块。AEOP使用生命周期在一个分布式、层次、有状态和动态的结构中将事件分组。</p>
<h4>AEOP中的信息&#8220;装配线&#8221;是围绕动态生命周期模式的多联装（Multi-shell）容器构建的</h4>
<p>所有现代软件平台都是围绕某种形式的容器模式构建的。AEOP也不例外。基于J2EE的应用服务器甚至有两类容器：Servlet和EJB。操作系
统可被视为是一种应用程序的容器。容器的概念和&#8220;计算机资源是有限的&#8221;这一思想有一定联系。容器在AEOP架构中的使用是不同的：</p>
<ul>
    <li>容器创建和管理的对象是业务实体资源的直接表示。例如，AEOP操作容器管理整个订单生命周期，不仅仅是反映现有计算机资源的对象。 </li>
    <li>容器可以区分作为正常事件序列一部分、改变受管资源状态的调用和触发正常操作之外变更的调用。由于存在两类变更，因而每个容器都关联两类变更管理模块。为了提供比现有静态架构更好的企业动态现实支持，AEOP容器支持受管资源的动态生命周期。 </li>
    <li>容
    器并非类似J2EE应用服务器中的单独结构。各容器按照控制层次链接在了一起。集成的事件模型驱动了系统外产生事件的接收和处理。在这种情况下，既不在最
    顶端也不在最底端的容器扮演了双重角色，一个作为资源生命周期管理器，另一个作为受管理的资源。这就是给予系统容器的多联装（Multi-shell）结
    构。</li>
</ul>
<p>整个AEOP架构和实现是围绕描述容器（它管理代表真实业务实体的资源）的模式而构建的，对正常操作和变更进行了区别，是反映业务控制层级的结构的一部分。</p>
<img alt="" _href="img://Fig4.jpg" src="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig4.jpg" />
<p>图4. AEOP多联装（Multi-shell）容器架构将技术置于顶端，业务操作置于中间，事件处理置于底部</p>
<p>每个AEOP容器可能处理3类事件：（1）由&#8220;事件模型&#8221;模块标识的正常操作；（2）来自由控制层级中上层容器发出的内部变更的事件；或（3）来自由控制层级中下层容器发出的外部变更的事件。</p>
<p>除了主生命周期及其关联的事件模型，那里还有被认为是正常操作&#8220;静态部分&#8221;的业务实体。例如，在正常操作期间不期望改变的项目价格或物理位置。它们
是通过所谓的&#8220;静态模型&#8221;的模块捕捉到的。这并不意味着它们就是固定且隔离于业务动态之外。静态模型只有通过变更管理流程使用内部和外部变更来更新。</p>
<p>AEOP控制层次可被用来设置容器的模式：初始化、操作和关闭。只有处于操作模式的容器才能处理事件。</p>
<p>在AEOP架构中，有3个相关元素：1）组件和控制的高级别技术结构，2）操作平台，3）事件处理平台。</p>
<p>高级别AEOP技术代表整个应用，该应用可被认为是一个自适应系统。它有3个主要平台，并且它们各自也都可被认为是一个自适应子系统：上面的平台扮
演了管理角色，下面的平台扮演了环境角色。每个平台自己都有定义良好的、实现了自身功能的事件模型，并且它还要和其他两个进行交互。在每个平台上我们都可
以发现一个仓储，它可以是一个缓存数据库或一个较传统的关系数据库。</p>
<p>与外部系统的集成遵循相同的事件模型。根据外部系统类型的不同，可以使用的集成策略有两种。如果AEOP只有访问持久化仓储的权限，它可以使用始终
运行的调度任务来查看数据库记录中的数据变更。第二个方法依赖API调用，如果可以将外部系统实现改成在主业务实体变更时发起调用，那么就可以实施这个策
略。</p>
<img alt="" _href="img://Fig5.jpg" src="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig5.jpg" />
<p>图5. 高级别AEOP多联装（Multi-shell）容器架构</p>
<p>这3个平台中的每一个也都是围绕特定生命周期元素构建的。操作平台围绕主业务实体生命周期，系统运行时平台围绕用户会话，安装/持久化平台围绕版本控制生命周期。</p>
<p>虽然数据只能按照苛刻的事件模型蓝图来处理，但是相同的数据却可以被任何有权访问系统且有正确证书的用户访问。但是，很少有针对平台用户的数据查看
工具。例如，系统运行时平台有一个针对运行时错误的查看器，它被用来监测用户和分布式系统。这一工具也可在各子系统失效时重新启动它们。</p>
<p>AEOP技术级还实现了一个完整的初始化过程。启动过程中，在用户可以运行第一个任务之前，应用必须经历3个步骤：</p>
<ul>
    <li><strong>启动应用：</strong>系统管理员启动主应用。这是通过启动像Tomcat（J2EE
    servlet容器）以及Axis这样的容器（Web服务平台）做到的。应用可以将Spring框架加载到一个轻量级容器中，并使用Spring
    bean配置文件加载初始的&#8220;启动&#8221;模块。&#8220;启动&#8221;模块初始化&#8220;系统&#8221;模块。该模块负责主应用的硬编码配置。它还可能包含对现有远程数据源的硬连接、读取
    远程部署的应用版本的Web服务端点、测试方法和对各种分布式系统的开放互联性，以及提供正常操作、性能和日志相关数据的功能。产生数据的主要用户是开发
    者和技术支持。</li>
    <li><strong>安装/启动/持久化/恢复 &#8220;系统&#8221;模块：</strong>这个模块实现了所有系统相关的功能，包括检查系统配置。它的主要功能是将一个包含所有资源（远程数据源、用户、版本、集群中的服务器、连接、安全数据等）及其状态的系统Map载入缓存。该模块提供了应用监视器。这个模块的主要用户是技术支持。步骤：
    <ul>
        <li>此阶段的第一个步骤是验证分布式系统上线并正在运行。如果远程系统没有激活，一个被调度的操作变更将被发送给操作系统，由它使那些依赖它们的任务无效。它还将把它们的缓存数据设为&#8220;过时&#8221;。它还将给应用仪表盘发送一个信号，并在日志中记录。 </li>
        <li>一旦这个工作完成，它就验证那些远程数据位置的软件版本是否正确。如果不正确，它将使它们失效，并给应用仪表盘发送一个信号和日志记录的动作。 </li>
        <li>最后一步是检查那些远程分布式系统的数据定义。如果它们改变了，将采取同前一活动相同的步骤。</li>
    </ul>
    </li>
    <li><strong>启动主应用运转：</strong>这是用户可以访问应用之前的最后一个步骤。它将操作上下文，连同所有激活的用户实例和它们的状态载入缓存。操作上下文的一部分是指向分布式系统数据及其状态，以及这些分布式系统操作上下文的指针。这个模块的主要用户是业务用户。</li>
</ul>
<img alt="" _href="img://Fig6.jpg" src="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig6.jpg" />
<p>图6. 系统控制层级确定的3个主要容器的状态</p>
<p>初始化之后，同一架构被用来控制主应用的操作就绪状态。它有3个场景：</p>
<ul>
    <li>用户运行/创建查询时产生的错误：这是最普通的场景。一旦错误被操作模型子平台检测到，系统就被设置成&#8220;操作错误&#8221;模式，一
    条消息将被发送给系统模型子平台，并且待显示的新状态/警报被发送给监测主应用的技术支持团队。出于日志记录的目的（这是给开发团队的信息），同一错误将
    被发送给安装/持久化/恢复模型子平台。用户也将收到一条显示当前事件状态以及可用选择的消息。一个选择是由前一步恢复实例。因为整个操作是围绕保证前一
    事件被成功完成的事件模型构建而成的，这令这一选择成为可能。</li>
    <li>经理或数据源管理员改变操作上下文：在这个情况下，主应用被设置成特殊的&#8220;操作变更&#8221;模式。当前受变更影响、正在运行任务的所有用户都将被通知。他们有两个选择：要么经历一个实例更新过程，要么简单地忽略。 </li>
    <li>产生了一个环境系统错误：在这个情况下，监测IT环境的技术支持团队会得到通知。它是通过能够监测集群或J2EE/NET应用服务器的工具做到的。此时，主应用将试图记录最近的活动或帮助调试的应用服务器堆栈信息。</li>
</ul>
<p>接下来的细节是关于AEOP操作平台的。事件模型是围绕业务实体的类型构建的。每个产品类型的服务有其自己的生命周期，它由自己的事件蓝图表示。事
件蓝图是定义良好的有序事件集合。每个蓝图关联一组变更类型。内部或外部事件可以是正常操作的一部分，或可以代表不同类型的变更。每个事件必须被清晰地标
出，因为它是要被一定的模块处理的。这种方法不同于事件驱动的架构方法，后者将事件视为&#8220;在你的企业内部或外部发生的值得注意的东西&#8221;。它也不同于
EDA，EDA是以事件结构为中心的，比如它需要有事件头、事件体、事件时戳等。AEOP没有任何这些限制，因为整个结构是由它的类型决定的。</p>
<img alt="" _href="img://Fig7.jpg" src="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig7.jpg" />
<p>图7. AEOP的&#8220;信息装配线&#8221;是围绕业务操作的容器被构建的</p>
<p>操作平台使得3类基本用户——工人（他们支持正常操作），经理（他们触发内部操作变更）和外部业务团体（即用户）——之间的交互自动化。</p>
<p>最后一个要详细描述的平台是AEOP事件处理。&#8220;装配线&#8221;概念能在超过一个世纪的时间里如此流行，其中一个原因就是，每一步可以轻易地和其余的步骤
解耦。除此之外，不管他需要执行什么工作，每个&#8220;岗位&#8221;的工人都将遵循相同步骤。当一个产品的主实例到达这个&#8220;岗位&#8221;，它就像一个需要使用各种零件&#8220;填充
&#8221;的空
&#8220;壳&#8221;一样。这些零件有两类：在当前&#8220;岗位&#8221;待组装的特殊零件；对装配过程只起帮助作用的零件，我们称这些零件为&#8220;工具&#8221;。例如，一个&#8220;工具&#8221;可能是帮助
装配过程的某种胶水。这三个待组装元素有它们自己的仓库，它们有自己的&#8220;到达&#8221;时间安排，并且它们遵循特殊的装配过程逻辑。一旦组装完成，在到达下一个&#8220;
组装岗位&#8221;之前，那个零件实例不会发生任何事情。</p>
<p>&#8220;信息装配线&#8221;跟真实的装配线概念非常相似。在事件处理期间，我们遇到的是同类信息：代表主业务实体的&#8220;壳&#8221;，特定于一个事件和需要被增加实例的信
息，以及被称为&#8220;工具&#8221;、只特定于需要被增加事件的信息。&#8220;工具&#8221;类型信息的主要特征是，它是有限的，可以为同一事件多次使用它，并且在处理事件过程中你
可能把它&#8220;用光&#8221;，在某种程度上类似装配过程期间用来粘住零件的&#8220;胶水&#8221;。在订单处理中，&#8220;工具&#8221;信息的一个例子就是企业给客户的赊账限额。他可能一次性
使用所有可用赊账限额支付产品，或者他可能决定只使用部分，他可以使用它支付多次购买，并且在一个购买过程中他可能把它&#8220;用光&#8221;了。</p>
<p>另外它与&#8220;仓库概念&#8221;也很相似。&#8220;待装配&#8221;信息对何时开始检索它有明确的规则。例如，当客户用信用卡支付帐单时，账户信息是实时从银行检索出来的。保存在任何其他数据&#8220;仓库&#8221;中的值都不是一个有效的值。</p>
<p>处理事件期间，从各系统取信息可以通过事件&#8220;定位&#8221;层和事件&#8220;调度器&#8221;层来完成。只有在完成这两步之后，&#8220;信息&#8221;才能按照逻辑进行&#8220;装配&#8221;。&#8220;定位
&#8221;层使用一种面向消息的组件，&#8220;调度器&#8221;层使用以调度为中心的组件，&#8220;逻辑&#8221;层使用BPM/业务规则引擎作为主组件。次序总是不变的。</p>
<p>调度器在架构/设计中的任务不仅仅是安排不同任务的时间，它的另一个任务是帮助设计一个在事件层完成控制状态变化的多线程架构。这是通过使用调度器
作为一个事件模块做到的，它把在状态变化期间可能有并行任务的流程转换成单独的&#8220;泳道&#8221;。这样，我们就可以在事件层像调度器处理每个事件子任务那样来实现
状态变化逻辑了。这样，流程&#8220;泳道&#8221;中的失效将使整个系统处于一个清晰可辨的状态中。 </p>
<img alt="" _href="img://Fig8.jpg" src="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig8.jpg" />
<p>图8. AEOP事件处理容器——定位、调度和逻辑</p>
<p>结合所有这3个元素，&#8220;信息装配线&#8221;可以被构建成对任何企业系统都是通用的，不论企业涉足的领域和规模大小。这与装配线的方法类似，起源于汽车制造业，后来扩展至所有其他制造行业。</p>
<p>AEOP事件处理容器针对内外部变更有两类变更管理模块。假如一个事件被标识为一个变更，决策表将把具体的变更类型和特殊事件联系起来。这个架构是
作为一组插件来设计的，它是根据现有实例的状态被调用的。例如，在订单处理中，对于预付和未付订单而言，处理价格变更的方法是不同的。</p>
<h4>总结——数天内完成架构、数周内完成设计、数月内完成实现——构建集成的DBA服务器端基础设施的简易之道</h4>
<p>AEOP方法有诸多优点。主要优点是它标准化了服务器端应用的架构，这正是当今IT所缺失的。它将这个服务器端实现转变成事件插件代码的编写，类似微软Windows应用的编写方式。</p>
<a _href="resource://Fig9_lg.jpg" href="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig9_lg.jpg"><img alt="" _href="img://Fig9.jpg" src="http://www.infoq.com/resource/articles/beyond-soa-dba-part-2/zh/resources/Fig9.jpg" /></a>
<p>图9. 自适应操作平台支持动态、拥有控制层级、分布式和有状态的业务</p>
<p>使用AEOP实现应用的3步骤包括：</p>
<ol>
    <li>获取对象流和变更类型</li>
    <li>获取3个平台的组件</li>
    <li>构建每个事件处理的5个模型</li>
</ol>
<p>在这个架构中，像SOA这样的技术和架构概念扮演配角。像BPM引擎、调度器、消息传递这样的组件在架构中有明确的角色，但是它们对设计的影响很
小。这类似于飞机设计中各零件扮演角色的方式。电动发动机、电线、螺母和螺钉对整个飞机的功能至关重要，但是它们对设计过程却非如此。</p>
<p>由于这种方法不依赖于业务，可以构建类似微软Visual C++向导或Visual Basic这样的工具进一步使实现过程自动化。这不仅提高了开发团队的生产力，而且还有助于开发者关注实现的真实方面，而不是与错误的架构&#8220;搏斗&#8221;。</p>
<p><strong>即将到来的第三部分——案例研究和局外人观点 <br />
本文将在第三部分继续，它探讨一个真实实现的案例研究和新的自适应系统理论的简要总结。</strong></p>
<p>查看英文原文：<a target="_blank" href="http://www.infoq.com/cn/articles/beyond-soa-dba-part-2">Beyond SOA, a New Type of Framework for Dynamic Business Applications - Part II</a>。</p>
<p><br />
</p>
<p>转自：http://www.infoq.com/cn/articles/beyond-soa-dba-part-2<br />
</p>
<p><br />
</p>
<img src ="http://www.blogjava.net/jhyan/aggbug/232644.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jhyan/" target="_blank">Joshua Yan</a> 2008-10-06 13:08 <a href="http://www.blogjava.net/jhyan/archive/2008/10/06/232644.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>超越SOA：动态业务应用的新企业应用框架(1) 转载</title><link>http://www.blogjava.net/jhyan/archive/2008/10/06/232641.html</link><dc:creator>Joshua Yan</dc:creator><author>Joshua Yan</author><pubDate>Mon, 06 Oct 2008 05:05:00 GMT</pubDate><guid>http://www.blogjava.net/jhyan/archive/2008/10/06/232641.html</guid><wfw:comment>http://www.blogjava.net/jhyan/comments/232641.html</wfw:comment><comments>http://www.blogjava.net/jhyan/archive/2008/10/06/232641.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jhyan/comments/commentRss/232641.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jhyan/services/trackbacks/232641.html</trackback:ping><description><![CDATA[<h2><br />
</h2>
<h2>第一部分——即使拥有全部需求和最佳设计，你的架构仍然很可能失败，原因在于&#8230;&#8230;</h2>
<p><strong>目前的管理学校，教育培养的是公司经营者。设计公司几乎没有引起重视&#8230;&#8230;几乎从来没有任何人为了取得计划的增长和稳定性，有意识和有思想地设计一个组织。</strong></p>
<p><strong>——&nbsp;&nbsp;Jay W. Forrester，设计未来（1998）</strong></p>
<h3>介绍</h3>
<p>在一篇名为《动态业务应用势在必行（The Dynamic Business Applications Imperative）》的论文中，Forrester的高级分析师John R. Rymer指出了当今应用的一个致命缺陷：</p>
<p style="margin-left: 40px; font-weight: bold;">当今应用迫使人们去寻找一种将孤立的信息和功能组映射到他们任务和过程的方法，它们强迫IT人员花高额预算来跟踪不断变化的市场、策略、规章制度和业务模型。</p>
<p style="margin-left: 40px; font-weight: bold;">在下一个5年内，IT的主要目标应该是发明新一代企业软件，适应业务和业务工作，同时能随业务演变而演变。</p>
<p style="margin-left: 40px; font-weight: bold;">Forrester称这个新生代为动态业务应用，
强调了和业务过程及工作（为人而设计）的紧密配合，对业务变化的自适应（为变化而构建）。在这个阶段，动态业务应用的需求比创建它们所需的设计实践更清
晰。工具都是现成的：面向服务架构（SOA）、业务过程管理（BPM）和业务规则领域中的先驱——包括独立软件开发商（ISV）——已经开始向我们展示了
这种方法。现在就是开始这段旅程的时候。</p>
<p>在这篇由两部分组成的文章中，我们会从架构和方法论的角度，采用历史的观点来看待这些动态业务应用（DBA）的发展。我们的目标是获得一种能使应用容易适应业务变化和其他必要修改的构建方法。随着企业在21世纪关注灵活性，DBA是使业务和IT在未来几十年内成功的关键。</p>
<img src="http://www.infoq.com/resource/articles/dynamic-business-applications/en/resources/Fig1.jpg" alt="" />
<p><strong>图 1. 灵活性和效率——21世纪企业的两个主要驱动力</strong></p>
<h3>动态性对我们意味着什么？</h3>
<p>在软件工程领域，许多框架或产品都声称具有自适应性。在我们设法理解一个解决方案在适应变化方面究竟有多好之前，需要给系统是如何变化的——它们的动态性——下一个可靠的定义。</p>
<p>早期的面向对象方法论认识到<a href="http://www.infoq.com/cn/articles/dynamic-business-applications#ednref1">[1]</a>：为了使系统分析中立，它必须基于两类现实世界的需求：</p>
<ul>
    <li>现实世界的实体 —— 收集现实世界实体的信息和它们间的关系，有助于分析师开始以一种系统的、结构的、客观的观点来看待需求，而非一种技术的、主观的观点  </li>
    <li>现实世界的事件 —— 系统行为只由改变现实世界实体状态的事件的出现来驱动</li>
</ul>
<p>在这样的背景下，对于每一个被分析的系统，我们总能识别一个或多个最重要的实体。每个实体都又包含3个关联元素：事件、状态和生命周期。每个事件代
表状态中的一个变化，所有普通实体状态的有序和代表了一个生命周期。但是，那些触发状态变化且是正常流程一部分的事件与那些触发状态变化但不是正常流程一
部分的事件之间有明显的差异。例如，当一个产品订单被提交之后，一组可能发生的事件包括付费处理和订单交付。当一个用户变更订单或当企业改变价格时，我们
不能认为这些动作是正常流程的一部分，因此它们与实体（如订单）的生命周期无关。核心实体实例的生命周期单独定义了在正常操作中系统最有可能处理的东西。
所有其他事件类型，如变化或中间步骤，被区别对待。</p>
<p>这个场景对很多工程师都不陌生：一个系统模型包含一个核心实体结构，该实体具有一组事件，这些事件组成了实体的生命周期。这个系统模型对分析师和设
计者都很清晰且易于理解。建模工具，如有限状态机、实体关系图、实体状态转换图和数据流图，为了帮助这种方法已经经过了快20年的完善。那些为复杂系统
（如空客380或F-22，后者是世界上最高级的战斗机）服务、拥有数十亿行代码的软件就是这样被编写出来的。使用对象流图（它是捕获事件和状态转换的基
础模型）虚拟化实体生命周期是这个模型的关键。在这个情况下，架构可以被认为是静态的，因为整个系统状态在时间轴上的任意一点都是确定的。</p>
<img src="http://www.infoq.com/resource/articles/dynamic-business-applications/en/resources/Fig2.jpg" alt="" />
<p><strong>图 2. 事件模型、状态变化和生命周期是正常操作的核心</strong></p>
<p>普通事件、状态、生命周期间的关系，以及从其他事件类型中分出的普通事件是理解所建议的动态操作框架的基础。正如James Martin
和James
Odell很久以前在《面向对象分析设计》中所写的，分析师、设计师和实现者都应该使用同一系统模型。分析师使用数据流图思考，设计师使用结构图思考，程
序员使用Java和SQL思考。在数据流上下文中，分析师识别对象类型，并思考改变对象状态的事件。最终用户也理解这个相同的认识。他们也应该按照对象类
型、事件、对象状态的变化，以及触发和控制事件的业务规则进行思考。Martin和Odell强调了对象流图对系统设计师的重要性：&#8220;事件模式适合按照事
件、触发器、条件和操作来描述过程。但是这种方式不适合描述大型复杂过程。一个系统领域常常太大或太复杂，无法表示成事件和触发器。此外，可能只有一个高
级别的认识才是必要的。这对战略级别的规划尤其正确。在这样的情况下，一个对象流图是有用的。对象流图（OFD）与数据流图（DFD）类似，因为它们描述
了活动和其他活动间的接口。在DFD中，这个接口传递数据。在对象技术中，我们不再限于数据传递。相反，图应该表示从一个活动传递到另一个活动的任何类型
事物：不论它是报表、零部件、已完货物、设计、服务、硬件、软件——或数据。简而言之，OFD指的就是被产生的对象，以及产生和交换它们的活动。&#8221;</p>
<p>为了捕获与业务操作关联的信息流，业务分析师用价值流程图（Value Stream
Mapping）对OO方法论进行了补充。价值流程图起源于丰田，与精益制造关系紧密。美国国家环境保护局将价值流程图定义为&#8220;用来认识那些产生产品或交
付服务的活动序列与信息流程的精益过程映射方法。&#8221;此处的关键词是&#8220;产品&#8221;和&#8220;服务&#8221;。它们显现了合适的信息流程在整个企业中扮演的统一角色。</p>
<p>把过程流图和价值流程图两个概念结合在一起后，它产生了一个完全代表整个企业经营范围、可被方便翻译成OO（图2）概念的框架基础。</p>
<p>但是，许多系统并不是静态的，它们变化无常的行为无法被一组关系和事件捕获。事实上，它们发生在不可知的<a href="http://www.infoq.com/cn/articles/dynamic-business-applications#ednref2">[2]</a>未来，传统用来捕获它们动态特点的工具不起作用。所有的业务应用和绝大多数现实世界的系统都归于此类。这些系统，基于它们和其他外部系统的交互方式，处理3类变化：</p>
<ul>
    <li>正常工作 ——
    组成主实体或实体们生命周期的正常事件序列。通过每个事件——实体改变其状态——通常可以方便地定义一个过程。在正常工作行为内部，有些操作上下文元素不
    期望被改变。例如，当一个客户订购一个产品时，在整个提取订单、准备订单和交付订单的过程中，诸如价格、组成和交付方式等是不期望被改变的。 </li>
    <li>内部变化 —— 如上所述，在整个核心实体生命周期内，某些上下文元素不期望被改变。在现实世界中，这并不总是真理，因为管理决策或其他因素会迫使上下文元素变化。我们称内部系统属性的变化是内部变化。  </li>
    <li>外
    部或环境变化 ——
    不管一个企业如何相信他们&#8220;拥有&#8221;一个客户，但是这个客户总有保留改变他或她意志的自由。一个系统不太可能与外部系统（如客户或供应商）总是有一个&#8220;固定
    的&#8221;合同。然而，正常工作很可能围绕这个&#8220;固定的&#8221;规则集合进行设计。我们称系统外部引起的变化为外部变化。</li>
</ul>
<p>要对现实世界系统建模，就必须处理好这所有3种变化类型。这种模型与静态架构模型相比，在管理复杂性上有了极大的提高。从正常工作的观点来看，内部
和外部系统完全独立于主信息流运行。内部和外部系统甚至有它们自己的操作——管理有其自身的决策周期，客户有其自己的操作环境——由各自的信息流描述。就
信息流而言，这3种系统分别运行在3个平行宇宙中。解决这3种非同步信息流的唯一办法就是为每个信息流实现一个独立全面的变更管理。这种复杂交互在图
3（动态操作图）中表示。</p>
<p>邮轮公司给客户提供的服务可以作为解释动态操作的例子。在订购时，一个客户会决定在游览期间他计划参与的服务。但是，不仅客户可能在游览前和游览中
改变主意，而且邮轮公司也可能会为了利用新机会或应对未知事件改变服务。按照当前方法设计的系统，大部分变更都以极高的运营成本人工处理。使用基于动态业
务应用架构原则设计出的系统，来自客户和内部管理决策的变更由两个与正常工作完全集成的变更管理子系统负责。这不仅能降低成本，而且还提高了服务质量，甚
至可以最优化运营来提高利润。因为是完全通用的，它还可以重用标准组件。最终结果对于参与的每个人、业务、IT和客户来说是多赢的。</p>
<img src="http://www.infoq.com/resource/articles/dynamic-business-applications/en/resources/Fig3.jpg" alt="" />
<p><strong>图 3. 动态操作有3个维度——正常事件、内部控制和外部反馈</strong></p>
<p>动态业务应用的目标之一就是使设计和软件实现变得简单，以支持对所有业务来说司空见惯的动态系统。以我们的经验，与一个框架优先的工程学相结合是构建一个DBA的最有效的技术方法。</p>
<h3>设计企业系统要求框架先行</h3>
<p>构建动态业务应用说起来简单，做起来难。工程，包括软件工程，都采用了有百年历史的框架优先方法。设计一座桥梁、一架飞机或者甚至是一个软件应用都
使用相同的方法：一个设计团队先收集需求，然后使用一组定义良好的框架步骤来设计和构建系统。在设计桥梁和其他工程系统时，现有框架已被证明非常成功。但
在使用它来为业务系统开发软件时，却碰了壁。这两类系统之间有一个根本区别。在设计桥梁和飞机时，最终结果总是一个拥有静态架构的系统：当变更发生时，如
增加桥梁负重或飞机速度，整个系统可能就要重头重新设计。不幸的是，软件也常常使用一个静态架构进行设计：每当一个非预期的变更被引入到运营中时，很可能
所有事情都停了下来，使用包含新增功能的系统替代现有系统。因为业务运营在一个不断变化的环境中，而且比以往更依赖IT系统，这种停——走式的解决方案是
不可接受的。持续升级和在企业基础设施中集成系统的成本已经达到了无法支撑的地步。</p>
<p>依赖业务涉众作为我们全部需求的输入首先就是个问题。考虑到需求，目前还没有真正适合动态操作的&#8220;框架优先&#8221;软件设计方法。甚至卡内基梅隆软件工程
学院也表示架构是由场景驱动的，场景以涉众输入为基础被创建出来：&#8220;诱导一个软件密集型系统的业务目标是标准架构设计和分析方法的一个组成部分。业务目标
是驱动方法的引擎，通过将它们的实现作为场景&#8230;&#8230;一个理想的设计方法或过程必须考虑众多涉众和众多影响。&#8221;</p>
<p>作为工程师，当我们收集系统需求时，我们怎能知道我们得到了正确的场景或是否遇上了正确的涉众？我们又如何能说明业务未来的变化，而这些变化通常连参与的涉众都不知道？</p>
<p>&#8220;企业经营者和企业设计师之间存在着根本区别。为了说明这点，考虑一下在一架飞机成功操作背后的两种最重要的人。一个是飞机设计师，另一个是这架飞
机的飞行员。设计师创造的飞机连平庸的飞行员都可成功驾驶。一般情况下，经理更像是飞行员而非一个设计师。一个经理管理一个组织，这和一个飞行员驾驶飞机
没什么两样。飞行员的成功依赖于那些创造了一架成功飞机的飞机设计师。另一方面，是谁来设计一家由管理者管理的公司呢？几乎从没有任何人有意识和有思想的
去设计一个组织，以取得有计划的增长和稳定性。在当前的管理学校中，教育培养的是企业的经营者，而如何设计企业几乎不受重视。&#8221;</p>
<p>在几年前完成的报告&#8220;设计未来&#8221;中，MIT的教授和系统动态之父Jay Forrester，指出这个问题是我们为企业设计系统的基本限制：</p>
<p>Forrester的观察进一步使当前的企业架构方法失效。在我们需要设计一个企业系统架构时，作为知识主要来源的涉众甚至是错误的分类。他们是企
业的&#8220;用户&#8221;，不是&#8220;设计师&#8221;。在设计飞机时，飞机设计师决不可能去询问飞行员或乘客关于飞机制造方面的事情。但是，在学校、工程或MBA课程中却没有企
业设计这门课。</p>
<p>那么回到企业架构，其中有一个根本的断档。企业架构的&#8220;用户&#8221;是企业涉众，很可能是熟悉企业动态性的企业毕业生，但是他们不熟悉工程方法。企业系统
的设计者和构建者——软件工程师——熟悉静态框架，但是对动态框架却很陌生。事实上，还没有说明业务动态的框架。根据企业架构框架，这是一个需要填补的缺
口。这个框架只描述企业是如何&#8220;被设计的&#8221;，但是也会定义开发路线图和主要组件，使用它们来构建企业的支持系统。</p>
<img src="http://www.infoq.com/resource/articles/dynamic-business-applications/en/resources/Fig4.jpg" alt="" />
<p><strong>图 4. 企业架构的业务和工程方法</strong></p>
<p>我们建议根本改变我们架构和设计信息系统的方式，以一种不要求业务涉众作为主要输入的方式。我们推荐利用一个以业务实体生命周期和事件模型为中心的框架作为架构的主要输入来源。业务场景只被用来微调一个已完架构，而不是作为主要驱动力。</p>
<p>这种框架优先方法从一开始就说明了业务动态，而不是事后诸葛亮。它暗示被设计的企业应用是动态适应的，而不是像由今天的方法论所实现的那样是静态适应的。这种方法成数量级的减小了开发和维护软件的成本，并砍掉了与改变和维护现有系统直接相关的超过70%的IT开销。</p>
<img src="http://www.infoq.com/resource/articles/dynamic-business-applications/en/resources/Fig5.jpg" alt="" />
<p><strong>Fig 5. 基于框架的软件解决方案开发方法</strong></p>
<p>在我们建议的方法中，业务场景只被作为一个已完架构的微调，而不是主要驱动力。我们将我们的直觉、经验和技巧输入到设计过程中越晚，产生导致巨大损失的错误的可能性就越少。由涉众输入引起的需求变更会在已经建好的现有解决方案框架中处理，减少了风险和延迟。</p>
<p>一份Standish报告研究表明，超过1千万美元的项目，成功率只有3%。行业咨询和哈佛商学院教授Andrew
McAfee表示，部署如此高成本技术（如ERP、CRM、供应链管理、电子商务和其他企业应用）组织的成功率在25% ~
70%之间。McAfee总结说：&#8220;这些面临的问题并非是单独的，它们都是同一事情的不同例子，基本上都是使用IT改变业务过程的结果。&#8221;。最近，这些百
分比有所提高，但是对于复杂系统IT仍缺乏清晰的路线。框架优先的方法能使业务变化集成到IT实现中，并提供了业务和技术之间更清晰的转换，可以将成功率
提高接近100%。建构复杂系统的时间由几个月或几年缩短至几天。</p>
<h3>动态操作的服务器架构 —— 忘记SOA，迎接信息装配线</h3>
<p>90年代早期，事件几乎是每本面向对象方法论书籍中的核心角色。随着象Windows这样基于GUI操作系统的出现，GUI开发平台依靠复杂事件模型来设计和构建单个应用。但是，在客户机-服务器环境中，服务器端的事件处理总是基于一个简单得多的模型。</p>
<p>当基于Web的技术（如J2EE和.NET）开始替代传统的客户机-服务器应用，客户机和服务器都经历了根本的转变。客户端的富OS事件模型由
Web浏览器和原始的脚本语言代替。在服务器端，事件处理由无状态、扁平的、静态架构所替代。其方式非常类似将网页传给Web浏览器的方式。</p>
<p>为了模拟现实世界的需求，需要一个有状态的、层次的、动态的和分布式的架构，设计必须严重依赖数据库来存储范围广泛的各种动态信息。但是根据其定
义，关系数据库非常适合存储不常变化的数据间关系。保存动态、分布式、层次的和有状态信息要求一个不同的基础设施，它不是以关系数据库为中心的。</p>
<p>基于Web的技术为支持现实世界系统引入了其他挑战。当J2EE应用服务器在一个分布式环境被使用时，使用Java作为编程语言的一个最大优势完全
没有了。Java虚拟机的垃圾回收从来没有被设计成能自动清除在多实例间交换的内存对象。在这种情况下，架构师和设计师必须编排整个对象生命周期，不考虑
编程语言的能力。甚至在数据保存在数据库中时，这种相同的数据清除问题也变得非常困难。</p>
<p>正如我们已经看到的，一旦我们能从正常工作中分离变化，架构就能只依赖事件和生命周期进行设计和实现。围绕生命周期进行系统设计已经经历了一个世纪——它被称为装配线。</p>
<p>在装配线于20世纪早期引入之前，制造业的工作方式多多少少和今天面向服务架构（SOA）处理信息的方式一样。每个对于SOA服务的调用一般都被视
为一个无状态调用。为了说明以前调用的历史，每个服务必须完全实现如何处理系统内部状态。一旦需求改变，几乎所有服务也需要以成本极高的方式重新编码来改
变它们各自的实现。</p>
<img src="http://www.infoq.com/resource/articles/dynamic-business-applications/en/resources/Fig6.jpg" alt="" />
<p><strong>图 6. 服务器架构是以事件模型为基础的</strong></p>
<p>我们建议使用以事件模型和生命周期为中心的信息架构作为业务需求和系统架构的双向翻译平台。事件模型在下一级被扩展成四个基本模型：状态、分布式、层次和动态。所有这5个模型可被基础需求和架构模型中的业务或技术人员方便地解释：</p>
<ul>
    <li><strong>事件模型/生命周期</strong>——
    它是构建其他模型的基础核心。对业务用户来说，它是价值流，反映产品/服务生命周期和为客户创造价值的过程序列。对技术人员来说，同一事件序列反映了代表
    业务实体对象的状态变化。最终结果是，事件模型扮演了解耦元素，大大简化了设计和实现。事件模型还扮演了另一个重要角色。因为其他四个模型是围绕事件模型
    而构建的，它还扮演一个集成平台。事实上，事件模型是创造实现变更、层次和分布式组件的唯一办法。 </li>
    <li><strong>状态模型</strong>—— 对业务用户来说，这个模型扮演了企业的面板，捕获当前经营的整体状况。对技术人员来说，它是系统的整体状态，它是全部生命周期实例的当前状态，以及它们的变化之和。  </li>
    <li><strong>分布式模型</strong> —— 对业务用户来说，这个模型捕获了其生命周期内控制产品/服务的各种组织。对技术人员来说，主实体只能基于分布式模型来控制。  </li>
    <li><strong>层次模型</strong>—— 所有业务都有代表管理层级的层次结构。所有系统设计应该在架构上反映这种控制层次。正如销售VP不能给CEO下命令一样，低层级的组件不能给高层级的组件发送执行&#8220;命令&#8221;。  </li>
    <li><strong>动态模型</strong>—— 继事件模型之后最重要的模型。业务用户使用它来捕获平时必须被处理的全部变更。如前所述，有两种变化类型：外部，如客户输入；内部，如管理决策。对技术人员来说，动态模型被翻译成一个匹配各种事件、生命周期和变化类型的插件架构。</li>
</ul>
<p>这5个模型不仅可以被用在初始设计，对贯穿整个系统生命周期的需求变更亦有裨益。它们一起形成了自适应系统设计所缺失的框架步骤。这5个模型排除了用例作为企业架构的主输入的必要性。它们可以被翻译成一个清晰和全面的工程问题集合，与在桥梁或飞机设计中使用的方法类似。</p>
<img src="http://www.infoq.com/resource/articles/dynamic-business-applications/en/resources/Fig7.jpg" alt="" />
<p><strong>图 7. 自适应架构是以5个模型为基础的信息架构结果</strong></p>
<p>这5个模型定义了以信息变化和装配线为中心的动态业务应用通用架构。最重要的子系统是：静态模型、变更管理、虚拟装配对象和事件处理。在下一个细化层级，还有两个子系统：系统命令和控制与持久化。</p>
<p>这个架构还解决了在寻求一个适用于事务型工作流隐喻的通用解决方案过程中长期存在的问题，它是由Jim Gray<a href="http://www.infoq.com/cn/articles/dynamic-business-applications#ednref3">[3]</a>在
几十年前提出的。因为整个设计以单个事件的执行为中心，不仅可以实现&#8220;移动到下一个装配步骤&#8221;，而且也可实现&#8220;移动到前一个装配步骤&#8221;。实现需要根据用户
的输入决定前往哪个&#8220;方向&#8221;。通过将多个步骤&#8220;链接&#8221;在一起，可以使用相同的架构实现一个事务型工作流的&#8220;撤销（Undo）&#8221;操作。</p>
<p>动态业务应用的一个关键元素是事件处理。使用新的自适应系统信息理论，可以使用一个通用组件结构来&#8220;执行&#8221;每个事件。这个组件使用声明性编程来内嵌
业务逻辑、调用工作流引擎、调度器和业务规则引擎。这个实现不仅可以极大加速自适应系统开发，而且可以使后期改变非常容易处理，也减少了维护复杂集成的需
要。</p>
<p>我们建议围绕事件（操作）和事件生命周期创建一个供给控制、运营和环境的物理模型。生命周期控制器为离散事件管理装配信息。变更管理功能指导标准事件模型和个体事件内外部变更的执行。</p>
<h3>结论</h3>
<p>我们已经讨论了扁平、无状态、静态、客户端——服务器、基于Web的解决方案的演变方式所带来的IT架构和层次、有状态、动态、分布式业务的现实世
界之间的脱节。我们还讨论了传统工程方法为什么不能支撑能支持动态业务的自适应系统的开发。我们展示这两个问题的可能解决方案可以用一种新的模型驱动架构
方法来找到。</p>
<p>本文的第二部分将描述动态业务应用的可能架构，并给出一个案例研究，介绍我们概念的实际实现。</p>
<h3>参考文献</h3>
<p><a href="http://www.infoq.com/cn/articles/dynamic-business-applications#ednref1" id="ednref1">[1]</a> Yourdon Systems Method —— Model Driven Systems Development —— Yourdon Press, 1993</p>
<p><a href="http://www.infoq.com/cn/articles/dynamic-business-applications#ednref2" id="ednref2">[2]</a>
Eric D. Beinhocker —— "The Origin of Wealth", HBS Press Book,2006 ——
在他的新书&#8220;The Origin of Wealth&#8221;中，麦肯锡公司高级顾问Eric D.
Beinhocker声称，将经济视为一种静态、平衡的系统的传统观点正在经受一场彻底的反思，包括为数众多的原则。新的中心是：&#8220;复杂经济学&#8221;，其中经
济被视为一种高度动态的、不断演变、几乎无法预测的系统。这个摘录涉及在未来未知时公司如何来制定战略。</p>
<p><a href="http://www.infoq.com/cn/articles/dynamic-business-applications#ednref3" id="ednref3">[3]</a> Mark Whitehorn ,The Register, Interview with Jim Gray —— http://www.regdeveloper.co.uk/2006/05/30/jim_gray/</p>
<p><strong>查看英文原文</strong>：<a href="http://www.infoq.com/articles/dynamic-business-applications" title="Beyond SOA: A New Enterprise Architecture Framework for Dynamic Business Applications">Beyond SOA: A New Enterprise Architecture Framework for Dynamic Business Applications</a></p>
<p><br />
</p>
<p><br />
</p>
<p>转自：http://www.infoq.com/cn/articles/dynamic-business-applications<a href="http://www.infoq.com/articles/dynamic-business-applications" title="Beyond SOA: A New Enterprise Architecture Framework for Dynamic Business Applications"><br />
</a></p>
<img src ="http://www.blogjava.net/jhyan/aggbug/232641.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jhyan/" target="_blank">Joshua Yan</a> 2008-10-06 13:05 <a href="http://www.blogjava.net/jhyan/archive/2008/10/06/232641.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>判断js函数是否存在，如果存在则执行</title><link>http://www.blogjava.net/jhyan/archive/2008/09/25/231060.html</link><dc:creator>Joshua Yan</dc:creator><author>Joshua Yan</author><pubDate>Thu, 25 Sep 2008 03:00:00 GMT</pubDate><guid>http://www.blogjava.net/jhyan/archive/2008/09/25/231060.html</guid><wfw:comment>http://www.blogjava.net/jhyan/comments/231060.html</wfw:comment><comments>http://www.blogjava.net/jhyan/archive/2008/09/25/231060.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jhyan/comments/commentRss/231060.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jhyan/services/trackbacks/231060.html</trackback:ping><description><![CDATA[假设funcName为函数名字，用如下方法就可以达到目标<br />
<br />
一定要添加try catch块，否则不起作用。<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;<br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(</span><span style="color: #0000ff;">typeof</span><span style="color: #000000;">(eval(funcName))</span><span style="color: #000000;">==</span><span style="color: #000000;">"</span><span style="color: #000000;">function</span><span style="color: #000000;">"</span><span style="color: #000000;">)&nbsp;&nbsp;<br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;funcName();<br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">(e)<br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">alert("not&nbsp;function");&nbsp;</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp; <br />
</span></div>
<img src ="http://www.blogjava.net/jhyan/aggbug/231060.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jhyan/" target="_blank">Joshua Yan</a> 2008-09-25 11:00 <a href="http://www.blogjava.net/jhyan/archive/2008/09/25/231060.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>clientHeight、offsetHeight和scrollHeight（转载 ）</title><link>http://www.blogjava.net/jhyan/archive/2008/08/29/225617.html</link><dc:creator>Joshua Yan</dc:creator><author>Joshua Yan</author><pubDate>Fri, 29 Aug 2008 09:00:00 GMT</pubDate><guid>http://www.blogjava.net/jhyan/archive/2008/08/29/225617.html</guid><wfw:comment>http://www.blogjava.net/jhyan/comments/225617.html</wfw:comment><comments>http://www.blogjava.net/jhyan/archive/2008/08/29/225617.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jhyan/comments/commentRss/225617.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jhyan/services/trackbacks/225617.html</trackback:ping><description><![CDATA[<p>我们这里说说四种浏览器对 document.body 的&nbsp;clientHeight、offsetHeight 和 scrollHeight 的解释，这里说的是 document.body，如果是 HTML 控件，则又有不同，<a href="http://www.cftea.com/c/2006/12/PCTKER6T0V62S854.asp" target="_blank">点击这里</a>查看。</p>
<p>这四种浏览器分别为IE（Internet Explorer）、NS（Netscape）、Opera、FF（FireFox）。</p>
<p><strong>clientHeight<br />
</strong>大家对 clientHeight 都没有什么异议，都认为是内容可视区域的高度，也就是说页面浏览器中可以看到内容的这个区域的高度，一般是最后一个工具条以下到状态栏以上的这个区域，与页面内容无关。</p>
<p><strong>offsetHeight<br />
</strong>IE、Opera 认为 offsetHeight = clientHeight + 滚动条 + 边框。<br />
NS、FF 认为 offsetHeight 是网页内容实际高度，可以小于 clientHeight。</p>
<p><strong>scrollHeight</strong><br />
IE、Opera 认为 scrollHeight 是网页内容实际高度，可以小于 clientHeight。<br />
NS、FF 认为 scrollHeight 是网页内容高度，不过最小值是 clientHeight。</p>
<p><strong>简单地说</strong><br />
clientHeight 就是透过浏览器看内容的这个区域高度。<br />
NS、FF 认为
offsetHeight 和 scrollHeight 都是网页内容高度，只不过当网页内容高度小于等于 clientHeight
时，scrollHeight 的值是 clientHeight，而 offsetHeight 可以小于 clientHeight。<br />
IE、Opera 认为 offsetHeight 是可视区域&nbsp;clientHeight 滚动条加边框。scrollHeight 则是网页内容实际高度。</p>
<p><strong>同理</strong><br />
clientWidth、offsetWidth 和 scrollWidth 的解释与上面相同，只是把高度换成宽度即可。</p>
<p><span class="chapterTitle">重要说明</span></p>
以上是在没有指定 DOCTYPE 的情况下，如果指定了 DOCTYPE，比如：DTD XHTML 1.0 Transitional，则意义又会不同，在这种情况下这三个值都是同一个值，都表示内容的<strong>实际</strong>高度。新版本的浏览器大多支持根据页面指定的 DOCTYPE 来启用不同的解释器。下载或浏览<a href="http://www.cftea.com/c/751/PX8O1XEX53RM4DIW.htm" target="_blank">测试文件</a>。
如果要在指定的 DOCTYPE 下按上述意义来应用，怎么办呢？答案是：将 document.body 和
document.documentElement 一起应用，比如：document.documentElement.scrollLeft ||
document.body.scrollLeft（一般将 document.documentElement 写在前面）<br />
<br />
<br />
转自：http://www.cftea.com/c/751.asp<br />
<img src ="http://www.blogjava.net/jhyan/aggbug/225617.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jhyan/" target="_blank">Joshua Yan</a> 2008-08-29 17:00 <a href="http://www.blogjava.net/jhyan/archive/2008/08/29/225617.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>document.body.scrollTop 值总为0的解决方法（转载）</title><link>http://www.blogjava.net/jhyan/archive/2008/08/29/225618.html</link><dc:creator>Joshua Yan</dc:creator><author>Joshua Yan</author><pubDate>Fri, 29 Aug 2008 09:00:00 GMT</pubDate><guid>http://www.blogjava.net/jhyan/archive/2008/08/29/225618.html</guid><wfw:comment>http://www.blogjava.net/jhyan/comments/225618.html</wfw:comment><comments>http://www.blogjava.net/jhyan/archive/2008/08/29/225618.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jhyan/comments/commentRss/225618.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jhyan/services/trackbacks/225618.html</trackback:ping><description><![CDATA[<div id="articleBody">
<p>做页面的时候可能会用到位置固定的层，读取 document.body.scrollTop 来设置层的位置，像这样：</p>
<pre class="code">window.onscroll = function ()<br />
{<br />
var oFix = document.getElementById("divfix");<br />
oFix.style.top = document.body.scrollTop + "px";<br />
}</pre>
<p>可是怎么没有达到预期效果呢，输出 document.body.scrollTop 的值一看，一直都是 0。原来是 DTD
的问题,要是页面直接用 开头的话就没有问题了。但是要符合 web 标准，DTD 当然是不能少的。具有 DTD 时用
document.documentElement.scrollTop 代替 document.body.scrollTop 就可以了。</p>
<pre class="code">window.onscroll = function ()<br />
{<br />
var oFix = document.getElementById("divfix");<br />
oFix.style.top = document.<span class="caution">documentElement</span>.scrollTop + "px";<br />
}<br />
</pre>
<p>编者注：</p>
<ul>
    <li>页面具有 DTD（或者说指定了 DOCTYPE）时，使用 document.documentElement。</li>
    <li>页面不具有 DTD（或者说没有指定了 DOCTYPE）时，使用 document.body。</li>
    <li>在 IE 和 Firefox 中均是如此。</li>
    <li>为了兼容，可以使用如下代码：
    <div class="code">var scrollTop = window.pageYOffset&nbsp; <br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; || document.documentElement.scrollTop&nbsp; <br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; || document.body.scrollTop&nbsp; <br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; || 0;</div>
    </li>
</ul>
<br />
转自：http://www.cftea.com/c/2008/06/U1FSRIC247DWTK2M.asp<br />
</div>
<img src ="http://www.blogjava.net/jhyan/aggbug/225618.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jhyan/" target="_blank">Joshua Yan</a> 2008-08-29 17:00 <a href="http://www.blogjava.net/jhyan/archive/2008/08/29/225618.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>mplayer 下播放rmvb文件</title><link>http://www.blogjava.net/jhyan/archive/2008/08/16/222404.html</link><dc:creator>Joshua Yan</dc:creator><author>Joshua Yan</author><pubDate>Sat, 16 Aug 2008 03:40:00 GMT</pubDate><guid>http://www.blogjava.net/jhyan/archive/2008/08/16/222404.html</guid><wfw:comment>http://www.blogjava.net/jhyan/comments/222404.html</wfw:comment><comments>http://www.blogjava.net/jhyan/archive/2008/08/16/222404.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jhyan/comments/commentRss/222404.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jhyan/services/trackbacks/222404.html</trackback:ping><description><![CDATA[1.到mplayer官网上下载codecs，我下载的是all<br />
<br />
2.解压到/usr/lib/codecs<br />
<br />
3.ok<br />
<br />
留下脚印备忘<br />
<br />
<br />
<img src ="http://www.blogjava.net/jhyan/aggbug/222404.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jhyan/" target="_blank">Joshua Yan</a> 2008-08-16 11:40 <a href="http://www.blogjava.net/jhyan/archive/2008/08/16/222404.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在Eclipse 3.4上使用FlexBuilder的方法(转载)</title><link>http://www.blogjava.net/jhyan/archive/2008/08/08/220796.html</link><dc:creator>Joshua Yan</dc:creator><author>Joshua Yan</author><pubDate>Thu, 07 Aug 2008 16:33:00 GMT</pubDate><guid>http://www.blogjava.net/jhyan/archive/2008/08/08/220796.html</guid><wfw:comment>http://www.blogjava.net/jhyan/comments/220796.html</wfw:comment><comments>http://www.blogjava.net/jhyan/archive/2008/08/08/220796.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jhyan/comments/commentRss/220796.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jhyan/services/trackbacks/220796.html</trackback:ping><description><![CDATA[<div class="PostHead">
<h1>在Eclipse 3.4上使用FlexBuilder的方法</h1>
<ul>
    <li class="PostAuthor">Author: admin </li>
    <li class="PostCateg">Filed under: <a href="http://www.sou5.cn/?cat=5" title="View all posts in 随便帖" rel="category">随便帖</a></li>
</ul>
</div>
<small class="PostTime"><strong>Wednesday</strong><br />
Aug 6,2008</small>
<p class="fp"><a class="zem_slink" title="Eclipse (software)" rel="homepage" href="http://www.eclipse.org/">Eclipse</a> 3.4发布已经有一段时间了，其带来很多新的<a href="http://download.eclipse.org/eclipse/downloads/drops/R-3.4-200806172000/whatsnew3.4/eclipse-news-part1.html" target="_blank">特性</a>，
但是对于使用FlexBuilder的朋友来说，想要切换到Eclipse 3.4就没那么容易，因为FlexBuilder是基于Eclipse
3.3的，和Eclipse 3.4并不兼容，在Eclipse 3.4刚发布的时候我就做过尝试，可是mxml编辑器却不能打开，会报
org.eclipse.jface.util.Assert$AssertionFailedException: <a class="zem_slink" title="Assertion (computing)" rel="wikipedia" href="http://en.wikipedia.org/wiki/Assertion_%28computing%29">Assertion</a> failed，当时没有时间折腾，Adobe官方关于这里Bug的说明在<a href="https://bugs.adobe.com/jira/browse/FB-13155" target="_blank">这里</a>，这里据说在FlexBuilder 3.01已经解决了这样的问题，可那里有3.01下载，对不起，我也不知道。今天无意发现了<a href="http://www.tekool.net/blog/2008/06/28/flex-builder-3-plugin-dont-work-with-eclipse-34/" target="_blank">这里</a>，这里提供了一个<a href="http://www.tekool.net/blogfiles/flex-builder-3-plugin-dont-work-with-eclipse-34/FB3_Eclipse34_patch.zip" target="_blank">补丁</a>，利用这个我们就可以在Eclipse 3.4上使用FlexBuilder了。安装方法如下：  首先从<a href="http://www.tekool.net/blogfiles/flex-builder-3-plugin-dont-work-with-eclipse-34/FB3_Eclipse34_patch.zip" target="_blank">这里</a>下载这个补丁包：  <code><a class="zem_slink" title="Wget" rel="homepage" href="http://www.gnu.org/software/wget/">wget</a> http://www.tekool.net/blogfiles/flex-builder-3-plugin-dont-work-with-eclipse-34/FB3_Eclipse34_patch.zip</code> 然后解压该补丁包，解压后在Flex <a class="zem_slink" title="Builder pattern" rel="wikipedia" href="http://en.wikipedia.org/wiki/Builder_pattern">Builder</a> 3 Plug-in/eclipse/<a class="zem_slink" title="Plugin" rel="wikipedia" href="http://en.wikipedia.org/wiki/Plugin">plugins</a>应该有两个文件：</p>
<ul>
    <li>com.adobe.flexbuilder.debug.e33_3.0.194161.jar</li>
    <li>com.adobe.flexbuilder.editors.derived_3.0.194161.jar</li>
</ul>
<p>在您的FlexBuilder目录下找多对应的文件，因为可能补丁包的版本和您安装的FlexBuilder版本有差异，所以直接在查找类似名称的文件即可，如：</p>
<pre><a class="zem_slink" title="Ls" rel="wikipedia" href="http://en.wikipedia.org/wiki/Ls">ls</a> -l plugins/com.adobe.flexbuilder.editors.derived*<br />
-rw-r--r-- 1 feiy feiy 218286 2008-06-30 08:04 plugins/<strong><em>com.adobe.flexbuilder.editors.derived_3.0.196042.jar</em></strong></pre>
<p>那么首先将<strong>com.adobe.flexbuilder.editors.derived_3.0.194161.jar</strong>复制到FlexBuilder的plugins目录下，然后在Plugins目录执行如下命令：</p>
<pre>cp com.adobe.flexbuilder.editors.derived_3.0.196042.jar  com.adobe.flexbuilder.editors.derived_3.0.196042.jar.old<br />
mv com.adobe.flexbuilder.editors.derived_3.0.194161.jar  com.adobe.flexbuilder.editors.derived_3.0.196042.jar</pre>
<p>接着在FlexBuilder/plugins目录中查找<strong><em>com.adobe.flexbuilder.debug.e33</em></strong>开头的目录:</p>
<pre>ls -l |<a class="zem_slink" title="Grep" rel="wikipedia" href="http://en.wikipedia.org/wiki/Grep">grep</a> com.adobe.flexbuilder.debug.e33<br />
drwxr-xr-x 3 feiy feiy    4096 2008-08-05 11:22 <em><strong>com.adobe.flexbuilder.debug.e33_3.0.196042</strong></em></pre>
<p>以上<strong><em>com.adobe.flexbuilder.debug.e33_3.0.196042</em></strong>目
录就是我们要找的目录，那么首先将com.adobe.flexbuilder.debug.e33_3.0.194161.jar解压到临时目录，然后
将解压出来的文件复制到FlexBuilder/plugins
/com.adobe.flexbuilder.debug.e33_3.0.196042目录中。 安装以上补丁后，就可以在Eclipse
3.4中正常使用FlexBuilder了。</p>
<p><br />
</p>
<p><br />
</p>
<p>如果还是不行就执行./eclipse -clean<br />
</p>
<img src ="http://www.blogjava.net/jhyan/aggbug/220796.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jhyan/" target="_blank">Joshua Yan</a> 2008-08-08 00:33 <a href="http://www.blogjava.net/jhyan/archive/2008/08/08/220796.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>fb3 sn</title><link>http://www.blogjava.net/jhyan/archive/2008/08/07/220621.html</link><dc:creator>Joshua Yan</dc:creator><author>Joshua Yan</author><pubDate>Thu, 07 Aug 2008 04:31:00 GMT</pubDate><guid>http://www.blogjava.net/jhyan/archive/2008/08/07/220621.html</guid><wfw:comment>http://www.blogjava.net/jhyan/comments/220621.html</wfw:comment><comments>http://www.blogjava.net/jhyan/archive/2008/08/07/220621.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jhyan/comments/commentRss/220621.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jhyan/services/trackbacks/220621.html</trackback:ping><description><![CDATA[1377-4364-8105-1017-5779-4100 <br />
1377-4864-2155-4708-3713-2066 <br />
1377-4561-2389-2527-0543-9076 <br />
1377-4167-2588-8404-4842-4168 <br />
1377-4469-0634-7084-5700-9553 
<img src ="http://www.blogjava.net/jhyan/aggbug/220621.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jhyan/" target="_blank">Joshua Yan</a> 2008-08-07 12:31 <a href="http://www.blogjava.net/jhyan/archive/2008/08/07/220621.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>fedora9 下触摸板设置备忘</title><link>http://www.blogjava.net/jhyan/archive/2008/08/05/220301.html</link><dc:creator>Joshua Yan</dc:creator><author>Joshua Yan</author><pubDate>Tue, 05 Aug 2008 15:00:00 GMT</pubDate><guid>http://www.blogjava.net/jhyan/archive/2008/08/05/220301.html</guid><wfw:comment>http://www.blogjava.net/jhyan/comments/220301.html</wfw:comment><comments>http://www.blogjava.net/jhyan/archive/2008/08/05/220301.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jhyan/comments/commentRss/220301.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jhyan/services/trackbacks/220301.html</trackback:ping><description><![CDATA[fedora 9下触摸板单击，双击，滚动不可用，首先安装更新 http://www.ocf.berkeley.edu/~bobk/packages/synaptics-0.14.6-8.1.fc9.i386.rpm<br />
<br />
然后设置触摸板，在xorg.conf 里面修改<br />
<br />
<br />
Section "ServerLayout"<br />
&nbsp;&nbsp;&nbsp; Identifier&nbsp;&nbsp;&nbsp;&nbsp; "Default Layout"<br />
&nbsp;&nbsp;&nbsp; Screen&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp; "Screen0" 0 0<br />
&nbsp;&nbsp;&nbsp; InputDevice&nbsp;&nbsp;&nbsp; "Keyboard0" "CoreKeyboard"&nbsp;&nbsp; ＃＃＃＃＃＃<br />
<br />
EndSection<br />
<br />
<br />
Section "InputDevice"<br />
&nbsp;&nbsp;&nbsp; Identifier&nbsp; "Synaptics"<br />
&nbsp;&nbsp;&nbsp; Driver&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "synaptics"<br />
&nbsp;&nbsp;&nbsp; Option&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "Device" "/dev/input/mice"<br />
&nbsp;&nbsp;&nbsp; Option&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "Protocol" "auto-dev"<br />
&nbsp;&nbsp;&nbsp; Option&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "Emulate3Buttons" "yes"<br />
&nbsp;&nbsp;&nbsp; Option "TapButton1" "1"<br />
&nbsp;&nbsp;&nbsp; Option "TapButton2" "2"<br />
&nbsp;&nbsp;&nbsp; Option "SHMConfig" "on"<br />
EndSection<br />
<br />
<br />
保存，重新登录，ok<br />
<br />
<img src ="http://www.blogjava.net/jhyan/aggbug/220301.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jhyan/" target="_blank">Joshua Yan</a> 2008-08-05 23:00 <a href="http://www.blogjava.net/jhyan/archive/2008/08/05/220301.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>firefox 3下听在线音乐 （1 听）</title><link>http://www.blogjava.net/jhyan/archive/2008/06/30/211790.html</link><dc:creator>Joshua Yan</dc:creator><author>Joshua Yan</author><pubDate>Mon, 30 Jun 2008 15:58:00 GMT</pubDate><guid>http://www.blogjava.net/jhyan/archive/2008/06/30/211790.html</guid><wfw:comment>http://www.blogjava.net/jhyan/comments/211790.html</wfw:comment><comments>http://www.blogjava.net/jhyan/archive/2008/06/30/211790.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/jhyan/comments/commentRss/211790.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jhyan/services/trackbacks/211790.html</trackback:ping><description><![CDATA[<p>同时在firefox里安装了一个mediaWrap的plugin</p>
<p>同时在about:config里增加了两个配置项：</p>
<p><span style="color: #ff0000;">Network.protocol-handler.app.mms&nbsp;&nbsp; string /usr/bin/mplayer</span>
</p>
<p><span style="color: #ff0000;">Network.protocal-handler.external.mms boolean True</span></p>
<p><br />
</p>
<p><span style="color: #ff0000;">这样就可以在1 听上面听歌曲了<br />
</span>
</p>
<img src ="http://www.blogjava.net/jhyan/aggbug/211790.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jhyan/" target="_blank">Joshua Yan</a> 2008-06-30 23:58 <a href="http://www.blogjava.net/jhyan/archive/2008/06/30/211790.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>