??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲精品国产第1页,亚洲AV无码成人精品区在线观看,亚洲国产精品一区二区九九http://www.tkk7.com/canonical/zh-cnSat, 10 May 2025 17:35:30 GMTSat, 10 May 2025 17:35:30 GMT60可逆计:下一代Y件构造理?/title><link>http://www.tkk7.com/canonical/archive/2019/04/29/433737.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Mon, 29 Apr 2019 02:18:00 GMT</pubDate><guid>http://www.tkk7.com/canonical/archive/2019/04/29/433737.html</guid><wfw:comment>http://www.tkk7.com/canonical/comments/433737.html</wfw:comment><comments>http://www.tkk7.com/canonical/archive/2019/04/29/433737.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/canonical/comments/commentRss/433737.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/canonical/services/trackbacks/433737.html</trackback:ping><description><![CDATA[<div> 原文链接Q?a >https://zhuanlan.zhihu.com/p/64004026</a></div><div>谨以此文庆祝清华建校108周年Q及5字班本科毕业20周年</div><div><div><p>作者: <a href="mailto:canonical_entropy@163.com">Canonical</a></p><p>众所周知Q计机U学得以存在的基x两个基本理论Q图灵于1936q提出的<a wrap="" target="_blank" rel="nofollow noreferrer" data-za-detail-view-id="1043">囄机理?/a>和丘奇同q早期发表的<a wrap="" target="_blank" rel="nofollow noreferrer" data-za-detail-view-id="1043">Lambda演算理论</a>。这两个理论奠定了所谓通用计算QUniversal ComputationQ的概念基础Q描l了h相同计算能力Q图灵完备)Q但形式上却南辕北辙、大相径庭的两条技术\Uѝ如果把q两U理论看作是上帝所展示的世界本源面貌的两个极端Q那么是否存在一条更加中庸灵zȝ到达通用计算彼岸的中间\? </p><p>?936q以来,软g作ؓ计算机科学的核心应用Q一直处在不间断的概念变革过E中Q各cȝ序语a/pȝ架构/设计模式/Ҏ论层ZIP但是I其软g构造的基本原理Q仍然没有脱Z个基本理论最初所讑֮的范围。如果定义一U新的Y件构造理论,它所引入的新概念本质上能有什么特异之处?能够解决什么棘手的问题Q?/p><p>本文中笔者提出在囄机和lambda演算的基上可以很自然的引入一个新的核心概?-<strong>可逆?/strong>Q从而Ş成一个新的Y件构造理?-<strong>可逆计(Reversible ComputationQ?/strong>。可逆计提供了区别于目前业内主方法的更高层次的抽象手D,可以大幅降低软g内在的复杂性,为粗_度软g复用扫除了理论障?/p><p>可逆计的思想来源不是计算机科学本w,而是理论物理学,它将软g看作是处于不断演化过E中的抽象实体, 在不同的复杂性层ơ上׃同的q算规则所描述Q它所x的是演化q程中生的微小差量如何在系l内有序的传播ƈ发生怺作用?/p><p>本文W一节将介绍可逆计理论的基本原理与核心公式,W二节分析可逆计理Zlg和模型驱动等传统软g构造理论的区别和联p,q介l可逆计理论在软g复用领域的应用,W三节从可逆计角度解构Docker、React{创新技术实c?/p><h2>一. 可逆计的基本原理</h2><p>可逆计可以看作是在真实的信息有限的世界中Q应用图灵计和lambda演算对世界徏模的一U必然结果,我们可以通过以下单的物理囑փ来理解这一炏V?/p><p>首先Q图灉|是一U结构固化的机器Q它h可枚丄有限的状态集合,只能执行有限的几条操作指令,但是可以从无限长的纸带上d和保存数据。例如我们日怋用的电脑Q它在出厂的时候硬件功能就已经定了,但是通过安装不同的YӞ传入不同的数据文Ӟ最l它可以自动产生L复杂的目标输出。图灉|的计过E在形式上可以写? </p><p><img src="https://www.zhihu.com/equation?tex=%E7%9B%AE%E6%A0%87%E8%BE%93%E5%87%BA+%3D+%E5%9B%BA%E5%AE%9A%E6%9C%BA%E5%99%A8%EF%BC%88%E6%97%A0%E9%99%90%E5%A4%8D%E6%9D%82%E7%9A%84%E8%BE%93%E5%85%A5%EF%BC%89%5C%5C" alt="目标输出 = 固定机器Q无限复杂的输入Q\\" /></p><p>与图灉|相反的是Qlambda演算的核心概忉|函数Q一个函数就是一台小型的计算机器Q函数的复合仍然是函敎ͼ也就是说可以通过机器和机器的递归l合来生更加复杂的机器。lambda演算的计能力与囄机等Pq意味着如果允许我们不断创徏更加复杂的机器,即输入一个常?Q我们也可以得到L复杂的目标输出。lambda演算的计过E在形式上可以写?/p><p><img src="https://www.zhihu.com/equation?tex=%E7%9B%AE%E6%A0%87%E8%BE%93%E5%87%BA+%3D+%E6%97%A0%E9%99%90%E5%A4%8D%E6%9D%82%E7%9A%84%E6%9C%BA%E5%99%A8%EF%BC%88%E5%9B%BA%E5%AE%9A%E8%BE%93%E5%85%A5%EF%BC%89%5C%5C" alt="目标输出 = 无限复杂的机器(固定输入Q\\" /> </p><p>可以看出Q以上两U计过E都可以被表达ؓY=F(X) q样一U抽象的形式。如果我们把Y=F(X)理解ZU徏模过E,x们试囄解输入的l构以及输入和输Z间的映射关系Q采用最l济的方式重出,则我们会发现囄机和lambda演算都假定了现实世界中无法满的条g。在真实的物理世界中Qhcȝ认知L有限的,所有的量都需要区分已知的部分和未知的部分Q因此我们需要进行如下分解: </p><p><img src="https://www.zhihu.com/equation?tex=%5Cbegin%7Balign%7D+Y+%26%3D+F%28X%29+%5C%5C+++%26%3D+%28F_0%2BF_1%29%28X_0%2BX_1%29++%5Ctag%7B%E6%8B%86%E5%88%86%E5%B7%B2%E7%9F%A5%E5%92%8C%E6%9C%AA%E7%9F%A5%7D+%5C%5C+++%26%3D+F_0%28X_0%29%2B+%E2%96%B3++++++%5Ctag%7B%E7%B1%BB%E4%BC%BCTaylor%E7%BA%A7%E6%95%B0%E5%B1%95%E5%BC%80%7D+%5Cend%7Balign%7D" alt="\begin{align} Y &= F(X) \\ &= (F_0+F_1)(X_0+X_1) \tag{拆分已知和未知} \\ &= F_0(X_0)+ △ \tag{cMTaylorU数展开} \end{align}" /> </p><p>重新整理一下符P我们得C一个适应范围更加q泛的计模?</p><p><img src="https://www.zhihu.com/equation?tex=Y%3DF%28X%29%5Coplus%E2%96%B3%5C%5C" alt="Y=F(X)\oplus△\\" /> </p><p>除了函数q算F(X)之外Q这里出C一个新的结构运符⊕Q它表示两个元素之间的合成运,q不是普通数值意义上的加法,同时引出了一个新的概念:差量△?#9651;的特异之处在于,它必然包含某U负元素QF(X)?#9651;合ƈ在一起之后的l果q不一定是“增加”了输出,而完全可能是“减少”?/p><p>在物理学中,差量△存在的必然性以?#9651;包含逆元q一事实完全是不a而喻的,因ؓ物理学的建模必须要考虑C个基本事实:</p><ol><li> 世界?#8220;不?#8221;的,噪声永远存在</li><li> 模型的复杂度要和问题内在的复杂度相匹配,它捕L是问题内怸E_不变的趋势及规律?/li></ol><p>例如Q对以下的数?​ ​ </p><figure data-size="normal"><img src="https://pic4.zhimg.com/80/v2-91f19a10faa36653267ffbd4eab86b7f_hd.jpg" data-caption="" data-size="normal" data-rawwidth="700" data-rawheight="300" data-original="https://pic4.zhimg.com/v2-91f19a10faa36653267ffbd4eab86b7f_r.jpg" data-actualsrc="https://pic4.zhimg.com/v2-91f19a10faa36653267ffbd4eab86b7f_b.jpg" alt="" width="700" /></figure><p> 我们所建立的模型只能是cM?a)中的单曲U,?b)中的模型试图_拟合每一个数据点在数学上UC拟合Q它难以描述新的数据Q而图(c)中限制差量只能ؓ正值则会极大的限制模型的描q精度?/p><p>以上是对Y=F(X)⊕△q一抽象计算模式的一个启发式说明Q下面我们将介绍在Y件构造领域落实这一计算模式的一U具体技术实现方案,W者将其命名ؓ<em><strong>可逆计?/strong></em>?所谓可逆计,是指pȝ化的应用如下公式指导软g构造的一U技术\U?</p><p><img src="https://www.zhihu.com/equation?tex=App+%3D+Biz+%5Cquad+aop%5C_extends+%5Cquad+Generator%5Clangle+DSL%5Crangle+%5C%5C" alt="App = Biz \quad aop\_extends \quad Generator\langle DSL\rangle \\" /> </p><blockquote>App : 所需要构建的目标应用E序 <br />DSL: <a wrap="" target="_blank" rel="nofollow noreferrer" data-za-detail-view-id="1043">领域特定语言QDomain Specific LanguageQ?/a>Q针对特定业务领域定制的业务逻辑描述语言Q也是所谓领域模型的文本表示形式 <br />Generator : Ҏ领域模型提供的信息,反复应用生成规则可以推导产生大量的衍生代码。实现方式包括独立的代码生成工具Q以及基?a wrap="" target="_blank" rel="nofollow noreferrer" data-za-detail-view-id="1043">元编E(MetaprogrammingQ?/a>的编译期模板展开 <br />Biz : Ҏ已知模型推导生成的逻辑与目标应用程序逻辑之间的差异被识别出来Qƈ攉在一P构成独立的差量描q?br />aop_extends: 差量描述与模型生成部分通过cM面向切面~程QAspect Oriented ProgrammingQ的技术结合在一Pq其中涉及到Ҏ型生成部分的增加、修攏V替换、删除等一pd操作 </blockquote><p>DSL是对关键性领域信息的一U高密度的表达,它直接指导Generator生成代码Q这一点类g囄计算通过输入数据驱动机器执行内置指o。而如果把Generator看作是文本符L替换生成Q则它的执行和复合规则完全就是lambda演算的翻版。差量合q在某种意义上是一U很新奇的操作,因ؓ它要求我们具有一U细致入微、无所不达的变化收集能力,能够把散布系l各处的同阶量分离出来q合q在一Pq样差量才具有独立存在的意义和h倹{同Ӟpȝ中必L徏立逆元和逆运的概念Q在q样的概念体pM差量作ؓ“存在”?#8220;不存?#8221;的؜合体才可能得到表达?/p><p>现有的Y件基架构如果不经q彻底的攚w,是无法有效的实施可逆计的。正如图灉|模型孕育了C语言QLambda演算促生了Lisp语言一PZ有效支持可逆计,W者提Z一U新的程序语a<em>X语言</em>Q它内置了差量定义、生成、合q、拆分等关键Ҏ,可以快速徏立领域模型,q在领域模型的基上实现可逆计?</p><p>Z实施可逆计,我们必须要徏立差量的概念。变化生差量,差量有正有负Q而且应该满下面三条要求Q?/p><ol><li>差量独立存在</li><li>差量怺作用</li><li>差量hl构</li></ol><p>在第三节中笔者将会以Docker为实例说明这三条要求的重要性?/p><p>可逆计的核心?#8220;可?#8221;Q这一概念与物理学中熵的概忉|息相养I它的重要性其实远q超ZE序构造本w,?a data-za-detail-view-id="1043">可逆计的Ҏ论来?/a>一文中Q笔者会对它有更详细的阐q?/p><p>正如复数的出现扩充了代数方程的求解空_可逆计ؓ现有的Y件构造技术体p补充了“可逆的差量合ƈ”q一关键性技术手D,从而极大扩充了软g复用的可行范_使得pȝU的_粒度Y件复用成为可能。同时在新的视角下,很多原先难以解决的模型抽象问题可以找到更加简单的解决ҎQ从而大q降低了软g构造的内在复杂性。在W二节中W者将会对此进行详l阐q?/p><p>软g开发虽然号U是知识密集性的工作Q但到目前ؓ止,众多一U程序员的日怸仍然包含着大量代码拯/_脓/修改的机械化手工操作内容Q而在可逆计理ZQ代码结构的修改被抽象ؓ可自动执行的差量合ƈ规则Q因此通过可逆计,我们可以Y件自w的自动化生产创造基条g。笔者在可逆计理论的基础上,提出了一个新的Y件工业化生模式<strong>NOP</strong>QNop is nOt ProgrammingQ,以非~程的方式批量生产Y件。NOP不是~程Q但也不是不~程Q它的是业务h员可以直观理解的逻辑与纯技术实现层面的逻辑相分,分别使用合适的语言和工具去设计Q然后再把它们无~的_接在一赗笔者将在另一文章中对NOPq行详细介绍?/p><p>可逆计与<a wrap="" target="_blank" rel="nofollow noreferrer" data-za-detail-view-id="1043">可逆计机</a>有着同样的物理学思想来源Q虽然具体的技术内涵ƈ不一_但它们目标却是统一的。正如云计算试图实现计算的云化一P可逆计和可逆计机试图实现的都是计的可逆化?/p><h2>? 可逆计对传统理论的承和发展</h2><h3>Q一Q?a wrap="" target="_blank" rel="nofollow noreferrer" data-za-detail-view-id="1043">lgQComponentQ?/a></h3><p>软g的诞生源于数学家研究希尔伯特W十问题时的副品,早期软g的主要用途也是数学物理计,那时软g中的概念无疑是抽象的、数学化的。随着软g的普及,来多应用软g的研发催生了面向对象和组件化的方法论Q它试图弱化抽象思维Q{而脓qhcȝ常识Q从Z的日常经验中汲取知识Q把业务领域中h们可以直观感知的概念映射Y件中的对象,仿照物质世界的生产制造过E从无到有、从到大,逐步拼接l装实现最lY件品的构造?/p><p>像框架、组件、设计模式、架构视囄软g开发领域中耳熟能详的概念,均直接来自于建筑业的生l验。组件理论承了面向对象思想的精华,借助可复用的预制构gq一概念Q创造了庞大的第三方lg市场Q获得了I前的技术和商业成功Q即使到今天仍然是最L的Y件开发指导思想。但是,lg理论内部存在着一个本质性的~陷Q阻了它把自己的成功l推q到一个新的高度?/p><p>我们知道Q所谓复用就是对已有的制成品的重复用。ؓ了实现组件复用,我们需要找C个Y件中的公共部分,把它分离出来q按照组件规范整理成标准形式。但是,A和B的公共部分的_度?strong>比A和B都要?/strong>的,大量软g的公共部分是比它们中M一个的_度都要<strong>得?/strong>的。这一限制直接D大_度的Y件功能模块越难以被直接复用,lg复用存在理论上的极限。可以通过lgl装复用60%-70%的工作量Q但是很有过80%Q更不用说实现复用度90%以上的系l整体复用了?/p><p>Z克服lg理论的局限,我们需要重新认识Y件的抽象本质。Y件是在抽象的逻辑世界中存在的一U?strong>信息</strong>产品Q信息ƈ不是物质。抽象世界的构造和生规律与物质世界是有着本质不同的。物质品的生L有成本的Q而复制Y件的辚w成本却可以是0。将桌子从房间中U走在物质世界中必须要经q门或窗Q但在抽象的信息I间中却只需要将桌子的坐标从x改ؓ-x而已。抽象元素之间的q算关系q不受众多物理约束的限制Q因此信息空间中最有效的生产方式不是组装,而是掌握和制定运规则?/p><p>如果从数学的角度重新去解读面向对象和lg技术,我们会发现可逆计可以被看作是组件理论的一个自然扩展?</p><ul><li> 面向对象 : 不等?A > B </li><li>lg : 加法 A = B + C </li><li>可逆计?: 差量 Y = X + △Y </li></ul><p>面向对象中的一个核心概忉|l承Q派生类从基cȝ承,自动h基类的一切功能。例如老虎是动物的一U派生类Q在数学上,我们可以说老虎(A)q个概念所包含的内Ҏ动物(B)q个概念更多Q老虎>动物Q即A>BQ。据此我们可以知道,动物q个概念所满的命题,老虎自然满Q? 例如动物会奔跑,老虎必然也会奔跑Q?P(B) -> P(A) Q。程序中所有用到动物这一概念的地斚w可以被替换ؓ老虎QLiscov代换原则Q。这样通过l承将自动推理关系引入到Y仉域中来,在数学上q对应于不等式,也就是一U偏序关pR?/p><p>面向对象的理论困境在于不{式的表达能力有限。对于不{式A > BQ我们知道A比B多,但是具体多什么,我们q没有办法明的表达出来。而对?A > BQ?D > Eq样的情况,即多出来的部分一模一P我们也无法实现这部分内容的重用。组件技术明指?l合优于l承"Q这相当于引入了加法 </p><p><img src="https://www.zhihu.com/equation?tex=A%3DB%2BC%5C%5C+D%3DE%2BC+" alt="A=B+C\\ D=E+C " /> </p><p>q样可以抽象出lgCq行重用?/p><p>沿着上述方向推演下去Q我们很Ҏ定下一步的发展是引?#8220;减法”Q这h可以?A = B + C看作是一个真正的方程Q通过方程左右U项求解?</p><p><img src="https://www.zhihu.com/equation?tex=B%3DA-C%3DA%2B%28-C%29%5C%5C" alt="B=A-C=A+(-C)\\" /> </p><p>通过减法引入?#8220;负组?#8221;是一个全新的概念Q它Y件复用打开了一扇新的大门?/p><p>假设我们已经构徏好了pȝ X = D + E + FQ?现在需要构?Y = D + E + G。如果遵循组件的解决ҎQ则需要将X拆解为多个组Ӟ然后更换lgF为G后重新组装。而如果遵循可逆计的技术\U,通过引入逆元 -FQ?我们立刻得到</p><p><img src="https://www.zhihu.com/equation?tex=Y+%3D+X-F%2BG%3DX%2B%28-F%2BG%29%3DX%2B%E2%96%B3Y%5C%5C" alt="Y = X-F+G=X+(-F+G)=X+△Y\\" /> </p><p>在不拆解X的情况下Q通过直接q加一个差?#9651;YQ即可将pȝX转化为系lY?/p><p>lg的复用条件是“相同方可复用”Q但在存在逆元的情况下Q具有最大颗_度的完整系lX在完全不改的情况下直接就可以被复用,软g复用的范围被拓展?#8220;相关卛_复用”QY件复用的_度不再有Q何限制。组件之间的关系也发生了深刻的变化,不再是单调的<em>构成关系</em>Q而成为更加丰富多变的<em>转化关系</em>?/p><p>Y = X + △Y q一物理囑փ对于复杂软g产品的研发具有非常现实的意义。X可以是我们所研发的Y件品的基础版本或者说ȝ本,在不同的客户处部|实施时Q大量的定制化需求被隔离到独立的差量△Y中,q些定制的差量描q单独存放,通过~译技术与ȝ本代码再合ƈC赗主版本的架构设计和代码实现只需要考虑业务领域内稳定的核心需求,不会受到特定客户处偶然性需求的冲击Q从而有效的避免架构腐化。主版本研发和多个项目的实施可以q行q行Q不同的实施版本对应不同?#9651;YQ互不媄响,同时ȝ本的代码与所有定制代码相互独立,能够随时q行整体升?/p><h3>Q二Q?a wrap="" target="_blank" rel="nofollow noreferrer" data-za-detail-view-id="1043">模型驱动架构QModel Driven Architecture)</a></h3><p>模型驱动架构QMDAQ是由对象管理组l(Object Management GroupQOMGQ在2001q提出的软g架构设计和开发方法,它被看作是Y件开发模式从以代码ؓ中心向以模型Z心{变的里程,目前大部分所谓Y件开发^台的理论基础都与MDA有关?/p><p>MDA试图提升软g开发的抽象层次Q直接用徏模语aQ例如Executable UMLQ作为编E语aQ然后通过使用cM~译器的技术将高层模型译为底层的可执行代码。在MDA中,明确区分应用架构和系l架构,q分别用<strong>q_无关模型PIM</strong>QPlatform Independent ModelQ和<strong>q_相关模型PSM</strong>QPlatform Specific ModelQ来描述它们。PIM反映了应用系l的功能模型Q它独立于具体的实现技术和q行框架Q而PSM则关注于使用特定技术(例如J2EE或者dotNetQ实现PIM所描述的功能,为PIM提供q行环境?/p><p>使用MDA的理惛_景是Q开发h员用可视化工具设计PIMQ然后选择目标q行q_Q由工具自动执行针对特定q_和实现语a的映规则,PIM转换为对应的PSMQƈ最l生成可执行的应用程序代码。基于MDA的程序构造可以表qCؓ如下公式 </p><p><img src="https://www.zhihu.com/equation?tex=App%3DTransformer%28PIM%29%5C%5C" alt="App=Transformer(PIM)\\" /> </p><p>MDA的愿景是像C语言取代汇编那样最l彻底消灭传l编E语a。但l历了这么多q发展之后,它仍未能够在q泛的应用领域中展现出相对于传统~程压倒性的竞争优势?/p><p>事实上,目前ZMDA的开发工具在面对多变的业务领域时QL难掩其内在的不适应性。根据本文第一节的分析Q我们知道徏模必要考虑差量。而在MDA的构造公式中Q左侧的App代表了各U未知需求,而右侧的Transformer和PIM的设计器实际上都主要由开发工具厂商提供,<strong>未知=已知</strong>q样一个方E是无法持久保持q的?/p><p>目前Q工具厂商的主要做法是提供大而全的模型集合,试图事先预测用户所有可能的业务场景。但是,我们知道“天下没有免费的午?#8221;Q模型的价值在于体C业务领域中的本质性约束,没有M一个模型是所有场景下都最优的。预需求会D出现一U悖? 模型内置假定q少Q则无法Ҏ用户输入的少量信息自动生成大量有用的工作Q也无法防止用户出现误操作,模型的hg明显Q而如果反之,模型假定很多Q则它就会固化到某个特定业务场景Q难以适应新的情况?/p><p>打开一个MDA工具的设计器Q我们最l常的感受是大部分选项都不需要,也不知道是干什么用的,需要的选项却到处找也找不到?/p><p>可逆计对MDA的扩展体Cؓ两点Q?</p><ol><li>可逆计中Generator和DSL都是鼓励用户扩充和调整的Q这一点类g<a wrap="" target="_blank" rel="nofollow noreferrer">面向语言~程QLanguage-oriented programmingQ?/a>?</li><li> 存在一个额外的差量定制ZQ可以对整体生成l果q行_的局部修正?/li></ol><p>在笔者提出的NOP生模式中,必须要包含一个新的关键组Ӟ<strong>设计器的设计?/strong>。普通的E序员可以利用设计器的设计器快速设计开发自q领域特定语言QDSLQ及其可视化设计器,同时可以通过设计器的设计器对pȝ中的L设计器进行定制调_自由的增加或者删除元素?/p><h3>Q三Q?a wrap="" target="_blank" rel="nofollow noreferrer" data-za-detail-view-id="1043">面向切面~程QAspect Oriented Programming)</a></h3><p>面向切面QAOPQ是与面向对象(OOPQ互补的一U编E范式,它可以实现对那些横跨多个对象的所?strong>横切x?/strong>Qcross-cutting concernQ的装。例如,需求规g可能规定所有的业务操作都要记录日志Q所有的数据库修Ҏ作都要开启事务。如果按照面向对象的传统实现方式Q需求中的一句话会D众多对象cM陡然膨胀出现大量的冗余代码,而通过AOPQ? q些公共?#8220;修饰?#8221;的操作就可以被剥d独立的切面描qC。这是所谓纵向分解和横向分解的正交性?/p><figure data-size="normal"><img src="http://www.tkk7.com/images/blogjava_net/canonical/aop.png" alt="" width="412" height="283" /><br /></figure><p>AOP本质上是两个能力的组合:</p><ol><li>在程序结构空间中<strong>定位</strong>到目标切点(PointcutQ?/li><li>对局部程序结构进行修改,扩展逻辑QAdvice)<strong>~织</strong>(Weave)到指定位|?/li></ol><p>定位依赖于存在良好定义的整体l构坐标p(没有坐标怎么定位Q)Q而修改依赖于存在良好定义的局部程序语义结构。目前主的AOP技术的局限性在于,它们都是在面向对象的语境下表辄Q而领域结构与对象实现l构q不L一致的Q或者说用对象体pȝ坐标去表N域语义是不充分的。例如,甌人和审批人在领域模型中是需要明区分的不同的概念,但是在对象层面却可能都对应于同样的Personc,使用AOP的很多时候ƈ不能直接领域描q{换ؓ切点定义和Advice实现。这U限制反映到应用层面Q结果就是除了日志、事务、gq加载、缓存等数与特定业务领域无关的“l典”应用之外Q我们找不到AOP的用武之地?/p><p>可逆计需要类似AOP的定位和l构修正能力Q但是它是在领域模型I间中定义这些能力的Q因而大大扩充了AOP的应用范围。特别是Q可逆计中领域模型自我演化产生的结构差?#9651;能够以类似AOP切面的Ş式得到表达?/p><p>我们知道Q组件可以标识出E序中反复出现的“<em>相同?/em>”Q而可逆计可以捕L序结构的“<em>怼?/em>”。相同很|见Q需要敏锐的甄别Q但是在Mpȝ中,有一U相似性都是唾手可得的Q即动力学演化过E中pȝ与自w历史快照之间的怼性。这U相似性在此前的技术体pMq没有专门的技术表辑Ş式?/p><p>通过U向和横向分解,我们所建立的概念之|存在于一个设计^面当中,当设计^面沿着旉轴演化时Q很自然的会产生一?#8220;三维”映射关系Q后一时刻的设计^面可以看作是从前一时刻的^面增加一个差量映(定制Q而得刎ͼ而差量是定义在^面的每一个点上的。这一囑փcM?a wrap="" target="_blank" rel="nofollow noreferrer">范畴论(Category TheoryQ?/a>中的函子QFunctorQ概念,可逆计中的差量合q扮演了函子映射的角艌Ӏ因此,可逆计相当于扩展了原有的设计I间Qؓ演化q一概念扑ֈ了具体的一U技术表现Ş式?/p><h3>Q四Q?a wrap="" target="_blank" rel="nofollow noreferrer" data-za-detail-view-id="1043">软g产品U(Software Product LineQ?/a></h3><p>软g产品U理论源于一个洞察,?strong>在一个业务领域中Q很有软gpȝ是完全独特的</strong>Q大量的软g产品之间存在着形式和功能的怼性,可以归结Z个品家族,把一个品家族中的所有品(已存在的和尚未存在的Q作Z个整体来研究、开发、演q,通过U学的方法提取它们的共性,l合有效的可变性管理,有可能实现规模化、系l化的Y件复用,q而实现Y件品的工业化生产?/p><p>软g产品U工E采用两阶段生命周期模型Q区?strong>领域工程</strong>?strong>应用工程</strong>。所?strong>领域工程</strong>Q是指分析业务领域内软g产品的共性,建立领域模型及公q软g产品U架构,形成可复用的核心资的过E,即面向复用的开发(development for reuseQ。?strong>应用工程</strong>Q其实质是用复用来开发( development with reuseQ,也就是利用已l存在的体系架构、需求、测试、文档等核心资来制造具体应用品的生zd?/p><p>卡耐基梅隆大学软g工程研究所QCMU-SEIQ的研究人员?a wrap="" target="_blank" rel="nofollow noreferrer" data-za-detail-view-id="1043">2008q的报告</a>中宣UY件品线可以带来如下好处Q?/p><ol><li> 提升10倍以上生产率</li><li> 提升10倍以上品质?/li><li> ~减60%以上成本</li><li> ~减87%以上人力需?/li><li> ~减98%以上产品上市旉</li><li> q入新市场的旉以月计,而不是年</li></ol><p>软g产品U描l的理想非常好Q复用度90%以上的品复用、随需而变的敏捷定制、无视技术变q媄响的领域架构、优异可观的l济效益{等。它所存在的唯一问题是<strong>如何才能做到</strong>Q尽Y件品线工程试图通过l合利用所有管理的和技术的手段Q在l织U别{略性的复用一切技术资产(包括文档、代码、规范、工L{)Q但在目前主的技术体制下Q发展成功的软g产品U仍焉临着重重困难?/p><p>可逆计的理念与Y件品线理论高度契合Q它的技术方案ؓ软g产品U的核心技术困?--可变性管理带来了新的解决思\。在软g产品U工E中Q传l的可变性管理主要是适配、替换和扩展q三U方式: </p><figure data-size="normal"><img src="http://www.tkk7.com/images/blogjava_net/canonical/product_line.png" alt="" width="470" height="224" /><br /></figure><p>q三U方式都可以看作是向核心架构补充功能。但是可复用性的障碍不仅仅是来自于无法追加新的功能,很多时候也在于无法屏蔽原先已经存在的功能。传l的适配技术等要求接口一致匹配,是一U刚性的Ҏ要求Q一旦失配必导致不断向上传导应力,最l只能通过整体更换lg来解决问题。可逆计通过差量合ƈ为可变性管理补充了“消除”q一关键性机Ӟ可以按需在领域模型空间中构徏出柔性适配接口Q从而有效的控制变化点媄响范围?/p><p>可逆计中的差量虽然也可以被解释ؓ对基模型的一U扩展,但是它与插g扩展技术之间还是存在着明显的区别。在q_-插gq样的结构中Q^台是最核心的主体,插g依附于^台而存在,更像是一U补丁机Ӟ在概念层面上是相Ҏ要的部分。而在可逆计中Q通过一些Ş式上的变换,我们可以得到一个对U性更高的公式Q? </p><p><img src="https://www.zhihu.com/equation?tex=+A+%3D+B+%5Coplus+G%28D%29+%5Cequiv+%28B%EF%BC%8CD%29+%5C%5C" alt=" A = B \oplus G(D) \equiv (BQD) \\" /> </p><p>如果把G看作是一U相对不变的背景知识Q则形式上我们可以把它隐藏v来,定义一个更加高U的“括号”q算W,它类g数学中的“内积”。在q种形式下,B和D是对偶的QB是对D的补充,而D也是对B的补充。同Ӟ我们注意到G(D)是模型驱动架构的体现Q模型驱动之所以有价值就在于模型D中发生的微小变化Q可以被G攑֤为系l各处大量衍生的变化Q因此G(D)是一U非U性变换,而B是系l中去除D所对应的非U性因素之后剩余的部分。当所有复杂的非线性媄响因素都被剥dM后,最后剩下的部分B有可能是简单的Q甚臌够Ş成一U新的可独立理解的领域模型结?可以cL声L与空气的关系Q声波是I气的扰动,但是不用研究I气本体Q我们就可以直接用正弦L模型来描q声??/p><p>A = (B,D)的Ş式可以直接推q到存在更多领域模型的情?</p><p><img src="https://www.zhihu.com/equation?tex=+A+%3D+%28B%2CD%2CE%2CF%2C+...%29+%5C%5C" alt=" A = (B,D,E,F, ...) \\" /> </p><p>因ؓB、D、E{概念都是某UDSL所描述的领域模型,因此它们可以被解释ؓA投媄到特定领域模型子I间所产生的分量,也就是说Q应用A可以被表CZؓ一?#8220;特征向量”QFeature VectorQ, 例如 </p><p><img src="https://www.zhihu.com/equation?tex=%E5%BA%94%E7%94%A8A+%3D+%28Biz%2C%E6%9D%83%E9%99%90%2C%E6%B5%81%E7%A8%8B%2C%E6%8A%A5%E8%A1%A8%2C...%29+%5C%5C" alt="应用A = (Biz,权限,程,报表,...) \\" /> </p><p>与Y件品线中常用的<a wrap="" target="_blank" rel="nofollow noreferrer" data-za-detail-view-id="1043">面向特征~程QFeature Oriented ProgrammingQ?/a>相比Q可逆计的特征分解Ҏ领域特定描述Q特征边界更加明,特征合成时生的概念冲突更容易处理?/p><p>特征向量本n构成更高l度的领域模型,它可以被q一步分解下去,从而Ş成一个模型列,例如定义</p><p><img src="https://www.zhihu.com/equation?tex=D%27+%5Cequiv+%5BB%EF%BC%8CD%5D%5C+G%27%28D%27%29%5Cequiv+B%5Coplus+G%28D%29%5C%5C" alt="D' \equiv [BQD]\ G'(D')\equiv B\oplus G(D)\\" /> </p><p>, q且假设D'可以l箋分解</p><p><img src="https://www.zhihu.com/equation?tex=D%27%3DV%5Coplus+M%28U%29%3DM%27%28U%27%29+%5C%5C" alt="D'=V\oplus M(U)=M'(U') \\" /> </p><p>Q则可以得到 </p><p><img src="https://www.zhihu.com/equation?tex=%5Cbegin%7Balign%7D+A+%26%3D+B+%E2%8A%95+G%28D%29+%5C%5C+++%26%3D+G%27%28D%27%29+%5C%5C++%26%3D+G%27%28M%27%28U%27%29%29%5C%5C++%26%3D+G%27%28M%27%28%5BV%2CU%5D%29%29+%5C%5C++%5Cend%7Balign%7D+%5C%5C" alt="\begin{align} A &= B ⊕ G(D) \\ &= G'(D') \\ &= G'(M'(U'))\\ &= G'(M'([V,U])) \\ \end{align} \\" /> </p><p> 最l我们可以通过领域特征向量U'来描qD’Q然后再通过领域特征向量D‘来描q原有的模型A?/p><p>可逆计的q一构造策略类g深度经|络Q它不再局限于h极多可调参数的单一模型Q而是建立抽象层不同、复杂性层U不同的一pd模型Q通过逐步求精的方式构造出最l的应用?/p><p>在可逆计的视角下,应用工程的工作内容变成了使用特征向量来描qY仉求,而领域工E则负责Ҏ特征向量描述来生成最l的软g?/p><h2>? 初露端倪的差量革命</h2><h3>Q一QDocker</h3><p>Docker?013q由创业公司dotCloud开源的应用容器引擎Q它可以Q何应用及其依赖的环境打包成一个轻量、可UL、自包含的容器(ContainerQ,q据此以容器为标准化单元创造了一U新型的软g开发、部|和交付形式?/p><p>Docker一Zq杀了Google的亲儿子lmctfy QLet Me Contain That For YouQ容器技术,同时也把Google的另一个亲儿子Go语言q速捧成了|红Q之后Docker的发? 更是一发而不可收拾?014q开始一场Docker风暴席卷全球Q以前所未有的力度推动了操作pȝ内核的变革,在众多巨头的跟风造势下瞬间引爆容器云市场Q真正从Ҏ上改变了企业应用从开发、构建到部v、运行整个生命周期的技术Ş态?/p><figure data-size="normal"><img src="https://pic2.zhimg.com/80/v2-d6ef1c89995987f99c69e2c9f2456985_hd.jpg" data-caption="" data-size="normal" data-rawwidth="1080" data-rawheight="608" data-original="https://pic2.zhimg.com/v2-d6ef1c89995987f99c69e2c9f2456985_r.jpg" data-actualsrc="https://pic2.zhimg.com/v2-d6ef1c89995987f99c69e2c9f2456985_b.jpg" alt="" width="674" height="379" /></figure><p>Docker技术的成功源于它对软gq行时复杂性的本质性降低,而它的技术方案可以看作是可逆计理论的一U特例。Docker的核心技术模式可以用如下公式q行概括</p><p><img src="https://www.zhihu.com/equation?tex=App+%3D+Docker%5Clangle+Dockerfile%5Crangle+%5Cquad+unionfs+%5Cquad+BaseImage%5C%5C" alt="App = Docker\langle Dockerfile\rangle \quad unionfs \quad BaseImage\\" /> </p><p><strong>Dockerfile</strong>是构建容器镜像的一U领域特定语aQ例?/p><div><pre><code>FROM ubuntu:16.04 <br />RUN useradd --user-group --create-home --shell /bin/bash work <br />RUN apt-get update -y && apt-get install -y python3-dev <br />COPY . /app RUN make /app <br />ENV PYTHONPATH /FrameworkBenchmarks <br />CMD python /app/app.py <br />EXPOSE 8088</code></pre></div><p>通过Dockerfile可以快速准的描述容器所依赖的基镜像Q具体的构徏步骤Q运行时环境变量和系l配|等信息?/p><p><strong>Docker</strong>应用E序扮演了可逆计中Generator的角Ԍ负责解释DockerfileQ执行对应的指o来生成容器镜像?/p><p>创造性的使用<a wrap="" target="_blank" rel="nofollow noreferrer" data-za-detail-view-id="1043">联合文gpȝ</a>QUnion FSQ,是Docker的一个特别的创新之处。这U文件系l采用分层的构造方式,每一层构建完毕后׃会再发生改变Q在后一层上q行的Q何修攚w只会记录在自p一层。例如,修改前一层的文g时会通过Copy-On-Write的方式复制一份到当前层,而删除前一层的文gq不会真的执行删除操作,而是仅在当前层标记该文g已删除。Docker利用联合文gpȝ来实现将多个容器镜像合成Z个完整的应用Q这一技术的本质正是可逆计中的aop_extends操作?/p><p>Docker的英文是码头搬运工h的意思,它所搬运的容器也l常被h拿来和集装箱做对比:标准的容器和集装q|使得我们可以自由的对它们q行传输/l合Q而不用考虑容器中的具体内容。但是这U比较是肤浅的,甚至是误导性的。集装箱是静态的、简单的、没有对外接口的Q而容器则是动态的、复杂的、和外部存在着大量信息交互的。这U动态的复杂l构惛_普通的静态物件一样封装成所谓标准容器,光度不可同日而语。如果没有引入支持差量的文gpȝQ是无法构徏ZU柔性边界,实现逻辑分离的?/p><p>Docker所做的标准装其实虚拟Z能做刎ͼ甚至差量存储机制在虚拟机中也早早的被用于实现增量备䆾QDocker与虚拟机的本质性不同到底在什么地方?回顾W一节中可逆计对差量三个基本要求Q我们可以清晰的发现Docker的独特之处?/p><ol><li>差量独立存在QDocker最重要的h值就在于通过容器装Q抛弃了作ؓ背景存在Q必不可,但一般情况下不需要了解)Q占据了99%的体U和复杂度的操作pȝ层。应用容器成Z可以独立存储、独立操作的W一性的实体。轻装上늚容器在性能、资源占用、可理性等斚w完全越了虚胖的虚拟机?/li><li>差量怺作用QDocker容器之间通过_受控的方式发生相互作用,可通过操作pȝ的namespace机制选择性的实现资源隔离或者共享。而虚拟机的差量切片之间是没有M隔离机制的?/li><li>差量hl构Q虚拟机虽然支持增量备䆾Q但是h们却没有合适的手段M动构造一个指定的差量切片出来。归根结底,是因拟机的差量定义在二进制字节空间中Q而这个空间非常瘠,几乎没有什么用户可以控制的构造模式。而Docker的差量是定义在差量文件系l空间中Q这个空间承了LinuxC֌最丰富的历史资源。每一条shell指o的执行结果最l反映到文gpȝ中都是增?删除/修改了某些文Ӟ所以每一条shell指o都可以被看作是某个差量的定义。差量构成了一个异怸富的l构I间Q差量既是这个空间中的变换算W(shell指oQ,又是变换符的运结果。差量与差量盔R产生新的差量Q这U生生不息才是Docker的生命力所在?/li></ol><h3>Q二QReact</h3><p>2013q_也就是Docker发布的同一q_Facebook公司开源了一个革命性的Web前端框架React。React的技术思想非常独特Q它以函数式~程思想为基Q结合一个看似异惛_开的虚拟DOMQVirtual DOM)概念Q引入了一整套新的设计模式Q开启了前端开发的新大航v时代?/p><div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #000000; ">class HelloMessage extends React.Component {<br />  constructor(props) {<br />    super(props);<br />    </span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">.state </span><span style="color: #000000; ">=</span><span style="color: #000000; "> { count: </span><span style="color: #000000; ">0</span><span style="color: #000000; "> };<br />    </span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">.action </span><span style="color: #000000; ">=</span> <span style="color: #0000FF; ">this</span><span style="color: #000000; ">.action.bind(</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">);<br />  }<br />  <br />  action(){<br />    </span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">.setState(state </span><span style="color: #000000; ">=></span><span style="color: #000000; "> ({<br />      count: state.count </span><span style="color: #000000; ">+</span> <span style="color: #000000; ">1</span><span style="color: #000000; "><br />    }));<br />  },<br />  <br />  render() {<br />    </span><span style="color: #0000FF; ">return</span><span style="color: #000000; "> (<br />      </span><span style="color: #000000; "><</span><span style="color: #000000; ">button onClick</span><span style="color: #000000; ">=</span><span style="color: #000000; ">{</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">.action}</span><span style="color: #000000; ">></span><span style="color: #000000; "><br />        Hello {</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">.props.name}:{</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">.state.count}<br />      </span><span style="color: #000000; "></</span><span style="color: #000000; ">button</span><span style="color: #000000; ">></span><span style="color: #000000; "><br />    );<br />  }<br />}<br /><br />ReactDOM.render(<br />  </span><span style="color: #000000; "><</span><span style="color: #000000; ">HelloMessage name</span><span style="color: #000000; ">=</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Taylor</span><span style="color: #000000; ">"</span> <span style="color: #000000; ">/></span><span style="color: #000000; ">,<br />  mountNode<br />);</span></div><pre><code></code></pre></div><p>Reactlg的核心是render函数Q它的设计参考了后端常见的模板渲染技术,主要区别在于后端模板输出的是HTML文本Q而Reactlg的Render函数使用cMXML模板的JSX语法Q通过~译转换在运行时输出的是虚拟DOM节点对象。例如上面HelloMessagelg的render函数被翻译后的结果类g</p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #000000; ">render(){<br />   </span><span style="color: #0000FF; ">return</span> <span style="color: #0000FF; ">new</span><span style="color: #000000; "> VNode(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">button</span><span style="color: #000000; ">"</span><span style="color: #000000; ">, {onClick: </span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">.action, <br />          content: </span><span style="color: #000000; ">"</span><span style="color: #000000; ">Hello </span><span style="color: #000000; ">"</span><span style="color: #000000; ">+</span> <span style="color: #0000FF; ">this</span><span style="color: #000000; ">.props.name </span><span style="color: #000000; ">+</span> <span style="color: #000000; ">"</span><span style="color: #000000; ">:</span><span style="color: #000000; ">"</span> <span style="color: #000000; ">+</span> <span style="color: #0000FF; ">this</span><span style="color: #000000; ">.state.count });<br />}</span></div>可以用以下公式来描述ReactlgQ?nbsp; VDom = render(state)</div><div>当状态发生变化以后,只要重新执行render函数׃生成新的虚拟DOM节点Q虚拟DOM节点可以被翻译成真实的HTML DOM对象Q从而实现界面更新。这U根据状态重新生成完整视囄渲染{略极大化了前端界面开发。例如对于一个列表界面,传统~程需要编写新增行/更新?删除行等多个不同的DOM操作函数Q而在React中只要更改state后重新执行唯一的render函数卛_?p>每次重新生成DOM视图的唯一问题是性能很低Q特别是当前端交互操作众多、状态变化频J的时候。React的神来之W是提出了基于虚拟DOM的diff法Q可以自动的计算两个虚拟DOM树之间的差量Q状态变化时只要执行虚拟Dom差量对应的DOM修改操作卛_Q更新真实DOM时会触发样式计算和布局计算Q导致性能很低Q而在JavaScript中操作虚拟DOM 的速度是非常快的)。整体策略可以表CZؓ如下公式 </p><p><img src="https://www.zhihu.com/equation?tex=state_1%3Dstate_0%5Coplus+action%5C%5C+%5CDelta+VDom%3Drender%28state_1%29-render%28state_0%29%5C%5C+%5CDelta+Dom+%3DTranslater%28%5CDelta+VDom%29+%5C%5C" alt="state_1=state_0\oplus action\\ \Delta VDom=render(state_1)-render(state_0)\\ \Delta Dom =Translater(\Delta VDom) \\" /> </p><p> 昄Q这一{略也是可逆计的一U特例?/p><p>只要E微留意一下就会发玎ͼ最q几qmerge/diff/residual/delta{表辑ַ量运的概念来多的出现在软g设计领域中。比如大数据领域的流计算引擎中,与表之间的关系可以表示?</p><p><img src="https://www.zhihu.com/equation?tex=Table%3D%5Cint+%5CDelta+Stream+%5C%5C" alt="Table=\int \Delta Stream \\" /> </p><p>对表的增删改查操作可以被~码Z件流Q而将表示数据变化的事件篏U到一起就形成了数据表?/p><p>CU学发端于微U分的发明,而微分的本质是自动计算无穷差量,而积分则是微分的逆运,自动ҎI小量进行汇dq?9世纪70q代Q经学l历了一际革命,微U分的思想引入l济分析Q在辚wq一概念之上重徏了整个经学大厦。Y件构造理论发展到今天Q已l进入一个瓶颈,也到了应该重新认识差量的时候?/p><h2>? l语</h2><p>W者的专业背景是理论物理学Q可逆计源于笔者将物理学和数学的思想引入软g领域的一U尝试,它最早由W者在2007q左x出。一直以来,软g领域对于自然规律的应用一般情况下都只限于"模拟"范畴Q例如流体动力学模拟软gQ虽然它内置了hcL认知的最深刻的一些世界规律,但这些规律ƈ没有被用于指导和定义软g世界自n的构造和演化Q它们的指向范围是Y件世界之外,而不是Y件世界自w。在W者看来,在Y件世界中Q我们完全可以站?#8220;上帝的视?#8221;Q规划和定义一pd的结构构造规律,辅助我们完成软g世界的构建。而ؓ了完成这一点,我们首先需要徏立程序世界中?#8220;微积?#8221;?/p><p>cM于微U分Q可逆计理论的核心是将“差量”提升为第一性的概念Q将全量看作是差量的一U特例(全量=单位?全量Q。传l的E序世界中我们所表达的都只是“?#8221;Q而且?#8220;所?#8221;Q差量只能通过全量之间的运间接得刎ͼ它的表述和操U都需要特D处理,而基于可逆计理论,我们首先应该定义所有差量概늚表达形式Q然后再围绕q些概念d立整个领域概念体pRؓ了保证差量所在数学空间的完备性(差量之间的运结果仍焉要是合法的差量)Q差量所表达的不能仅仅是“?#8221;Q而必L“?#8221;?#8220;没有”的一U؜合体。也是说差量必L“可逆的”。可逆性具有非常深ȝ物理学内涵,在基本的概念体系中内|这一概念可以解决很多非常手的Y件构造问题?/p><p>Z处理分布式问题,C软g开发体pdl接受了不可变数据的概念Q而ؓ了解军__度软g复用问题Q我们还需要接受不可变逻辑的概念(复用可以看作是保持原有逻辑不变Q然后增加差量描qͼ。目前,业内已经逐步出现了一些富有创造性的d应用差量概念的实践,它们都可以在可逆计的理论框架下得到统一的诠释。笔者提Z一U新的程序语aX语言Q它可以极大化可逆计的技术实现。目前笔者已l基于X语言设计q实C一pd软g框架和生产工Pq基于它们提Z一U新的Y件生产范式(NOPQ?/p></div></div><img src ="http://www.tkk7.com/canonical/aggbug/433737.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/canonical/" target="_blank">canonical</a> 2019-04-29 10:18 <a href="http://www.tkk7.com/canonical/archive/2019/04/29/433737.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jQuery中的~程范式http://www.tkk7.com/canonical/archive/2011/12/25/367146.htmlcanonicalcanonicalSun, 25 Dec 2011 13:23:00 GMThttp://www.tkk7.com/canonical/archive/2011/12/25/367146.htmlhttp://www.tkk7.com/canonical/comments/367146.htmlhttp://www.tkk7.com/canonical/archive/2011/12/25/367146.html#Feedback5http://www.tkk7.com/canonical/comments/commentRss/367146.htmlhttp://www.tkk7.com/canonical/services/trackbacks/367146.html  览器前端编E的面貌?005q以来已l发生了深刻的变化,qƈ不简单的意味着出现了大量功能丰富的基础库,使得我们可以更加方便的编写业务代码,更重要的是我们看待前端技术的观念发生了重大{变,明确意识C如何以前端特有的方式释放E序员的生力。本文将l合jQuery源码的实现原理,对javascript中涌现出的编E范式和常用技巧作一单介l?br /> 
1. AJAX: 状态驻留,异步更新
  首先来看一点历双Ӏ?br />A. 1995qNetscape公司的Brendan Eich开发了javacript语言Q这是一U动?dynamic)、弱cd(weakly typed)、基于原?prototype-based)的脚本语a?br />B. 1999q微软IE5发布Q其中包含了XMLHTTP ActiveX控g?br />C. 2001q微软IE6发布Q部分支持DOM level 1和CSS 2标准?br />D. 2002qDouglas Crockford发明JSON格式?br />xQ可以说Web2.0所依赖的技术元素已l基本成形,但是q没有立d整个业界产生重大的媄响。尽一?#8220;面异步局部刷?#8221;的技巧在E序员中间秘密的传Q甚臛_生了bindowsq样庞大臃肿的类库,但ȝ来说Q前端被看作是瘠而又肮脏的沼泽地Q只有后台技术才是王道。到底还~少些什么呢Q?br />  当我们站在今天的角度d?005q之前的js代码Q包括那些当时的牛h所写的代码Q可以明昄感受到它们在E序控制力上的孱弱。ƈ不是?005q之前的js技术本w存在问题,只是它们在概念层面上是一盘散沙,~Zl一的观念,或者说~少自己独特的风? 自己的灵。当时大多数的hQ大多数的技术都试图在模拟传l的面向对象语言Q利用传l的面向对象技术,dCl的GUI模型的仿制品?br />  2005q是变革的一q_也是创造概늚一q。伴随着Google一pd让h耳目一新的交互式应用的发布,Jesse James Garrett的一文章《Ajax: A New Approach to Web Applications》被qؓ传播。Ajaxq一前端Ҏ的概念迅速将众多分散的实늻一在同一口号之下Q引发了Web~程范式的{换。所谓名不正则言不顺Q这下无名群众可扑ֈl织了。在未有Ajax之前Qh们早已认识到了B/S架构的本质特征在于浏览器和服务器的状态空间是分离的,但是一般的解决Ҏ都是隐藏q一区分Q将前台状态同步到后台Q由后台l一q行逻辑处理Q例如ASP.NET。因为缺乏成熟的设计模式支持前台状态驻留,在换늚时候,已经装蝲的js对象被q被丢弃Q这栯q能指望它去完成什么复杂的工作吗?
  Ajax明确提出界面是局部刷新的Q前台驻留了状态,q就促成了一U需要:需要js对象在前台存在更长的旉。这也就意味着需要将q些对象和功能有效的理hQ意味着更复杂的代码l织技术,意味着Ҏ块化Q对公共代码基的渴求?br />  jQuery现有的代码中真正与Ajax相关Q用XMLHTTP控g异步讉K后台q回数据Q的部分其实很少Q但是如果没有Ajax, jQuery作ؓ公共代码Zq乏存在的理由?br />
