?
面向对象方法目前是软件工程学中的主流方法论之一,但在实际运用中,存在如下问题:
1)对象在描述业务模型时的能力欠缺。业务模型往往重点关注(功能)边界、(与其他模型的)关系等,对象分析方法往往
表述较泛,相对而言,用组件来表达业务模型会更理想;
2)对象分析方法没有站在不同尺度分析问题。例如,一个员工管理系统,在确定了其构成的各个对象之后,如果把这个粒度级别称之为“功能”级别,那么
在更大的“模块”级别或者“子系统”级别如何分析?你能够称一个“模块”也是一个对象吗?虽然直觉上两者没有本质的不同;
3)对象分析的产出物在实现时与编程模型的差异。在分析文档中表现的类似于“节点互联”(或者形象的称之为搭积木)的风格往往在实现时荡然无存,最终
交付使用的软件内部的各个单元边界不清、关系混乱、紧紧的耦合在一起,所谓的“节点互联”只是形式或逻辑上的,例如,在分析文档中的一个“数据表格”对象
在实现是可能对应着一组JSP?Tag以及几个JavaBean,而且这些代码可能分散在项目的不同位置;
以“员工管理系统”为例,其“员工档案管理”的用例简述如下:
?
显然,该用例可以简单描述为“对员工资料”的CRUD(增删改查)操作,接下来分析构成该应用程序的各个组成部分,我们会需要:
1)数据表格(展现数据、查询、编辑数据);
2)DAO(Data
Access
Object,作为存取数据的中间方);
3)DataSource数据源(连接、存取数据库);
另外,数据表格不能满足我们的要求,我们在保存数据同时会向另外一张表中存取数据。DAO在运行过程中会记录操作日志,而且日志的格式是可定制的。
?
一般的,我们开发的该应用程序其内部结构为下图所示
?
?
在以上实现过程中,一般会出现以下问题:
1)对比发现,设计分析的结果已经与实现阶段不一致,注意图中数据表格部分在实现阶段已经被分割为两部分,事实上,如果很多的业务逻辑都用到了该表格,这些不同应用
程序中表格对应的业务逻辑有至少70%的代码是雷同的(例如,所有的查询方法都是首先校验来自页面的条件,然后调用其他业务逻辑等等),所以这些“公共”的业务逻辑代码
应该属于数据表格组件并且提供“扩展点”供实际扩展,但是现实中很多的编程模型没有提供这种机制;
2)实现时硬编码紧耦合。很多时候,开发人员会直接在业务逻辑中实例化某(比如DAO)Bean对象从而构成硬编码的紧耦合;
3)即使应用了如Spring来实现Bean间的解耦,但是Spring本身不易理解的概念(诸如DI、IOC、AOP等)造成了较高的学习成本,此外,接口隔离很多时候
依然存在着冗余,更多的时候BeanA只关心BeanB的某个方法的签名而非整个接口,并且,Spring的编程模型是复杂的,注入一个接口除了声明之外,一般还需要一个
Setter方法;
?
1)一套更简单、直观的分析方法。这套方法更好的定义了业务的边界、更贴近业务需要的关系(例如依赖、扩展、组合等等),类似于DIY电脑,首先,用一套方法
定义内存、CPU、主板等,这些组件的边界、关系非常清晰直观;
2)彻底的组件化视角。把我们的一个复杂的系统想象成办公大楼,你会发现,不同尺度空间中的各个组成单元都是“组装”起来的,你用显示器、主机、键盘等组装成电脑,用电脑、电话
办公桌、隔断等组装成一个办公单元,用多个办公单元、会议室等组成一个办公区域....,不同尺度空间(办公单元、办公区域、办公室、部门楼层...)都是像“搭积木”一样的组装
过程;
3)如果能够做到打破系统中组件与非组件(在现实开发中,一个JSP的Tag或者一个Util对象可能被视为组件,而一个普通的Java类可能则不会)的壁垒,实现系统的彻底组件
化,而且,重要的一点,“组件与组件组合(或聚合)后依然是组件”,那么我们就能得到一套“像搭积木”一样的分析、开发模型;
?
面向积木编程(分析)有两个要点:
1)识别积木块;
2)将积木块组装在一起;
一组拥有明确边界与标准关系(一般被描述为与实现分离的描述符)且可以与其他积木块构成更大积木块的软件单元。
这组软件单元可能包括:其他的积木块、子程序组、视图、业务逻辑、配置项、描述符(功能项、关系项等等)、安装卸载单元、说明项等等,如下图:
?
?
积木块关系图
?
?
面向积木体系的视角下,上述应用程序在实现阶段为如下结构
?
?
面向积木方法在此解决了上面所提及的问题:
1)面向积木(组件)分析而非面向对象分析业务;
2)一切皆组件
,该应用程序也是一个组件,组件间的关系体现为:依赖、扩展、包含、组合、继承等,关系一般体现在配置文件中,实现天然的松耦合。
重要的,实现了设计阶段与实现阶段的高度一致性
,所分析即所实现
。
?
设计的本质是基于某种目的将一个相对杂乱的体系映射为一个相对有秩序的体系。
假设该“有秩序的体系”为一金字塔结构,在此基础上探讨面向对象(OO)方法论的特性,如下图:
?
?
?
系统建设成本正比于系统在某一尺度空间(例如,在功能级别)上的全部功能数= ∑ f(i)=∑
f(s(i)+r(i))
上式中,s(i)为节点i特定(独有)的功能数,r(i)为该节点在其他节点(m)中s(m)的子集。显然,一旦需求确定,i与f(s)为常量,系统建设成本正比于r(i),即直观理解为
系统建设成本正比于重复功能数。
在考虑如何降低成本,即考虑如何是的r(i)减小的视角下分析组成系统各个单元之间的关系,首先,功能需要与其他功能具备明确的边界,我们称该特性为“封装”;降低r(i)的
一个重要手段是提高复用性,复用中最重要的两种:重复应用与泛化,泛化的机制我们称之为“继承”;在继承的基础上的变化(覆盖或重载),我们称之为“多态”,到此为止,OO的理念
就确立了。
接下来思考更高(或更低)尺度(如模块级别)上系统的单元结构,你会发现如果使得r(i)趋于最小,上述的方法同样成立。
所以,得出当构成系统的组成单元在不同尺度空间中体现OO特性的前提下,系统建设成本是相对较低的,这种架构称之为分形架构。
事实上,分形架构(模式)体现在很多具体的实现中,例如,JavaBean就是其中的一种。
?
?
?
?
?