﻿<?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/4829.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 12:25:40 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 12:25:40 GMT</pubDate><ttl>60</ttl><item><title>[导入]无参数调用</title><link>http://www.blogjava.net/canonical/articles/19694.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Mon, 14 Nov 2005 07:37:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/articles/19694.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/19694.html</wfw:comment><comments>http://www.blogjava.net/canonical/articles/19694.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/19694.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/19694.html</trackback:ping><description><![CDATA[<!--StartFragment -->&nbsp;<FONT color=#000000 size=3>&nbsp;&nbsp;&nbsp; 全局变量在现代程序设计中可谓是臭名昭著。函数之间通过全局变量形成隐蔽的couple, 其联系难以追踪，难以控制，也使得程序的意图变得非常隐晦。但从另一方面说，隐蔽的关联也意味着两个函数的关联没有被固化，可以随时根据需要做出调整。例如,<BR>&nbsp;&nbsp;&nbsp; funcA(varA,varB,varC);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; funcB(varA,varB,varC,varD);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; funcC(varA);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; funcD(varA,varB,varC,varD);<BR>&nbsp;&nbsp;&nbsp; 在以上程序中，funcA将调用funcB,但是funcB需要一个特殊的参数varD。我们可以选择在funcA的参数列表中增加这一参数，但这样 funcA的定义就破坏了它本身的意图：它包含了一些具体的与自身意图无关的实现细节。一旦funcB的实现改变，例如它不再需要varD, 或者需要更多的参数， 则funcA需要随之进行调整。<BR>&nbsp;&nbsp;&nbsp; 实际上在程序中我们可以通过两两关系进行参数接力，也可以采用中心化的方式，即各个函数都从环境（公共变量区）中取得所需参数。面向对象是一种折衷的解决方案：对象的成员函数之间通过成员变量形成隐蔽的依赖，但是这种依赖又不会扩散到对象之外。最理想的情况下，我们可以采用无参数的函数调用，函数名揭示出我们的意图而不用考虑交互的细节。在写伪代码的时候，经常可以发现我们实际定义并使用的参量要远少于最终实现所用到的参量。如果我们要实现伪代码方式的程序书写，那么在变量生存空间上还要做出比面向对象更加灵活，更加精细的控制。</FONT> <img src ="http://www.blogjava.net/canonical/aggbug/19694.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> 2005-11-14 15:37 <a href="http://www.blogjava.net/canonical/articles/19694.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[导入]解耦只是第一步</title><link>http://www.blogjava.net/canonical/articles/19695.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Mon, 14 Nov 2005 07:37:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/articles/19695.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/19695.html</wfw:comment><comments>http://www.blogjava.net/canonical/articles/19695.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/19695.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/19695.html</trackback:ping><description><![CDATA[<!--StartFragment -->&nbsp;<FONT style="COLOR: rgb(0,0,0)" size=3>&nbsp;&nbsp;&nbsp; 在软件开发中，很重要的概念就是解耦(decouple)，其更加数学化的表述是正交分解。但是按照级列设计理论，元素完全独立的一阶系统只是复杂性最低的模型，或者说，当我们在信息不足的情况下识别出系统中最主要的几个实体之后，对它们的最自然的假设就是互相独立。随着认识的深入，需要逐步补充元素之间的相互作用方式。这就如同Taylor级数展开，任何解析函数都可以展开为Taylor级数，而在物理世界中，一般前几项近似就足够了，因而才造就了如此多的线性定理。在软件开发中，演化(evolution)逐渐成为一个重要的概念，我们也开始关心起系统设计长期的适应性，特别是随着系统的发展，我们认识的深入，如何才能逐步引入新的结构而不破坏原先的整体架构。即我们需要能够控制微扰(perturbation)下原有系统结构的稳定性。但是在目前的软件世界中，连构造基本的结构都困难重重，更别说对结构稳定性的研究了。不过这是一个循序渐进的过程，迟早它会被提上议事日程。<BR>&nbsp;&nbsp;&nbsp; 在分解过程中，一个基本的问题是对象之间确实存在着相互作用，并不是无关的。此时常用的手法是抽提出公共接口，即对象不再两两依赖而是共同依赖于某种公共知识。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objectA ＜--＞ objectB&nbsp;&nbsp;&nbsp; ==＞&nbsp; objectA ＜--＞ commonInterface ＜--＞ objectB<BR>&nbsp;&nbsp;&nbsp; 这就如同物理中场方程的处理方式，粒子不再是两两发生作用而是独立的与外部平均场发生作用，而粒子之间认为是独立的。</FONT> <img src ="http://www.blogjava.net/canonical/aggbug/19695.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> 2005-11-14 15:37 <a href="http://www.blogjava.net/canonical/articles/19695.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[导入]AOP与结构</title><link>http://www.blogjava.net/canonical/articles/19696.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Mon, 14 Nov 2005 07:37:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/articles/19696.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/19696.html</wfw:comment><comments>http://www.blogjava.net/canonical/articles/19696.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/19696.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/19696.html</trackback:ping><description><![CDATA[<!--StartFragment -->&nbsp;<FONT color=#000000>函数封装可以看作是对语句流中的一个区间（range）的抽象（基本等价于一个点抽象），而AOP (Aspect Oriented Programming)则定义了一维线性结构（程序文本）中的区间的边（boundary）。在未有aop之前为了定义这种boundary, 我们往往不得不借助于继承技术，通过在基类(base class)中预先定义所需的结构来打破函数的原子性。例如<BR>class BaseClass{<BR>&nbsp;&nbsp; public void doSomething(){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; before();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reallyDo():<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; after();<BR>&nbsp;&nbsp; }</FONT>
<P><FONT color=#000000>&nbsp;&nbsp; protected void before(){}<BR>&nbsp;&nbsp; protected void after(){}<BR>}</FONT></P>
<P><FONT color=#000000>class ExtClass extends BaseClass{<BR>&nbsp;&nbsp; protected void before(){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ....<BR>&nbsp;&nbsp; }<BR>}</FONT></P>
<P><FONT color=#000000>根据拓扑学(topology)，二维情况下最重要的拓扑结构是所谓的环(loop)。例如，在界面上我们经常将各种不同的内容放置在某一类固定的边框中，一种好的界面技术应该能够将这种边框独立的抽象出来。在witrix平台的tpl模板语言中，我们通过bodyTag可以轻易的实现这一抽象。<BR>＜app:普通消息边框＞<BR>＜input type="text" value="name" /＞<BR>...<BR>＜/app:普通消息边框＞<BR>这种抽象其实已经超出了AOP的范畴。</FONT></P><img src ="http://www.blogjava.net/canonical/aggbug/19696.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> 2005-11-14 15:37 <a href="http://www.blogjava.net/canonical/articles/19696.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[导入]关于结构</title><link>http://www.blogjava.net/canonical/articles/19699.html</link><dc:creator>canonical</dc:creator><author>canonical</author><pubDate>Mon, 14 Nov 2005 07:37:00 GMT</pubDate><guid>http://www.blogjava.net/canonical/articles/19699.html</guid><wfw:comment>http://www.blogjava.net/canonical/comments/19699.html</wfw:comment><comments>http://www.blogjava.net/canonical/articles/19699.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/canonical/comments/commentRss/19699.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/canonical/services/trackbacks/19699.html</trackback:ping><description><![CDATA[<!--StartFragment -->
<P><FONT color=#000000 size=3>&nbsp;&nbsp;&nbsp;&nbsp; 所谓结构，简单的说就是一组关系的集合。（结构就是关系的说法就太过于简陋了）。在数学上，最基本的关系就是集合之间的包含（contains)关系，而等价(equivalance)关系，序(order)关系（坐标）等都可以基于包含关系推导出来。从集合论的角度上说，所谓的关系也是通过集合来刻画的（两元素相关指的是它们属于同一集合），而函数的定义就是集合之间的映射。因此，在集合论看来，一切都是集合，数据的结构与函数的结构,或者结构的结构的结构之间并无本质性的区别, 甚至数据与结构之间也存在着内在的统一性。一些我们早已默认接受的基本实体，在集合论的框架下也是通过集合的结构来刻画的，例如自然数1,2,3，这些数字本身也是通过一些复杂的构造过程来进行描述的，它们只是一些基本结构的速记符号而已。<BR>&nbsp;&nbsp;&nbsp; 当然，世界并不简单。集合论所没有述及的一个事实是，集合的集合比集合本身要复杂。结构的级列也构成了复杂性的级列，每一个层次都比前一个层次要复杂的多。最明显的表现就是函数的总数比实数多。在现实的世界中，我们很多时候都是处在某一复杂性层次上，因而可以深切的感受到基本元素与结构，与结构的结构之间的这种深刻的差异。<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; 伟大的von Neumann在计算机世界中定义了两种基本的东西，数据与指令，在von Neumann体系架构下，两者的界限是明确的。CPU的存在定义了指令与数据之间的结合关系（apply), 而CPU的串行执行强制定义了指令之间的序关系(order)。在软件中我们通过函数封装定义了指令的集合，而这些集合之间仍然存在着由main函数所驱动的序关系。因为函数也是通过数据（代码）来表达的，因而在形式语义上，我们有可能证明能够表达的函数结构与数据结构是完全一致的（注，这方面我并无研究，也不太感兴趣）。但是现实情况下，我们对函数之间的结构的控制要弱于对数据结构的控制。最明显的，程序运行时，函数(指令）空间基本上是静态的，不变的，而数据空间则不断的发生着变化。现代软件系统中plugin, 动态配置，运行时java代码增强(enhance)等技术的不断发展正在逐渐缩小着这方面的差距。</FONT></P>
<P><FONT color=#000000 size=3>&nbsp;&nbsp;&nbsp; 在数据结构方面，C语言中的Struct结构体是一个很大的进步。因为由此引出的复杂类型系统是对结构的一种抽象描述: 在编译期唯一的一个Struct定义可能对应着运行期的多个实例(instance)。而在引入模板(template)特性之前，每个函数定义都唯一的对应于一些二进制指令。类(Class)相对于Struct的突破之处在于它表达了函数（指令）与数据之间的相关关系。Class之间的关系构成结构的结构。在编译期，我们所面对的只是类型定义，因而处理的正是结构问题，此时并没有实际的数据实例。而传统上，编译期所处理的结构都是静态的，现在脚本语言 (script)与language oriented programming正在逐渐突破这一限制。编译期处理结构问题所造成的另外一个现实是，目前我们对于结构的描述必须基于类型系统来进行，一般情况下无法方便的单独定制实例的结构。<BR>&nbsp;&nbsp;&nbsp; 函数在其本义上只是对数据的变换，从数据空间的角度看，函数可以被看作是数据之间的一种动态结构，其最终形态在运行时结合输入数据才展开。高阶 (higher order)函数接受函数作为参数，因而可以看作是对结构的变换。但无论如何，函数与过程化处理并不是一回事，只是在von Neumman体系下，可以观测到函数顺序执行才引入了时间概念。</FONT></P><img src ="http://www.blogjava.net/canonical/aggbug/19699.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> 2005-11-14 15:37 <a href="http://www.blogjava.net/canonical/articles/19699.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>