2. 模块化:理名字I间
  当大量的代码产生出来以后Q我们所需要的最基础的概念就是模块化Q也是对工作进行分解和复用。工作得以分解的关键在于各h独立工作的成果可以集成在一赗这意味着各个模块必须Z一致的底层概念Q可以实C互,也就是说应该Z一套公׃码基Q屏蔽底层浏览器的不一致性,q实现统一的抽象层Q例如统一的事件管理机制等。比l一代码基更重要的是Q各个模块之间必L有名字冲H。否则,即两个模块之间没有M交互Q也无法共同工作?br />  jQuery目前鼓吹的主要卖点之一是对名字空间的良好控制。这甚至比提供更多更完善的功能点都重要的多。良好的模块化允许我们复用Q何来源的代码Q所有h的工作得以积累叠加。而功能实C仅是一时的工作量的问题。jQuery使用module pattern的一个变U来减少对全局名字I间的媄?仅仅在window对象上增加了一个jQuery对象(也就?函数)?br />   所谓的module pattern代码如下Q它的关键是利用匿名函数限制临时变量的作用域?br />  var feature =(function() {

// U有变量和函?br />var privateThing = 'secret',
    publicThing = 'not secret',

    changePrivateThing = function() {
        privateThing = 'super secret';
    },

    sayPrivateThing = function() {
        console.log(privateThing);
        changePrivateThing();
    };

// q回对外公开的API
return {
    publicThing : publicThing,
    sayPrivateThing :  sayPrivateThing
}
})();
  js本n~Z包结构,不过l过多年的尝试之后业内已l逐渐l一了对包加载的认识QŞ成了RequireJs库这样得C定共识的解决Ҏ。jQuery可以与RequireJS库良好的集成在一? 实现更完善的模块依赖理。http://requirejs.org/docs/jquery.html
 
  require(["jquery", "jquery.my"], function() {
    //当jquery.js和jquery.my.js都成功装载之后执?br />    $(function(){
      $('#my').myFunc();
    });
  });
 
  通过以下函数调用来定义模块my/shirt, 它依赖于my/cart和my/inventory模块Q?br />  require.def("my/shirt",
    ["my/cart", "my/inventory"],
    function(cart, inventory) {
        // q里使用module pattern来返回my/shirt模块对外暴露的API
        return {
            color: "blue",
            size: "large"
            addToCart: function() {
                // decrement是my/inventory对外暴露的API
                inventory.decrement(this);
                cart.add(this);
            }
        }
    }
  );

