向banq老师请教一组架构问题

这些问题之前和别人讨论过,但是一直没有结论,考虑banq是jdon架构设计者,固前来讨论
1、banq在设计架构的时候用什么建模工具?我一直用Rose,后来发现其实Rose不是一个好的架构设计工具,而是一个应用系统设计工具,因为Rose不支持UML2.0,一些复杂的类关系表述不清,事实上多数架构都存在这些复杂的关系,IBM对Rose的定位是:IBM开发人员开发IBM产品的时候从来不用Rose,而Rose是针对购买IBM产品的其他开发商使用IBM产品进行二次开发应用的随产品附赠应用建模工具,可见Rose在架构设计上是疲软的。
2、也是我主要的问题:UML与架构的关系
都说UML相当于设计图纸,只要图纸有了,照着实现就能做出成品,UML是架构设计的精髓,可是太多的架构设计技巧在UML上面展现不出来,所以这其中就具有一个权衡可视化建模和实际架构代码粒度的问题。
banq在jdon下载包中的doc文件夹下赠送了jdon相关时序图,可是jdon这么些类,这几张图就是九牛一毛,在tomcat6的源代码中也是只有几张简单的图,占tomcat数以百计类中的很小一部分,另外在下载的其他apache开源项目代码中鲜有赠送设计图纸,就算有也是简单的几个类。
我说这个的主要意思是一个架构是一个比较精细的东西,比开发应用精密的多,可能为了扩展性,实现一些功能要写一大堆类,每个类都有架构思想和设计模式的体现,这些东西通过指导性的UML很难一应俱全,到底该怎么权衡这些关系,该不该把每个类,每个实例的生命周期都画在图上?
说的有点抽象,举一个具体的例子:
比如java中的HashMap,在HashMap中定义了静态内部类Entry,这样做的好处是
1、根据数据亲密性原则,将HashMap中关联的数据key和value封装起来
2、这个结构只对HashMap本身有用,所以定义成私有的内部类,以免其他类与Entry产生不必要的耦合
根据两个原则,这个“静态内部类Entry”是一个设计非常严谨,几乎找不到更好决定的决定
但是站在设计HashMap当初的角度上考虑,例如banq老师设计这个HashMap作为架构的核心组成部分,banq会不会用UML表现出HashMap与Entry关系以记录自己的设计决定呢?
一、如果是,就说明在架构设计的UML图纸里面画上HashMap和Entry,这其中设计到的问题包括
(1)UML中很难找到方法表演一个类是另一个类的静态内部类,更难找到方法体现这两种类之间的关系,因为一个内部类可以直接调用外部类的方法。
(2)如果把这些画上了,那么意味着很多其他同等细节的东西也需要在UML上面体现,将会产生一个硕大的难以短时间读懂的图纸。
二、如果不是,则产生的主要问题有
(1)HashMap与Entry关系确确实实是你精心设计的结果,是很重要的部分,不是实现架构时候的灵机一动的决定。
(2)你可能确确实实需要在设计而不是开发阶段能够记录下这个决定,并且很有可能实现架构的人不是设计者你,你也需要保证实现者准确的接收到你的意图。
所以,这就陷入了两难的窘境,我也层试图写架构,可是发现总是无法掌握UML粒度,并且达不到UML指导的作用。经常是知道UML怎么画,但是不知道怎么用UML记录下想法,经常画是一套,做则与图脱节。

不谈请教,讨论讨论吧。

首先,UML适合架构描述吗?这个问题也有讨论,所以专门提出ADL:
Is UML an Architectural Description Language:
http://www.sigplan.org/oopsla/oopsla99/2_ap/tech/2d1a_uml.html

关于使用描述语言ADL或UML或模式语言等描述设计粒度问题,这个恐怕没有一个标准。我个人经验,如果你要特别突出内部Entry这样一个重要但细节的设计的话,你就需要以模式概念表达出来,比如取个名称“内部Entry模式”,在相应的上分类图中标注出来。

其实上帝缺省是阻止人沟通的,所以,任何一个沟通表达方式都有一个缺陷,就是沟通表达元素不能太多,一多就陷入大家对沟通表达元素的学习中,你说明一个软件系统,只要几张主要UML图就可以,而不能面面俱到,反而不突出重点,让别人无法理解。

粒度最小单元到模式为止,有的方法学建议到合约Contact为止,一个Contact是两个类之间互动关系和约束,而模式也基本是两个以上类之间的结构或互动关系与约束。模式或COntact以内就作为白盒子了。

我记得Evans书中说过,他不止一两次看见一个项目组画了恨不得一整面墙的UML图,这种图一眼看上去根本找不到中心在哪,Evans反对在画设计图期间过早的陷入细节问题,他也提倡简洁,他说一般人们会画一些图,然后给图中无法表示的东西加上标记注视,但是他不这么做,他会写一个文档,然后再文档的某一章中附上图。我理解Evans可能认为UML对于架构的表现终究是非常有限的,甚至比文字弱得多,所以在做架构的时候应该以文字为主导并附加图纸,而不是以图纸主导附加文字。

我记得Evans书中说过,他不止一两次看见一个项目组画了恨不得一整面墙的UML图,这种图一眼看上去根本找不到中心在哪,Evans反对在画设计图期间过早的陷入细节问题,他也提倡简洁,他说一般人们会画一些图,然后给图中无法表示的东西加上标记注视,但是他不这么做,他会写一个文档,然后再文档的某一章中附上图。我理解Evans可能认为UML对于架构的表现终究是非常有限的,甚至比文字弱得多,所以在做架构的时候应该以文字为主导并附加图纸,而不是以图纸主导附加文字。

