﻿<?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-canonical-随笔分类-设计理论</title><link>http://www.blogjava.net/canonical/category/4849.html</link><description /><language>zh-cn</language><lastBuildDate>Sun, 08 May 2011 22:31:23 GMT</lastBuildDate><pubDate>Sun, 08 May 2011 22:31:23 GMT</pubDate><ttl>60</ttl><item><title>从面向对象到面向切面</title><link>http://www.blogjava.net/canonical/archive/2011/05/08/349771.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Sun, 08 May 2011 04:07:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2011/05/08/349771.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/349771.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2011/05/08/349771.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/349771.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/349771.html</trackback:ping><description><![CDATA[1. C语言抽象出了软件所在的领域(domain): 由变量v1,v2,...和函数f1,f2,...组成的空间<br />
<br />
2. 面向对象(OOP)指出，在这一领域上可以建立分组(group)结构：一组相关的变量和函数构成一个集合，我们称之为对象(Object)。同时在分组结构上可以定义一个运算(推理)关系:&nbsp; D &gt; B, 派生类D从基类B继承（inheritance)，相应的派生对象符合基类对象所满足的所有约束。推理是有价值的，因为根据 D &gt; B, B &gt; A 可以自动推导出 D &gt; A，所有针对A的断言在理论上对D都成立(这也就是我们常说的&#8220;派生对象 is a 基类对象&#8221;)。编译器也能有点智能了。<br />
&nbsp;&nbsp; 一个有趣的地方是，D &gt; B意味着在D和B之间存在着某种差异，但是我们却无法把它显式的表达出来！也就是说在代码层面上我们无法明确表达 D - B是什么。为了把更多的信息不断的导入到原有系统中，面向对象内置提供的方法是建立不断扩展的类型树，类型树每增长一层，就可以多容纳一些新的信息。这是一种金字塔式的结构，只不过是一种倒立的金字塔，最终基点会被不断增长的结构压力所压垮。<br />
<br />
3. 组件技术(Component)本质上是在提倡面向接口(interface)，然后通过接口之间的组合(Composition)而不是对象之间的继承(inheritance)来构造系统。基于组合的观念相当于是定义了运算关系：D = B + C。终于，我们勉强可以在概念层面上做加法了。<br />
&nbsp;&nbsp; 组件允许我们随意的组合，按照由简单到复杂的方向构造系统，但是组件构成的成品之间仍然无法自由的建立关系。这意味着组件组装得到的成品只是某种孤立的，偶然的产物。<br />
&nbsp;&nbsp; F = A + B + C&nbsp; ? G = A + D + C。<br />
<br />
4. 在数学上，配备了加法运算的集合构成半群，如果要成为群(Group)，则必须定义相应的逆运算：减法。 群结构使得大粒度的结构变换成为可能。<br />
&nbsp;&nbsp; F = A + B + C = A + D - D + B + C = (A + D + C) - D + B = G - D + B<br />
&nbsp;&nbsp; 在不破坏原有代码的情况下，对原有系统功能进行增删，这就是面向切面(AOP)技术的全部价值。<br />
<br />
<br />
<img src ="http://www.blogjava.net/canonical/aggbug/349771.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2011-05-08 12:07 <a href="http://www.blogjava.net/canonical/archive/2011/05/08/349771.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>业务架构平台的自举问题</title><link>http://www.blogjava.net/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.blogjava.net/canonical/archive/2011/02/11/344053.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/344053.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2011/02/11/344053.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/344053.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/344053.html</trackback:ping><description><![CDATA[&nbsp;&nbsp; 业务架构平台的设计与实现要比普通业务系统困难很多。一个核心难点在于如何建立普遍有效的应用程序模型，如何控制各种偶然性的业务需求对系统整体架构的冲击。大多数现有的业务架构平台都是提供了一个庞大的万能性产品，它预料到了所有可能在业务系统开发中出现的可能性，并提供了相应的处理手段。业务系统开发人员的能力被限定在业务架构平台所允许的范围之内。如果业务架构平台的复杂度为A+，则我们最多只能用它来开发复杂度为A的业务系统。一个典型的特征就是使用业务架构平台的功能配置非常简单，但是要开发相应的功能特性则非常困难，而且必须采用与业务系统开发完全不同的技术手段和开发方式。<br />
&nbsp;&nbsp; 采用业务架构平台来开发业务系统，即使看似开发工作量小，最终产生的各类配置代码量也可能会大大超过普通手工编程产生的代码量，这意味着平台封装了业务内在的复杂性，还是意味着平台引入了不必要的复杂性？很多业务架构平台的卖点都是零代码的应用开发，低水平的开发人员也可以主导的开发，但是为什么高水平的程序员不能借助于这些开发平台极大的提高生产率？<br />
&nbsp;&nbsp; 一般的业务架构平台无法回答以下问题：<br />
1) 业务系统可以通过使用设计工具来重用业务架构平台已经实现的功能，但是业务系统内部大量相似的模型配置如何才能够被重用？<br />
2) 特定的业务领域中存在着大量特殊的业务规则，例如&#8220;审批串行进行，每一步都允许回退到上一步，而且允许选择跳转到任意后一步&#8221;。这些规则如何才能够被引入设计工具，简化配置过程？<br />
3) 已经开发好的业务系统作为产品来销售的时候，如何应对具体客户的定制化？如果按照客户要求修改配置，则以后业务系统自身是否还能够实现版本升级？<br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp; Witrix平台提供的基本开发模型为 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>App = Biz aop-extends Generator&lt;DSL&gt;</strong><br />
在这一图景下，我们就可以回答以上三个问题：<br />
1) 业务模型通过领域特定语言(DSL)来表达，因此可以使用语言中通用的继承或者组件抽象机制来实现模型重用。<br />
2) 推理机对于所有推理规则一视同仁，特殊的业务规则与通用的业务规则一样都可以参与推理过程，并且一般情况下特殊的业务规则更能够大幅简化系统实现结构。<br />
3) 相对于原始模型的修改被独立出来，然后应用面向切面(AOP)技术将这些特定代码织入到原始模型中。原始模型与差异修改相互分离，因此原始模型可以随时升级。<br />
<br />
&nbsp; Witrix平台所强调的不是强大的功能，而是一切表象之后的数学规律。Witrix平台通过少数基本原理的反复应用来构造软件系统，它本身就是采用平台技术构造的产物。我们用复杂度为A的工具制造复杂度为A+的产品，然后进一步以这个复杂度为A+的产品为工具来构造复杂度为A++的产品。<br />
<br />
<img src ="http://www.blogjava.net/canonical/aggbug/344053.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2011-02-11 14:02 <a href="http://www.blogjava.net/canonical/archive/2011/02/11/344053.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>模型驱动的数学原理</title><link>http://www.blogjava.net/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.blogjava.net/canonical/archive/2011/02/07/343919.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/343919.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2011/02/07/343919.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/343919.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/343919.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;
一种技术思想如果确实能够简化编程，有效降低系统构造的复杂性，那么它必然具有某种内在的数学解释。反之，无论一种技术机制显得如何华丽高深，如果它没有
清晰的数学图象，那么就很难证明自身存在的价值。对于模型驱动架构(MDA)，我长期以来一直都持有一种批判态度。（Physical Model
Driven<a href="http://canonical.javaeye.com/blog/29412"> http://canonical.javaeye.com/blog/29412</a>
）。原因就在于&#8220;由工具自动实现从平台无关模型(PIM)向平台相关模型(PSM)的转换&#8221;这一图景似乎只是想把系统从实现的泥沼中拯救出来，遮蔽特定语
言，特定平台中的偶然的限制条件，并没有触及到系统复杂性这一核心问题。而所谓的可视化建模充其量不过是说明人类超强的视觉模式识别能力使得我们可以迅速
识别系统全景图中隐含的整体结构，更快的实现对系统结构的理解，并没有证明系统复杂性有任何本质性的降低。不过如果我们换一个视角,
不把模型局限为某种可视化的结构图,而将它定义为某种高度浓缩的领域描述,
则模型驱动基本上等价于根据领域描述自动推导得到最终的应用程序。沿着这一思路，Witrix平台中的很多设计实际上可以被解释为模型定义，模型推导以及
模型嵌入等方面的探索。这些具体技术的背后需要的是比一般MDA思想更加精致的设计原理作为支撑。我们可以进行如下抽象分析。（Witrix架构分析 <a href="http://canonical.javaeye.com/blog/126467">http://canonical.javaeye.com/blog/126467</a>
）<br />
<br />
1. 问题复杂？线性切分是削减问题规模（从而降低问题复杂性）的通用手段，例如模块(Module)。（软件中的分析学 <a href="http://canonical.javaeye.com/blog/33885">http://canonical.javaeye.com/blog/33885</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&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;M1&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;M2&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;M3&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />&nbsp;&nbsp;&nbsp; <br />
</span></div>
<p><br />
</p>
<p>2. 分块过多？同态映射是系统约化的一般化策略，例如多态（polymorphism）。（同构与同态：认识同一性 <a href="http://canonical.javaeye.com/admin/blogs/340704">http://canonical.javaeye.com/admin/blogs/340704</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;">(abc,abb,ade,<img src="http://www.blogjava.net/Images/dot.gif" alt="" />)&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;[a],&nbsp;&nbsp;&nbsp;(bbb,&nbsp;bcd,bab,<img src="http://www.blogjava.net/Images/dot.gif" alt="" />)&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;[b]</span></div>
<p><br />
</p>
<p>3. 递归使用以上两种方法，将分分合合的游戏进行到底，推向极致。<br />
<br />
4. 以少控多的终极形态？如果存在，则构成输入与输出之间的非线性变换（输入中局部微小变化将导致输出中大范围明显的变化）。</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&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;F(M)</span></div>
<p><br />
</p>
<p>5.
变换函数F可以被诠释为解释器(Interpreter)或者翻译机，例如工作流引擎将工作流描述信息翻译为一步步的具体操作，工作流描述可以看作是由底
层引擎支撑的，在更高的抽象层面上运行的领域模型。但是在这种观点下，变换函数F似乎是针对某种特定模型构造的，引擎内部信息传导的途径是确定的，关注的
重点始终在模型上，那么解释器自身应该如何被构造出来呢？</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&nbsp;</span><span style="color: #000000;">~</span><span style="color: #000000;">&nbsp;M</span></div>
<p><br />
</p>
<p>6.
另外一种更加开放的观点是将变换函数F看作是生成器(Generator)或者推理机。F将根据输入的信息，结合其他知识，推理生成一系列新的命题和断
言。模型的力量源于推导。变换函数F本身在系统构造过程中处于核心地位，M仅仅是触发其推理过程的信息源而已。F将榨干M的最后一点剩余价值，所有根据M
能够确定的事实将被自动实现，而大量单靠M自身的信息无法判定的命题也可以结合F内在的知识作出判断。生成器自身的构造过程非常简单--只要不断向推理系
统中增加新的推理规则即可。语言内置的模板机制(template)及元编程技术(meta
programming)，或者跨越语言边界的代码生成工具都可以看作是生成器的具体实例。（关于代码生成和DSL <a href="http://canonical.javaeye.com/blog/275015">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&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;G</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">M</span><span style="color: #000000;">&gt;</span></div>
<p><br />
</p>
<p>7. 生成器G之所以可以被独立实现，是因为我们可以实现相对知识与绝对知识的分离, 这也正是面向对象技术的本质所在。（面向对象之形式系统 <a href="http://canonical.javaeye.com/blog/37064">http://canonical.javaeye.com/blog/37064</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;">G</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">M</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">==&gt;</span><span style="color: #000000;">&nbsp;G&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;{m&nbsp;</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">&nbsp;m.x(a,b,c);m.y();&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />&nbsp;}</span></div>
<p><br />
</p>
<p>8.
现实世界的不完美，就在于现实决不按照我们为其指定的理想路线前进。具体场景中总是存在着大量我们无法预知的&#8220;噪声&#8221;，它们使得任何在&#8220;过去&#8221;确立的方程
都无法在&#8220;未来&#8221;保持持久的平衡。传统模型驱动架构的困境就在于此。我们可以选择将模型M和生成器G不断复杂化，容纳越来越多的偶然性，直至失去对模型整
体结构的控制力。另外一种选择是模型在不断膨胀，不断提高覆盖能力的过程中，不断的空洞化，产生大量可插入(plugin)的接入点，最终丧失模型的推理
能力，退化成为一种编码规范。Witrix平台中采用的是第三种选择：模型嵌入--模型中的多余信息被不断清洗掉，模型通过精炼化来突出自身存在的合理
性，成为更广泛的运行环境中的支撑骨架。（结构的自足性 <a href="http://canonical.javaeye.com/blog/482620">http://canonical.javaeye.com/blog/482620</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&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;G0</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">M0</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;&nbsp;，&nbsp;App&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;G0</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">M1</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">，&nbsp;App&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;G1</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">M1</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> <br />
</span></div>
<p><br />
</p>
<p>9.
现在的问题是：如何基于一个已经被完美解决的重大问题，来更有效率的搞定不断出现但又不是重复出现的小问题。现在我们所需要的不是沿着某个维度进行均匀的
切分，而必须是某种有效的降维手段。如果我们可以定义一种投影算子P,
将待解决的问题投射到已经被解决的问题域中，则剩下的补集往往可以被简化。（主从分解而不是正交分解 <a href="http://canonical.javaeye.com/blog/196826">http://canonical.javaeye.com/blog/196826</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;">dA&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;App&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;P[App]&nbsp;&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;App&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;G0</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">M0</span><span style="color: #000000;">&gt;</span></div>
<p><br />
</p>
<p>10. 要实现以上微扰分析策略，前提条件是可以定义逆元，并且需要定义一种精细的粘结操作，可以将分散的扰动量极为精确的应用到基础系统的各处。Witrix平台的具体实现类似于某种AOP（面向切面编程）技术。（逆元：不存在的真实存在 <a href="http://canonical.javaeye.com/blog/325051">http://canonical.javaeye.com/blog/325051</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&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;A&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;D&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;B&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(A&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;B&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;C)&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;C&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;D&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;App0&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">-</span><span style="color: #000000;">C&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;D)&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;G0</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">M0</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;dA</span></div>
<p><br />
</p>
<p>11. 模型驱动并不意味着一个应用只能由唯一的一个模型来驱动，但是如果引入多个不同形式的模型，则必须为如下推理提供具体的技术路径：<br />
&nbsp; A. 将多个模型变换到共同的描述域 <br />
&nbsp; B. 实现多个模型的加和 <br />
&nbsp; C. 处理模型之间的冲突并填补模型之间的空白<br />
在Witrix平台中模型嵌入/组合主要依赖于文本化及编译期运行等机制。（文本化 <a href="http://canonical.javaeye.com/blog/309395">http://canonical.javaeye.com/blog/309395</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&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Ga</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Ma</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;Gb</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Mb</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;dA</span></div>
<p><br />
</p>
<p>12.
系统的开发时刻t0和实施时刻t1一般是明确分离的，因此如果我们要建立一个包含开发与实施时刻信息的模型，则这一模型必须是含时的，多阶段的。关于时
间，我们所知道的最重要的事实之一是&#8220;未来是不可预知的&#8221;。在t0时刻建立的模型如果要涵盖t1时刻的所有变化，则必须做出大量猜测，而且t1时刻距离
t0时刻越远，猜测的量越大，&#8220;猜测有效&#8221;这一集合的测度越小，直至为0。延迟选择是实现含时系统控制的不二法门。<br />
&nbsp;&nbsp;
在Witrix平台中，所有功能特性的实现都包含某种元数据描述或者定制模板，因此结合配置机制以及动态编译技术既可实现多阶段模型。例如对于一个在未来
才能确定的常量数组，我们可以定义一个Excel文件来允许实施人员录入具体的值，然后通过动态编译技术在编译期解析Excel文件，并完成一系列数值映
射运算，最终将其转化为编译期存在的一个常量。这一过程不会引入任何额外的运行成本，也不要求任何特定的缓存机制，最终的运行结构与在未来当所有信息都在
位之后再手写代码没有任何区别。（D语言与tpl之编译期动作 <a href="http://canonical.javaeye.com/blog/57244">http://canonical.javaeye.com/blog/57244</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(t1)&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;G(t0,t1)</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">M(t0,t1)</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;dA(t0,t1)</span></div>
<p><br />
</p>
<p>13. 级列理论提供了一个演化框架，它指出孤立的模型必须被放在模型级列中被定义，被解释。（关于级列设计理论 <a href="http://canonical.javaeye.com/blog/33824">http://canonical.javaeye.com/blog/33824</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;">M[n]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;G</span><span style="color: #000000;">&lt;</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;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;dMn</span></div>
<p><br />
</p>
<p>14.
推理的链条会因为任何局部反例的出现而中断。在任意时空点上，我们能够断言的事实有哪些？信息越少，我们能够确定的事实越少，能够做出的推论也就越少。现
在流行的很多设计实质上是在破坏系统的对称性，破坏系统大范围的结构。比如明明ORM容器已经实现所有数据对象的统一管理，非要将其拆分为每个业务表一个
的DAO接口。很多对灵活性的追求完全没有搞清楚信息是对不确定性的消除，而不确定性的减少意味着限制的增加，约束的增加。（From Local To
Global <a href="http://canonical.javaeye.com/blog/42874">http://canonical.javaeye.com/blog/42874</a>
）<br />
<br />
&nbsp;&nbsp;
组件/构件技术的宣言是生产即组装，但是组装有成本，有后遗症（例如需要额外的胶水或者螺钉）。软件的本质并不是物质，而是信息，而信息的本质是抽象的规
律。在抽象世界中最有效的生产方式是抽象的运算，运算即生产。组件式开发意味着服从现有规律，熟练应用，而原理性生产则意味着不断创造新的规律。功能模
块越多，维护的成本越高，是负担，而推理机制越多，生产的成本越低，是财富。只有恢复软件的抽象性，明确把握软件构造过程内在的数学原理，才能真正释放软
件研发的生产力。（从编写代码到制造代码 <a href="http://canonical.javaeye.com/blog/333167">http://canonical.javaeye.com/blog/333167</a>
）<br />
</p>
<p><br />
</p>
<p>注解1：很多设计原则其实是在强调软件由人构造由人理解，软件开发本质上是人类工程学，需要关注人类的理解力与协作能力。例如共同的建模语言减少交互成本，基于模型减少设计与实现的分离，易读的代码比高性能的代码更重要，做一件事只有唯一的一种方式等。<br />
<br />
注解2：生成系统的演绎远比我们想象的要深刻与复杂得多。例如生命的成长可以被看作是在外界反馈下不断调整的生成过程。<br />
<br />
注解3：领域描述是更紧致但却未必是更本质的表达。人类的DNA如果表达为ATGC序列完全可以拷贝到U盘中带走，只要对DNA做少量增删，就可以实现老
鼠到人类的变换（人类和老鼠都有大约30000条基因，其中约有80%的基因是&#8220;完全一样的&#8221;，大约共享有99%的类似基因），但是很难认为人类所有智慧
的本质都体现在DNA中，DNA看起来更像是某种序列化保存形式而已。<br />
<br />
注解4：模型转换这一提法似乎是在强调模型之间的同构对应，转换似乎总是可以双向进行的，仅仅是实现难度限制了反向转换而已。但是大量有用的模型变换却是单向的，变换过程要求不断补充新的信息。<br />
<br />
注解5：模型驱动在很多人看来就是数据库模型或者对象模型驱动系统界面运行，但实际上模型可以意指任意抽象知识。虽然在目前业内广泛流行的对象范式下，所
有知识都可以表达为对象之间的关联，但是对象关系（名词之间的关联关系）对运算结构的揭示是远远不够充分的。很多时候所谓的领域模型仅仅是表明概念之间具
有相关性，但是如果不补充一大段文字说明，我们对于系统如何运作仍然一知半解。数学分析其实是将领域内在的意义抽空，仅余下通用的形式化符号。<br />
</p>
<img src ="http://www.blogjava.net/canonical/aggbug/343919.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2011-02-07 02:56 <a href="http://www.blogjava.net/canonical/archive/2011/02/07/343919.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>结构的稳定性</title><link>http://www.blogjava.net/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.blogjava.net/canonical/archive/2009/12/06/304906.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/304906.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2009/12/06/304906.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/304906.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/304906.html</trackback:ping><description><![CDATA[&nbsp;&nbsp; 结构的稳定性，直观的理解起来，就是结构在存在外部扰动的情况下长时间保持某种形式不变性的能力。稳定意味着小的扰动造成的后果也是&#8220;小&#8221;的。在数学中，Taylor级数为我们描绘了变化传播的基本图景。<br />
<br />
&nbsp;<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&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;dx)&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;F(x0)&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;F</span><span style="color: #000000;">'</span><span style="color: #000000;">(x0)*dx&nbsp;+&nbsp;0.5*F</span><span style="color: #000000;">''</span><span style="color: #000000;">(x0)*dx^2&nbsp;+&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span></div>
<br />
扰动dx可能在系统F中引发非常复杂的作用过程，在系统各处产生一个个局部变化结果。表面上看起来，似乎这些变化结果存在着无穷多种可能的分组方式，例如 (F'(x0)-2)*dx + 2*dx^2, 但是基于微分分析，我们却很容易了解到Taylor级数的每一级都对应着独立的物理解释，它们构成自然的分组标准。某一量级下的所有变化汇总归并到一起，并对应一个明确的整体描述。在抽象的数理空间中，我们具有一种无所不达的变化搜集能力。变化项可以从基础结构中分离出来，经过汇总后可以对其进行独立的研究。变化本身并不会直接导致基础结构的崩溃。<br />
&nbsp;&nbsp; 在软件建模领域，模型的稳定性面临的却是另一番场景。一个软件模型一旦被实现之后，种种局部需求变更就都会形成对原有基础结构的冲击。一些局部的需求变化可能造成大片原有实现失效，我们将被迫为类似的需求重新编写类似的代码。此时，软件开发并不像是一种纯粹的信息创造，而是宛若某种物质产品的生产（参见从编写代码到制造代码 <a href="http://canonical.javaeye.com/blog/333167">http://canonical.javaeye.com/blog/333167</a> ）。显然，我们需要一种能力，将局部变化从基础结构中剥离出来，经过汇总归并之后再进行综合分析和处理。这正是AOP(Aspect Oriented Programming)技术的价值所在。<br />
<br />
&nbsp;&nbsp;&nbsp; <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&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(G0</span><span style="color: #000000;">+</span><span style="color: #000000;">dG0)</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">M0</span><span style="color: #000000;">+</span><span style="color: #000000;">dM0</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">==&gt;</span><span style="color: #000000;">&nbsp;M1&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;G0</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">M0</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;dM</span></div>
&nbsp; AOP本质上是软件结构空间的自由修正机制。只有结合AOP技术之后，软件模型才能够重新恢复抽象的本质，在时间之河中逃离随机变化的侵蚀，保持实现层面的稳定性。在这一背景下，建模的目的将不是为了能够跟踪最终需求的变动，而是要在某个独立的层面上能够自圆其说，能够具有某种独立存在的完满性，成为思维上可以把握的某个稳定的基点。模型的真实性将因为自身结构的完备性而得到证明，与外部世界的契合程度不再是价值判断的唯一标准。<a href="http://canonical.javaeye.com/blog/482620">http://canonical.javaeye.com/blog/482620</a><br />
<br />
<img src ="http://www.blogjava.net/canonical/aggbug/304906.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2009-12-06 12:23 <a href="http://www.blogjava.net/canonical/archive/2009/12/06/304906.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>结构的自足性</title><link>http://www.blogjava.net/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.blogjava.net/canonical/archive/2009/10/07/297381.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/297381.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2009/10/07/297381.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/297381.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/297381.html</trackback:ping><description><![CDATA[&nbsp;&nbsp; 说到软件建模，一个常见的论调是模型应该符合实际需求，反映问题的本质。但是何谓本质，却是没有先验定义的。在成功的建立一个模型之前，无论在内涵上还是在外延上我们都很难说清楚一个问题的本质是什么。如果将模型看作是对领域结构的一种显式描述和表达，我们可以首先考察一下一个&#8220;合适&#8221;的结构应该具备哪些特征。<br />
&nbsp;&nbsp; 按照结构主义哲学的观点，结构具有三个要素：整体性，具有转换规律或法则（转换性），自身调整性（自律性）。整体性意味着结构不能被简单的切分，其构成要素通过内在的关系运算实现大范围的关联与转换，整体之所以成为整体正是以转换/运算的第一性为保证的。这种转换可以是共时的（同时存在的各元素），也可以是历时的（历史的转换构造过程），这意味着结构总要求一个内在的构造过程，在独立于外部环境的情况下结构具有某种自给自足的特性，不依赖于外部条件即可独立的存在并保持内在的活动。自律性意味着结构内在的转换总是维持着某种封闭性和守恒性，确保新的成分在无限地构成而结构边界却保持稳定。注意到这里对结构的评判并不是来自外在规范和约束，而是基于结构内在的规律性，所强调的不是结构对外部条件的适应性，而是自身概念体系的完备性。实际上，一个无法直接对应于当前实际环境的结构仍然可能具有重要的价值，并在解决问题的过程中扮演不可或缺的角色。在合理性这个视角下，我们所关注的不仅仅是当前的现实世界，而是所有可能的世界。一个&#8220;合理&#8221;的结构的价值必能在它所适应的世界中凸现出来。<br />
&nbsp;&nbsp; 在信息系统中，我们可能经常会问这个模型是否是对业务的准确描述，是否可以适应需求的变更，是否允许未来的各种扩展等等。但是如果换一个思维方向，我们会发现这些问题都是针对最终确立的模型而发问的，而在模型构建的过程中，那些可被利用的已存在的或者可以存在的模型又是哪些呢。每一个信息模型都对应着某种自动推理机，可以接收信息并做一定的推导综合工作。一个可行的问题是，如何才能更有效的利用已有的信息进行推导，如何消除冗余并减少各种转换成本。我们经常可以观察到，某一信息组织方式更充分的发掘了信息之间的内在关联（一个表象是它对信息的使用不是简单的局域化的，而是在多处呈现为互相纠缠的方式，难以被分解），这种内在关联足够丰富，以至于我们不依赖于外部因素就可以独立的理解。这种纠缠在一起的信息块自然会成为我们建模的对象。<br />
&nbsp;&nbsp; 如果模型的&#8220;覆盖能力&#8221;不再是我们关注的重点，那么建模的思维图式将会发生如下的转化<br />
<div align="center"><img src="http://www.blogjava.net/images/blogjava_net/canonical/MicroModel.jpg" alt="" border="0" /></div>
<br />
<br />
最终的模型可以由一系列微模型交织构成。模型的递进构造过程并不同于组件(Component)的实物组装接口，也不是CAD图纸堆叠式的架构概念所能容纳的。在Witrix平台中，模型分解和构造表达为如下形式&nbsp; <a href="http://canonical.javaeye.com/blog/333167">http://canonical.javaeye.com/blog/333167</a><br />
&nbsp;&nbsp;&nbsp;&nbsp; Biz[n] = Biz[n+1] aop-extends CodeGenerator&lt;DSLx, DSLy&gt;。<br />
&nbsp;&nbsp; 在软件发展的早期，所有的程序都是特殊构造的，其必然的假设是【在此情况下】，重用不在考虑范围之内，开发可以说是一个盲目试错的过程。随着我们逐步积累了一些经验，开始自觉的应用理论分析手段，【在所有情况下】都成立的一些普适的原理被揭示出来，它们成为我们在广阔的未知世界中跋涉时的向导。当我们的足迹渐渐接近领域的边界，对领域的全貌有一个总体的认知之后，一种对自身成熟性的自信很自然的将我们导向更加领域特定的分析。很多时候，我们会发现一个特化假设可以大大提高信息的利用率，推导出众多未被显式设定的知识。我们需要那些【在某些情况下】有效的规则来构成一个完备的模型库。这就如同有大量备选的数学定理，面对不同的物理现象，我们会从一系列的数学工具中选择一个进行使用一样。<br />
&nbsp;&nbsp; <br />
<br />
<br />
<img src ="http://www.blogjava.net/canonical/aggbug/297381.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2009-10-07 17:10 <a href="http://www.blogjava.net/canonical/archive/2009/10/07/297381.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>行为聚集</title><link>http://www.blogjava.net/canonical/archive/2009/07/11/286397.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Sat, 11 Jul 2009 13:37:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2009/07/11/286397.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/286397.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2009/07/11/286397.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/286397.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/286397.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 软件开发技术的技术本质在于对代码结构的有效控制. 我们需要能够有效的分解/重组代码片断, 凸显设计意图. 面向对象是目前最常见的代码组织技术. 典型的, 它可以处理如下模式<br />
&nbsp; A1 --&gt; B2,&nbsp; A2 --&gt; B2,&nbsp; A3 --&gt; B3 ...<br />
我们观察到A1和A2之间, B2和B2之间具有某种概念关联性, 同时存在某种抽象结构 [A] --&gt; [B]. <br />
对于这种情况, 我们可以定义对象 [A], [B], 它们分别是 A1和A2的聚合, B1和B2的聚合等. 举例来说, 对于如下表格描述, &lt;ui:Col&gt;所提供的信息在映射为html实现的时候将在多处被应用. <br />
&lt;ui:Table data="${data}"&gt;<br />
&nbsp; &lt;ui:Col name="fieldA" label="labelA" width="20" /&gt;<br />
&nbsp; &lt;ui:Col name="fieldB" label="labelB" width="10" /&gt;&nbsp; <br />
&lt;/ui:Table&gt;<br />
这里&lt;ui:Col&gt;提供的信息对应三个部分的内容: 1. 列标题 2. 列样式(宽度等)&nbsp; 3. 列数据<br />
<br />
面向对象的常见做法是抽象出 UiCol对象, 它作为UiTable对象的属性存在, 在生成表头, 表列样式和表格数据内容时将被使用. 但是我们注意到面向对象要求多个方法通过this指针形成状态耦合<br />
<br />
，在某种意义上它意味着所有的成员方法在任一时刻都是同时存在着的。它们所代表着的存在的代价必须被接受（存储空间等）。即使并不同时被使用，我们仍然需要同时持有所有成员函数指针及<br />
<br />
共享的this指针。实际上, 我们并不一定需要A1和A2同时在场. 在这种情况下, 编译期技术可以提供另一种不同的行为聚合方式.<br />
<br />
<br />
&lt;table&gt;<br />
&nbsp; &lt;thead&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;sys:CompileTagBody cp:part="thead" /&gt;<br />
&nbsp; &lt;/thead&gt;<br />
&nbsp; &lt;cols&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;sys:CompileTagBody cp:part="cols" /&gt;<br />
&nbsp; &lt;/cols&gt;<br />
&nbsp; &lt;tbody&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;sys:CompileTagBody cp:part="tbody" /&gt;<br />
&nbsp; &lt;/tbody&gt;<br />
&lt;/table&gt;<br />
<br />
只要&lt;ui:Col&gt;标签的实现中针对编译期的cp:part变量进行分别处理, 即可实现信息的部分析取. <br />
<br />
<br />
<img src ="http://www.blogjava.net/canonical/aggbug/286397.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2009-07-11 21:37 <a href="http://www.blogjava.net/canonical/archive/2009/07/11/286397.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>信道构建</title><link>http://www.blogjava.net/canonical/archive/2009/03/22/261352.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Sun, 22 Mar 2009 13:10:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2009/03/22/261352.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/261352.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2009/03/22/261352.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/261352.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/261352.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 分层是最常见的软件架构方式之一。分层之后可以区分出横纵两个维度,纵向往往表现出一种隔离性。出于有意无意的各种原因，层次之间传递信息很容易出现模糊甚至丢失的现象。B/S多层体系架构下的程序因为浏览器和服务器之间的状态空间相互独立，相对于共享全局状态空间的C/S程序，更容易出现信息传递不畅的问题。实际上，我们经常可以观察到B/S程序中存在着大量的"接力"代码，即在交界处，总是存在着大量用于读取变量，拼接变量，转换变量等与主体业务无关但却又不可或缺的代码。在多层架构程序中，信道构建应该是一个需要给予足够重视的问题。<br />
<div align="center"><img src="http://www.blogjava.net/images/blogjava_net/canonical/layer.gif" alt="" border="0" height="238" width="332" /></div>
<br />
&nbsp;&nbsp;&nbsp; 在系统规划中，多层结构应该内置与具体语义无关的通用信道，它跨越多个层次，允许信息透明的通过，并以未预期的方式在不同的层面激发各种相关的行为。在Witrix平台中，平台代码与特定应用中的业务代码处于高度交织的状态，一个特定业务功能的实现往往需要多处业务代码相互协同，平台必须成为某种透明的背景。例如，假设我们编制了一个通用的列表选择控件,它封装的逻辑是从一个实体列表中进行选择<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;app:SelectOne objectName="MyEntity" /&gt;<br />
如果现在要求选择时只列出某个类型的实体，则调用形式为<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;app:SelectOne objectName="MyEntity" extArgs="$bizId=select&amp;amp;$type=1" /&gt;<br />
在调用入口处补充必要的信息之后会推动系统在遥远的状态空间中应用一个特定的过滤条件。这里$bizId负责指示平台应用特定的元数据配置，而其他的参数则由元数据中的逻辑负责处理。平台与特定业务代码各取所需，相互配合，将尽可能多的逻辑剥离为通用机制。<br />
<div align="center"><img src="http://www.blogjava.net/images/blogjava_net/canonical/info.gif" alt="" border="0" height="271" width="276" /></div>
<br />
<br />
<img src ="http://www.blogjava.net/canonical/aggbug/261352.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2009-03-22 21:10 <a href="http://www.blogjava.net/canonical/archive/2009/03/22/261352.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>同构与同态：认识同一性</title><link>http://www.blogjava.net/canonical/archive/2009/02/28/257150.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Sat, 28 Feb 2009 08:57:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2009/02/28/257150.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/257150.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2009/02/28/257150.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/257150.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/257150.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;
现代数学是建立在等价类这一概念的基础之上的。同构是对等价关系的一种刻划。简单的可以把它理解为两个系统之间的一种&#8220;保持&#8221;运算规则的一一对应关系。在
数学中一个符号所代表的是所有能够互相同构的对象。例如整数3可以看作是与某个元素个数为3的集合可以建立一一对应关系的所有的集合所构成的整体。所以在
数学中，如果我们解决某个特定的问题，它同时也就意味着我们解决了一系列相互等价的问题。<br />
&nbsp;&nbsp;&nbsp; 同构关系对于认知可以起到本质上的简化作用。如果通过一个推理链条，确认了A == B == C == D，则可以直接从概念上推导出 A
== D,
这一关系有可能被直观理解，而不需要理会中间的推理步骤。（注意到以上元素两两建立同构关系的时候可能要采用不同的对应手段，因此上面的等式并不是平凡
的。）另一方面，我们可以确定一个模型元素M,&nbsp; 将系统简化为 A == M, B == M, C == M, D ==
M。只要理解了元素M就理解了等价的其他元素。
<p>&nbsp;&nbsp;&nbsp; Witrix平台中PDM定义作为基础的结构模型，它同时映射成为数据库表，以及hbm, java,
meta等多个代码文件，此外还对应于约定的WebObject名称和BizFlow文件名称，相应的报表文件目录等。我们只要理解了pdm模型，即可通
过推理自然的掌握各个层面上对应的结构。这意味着只要知道实体名称，就知道如何通过Web访问这个对象，知道数据在数据库中对应的数据库表，而不需要知道
后台是如何读取前台提交的参数以及如何执行保存数据指令的。不仅仅是在模型驱动领域，在系统设计的各个方面，我们都应该尽量充分的利用当前的信息通过推理
得到系统其他部分的结构，而不是通过手工关联或者判断在程序中动态维持这种对应关系。例如在flow-cp机制中，biz的id,
action的id等都根据step配置的id推导得到，这样在工作列表跳转的时候就可以根据规则推导出跳转页面对应的链接，而不需要手工编写页面重定向
代码。</p>
<p style="text-align: center;"><br />
<img src="http://www.blogjava.net/images/blogjava_net/canonical/mapping.jpg" alt="" border="0" height="262" width="262" /><br />
</p>
<p><br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;
同态（homomorphism）关系相对于同构关系，只强调单向映射的可行性，它是一个舍弃属性的过程。同态作为最基础的认知手段之一，它不仅仅是用一
个符号来置换一组元素，而是同时保留了某种全局的运算关系，因此同态映像可以构成某种独立的完整的研究对象。通过同态映射，我们可以在不同的抽象层面上研
究原系统的一个简化版本。例如meta中的layout是一种典型的领域特定语言(DSL)。<br />
&nbsp;&nbsp;&nbsp; userName userTitle<br />
&nbsp;&nbsp;&nbsp; emailAddress<br />
<br />
每一个字段表示了一个可能任意复杂的inputor或者viewer,
字段之间的前后关系描述了最终显示页面上显示内容的相对关系。当viewer根据需求发生改变的时候，并不影响到layout层面上的关系，因此
layout可以保持不变。如果我们在系统中把问题分解为多个抽象层面上，多个观察视角上的同态模型，则可能实现更高的软件复用程度。<br />
&nbsp;&nbsp;&nbsp;
在Witrix平台的设计中，很多细粒度的标签都定义为tpl文本段，这样平台只要理解某一层面上的交互关系，实际应用中可能出现的细节在标签内部进行局
部处理，不会突破原始设计的形式边界，不会影响到原先设定的主体系统结构。例如BizFlow中的tpls段，action的source段等。<br />
&nbsp;&nbsp;&nbsp;
上世纪50年代以前，生物学家做梦也想象不到具有无限复杂性的生物遗传过程，竟然可以被抽象为ATGC四个抽象符号的串联。生命竟然不理会各种已知的或是
未知的物理化学作用，被抽象的三联码所驱动。一种抽象的本质似乎成了生命世界的本原。在软件的世界中，可以被识别的抽象元素绝不只是语言本身所提供的那些
机制。</p>
<img src ="http://www.blogjava.net/canonical/aggbug/257150.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2009-02-28 16:57 <a href="http://www.blogjava.net/canonical/archive/2009/02/28/257150.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>类型化：形而上学的信仰</title><link>http://www.blogjava.net/canonical/archive/2009/02/21/255974.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Sat, 21 Feb 2009 11:43:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2009/02/21/255974.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/255974.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2009/02/21/255974.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/255974.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/255974.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
有一个心理学实验，要求被试者将青草，公鸡，牛三个东西分
成两组，结果多数中国儿童将青草和牛分成一组，而多数美国儿童将公鸡和牛分成一组。中国人的思想中青草和牛之间存在现实的关系，牛吃草，而西方人的典型逻
辑是公鸡和牛都属于动物这一范畴。通过分类将物体类型化，这是西方人从小就接受的训练。据说美国婴儿学习名词的速度要快于动词，而中国的婴儿则相反，这并不是偶然的。
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
中国人的传统哲学认为世界是普遍联系的，事物之间存在着祸福相依的辩证转化关系。而古希腊人强调个体意识，以两分法看待世界，他们将世界看成是孤立的物体组成（原子论）构成，然后选择一个孤立物体（脱离背景），开始研究它的各项属性，接着将属性泛化，构成分类的基础。西方语言中大量抽象概念都是从作为属性的形容词直接转化而来，例如
white
--&gt;
whiteness
。而中文中很少有精确的类型定义，而多半是富有表现力的，隐喻性的词语，例如我们不谈论抽象的白，而只说雪白，没有抽象的
size
，而只说具体的大小。
</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
亚里士多德认为铁球在空气中下落是因为它具有&#8220;重性&#8221;，而木块在水中漂浮是因为木块具有&#8220;轻性&#8221;。这种将一切原因归结为事物内在属性的传统在一定程度上妨碍了西方人认识到背景的存在和作用，但使得他们可以把问题简化。
</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
古希腊人对于类型的热衷源于他们对于永恒的迷恋。静态的亘古不变的世界才是他们的思想栖息的场所。具体的物体是易逝的，多变的，只有抽象的类型才是永恒的存在，也只有抽象概念之间的关系才是永真的联系。而具体实例之间的关联在某种程度上被认为是不重要的，甚至是不可靠的。
</p>
<p class="MsoNormal" style="text-align: center;" align="center"><br />
<img src="http://www.blogjava.net/images/blogjava_net/canonical/class.jpg" alt="" border="0" height="196" width="264" /><br />
</p>
<p class="MsoNormal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
将具有某一属性的所有物体定义为一个集合，这一做法在上世纪初被发现会引起逻辑悖论，动摇了整个数学的基础，它绝不像表面上看起来那么单纯。但确定无疑的是，通过类型来把握不变的事实是一种非常重要且有效的认识策略。面向对象语言强调名词概
念，从引入类定义以及类之间的继承关系开始，这符合西方一贯的作风。而
Ruby
这种强调实例间关系的动态语言首先由日本人发明，可能也不是偶然的。虽然现在大家都在玩高科技了，可实际贩卖给你的多半仍然是包治百病的祖传秘方。文化可能造成认知上的一种偏执，在技术领域这一现象并没有被清楚的意识到。
</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/canonical/aggbug/255974.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2009-02-21 19:43 <a href="http://www.blogjava.net/canonical/archive/2009/02/21/255974.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从编写代码到制造代码</title><link>http://www.blogjava.net/canonical/archive/2009/02/15/254784.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Sun, 15 Feb 2009 10:21:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2009/02/15/254784.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/254784.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2009/02/15/254784.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/254784.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/254784.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;
软件开发作为一种工程技术，它所研究的一个重点就是如何才能有效降低软件产品的研发成本。在这一方向上，组件技术取得了空前的成功。它所提供的基本图景是
像搭积木一样从无到有的组装出最终的产品。在某种意义上，这是对现代建筑工业的模仿和致敬。新材料，预制件，框架结构，这些建筑学的进展在软件领域被一一
复制，建筑工地上的民工自然也成为了程序员们学习的楷模。毕竟，在组件的世界中码代码，基本上也是一种&#8220;搬砖&#8221;的行为。</p>
<p>
&nbsp;&nbsp;&nbsp;
值得庆幸的是，软件开发作为一种智力活动，它天生具有一种&#8220;去民工化&#8221;的倾向。信息产品有着与物质世界产品完全不同的抽象本质。在物理空间中，建造100
栋房屋，必须付出100倍的努力，老老实实的干上100遍。而在概念空间中建造100栋房屋，我们却可以说其他房屋与第一栋一模一样，加点平移旋转变换即
可。一块砖填了地基就不能用来盖屋顶，而一段写好的代码却可以在任何可用的场合无损耗的被使用。一栋建好的房屋发现水管漏水要大动干戈，而在完成的软件中
补个局部bug却是小菜一碟。在抽象的世界中有效的进行生产，所依赖的不应该是大干,苦干的堆砌，而应该是发现某种可用于推导的原理，基于这些原理，输入
信息可以立刻转换为最终的结果，而不需要一个逐步构造的过程。即我们有可能超越组装性生产，实现某种类似于数学的原理性生产。<a href="http://canonical.javaeye.com/blog/325051" mce_href="/blog/325051">http://canonical.javaeye.com/blog/325051</a><br />
</p>
<p>&nbsp;&nbsp;&nbsp;
代码复用是目前软件业中鼓吹降低生产成本的主要口号之一。但是在组件技术的指向下，一般所复用的只是用于构建的砖块，而并不是某种构造原理。即使在所有信
息已经确定的情况下，我们仍然不可能从需求立刻得到可执行的产品。很多代码即使我们在想象中已经历历在目，却仍然需要一行行把它们誊写下来。当我们发现系
统中已经没有任何组件值得抽象的时候，仍然留下来众多的工作需要机械化的执行。代码复用的理想国距离我们仍然非常的遥远。</p>
<p>
&nbsp;&nbsp;&nbsp;
子例程(subroutine)是最早的代码重用机制。这就像是将昨天已经完成的工作录制下来，在需要的时候重新播放。函数(function)相对于子
例程更加强大。很多代码看起来并不一样，但是如果把其中的差异部分看作是变量，那么它们的结构就可以统一了。再加上一些判断和循环，很多面目迥异的东西其
实是存在着大量共享信息的。面向对象技术是一次飞跃性的发展。众多相关信息被打包到一个名称（类型）中，复用的粒度和复杂度都大大提升。派生类从基类继
承，可以通过重载实现对原有代码的细致调整。不过，这种方式仍然无法满足日益增长的复用需求。很多时候，一个名称并不足以标定我们最终需要的代码结构，在
实际使用的时候还需要补充更多的信息。类型参数化，即泛型技术，从事后的角度看其实是一种明显的解决方案。根据参数动态的生成基类自然可以吸纳更多的变
化。经历了所谓Modern
C++的发展之后，我们现在已经非常明确，泛型并非仅仅能够实现类型共变，而是可以从类型参数中引入更丰富的结构信息，它的本质是一种代码生成的过程。<a href="http://canonical.javaeye.com/blog/57244" mce_href="/blog/57244">http://canonical.javaeye.com/blog/57244</a>
认清了这一点，它的扩展就非常明显了<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;">&nbsp;&nbsp;&nbsp;BaseClass</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">ArgClass</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">--&gt;</span><span style="color: #000000;">&nbsp;CodeGenerator</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">DSL</span><span style="color: #000000;">&gt;</span></div>
<p>DSL（或者某种模型对象）相对于普通的类型(Class)，信息密度要大很多，它可以提供更丰富也更完整的输入信息。而CodeGenerator也不必拘泥于基础语言本身提供的各种编译机制，而是可以灵活应用各种文本生成技术。<a href="http://canonical.javaeye.com/blog/309395" mce_href="/blog/309395">http://canonical.javaeye.com/blog/309395</a>
CodeGenerator在这里所提供的正是根据输入模型推导出完整实现代码的构造原理。</p>
<p>
&nbsp;&nbsp;&nbsp;
现在很多人热衷于开发自己的简易代码生成工具，这些工具也许可以在简单的情形下减轻一些体力工作，但是生成的代码一般不能直接满足需求，仍然需要手工执行
大量的删改工作。当代码生成之后，它成为一种固化的物质产品，不再能够随着代码生成工具的改进而同步改进，在长期的系统演化过程中，这些工具并不一定能够
减少累积的工作量。<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;">&nbsp;&nbsp; 修正过程&nbsp;&nbsp;</span><span style="color: #000000;">==&gt;</span><span style="color: #000000;">&nbsp;CodeGenerator</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">DSL</span><span style="color: #000000;">&gt;</span></div>
<p>为了改进以上代码生产过程，一些人试图在CodeGenerator中引入越来越多的可配置性，将各种变化的可能内置在构造原理中。显然这会造成CodeGenerator的不正常的肿胀。当更多的偶然性被包含在原理中的时候，必然会破坏原理的简单性和普适性。 <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;">&nbsp;&nbsp; 输入信息&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;一段用于推导的原理&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;修正补充&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;真实模型</span></div>
<p>必须存在[修正补充]这一项才能维持以上方程的持久平衡。</p>
<p>
&nbsp;&nbsp;&nbsp; 为了摆脱人工修正过程，将模型调整纳入到概念世界中，我们需要超越继承机制的，更加强大的，新的技术手段。其实在当前的技术背景下，这一技术已经是呼之欲出了。这就是AOP, Aspect Oriented Programming。<a href="http://canonical.javaeye.com/blog/34941" mce_href="/blog/34941">http://canonical.javaeye.com/blog/34941</a>
<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;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Biz&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">[AOP&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">]</span><span style="color: #000000;">==&gt;</span><span style="color: #000000;">&nbsp;CodeGenerator</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">DSL</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> <br />
</span></div>
<p>继承仅仅能够实现同名方法之间的简单覆盖，而AOP所代表的技术原理却是在代码结构空间中进行任意复杂的删改操作,它潜在的能力等价于人工调整。</p>
<p>
&nbsp;&nbsp;&nbsp; 为了实现上述生产模式，需要对编程语言，组件模型，框架设计等方面进行一系列改造。目前通用的AOP实现和元编程技术其实并不足以支持以上模式。<a href="http://canonical.javaeye.com/blog/275015" mce_href="/blog/275015">http://canonical.javaeye.com/blog/275015</a>
<br />
&nbsp;&nbsp;&nbsp; 这一生产模式将会如何演化，也是一个有趣的问题。按照级列理论，我们立刻可以得到如下发展方向：</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;">&nbsp;&nbsp;&nbsp; Context0&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;DSL1&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;EXT0&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;DSL0&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp; Context1&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;DSL2&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;EXT1&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;DSL1&nbsp; <br />
&nbsp;&nbsp;&nbsp; <img src="http://www.blogjava.net/Images/dot.gif"  alt="" /> <br />
</span></div>
<p><a href="http://canonical.javaeye.com/blog/33824" mce_href="/blog/33824">&nbsp;http://canonical.javaeye.com/blog/33824</a></p>
<p>Witrix平台中BizFlow可以看作是对DaoWebAction的修正模型，但是它本身具有完整的意义，可以直观的被理解。在BizFlow的基础上可以逐步建立SeqFlow，StateFlow等模型。<a href="http://canonical.javaeye.com/blog/126467" mce_href="/blog/126467">http://canonical.javaeye.com/blog/126467</a></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
现在有些人试图深挖函数式语言，利用模式匹配之类的概念，做符号空间的全局优化。但是我们需要认识到通用的机制是很少的，能够在通用语言背景下被明确提出
的问题更是很少的。只有在特定领域中，在掌握更多局部信息的情况下，我们才能提出丰富的问题，并作出一定背景下的解答。DSL的世界中待做的和可做的工作
很多。<a href="http://canonical.javaeye.com/blog/147065" mce_href="/blog/147065">http://canonical.javaeye.com/blog/147065</a>
<br />
</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于程序员而言，未来将变得越来越丰富而复杂，它将持续拷问我们的洞察力。我们不是一行行的编写代码，把需求一条条的翻译到某种实现上，而是不断发明局部的生产原理，依靠自己制定的规则在抽象的空间中不断的创造新的表象。<br />
</p>
<img src ="http://www.blogjava.net/canonical/aggbug/254784.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2009-02-15 18:21 <a href="http://www.blogjava.net/canonical/archive/2009/02/15/254784.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>逆元：不存在的真实存在 </title><link>http://www.blogjava.net/canonical/archive/2009/02/07/253744.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Sat, 07 Feb 2009 14:22:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2009/02/07/253744.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/253744.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2009/02/07/253744.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/253744.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/253744.html</trackback:ping><description><![CDATA[<div class="blog_content">
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
负数没有直接的几何意义，因此它被认为是对应于不存在的事物。而按照古希腊的逻辑，不存在的事物是不可能存在的，因而也就是无法被理解的，更不可能参与到
推理过程中，因此是无意义的，无法被定义的，
因此它是不存在的。中国人注重的是运算的合理性，而不是数的真理性，大概在公元前400年左右就创造了负数和零的概念。而在西方直到公元7世纪（唐代）的
一本印度人的著作中才出现负数，它被用来表示负债。西方人没有能够创造负数，他们对负数的接受更迟至15世纪左右。这件事实在一定程度上说明了存在某种深
刻的困难阻碍我们理解负数概念。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在引入负数之前，3x^2 + 8 = 4x 和&nbsp; 3x^2 + 4x + 8 = 0
这两个方程的结构是完全不同的，它们需要不同的求解技术，因此也就不可能利用符号抽象出 a x^2 + b x + c =
0。引入负数才使得我们能够以统一的方式提出问题，并研究通用的求解技术。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 群论(Group Theory)是对结构进行抽象研究的数学分支。群的定义包括四条规则<br />
1.&nbsp;&nbsp;&nbsp; 元素之间的运算满足结合律 (a * b) * c = a * (b * c)<br />
2.&nbsp;&nbsp;&nbsp; 元素之间的运算封闭，即 a * b 仍然属于该群<br />
3.&nbsp;&nbsp;&nbsp; 存在单位元，即对所有a, a * e = e*a = a<br />
4.&nbsp;&nbsp;&nbsp; 每个元素存在对应的逆元，a * a^-1= e<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 逆运算是非常重要的结构要求，逆元是对负数的一种抽象推广。如果没有逆元，则只能构成半群(semi-group)，它的性质要少很多。</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 目前软件设计中所有的原则都指向组装过程，从无到有，层层累进。构件组装的隐喻中所包含的图像是操纵实际可见的积木，是缺少逆元概念的。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 考察一个简单的例子，假设需要的产品是三角形内部挖去一个五边形的剩余部分。有三种生产策略：<br />
1.&nbsp;&nbsp;&nbsp; 对最终需要的产品形态进行三角剖分，使用8个小三角形拼接出来。这种方式比较繁琐，而且最后粘接工序的可靠性和精确性值得怀疑。<br />
2.&nbsp;&nbsp;&nbsp; 拿到一个真实的三角形，然后用刀在内部挖出一个五边形的洞。这种方式需要消耗一定的人工，而且也很难保证五边形的精确性，即使我们曾经精确的生产过其他五角形和三角形。实际上一般情况下我们是逐步锉出一个五边形的，并没有充分利用到五边形的对称性。<br />
3.&nbsp;&nbsp;&nbsp; 在概念空间中做一个抽象计算&nbsp; (-五边形) + (三角形) = 所需产品<br />
如果我们能够生产一种负的五边形和一种正的三角形，则可以立刻得到最终的产品。<br />
</p>
<p style="text-align: center;"><img src="http://www.blogjava.net/images/blogjava_net/canonical/principle.jpg" alt="" border="0" width="446" height="444" /><br />
</p>
<p><br />
&nbsp;<br />
在软件开发的实践中，我们目前多数采用的是两种方式：<br />
1.&nbsp;&nbsp;&nbsp; 采用可视化设计工具通过拖拽操作开发出完整的界面和后台<br />
2.&nbsp;&nbsp;&nbsp; 拷贝一些已有的代码，删除掉不需要的部分，增加一些新的实现，也可能对已有实现做一些不兼容的修正。<br />
<br />
在第二种方式中<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 新结构的构造 = 已有结构 + 软件之外的由人执行的一个剪裁过程<br />
这个剪裁过程表现为一个时间序列。如果我们对原有结构进行了调整，则需要重新关联一个时间序列，而此时间序列并不会自动重播。为了压缩以时间为度量单位的
生产成本，我们必须减少对时间序列的依赖。在时间序列中展开的一个构造过程可以被转化为一个高维设计空间中的一种更加丰富的构造原理，我们最终的观测可以
看作是设计空间向物理空间的一个投影（想象一束光打下来）。这种方式更容易保证程序的正确性。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 时间序列 --[原理转化]--&gt; 空间关系</p>
<p><br />
&nbsp;&nbsp;&nbsp;
这样我们就可以使用第三种生产策略：利用构造原理进行抽象计算。如果我们只盯着产品的最终形态看，只是想着怎么把它像搭积木一样搭建出来，就不可能识别出
系统结构本身所蕴含的对称性。如果我们发现了系统内蕴的结构特征，但是却只能通过构造过程中的行动序列来追随它，同样无法实现有效的工作复用。同时因为这
个行动序列一般处于系统规则约束之外，完全由人的自觉来保障，因此很难保证它的正确性。现实世界的规范要求并不是模型本身所必须满足的，只要我们能够创造
新的结构原理，在概念空间中我们就可以拥有更多的自由。现在业内鼓吹的软件构造原理多半是参照物理世界中生产具体物质产品的生产工序，却没有真正把握信息的抽象本质。掌握规则，制订规则，才是信息空间中的游戏规则。<br />
<br />
&nbsp;&nbsp;&nbsp; 物理学中最重要的分析学思想之一是微扰论(Perturbation).
针对一个复杂的物理现象，首先建立一个全局的规范的模型，然后考虑各种微扰条件对原有模型的影响。在小扰动情况下，模型的变化部分往往可以被线性化，被局
域化，因而问题得到简化。微扰分析得到的解依赖于全局模型的解而存在，因而这是一种主从关系的分解方式。但是如果主体模型是我们已经熟知的物理现象，则我
们关注的重点可以全部放在扰动解上，认为所有特定的物理规律都体现在扰动解中。如果微扰分析得到的物理元素足够丰富，则微扰模型本身可以成为独立的研究对
象，在其中我们同样可以发现某种普适的结构规律。<br />
&nbsp;&nbsp;&nbsp; 考察如下的构造过程<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; X = a + b + c<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Y = a + b + d = (a + b + c) - c + d = X - c + d<br />
&nbsp;&nbsp;&nbsp; 对于数学而言，上述的推导是等价的，但是对于物理学而言，Y = a + b + d 和&nbsp; Y = X - c +
d是有着本质不同的。第一种方式要求打破原先X的构造，而重新的组装其实是有成本的，特别是在X本身非常复杂的情况下。典型的，如果X是经过测试的功能，
重新组装后原先由测试保障的概念边界被打破。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们可以从Y = X + dX抽象出扰动模型&nbsp; dX = - c + d<br />
主从分解模式自然的导出逆元概念。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
如果没有逆元，我们必然需要分解。但是如果发掘了背景这一概念，在逆元运算下，对背景不是分解让其成为可见的部分，而是采用追加的，增删的方法对背景结构
进行修正，则我们有可能在没有完整背景知识的情况下，独立的理解局部变化的结构。即背景是透明的，知识成为局部的。在Witrix平台中，BizFlow
+ DaoWebAction + StdPage
才构成完整的程序模型，BizFlow其实是对标准模型的差异描述，但是它可以被单独的理解。如果我们从接触程序开始就接受BizFlow,
就可能完全不需要了解数据库访问和前台界面渲染的知识。我们并不是通过在DaoWebAction中设定各种可预见的调用形式，而是在BizFlow中通
过类似AOP的操作方式直接对标准模型进行修正。这种修正中一个很重要的部分就是删除标准模型中缺省提供的功能。<br />
&nbsp;&nbsp;&nbsp;&nbsp; WebMVC之前世今生 <a href="http://canonical.javaeye.com/blog/163196">http://canonical.javaeye.com/blog/163196</a>
<br />
&nbsp;&nbsp;&nbsp;&nbsp; Witrix架构分析 <a href="http://canonical.javaeye.com/blog/126467">http://canonical.javaeye.com/blog/126467</a>
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 变化的部分构成独立于原始模型的新的模型，它的结构关系是完备的，可以独立的理解。在原始模型崩溃的情况下，它仍然可能保持有效性。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 从物理学的角度看，我们所观测到的一切物理现象，都是某种物理作用的结果，也就是物质结构相对于背景状况的一种偏离。我们只可能观测到变化的部分，因此我们对世界的认识其实只是世界的扰动模型而已，世界的本体不属于科学研究的范畴。</p>
</div>
<img src ="http://www.blogjava.net/canonical/aggbug/253744.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2009-02-07 22:22 <a href="http://www.blogjava.net/canonical/archive/2009/02/07/253744.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>文本化</title><link>http://www.blogjava.net/canonical/archive/2009/01/04/249666.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Sat, 03 Jan 2009 16:55:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2009/01/04/249666.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/249666.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2009/01/04/249666.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/249666.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/249666.html</trackback:ping><description><![CDATA[<div class="blog_content">
<p>&nbsp;&nbsp;&nbsp;
软件技术的发展是一个结构化不断加深的过程，我们逐渐拥有了越来越丰富的结构识别, 表达和处理手段。在这一方向上,
组件技术最终取得了巨大的商业成功。但是区分同时也就意味着隔阂。面向对象技术最基础的概念在于 O = C(O),
对象的复合(Composition)仍然是对象.&nbsp; 然而在越来越复杂的软件生态环境中,这一图景实现的可能性被大大的压缩.
面对层层封装造成的形态各异的表达方式, 不同来源, 不同目标, 不同运行环境下的信息的交互变得越来越困难。我们逐渐丧失了概念上的简洁性,
也丧失了数学世界中的那种穿透一切的统一的力量. 所谓SOA（Serivce Oriented
Architecture)技术试图通过补充更多的环境信息，放弃状态关联，暴露元知识等方式来突破现有的困境。 <a href="http://canonical.javaeye.com/blog/33803">http://canonical.javaeye.com/blog/33803 </a>
这其中一项关键的技术抉择是基于文本格式进行信息表达。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
在过去10年中Web技术取得了空前的成功，它造就了互联网这一世界上最大的分布式集成应用。SOA从某种程度上说是对这一事实在技术层面上的反思。基于
文本传递的web技术所表现出来的开放性，可理解性和可观测性，与封闭的，难以直接解读的，必须拥有大量相关知识才能正确操作的二进制结构相比，这本身就
是革命性的创新。不需要特殊的工具就可以非常轻易的察看到网页程序的输入输出，所有交互过程都处在完全透明的检查下，各种不曾事先规划的文本处理手段都可
以参与到web创建的过程中。随着速度，存储不再是我们考虑的首要问题，文本化作为一种技术趋势逐渐变得明确起来。但是任何一种技术思想的成功或失败都不
可能是因为某种单一的原因所造成的，因此有必要对文本化的技术价值做更加细致的剖析。<br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp; 1.
文本化是一定程度上的去结构化，但是通过这种方式我们获得了对程序结构的更强的控制力。无论我们所关心的文本片断层层嵌套在大段文本的哪个部分，我们都可
以通过text.indexOf(subStr)来实现定位，通过text.replace(oldStr,newStr)实现变换。而在组件系统中，我
们只有通过某种预定的遍历方式逐步递归才有可能访问到组件内部的组成对象。如果某个组件不按照规范实现或者规范中缺少明确的设定，则这一信息关联链条将会
断裂。在一些组件系统中，甚至没有规定一种统一的遍历方式，则我们根本无法定义出通用的大范围的结构定位/变换手段。即使是在设计精良的组件框架中，受限
制于组件的封装性要求，我们也不可能访问到全部的信息。当我们以组件设计者意料之外的方式使用这些组件的时候，就会遇到重重障碍。即使所需的只是微小的局
部调整，因为无法触及到需要修改的部分，我们也可能被迫放弃整个组件。<br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp; 2.
文本是普适的信道。各种操作系统，各种程序语言所具有的最基本的能力就是文本处理能力，对于文本格式的约定是最容易达成共识的。虽然对于机器而言，理解基
于地址定位的二进制数字可能更加直接，但是所有的应用程序都是由人来负责编制，调试，部署，维护的，如果人可以不借助特殊的工具就可以明确了解到系统内发
生的过程，则系统的构建和维护成本就会大幅下降。<br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp; 3.
文本表述形式上的冗余性增强了系统的概念稳定性和局部可理解性。在二进制格式中，经常出现的是根据相对地址定位，这要求我们完整理解整个二进制结构，才能
够逐步定位到局部数据块。同时，二进制格式中也经常使用一些外部的信息，例如某个位置处的数据为整型，占用四个字节等。这样的信息可能只能在文档说明里查
到，而在数据体中没有任何的体现，这限制了独立的理解可能性。与此相反，文本格式经常是自说明式的，例如width:3.5px,
这提高了系统的可理解性，特别是局部可理解性。即使我们对系统只具有很少的知识，一般也能根据数据周围的相关信息进行局部操作。一般很容易就能够定位到特
殊的局部数据区，安全的跳过众多未知的或者不被关心的结构. 一个程序新手也可以在很短时间内靠着连蒙带猜,
实现xml格式的word文件中的书签替换功能,而要搞清楚word的二进制格式,并独立编制出正确的替换功能,显然就不是一两周的工作量可以解决的了.
这其中, 可理解性的差异是存在着数量级上的鸿沟的.<br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp; 4. xml这种半结构化的文本格式规范的兴起, 以通用的方式为文本描述引入了基本的形式约束, 实现了结构表达的均一性.
C语言中的宏(Macro)本质上就是一种文本替换技术,它的威力在于没有预定义的语义, 因此可以超越其他语法成分, 破除现有语法无法跨越的限制.
但是它的危险性在于缺乏与其能力相适应的形式约束, 难以控制. 而在xml格式规范下, 不同语义,
不同抽象层面的节点可以共存在同一个形式体系中, 可以用通用的方式进行定位,校验, 转换等. Witrix平台在动态xml方面发展了一系列技术,
为文本处理引入了更多应用相关的规则, 增强了文本描述的抽象能力和表达能力.&nbsp; <br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp; 5. 文本作为描述(description)而不是执行指令(execution). C语言的源代码与机器码基本上是一一对应的,
即源代码本身所表达的就是指令的执行过程. 而在Web应用领域, HTML语言仅仅是声明界面上需要展现什么,
但是如何去实现是由通用的解析引擎负责,它并不是我们关注的重点. 描述需要结合诠释(解释)才能够产生实际的运行效果,
才能对现实的物理世界产生影响.这在某种程度上实际上是延迟了执行过程. 一种描述可以对应多种诠释,
例如同样的元数据在前台可以用来生成界面,在后台可以用于生成数据库, 进行数据有效性校验等. 在特定的应用领域中,执行引擎可以是通用的,
可以独立于描述本身不断演化, 因此一种领域特定的描述,它所承载的内容并不是固化的, 而是可以随着执行引擎的升级不断增强的. 例如,
在Witrix平台中, FlowDSL本身所做出的流程描述是稳定的,
但是随着流程引擎不断改进,不断引入新的功能,所有使用DSL的已实现的应用都同步得到升级. <a href="http://canonical.javaeye.com/blog/275015">http://canonical.javaeye.com/blog/275015</a>
<br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp; 6. Text = Process(Text) 这个不动点在Unix系统中得到了充分的应用: 多个小程序通过管道(Pipe)组合在一起,
可以完成相当复杂的功能. 一个更加丰富的处理模型是 XML = Process(XML). 文本描述很自然的支持多趟处理,
它使得我们可以充分利用全局知识(后续的处理过程可以使用前次处理过程收集的全局信息), 可以同时支持多个抽象层面(例如DSL的不断动态展开).
Witrix平台中的编译期运行技术实际上就对应于如下简单规则: 编译期运行产生文本输出, 对输出文本再次进行编译. 通过这一递归模式,
可以简单的实现动态解析与静态描述之间的平衡. 模板(Template)技术是具有关键性作用的文本生成技术.
out.write("&lt;div&gt;");out.write(value);out.write("&lt;/div&gt;");这种
API拼接方式显然不如&lt;div&gt;${value}&lt;/div&gt;这种模板生成方式直观且易于使用.
在Witrix平台的tpl模板语言中, xml的规范性使得在多趟编译过程中我们一直可以维持某种形式约束. <br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp; 7. 不是所有的情况下都应该使用文本. 普元EOS中所鼓吹的XML总线之类的技术是我所极力反对的. <a href="http://canonical.javaeye.com/blog/33794">http://canonical.javaeye.com/blog/33794</a>
</p>
</div>
<img src ="http://www.blogjava.net/canonical/aggbug/249666.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2009-01-04 00:55 <a href="http://www.blogjava.net/canonical/archive/2009/01/04/249666.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于代码生成和DSL</title><link>http://www.blogjava.net/canonical/archive/2008/11/23/242084.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Sun, 23 Nov 2008 03:57:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2008/11/23/242084.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/242084.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2008/11/23/242084.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/242084.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/242084.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 代码生成(Code Generation)本身是一个非常宏大的概念。从某种意义上说，当我们明确了计算的意义之后，所做的一切都只是一系列代码生成的过程，最终的目标是生成某种可执行的机器码。对web程序员来说，代码生成是最熟悉不过的了，每天我们所做的工作就是JSP=&gt;Servlet=&gt;HTML。不过，现在多数人脑海中的代码生成，指的一般只是根据配置输出一个或多个程序文本的过程，最常见的是根据数据库模型生成增删改查相关代码。这种技术其实很少在小型以上的项目中起到积极的作用．因为一般的生成工具都没有实现追加功能，无法适应模型的增量修改。此外一般生成的代码相比于手工书写的代码要更加冗长，需要被直接理解的代码总量不降反升．为图一时之快，所要付出的是长期的维护成本。<br />
<br />
&nbsp;&nbsp; 在应用开发中，有些领域是非常适合于使用代码生成技术的。例如根据领域模型生成ORM(对象-关系映射)描述，或者根据接口描述生成远程调用代理/存根 (Proxy/Stub)等。因为它们实际上只是对同一信息的不同技术形式或者不同技术层面的同义反复而已。这种生成最理想的方式是动态进行，可以随时保持模型的有效性。RoR(RubyOnRails)框架中ActiveRecord技术便是一个成功的范例，它甚至提供了动态生成的DAO函数，减少了一系列的包装调用过程。<br />
<br />
&nbsp;&nbsp; 代码生成更加深刻的应用是完成高层模型向低层模型的转化，这一过程往往是非平凡(non-trivial)的。在Witrix平台中通过代码生成来支持领域抽象，可以用非常低的成本跨越结构障碍，将自定义的领域模型嵌入到现有的技术体系中。这其中我们的主要工作是解决了生成代码与手工书写代码之间的有效隔离及动态融合问题，确保代码生成可以反复的以增量的方式进行，同时支持最细粒度处对生成的代码进行定制调整。<br />
<br />
&nbsp;&nbsp; 举一个简单的例子，假设现在需要开发一个三步审批的流程，每一步的操作人可以录入意见，可以选择通过或者回退，可以选择下一步操作的具体操作人，系统自动记录操作时间，每个操作人可以查看自己的操作历史等。虽然在现有技术体系中实现这一功能需要不少代码，但是在业务层面上描述这一功能并不需要很多文字，实际需要提供的信息量很小。显然，建立领域模型是比较适合的做法，可以定义一种DSL(Domain Specific Language)来描述这一模型。<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;">&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">flow_cp:SeqFlow</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">step&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="draft"</span><span style="color: #ff0000;">&nbsp;userField</span><span style="color: #0000ff;">="draferId"</span><span style="color: #ff0000;">&nbsp;dateField</span><span style="color: #0000ff;">="draftTime"</span><span style="color: #ff0000;">&nbsp;waitStatus</span><span style="color: #0000ff;">="drafted"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">step&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="check"</span><span style="color: #ff0000;">&nbsp;userField</span><span style="color: #0000ff;">="checkerId"</span><span style="color: #ff0000;">&nbsp;dateField</span><span style="color: #0000ff;">="checkTime"</span><span style="color: #ff0000;">&nbsp;opinionField</span><span style="color: #0000ff;">="checkOpinion"</span><span style="color: #ff0000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;waitStatus</span><span style="color: #0000ff;">="sent"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">step&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="approve"</span><span style="color: #ff0000;">&nbsp;userField</span><span style="color: #0000ff;">="approverId"</span><span style="color: #ff0000;">&nbsp;dateField</span><span style="color: #0000ff;">="approveTime"</span><span style="color: #ff0000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;opinionField</span><span style="color: #0000ff;">="approveOpinion"</span><span style="color: #ff0000;">&nbsp;waitStatus</span><span style="color: #0000ff;">="checked"</span><span style="color: #ff0000;">&nbsp;passStatus</span><span style="color: #0000ff;">="approved"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;">&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">flow_cp:SeqFlow</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span></div>
<br />
&nbsp;&nbsp; 以上功能涉及到多个操作场景，实现的时候需要补充大量具体信息，其中很大一部分信息来自于背景知识，例如显示样式，界面布局，前后台通信方式等。以上模型可以进一步抽象为如下标签<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;">&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">flow_cp:StepFlow3</span><span style="color: #0000ff;">/&gt;</span></div>
<br />
&nbsp; 在不同应用中复用以上流程逻辑的时候可能需要局部修正，例如<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;">&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">flow_cp:StepFlow3</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">step&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="check"</span><span style="color: #ff0000;">&nbsp;userField</span><span style="color: #0000ff;">="checker"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">flow_cp:StepFlow3</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span></div>
<br />
&nbsp;&nbsp; 更加复杂的情形是DSL本身提供的抽象无法满足全部需求，而需要在局部补充更多模型之外的信息，例如物品接收单审批通过后自动导入库存等。<br />
&nbsp;<br />
&nbsp;&nbsp; 在Witrix中，代码生成不是直接产生最终的输出，而是在编译期生成基础模型，它与补充描述通过extends算子进行融合运算之后产生最终输出, 这种融合可以实现基础功能的新增，更改或者删除。典型的调用形式为<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;"><br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">biz-flow</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">extends</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">flow_cp:StepFlow3</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">step&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="check"</span><span style="color: #ff0000;">&nbsp;userField</span><span style="color: #0000ff;">="checker"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">flow_cp:StepFlow3</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">extends</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">action&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="pass_approve"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" />.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">action</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">biz-flow</span><span style="color: #0000ff;">&gt;</span></div>
<br />
这里的操作过程可以看作是BizFlow extends SeqFlow&lt;FlowConfig extends StepFlow3Config&gt;，与泛型技术非常类似，只是需要更强的局部结构控制能力。<br />
&nbsp;&nbsp;&nbsp; 按照级列理论<a href="http://canonical.javaeye.com/blog/33824">http://canonical.javaeye.com/blog/33824</a> ，我们可以定义一个DSL的级列，整个抽象过程为<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;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Context0&nbsp;+&nbsp;DSL1&nbsp;+&nbsp;EXT0&nbsp;=&nbsp;DSL0<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Context1&nbsp;+&nbsp;DSL2&nbsp;+&nbsp;EXT1&nbsp;=&nbsp;DSL1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" />&nbsp;&nbsp; <br />
</span></div>
<br />
&nbsp;&nbsp;&nbsp; 在目前一些通用语言中，也有一些所谓内嵌DSL的方案，可以提供比较简洁的业务描述。但是仅仅建立DSL描述是不充分的，从级列理论的观点看，我们必须提供一种DSL的补充手段，能够在细节处补充DSL模型之外的信息，实现两者的自然融合。同时我们应该可以在不同的抽象层面上独立的进行操作，例如在 DSL1和DSL2的层面上都可以通过类似继承的操作实现局部调整，这同时也包括在不同的抽象层面上都能对模型进行合法性校验。<br />
&nbsp;&nbsp;&nbsp; <br />
<img src ="http://www.blogjava.net/canonical/aggbug/242084.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2008-11-23 11:57 <a href="http://www.blogjava.net/canonical/archive/2008/11/23/242084.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AOP on XML Tag</title><link>http://www.blogjava.net/canonical/archive/2008/07/07/212933.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Sun, 06 Jul 2008 16:12:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2008/07/07/212933.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/212933.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2008/07/07/212933.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/212933.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/212933.html</trackback:ping><description><![CDATA[&nbsp; AOP(Apsect Oriented Programming)概念的正式出现也有一些时日了，但是它在程序构造过程中似乎仍未找到合适的切入点，一般系统的设计实现很少将AOP作为必要的技术元素。AOP作为一种普适的技术思想，它所代表的是程序结构空间中的定位和组装技术。<a href="http://canonical.javaeye.com/blog/34941">http://canonical.javaeye.com/blog/34941</a> AOP使我们可以通过非侵入性的方式动态修改&#8220;任意&#8221;已经构建好的程序，而不需要事前有大量的设计准备。原则上说,这种技术思想是可以在任何程序语言基础上进行表达的，并不是只有java, C#这样的面向对象语言才允许AOP操作. Witrix平台中所应用的部分技术与AOP有些类似，只是大量的结构调整表现为xml生成和xml变换，在具体的使用方式上也有一些微妙的差异。<a href="http://canonical.javaeye.com/blog/126467">http://canonical.javaeye.com/blog/126467</a><br />
<br />
&nbsp; 相对于通用程序语言，xml语言其实是AOP技术的一个更加合适的形式载体。<br />
1. xml格式特殊的规范性确保了在最细的逻辑粒度上，程序结构也是可识别的，可操纵的（在这一点上非常类似于函数式语言）。而所有的命令式语言(imperative language)中，函数内部的结构都是很难采用统一方式进行描述和定位的。 <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;">&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">ns1:loop</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">rpt:Row</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">ns1:loop</span><span style="color: #0000ff;">&gt;</span></div>
<br />
2. xml节点的坐标可以采用xpath或者css选择符等通用方式进行描述，而一般程序结构无法达到xml格式这样的均一性，其中的坐标定位方式要复杂得多。<br />
3. xml节点上可以增加任意属性，不同的属性可以属于不同的命名空间(namespace)，这些属性可以辅助AOP的定位机制。而一般程序语言中如果没有Annotation机制, 则定位只能依赖于函数名和类名（函数参数只有类型没有名称），而类名和函数名随时可能因为业务变化而调整（不是专为定位而存在）, 由此构建的切点描述符是不稳定的。<br />
&nbsp; <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: #0000ff;">&lt;</span><span style="color: #800000;">ui:PageTable&nbsp;</span><span style="color: #ff0000;">pager</span><span style="color: #0000ff;">="${pager}"</span><span style="color: #ff0000;">&nbsp;cache:timeout</span><span style="color: #0000ff;">="1000"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span></div>
4. xml节点的增删改查显然要比字节码生成技术要简单和直观得多。<br />
&nbsp; &nbsp;<br />
<br />
&nbsp;&nbsp; AOP技术难以找到应用的一个重要原因在于很多人机械式的将它定位为一种横切技术，认为它的价值完全在于某个确定的切面可以插入到多个不同的切点，实现系统的横向分解。而在实际应用中，业务层面上很少具有可抽象的固定的共同性，我们所迫切需要的一般是对已有程序结构进行动态扩展的一种能力。横切是AOP的一种特殊的应用，但不是它的全部。相对于继承(inheritance)等依赖于概念诠释的结构扩展机制，AOP所代表正是对程序结构空间进行任意操纵的一种能力。AOP可以为基础结构增加功能，改变原有功能实现，也可以取消原有功能实现，它不需要把所有的扩展逻辑按照树形结构进行组织，不要求在基础结构中为扩展编写特殊的代码。这种自由的结构扩展能力在Witrix平台中被发展为&#8220;实现业务代码与平台基础架构之间的动态融合&#8221;。<br />
<br />
&nbsp;&nbsp; 在Witrix平台的实际应用中，AOP的切点匹配能力并不是十分重要。一般情况下我们主要通过整体结构规划来确保控制点意义明确且相对集中，因此不需要额外通过切点匹配进行业务功能的再组织，不需要再次从杂乱的程序逻辑中重新发现特殊的控制点。例如在Witrix平台的Jsplet框架中所有后台事件响应都通过objectName和objectEvent参数触发，在触发后台事件响应函数之前都会调用bizflow文件中的beforeAction段。<br />
&nbsp;&nbsp; 在bizflow文件中，aop操作是明确指定到具体函数的，使用模糊匹配在一般情况下只会使问题变得不必要的复杂化。例如扩展actQuery函数<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;">&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">action&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="aop-Query-default"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">source</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;通过自定义标签抽象出多个Action之间的共用代码<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">app:DoWorkA</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">source</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">action</span><span style="color: #0000ff;">&gt;</span></div>
<br />
&nbsp; &nbsp;<br />
&nbsp;&nbsp; 在Witrix平台中结构组装主要是通过自定义标签库和extends算子来实现，它们都依赖于xml格式的规范性。<br />
1. 通过在custom目录下实现同名的自定义标签，即可覆盖Witrix平台所提供的缺省标签实现，这里所依赖的并不是复杂的匹配过程，而是自然直观的映射过程。<a href="http://canonical.javaeye.com/blog/196826">http://canonical.javaeye.com/blog/196826</a><br />
2. 所有的xml配置文件支持extends操作，它允许定制两个具有业务含义的xml节点之间的结构融合规则。例如&lt;biz-flow extends="docflow"&gt;。<br />
<br />
&nbsp;&nbsp; 实际使用中, AOP技术的一个应用难点在于状态空间的管理问题。一般interceptor中所能访问的变量局限为this指针所携带的成员变量，以及函数调用时传入的调用参数。interceptor很难在状态空间中创建新的变量，也很难读取在其他地方所产生的状态变量。例如对于如下扩展 A(arg1); B(arg2); C(arg3); =〉 Ax(arg1); B(arg2); Cx(arg3); 因为原有的调用序列中没有传递额外的参数，因此A和C的扩展函数之间很难实现共享内部变量x。在TPL模板语言中，tpl本身是无状态的，状态变量通过外部的$thisContext对象统一管理。通过这种行为与状态的分离，结合灵活的变量作用域控制机制，可以以比较简单的方式实现扩展函数之间的信息共享。<br />
<br />
<img src ="http://www.blogjava.net/canonical/aggbug/212933.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2008-07-07 00:12 <a href="http://www.blogjava.net/canonical/archive/2008/07/07/212933.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>主从分解而不是正交分解</title><link>http://www.blogjava.net/canonical/archive/2008/05/26/202801.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Sun, 25 May 2008 16:41:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2008/05/26/202801.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/202801.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2008/05/26/202801.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/202801.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/202801.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 说到分解，很多人心中的意象大概只有正交分解。正交分解无疑是最重要的一种分析方法，它也是所谓&#8220;分而治之&#8221;思想最常见的实现策略。但是正交分解一般潜在的假定是分解后的子部分是大致均衡的，它们是相对具有独立价值的，可以彼此脱离独立发展。这是分解后实现系统解耦的重要原因。<a href="http://canonical.javaeye.com/blog/33885">http://canonical.javaeye.com/blog/33885</a> 但是物理学中另一种重要的分析学思想是微扰论(Perturbation). 针对一个复杂的物理现象，首先建立一个全局的规范的模型，然后考虑各种微扰条件对原有模型的影响。在小扰动情况下，模型的变化部分往往可以被线性化，被局域化，因而问题得到简化。微扰分析得到的解依赖于全局模型的解而存在，因而这是一种主从关系的分解方式。但是如果主体模型是我们已经熟知的物理现象，则我们关注的重点可以全部放在扰动解上，认为所有特定的物理规律都体现在扰动解中。如果微扰分析得到的物理元素足够丰富，则微扰模型本身可以成为独立的研究对象，在其中我们同样可以发现某种普适的结构规律。<br />
&nbsp;&nbsp;&nbsp; Witrix平台中系统化的应用主从分解模式，通过类似AOP的技术实现了业务模型与平台技术的自然结合。<a href="http://canonical.javaeye.com/blog/126467">http://canonical.javaeye.com/blog/126467</a> 最近我们的一个产品的新版本即将在全国范围内部署，如何有效的控制众多相近的二次开发版本，同时确保主版本的快速升级，是在架构层面必须解决的问题。<a href="http://canonical.javaeye.com/blog/73265">http://canonical.javaeye.com/blog/73265</a> 在Witrix平台中，各部署版本并不是直接修改主版本源代码得到，而是将差异化代码放在单独的目录中进行管理，由系统运行平台负责将差异化定制代码与主版本代码进行动态融合，实现部署版本的客户化。在这一过程中，系统模型本身支持逆元结构至关重要，否则某些多余的元素无法通过差异性描述去除，则将出现局部模型失效的情况。<br />
&nbsp;&nbsp;&nbsp; Witrix平台定义了特殊的_custom目录，它的内部目录结构与defaultroot目录相同，系统平台优先使用该目录下文件所提供的功能实现。同时定义了系统参数global.app_id和global.default_app_id，它们分别用来区分当前程序版本以及程序主版本代码。例如当global.app_id=beijing,global.default_app_id=main的时候，系统中装载ui.xml这个标签库时经历如下过程，<br />
1.&nbsp;&nbsp; &nbsp;装载平台内置的标签库，文件路径为 /_tpl/ui.xml.<br />
2.&nbsp;&nbsp; &nbsp;根据global.default_app_id设置，装载/_custom/main/_tpl/ui.xml, 其中定义的标签实现将覆盖平台缺省提供的标签实现。对于那些不需要特殊定制的标签，继续使用平台提供的缺省实现。<br />
3.&nbsp;&nbsp; &nbsp;根据global.app_id设置，装载/_custom/beijing/_tpl/ui.xml, 其中定义的标签实现将覆盖产品主版本的标签实现。<br />
<br />
基础平台中对于代码动态融合定义了精细的融合策略，将通过编译技术检查扩展标签的接口与缺省实现的接口相兼容，由此确保代码扩展后不会破坏主版本中的已有调用代码。<br />
&nbsp;&nbsp;&nbsp; 在基础平台的实现中，很多实现代码都是类似<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;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">df:WhenAllowFinishWf</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">df:FinishWfButton&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">df:WhenAllowFinishWf</span><span style="color: #0000ff;">&gt;</span></div>
<br />
这样的类似废话的标签调用。但是通过这些标签的标记，我们确立了系统的逻辑结构，标定了系统中可以被安全替换的逻辑片断。
<img src ="http://www.blogjava.net/canonical/aggbug/202801.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2008-05-26 00:41 <a href="http://www.blogjava.net/canonical/archive/2008/05/26/202801.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>不完全的计算</title><link>http://www.blogjava.net/canonical/archive/2008/03/16/186614.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Sun, 16 Mar 2008 07:04:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2008/03/16/186614.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/186614.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2008/03/16/186614.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/186614.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/186614.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 在与一些年岁较大的C程序员接触的过程中，可以比较明显的感受到C的思维方式与面向对象思想的不同。C的世界很清澈，先做A, 再做B, 我们所期待发生的计算过程与源代码的结构是直接一一对照的。这意味着程序将要执行的计算过程在编写代码的时刻就已经确定下来。面向对象首先需要确定的是类，对象等中间元素，而并不是最终的计算过程。对象可以之间可以产生很复杂的结构关系，透过这种中间逻辑结构我们来理解最终要发生的计算过程。在事件驱动的应用场景下，面向对象是一种更加有效的描述，<br />
&nbsp; o.someFunc()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o.onEventA();<br />
&nbsp;&nbsp;&nbsp; sub1.someFunc();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ==&gt;&nbsp;&nbsp;&nbsp;&nbsp; sub1.onEventA();<br />
&nbsp;&nbsp;&nbsp; sub2.someFunc();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sub2.onEventB();<br />
如果把对象看作是函数+状态的集合，则对象组装的关系实际上是函数集合之间的一种组装关系。当具体的事件发生的时候，将触发对象上确定的响应函数，此时在各个层面上所实际发生的计算才能被确定下来。<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/canonical/aggbug/186614.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2008-03-16 15:04 <a href="http://www.blogjava.net/canonical/archive/2008/03/16/186614.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WebMVC之前世.今生</title><link>http://www.blogjava.net/canonical/archive/2008/02/18/180551.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Mon, 18 Feb 2008 14:02:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2008/02/18/180551.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/180551.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2008/02/18/180551.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/180551.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/180551.html</trackback:ping><description><![CDATA[&nbsp;&nbsp; 所谓WebMVC即Model2模型是目前Web开发领域的主流模型，Struts/Struts2框架是其典型实现。在概念层面上，这种程序组织模型是怎样建立起来的?与其他Web开发模型(如面向对象模型)具有怎样的联系? 它未来可能的发展方向在哪里? 结合Witrix开发平台的具体实践，基于级列设计理论我们可以看到一条概念发展的脉络。<a href="http://canonical.javaeye.com/blog/33824">http://canonical.javaeye.com/blog/33824</a><br />
<img src="http://www.blogjava.net/images/blogjava_net/canonical/web_app_structure.jpg" alt="" border="0" height="992" width="747" /><br />
&nbsp;&nbsp; 1. 外部视角：原始的servlet规范提供了一个简单的面向IO的程序响应模型。一次前台访问由一个特定的servlet负责响应，它从request中读取输入流，在全局session中保持临时状态，向response中写入输出流。在此基础上，JSP提供的模板概念翻转了程序和输出文本之间的相对地位，简化了文本输出过程。至此，这种整体的程序模型基本上只是规范化了外部系统访问Web服务器的响应模型，并没有对后台程序的具体实现制定明确的约束条件。因此在最粗野的后台实现中，读取参数，业务处理，生成页面等处理步骤是纠缠在一起的，很难理解，也很难重用。每一个后台页面都是一个不可分析的整体。<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;">&lt;%</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;String&nbsp;paramA&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;request.getParameter(</span><span style="color: #000000;">"</span><span style="color: #000000;">paramA</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;ResultSet&nbsp;rsA&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><br />
</span><span style="color: #000000;">%&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;result&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&lt;%=</span><span style="color: #000000;">rsA.getString(</span><span style="color: #000000;">0</span><span style="color: #000000;">)&nbsp;</span><span style="color: #000000;">%&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;String&nbsp;paramB&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;request.getParamter(</span><span style="color: #000000;">"</span><span style="color: #000000;">paramB</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;ResultSet&nbsp;rsB&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><br />
</span><span style="color: #000000;">&lt;%</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;rsB.close();<br />
&nbsp;&nbsp;&nbsp;rsA.close();<br />
&nbsp;&nbsp;&nbsp;conn.close();<br />
</span><span style="color: #000000;">%&gt;</span></div>
<br />
<br />
2. 自发分离：在复杂的程序实践中，我们会自发的对业务处理代码和界面代码进行一定程度的分离。因为我们可以直观的感受到这两种代码的稳定性并不匹配。例如不同业务处理过程产生的结果都可以用一个html表格来展现，而同一个业务处理过程产生的结果页面可能经常发生变化。一般我们倾向于将业务代码写在页面上方，而界面代码写在页面下方，并使用一些原始的分解机制，例如include指令。这种分离是随意的，缺乏形式边界的。例如我们无法表达被包含的页面需要哪些参数，也难以避免全局变量名冲突。需要注意的是，分层的一般意义在于各个层面可以独立发展，它的隐含假定是各层面之间的交互是规范化的，只使用确定的数据结构，按照确定的方式进行交互。例如业务层和界面层通过标准的List/Map等数据结构交互，而不是使用具有无限多种样式的特殊的数据结构。(在弱类型语言环境中，实体对象的结构和Map是等价的).<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;">&lt;%</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;List&nbsp;header&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><br />
&nbsp;&nbsp;&nbsp;List&nbsp;dataList&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><br />
</span><span style="color: #000000;">%&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">&lt;%</span><span style="color: #000000;">@&nbsp;include&nbsp;file</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">/show_table.jsp</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">%&gt;</span></div>
<br />
<br />
&nbsp;&nbsp; 3. 规范分离：JSP所提供的useBean和tag机制，即所谓的Model1模型，是对程序结构分离的一种规范化。业务代码封装在java类中，一般业务函数与web环境无关，即不使用request和response对象, 允许单元测试。tag机制可以看作是对include指令的增强，是一种代码重用机制。tld描述明确了调用tag时的约束关系。调用tag时需要就地指定调用参数，而include页面所依赖的参数可能是在此前任意地方指定的，是与功能实现分离的。此外tag所使用的参数名是局部对象上的属性名，从而避免了对全局变量的依赖。很遗憾的是，jsp tag所封装的仍然是原始的IO模型，对程序结构缺乏精细的定义，在概念层面上只是对文本片段的再加工，难以支撑复杂的控件结构。早期jsp tag无法利用jsp模板本身来构造，无法构成一个层层递进的概念抽象机制，更是让这种孱弱的重用模型雪上加霜。在其位却无能谋其政，这直接造成了整个j2ee前台界面抽象层的概念缺失，以致很多人认为一种前台模板重用机制是无用的。在Witrix平台中所定义的tpl模板语言，充分利用了xml的结构特点，结合编译期变换技术，成为Witrix平台中进行结构抽象的基本手段。实际上，xml能够有效表达的语义比一般人所想象的要多得多。<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;">　</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">jsp:useBean&nbsp;id</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">myBiz</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;</span><span style="color: #000000;">&lt;%</span><span style="color: #000000;">&nbsp;List&nbsp;dataList&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;myBiz.process(paramA)&nbsp;</span><span style="color: #000000;">%&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">ui:Table&nbsp;data</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">&lt;%=&nbsp;dataList&nbsp;%&gt;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">/&gt;</span></div>
<br />
&nbsp;&nbsp; <br />
&nbsp; 4. 框架分离：在Model1模型中，页面中存在着大量的粘结性代码，它们负责解析前台参数，进行类型转换和数据校验，定位特定的业务处理类，设置返回结果，控制页面跳转等。一种自然的想法是定义一个全局的程序框架，它根据集中的配置文件完成所有的粘结性操作。这也就是所谓面向action的WebMVC模型。这一模型实现了服务器端业务层和界面层在实现上的分离，但是对于外部访问者而言，它所暴露的仍然是原始的自动机模型：整个网站是一个庞大的自动机，每次访问都触发一个action，在action中可能更改自动机的状态（作为全局状态容器的session对象或者数据库）。struts作为面向action框架的先驱，它也很自然的成为了先烈。struts中所引入的FormBean, 链接管理等概念已经在实践中被证明是无益的。一些新兴的框架开始回归到通用的Map结构，直接指定跳转页面，或者利用CoC(Convention Over Configuration)缺省映射.<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: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;RegisterAction&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;Action&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;ActionForward&nbsp;perform&nbsp;(ActionMapping&nbsp;mapping,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ActionForm&nbsp;form,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletRequest&nbsp;req,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletResponse&nbsp;res)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;RegisterForm&nbsp;rf&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(RegisterForm)&nbsp;form;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;mapping.findForward(</span><span style="color: #000000;">"</span><span style="color: #000000;">success</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
}</span></div>
<br />
&nbsp;&nbsp; <br />
5. 横向延展：分层之后必然导向各个层面的独立发展，我们的视野自然也会扩大到单个页面之外，看到一个层面上更多元素之间的相互作用．在面向对象语言大行其道的今天，继承(inheritance)无疑是多数人首先想到的程序结构组织手段．后台action可以很自然的利用java语言自身的继承机制，配置文件中也可以定义类似的extends或者parent属性．但是对于前台页面一般却很少有适用的抽象手段，于是便有人致力于前台页面的对象语言化：首先将前台页面采用某种对象语言表达，然后再利用对象语言内置的结构抽象机制．放弃界面的可描述性，将其转化为某种活动对象，在我看来是一种错误的方向．而JSF(JavaServerFace)规范却似乎想在这个方向上越走越远．JSF早期设计中存在的一个严重问题是延续了面向对象语言中的状态与行为绑定的组织方式．这造成每次访问后台页面都要重建整个Component Tree, 无法实现页面结构的有效缓存．而Witrix平台中的tpl模板语言编译出的结构是无状态的，可以在多个用户之间重用．<br />
<br />
&nbsp; 6. 相关聚合：对象化首先意味着相关性的局域化，它并不等价于对象语言化. 当面对一个大的集合的时候，最自然的管理手段便是分组聚合：紧密相关的元素被分配到同一分组，相关性被局域化到组内．例如，针对某个业务对象的增删改查操作可以看作属于同一分组. struts中的一个最佳实践是使用DispatchAction, 它根据一个额外的参数将调用请求映射到Action对象的子函数上．例如/book.do?dispatchMethod=add. 从外部看来，这种访问方式已经超越了原始的servlet响应模型，看起来颇有一些面向对象的样子，但也仅仅局限于样子而已．DispatchAction在struts框架中无疑只是一种权宜之计，它与form, navigation等都是不协调的，而且多个子函数之间并不共享任何状态变量（即不发生内部的相互作用），并不是真正对象化的组织方式．按照结构主义的观点，整体大于部分之和．当一组函数聚集在一起的时候，它们所催生的一个概念便是整体的表征：this指针．Witrix平台中的Jsplet框架是一个面向对象的Web框架，其中同属于一个对象的多个Action响应函数之间可以共享局部的状态变量（thisObj），而不仅仅是通过全局的session对象来发生无差别的全局关联．<a href="http://canonical.javaeye.com/blog/33873">http://canonical.javaeye.com/blog/33873</a> 需要注意的是，thisObj不仅仅聚集了后台的业务操作，它同时定义了前后台之间的一个标准状态共享机制，实现了前后台之间的聚合．而前台的add.jsp, view.jsp等页面也因此通过thisObj产生了状态关联，构成页面分组．为了更加明确的支持前台页面分组的概念，Witrix平台提供了其他一些辅助关联手段．例如标准页面中的按钮操作都集中在std.js中的stdPage对象上，因此只需要一条语句stdPage.mixin(DocflowOps);即可为docflow定制多个页面上的众多相关按钮操作．此外Witrix平台中定义了标准的url构建手段，它确保在多个页面间跳转的时候，所有以$字符为前缀的参数将被自动携带．从概念上说这是一种类似于cookie，但却更加灵活，更加面向应用的状态保持机制．<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;">　　</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;DaoWebAction&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;WebContext{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IEntityDao&nbsp;entityDao;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;metaName;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;Object&nbsp;actQuery(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thisObj.put(</span><span style="color: #000000;">"</span><span style="color: #000000;">pager</span><span style="color: #000000;">"</span><span style="color: #000000;">,pager);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;success();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;Object&nbsp;actExport(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Pager&nbsp;pager&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(Pager)thisObj.get(</span><span style="color: #000000;">"</span><span style="color: #000000;">pager</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;success();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<br />
<br />
&nbsp; 7. 描述分离：当明确定义了Action所聚集而成的对象结构之后，我们再次回到问题的原点：如何简化程序基元（对象）的构建？继承始终是一种可行的手段，但是它要求信息的组织结构是递进式的，而很多时候我们实际希望的组织方式只是简单的加和。通过明确定义的meta(元数据)，从对象中分离出部分描述信息，在实践中被证明是一种有效的手段。同样的后台事件响应对象(ActionObject)，同样的前台界面显示代码(PageGroup)，配合不同的Meta，可以产生完全不同的行为结果, 表达不同的业务需求。<a href="http://canonical.javaeye.com/blog/114066">http://canonical.javaeye.com/blog/114066</a> 从概念上说，这可以看作是一种模板化过程或者是一种复杂的策略模式 ProductWebObject = DaoWebObject&lt;ProductMeta&gt;。当然限于技术实现的原因，在一般框架实现中，meta并不是通过泛型技术引入到Web对象中的。目前常见的开发实践中，经常可以看见类似BaseAction&lt;T&gt;, BaseManager&lt;T&gt;的基类，它们多半仅仅是为了自动实现类型检查。如果结合Annotation技术，则可以超越类型填充，部分达到Meta组合的效果。使用meta的另外一个副作用在于，meta提供了各个层面之间新的信息传递手段，它可以维系多个层面之间的共变(covariant)。例如在使用meta的情况下，后台代码调用requestVars(dsMeta.getUpdatableFields())得到提交参数，前台页面调用forEach dsMeta.getViewableFields()来生成界面. 则新增一个字段的时候，只需要在meta中修改一处，前后台即可实现同步更新，自动维持前后台概念的一致性。有趣的是，前后台在分离之后它们之间的关联变得更加丰富。<br />
<br />
8. 切面分离: Meta一般用于引入外部的描述信息，很少直接改变对象的行为结构。AOP(Aspect Oriented Programming)概念的出现为程序结构的组织提供了新的技术手段。AOP可以看作是程序结构空间中定位技术和组装技术的结合，它比继承机制和模板机制更加灵活，也更加强大。<a href="http://canonical.javaeye.com/blog/34941">http://canonical.javaeye.com/blog/34941</a> Witrix平台中通过类似AOP的BizFlow技术实现对DaoWebAction和前台界面的行为扩展，它可以在不扩展DaoWebAction类的情况下，增加/修正/减少web事件响应函数，增加/修正/减少前台界面展现元素。当前台发送的$bizId参数不同的时候，应用到WebObject上的行为切片也不同，从而可以自然的支持同一业务对象具有多个不同应用场景的情况（例如审核和拟制）。在BizFlow中定义了明确的实体化过程，前台提交的集合操作将被分解为针对单个实体的操作。例如前台提交objectEvent=Remove&amp;id=1&amp;id=2,将会调用两次&lt;action id="Remove-default"&gt;操作。注意到AOP定位技术首先要求的就是良好的坐标定义, 实体化明确定义了实体操作边界，为实体相关切点的构造奠定了基础。<a href="http://canonical.javaeye.com/blog/33784">http://canonical.javaeye.com/blog/33784</a><br />
<br />
9. 背景消除：在Witrix平台中, (DaoWebAction + StdPageGroup + Meta + BizFlow)构成完整的程序模型，因此一般情况下并不需要继承DaoWebAction类，也不需要增加新的前台页面文件，而只需要在BizFlow文件中对修正部分进行描述即可。在某种程度上DaoWebAction+StdPageGroup所提供的CRUD(CreateReadUpdateDelete)模型成为了默认的背景知识。如果背景信息极少泄漏，则我们可以在较高抽象层次上进行工作，而不再理会原始的构造机制。例如在深度集成hibernate的情况下，很少会有必须使用SQL语句的需求。BizFlow是对实体相关的所有业务操作和所有页面展现的集中描述，在考虑到背景知识的情况下，它定义了一个完整的自给自足的程序模型。当我们的建模视角转移到BizFlow模型上时，可以发展出新的程序构造手段。例如BizFlow之间可以定义类似继承机制的extends算子，可以定义实体状态驱动的有限自动机，可以定义不同实体之间的钩稽关系（实体A发生变化的时候自动更新实体B上的相关属性），也可以定义对Workflow的自然嵌入机制。从表面上看，BizFlow似乎回归到了前后台大杂烩的最初场景（甚至更加严重，它同时描述了多个相关页面和多个相关操作），但是在分分合合的模型建立过程中，大量信息被分解到背景模型中，同时发展了各种高级结构抽象机制, 确保了我们注意力的关注点始终是有限的变化部分。而紧致的描述提高了信息密度，简化了程序构造过程。<a href="http://canonical.javaeye.com/blog/126467">http://canonical.javaeye.com/blog/126467</a><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;">&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">bizflow&nbsp;</span><span style="color: #ff0000;">extends</span><span style="color: #0000ff;">="docflow"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #008000;">&lt;!--</span><span style="color: #008000;">&nbsp;引入docflow模型，包括一系列界面修正和后台操作　</span><span style="color: #008000;">--&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">biz&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="my"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">tpls</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">tpl&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="initTpl"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">script&nbsp;</span><span style="color: #ff0000;">src</span><span style="color: #0000ff;">="my_ops.js"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">&gt;&lt;/</span><span style="color: #800000;">script</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">script</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stdPage.mixin(MyOps);&nbsp;//&nbsp;引入多个页面上相关按钮对应的操作<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">script</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">tpl</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">tpls</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">biz</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">bizflow</span><span style="color: #0000ff;">&gt;</span></div>
<br />
<br />
<br />
<img src ="http://www.blogjava.net/canonical/aggbug/180551.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2008-02-18 22:02 <a href="http://www.blogjava.net/canonical/archive/2008/02/18/180551.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关系模型与ORM</title><link>http://www.blogjava.net/canonical/archive/2008/01/06/173154.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Sun, 06 Jan 2008 11:04:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2008/01/06/173154.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/173154.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2008/01/06/173154.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/173154.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/173154.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 关系数据库模型在理论上主要解决的是消除数据冗余的问题。关系模型的数学基础是所谓的集合论，而集合的基本含义正是一组具有某种原子性的互不相同的元素。面向对象技术是对相关性进行局域化的一种手段（相关的数据和操作聚集到同一对象名义下），在这一局域化过程中，相同的元素被识别出来，成为独立的对象。从某种意义上说，关系模型与对象模型是殊途同归的过程，是从不同侧面对同一事物的反映。关系模型中，我们关注的重点是元素组成的集合，允许的连接关系定义在集合之上。而在对象模型中，我们关注的首先是横向关联的实体，实体之间具有稳定的联系。在概念层面上，从对象模型映射到一种关系存储模型只是一个分组问题。为了断开实体之间的直接联系，关系模型创造了一个id字段，而对象模型并不是需要显式id的。在关系模型中，关联并不是通过某种存在的结构来表达的（一个实体持有另一个实体的指针，拥有直接联系），而是将直接关联问题弱化为某种计算过程，我们必须检查id的值（不是某种直接的存在性），通过某种运算过程才能重新发现数据之间的关联。<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 通过id（伴随一个匹配计算过程）来进行间接关联对于保证模型的一致性是非常关键的。在ORM中恢复了对象的强关联其实会造成很多潜在的复杂性。例如为了维护对象层面结构的一致性，在更新父子关系的时候，我们需要同时调用 child.setParent(parent); parent.getChildren().remove(child); 当关联结构更加复杂的时候，这里所需要的维护工作是随之增加的。不过，在ORM中，对象的形态是暂时性的。在ORM的一次session的操作过程中，对于对象状态的修改可以是不一致的。例如我们可以只调用child.setParent(parent); 而不需要同时&nbsp; parent.getChilren().remove(child); 只要我们在此次session操作中，不需要同时用到parent.getChildren(). 这种关联的暂时性对于很多ORM应用来说是必不可少的。<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 对象模型中可以直接表达的结构关系比关系模型要丰富一些，例如继承关系，many-to-many, one-to-list等。但是所有这些都不是真正本质性的差异。抛弃概念诠释，基类与众多派生类之间的关系基本上可以等价于一组one-to-one关系。而当关联对象本身的重要性凸现出来的时候，当我们无法把它约化为对象上的一些附属特性的时候（例如数组的下标），我们必然要建立相应的关联对象，而这正对应于关系模型中的中间关联表。中间关联表上增加额外的字段是一个自然的扩展过程，而对象模型上做这样的扩充往往表现为形态上的重大的不兼容的变化，例如从getManyToManyEntity() -&gt; getToManyRelation(), 这实际上意味着这里的对象形式是偶然的，简化的。 <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 在原始的关系数据库模型中，所有的表之间的地位是平等的，所有字段之间的地位是平等的（主键和外键在参与数据关联时和其他字段的处理方式一致）。这种概念上的均一性和普遍性往往被认为是理论的优美之处。但是现实世界是复杂的，发展的方向就是逐步识别出不同之处，并找出自然的表达形式将这些不同表达出来。均匀的关系模型是对称性最高的，最简化的模型。在面对物理约束时，它隐含的假设是集合之间很少发生相互作用，单表（表单到数据表之间的映射）和主从表是最广泛的情况。试着想象一下关系模型，在思维中一般我们只能看到两个数据表，当考虑到多个表的时候，因为这些表之间没有明确的可区分性，因此它们的意象是模糊的。只有明确意识到主键，外键，主表，从表，字典表，事实表，纬度表这些不同的概念的时候，当对称性出现破缺的时候，我们思维中的模型才能够丰富化起来。<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 关系模型理论应用到数据库具体应用中时，并不需要死守关系范式教条，它们只是描述了某种极端化的对唯一性的追求。面对具体应用的时候，理论本身也在不断丰富化。我并不把现实应用中必然需要增加冗余字段看作是关系理论失效的结果。从关系完全分解，到关系完全不分解之间，我们可以建立大量的模型。建立冗余字段的时候，我们存在着大量可能的选择，到底哪一种选择是最优的，理论方面仍然可以给我们以具体的指导。理论在各种不同纯化程度的关系模型中都可以给我们以直观的建议。数据仓库理论中建立的snowflake模式和star模式，强调了针对主题域的允许部分冗余的关系分解。这里实际上是强调了表之间的不同性。不再是所有的表都处于同一地位。Fact Table和Dimension Table之间的区别被识别出来，并被明确处理。在我看来，这是原始关系模型的一种自然发展，它也是关系模型理论的一部分。理论不应该是单一的，而是提供一个模型级列，在不同的复杂性层次上，我们可以根据理论的指导选择具体的实现模型。<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 关于ORM <a href="http://canonical.javaeye.com/blog/111500">http://canonical.javaeye.com/blog/111500</a><br />
&nbsp;&nbsp;&nbsp; 关系模型中的所谓关系是在使用时刻才定义的，所有建立关系的方式在某种程度上都是等价的，也是外在的。而在ORM中主键与外键之间的关联被独立出来，成为模型内置的部分。这在很多时候简化了数据查询的结构构造过程。<br />
&nbsp;&nbsp;&nbsp; 在ORM中主键因为缓存的存在而显出与其他字段的区别。ORM的使用使得数据存储的分解策略得到扩充。并不是所有的表的更新频度都是一致的，而且表中的数据量大小也不同。字典表一般较小，而且很少更新，可以安全的复制。在整个数据存储框架中，ORM作为独立的技术元素参与数据存储过程，通过主键提供缓存服务，产生了新的数据分布模型，提供了新的性能优化契机。<br />
<br />
<br />
<img src ="http://www.blogjava.net/canonical/aggbug/173154.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2008-01-06 19:04 <a href="http://www.blogjava.net/canonical/archive/2008/01/06/173154.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>代码之外的结构</title><link>http://www.blogjava.net/canonical/archive/2007/12/15/167994.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Sat, 15 Dec 2007 11:46:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2007/12/15/167994.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/167994.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2007/12/15/167994.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/167994.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/167994.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 我在各种场合一直都在强调结构问题是独立的，在程序语言之外存在着独立的，可研究的，富有成效的结构问题。<a href="http://canonical.javaeye.com/blog/147424 ">http://canonical.javaeye.com/blog/147424 </a>在这个方向上更进一步，我们注意到所有的代码并不是天然出现的，而是由人所编制的，因此代码世界内部并不构成封闭的，自足的某个世界。代码中的结构问题并不是由代码本身完全解决的，即在代码之外仍然存在着技术上可研究的结构问题。<br />
&nbsp;&nbsp;&nbsp; 我们在编制代码的同时也在编制着大量的说明文档。这些文档描述了代码片断之间的相互关系，描述了代码未来的扩展方向，描述了代码之间的可能的交互方式，同时也描述了针对现有代码实现的很多具体约束。例如我们在文档中约定某个量要在10和20之间，但在代码中却不一定显式进行了判断。针对代码结构的很多具体约束条件和相关性描述可能只在文档中体现，只在程序员的头脑中存在，而并不一定忠实的在代码结构中得到表达。<br />
&nbsp;&nbsp;&nbsp; 我在设计领域基本持有一种物理实在论，即某种技术相关的约束应该在技术世界中通过技术手段得到表达。只是这里的技术手段却不一定指在应用中加上特定的代码实现，虽然我们在代码实现中更直接的表达设计要求无疑是需要提倡的。为了在程序中有效的维护结构相关性，我们并不一定需要抽象出所有可能重用的代码，并不一定需要确保某一概念在程序中只有精确的唯一的表达。程序中难以直接精确表达的弱关联，仍然可以通过开发/设计工具等技术手段得到有效的维护。我们需要保证的是代码世界中知识的自恰性，而自恰性并不等于唯一性。<a href="http://canonical.javaeye.com/blog/33788">http://canonical.javaeye.com/blog/33788</a><br />
&nbsp;&nbsp;&nbsp; 在Witrix中我们采用一种物理模型驱动的开发方式，<a href="http://canonical.javaeye.com/blog/29412">http://canonical.javaeye.com/blog/29412</a> 由pdm模型出发，自动生成hibernate的hbm文件，java实体类，元数据meta文件，前台Action注册文件等。生成的配置文件通过syncWithModel标记与模型保持着稳定的关联。所有配置文件都支持手工修改，开发工具识别syncWithModel标记，当pdm模型发生变化的时候，工具自动将变化信息同步到各个配置文件中。注意到这里并不是采用一个统一的元数据模型的方式，各个配置文件所表达的信息在一定程度上是重复的，也可能是不一致的。例如后台数据库允许保存100个字节，但是前台meta中我们可能配置只允许录入20个字节。根据不同应用场景的需要，我们可以在各个层面对每个配置文件进行独立的调节. 当然,在一般情况下并不存在这种需要。整个开发过程中，信息表达的自恰性并不是在应用程序代码中得到定义的,而是因为开发工具的存在而在技术上得到保证的。放松模型之间的唯一匹配要求，我们可以得到更加丰富，更加灵活的软件结构。实际上我认为RoR(RubyOnRails)采用直接映射的ActiveRecord的方式虽然有效保证了系统变动中知识的一致性，但是如果不允许在各个层面上都能够自然的定义某种偏离，它在复杂应用中的价值就要打上大大的折扣。<br />
<br />
<img src ="http://www.blogjava.net/canonical/aggbug/167994.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2007-12-15 19:46 <a href="http://www.blogjava.net/canonical/archive/2007/12/15/167994.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>结构的独立性</title><link>http://www.blogjava.net/canonical/archive/2007/12/10/166820.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Mon, 10 Dec 2007 15:57:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2007/12/10/166820.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/166820.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2007/12/10/166820.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/166820.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/166820.html</trackback:ping><description><![CDATA[&nbsp;&nbsp; 设计考虑的是最终需要什么，最终我们要提供的调用接口是什么，我们所直接需要的某个有价值的，直接存在的，直接可以接触的结构是什么，而不是它所依据的原理是什么，不是它的具体构造过程或者构造方法是什么。比如说我们在程序中完全不需要内置Map这一结构，因为它可以通过列表等结构组合构建出来，但是很显然，Map这一概念的直接存在对我们来说是方便的，是经济的，是有效的。我们在思考的时候并不需要考虑它是采用List实现还是采用Set实现，或者任何它本身的构造结构。这一概念在我们的思想中成为某种原子化的东西。<br />
<br />
&nbsp;&nbsp;&nbsp; 那么，我们到底需要构建哪些概念，才能够最方便的基于这些概念应对万千应用系统的开发呢。 这是我们需要在结构空间作出探索的。 这里的思维方向不是把系统推向某种纯粹化，某种极致的简单化，而是让它更加物理化，揭示出更多的层次，更加关切在物理约束情况下如何实现灵活性的最大化。一种概念在物理上如果被证明能够在很多场景下成为不变的基元，则它便是有价值的，是可以进行物理诠释的。<br />
<br />
&nbsp;&nbsp; 很多人习惯于接受语言存在的现实，接受设计后的结果，但是作为程序语言设计者，他们又是如何工作的？他们是否真的是从纯粹的数学关系推演得到所有的语法特征，还是他们预先已经在心中设定了应该出现的语法特征，然后去寻找它的数学表达，只是借此清除思维中潜在存在的矛盾性呢？<br />
<br />
&nbsp;&nbsp;&nbsp; 语言中存在的所有特征是经过全局考虑的，是清除了所有概念的矛盾冲突的。但是在现实中，我们偶然构造的结构却可能是局限于当下的信息构造的，因此它们相会的时候，可能会出现不协调，可能会出现结构障碍。例如同样是关闭操作，有些人命名为close, 另一些人命名为destroy. 可能一个具有额外参数，另外一个没有。这里可能需要一种adaptor接口的封装，也可能使用ruby那种method-missing的动态判断。对于更加错综复杂的结构问题，其解决方案就不是那么显然的了，但这并不意味着我们无办法可想。究竟设计何种结构边界才能最小化结构融合时所要付出的代价呢？结构被识别并表征出来以后，是否允许它在一定范围内有所变形？在变形中我们需要保持的拓扑不变量是什么？结构动态调整的时候，我们是否需要定义调整的物理代价，是否能够定义某种动力学？<br />
<br />
&nbsp;&nbsp; 我所阐述的只是在计算机理论中从数学视角向物理视角的转换，它不是必然给你提供某种超越当下的能力，而是提供一种不同的眼光看待所有的一切。视角变换后，我们发现了一些新的命题，而在原先的视角下在我们的话语体系中原本是无法表达这些命题的。串行程序假设了只有1颗CPU, 而函数式语言假设了可以有无限多个CPU, 你不觉得1至无穷之间缺点什么吗。我们可以创造一些东西把1至无穷之间的空白补齐，概念空间是连续的。<br />
&nbsp;<br />
<br />
<img src ="http://www.blogjava.net/canonical/aggbug/166820.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2007-12-10 23:57 <a href="http://www.blogjava.net/canonical/archive/2007/12/10/166820.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于抽象性的一些说明</title><link>http://www.blogjava.net/canonical/archive/2007/12/09/166520.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Sun, 09 Dec 2007 14:25:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2007/12/09/166520.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/166520.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2007/12/09/166520.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/166520.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/166520.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp; 没有人否认抽象的意义，但是抽象是否就是抽象到无穷大，这是个可以明确定义的问题，也是数学领域正在解决的问题。在我们的思考中没有明确定义何处是边界，
没有明确的限制，这便是导向无穷的一种思维方式，它和现实中是否真的允许消耗无限多的资源，创建无限多的对象无关。当我们认为自己明白了终极的意义，明白
了一种推向无穷的抽象，这并不是理解了世界的全部，我们仍然要明白如何解决一些更加小范围，但是却又普遍发生的事情。
<br />
例如现在我的系统中只需要10个相互依赖的线程，如果我们定死了10这个数字，显然我们可以发展一种这个领域特有的高效的一些算法结构。而抽象到通用语言
中的时候，显然我们只能假设线程数是任意大，或者是充分大的，而无法充分利用10这一领域信息，因此在这个意义上我说通用语言不是有效的。
<br />
说到10这个确定的数字，不过是一种极端化的比喻。我常说概念是连续的，并不是非此即彼的，因此并不是从一种普遍情况到一种最特殊的情况之间不再有其他情
况了。在这中间环节，存在着非常深刻的复杂的物理事实。但是这些事实却又是某种有限性向我们揭示出来的。（请不要把这里的有限性理解为算术中的10以内）
<br />
<br />
现在来一个理论推演吧：
<br />
1. 任何系统都在一定约束下运行，即它们需要符合某些约束条件
<br />
2. 通用语言描述了某些结构，但是这些结构是充分通用的，能够应用到尽可能广泛的领域的
<br />
3. 线程数=10这个约束过份特殊，显然通用语言是不会考虑这个约束。实际上目前在通用语言设计中，无限资源假定基本都是默认的。
<br />
4. 我们承认某些现实的约束通用语言是不会考虑的
<br />
5. 在最特殊的，明显不会考虑的约束以及非常通用，一般通用语言必然考虑的约束之间，是否存在着更多的，非平凡的结构呢
<br />
6. 假如10年以内我们所有的硬件都只能支持10个内核，在我的产品研发中假定10个线程有问题吗。难道我在开发的时候就不再需要抽象了吗。我在其他方面仍然是需要建立抽象的。
<br />
7. n个抽象约束+1个具体约束，以及 n个无限约束+1个有限约束 仍然是有效的抽象形式。原谅我在这里又使用了有效一词，它真的很难理解吗。
<br />
8. 不是在我们的思维中存在着具体的或者有限的物理量,就意味着这种思维是不抽象的.
<br />
<br />
函数式语言或者任何一种其他我们已知的与Turing机等价的语言，它们在某种数学的含义上说是"没有差别的"。但是在我们的实际使用过程中，显然我们是
能够感受到它们之间的结构差异的。否则那些不断发明新的函数式语言的人的大脑都进水了吗？在具体使用中，总有人偏好这个语言,有人偏好那个语言,
总是某种情况下应用某个语言会方便一些,另一些麻烦一些。难道在所有函数式语言中开发类似ErLang解决的那些程序结构都是一样方便的吗？
<br />
<br />
有些人的论调是无论啥都逃不出函数式语言的思想。但是假如现在限定你必须使用java语言来开发商业应用，难道你罢工吗？如果你不使用函数式语言，你所做
的工作就不是程序工作了？你所解决的难道不是程序结构问题了吗？现在就是有一个结构问题要解决, 它是和语言无关的. 语言提供了就可以直接用,
语言没有提供我们可以写代码构造. 难道除了语言直接体现的结构之外, 程序本身就无法构造任何具有通用价值的结构了吗？</p>
<p>   我在说到函数式语言的时候，基本的态度只是说不要太沉迷于一种特殊的抽象方式，应该多看看别的视角。在不同的情况下存在着做事情的不同的最优方式。思维中不要只允许永远，而容不下现在。
<br />
<br />
非此即彼，天下唯我,是我们思维中经常陷入的一个误区。现在计算机领域所谓的理论主要是基于数学视角的，没有考虑物理世界因为我们观察的有限性，因为资源
的有限性所造成的种种约束，此外数学中目前也没有考虑到物理世界真实的各种复杂性的存在。在我们想到一种计算机理论的时候，图像过于简单化，这种简单化被
认为是优美的全部。其实我们应该思维更加开放一些。
</p>
<img src ="http://www.blogjava.net/canonical/aggbug/166520.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2007-12-09 22:25 <a href="http://www.blogjava.net/canonical/archive/2007/12/09/166520.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于语言有效性的一些澄清</title><link>http://www.blogjava.net/canonical/archive/2007/12/09/166472.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Sun, 09 Dec 2007 09:19:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2007/12/09/166472.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/166472.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2007/12/09/166472.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/166472.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/166472.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 数学上的有效性与物理中的有效性是不同的，例如对于密码学问题，如果通过穷举法破解密码成功时，经过这些密码加密的数据已经过了有效期限，此时我们在数学上定义穷举法不是一种有效的破解方法。但是物理层面上我们说只要一种方法比另一种方法能够更快的解决问题，我们就说第一种方法比第二种方法有效，而无论密码被破解的时候该密码是否已经过了有效期限。<br />
<br />
&nbsp;&nbsp;&nbsp; 我所表述的论题并不是说特定的领域结构无法在某个特定的通用语言中有效实现。我想很多人对我的话语都有些误解。<br />
<strong>如果我们认为一种通用语言是比较稳定的,则它一般选择只内置一些通用的不带有领域特定含义的概念. 而缺乏领域知识,或者说因为通用语言故意的摒弃领域依赖, 它在处理领域相关的问题的时候并不是有效的.这种有效性不是数学含义上的,而是可以进行物理度量的.</strong> <br />
现在ErLang对通信领域具有良好的支持，你可以说它对于通信领域的结构是有效的。但是显然在ErLang中编写界面就不如面向对象语言得心应手。在ErLang中实现界面结构的时候，它对于界面结构的表述就不是那么符合我们直观的，对我们的实现过程来说就不是那么经济的。因此在界面结构的实现上，目前我们可以说ErLang相对于面向对象语言而言就是不那么有效的。也许你会说ErLang做XX发展之后怎见得就更差。但是如果允许引入未来这一具有无限可能性的因子，我们基本上无法针对现实的情况作出判断。例如我们目前并无法证明广义相对论相对于牛顿力学是更加精确的，如果允许在太阳星系中增加越来越多的隐蔽的摄动星体的话。按照库恩的科学革命论，每一个科学时代都具有着自己的科学范式，它总是具有着充分的自我辩护能力。范式的更新意味着格式塔的崩溃。回顾历史，哥白尼刚提出日心说的时候，并不是在计算精度，计算简洁性上真的远胜托勒密的地心说，只是日心说的哲学隐喻撼动了人心。<br />
<br />
&nbsp;&nbsp;&nbsp; 我说<strong>实际上现在的通用语言也是无法有效承载Domain Specific Structure的</strong>，这并不是意指在通用语言中无法针对特定应用作出特定扩展来支持特定的结构，而是说Domain Specific Structure是任意多的，作为通用语言它不应该把越来越多的结构内置在语言中(这不是很多人对ruby的希冀吗)，这么做对它来说首先是不经济的。同时某些特殊的结构在一定的场景下是有用的，但是把它抽象出来扩展到通用领域的时候，会出现有效性的丧失。例如现在我的系统中只需要10个相互依赖的线程，如果我们定死了10这个数字，显然我们可以发展一种这个领域特有的高效的一些算法结构。而抽象到通用语言中的时候，显然我们只能假设线程数是任意大，或者是充分大的，而无法充分利用10这一领域信息，因此在这个意义上我说通用语言不是有效的。<br />
<br />
&nbsp;&nbsp;&nbsp; 传统上数学使用的一种逼近范式是：当n趋于无穷大的时候，偏差趋于无穷小。现在物理学对数学的一种常见要求却是：当n限定在有限数量范围的时候（例如10以内），我们如何才能尽量减少偏差。这要求对小样本数学进行深入的研究，它所具有的物理内涵也是不同的。<br />
<br />
&nbsp;&nbsp;&nbsp; 在物理的视角下，我们所关心的不是世界在终极的意义上能否分解为函数的复合，不是要导向一种宗教式的顶礼膜拜，而是强调要尊重自己所直接感受到的，充分利用我们因为在这个世界上存在而获得的直观意象，发掘自己的直觉，这样我们才能在无限复杂的世界上借助有限的信息做出选择。<br />
<img src ="http://www.blogjava.net/canonical/aggbug/166472.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2007-12-09 17:19 <a href="http://www.blogjava.net/canonical/archive/2007/12/09/166472.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于通用语言能力的一些澄清</title><link>http://www.blogjava.net/canonical/archive/2007/12/09/166375.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Sat, 08 Dec 2007 16:16:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2007/12/09/166375.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/166375.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2007/12/09/166375.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/166375.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/166375.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 我在前面的文章中列举了大量物理学相关的例子来试图说明采用物理视角的必要性,但是可能因为物理事实大家不熟悉,结果直接被无视了. 在本文中我想有必要举一个软件领域的例子。只是在实际思考的过程中,我主要还是基于物理概念进行推理.<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 首先我所谓&#8220;<strong>现在的通用语言</strong>&#8221;，它并不意指&#8220;<strong>现在至未来所有通用语言之合集</strong>&#8221;，而是指&#8220;<strong>目前正在被使用的某一种通用语言</strong>&#8221;，这种差别便体现了我所强调的不同的价值观和不同的视角。不是一种覆盖一切的全称判断，而是在特定物理约束下的物理实体。<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 现在无论我们设计什么大型系统，一般总是要优先考虑微内核设计。但是很显然，如果我们的编程控制能力极强（强大到不现实的地步），我们可以把所有的代码实现为一个大的整体。一个整体的好处是勿用质疑的，否则Linux Torvalds就不会有信心和Tanenbaum PK。但即使是Linux, 随着系统越来越庞大，在内核中也补充了很多模块管理策略。我并不把这种情况看作是一种现在技术能力不到位所造成的结果，而是把它看作是在现实的物理约束下所促成的一种必然的选择。<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 按照类似的逻辑，我认为在通用语言层面不应该导入越来越多的特征，实际上也不可能把所有可能的结构方式都内置在语言中（这种不可能不是数学意义上的不可能）。这会破坏一种语言的纯洁性，使得它极难维护和发展。为了扩大通用语言的有效应用范围，一种显然的方式是在语言中定义一些支持结构再次抽象的机制，通过可插拔的方式实现与domain相关的知识的融合。ruby这样的语言提供了大量的元编程机制, Witrix平台中tpl模板语言也发展了一系列编译期结构构造技术, 但是显然它们都不能说是结构抽象技术的终极形态. 目前我对所有通用语言所提供的结构抽象和结构组装能力都是不满意的,因此在Witrix中发展了一些领域特定的结构融合手段.例如根据"继承"关系的结构诠释(继承可以看作是两个一维集合之间的覆盖关系), 我们扩展了extends的结构操作方式, 定义了广义的extends算子. 这些特定的结构关系目前在领域特定的BizFlow语言中体现, 它们在通用语言中是难以想象的, 而把它们放置在通用的语言中也是不合适的(这种复杂的结构融合操作如果不能结合领域知识进行直观的理解, 必将导向一种思维的混乱). 这就是我所谓"现在的通用语言无法有效承载Domain Specific Structure"的含义. 这种说法其实类似于"集合论是无法包容所有数学结构的". 我们在集合论中只研究最普遍的关系,而特定的结构在特定的学科中研究. <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 关于ErLang的例子, 我的原意是用来说明结构问题是独立的,它是<strong>和具体语言无关</strong>的.即基于消息传递发生数据关联的超轻量级进程模型这一结构不是和ErLang语言绑定的. 为此我特意加了一段说明:"这里不是要证明某种语言中无法描述这些结构，而是说结构是客观存在的，它并不是要在基础语言层面得到充分解决的".<strong> 即使在语言层面我们并不解决这个结构问题, 它仍然客观存在着,我们仍然可以用其他的技术手段去定义,去解决. 解决了这个结构问题就必然会带给我们价值,而无论我们使用何种实现语言</strong>.<br />
<br />
&nbsp;&nbsp;&nbsp; "什么原因，什么样的约束条件,导致了现在的通用语言是无法有效承载消息传递发生数据关联的超轻量级进程模型". 这一命题并不是我原文中论点的合理推论.我并不是要说某一种特定的领域结构无法在一种特定的通用语言中得到支持.而是说如果我们认为一种通用语言是比较稳定的,则它一般选择只内置一些通用的不带有领域特定含义的概念. 而缺乏领域知识,或者说因为通用语言故意的摒弃领域依赖, 它在处理领域相关的问题的时候并不是有效的.这种有效性不是数学含义上的,而是可以进行物理度量的. 现在也有很多人认为ErLang并不是真正的通用语言,它是针对通信领域进行了特定结构调整的, 是内置了领域特定结构的. 而目前在ErLang上建立GUI的努力也并不算是成功. <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 在前文中我举了一个例子试图说明:"在限定的物理约束下，我们的选择范围会大大缩小". "比如说我现在有无穷多种方式从北京跑到上海，但是如果限定只允许用1升汽油，那么我们的选择就近乎于0". 这里并不是要说明加上物理约束之后,我们便没有任何选择了.而是说物理约束对无穷多的可能方式起了<strong>限定选择</strong>的作用, 它最终造成我们在具体的物理场景下可能只有非常有限的选择. 例如现在允许用100升汽油, 有多少种运输方式可以满足我们的要求? 如果允许1000升呢? 但是如果不考虑所有物理约束, 我们是否能够证明说: 飞机和拖拉机的运输能力是完全一致的, 因为它们都能从北京开到上海. <br />
<br />
&nbsp;&nbsp;&nbsp; 我的观点是结构问题是独立存在的,它具有自身的价值, 研究它也需要建立特定的价值观. 一个结构可以体现为语言上的某种语法特征, 也可以通过框架等实现, 或者表现为某种设计模式,某种编程技巧. 我们在思考结构问题的时候并不是从特定语言的机制出发的, 当语言不直接支持的时候我们可以发展特定的实现技术支持它. 在未来的日子里某个结构可能被证明具有普适的价值,它会被吸收到某个通用语言中成为所有程序的支撑结构, 但是更多的结构永远都不会进入通用语言, 而是居留在某个特定的领域. 通用语言的发展并不是完全基于抽象的数学分析而进行的, 它可以从更加丰富的物理世界中吸取营养. 当一种结构进入通用语言的时候, 它所带来的绝对不只是一组数量关系,而是同时带来一系列经过实践检验的物理诠释. <br />
<br />
&nbsp;&nbsp;&nbsp; 我所谓的领域并不是指业务领域, 而是结构领域, 一个可以定义特定结构的物理场景. 一个特定的结构仍然可以支撑着任意多的具体应用. 例如CRUD操作可以作为数据管理模型. BizFlow作为界面和单实体的交互模型.<br />
<br />
&nbsp;&nbsp;&nbsp; 函数式语言为我们提供了一种具体的技术工具, 但是在现实的开发中, 为了有效的处理结构问题, 显然我们需要多种视角的组合, 而不是把所有可想见的图景都纯化为函数. 我们对世界的体验是多样化的. 这就是我所谓"世界比函数的集合要复杂"的含义. <br />
<img src ="http://www.blogjava.net/canonical/aggbug/166375.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2007-12-09 00:16 <a href="http://www.blogjava.net/canonical/archive/2007/12/09/166375.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>对语言与结构的说明</title><link>http://www.blogjava.net/canonical/archive/2007/12/08/166187.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Fri, 07 Dec 2007 18:51:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2007/12/08/166187.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/166187.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2007/12/08/166187.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/166187.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/166187.html</trackback:ping><description><![CDATA[&nbsp;&nbsp; 每当我在文字中对函数式语言有些不敬之意时,便好像动了某些人的奶酪,以至我的言辞总在被曲解后遭到排斥。我想这就是因为视角差异过大所造成的. 但是谦虚谨慎是传统的美德, 不能容纳他人的观点只会妨碍自己在某些方向的探索。<br />
&nbsp;&nbsp; 首先请不要轻易怀疑我的知识水平。当然如果总无法聚集起足够的注意力来理解别人话语中的细节，我也无话可说。<br />
&nbsp;&nbsp; 容纳他人的观点就意味着不要总在自己的话语体系中试图找到反例. 一个人总是受限于他的知识范围，因此他也经常在自己的知识范围内篡改曲解别人的意见。我从未说过 "一个具体的问题是现有的通用语言无法描述的". 我说的是"现实开发中所需要处理的结构问题并不是在语言层面得到充分<strong>解决</strong>的", "<strong>现在</strong>的通用语言也是无法<strong>有效</strong>承载Domain Specific Structure的". 请注意我对定语和动词的选择。其实我已经举了大量的例子来进行说明，但可能因为大多数人不是物理背景,对相关的内容不熟悉，所以直接无视了。这也很对，符合物理学的精神。<br />
<br />
&nbsp;&nbsp; 可能大多数人都知道函数式语言和命令式语言都是和图灵机等价的，因此它具有某种终极能力，怀疑它无异于怀疑我们世界存在的基础。但是请注意，这种等价性是数学性的。它潜在的要求是无限的能量和时间消耗。如果在限定的物理约束下，我们会发现我们的选择范围会大大缩小。所以我说"函数式语言和命令式语言的计算能力相同，但是在具体的情形下它们的描述能力是不同的". 比如说我现在有无穷多种方式从北京跑到上海，但是如果限定只允许用1升汽油，那么我们的选择就近乎于0。飞机和汽车的运输能力是相同的吗。物理学的一个基本精神在于一种物理性的约束是始终存在的。而事实上，我们在实际工作中也总是在各种有限的物理条件下工作。<br />
<br />
&nbsp;&nbsp; 也许有些人认为这种区分是无关紧要的，我们只关心某种终极的东西。但是物理学中有着太多的例证，说明在有限约束下，整个系统呈现出完全不同的性质。在通信领域我们都知道Shannon定理，它的物理诠释是在有噪声的信道上可以<strong>有效</strong>的进行<strong>准确</strong>的信息传递。但是这一诠释只能在有限的数学精度（远大于我们实际需求的精度）上成立, 在绝对准确的数学意义上，这是不可能的事情。<br />
<br />
&nbsp;&nbsp; 你觉得现在的通用语言做起领域相关的东西来很方便吗，这就是我所谓无法有效承载的含义。在这里我也没有否认"未来的牛语言可以轻松搞定目前难题"的可能性。<br />
<br />
&nbsp;&nbsp; 因为所有的软件设计最终都要落实到某种代码实现上，所以怎么会有什么神秘的软件结构是现有的语言无法描述的呢。但是ErLang中那种高并发，支持错误恢复的程序结构是在其他语言中能够轻松实现的吗。很多人不是在潜意识中认为ErLang的成功是函数式语言排他性的成功吗，不是认为命令式语言无论如何实现不了ErLang的程序结构的吗。很显然，在命令式语言中是无法直接实现ErLang中的程序结构的，否则它就变成了函数式语言，但是所有发生在ErLang世界中的事实都一样可以发生在命令式语言的世界中。ErLang语言的编译器可以是使用命令式语言实现的，在终极的意义上，语言之间能有什么区别呢？<br />
<br />
&nbsp;&nbsp; 我说"实际上现在的通用语言也是无法有效承载Domain Specific Structure的", 这还有另一层含义。通用语言设计总是要考虑到内置结构的某种通用性，设计时能够凭依的信息较少，因此不可能直接制造某种复杂的领域相关的结构。而目前已知的通用语言中提供的结构抽象的手段也不够强大（实际上我认为任何语言都不会强大到内置所有结构，也无法提供所有的结构抽象手段）， 相当于是把领域结构问题推给程序员解决。这就如同C语言把内存管理推给程序员解决一样。现在ruby比较流行不就是因为它能够动态处理很多结构问题吗，但是它现在所作的一切就是足够的了吗。难道二十年之后再来看这个语言，不能够发现它存在着巨大的改进空间吗。我们目前在Witrix中通过tpl模板语言，bizflow extends等机制，结合整体框架设计实现了一些与ruby不同的结构构造方法。这些手段都极大的增强了我们面对领域问题时的信心，也确保了我们的领域知识是技术层面上可积累的。但是即使这样，我对程序发展的现状就是满意的吗？难道不存在更加丰富的结构知识等待我们去发现吗？一般人总是习惯接受已经存在的现实，在有限的职业生涯中把它们当作不变的真理，却没有耐心的去思考如何去改变。<br />
<br />
&nbsp; 我认为很多结构问题不是需要在语言层面得到解决的，而是应该在独立的结构层（平台，框架）进行解决。这意味着没有必要在语言层面直接内置某种特定的结构，内置某种特定的结构抽象手段。这基本类似于说不要把集合论扩大到包含所有的数学关系，请在别的学科分支中进行研究。需要注意的是，我所谓的领域知识不是特定的业务知识，而是从业务知识中可以分析得到的某种更加通用的普适的结构知识，甚至是可以使用数学进行精确描述的。<br />
<br />
&nbsp; 现代软件发展的时间还很短，与数学和物理学这样深刻的学科相比，它无疑是相对幼稚的，是待成长的，是更加的不完美的。在程序构建的基本问题上并没有抽象出什么可以实际操作的精确规律。这是所谓Pattern在软件业流行的部分原因：我们希望用这种半形式化的方式捕获某种思考的结果。但是软件真的除了基于抽象数学的全局的全称性的证明之外，不能够在局部进行某种更加复杂，更加严谨的分析吗。<br />
<br />
&nbsp;&nbsp; 我们说结构问题是独立的，这也意味着它和具体的实现语言具有某种意义上的分离性。通过一种语言书写的结构可以在另一种语言中得到表达。我们可以建立语言中立的技术结构。一种所谓的结构在概念上具有某种确定的形态，我们可以脱离具体的语言来理解它。例如我说"面向对象的继承关系从结构观点上看是两个一维集合之间的覆盖关系". 在java中我们可以直接使用语言提供的继承机制，而在C语言中我们就需要建立某种结构体，手动维持所有的指针关联。而在Witrix平台中，我们从继承的结构诠释出发，定义了更加复杂的extends算子，这就需要利用java语言编制特定的parser来实现了。但是显然，在思考的时候我们所有的思维指向是结构本身，而不是任何通用语言的语法。<br />
<br />
&nbsp;&nbsp; 在物理学中，通过摄动分析我们可以清楚地意识到：同样一个物理现象对应的数学模型可以是众多的，但是在特定的参数区我们会选择某种特定的数学表述，并确定其中的待定参数。<br />
<br />
&nbsp;&nbsp; delta函数是物理学家狄拉克引入的，在Schwatz引入分布概念建立广义函数论之前，物理学家们已经使用这一函数工作了很多年。后来Abraham Robinsen利用数理逻辑方法，建立了非标准分析，通过模型论的方法精确定义了无穷小的概念，从更加直接的角度论证了delta的合理性。但是在物理学家看来，这些数学又有什么区别呢？物理学只是按照物理的诠释进行工作，具体的数学只是它可选的工具而已。<br />
<br />
&nbsp;&nbsp; 物理的真理并不是蕴含在数学中的，它需要我们独立的探索，从与数学不同的观点进行思考，检验，最终我们才能做出真正的发现。广义相对论可以采用Riemman几何进行描述，但是它的物理诠释却是Einstein提出的. 没有人说Riemann或者Hilbert发现了广义相对论。另外一方面，因为Einstein的工作触发了对于微分几何的更加深入的研究，靠着物理直觉的导引，我们将这一数学分支推进到了难以想象的深度。"数学是无法涵盖物理学的". 这不是说最终物理学无法采用数学语言进行描述，而是说在这一发展过程中，所有思想的推动来源于物理学的经验，来源于我们在这个物质世界上所进行的反复验证。不是在一个封闭的小屋中，整天摆弄各种数学符号，我们就能够发明所有的物理公式所对应的数学。实际上，现在学术界普遍承认，没有物理学的推进，很多数学的进展是不可能发生的。<br />
<br />
&nbsp;&nbsp; 物理系每天都在演算着Feynman路径积分, 但是所有人都知道这是没有什么严格的数学依据的.目前并无法定义路径积分的收敛性,但是所有人对此避而不谈. 只要形式演算合法,物理预测符合实验, 合理性的证明只是数学家们的事情. 在量子场论中所采用的重整化(Renormalization)方法不过是回避无穷大问题的一种形式手段.我们仍然无法在数学层面对所有的演算都给予合理化解释. 在更多的物理分支中工作，你就会发现物理学家的胆子不是一般的大。也许在未来我们能够发现这些物理过程背后数学机制的精确定义, 但也许最终我们也无法找到合适的定义方式. 但这对物理学家来说, 并不是很大的打击.因为指引我们的是物理直觉，是独立于数学的物质世界的意象。<br />
<br />
&nbsp;&nbsp; 我所想讨论的不是某种终极意义上的可能性，不是绝对概念之间的冲突，而是在物理现实的约束下，我们如何才能有效工作的问题。我已经反复表述了自己的观点: "<strong>结构是可抽象的，是具有独立意义的。这就是Witrix所提出的面向结构的设计视角。不是强调对象的所谓业务含义，不是强调某种通用语言（例如ruby）的灵活的语法结构。在这之间存在着厚重的具有物理意义的可以进行结构分析的技术层</strong>". 也许有人觉得我说的这是废话, 但是当系统化的执行一种思想的时候,就会揭示出未预料到的可能性. 整个Witrix平台简单的说起来就是"<strong>面向结构的级列分析</strong>", 但是如何找到合适的技术形式来体现这一思想,却绝对不是一件平凡的事情. "在Witrix中我们实现的代码重用程度和程序整体结构控制能力是超越了目前所有已知的公开技术的。这不是什么哲学，而是我们在残酷的商业竞争中得以生存的资本".<a href="http://canonical.javaeye.com/blog/126467 ">http://canonical.javaeye.com/blog/126467 </a><br />
<br />
&nbsp;&nbsp; 在我看来，计算机领域充斥着纯数学的深沉遐想和从工程实践而来的轻佻常识，还没有注意到物理学所能带来的不同的同样深刻的视角。我常说，好好学习物理是必要的，因为这个世界远比你想象的要复杂的多。<br />
<br />
<br />
<img src ="http://www.blogjava.net/canonical/aggbug/166187.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2007-12-08 02:51 <a href="http://www.blogjava.net/canonical/archive/2007/12/08/166187.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于函数式语言的一些说明</title><link>http://www.blogjava.net/canonical/archive/2007/12/06/165900.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Thu, 06 Dec 2007 14:12:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2007/12/06/165900.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/165900.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2007/12/06/165900.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/165900.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/165900.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 我的观点并不是什么具体的程序结构问题不能用函数式语言处理.我所要表述的是这和函数式语言中能否加入结构解决任意复杂问题无关。为什么所有的问题不能在集合论中解决，为什么要有独立的数学学科。物理学所有的定律都使用数学表述，是否意味着物理学的真理蕴含在数学之中。<br />
&nbsp;&nbsp;&nbsp; 我说<strong>实</strong><strong>际上现在的通用语言也是无法有效承载Domain Specific Structure的</strong><em><strong>。</strong></em>其实与以下说法是类似的<br />
<strong>数学是无法涵盖物理学的，现在的已知的数学工具是无法有效承载尚未得到充分探索的领域的物理的</strong><br />
&nbsp;&nbsp;&nbsp; 我说<strong>我所关心的不是语言层面的问题</strong><em><strong>。</strong></em>这类似于说<strong>不要把所有物理问题都推到数学层面去解决</strong>。<br />
&nbsp;&nbsp;&nbsp; 我们应该研究独立的结构，应该建立单独的价值观和方法论。不要谈及一个技术进展的时候就说某某语言好，不是一说到DSL的优点就要去抱ruby的大腿。此外，我的观点也不是去做业务分析，不是去如何更好的实现业务到基础技术结构的映射。<br />
&nbsp;&nbsp;&nbsp;
<strong>不是强调对象的所谓业务含义，不是强调某种通用语言（例如ruby）的灵活的语法结构。在这之间存在着厚重的具有物理意义的可以进行结构分析的技术层。</strong><br />
&nbsp;&nbsp;&nbsp;
我想说这个结构层面现在并未得到充分的关注，我们对于结构的问题并不是非常清楚，对程序结构的稳定性更是少有经验。我们在Witrix中做了大量的工作，试图做到如下的图景：<br />
&nbsp;&nbsp;
<strong>永远只写代码片断，而所有的代码片断组合在一起又构成一个可理解的整体</strong><br />
&nbsp;&nbsp;
<strong>对背景不是分解让其成为可见的部分，而是采用追加的，增删的方法对背景结构进行修正，则我们有可能在没有完整背景知识的情况下，独立的理解局部变化的结构。即背景是透明的，知识成为局部的。</strong><br />
<a href="http://canonical.javaeye.com/blog/126467">http://canonical.javaeye.com/blog/126467</a><br />
&nbsp;&nbsp;&nbsp;
在Witrix中我们实现的代码重用程度和程序整体结构控制能力是超越了目前所有已知的公开技术的。这不是什么哲学，而是我们在残酷的商业竞争中得以生存的资本。<br />
<br />
号外：<br />
&nbsp; 不要把具体的技术和一种技术思想混为一谈。一种实现总是包容了太多的思想。思想错了，实现对了。实现死了，思想活着。<br />
<img src ="http://www.blogjava.net/canonical/aggbug/165900.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2007-12-06 22:12 <a href="http://www.blogjava.net/canonical/archive/2007/12/06/165900.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于函数式语言的只言片语</title><link>http://www.blogjava.net/canonical/archive/2007/12/05/165664.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Wed, 05 Dec 2007 14:09:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2007/12/05/165664.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/165664.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2007/12/05/165664.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/165664.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/165664.html</trackback:ping><description><![CDATA[1. 函数式语言可以合理的看作是泛函分析思想的一种体现，从历史发展的时间上看大概也是具有这种可能性的。在Backus的论文中对函数式语言的一种乐观的情绪甚至扩大到functional algebra can be used to tranform programs and to solve equations whose "unknowns" are programms in much the same way one transform equations in high school algebra。这种信心只能来源于泛函分析和方程论，来自于数学分析学的发展。将函数的函数作为分析对象就构成泛函分析。泛函分析的最核心的思想当然不等价于它所研究的那些无穷维空间，不等价于种种正交基的构造。它的思想核心在于函数的函数具有独立的分析价值，具有脱离数量空间的具体的结构。这也是函数式语言试图推销的一种理念。<br />
<br />
<br />
2. 最近这些年来一种称为"范畴"(Category)的东西在计算机理论研究中频频出现。范畴论是从同调代数发展而来的一种较新的代数语言，但它显然也不是可以解决任何问题的灵丹妙药。多一种表达方式当然在某种程度上可以增进我们的理解。但是范畴本身只是研究一种基础结构，它本身并没有承载所有的物理事实，基于它不可能对所有的规律一网打尽。不是明白了范畴，就懂了程序。范畴论是一种基础性的语言，有些人致力于基于范畴论来构建数学的其他分支，取代集合论的地位。将计算的本质重新归结于范畴论是无意义的，它不过是对事实的另一种陈述方式。说&#8220;函数式语言是基于范畴&#8221;是无意义的，因为这和说&#8220;所有现代数学都基于集合论&#8221;一样。无法发现新的相互作用关系，所有的概念都只是同义反复。不是一拿起数学，就找到了组织。<br />
<br />
3. 我对函数式语言并没有什么反对意见。它是非常重要也非常优美的一种技术思想。但是现在一些函数式语言的狂热支持者似乎对函数世界充满了乌托邦式的幻想，一种大一统的世界观让人迷醉，但是它却解决不了现实的问题。所以我说无法认同函数式编程的世界观。作为一种具体的技术工具，问题不在于函数式语言是否体现了计算的本质，而在于它是否向我们提供了称手的兵器。现在我要计算两个小球相互碰撞的问题，我可以操起广义相对论，量子力学啥的开始大干一场，也可以用个牛顿力学小试牛刀，甚至可以只用反射关系摆个等式。但是在绝大多数情况下我们都会说这里面的物理是弹性反射而不是相对论。在理论分析中我们经常使用平面波假设，但只要实际关心的对象不在波包的边缘，没有人会认为平面波不是真实的物理机制。理论物理不是理想物理。在具体的参数设定下，我们只会使用特定的物理学。<br />
&nbsp;&nbsp; 对世界的认识并不是非此即彼的。并不是说函数式语言好它就永远都好，要把所有对立面都灭掉。也不是说函数式不好，命令式就必然的好，就必然的能够解决问题。函数式语言的世界观过分单纯而排他，这是我反对的，我同样无法认同面向对象的本体论论调。就像CISC和RISC架构之争一样，最终我们在现实的物理约束下，运行的最好的芯片是两者思想的结合。这是我们面对物理世界的基本态度。<br />
&nbsp;&nbsp; <br />
4. 函数式语言中时间是个有趣的概念。命令式语言中因为赋值语句的存在，使得我们可以观测到状态的变化，因此必然要定义时间。而函数式语言是无状态的，可以是无时间概念（对Lazy Caculation的依赖是否体现了深层次上对时间概念的需求？）。有些人认为函数可以看作是相空间中的迁移函数，是与相对论协调的，因而反映了时间的本质等等。相对论主要是解决了物理规律的协变性的问题，在此过程中它使人们认识到了时空之间奇异的对称性。但是广义相对论的表述中时间也是可逆的。真正定义了时间之箭的是热力学第二定律。根据Landauer's principle: 擦除(erase)1比特信息，耗散到环境中的能量至少是k*T*ln2, 或者说熵增至少是k*ln2. 这意味着只要我们对眼前的黑板不停的写了擦，擦了写，就必然无法回到过去。物理世界是复杂的。<br />
<br />
5. 如果将状态看作是可以附着在某个对象上的标记，显然状态的存在性便于我们识认概念的唯一性。对象还是那个对象，只是状态标记发生了变化。而如果系统中没有状态，则必然产生了一个新的概念。这在很多情况下是不必要的负担。状态的存在使得系统在局部结构上允许出现非常复杂的变化，函数式编程的拥趸们对此多有诟病。但是从另一个方面上说，状态使得我们可以基于局部信息处理很多问题而不需要把它扩大化为一个全局匹配问题。<br />
<br />
6. 函数构成函数似乎是很完备统一的世界。 但是在物理世界中发生的一切却复杂的多。虽然世界可以还原为原子，但是原子构成分子，分子构成宏观物质时，系统的基本性状发生了本质性的变化，并不再是统一的形式。每一个层面上都会产生独立的结构规律。<br />
<br />
7. 函数式语言和命令式语言的计算能力相同（可以相差一个任意长度的多项式时间），但是在具体的情形下它们的描述能力是不同的。我所关心的不是语言层面的问题，因为语言本身的能力并不足以解决现实开发中的所有问题。即现实开发中所需要处理的结构问题并不是在语言层面得到充分解决的，这是我们需要做工作的地方。<br />
&nbsp;&nbsp; 关于现实中的结构问题，我无意去定义什么万能的描述能力。你可以用微分几何，积分几何，广义变分等等手段去证明圆盘是某种意义下的周长最短的东西，但是这一切对你发明轮子并无本质上的助益。不过可以说说现实中的结构。这里不是要证明某种语言中无法描述这些结构，而是说结构是客观存在的，它并不是要在基础语言层面得到充分解决的。实际上现在的通用语言也是无法有效承载Domain Specific Structure的。<br />
A. ErLang大概是目前世界上应用最为深入的函数式语言了。它确实发挥了函数式语言无显式状态变量的优势。但是它对程序构建本质上的帮助更多的来源于无共享的超轻量级进程模型，相当于定制了一般操作系统所提供的基本服务。微软的一个实验性操作系统项目Singularity, 其中也定义了只通过消息传递发生数据关联的超轻量级进程模型，它使用C#的一个扩展语言，额外增加的功能是消息管道上定义的规格状态机，对消息交互的时空模式进行额外的规约。这里对我们真正有价值的是隔离的单元结构。<br />
B. AOP是程序结构空间中的定位和组装技术。在Witrix中我们规范化了切点处的状态空间，并对AOP进行了偏置处理.这种结构调整大大提高了AOP的可用性，使得它成为Witrix中的核心技术手段之一。<br />
C. 面向对象的继承关系从结构观点上看是两个一维集合之间的覆盖关系。在Witrix中扩展了extends所对应的结构操作，创造了新的结构融合手段。<br />
<img src ="http://www.blogjava.net/canonical/aggbug/165664.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2007-12-05 22:09 <a href="http://www.blogjava.net/canonical/archive/2007/12/05/165664.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于[面向集合的框架设计]的一些说明</title><link>http://www.blogjava.net/canonical/archive/2007/12/03/165039.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Mon, 03 Dec 2007 15:54:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2007/12/03/165039.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/165039.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2007/12/03/165039.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/165039.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/165039.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 我习惯于概念层的推演，而且所阐述的东西多数是我们创造过程中的副产品，与业内常见的观念实际上是有着很大差异的。有些人感觉我的文章读不明白是因为没有采用类似的视角，或者还没有独立思考过很多问题。如果只是从业内已经熟知的概念出发试图理解我所写的内容，显然是不可能的事情。所以我常说know something already known. <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;">myFunc(){<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;each&nbsp;x&nbsp;in&nbsp;set<br />
&nbsp;&nbsp;&nbsp;&nbsp;doSomethingValuable(x);<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;packedResult;<br />
}<br />
<br />
myOtherFunc(packedResult){<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;each&nbsp;y&nbsp;in&nbsp;pakedResult<br />
&nbsp;&nbsp;&nbsp;&nbsp;doSomethingOther(y)<br />
}</span></div>
<br />
其实我们真正关心的是循环内部的某个过程，但是我们经常可以观察到它们被某些通用的或者特定的循环（集合遍历）操作所包围着。Witrix的设计方式是强调业务关注点，而把所有的汇总操作尽量抽象完成。比如现在界面上显示一些字段。从抽象的操作上说<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;">&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;each&nbsp;field&nbsp;in&nbsp;dsMeta.viewableFields<br />
&nbsp;&nbsp;&nbsp;&nbsp;show&nbsp;field.viewer</span></div>
<br />
这一过程在平台代码中实现，它是一个通用的集合操作过程。不同的具体应用只是关心具体字段的展现形式，虽然我们必然需要字段集合，但是它不是我们注意力的重心。<br />
&nbsp; 如果考虑到字段在界面上展示有一个布局问题，我们所要修改的是集合内部的结构方式：<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;">&nbsp;&nbsp;某种结构循环方式（dsMeta.字段组成的布局集合）<br />
&nbsp;&nbsp;&nbsp;&nbsp;show&nbsp;field.viewer</span></div>
<br />
抽离出集合，实际上是在最大限度上分离结构问题和内容问题。&nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; 结构是可抽象的，是具有独立意义的。这就是Witrix所提出的面向结构的设计视角。不是强调对象的所谓业务含义，不是强调某种通用语言（例如ruby）的灵活的语法结构。在这之间存在着厚重的具有物理意义的可以进行结构分析的技术层。<a href="http://canonical.javaeye.com/blog/60758 ">http://canonical.javaeye.com/blog/60758&nbsp;</a> <a href="http://canonical.javaeye.com/blog/126467">http://canonical.javaeye.com/blog/126467</a><br />
<br />
<img src ="http://www.blogjava.net/canonical/aggbug/165039.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2007-12-03 23:54 <a href="http://www.blogjava.net/canonical/archive/2007/12/03/165039.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从指针到引用</title><link>http://www.blogjava.net/canonical/archive/2007/12/02/164717.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Sun, 02 Dec 2007 14:14:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2007/12/02/164717.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/164717.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2007/12/02/164717.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/164717.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/164717.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 地址(Address)是现代计算机体系架构中的核心概念，它在程序设计语言上的体现就是C语言中的指针(Pointer)。在C语言中，所有的高级技巧都和指针这个概念相关。指针只是一个存放了一个地址的变量，但是C语言中提供了一个方便的间接访问方式，p-&gt;x, 它使得拥有指针在概念上就等价于拥有了指针所指的全部内容。在这种诱导下，我们渐渐模糊了地址和地址所存储的内容之间的区别。这也是指针的指针这样的概念总是让初学者迷惑不解的重要原因。<br />
&nbsp;&nbsp;&nbsp; 指针是对地址的符号化。它所带来的第一大好处是使得我们摆脱了对绝对地址空间的依赖。如同Newton第一定律所阐述的：物理规律与所发生的惯性坐标系无关。同样，数字空间中发生的的事件与所处的绝对地址也是无关的。在符号化的方向上更进一步，如果我们专注于指针的关联语义，而放弃指针的指针这样的混杂概念，就会得到具有独立价值的引用(Reference)概念.<br />
&nbsp;&nbsp;&nbsp; 从表面上看起来，数字空间只是一个无限延展的一维地址空间，每一地址处只能存放一个有限大小的离散数值，似乎它的几何学是贫瘠的。但是因为在软件设计中，一般是不考虑寻址时间的。这意味着在拥有指针的情况下，我们可以&#8220;立刻&#8221;访问到数字空间的任意遥远的地方。这种超时空的信息传递过程使得我们可以利用&#8220;引用&#8221;概念轻松的构建一个多维的表示空间。在面向对象的技术背景下，x.y.z这样的形式表示暗示着x,y,z是同时存在的。当z发生变化的时候，通过y.z和x.y的信息传导，x对象本身也发生了某种变化。<br />
&nbsp;&nbsp;&nbsp; 随着web技术的流行，独立的状态/地址空间的存在性逐渐成为系统不可回避的假设, "同时性"的物理约束越来越难以维持. 相对论规定了物理现象的定域性, 在数字空间我们一直忽视了它.但有趣的是, 网络上的传输时延却迫使我们重新发现了"引用"形式下必然存在着的物理过程. 引用本身只是标记了某种信息关联, 并不一定意味着同时性约束. 并发编程领域的所谓的Future对象是对传统引用概念的一种有趣扩展.<br />
&nbsp;&nbsp; result = obj.callMethod(args) ==&gt;&nbsp; future = obj.callMethod(args)<br />
future对象可以被自由传递, 只有当实际访问到它的属性的时候, 才会触发时序约束.&nbsp; <br />
<img src ="http://www.blogjava.net/canonical/aggbug/164717.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2007-12-02 22:14 <a href="http://www.blogjava.net/canonical/archive/2007/12/02/164717.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>面向集合的框架设计</title><link>http://www.blogjava.net/canonical/archive/2007/11/25/163048.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Sun, 25 Nov 2007 15:37:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2007/11/25/163048.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/163048.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2007/11/25/163048.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/163048.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/163048.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;
判断和循环是程序中最基本的语句结构。而在vonNeumann体系架构下，循环是对集合进行操作所需的基本步骤。一个有趣的事实是，函数式语言所宣称的
生产力的来源很大程度上在于集合操作的便捷性。在数学中我们通过张量分析，泛函分析等可以清楚地意识到集合之间的相互作用是可抽象的，是可以独立理解的，
即我们可以在不涉及具体基元结构的层面上独立的定义并执行集合运算。如何将这种概念独立性在框架层面展开是一个非常深刻的命题。<br />
&nbsp;&nbsp;&nbsp; 在基元结构上应用基础操作p(d)这一微观场景一般情况下是容易理解并实现的, 但通常程序中所定义的大量边界是基于集合变量的,
因此很多代码都是封包和解包操作, 在层层嵌套的循环结构深处我们才能发现真正具有业务价值的基元结构.
将集合操作提升到系统层，减少或简化在应用层需要显式编制的循环结构是框架设计层面需要考虑的问题. <br />
&nbsp;&nbsp;&nbsp; 一个最基本的方法是尽量定义通用的同构操作, 避免构造中间集合. 例如前后台之间通过json等通用协议交换复杂结构的对象,
避免定义特殊的中间处理过程. 一个与之相配合的重要技术手段是通过类查询语句(描述方式)直接构造特定的集合.
例如prototype.js中提供的$$('div
div.myclass').each(op)这样的处理方式显然要比在循环过程中基于特定条件过滤要方便的多.
而在AOP操作中切点的集合定义方式也是其提供的核心价值之一. 与集合操作相适应的一种代码风格是流式设计(stream),
这正是jQuery试图鼓吹的主要价值(虽然我个人认为它有些走极端). 流式设计的核心结构实际上是 x += dx,
它不需要集合是一次性构造的, 便于支持一种逐步部分修正的概念模型. <br />
&nbsp;&nbsp;&nbsp; 为了支持集合的隐式构造, 我们需要以通用的方式定义元素到集合的组装规则.
在Witrix平台的前台js框架中我们定义了由独立的html组件到复合查询条件的拼接规则,
定义了由每个html组件的数据校验函数到整个form的数据校验函数之间的组装规则,
定义了由单个html组件提交参数到整个form提交参数之间的组装规则. 在Witrix平台的标准界面上,
框架本身的编制基于js.query.buildCondition(frmQuery),
js.validate.validateForm(frmUpdate), ajax.addForm(frmUpdate)等少量集合操作进行,
在不同的应用场景下, 我们只需要关心每一个字段如何显示, 提交哪些属性, 而由系统负责将它们自动组装并在后台进行分派. 面向不同的应用,
框架代码不需要做出任何修改, 确保了系统结构的可重用性. <br />
&nbsp;&nbsp; Witrix平台的后台处理模型中定义了实体化过程, DaoWebAction基于CRUD等原子操作定义了批量提交,
数据导入导出等复合的甚至是嵌套的集合操作. 在不同的应用中, 我们通过修改bizflow文件中&lt;action
id="ViewDetail-default"&gt;, &lt;action
id="Update-default"&gt;等针对单实体的业务规则即可适应不同的业务场景, 而不需要为特定的应用重复编制集合处理过程. <br />
&nbsp;&nbsp;&nbsp; 面向集合+通用组装规则是Witrix平台设计中采用的基本设计手法之一,
它使得我们在一般应用中只需要考虑单实体,单字段等基元结构上发生的特定业务, 大大简化了系统构造过程.
但是也需要认识到从个体到集合的扩张(p(d) -&gt; P(D) )是非平凡的, 集合比个体的简单加和要更多,
为此架构中需要保留对集合边界的识别能力, 例如需要允许在数据导入完成之后执行特定的业务规则而不是仅仅针对每一数据行执行业务规则.
<img src ="http://www.blogjava.net/canonical/aggbug/163048.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2007-11-25 23:37 <a href="http://www.blogjava.net/canonical/archive/2007/11/25/163048.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Witrix架构分析</title><link>http://www.blogjava.net/canonical/archive/2007/09/23/147641.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Sun, 23 Sep 2007 15:53:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/archive/2007/09/23/147641.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/147641.html</wfw:comment><comments>http://www.blogjava.net/canonical/archive/2007/09/23/147641.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/147641.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/147641.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Witrix开发平台基于级列设计理论发展了一系列新的设计思想和软件分解机制。并提出了一种新的Web体系架构。<a href="http://canonical.javaeye.com/blog/33824" _fcksavedurl="http://canonical.javaeye.com/blog/33824">http://canonical.javaeye.com/blog/33824</a><br />
&nbsp; <img src="http://www.blogjava.net/images/blogjava_net/canonical/witrix.gif" _fcksavedurl="http://www.blogjava.net/images/blogjava_net/canonical/witrix.gif" alt="" height="735" width="753" /><br />
<br />
Witrix架构呈"可"字形态，其中定义了三条主要的分界线:<br />
1. 浏览器和服务器之间通过语义结构明晰的URL形成两分结构。<a href="http://canonical.javaeye.com/blog/99122" _fcksavedurl="http://canonical.javaeye.com/blog/99122">http://canonical.javaeye.com/blog/99122</a><br />
2. 系统前台至后台存在一条预制的非侵入的信道. 它维持了一种无害的可扩展结构.
具体的说,系统从前台js到后台处理,对于所有$为前缀的参数是自动传递的,没有识别出的层将自动把这些参数传递下去.系统通过这一信道实现退化过程。在
我以前的文章中曾经指出过， 每一种可退化形式都对应存在一种非侵入性的可扩展设计。<a href="http://canonical.blogdriver.com/canonical/993807.html" _fcksavedurl="http://canonical.blogdriver.com/canonical/993807.html">http://canonical.blogdriver.com/canonical/993807.html</a><br />
3. Witrix内置了对于CRUD模型的支持， 而BizFlow通过类似AOP的方法对CRUD模型进行了扩展。这使得Witrix的模型驱动部分并不是仅仅针对单表或者单实体的维护, 而是可以实现特定的业务逻辑和CRUD逻辑的混杂. <br />
<br />
&nbsp;&nbsp;&nbsp; 这三条分界线分别规范了基础状态空间，对已有知识的重用以及面向未来的可扩展性。在这种大的宏观结构下，Witrix应用了如下技术手段:<br />
1. 对象化。Witrix中的Jsplet框架以对象的名义提供了对后台的状态和行为空间进行分解的基础手段。 <a href="http://canonical.javaeye.com/blog/33873" _fcksavedurl="http://canonical.javaeye.com/blog/33873">http://canonical.javaeye.com/blog/33873</a>。Witrix
依托于Jsplet对象实现相关性的局域化, 而不需要像一般面向action的框架那样直接访问http session这一全局状态空间.
前台发送的objectName参数同时在系统的不同层面标定了WebAction响应函数, Biz配置, DataSourceMeta元数据,
Hibernate实体等一系列相关概念, 使得它们构成一个统一的整体. <br />
2.
标准化。与REST架构风格类似，DaoWebAction规范化了后台响应事件。DaoWebAction上支持的标准事件有Query,
ViewDetail,Add, Update, Remove等,
它们构成一个完整的CRUD模型。与REST不同的是，DaoWebAction提供了一个空的响应事件BizAction。它相当于是CRUD模型中的
零元操作。在BizFlow模型下，它将被扩展为一个操作子空间，从而实现对于CRUD模型的超越。而在REST模型下所有的扩展操作必须依附于一个已经
具有固定语义的Method上，例如POST. <a href="http://canonical.javaeye.com/blog/99122" _fcksavedurl="http://canonical.javaeye.com/blog/99122">http://canonical.javaeye.com/blog/99122</a><br />
3. 实体化。在Witrix中充分发掘了ORM技术的能力, 使得单一业务对象上可以聚集到某一范围内的所有相关结构信息.
<a href="http://canonical.javaeye.com/blog/111500">http://canonical.javaeye.com/blog/111500</a>.
同时在DaoWebAction中通过EntityFilter机制实现了单实体化过程. 这意味着前台应用可以一次性提交多个批量操作,
后台框架负责把它们分解为针对单个实体的一次确定性操作, 在后台实现时只需要考虑单实体的情况即可.
一个简单的例子是前台提交objectEvent=Remove&amp;id=1&amp;id=2&amp;id=3 ,
WebAction层会为每一个id对应的实体调用BizFlow中的Remove-default操作. 实体化是一个非常重要的过程,
它使我们关注的核心成为单实体, 正是因为明确了单实体作为基本的关注点, 我们才可以建立更加复杂的状态机机制, 驱动系统状态变化.<br />
4. 组件化. 前台的tpl模板和后台的WebAction共享一个thisObj指针, 结合自定义标签机制, 资源(js/css等)管理机制等构成可以重用的组件结构. <br />
5. 偏置的AOP. BizFlow通过一种类似于AOP的操作对DaoWebAction提供的CRUD模型进行扩展,
使得模型的能力得到本质性的扩张. 这种AOP操作与通常意义的AOP的区别在于: 缺省行为在默认情况下发生, 除非显式禁止. 通过这种方式,
反转了base和extension之间的主体地位. 此外BizFlow所提供的不仅仅是行为的扩展,它同时提供了对界面的描述.
在前台tpl页面中通过<ds:bizviewops>&lt;ds:BizViewOps/&gt;等无参数的标签调用来定义嵌入坐标. <a href="http://canonical.javaeye.com/blog/34941" _fcksavedurl="http://canonical.javaeye.com/blog/34941">http://canonical.javaeye.com/blog/34941</a><br />
<img src="http://www.blogjava.net/images/blogjava_net/canonical/jsplet-model.jpg" _fcksavedurl="http://www.blogjava.net/images/blogjava_net/canonical/jsplet-model.jpg" alt="" height="832" width="682" /><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; 与传统的J2EE相比较, Witrix表现出很多变化:<br />
1. 不使用全局的session, 而是使用局域化的thisObj<br />
2. 不定义service层，其功能分解到BizFlow和Handler中，它们都不负责日常的DAO操作。独立的MDA部分负责所有的实体CRUD(Create Read Update Delete)操作。<br />
3. 不定义页面跳转规则，在前台使用拉模式直接表明跳转目标。结合前台stdPage对象在前台控制跳转目标。并可以在BizFlow中配置覆盖的规则，这样就可以针对不同的应用场景定义不同的跳转规则。<br />
4. 不是为每个模块, 每个应用场景编制一组新的页面,而是大多数模块共用少数几个标准页面.<br />
5. 不在与网络无关的service层上定义权限和事务管理。Witrix架构下通过URL明确区分了系统内部和外部,
前台访问后台时调用者的全部意图是以规范化的形式表达在url中的.
因此权限和事务管理作用在WebObject上在概念上也可以认为是约束直接作用在URL上, 这与REST风格是统一的.
当然我们也可以规范service方法的命名等, 但是显然要求一种随意性消失是有代价的,
在URL上我们已经付出了代价,为什么要在service上再付出一次. Witrix中Transaction和Auth的配置更加直观,
因为规范化了WebObject上的事件响应函数,一般我们也不需要进行特殊的配置.
Witrix这种设计更加适合于网络这一两分结构的，更加充分的利用这一架构边界所提供的隔离性. <br />
6. 不在页面中使用实体的字段名，而是大量通过元数据表达程序意图。<a href="http://canonical.javaeye.com/blog/114066" _fcksavedurl="http://canonical.javaeye.com/blog/114066">http://canonical.javaeye.com/blog/114066</a><br />
<br />
&nbsp;&nbsp;
一般J2EE多层架构下，所谓的架构分解主要是对程序纵向的分解，但是程序结构方面是没有横向分解的。而witrix架构的一个核心就是横向存在着
CRUD模型和Biz的分解。在系统的所有实现过程中，所有CRUD操作都剥离到MDA模型中，而不需要任何代码编制。典型的,
witrix后台代码一般写在handler中，命名为handler而不是service是因为handler中负责的内容和j2ee传统上的
service有所不同，一般service总是要负责某个实体的CRUD操作，大量的findxxx代码。一般提倡的最佳实践是实现某个通用的基类，所
有service都继承该基类获得CRUD能力。但是在Witrix架构中，根本没有这一需要。Handler只要完成自己特定的功能，它不追求操作概念
在其本身的完整性。没有CRUD,
handler没有意义。但是handler之所以有意义是因为它提供了CRUD之外的操作。当CRUD成为系统一种自动进行的背景操作时，我们不再需要
明确意识到它的存在。<br />
&nbsp;&nbsp;&nbsp; 我们需要认识到我们最终所需要的东西可能不是规整结构的, 它可能要求对于某个规整结构进行剪裁并增补附加元素.
但是这样的规整结构不应只存在于我们的想象之中，相应的剪裁过程应该是可以增量进行, 反复进行的. 在Witrix平台中， 基本的一种图景变化是:
Witrix中不再需要从头开始构造结构, 而只要指定当前业务和背景模型之间的差异部分.
在Witrix中所写的业务代码是对核心模型的扩展。这不仅仅是概念上的，而是实际体系架构上精确的体现。CRUD作为独立的模型吸收了系统中大量的变
化。整个模型内核是采用通用方式借助meta实现功能，并不涉及到特定于业务的类。对于那些我们已经掌握的知识,
Witrix提供了超越对象继承,AOP和组件重用的结构抽取手段, 使得知识可以稳步积累.<br />
&nbsp;&nbsp;&nbsp; &nbsp; 数学中存在两种基本的分解方式， 一种是加性分解 (a,b) + (c, d) =&gt; (a,b,c,d)， 另一种是乘性分解
(a,b) X (c, d) =&gt; (ac,bc,ad,bd)， 它也对应于张量(Tensor)运算. 在群论(Group
Theory)中，直积对于复杂性的化简至关重要，它的重要性要远在加和之上。实际上AOP操作类似于直积分解， 只是它的能力尚未得到充分的探索。
在Witrix中，biz的作用在感觉上很象是陪集(coset)运算：CURD *
biz。不同的biz作用到同样的CRUD模型上产生不同的操作集合，而所有biz组成的集合构成独立的整体。&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp; Witrix平台中作为内核的MDA部分首先是物理模型驱动, 而不是逻辑模型或者对象模型驱动.
我们通过在物理模型上标注的方法恢复部分对象模型的信息, 但是我们并不试图把整个软件建立为模型. 所建立的仅仅是整个程序模型的内核.
<a href="http://canonical.javaeye.com/blog/29412">http://canonical.javaeye.com/blog/29412</a> 一般业内鼓吹的所谓MDA成功的关键是要提高抽象层次。
但是陪集是更抽象吗。 正规子群更抽象吗。 它们只是系统的指标性表征，使对信息的distill, 是更容易理解的一个侧面而已,
抽象性并不是一个真正的目标。很多时候我们需要的是把系统降维到某个子空间中，形成一种可控性。 但是这个子空间并不一定是更抽象的。<br />
&nbsp;&nbsp;&nbsp; &nbsp; 群作为基本的代数系，一个本质特征是具有逆元。Witrix的MDA中明确定义了逆元结构，即界面上的元素 empty =
buttonA + (-buttonA)，这一分解公式应用到后台 OpA = Update * (-Update)&nbsp; *
OpA。假设我们已经建立了结构X, 现在需要建立一个与X略有不同的结构Y<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; X = a + b + c<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Y = a + d + c = (a + b + c) - b + d = X - b + d<br />
虽然Y的两种构造方式在数学上是等价的，
但在物理上并不等价。第一种方式对原有系统进行分解后再组装，而第二种方式没有打破原有的东西，不需要拆分。拆分总是可能存在问题的，正如你把所有电脑零
件拆装下来再装上很可能会发现多出几个零件。一般情况下第二种方式的构建成本要低. 特别是当一切都纠缠在一起的时候,
一种细粒度的逆元结构对于一种试图重用的结构是非常关键的.
可重用性的障碍不仅仅是来自于无法追加新的功能，很多时候也在于无法屏蔽原先已经提供的功能。目前所有的设计原则都未能适时识别出逆元的重要性。所有的设
计教条其实所指的方向都是加和, 如何分解出更小的组元, 如何把它们加和在一起, 如何从细部开始进行重新构建,
而不是说依赖于现有已经形成的宏观结构, 如何进行细粒度的调整. 所谓的AOP技术思考的关键点也在于如何给系统增加功能,
很少有人想到场景是为系统减少功能并把这种概念大规模正式应用的, 虽然说AOP已经在某种程度上具有了这种能力,
但是真正应用它仍然需要对AOP进行进一步的诠释. 当然，现在的软件业连基本结构的构造问题都没有完全搞清楚, 更别提所谓结构稳定性的问题了. <br />
&nbsp;&nbsp;&nbsp; &nbsp;从物理上说，Y = X - b +
d的分解方式具有特殊的意味。如果没有逆元，我们必然需要分解。但是如果发掘了背景这一概念，在逆元运算下，对背景不是分解让其成为可见的部分，而是采用
追加的，增删的方法对背景结构进行修正，则我们有可能在没有完整背景知识的情况下，独立的理解局部变化的结构。即背景是透明的，知识成为局部的。
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;
Witrix试图提供的一种图景是永远只写代码片断，而所有的代码片断组合在一起又构成一个可理解的整体。这个整体可以独立理解，不需要额外的结构元素。
Witrix架构所追求的是在不完全信息下建模，不进行整体建模。整体模型 + 不断变化的局部修正 构成
最终模型。平台技术的目标是让一切应该发生的自动发生，让一切不该发生的无法发生。这一模型的构建并不是trivial的，在概念和实现方面都要作出很多
的努力。<br />
&nbsp;&nbsp;&nbsp; &nbsp;<br />
题外：<br />
&nbsp;&nbsp;&nbsp; &nbsp;今天中午参加同学的婚礼, 席间和一个与同方有些渊源的同学谈到ezOne的现状, 大致的评语是: 垃圾, 自己人也不用. 听来也让人有些感叹. 中国原创的技术总是欺骗的代名词,&nbsp; 这一断言不应总是得到证实.</ds:bizviewops>
<img src ="http://www.blogjava.net/canonical/aggbug/147641.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/canonical/" target="_blank">canonical</a> 2007-09-23 23:53 <a href="http://www.blogjava.net/canonical/archive/2007/09/23/147641.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>