3. 奇?Q对象提?br />  当你W一眼看?函数的时候,你想C什么?传统的编E理论L告诉我们函数命名应该准确Q应该清晰无误的表达作者的意图Q甚臛_U长名字要优于短名字Q因为减了出现歧义的可能性。但是,$是什么?qQ它所传递的信息实在是太隐晦Q太暧昧了?是由prototype.js库发明的Q它真的是一个神奇的函数Q因为它可以一个原始的DOM节点提升(enhance)Z个具有复杂行为的对象。在prototype.js最初的实现中,$函数的定义ؓ
  var $ = function (id) {
    return "string" == typeof id ? document.getElementById(id) : id;
  };
  q基本对应于如下公式
      e = $(id)
  q绝不仅仅是提供了一个聪明的函数名称~写Q更重要的是在概念层面上建立了文本id与DOM element之间的一一对应。在未有$之前Qid与对应的element之间的距d分遥q,一般要element~存到变量中Q例?br />  var ea = docuement.getElementById('a');
  var eb = docuement.getElementById('b');
  ea.style....
但是使用$之后Q却随处可见如下的写?br />  $('header_'+id).style...
  $('body_'+id)....
id与element之间的距M乎被消除了,可以非常紧密的交l在一赗?br />  prototype.js后来扩展?的含义,
  function $() {
    var elements = new Array();
    
    for (var i = 0; i < arguments.length; i++) {
        var element = arguments[i];
        if (typeof element == 'string')
          element = document.getElementById(element);
    
        if (arguments.length == 1)
          return element;
    
        elements.push(element);
    }
    
    return elements;
  }
  q对应于公式
    [e,e] = $(id,id)
  很遗憾,q一步prototype.js走偏了,q一做法很少有实用的价倹{?br />  真正?发扬光大的是jQuery, 它的$对应于公?br />    [o] = $(selector)
  q里有三个增?br />  A. selector不再是单一的节点定位符Q而是复杂的集合选择W?br />  B. q回的元素不是原始的DOM节点Q而是l过jQueryq一步增强的h丰富行ؓ的对象,可以启动复杂的函数调用链?br />  C. $q回的包装对象被造型为数lŞ式,集合操作自然的整合到调用链中?br />
  当然,以上仅仅是对奇?的一个过分简化的描述,它的实际功能要复杂得? 特别是有一个非常常用的直接构造功?
   $("<table><tbody><tr><td>...</td></tr></tbody></table>")....
  jQuery根据传入的html文本直接构造出一pd的DOM节点,q将其包装ؓjQuery对象. q在某种E度上可以看作是对selector的扩? html内容描述本n是一U唯一指定.
  $(function{})q一功能实在是让h有些无语? 它表C当document.ready的时候调用此回调函数。真的,$是一个神奇的函数, 有Q何问题,?一下?br />  ȝh, $是从普通的DOM和文本描qC界到h丰富对象行ؓ的jQuery世界的跃q通道。跨q了q道门,来C理想国?br />   
4. 无定形的参数Q专注表达而不是约?br />  q型语a既然头上着??? 总难免让人有些先天不的感觉. 在程序中~ZcdU束, 是否真的是一U重大的~憾? 在传l的强类型语a? 函数参数的类?个数{都是由~译器负责检查的U束条g, 但这些约束仍然是q远不够? 一般应用程序中Z加强U束, M增加大量防M性代? 例如在C++中我们常用ASSERT, 而在java中也l常需要判断参数值的范围
    if (index < 0 || index >= size)
        throw new IndexOutOfBoundsException(
            "Index: "+index+", Size: "+size);            
  很显? q些代码导致程序中存在大量无功能的执行路径, x们做了大量判? 代码执行到某个点, pȝ抛出异常, 大喊此\不? 如果我们换一个思\, 既然已经做了某种判断,能否利用q些判断的结果来做些什么呢? javascript是一U弱cd的语a,它是无法自动U束参数cd? 那如果顺势而行,q一步弱化参数的形? ??推进CU极? 在弱无可q时? weak会不会成为标志性的特点?
  看一下jQuery中的事gl定函数bind,
   A. 一ơ绑定一个事?$("#my").bind("mouseover", function(){});
   B. 一ơ绑定多个事?$("#my").bind("mouseover mouseout",function(){})
   C. 换一个Ş? 同样l定多个事g
      $("#my").bind({mouseover:function(){}, mouseout:function(){});
   D. 想给事g监听器传点参?br />      $('#my').bind('click', {foo: "xxxx"}, function(event) { event.data.foo..})
   E. 想给事g监听器分个组
      $("#my").bind("click.myGroup″, function(){});
   F. q个函数Z么还没有疯掉???
   
   q是类型不定, 在固定位|上的参数的意义总要是确定的? 退一万步来说, q是参C|不重要?函数本n的意义应该是定的吧? 但这是什?
      取?value = o.val(), 讄?o.val(3)
      
   一个函数怎么可以q样q分, 怎么能根据传入参数的cd和个C同而行Z同呢? 看不眼是不? 可这是Z的hD. 既然不能防止, 那就故意允许. 虽然形式多变, 却无一句废? ~少U束, 不妨表?我不是出来吓人的).
   
5. 铑ּ操作: U性化的逐步l化
  jQuery早期最主要的卖点就是所谓的铑ּ操作(chain).
 
  $('#content') // 扑ֈcontent元素
    .find('h3') // 选择所有后代h3节点
    .eq(2)      // qo集合, 保留W三个元?br />        .html('改变W三个h3的文?)
    .end()      // q回上一U的h3集合
    .eq(0)
        .html('改变W一个h3的文?);

在一般的命o式语a? 我们总需要在重重嵌套循环中过滤数? 实际操作数据的代码与定位数据的代码纠~在一? 而jQuery采用先构造集合然后再应用函数于集合的方式实现两种逻辑的解? 实现嵌套l构的线性化. 实际? 我们q不需要借助q程化的思想可以很直观的理解一个集? 例如 $('div.my input:checked')可以看作是一U直接的描述,而不是对q程行ؓ的跟t?
   循环意味着我们的思维处于一U反复回l的状? 而线性化之后则沿着一个方向直U前q? 极大减轻了思维负担, 提高了代码的可组合? Z减少调用铄中断, jQuery发明了一个绝妙的L: jQuery包装对象本ncM数组Q集合). 集合可以映射到新的集合, 集合可以限制到自q子集合,调用的发赯是集合Q返回结果也是集合,集合可以发生l构上的某种变化但它q是集合, 集合是某U概念上的不动点Q这是从函数式语a中吸取的设计思想。集合操作是太常见的操作, 在java中我们很Ҏ发现大量所谓的装函数其实是在封装一些集合遍历操? 而在jQuery中集合操作因为太直白而不需要封?
   铑ּ调用意味着我们始终拥有一?#8220;当前”对象Q所有的操作都是针对q一当前对象q行。这对应于如下公?br />     x += dx
调用铄每一步都是对当前对象的增量描qͼ是针Ҏl目标的逐步l化q程。Witrixq_中对q一思想也有着q泛的应用。特别是Z实现q_机制与业务代码的融合Q^C提供对象Q容器)的缺省内容,而业务代码可以在此基上进行逐步l化的修正,包括取消~省的设|等?br />  话说回来, 虽然表面上jQuery的链式调用很? 内部实现的时候却必须自己多写一层@? 因ؓ~译器ƈ不知?自动应用于集合中每个元素"q回?
  $.fn['someFunc'] = function(){
    return this.each(function(){
      jQuery.someFunc(this,...);
    }
  }
 
6. data: l一数据理
  作ؓ一个js库,它必解决的一个大问题是js对象与DOM节点之间的状态关联与协同理问题。有些js库选择以js对象ZQ在js对象的成员变量中保存DOM节点指针Q访问时L以js对象为入口点Q通过js函数间接操作DOM对象。在q种装下,DOM节点其实只是作ؓ界面展现的一U底?#8220;汇编”而已。jQuery的选择与Witrixq_cMQ都是以HTML自nl构为基Q通过js增强(enhance)DOM节点的功能,它提升Z个具有复杂行为的扩展对象。这里的思想是非侵入式设?non-intrusive)和优雅退化机?graceful degradation)。语义结构在基础的HTML层面是完整的Qjs的作用是增强了交互行为,控制了展现Ş式?br />  如果每次我们都通过$('#my')的方式来讉K相应的包装对象,那么一些需要长期保持的状态变量保存在什么地方呢QjQuery提供了一个统一的全局数据理机制?br />  获取数据 $('#my').data('myAttr')   讄数据 $('#my').data('myAttr',3);
q一机制自然融合了对HTML5的data属性的处理
   <input id="my" data-my-attr="4" ... />
 通过 $('#my').data('myAttr')可以读取到HTML中设|的数据?br /> 
 W一ơ访问dataӞjQueryؓDOM节点分配一个唯一的uuid, 然后讄在DOM节点的一个特定的expando属性上, jQuery保证q个uuid在本面中不重复?br />   elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
 以上代码可以同时处理DOM节点和纯js对象的情c如果是js对象Q则data直接攄在js对象自n中,而如果是DOM节点Q则通过cachel一理?br /> 因ؓ所有的数据都是通过data机制l一理的,特别是包括所有事件监听函?data.events)Q因此jQuery可以安全的实现资源管理。在clone节点的时候,可以自动clone其相关的事g监听函数。而当DOM节点的内容被替换或者DOM节点被销毁的时候,jQuery也可以自动解除事件监听函? q安全的释放相关的js数据?br /> 
7. eventQ统一事g模型
  "事g沿着对象树传?q一图景是面向对象界面编E模型的_N所在。对象的复合构成对界面结构的一个稳定的描述Q事件不断在对象树的某个节点发生Qƈ通过冒机制向上传播。对象树很自然的成ؓ一个控制结构,我们可以在父节点上监听所有子节点上的事gQ而不用明与每一个子节点建立兌?br />  jQuery除了Z同浏览器的事件模型徏立了l一抽象之外,主要做了如下增强:
  A. 增加了自定制事g(custom)机制. 事g的传播机制与事g内容本n原则上是无关? 因此自定制事件完全可以和览器内|事仉过同一条处理\? 采用同样的监听方? 使用自定制事件可以增Z码的内聚? 减少代码耦合. 例如如果没有自定制事? 兌代码往往需要直接操作相关的对象
  $('.switch, .clapper').click(function() {
    var $light = $(this).parent().find('.lightbulb');
    if ($light.hasClass('on')) {
        $light.removeClass('on').addClass('off');
    } else {
        $light.removeClass('off').addClass('on');
    }
  });
而如果用自定制事g,则表辄语义更加内敛明确,
  $('.switch, .clapper').click(function() {
    $(this).parent().find('.lightbulb').trigger('changeState');
  });
  B. 增加了对动态创点的事g监听. bind函数只能监听函数注册到已经存在的DOM节点? 例如
    $('li.trigger').bind('click',function(){}}
  如果调用bind之后,新徏了另一个li节点,则该节点的click事g不会被监?
  jQuery的delegate机制可以监听函数注册到父节点上, 子节点上触发的事件会Ҏselector被自动派发到相应的handlerFn? q样一来现在注册就可以监听未来创徏的节?
    $('#myList').delegate('li.trigger', 'click', handlerFn);
  最qjQuery1.7中统一了bind, live和delegate机制, 天下一l? 只有on/off.
    $('li.trigger’).on('click', handlerFn);  // 相当于bind
    $('#myList’).on('click', 'li.trigger', handlerFn);  // 相当于delegate
    
8. 动画队列Q全局旉协调
  抛开jQuery的实C? 先考虑一下如果我们要实现界面上的动画效果, 到底需要做些什? 比如我们希望一个div的宽度在1U钟之内?00px增加?00px. 很容易想? 在一D|间内我们需要不时的去调整一下div的宽? [同时]我们q需要执行其他代? 与一般的函数调用不同的是, 发出动画指o之后, 我们不能期待立刻得到惌的结? 而且我们不能原地{待l果的到? 动画的复杂性就在于:一ơ性表达之后要在一D|间内执行,而且有多条逻辑上的执行路径要同时展开, 如何协调?
  伟大的艾萨克.牛顿爵士在《自然哲学的数学原理》中写道:"l对的、真正的和数学的旉自n在流逝着". 所有的事g可以在时间u上对? q就是它们内在的协调? 因此Z从步骤A1执行到A5, 同时步骤B1执行到B5, 我们只需要在t1时刻执行[A1, B1], 在t2时刻执行[A2,B2], 依此cL.
    t1 | t2 | t3 | t4 | t5 ...
    A1 | A2 | A3 | A4 | A5 ...
    B1 | B2 | B3 | B4 | B5 ...
  具体的一U实现Ş式可以是
  A. Ҏ个动? 其分装Z个Animation对象, 内部分成多个步骤.
      animation = new Animation(div,"width",100,200,1000,
                  负责步骤切分的插值函?动画执行完毕时的回调函数);
  B. 在全局理器中注册动画对象
      timerFuncs.add(animation);
  C. 在全局旉的每一个触发时? 每个注册的执行序列推进一? 如果已经l束, 则从全局理器中删除.
     for each animation in timerFuncs
        if(!animation.doOneStep())
           timerFuncs.remove(animation)

  解决了原理问?再来看看表达问题, 怎样设计接口函数才能够以最紧凑形式表达我们的意? 我们l常需要面临的实际问题:
  A. 有多个元素要执行cM的动?br />  B. 每个元素有多个属性要同时变化
  C. 执行完一个动M后开始另一个动?br />jQuery对这些问题的解答可以说是榨尽了js语法表达力的最后一点剩余h?
   $('input')
     .animate({left:'+=200px',top:'300'},2000)
     .animate({left:'-=200px',top:20},1000)
     .queue(function(){
       // q里dequeue首先执行队列中的后一个函?因此alert("y")
       $(this).dequeue();
       alert('x');
      })
     .queue(function(){
        alert("y");
        // 如果不主动dequeue, 队列执行׃断了,不会自动l箋下去.
        $(this).dequeue();
      });

  A. 利用jQuery内置的selector机制自然表达对一个集合的处理.
  B. 使用Map表达多个属性变?br />  C. 利用微格式表N域特定的差量概念. '+=200px'表示在现有值的基础上增?00px
  D. 利用函数调用的顺序自动定义animation执行的顺? 在后面追加到执行队列中的动画自然要等前面的动d全执行完毕之后再启动.
   
  jQuery动画队列的实现细节大概如下所C?
   A. animate函数实际是调用queue(function(){执行l束旉要调用dequeue,否则不会驱动下一个方法})
      queue函数执行? 如果是fx队列, q且当前没有正在q行动画(如果q箋调用两次animate,W二ơ的执行函数在队列中等?,则会自动触发dequeue操作, 驱动队列q行.
      如果是fx队列, dequeue的时候会自动在队列顶端加?inprogress"字符?表示要执行的是动画.
   B. 针对每一个属性,创徏一个jQuery.fx对象。然后调用fx.custom函数(相当于start)来启动动甅R?br />   C. custom函数中将fx.step函数注册到全局的timerFuncs中,然后试图启动一个全局的timer.
       timerId = setInterval( fx.tick, fx.interval );
   D. 静态的tick函数中将依次调用各个fx的step函数。step函数中通过easing计算属性的当前|然后调用fx的update来更新属性?br />   E. fx的step函数中判断如果所有属性变化都已完?则调用dequeue来驱动下一个方法?br />
  很有意思的? jQuery的实C码中明显有很多是接力触发代码: 如果需要执行下一个动d取出执行, 如果需要启动timer启动timer{? q是因ؓjsE序是单U程?真正的执行\径只有一?Z保证执行U烦不中? 函数们不得不互相帮助一? 可以惌, 如果E序内部h多个执行引擎, 甚至无限多的执行引擎, 那么E序的面貌就会发生本质性的改变. 而在q种情Ş? 递归相对于@环而言会成为更自然的描q?
 
9. promise模式Q因果关pȝ识别
  现实?L那么多时间线在独立的演化着, Z物在时空中交?却没有发生因? 软g? 函数们在源代码中排着? 隑օ会生一些疑? 凭什么排在前面的要先执行? N没有它就没有? 让全宇宙喊着1,2,3齐步前进, 从上帝的角度?大概是管理难度过大了, 于是便有了相对论. 如果怺之间没有交换信息, 没有产生怺依赖, 那么在某个坐标系中顺序发生的事g, 在另外一个坐标系中看? 可能是颠倒顺序的. E序员依葫芦ȝ, 便发明了promise模式.
  promise与future模式基本上是一回事,我们先来看一下java中熟悉的future模式.
  futureResult = doSomething();
  ...
  realResult = futureResult.get();
  发出函数调用仅仅意味着一件事情发生过, q不必然意味着调用者需要了解事情最l的l果. 函数立刻q回的只是一个将在未来兑现的承诺(Futurecd), 实际上也是某种句柄. 句柄被传来传? 中间转手的代码对实际l果是什?是否已经q回漠不兛_. 直到一D代码需要依赖调用返回的l果, 因此它打开future, 查看了一? 如果实际l果已经q回, 则future.get()立刻q回实际l果, 否则会d当前的执行\? 直到l果q回为止. 此后再调用future.get()L立刻q回, 因ؓ因果关系已经被徏? [l果q回]q一事g必然在此之前发生, 不会再发生变?
  future模式一般是外部对象d查看future的返回? 而promise模式则是由外部对象在promise上注册回调函?
  function getData(){
   return $.get('/foo/').done(function(){
      console.log('Fires after the AJAX request succeeds');
   }).fail(function(){
      console.log('Fires after the AJAX request fails');
   });
  }
 
  function showDiv(){
    var dfd = $.Deferred();
    $('#foo').fadeIn( 1000, dfd.resolve );
    return dfd.promise();
  }
 
  $.when( getData(), showDiv() )
    .then(function( ajaxResult, ignoreResultFromShowDiv ){
        console.log('Fires after BOTH showDiv() AND the AJAX request succeed!');
        // 'ajaxResult' is the server’s response
    });
  jQuery引入Deferredl构, Ҏpromise模式对ajax, queue, document.ready{进行了重构, l一了异步执行机? then(onDone, onFail)向promise中追加回调函? 如果调用成功完成(resolve), 则回调函数onDone被执行, 而如果调用失?reject), 则onFail被执行. when可以{待在多个promise对象? promise巧妙的地Ҏ异步执行已经开始之后甚臛_l结束之?仍然可以注册回调函数
  someObj.done(callback).sendRequest() vs. someObj.sendRequest().done(callback)
 callback函数在发出异步调用之前注册或者在发出异步调用之后注册是完全等L, q揭C出E序表达永远不是完全_? d在着内在的变化维? 如果能有效利用这一内在的可变? 则可以极大提升ƈ发程序的性能.
   promise模式的具体实现很? jQuery._Deferred定义了一个函数队列,它的作用有以下几点:
   A. 保存回调函数?br />   B. 在resolve或者reject的时L保存着的函数全部执行掉?br />   C. 已经执行之后, 再增加的函数会被立刻执行?br /> 
   一些专门面向分布式计算或者ƈ行计的语言会在语言U别内置promise模式, 比如E语言.
     def carPromise := carMaker <- produce("Mercedes");
     def temperaturePromise := carPromise <- getEngineTemperature()
     ...
     when (temperaturePromise) -> done(temperature) {
       println(`The temperature of the car engine is: $temperature`)
     } catch e {
       println(`Could not get engine temperature, error: $e`)
     }
  在E语言? <-是eventuallyq算W? 表示最l会执行, 但不一定是现在. 而普通的car.moveTo(2,3)表示立刻执行得到l果. ~译器负责识别所有的promise依赖, q自动实现调?
 
10. extend: l承不是必须?br />  js是基于原型的语言, q没有内|的l承机制, q一直让很多深受传统面向对象教育的同学们耿耿于怀. 但承一定是必须的吗? 它到底能够给我们带来什? 最U朴的回{是: 代码重用. 那么, 我们首先来分析一下承作Z码重用手D늚潜力.
  曄有个概念叫做"多重l承", 它是l承概念的超U赛亚h? 很遗憑֐来被诊断为存在着先天~陷, 以致于出C一U对于承概늚解读: l承是"is a"关系, 一个派生对?is a"很多基类, 必然会出现精分? 所以多重承是不好?
   class A{ public: void f(){ f in A } }
   class B{ public: void f(){ f in B } }
   class D: public A, B{}
 如果DcMA,B两个基类l承, 而A和BcM都实C同一个函数f, 那么DcM的f到底是A中的fq是B中的f, 抑或是A中的f+B中的f? q一困境的出现实际上源于D的基cA和B是ƈ列关p? 它们满交换律和l合? 毕竟,在概念层面上我们可能难以认可两个L概念之间会出C属关p? 但如果我们放松一些概念层面的要求, 更多的从操作层面考虑一下代码重用问? 可以单的认ؓB在A的基上进行操? 那么可以得C个线性化的结? 也就是说, 攑ּA和B之间的交换律只保留结合律, extends A, B ?extends B,A 会是两个不同的结? 不再存在诠释上的二义? scala语言中的所谓trait(Ҏ?机制实际上采用的是q一{略.
  面向对象技术发明很久之? 出现了所谓的面向斚w~程(AOP), 它与OOP不同, 是代码结构空间中的定位与修改技? AOP的眼中只有类与方? 不知道什么叫做意? AOP也提供了一U类似多重承的代码重用手段, 那就是mixin. 对象被看作是可以被打开,然后L修改的Map, 一l成员变量与Ҏp直接注射到对象体? 直接改变了它的行?
  prototype.js库引入了extend函数,
  Object.extend = function(destination, source) {
    for (var property in source) {
      destination[property] = source[property];
    }
    return destination;
  }
  是Map之间的一个覆盖运? 但很用, 在jQuery库中也得C延用. q个操作cM于mixin, 在jQuery中是代码重用的主要技术手D?--没有l承也没什么大不了?

11. 名称映射: 一切都是数?
  代码好不? 循环判断必须? 循环和判断语句是E序的基本组成部? 但是优良的代码库中却往往找不到它们的t媄, 因ؓq些语句的交l会模糊pȝ的逻辑ȝ, 使我们的思想q失在疲于奔命的代码q踪? jQuery本n通过each, extend{函数已l极大减了对@环语句的需? 对于判断语句, 则主要是通过映射表来处理. 例如, jQuery的val()函数需要针对不同标{进行不同的处理, 因此定义一个以tagName为key的函数映表
   valHooks: { option: {get:function(){}}}
q样在程序中׃需要到处写
   if(elm.tagName == 'OPTION'){
     return ...;
   }else if(elm.tagName == 'TEXTAREA'){
     return ...;
   }
可以l一处理
   (valHooks[elm.tagName.toLowerCase()] || defaultHandler).get(elm);
   
  映射表将函数作ؓ普通数据来理, 在动态语a中有着q泛的应? 特别? 对象本n是函数和变量的容器, 可以被看作是映射? jQuery中大量用的一个技巧就是利用名U映来动态生成代? 形成一U类似模板的机制. 例如Z实现myWidth和myHeight两个非常cM的函? 我们不需?br />  jQuery.fn.myWidth = function(){
      return parseInt(this.style.width,10) + 10;
    }
    
    jQuery.fn.myHeight = function(){
      return parseInt(this.style.height,10) + 10;
    }
而可以选择动态生?br />    jQuery.each(['Width','Height'],function(name){
      jQuery.fn['my'+name] = function(){
        return parseInt(this.style[name.toLowerCase()],10) + 10;
      }
    });
 
12. 插g机制Q其实我很简?nbsp;   
  jQuery所谓的插g其实是$.fn上增加的函数, 那这个fn是什么东?
  (function(window,undefined){
    // 内部又有一个包?br />    var jQuery = (function() {
      var jQuery = function( selector, context ) {
            return new jQuery.fn.init( selector, context, rootjQuery );
        }
       ....
      // fn实际是prototype的简?br />      jQuery.fn = jQuery.prototype = {
          constructor: jQuery,
          init: function( selector, context, rootjQuery ) {...  }
      }
    
      // 调用jQuery()是相当于new init(), 而init的prototype是jQuery的prototype
      jQuery.fn.init.prototype = jQuery.fn;
    
      // q里q回的jQuery对象只具备最基本的功? 下面是一pd的extend
      return jQuery;
    })();  
    ...
     // jQuery暴露为全局对象
    window.jQuery = window.$ = jQuery;
  })(window);
  昄, $.fn其实是jQuery.prototype的简?
 
  无状态的插g仅仅是一个函? 非常?
  // 定义插g
  (function($){
      $.fn.hoverClass = function(c) {
          return this.hover(
              function() { $(this).toggleClass(c); }
          );
      };
  })(jQuery);
 
  // 使用插g
  $('li').hoverClass('hover');
 
 对于比较复杂的插件开? jQuery UI提供了一个widget工厂机制,
 $.widget("ui.dialog", {
   options: {
        autoOpen: true,...
     },
     _create: function(){ ... },
     _init: function() {
        if ( this.options.autoOpen ) {
            this.open();
        }
     },
     _setOption: function(key, value){ ... }
     destroy: function(){ ... }
 });
 
 调用 $('#dlg').dialog(options)? 实际执行的代码基本如下所C?
  this.each(function() {
        var instance = $.data( this, "dialog" );
        if ( instance ) {
            instance.option( options || {} )._init();
        } else {
            $.data( this, "dialog", new $.ui.dialog( options, this ) );
        }
    }
 可以看出, W一ơ调?('#dlg').dialog()函数时会创徏H口对象实例,q保存在data? 此时会调用_create()和_init()函数, 而如果不是第一ơ调? 则是在已l存在的对象实例上调用_init()Ҏ. 多次调用$('#dlg').dialog()q不会创建多个实?

13. browser sniffer vs. feature detection
  览器嗅?browser sniffer)曄是很行的技? 比如早期的jQuery?br />  jQuery.browser = {
        version:(userAgent.match(/.+(?:rv|it|ra|ie)[/: ]([d.]+)/) || [0,'0'])[1],
        safari:/webkit/.test(userAgent),
        opera:/opera/.test(userAgent),
        msie:/msie/.test(userAgent) && !/opera/.test(userAgent),
        mozilla:/mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent)
  };
  在具体代码中可以针对不同的浏览器作出不同的处?br />  if($.browser.msie) {
      // do something
  } else if($.browser.opera) {
      // ...
  }  

  但是随着览器市场的竞争升, 竞争Ҏ之间的互相模仿和伪装DuserAgent一片؜? 加上Chrome的诞? Safari的崛? IE也开始加速向标准靠拢, sniffer已经起不到积极的作用. Ҏ检?feature detection)作ؓ更细_度, 更具体的手D? 逐渐成ؓ处理览器兼Ҏ的L方式.
  jQuery.support = {
        // IE strips leading whitespace when .innerHTML is used
        leadingWhitespace: ( div.firstChild.nodeType === 3 ),
        ...
    }
    只基于实际看见的,而不是曾l知道的, q样更容易做到兼Ҏ?

14. Prototype vs. jQuery
  prototype.js是一个立意高q的? 它的目标是提供一U新的用体验,参照Ruby从语aU别对javascriptq行攚w,q最l真的极大改变了js的面貌?, extends, each, bind...q些耳熟能详的概念都是prototype.js引入到js领域? 它肆无忌惮的在window全局名字I间中增加各U概? 大有谁先占坑谁有? 舍我其谁的气? 而jQuery则扣扣烦? q比较实用化的理念, 目标仅仅是write less, do more而已.  
  不过{待Ȁq的理想M者的命运往往都是壮志未酬w先? 当prototype.js标志性的bind函数{被吸收到ECMAScript标准中时, 便注定了它的没落. 到处修改原生对象的prototype, q是prototype.js的独门秘技, 也是它的ȝ. 特别是当它试图模仿jQuery, 通过Element.extend(element)q回增强对象的时? 是d被jQueryl带到沟里去? prototype.js与jQuery不同, 它L直接修改原生对象的prototype, 而浏览器却是充满bug, 谎言, 历史包袱q夹杂着商业阴谋的领? 在原生对象层面解决问题注定是一场悲? 性能问题, 名字冲突, 兼容性问题等{都是一个帮助库的能力所无法解决? Prototype.js?.0版本据说要做大的变革, 不知是要与历史决? 攑ּ兼容? q是l箋挣扎, 在夹~中求生.

canonical 2011-12-25 21:23 发表评论
]]>
从面向对象到面向切面http://www.tkk7.com/canonical/archive/2011/05/08/349771.htmlcanonicalcanonicalSun, 08 May 2011 04:07:00 GMThttp://www.tkk7.com/canonical/archive/2011/05/08/349771.htmlhttp://www.tkk7.com/canonical/comments/349771.htmlhttp://www.tkk7.com/canonical/archive/2011/05/08/349771.html#Feedback1http://www.tkk7.com/canonical/comments/commentRss/349771.htmlhttp://www.tkk7.com/canonical/services/trackbacks/349771.html
2. 面向对象(OOP)指出Q在q一领域上可以徏立分l?group)l构Q一l相关的变量和函数构成一个集合,我们UC为对?Object)。同时在分组l构上可以定义一个运?推理)关系:  D > B, zcD从基cBl承Qinheritance)Q相应的z对象W合基类对象所满的所有约束。推理是有h值的Q因为根?D > B, B > A 可以自动推导?D > AQ所有针对A的断a在理Z对D都成?q也是我们常说?#8220;z对象 is a 基类对象”)。编译器也能有点了?br />    一个有的地方是,D > B意味着在D和B之间存在着某种差异Q但是我们却无法把它昑ּ的表辑և来!也就是说在代码层面上我们无法明确表达 D - B是什么。ؓ了把更多的信息不断的导入到原有系l中Q面向对象内|提供的Ҏ是徏立不断扩展的cd树,cd树每增长一层,可以多容纳一些新的信息。这是一U金字塔式的l构Q只不过是一U倒立的金字塔Q最l基点会被不断增长的l构压力所压垮?br />
3. lg技?Component)本质上是在提倡面向接?interface)Q然后通过接口之间的组?Composition)而不是对象之间的l承(inheritance)来构造系l。基于组合的观念相当于是定义了运关p:D = B + C。终于,我们勉强可以在概念层面上做加法了?br />    lg允许我们随意的组合,按照q单到复杂的方向构造系l,但是lg构成的成品之间仍然无法自q建立关系。这意味着lgl装得到的成品只是某U孤立的Q偶然的产物?br />    F = A + B + C  ? G = A + D + C?br />
4. 在数学上Q配备了加法q算的集合构成半,如果要成为群(Group)Q则必须定义相应的逆运:减法?结构得大_度的结构变换成为可能?br />    F = A + B + C = A + D - D + B + C = (A + D + C) - D + B = G - D + B
   在不破坏原有代码的情况下Q对原有pȝ功能q行增删Q这是面向切面(AOP)技术的全部价倹{?br />



canonical 2011-05-08 12:07 发表评论
]]>
业务架构q_的自N?/title><link>http://www.tkk7.com/canonical/archive/2011/02/11/344053.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Fri, 11 Feb 2011 06:02:00 GMT</pubDate><guid>http://www.tkk7.com/canonical/archive/2011/02/11/344053.html</guid><wfw:comment>http://www.tkk7.com/canonical/comments/344053.html</wfw:comment><comments>http://www.tkk7.com/canonical/archive/2011/02/11/344053.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/canonical/comments/commentRss/344053.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/canonical/services/trackbacks/344053.html</trackback:ping><description><![CDATA[   业务架构q_的设计与实现要比普通业务系l困隑־多。一个核心难点在于如何徏立普遍有效的应用E序模型Q如何控制各U偶然性的业务需求对pȝ整体架构的冲凅R大多数现有的业务架构^台都是提供了一个庞大的万能性品,它预料到了所有可能在业务pȝ开发中出现的可能性,q提供了相应的处理手Dc业务系l开发h员的能力被限定在业务架构q_所允许的范围之内。如果业务架构^台的复杂度ؓA+Q则我们最多只能用它来开发复杂度为A的业务系l。一个典型的特征是使用业务架构q_的功能配|非常简单,但是要开发相应的功能Ҏ则非常困难Q而且必须采用与业务系l开发完全不同的技术手D和开发方式?br />    采用业务架构q_来开发业务系l,即看似开发工作量,最l生的各类配置代码量也可能会大大超q普通手工编E生的代码量,q意味着q_装了业务内在的复杂性,q是意味着q_引入了不必要的复杂性?很多业务架构q_的卖炚w是零代码的应用开发,低水q的开发h员也可以d的开发,但是Z么高水^的程序员不能借助于这些开发^台极大的提高生率?<br />    一般的业务架构q_无法回答以下问题Q?br /> 1) 业务pȝ可以通过使用设计工具来重用业务架构^台已l实现的功能Q但是业务系l内部大量相似的模型配置如何才能够被重用Q?br /> 2) 特定的业务领域中存在着大量Ҏ的业务规则,例如“审批串行q行Q每一步都允许回退C一步,而且允许选择跌{CQ意后一?#8221;。这些规则如何才能够被引入设计工P化配|过E?<br /> 3) 已经开发好的业务系l作Z品来销售的时候,如何应对具体客户的定制化Q如果按照客戯求修攚w|,则以后业务系l自w是否还能够实现版本升Q?br />    <br />    Witrixq_提供的基本开发模型ؓ <br />           <strong>App = Biz aop-extends Generator<DSL></strong><br /> 在这一图景下,我们可以回{以上三个问题:<br /> 1) 业务模型通过领域特定语言(DSL)来表达,因此可以使用语言中通用的承或者组件抽象机制来实现模型重用?br /> 2) 推理机对于所有推理规则一视同仁,Ҏ的业务规则与通用的业务规则一样都可以参与推理q程Qƈ且一般情况下Ҏ的业务规则更能够大幅化系l实现结构?br /> 3) 相对于原始模型的修改被独立出来,然后应用面向切面(AOP)技术将q些特定代码l入到原始模型中。原始模型与差异修改怺分离Q因此原始模型可以随时升U?br /> <br />   Witrixq_所的不是强大的功能Q而是一切表象之后的数学规律。Witrixq_通过数基本原理的反复应用来构造Y件系l,它本w就是采用^台技术构造的产物。我们用复杂度ؓA的工具制造复杂度为A+的品,然后q一步以q个复杂度ؓA+的品ؓ工具来构造复杂度为A++的品?br /> <br /> <img src ="http://www.tkk7.com/canonical/aggbug/344053.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/canonical/" target="_blank">canonical</a> 2011-02-11 14:02 <a href="http://www.tkk7.com/canonical/archive/2011/02/11/344053.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>模型驱动的数学原?/title><link>http://www.tkk7.com/canonical/archive/2011/02/07/343919.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Sun, 06 Feb 2011 18:56:00 GMT</pubDate><guid>http://www.tkk7.com/canonical/archive/2011/02/07/343919.html</guid><wfw:comment>http://www.tkk7.com/canonical/comments/343919.html</wfw:comment><comments>http://www.tkk7.com/canonical/archive/2011/02/07/343919.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/canonical/comments/commentRss/343919.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/canonical/services/trackbacks/343919.html</trackback:ping><description><![CDATA[<p>    一U技术思想如果实能够化编E,有效降低pȝ构造的复杂性,那么它必然具有某U内在的数学解释。反之,无论一U技术机制显得如何华丽高深,如果它没? 清晰的数学图象,那么很难证明自w存在的价倹{对于模型驱动架?MDA)Q我长期以来一直都持有一U批判态度。(Physical Model Driven<a > http://canonical.javaeye.com/blog/29412</a> Q。原因就在于“由工兯动实Cq_无关模型(PIM)向^台相x?PSM)的{?#8221;q一图景g只是xpȝ从实现的泥沼中拯救出来,遮蔽特定? aQ特定^C的偶然的限制条gQƈ没有触及到系l复杂性这一核心问题。而所谓的可视化徏模充光不过是说明hc超强的视觉模式识别能力使得我们可以q? 识别pȝ全景图中隐含的整体结构,更快的实现对pȝl构的理解,q没有证明系l复杂性有M本质性的降低。不q如果我们换一个视? 不把模型局限ؓ某种可视化的l构?而将它定义ؓ某种高度羃的领域描q? 则模型驱动基本上{h于根据领域描q自动推导得到最l的应用E序。沿着q一思\QWitrixq_中的很多设计实际上可以被解释为模型定义,模型推导以及 模型嵌入{方面的探烦。这些具体技术的背后需要的是比一般MDA思想更加_致的设计原理作为支撑。我们可以进行如下抽象分析。(Witrix架构分析 <a >http://canonical.javaeye.com/blog/126467</a> Q?br /> <br /> 1. 问题复杂Q线性切分是削减问题规模Q从而降低问题复杂性)的通用手段Q例如模?Module)。(软g中的分析?<a >http://canonical.javaeye.com/blog/33885</a> Q?/p> <div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><span style="color: #000000;">App </span><span style="color: #000000;">=</span><span style="color: #000000;"> M1 </span><span style="color: #000000;">+</span><span style="color: #000000;"> M2 </span><span style="color: #000000;">+</span><span style="color: #000000;"> M3 </span><span style="color: #000000;">+</span><span style="color: #000000;"> <img src="http://www.tkk7.com/Images/dot.gif" alt="" />    <br /> </span></div> <p><br /> </p> <p>2. 分块q多Q同态映是pȝU化的一般化{略Q例如多态(polymorphismQ。(同构与同态:认识同一?<a >http://canonical.javaeye.com/admin/blogs/340704</a> Q?/p> <div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><span style="color: #000000;">(abc,abb,ade,<img src="http://www.tkk7.com/Images/dot.gif" alt="" />) </span><span style="color: #000000;">-></span><span style="color: #000000;"> [a],   (bbb, bcd,bab,<img src="http://www.tkk7.com/Images/dot.gif" alt="" />) </span><span style="color: #000000;">-></span><span style="color: #000000;"> [b]</span></div> <p><br /> </p> <p>3. 递归使用以上两种ҎQ将分分合合的游戏进行到底,推向极致?br /> <br /> 4. 以少控多的终极Ş态?如果存在Q则构成输入与输Z间的非线性变换(输入中局部微变化将D输出中大范围明显的变化)?/p> <div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><span style="color: #000000;">App </span><span style="color: #000000;">=</span><span style="color: #000000;"> F(M)</span></div> <p><br /> </p> <p>5. 变换函数F可以被诠释ؓ解释?Interpreter)或者翻译机Q例如工作流引擎工作流描述信息译Z步步的具体操作,工作描q可以看作是由底 层引擎支撑的Q在更高的抽象层面上q行的领域模型。但是在q种观点下,变换函数Fg是针ҎU特定模型构造的Q引擎内部信息传导的途径是确定的Q关注的 重点始终在模型上Q那么解释器自n应该如何被构造出来呢Q?/p> <div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><span style="color: #000000;">App </span><span style="color: #000000;">~</span><span style="color: #000000;"> M</span></div> <p><br /> </p> <p>6. 另外一U更加开攄观点是将变换函数F看作是生成器(Generator)或者推理机。F根据输入的信息Q结合其他知识,推理生成一pd新的命题和断 a。模型的力量源于推导。变换函数F本n在系l构造过E中处于核心CQM仅仅是触发其推理q程的信息源而已。F榨qM的最后一点剩余h|所有根据M 能够定的事实将被自动实玎ͼ而大量单靠M自n的信息无法判定的命题也可以结合F内在的知识作出判断。生成器自n的构造过E非常简?-只要不断向推理系 l中增加新的推理规则卛_。语a内置的模板机?template)及元~程技?meta programming)Q或者跨语a边界的代码生成工具都可以看作是生成器的具体实例。(关于代码生成和DSL <a >http://canonical.javaeye.com/blog/275015</a> )</p> <div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><span style="color: #000000;">App </span><span style="color: #000000;">=</span><span style="color: #000000;"> G</span><span style="color: #000000;"><</span><span style="color: #000000;">M</span><span style="color: #000000;">></span></div> <p><br /> </p> <p>7. 生成器G之所以可以被独立实现Q是因ؓ我们可以实现相对知识与绝对知识的分离, q也正是面向对象技术的本质所在。(面向对象之Ş式系l?<a >http://canonical.javaeye.com/blog/37064</a> Q?/p> <div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><span style="color: #000000;">G</span><span style="color: #000000;"><</span><span style="color: #000000;">M</span><span style="color: #000000;">></span><span style="color: #000000;"> </span><span style="color: #000000;">==></span><span style="color: #000000;"> G </span><span style="color: #000000;">=</span><span style="color: #000000;"> {m </span><span style="color: #000000;">=></span><span style="color: #000000;"> m.x(a,b,c);m.y(); <img src="http://www.tkk7.com/Images/dot.gif" alt="" /> }</span></div> <p><br /> </p> <p>8. 现实世界的不完美Q就在于现实决不按照我们为其指定的理惌\U前q。具体场景中L存在着大量我们无法预知?#8220;噪声”Q它们得Q何在“q去”立的方E? 都无法在“未来”保持持久的^衡。传l模型驱动架构的困境在于此。我们可以选择模型M和生成器G不断复杂化,容纳来多的偶然性,直至失去Ҏ型整 体结构的控制力。另外一U选择是模型在不断膨胀Q不断提高覆盖能力的q程中,不断的空z化Q生大量可插入(plugin)的接入点Q最l失模型的推理 能力Q退化成ZU编码规范。Witrixq_中采用的是第三种选择Q模型嵌?-模型中的多余信息被不断清z掉Q模型通过_化来H出自n存在的合? 性,成ؓ更广泛的q行环境中的支撑骨架。(l构的自x?<a >http://canonical.javaeye.com/blog/482620</a> Q?/p> <div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><span style="color: #000000;">App </span><span style="color: #000000;">!=</span><span style="color: #000000;"> G0</span><span style="color: #000000;"><</span><span style="color: #000000;">M0</span><span style="color: #000000;">></span><span style="color: #000000;">  Q?nbsp;App </span><span style="color: #000000;">!=</span><span style="color: #000000;"> G0</span><span style="color: #000000;"><</span><span style="color: #000000;">M1</span><span style="color: #000000;">></span><span style="color: #000000;">Q?nbsp;App </span><span style="color: #000000;">=</span><span style="color: #000000;"> G1</span><span style="color: #000000;"><</span><span style="color: #000000;">M1</span><span style="color: #000000;">></span><span style="color: #000000;"> <br /> </span></div> <p><br /> </p> <p>9. 现在的问题是Q如何基于一个已l被完美解决的重大问题,来更有效率的搞定不断出现但又不是重复出现的小问题。现在我们所需要的不是沿着某个l度q行均匀? 切分Q而必L某种有效的降l手Dc如果我们可以定义一U投q子P, 待解决的问题投到已经被解决的问题域中Q则剩下的补集往往可以被简化。(M分解而不是正交分?<a >http://canonical.javaeye.com/blog/196826</a> Q?/p> <div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><span style="color: #000000;">dA </span><span style="color: #000000;">=</span><span style="color: #000000;"> App </span><span style="color: #000000;">-</span><span style="color: #000000;"> P[App]  </span><span style="color: #000000;">=</span><span style="color: #000000;"> App </span><span style="color: #000000;">-</span><span style="color: #000000;"> G0</span><span style="color: #000000;"><</span><span style="color: #000000;">M0</span><span style="color: #000000;">></span></div> <p><br /> </p> <p>10. 要实C上微扰分析策略,前提条g是可以定义逆元Qƈ且需要定义一U精l的_结操作Q可以将分散的扰动量极ؓ_的应用到基础pȝ的各处。Witrixq_的具体实现类g某种AOPQ面向切面编E)技术。(逆元Q不存在的真实存?<a >http://canonical.javaeye.com/blog/325051</a> Q?/p> <div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><span style="color: #000000;">App </span><span style="color: #000000;">=</span><span style="color: #000000;"> A </span><span style="color: #000000;">+</span><span style="color: #000000;"> D </span><span style="color: #000000;">+</span><span style="color: #000000;"> B </span><span style="color: #000000;">=</span><span style="color: #000000;"> (A </span><span style="color: #000000;">+</span><span style="color: #000000;"> B </span><span style="color: #000000;">+</span><span style="color: #000000;"> C) </span><span style="color: #000000;">-</span><span style="color: #000000;"> C </span><span style="color: #000000;">+</span><span style="color: #000000;"> D </span><span style="color: #000000;">=</span><span style="color: #000000;"> App0 </span><span style="color: #000000;">+</span><span style="color: #000000;"> (</span><span style="color: #000000;">-</span><span style="color: #000000;">C </span><span style="color: #000000;">+</span><span style="color: #000000;"> D) </span><span style="color: #000000;">=</span><span style="color: #000000;"> G0</span><span style="color: #000000;"><</span><span style="color: #000000;">M0</span><span style="color: #000000;">></span><span style="color: #000000;"> </span><span style="color: #000000;">+</span><span style="color: #000000;"> dA</span></div> <p><br /> </p> <p>11. 模型驱动q不意味着一个应用只能由唯一的一个模型来驱动Q但是如果引入多个不同Ş式的模型Q则必须为如下推理提供具体的技术\径:<br />   A. 多个模型变换到共同的描q域 <br />   B. 实现多个模型的加?<br />   C. 处理模型之间的冲Hƈ填补模型之间的空?br /> 在Witrixq_中模型嵌?l合主要依赖于文本化及编译期q行{机制。(文本?<a >http://canonical.javaeye.com/blog/309395</a> Q?/p> <div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><span style="color: #000000;">App </span><span style="color: #000000;">=</span><span style="color: #000000;"> Ga</span><span style="color: #000000;"><</span><span style="color: #000000;">Ma</span><span style="color: #000000;">></span><span style="color: #000000;"> </span><span style="color: #000000;">+</span><span style="color: #000000;"> Gb</span><span style="color: #000000;"><</span><span style="color: #000000;">Mb</span><span style="color: #000000;">></span><span style="color: #000000;"> </span><span style="color: #000000;">+</span><span style="color: #000000;"> dA</span></div> <p><br /> </p> <p>12. pȝ的开发时刻t0和实施时刻t1一般是明确分离的,因此如果我们要徏立一个包含开发与实施时刻信息的模型,则这一模型必须是含时的Q多阶段的。关于时 _我们所知道的最重要的事实之一?#8220;未来是不可预知的”。在t0时刻建立的模型如果要늛t1时刻的所有变化,则必d出大量猜,而且t1时刻距离 t0时刻远Q猜的量越大,“猜测有效”q一集合的测度越,直至?。gq选择是实现含时系l控制的不二法门?br />    在Witrixq_中,所有功能特性的实现都包含某U元数据描述或者定制模板,因此l合配置机制以及动态编译技术既可实现多阶段模型。例如对于一个在未来 才能定的常量数l,我们可以定义一个Excel文g来允许实施h员录入具体的|然后通过动态编译技术在~译期解析Excel文gQƈ完成一pd数值映 运,最l将其{化ؓ~译期存在的一个常量。这一q程不会引入M额外的运行成本,也不要求M特定的缓存机Ӟ最l的q行l构与在未来当所有信息都? 位之后再手写代码没有M区别。(D语言与tpl之编译期动作 <a >http://canonical.javaeye.com/blog/57244</a> Q?/p> <div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><span style="color: #000000;">App(t1) </span><span style="color: #000000;">=</span><span style="color: #000000;"> G(t0,t1)</span><span style="color: #000000;"><</span><span style="color: #000000;">M(t0,t1)</span><span style="color: #000000;">></span><span style="color: #000000;"> </span><span style="color: #000000;">+</span><span style="color: #000000;"> dA(t0,t1)</span></div> <p><br /> </p> <p>13. U列理论提供了一个演化框Ӟ它指出孤立的模型必须被放在模型列中被定义,被解释。(关于U列设计理论 <a >http://canonical.javaeye.com/blog/33824</a> Q?/p> <div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><span style="color: #000000;">M[n] </span><span style="color: #000000;">=</span><span style="color: #000000;"> G</span><span style="color: #000000;"><</span><span style="color: #000000;">M[n</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">]</span><span style="color: #000000;">></span><span style="color: #000000;"> </span><span style="color: #000000;">+</span><span style="color: #000000;"> dMn</span></div> <p><br /> </p> <p>14. 推理的链条会因ؓM局部反例的出现而中断。在L时空点上Q我们能够断a的事实有哪些Q信息越,我们能够定的事实越,能够做出的推Zp。现 在流行的很多设计实质上是在破坏系l的对称性,破坏pȝ大范围的l构。比如明明ORM容器已经实现所有数据对象的l一理Q非要将其拆分ؓ每个业务表一? 的DAO接口。很多对灉|性的q求完全没有搞清楚信息是对不定性的消除Q而不定性的减少意味着限制的增加,U束的增加。(From Local To Global <a >http://canonical.javaeye.com/blog/42874</a> Q?br /> <br />    lg/构g技术的宣言是生产即l装Q但是组装有成本Q有后遗症(例如需要额外的胶水或者螺钉)。Y件的本质q不是物质,而是信息Q而信息的本质是抽象的? 律。在抽象世界中最有效的生产方式是抽象的运,q算即生产。组件式开发意味着服从现有规律Q熟l应用,而原理性生产则意味着不断创造新的规律。功能模 块越多,l护的成本越高,是负担,而推理机制越多,生的成本越低,是胦富。只有恢复Y件的抽象性,明确把握软g构造过E内在的数学原理Q才能真正释放Y 件研发的生力。(从编写代码到刉代?<a >http://canonical.javaeye.com/blog/333167</a> Q?br /> </p> <p><br /> </p> <p>注解1Q很多设计原则其实是在强调Y件由人构造由人理解,软g开发本质上是hcdE学Q需要关注hcȝ理解力与协作能力。例如共同的建模语言减少交互成本Q基于模型减设计与实现的分,易读的代码比高性能的代码更重要Q做一件事只有唯一的一U方式等?br /> <br /> 注解2Q生成系l的演绎q比我们惌的要深刻与复杂得多。例如生命的成长可以被看作是在外界反馈下不断调整的生成过E?br /> <br /> 注解3Q领域描q是更紧致但却未必是更本质的表达。hcȝDNA如果表达为ATGC序列完全可以拯到U盘中带走Q只要对DNA做少量增删,可以实现? 鼠到人类的变换(人类和老鼠都有大约30000条基因,其中U有80%的基因是“完全一L”Q大U共享有99%的类似基因)Q但是很难认ZhcL有智? 的本质都体现在DNA中,DNA看v来更像是某种序列化保存Ş式而已?br /> <br /> 注解4Q模型{换这一提法g是在模型之间的同构对应,转换gL可以双向q行的,仅仅是实现难度限制了反向转换而已。但是大量有用的模型变换却是单向的,变换q程要求不断补充新的信息?br /> <br /> 注解5Q模型驱动在很多人看来就是数据库模型或者对象模型驱动系l界面运行,但实际上模型可以意指L抽象知识。虽然在目前业内q泛行的对象范式下Q所 有知识都可以表达为对象之间的兌Q但是对象关p(名词之间的关联关p)对运结构的揭示是远q不够充分的。很多时候所谓的领域模型仅仅是表明概念之间具 有相x,但是如果不补充一大段文字说明Q我们对于系l如何运作仍然一知半解。数学分析其实是领域内在的意义抽空Q仅余下通用的Ş式化W号?br /> </p> <img src ="http://www.tkk7.com/canonical/aggbug/343919.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/canonical/" target="_blank">canonical</a> 2011-02-07 02:56 <a href="http://www.tkk7.com/canonical/archive/2011/02/07/343919.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>资源文g理http://www.tkk7.com/canonical/archive/2010/01/17/309866.htmlcanonicalcanonicalSun, 17 Jan 2010 09:51:00 GMThttp://www.tkk7.com/canonical/archive/2010/01/17/309866.htmlhttp://www.tkk7.com/canonical/comments/309866.htmlhttp://www.tkk7.com/canonical/archive/2010/01/17/309866.html#Feedback0http://www.tkk7.com/canonical/comments/commentRss/309866.htmlhttp://www.tkk7.com/canonical/services/trackbacks/309866.html
1. 识别contextPath
   tpl模板中的所有资源相x{N会自动拼接Web应用的contextPath, 例如当contextPath=myApp?br />    <script src="/a.js"></script> 最l输?<script src="/myApp/a.js" ...>

2. 识别重复装蝲
   <script src="a.js" tpl:once="true"></script>
   tpl:once属性将保证在页面中script标签实际只会出现一?

3. 识别lg内相对\?br />   开发Weblg?我们希望所有资源文仉应该相对lg目录q行定位,但是直接输出?lt;script>{标{N是相对于最l的调用链接q行相对路径定位? 例如在page1.jsp中调用了lgA, 在组件A的实C, 输出?lt;script src="my_control.js"></script>
 我们的意图一般是相对于组件A的实现文件进行定? 而不是相对于page1.jspq行定位. tpl模板引擎的相对\径解析规则ؓ永远相对于当前文件进行定? 例如
  <c:include src="sub.tpl" />
在sub.tpl中的所有相对\径都相对于sub.tpl文gq行定位.

4. ~译期文件有效性检?br />    在编译期, tpl引擎会检查所有引入的资源文g的有效? 如果发现资源文g丢失, 直接抛出异? q样׃用等CU后才发现文件命名已修改{问?

5. ~存控制
  览器缺省会~存css, js{文? 因此pȝ上线后如果修改资源文件可能会造成与客L~存不一致的情况. 一个简单的处理方式是每ơ生成资源链接的时候都拼接文g的修Ҏ期或者版本号, q样既可利用客户端缓? 又可以保证L使用最新版? 例如
  <script src="a.js"></script>会输出 <script src="/myApp/myModule/a.js?344566" ...>

6. 字符集选择
  Z化国际化处理, 一般提倡的最佛_跉|式是坚持使用UTF-8~码. 但是很多情况下可能用系l内|的GBK~码会更加方便一? 另外集成一些既有代码时也存在着不同字符集的问题. 在Witrixq_? 所有输出的资源标签都会标明对应的字W集, 如果没有明确讄取pȝ参数中的~省字符?
 例如 <script src="a.js"></script> 会输出 <script ... charset="GBK"></script>

7. ~省theme支持
  Z支持多种面风格, 往往不是单的替换css文g卛_实现? 它可能意味着整个lg的实C码的更换. Witrixq_中通过一pd~省判断来简化这一q程. 例如如下代码表明如果讄了ui_themepȝ参数, q且对应的特D实现存? 则用特D实? 否则pȝ~省实现.
  <c:include src="${cp:ui_theme()}/ctl_my_ctl.tpl" >
    <c:include src="default/ctl_my_ctl.tpl" />
  </c:include>


canonical 2010-01-17 17:51 发表评论
]]>
AOP的应?/title><link>http://www.tkk7.com/canonical/archive/2009/12/13/305770.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Sun, 13 Dec 2009 03:34:00 GMT</pubDate><guid>http://www.tkk7.com/canonical/archive/2009/12/13/305770.html</guid><wfw:comment>http://www.tkk7.com/canonical/comments/305770.html</wfw:comment><comments>http://www.tkk7.com/canonical/archive/2009/12/13/305770.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/canonical/comments/commentRss/305770.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/canonical/services/trackbacks/305770.html</trackback:ping><description><![CDATA[<p>     AOP(Aspect Oriented Programming)早已不是什么新鲜的概念Q但有趣的是Q除了事?transaction), 日志(Log){寥寥几个样板应用之外,我们g找不到它的用武之地?a mce_href="/blog/34941">http://canonical.javaeye.com/blog/34941</a> 很多人的疑惑是我直接改代码就行了Q干吗要用AOP呢?AOP的定义和实现那么复杂Q能够提供什么特异的价值呢Q?br />     Witrixq_依赖于AOP概念来完成领域模型抽象与模型变换Q但是在具体的实现方式上Q却与常见的AOP软g包有着很大差异?a mce_href="/blog/542622">http://canonical.javaeye.com/blog/542622</a> AOP的具体技术内容包括定位和l装两个部分。简化切点定位方式和重新规划l装I间Q是Witrix中有效用AOP技术的前提?br />     在Witrixq_中,对于AOP技术的一U具体应用是支持产品的二ơ开发。在产品的实施过E中Q经帔R要根据客L特定需求,修改某些函数的实现。我? 可以选择在主版本代码中不断追加相互纠~的if-else语句Q试囑֎包容所有已知和未知的应用场景。我们也可以选择ȝ本代码和定制代码独立开发的? 式,ȝ本代码实现逻辑框架Q定制代码通过AOP机制与主版本代码融合Q根据具体场景要求对ȝ本功能进行修正。AOP的这U应用与所谓的横切概念是有所 区别的。典型的Q一个横切的切点会涉及到很多cȝ很多ҎQ而函数定制则往往要求准确定位到某个业务对象的某个特定的业务方法上。传lAOP技术的切点? 义方式ƈ不适合q种_的单点定位。在Witrixq_中,我们通过直接的名U映来定义切点。例如,修正spring中注册的MyObject对象? myFuncҎQ可以在app.aop.xml文g中增加如下标{?br /> </p> <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: #0000ff;"><</span><span style="color: #800000;">myObject</span><span style="color: #ff0000;">.myFunc</span><span style="color: #0000ff;">></span><span style="color: #000000;"><br />       在原函数执行之前执行<br />       </span><span style="color: #0000ff;"><</span><span style="color: #800000;">aop:Proceed</span><span style="color: #0000ff;">/></span><span style="color: #000000;"> </span><span style="color: #008000;"><!--</span><span style="color: #008000;"> 执行原函数内?nbsp;</span><span style="color: #008000;">--></span><span style="color: #000000;"><br />       在原函数执行之后执行<br /> </span><span style="color: #0000ff;"></</span><span style="color: #800000;">myObject.myFunc</span><span style="color: #0000ff;">></span><span style="color: #000000;"><br /> <br /> </span></div> <br /> <p> [spring对象?Ҏ名]q种映射Ҏ比基于正则字W串匚w的方式要单明的多。spring容器本n已经实现了对象的全局理功能Qspring对象名称必然是唯一的,公开发布的,怺之间不冲H的Q没有必要再通过匚wq算重新发现出它的唯一性?br />    对于一些确实存在的横切需求,我们可以通过Annotation机制来实现切点坐标标定,复杂的切点匚w问题重新划归为[对象?Ҏ名]?br /> </p> <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: #000000;">@AopClass({"myObject","otherObject"})<br />   class SomeClass{<br />      @AopMethod({"myFunc","otherFunc"})<br />      void someFunc(){}<br />   }<br /> <br /> </span></div>   <p>针对以上对象Q在app.aop.xml文g中可以定?/p> <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: #0000ff;"><</span><span style="color: #800000;">I-myObject</span><span style="color: #ff0000;">.I-myFunc</span><span style="color: #0000ff;">></span><span style="color: #000000;"><br />    <img src="http://www.tkk7.com/Images/dot.gif" alt="" />.<br /> </span><span style="color: #0000ff;"></</span><span style="color: #800000;">I-myObject.I-myFunc</span><span style="color: #0000ff;">></span><span style="color: #000000;"><br /> <br /> </span></div> <img src ="http://www.tkk7.com/canonical/aggbug/305770.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/canonical/" target="_blank">canonical</a> 2009-12-13 11:34 <a href="http://www.tkk7.com/canonical/archive/2009/12/13/305770.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>l构的稳定?/title><link>http://www.tkk7.com/canonical/archive/2009/12/06/304906.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Sun, 06 Dec 2009 04:23:00 GMT</pubDate><guid>http://www.tkk7.com/canonical/archive/2009/12/06/304906.html</guid><wfw:comment>http://www.tkk7.com/canonical/comments/304906.html</wfw:comment><comments>http://www.tkk7.com/canonical/archive/2009/12/06/304906.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/canonical/comments/commentRss/304906.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/canonical/services/trackbacks/304906.html</trackback:ping><description><![CDATA[   l构的稳定性,直观的理解v来,是l构在存在外部扰动的情况下长旉保持某种形式不变性的能力。稳定意味着的扰动造成的后果也?#8220;?#8221;的。在数学中,TaylorU数为我们描l了变化传播的基本图景?br /> <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: #000000;">F(x0 </span><span style="color: #000000;">+</span><span style="color: #000000;"> dx) </span><span style="color: #000000;">=</span><span style="color: #000000;"> F(x0) </span><span style="color: #000000;">+</span><span style="color: #000000;"> F</span><span style="color: #000000;">'</span><span style="color: #000000;">(x0)*dx + 0.5*F</span><span style="color: #000000;">''</span><span style="color: #000000;">(x0)*dx^2 + <img src="http://www.tkk7.com/Images/dot.gif" alt="" /></span></div> <br /> 扰动dx可能在系lF中引发非常复杂的作用q程Q在pȝ各处产生一个个局部变化结果。表面上看v来,gq些变化l果存在着无穷多种可能的分l方式,例如 (F'(x0)-2)*dx + 2*dx^2, 但是Z微分分析Q我们却很容易了解到TaylorU数的每一U都对应着独立的物理解释,它们构成自然的分l标准。某一量下的所有变化汇dq到一Pq对应一个明的整体描述。在抽象的数理空间中Q我们具有一U无所不达的变化搜集能力。变化项可以从基l构中分d来,l过汇d可以对其q行独立的研I。变化本wƈ不会直接D基础l构的崩溃?br />    在Y件徏模领域,模型的稳定性面临的却是另一番场景。一个Y件模型一旦被实现之后Q种U局部需求变更就都会形成对原有基l构的冲凅R一些局部的需求变化可能造成大片原有实现失效Q我们将被迫为类似的需求重新编写类似的代码。此Ӟ软g开发ƈ不像是一U纯_的信息创造,而是宛若某种物质产品的生产(参见从编写代码到刉代?<a >http://canonical.javaeye.com/blog/333167</a> Q。显Ӟ我们需要一U能力,局部变化从基础l构中剥d来,l过汇dq之后再q行l合分析和处理。这正是AOP(Aspect Oriented Programming)技术的价值所在?br /> <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: #000000;">M1 </span><span style="color: #000000;">=</span><span style="color: #000000;"> (G0</span><span style="color: #000000;">+</span><span style="color: #000000;">dG0)</span><span style="color: #000000;"><</span><span style="color: #000000;">M0</span><span style="color: #000000;">+</span><span style="color: #000000;">dM0</span><span style="color: #000000;">></span><span style="color: #000000;"> </span><span style="color: #000000;">==></span><span style="color: #000000;"> M1 </span><span style="color: #000000;">=</span><span style="color: #000000;"> G0</span><span style="color: #000000;"><</span><span style="color: #000000;">M0</span><span style="color: #000000;">></span><span style="color: #000000;"> </span><span style="color: #000000;">+</span><span style="color: #000000;"> dM</span></div>   AOP本质上是软gl构I间的自׃正机制。只有结合AOP技术之后,软g模型才能够重新恢复抽象的本质Q在旉之河中逃离随机变化的R蚀Q保持实现层面的E_性。在q一背景下,建模的目的将不是Z能够跟踪最l需求的变动Q而是要在某个独立的层面上能够自圆其说Q能够具有某U独立存在的完满性,成ؓ思维上可以把握的某个E_的基炏V模型的真实性将因ؓ自nl构的完备性而得到证明,与外部世界的契合E度不再是h值判断的唯一标准?a >http://canonical.javaeye.com/blog/482620</a><br /> <br /> <img src ="http://www.tkk7.com/canonical/aggbug/304906.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/canonical/" target="_blank">canonical</a> 2009-12-06 12:23 <a href="http://www.tkk7.com/canonical/archive/2009/12/06/304906.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>l构的自x?/title><link>http://www.tkk7.com/canonical/archive/2009/10/07/297381.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Wed, 07 Oct 2009 09:10:00 GMT</pubDate><guid>http://www.tkk7.com/canonical/archive/2009/10/07/297381.html</guid><wfw:comment>http://www.tkk7.com/canonical/comments/297381.html</wfw:comment><comments>http://www.tkk7.com/canonical/archive/2009/10/07/297381.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/canonical/comments/commentRss/297381.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/canonical/services/trackbacks/297381.html</trackback:ping><description><![CDATA[   说到软g建模Q一个常见的是模型应该符合实际需求,反映问题的本质。但是何谓本质,却是没有先验定义的。在成功的徏立一个模型之前,无论在内涵上q是在外延上我们都很难说清楚一个问题的本质是什么。如果将模型看作是对领域l构的一U显式描q和表达Q我们可以首先考察一下一?#8220;合?#8221;的结构应该具备哪些特征?br />    按照l构M哲学的观点,l构h三个要素Q整体性,h转换规律或法则(转换性)Q自w调整性(自律性)。整体性意味着l构不能被简单的切分Q其构成要素通过内在的关p运实现大范围的关联与转换Q整体之所以成为整体正是以转换/q算的第一性ؓ保证的。这U{换可以是共时的(同时存在的各元素Q,也可以是历时的(历史的{换构造过E)Q这意味着l构总要求一个内在的构造过E,在独立于外部环境的情况下l构h某种自给自的特性,不依赖于外部条g卛_独立的存在ƈ保持内在的活动。自律性意味着l构内在的{换Ll持着某种闭性和守恒性,保新的成分在无限地构成而结构边界却保持E_。注意到q里对结构的评判q不是来自外在规范和U束Q而是Zl构内在的规律性,所的不是结构对外部条g的适应性,而是自n概念体系的完备性。实际上Q一个无法直接对应于当前实际环境的结构仍然可能具有重要的价|q在解决问题的过E中扮演不可或缺的角艌Ӏ在合理性这个视角下Q我们所x的不仅仅是当前的现实世界Q而是所有可能的世界。一?#8220;合理”的结构的价值必能在它所适应的世界中凸现出来?br />    在信息系l中Q我们可能经怼问这个模型是否是对业务的准确描述Q是否可以适应需求的变更Q是否允许未来的各种扩展{等。但是如果换一个思维方向Q我们会发现q些问题都是针对最l确立的模型而发问的Q而在模型构徏的过E中Q那些可被利用的已存在的或者可以存在的模型又是哪些呢。每一个信息模型都对应着某种自动推理机,可以接收信息q做一定的推导l合工作。一个可行的问题是,如何才能更有效的利用已有的信息进行推|如何消除冗余q减各U{换成本。我们经常可以观察到Q某一信息l织方式更充分的发掘了信息之间的内在兌Q一个表象是它对信息的用不是简单的局域化的,而是在多处呈Cؓ互相U缠的方式,难以被分解)Q这U内在关联够丰富,以至于我们不依赖于外部因素就可以独立的理解。这U纠~在一L信息块自然会成ؓ我们建模的对象?br />    如果模型?#8220;覆盖能力”不再是我们关注的重点Q那么徏模的思维囑ּ会发生如下的{?br /> <div align="center"><img src="http://www.tkk7.com/images/blogjava_net/canonical/MicroModel.jpg" alt="" border="0" /></div> <br /> <br /> 最l的模型可以׃pd微模型交l构成。模型的递进构造过Eƈ不同于组?Component)的实物组装接口,也不是CAD囄堆叠式的架构概念所能容U的。在Witrixq_中,模型分解和构造表达ؓ如下形式  <a >http://canonical.javaeye.com/blog/333167</a><br />      Biz[n] = Biz[n+1] aop-extends CodeGenerator<DSLx, DSLy>?br />    在Y件发展的早期Q所有的E序都是Ҏ构造的Q其必然的假设是【在此情况下】,重用不在考虑范围之内Q开发可以说是一个盲目试错的q程。随着我们逐步U篏了一些经验,开始自觉的应用理论分析手段Q【在所有情况下】都成立的一些普适的原理被揭C出来,它们成ؓ我们在广阔的未知世界中跋涉时的向对{当我们的qҎ渐接q领域的边界Q对领域的全貌有一个M的认知之后,一U对自n成熟性的自信很自然的我们导向更加领域特定的分析。很多时候,我们会发C个特化假讑֏以大大提高信息的利用率,推导Z多未被显式设定的知识。我们需要那些【在某些情况下】有效的规则来构成一个完备的模型库。这如同有大量备选的数学定理Q面对不同的物理现象Q我们会从一pd的数学工具中选择一个进行用一栗?br />    <br /> <br /> <br /> <img src ="http://www.tkk7.com/canonical/aggbug/297381.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/canonical/" target="_blank">canonical</a> 2009-10-07 17:10 <a href="http://www.tkk7.com/canonical/archive/2009/10/07/297381.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>行ؓ聚集http://www.tkk7.com/canonical/archive/2009/07/11/286397.htmlcanonicalcanonicalSat, 11 Jul 2009 13:37:00 GMThttp://www.tkk7.com/canonical/archive/2009/07/11/286397.htmlhttp://www.tkk7.com/canonical/comments/286397.htmlhttp://www.tkk7.com/canonical/archive/2009/07/11/286397.html#Feedback0http://www.tkk7.com/canonical/comments/commentRss/286397.htmlhttp://www.tkk7.com/canonical/services/trackbacks/286397.html   A1 --> B2,  A2 --> B2,  A3 --> B3 ...
我们观察到A1和A2之间, B2和B2之间h某种概念兌? 同时存在某种抽象l构 [A] --> [B].
对于q种情况, 我们可以定义对象 [A], [B], 它们分别?A1和A2的聚? B1和B2的聚合等. 举例来说, 对于如下表格描述, <ui:Col>所提供的信息在映射为html实现的时候将在多处被应用.
<ui:Table data="${data}">
  <ui:Col name="fieldA" label="labelA" width="20" />
  <ui:Col name="fieldB" label="labelB" width="10" /> 
</ui:Table>
q里<ui:Col>提供的信息对应三个部分的内容: 1. 列标?2. 列样?宽度{?  3. 列数?br />
面向对象的常见做法是抽象?UiCol对象, 它作为UiTable对象的属性存? 在生成表? 表列样式和表格数据内Ҏ被使用. 但是我们注意到面向对象要求多个方法通过this指针形成状态耦合

Q在某种意义上它意味着所有的成员Ҏ在Q一时刻都是同时存在着的。它们所代表着的存在的代h必须被接受(存储I间{)。即使ƈ不同时被使用Q我们仍焉要同时持有所有成员函数指针及

׃n的this指针。实际上, 我们q不一定需要A1和A2同时在场. 在这U情况下, ~译期技术可以提供另一U不同的行ؓ聚合方式.


<table>
  <thead>
    <sys:CompileTagBody cp:part="thead" />
  </thead>
  <cols>
    <sys:CompileTagBody cp:part="cols" />
  </cols>
  <tbody>
    <sys:CompileTagBody cp:part="tbody" />
  </tbody>
</table>

只要<ui:Col>标签的实C针对~译期的cp:part变量q行分别处理, 卛_实现信息的部分析?




canonical 2009-07-11 21:37 发表评论
]]>
վ֩ģ壺 㽶ѿƬƵapp| ƵѲ| 91޾Ʒһۺϲ| Ұ߹ۿ | ޹Ʒһþ| ƬAVƬѹۿ| avվ| AVþƷ鵺̳| ȫӰѹۿȫ| ssswwwձվƬ| videos| ޾ƷMV߹ۿ| ԲaëƬ| ߵƵ߹ۿ| þþþ޹| պvavaŷva| ŮƵվ| ϼ˳߹ۿƵ| ëƬ쿴| ëƬѹۿ| ޾ƷҹVAþó| Ʒۺ| 1000Ƶ| Ʒվ| ĻĻɫ| þԭAV鶹| Ѵ߹ | ѹۿһ| aһƵ| 鶹69Ƶ| ĻAVJI| ޹Ʒ߹ۿ | һaƬþëƬ| AAƬٸAAƬֱ| APPѹۿƵ| ݾ߹ۿվ| ɫAVպ߹ۿ| һҹ| þ޾Ʒ| ޳aƬ߹ۿ| ޹Ʒ۲ӰԺþ |