有道理,文字也是一种描述,文字+UML只是描述形式不一样,但是多了还是无法突出重点。架构只是几张图就可以,大道至简。

完整架构描述需要文档+架构UML图。比如NGOSS 或J2EE等文档 API和描述都是完整架构描述的范例。

比如tomcat6源代码中附赠的图,仅仅包含tomcat接收到请求,如何把这个请求层层处理,都经过哪些类处理兵最终形成我们用的request整个过程图画上了,我承认这是tomcat的核心。但是tomcat还包含很多其他的东西,比如如何设计connector架构以保证能更换成NIO,AJP13、如何实现Realm、如何解析http协议、如何协作完成类加载器层级、如何支持EJB等等这些issues没有相关设计图纸,也不能说这些问题不重要,我不知道是他们对这些问题压根不需要画图还是不愿意在源代码中赠送(话说本来是开源产品又有什么关系)。

我想知道banq在设计jdon是怎么做的?
比如想设计一个架构可以:
第一步: 收集需求,识别架构驱动因素(架构动机)
第二步:确认核心线路并画出uml图
第三步:在核心线路外围支撑工具以及过程画成子图或者冠以模式名称标记

架构设计时,先了解几个不能做的,就象买股票,首先要掌握什么是顶,不能在顶部买。


如果你想失败,那就期望一个银弹式的设计
如果你想失败,那就满足所有人的需求。如果一个公司试图为所有人创造一个产品,那么最后不会适用于任何人
如果你想失败,那就追求完美

我认为好的架构是重构出来的,而不是一开始就能设计出来。
但是如果开始没有一个正确方向的选择,后面花再多力气重构也没有用。

设计Jdon时的动机是在多层架构项目开发中,发现重用部分,就提炼出来,结果带出一批出来,所以,好的框架设计总是来自于框架的用户:程序员。

面向用户设计是架构的基本动机。
[该贴被banq于2009-07-23 10:25修改过]

那么另外一个问题:如何识别实体和职责?
一个架构的想法,首先应该产生于其他人的需求,或者对于现有环境某些不够自动化方面的自我发现和补充
那么在从拥有需求阶段 -> 设计成类图阶段,有一个过渡过程,即识别实体和实体的职责,否则图没法画
然而这部分工作,我认为是整个设计阶段最困难的,有些实体能从客观存在物之间抽象,有些实体,典型(XXXManager\XXXHelper)是属于技术辅助性类,从客观世界中抽象不出来,如何把他们识别出来?另外分配职责又是另一个难题,很多职责属于这个类也行属于那个类也行非常含糊,所以Ward设计了CRC来帮助在这个阶段,力图将实体和职责识别出来,因为没有这些,后面的类图、协作图、时序图都是空谈。

CRC其实是责任和委托的区分,责任可以认为是实体本身固有的一些特征和行为,而委托协调则会产生依赖或关联关系。

如何识别实体和职责?这里还是有一个实体边界划分的问题,有时单靠CRC一种方法学还不能确定把握,使用多个方法学联合应用:

比如DDD的实体边界和聚合边界就很有可操作性;

Specification 模式:将不变性放入Specification ,将变量留在实体中。实体分离出特征,这些特征有自己的变化轨迹:过去 现在和将来。

DBC的Contract合约可以认为是CRC的Collaborator详细定义,通过Contract合约规定了协调委托接口。

那么通过剥离,剩下的应该就是实体自己的职责东西,职责也可以通过聚合模式来判断,是整体和部分关系,离开部分,整体就不正常了。


我是这样想的,关于您所说的DDD,名字"领域驱动设计"就说明了这是一个和领域相关的方法论,用来识别带有业务含义的实体,比如从百货市场这个客观模型抽象成电子商城这个虚拟模型。
但是如果是支撑架构级别的,可能就需要其他的方法论支撑了,比如站在架构角度你如何去发现Proxy和InvocationHandler以及它们之间的关系

支撑架构可能需要对各种架构充分了解研习,比如Proxy和InvocationHandler是从JDK的动态代理模式以及反射机制中知晓的。

> 支撑架构可能需要对各种架构充分了解研习,比如Proxy和InvocationHandler是从JDK的动态代理模式以及反射机制中知晓的。

我不是这个意思,我的意思是站在设计者的角度上看,举个更显眼一点的例子JAAS,JAAS包含Subject、Principal、LoginContext、CallbackHandler等等元素,在学习JAAS怎么开发之前,先要灌输这些概念以及组织形式,然后才了解API怎么使用,这也是现代架构趋势:一组简单的API伴随着一整套系统方法论和概念。但是站在设计角度上,如果你发现你需要一个认证授权的架构,你需要自己设计一个提供某种程度的灵活性,那么如何做才能识别Subject、Principal这些元素能帮助你实现你想要的灵活性。

你的意思是:如何识别一个架构的设计是否满足自己需要的灵活性吗?

> 你的意思是:如何识别一个架构的设计是否满足自己需要的灵活性吗?

恩,还包括如何设计类来实现这些灵活性

这个挺难回答的,应该有这方面架构识别灵活性的更抽象理论,我目前认为可能取决于架构师本身的素质和专业水准。

另外,灵活会导致复杂,如何在复归简单,实现大道至简,这大概也是一个识别标准。

至于如何设计类来实现灵活性?采取切分方式,也就是OO一套方法论,将粒度尽可能细腻化,切入后,再用简单的边界合起来,这样,从复杂复归简单。