arm-linux

http://armboard.taobao.com/

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

               测试驱动的面向接口编程的开发流程

1.        引言

 

OOP面向对象编程,这个大家都没什么争议(除了那些不能算是程序员的人之外)。但是,什么是OOP面向对象编程呢,这个各人的理解就有很大的不同。

有人认为,OOP面向对象编程,核心是对象Object。对象是一个封装了数据和操作的代码集合。

也有人认为,OOP面向对象编程,实际应该是面向类编程。因为对象是类的实例。类是对象的模板。实际上是类封装了数据和操作。对象不过是运行时的特征,是运行时类的表现。

可以说,以上这几种观点都很有道理,对我们的编程水平的提高也有很大的帮助。面向类编程,也是很多OOP程序员所接受的观点。

但是,“类”这个概念有着很灵活的意思。可以说是一个多义词。特别是OOP面向对象编程大行其道之后,众多概念都用上了“类”这个时髦的词语。

顺便说一下,计算机世界就是这样子,有着无数的多义词。每个公司、组织总是给自己发明的概念加上一个时髦的词语。炒“概念”是IT界市场营销的一大手段。.COM.Net,“体系结构”,“网关”,“中间件”等众多词语承载了太多太多的意思,以至于很容易混舀。看来,IT界是患上了词语极度贫乏的失语症了。其实,不光是IT界这样,记得我曾经的领域“管理学”中,也充斥着“新概念”。如果不对那些时髦的名词,缩写加以解释,就连我这种高材生也摸不着头脑。

好了,又跑题了!闲话少叙,总之,对于“类”,有n多种意思,我经过深思熟虑,也对它们有一些解释。

 

----------------注意,以下都是我个人的理解,如有反对意见,没关系,你坚持你的,我坚持我的好了。

 

“类”,对应的英文就有两个,Class种类,Type类型/模范,台湾译成“型别”。顺便说一句,我觉得台湾对于IT专业术语的翻译很有意思,往往比大陆翻得更贴切----虽然有些拗口。大陆翻得很通顺,但是其中不同英文的细微差异就没有翻出来,往往使人很头大!

 

 

 

2,软件开发过程

 

 

我们开发软件,有几个阶段:

1,分析阶段----OOA面向对象分析阶段

分析现存业务,分析需求。也要概念性的设计出我们的系统。然后分析我们的系统的用户需求。

成果就是:Use Case用例图。重点是分析而获得概念中的系统的用户需求。从而得到我们软件的功能。

 

 

2,设计阶段----OOD面向对象设计阶段

设计出软件,将我们的概念化为图纸。

1)                概念设计

这个阶段做出一些重要的决定。如软件的体系结构,所采用的技术方案,采用的数据库,中间件,操作系统,硬件。等。

2)                详细设计

这个阶段是一个叠代的阶段。我们很难说什么是详细,什么是更详细。

我们通常从Use Case用例图着手进行设计,首先画出类图,然后再画出使用类的序列图。

此时,我们设计的焦点是业务领域。不涉及数据库访问层和UI表现层,以及其它服务。

3)                设计软件的其他层,这些是通用的或者是类似的

就是设计数据库访问层和UI表现层,以及其它服务等等。

 

 

3,实现阶段----OOP面向对象实现阶段

1)设计实现类

在设计阶段,我们并不考虑怎样实现类图中的“类”。特别是特殊的“业务领域”。在实现阶段,我们设计实现类,并利用继承、委派,或者在此基础上的设计模式,编程准则和经验来设计实现类。

成果是类图,这个类图有继承、委派等结构;还有序列图,这个图也侧重于实现类的动作。

2)用代码实现类

   用代码实现类。

(1)    在源代码中写上注释。

(2)    用代码“声明”注释。即用注释来命名变量名,或者函数名。

(3)    设计算法,并用代码实现算法。

----总之,我们的代码名字应该说明自己是做什么的,或者自己是什么。而不应该说明自己怎么做。

怎么做孕含在代码中的算法。只有最后的方法,才会表明自己实际是怎么做的。

我们的解题/算法概念是一级(方法层次)一级往下发展的。是一级一级隔离的。

所以,我们常常看到一些框架,它们的一个方法比如说是提供a对象的。方法明说他是提供a对象的,至于他是怎样提供a对象的,要到它的函数体内寻找答案。而体内可能还是间接的,又调用了其他方法。

 

逻辑分离的好处是,

1我们可以直接使用现存的框架/类库;

2实现的问题可以由其他程序员想办法解决。我们算是用方法名给那个程序员出了个题目。我们只管使用他的成果就是了。

3还可以并行开发。即使那个方法还没有实现,我也只管调用那个方法签名好了。 我可以是抽象类,  也可以测试时使用作弊的手法,假装那个方法能够工作了就行了。只要测试成功,我的任务就算完成了!

 

 

4,测试

测试,我们是测试驱动开发。在实现阶段的开头,我们设计实现类时,或者之前,就要针对接口设计并实现单元测试。

本阶段的测试是集成测试和压力测试,上线测试,交付测试。

5,重构

实现时,我们就边实现,边进行重构了。

这里是指,上线后,软件变更需求,需要增加或者改变功能时,我们可能会闻到现有代码散发的bad smell

Eclipse拥有最好的重构工具,利用它,再加上我们的重构知识,优异的实现就是非常顺利成章的。

重构所需的开发环境:

1)            JUnit测试支持,  至少要支持调用main()方法。 如果没有测试,那么不仅重构是不可能的,就连代码编写也是极其困难的。最好能够有脚本自动测试工具,自动运行测试。

2)            断点调试工具和log日志报错。这两者都是编程两(良)友。程序出错并不可怕,最可怕的就是找不到出错的原因。电脑作为程序员最好的朋友,永远不会说谎,只要你了解她的运作机制,她就永远听你的话。但是,电脑的内部运作机制又是极其复杂的,可以说是无尽的。要了解她,她的反馈是必不可少的。调试和日志就是她和我们的交流!

 

 

 

 

3,我对类型等概念的理解和定义

 

明白了软件开发的过程,接下来我们再来研究一下“类”class/type,接口interface这个概念。

在我们计算机界,技术的发展都是有很多个人和公司推动的,是来自于商业竞争和技术竞争的,也是方兴未艾的。在IT界,有一个很突出的现象,那就是“炒概念”。2000IT业狂飙之际,“注意力经济”成为一个新的经济学名词。

炒作各种IT概念,确实圈到了不少钱。一句话,在IT界,谁能吹,谁就能够发大财!对象,服务,组件,架构,构建……各种各样时尚的名词满嘴胡吹。

每家公司都把自己的技术,甚至是浑身不搭界的技术硬套上时尚的名词。搞得人们不知所云。

比如说,Business Object,让我映像最深,最感啼笑皆非!BO的几项技术叫做:“语义层”,“钻取”,“仪表盘”……

刚开始学用BO时,被这些时尚的概念搞得稀里糊涂,颇为憧憬。可实际接触下来一看,原来所谓语义层就是一层建立在数据库之上的逻辑层,类似于视图而已的破技术。

而神秘的“钻取”则更是可笑:不就是分层字段的展开和回退吗?!

好了,不说这些题外话了,总之,在IT界,一个名词,特别是那种大热的时尚名词,通常都有几百上千个意思。各有各的理解。各种完全不同,甚至互相对立的概念,可能都叫同一个名词!

而,“类”就是其中之一!对此,有必要呈清这个概念,方法就是用我的理解来重新界定这个概念。

 

我们知道,宇宙万物都可以分类,都有类型。面向对象程序设计,就是运用了这个原理来在程序中模拟这个世界的一部分----一个系统。

面向对象object编程,也可以称之为面向类型type编程。对象是程序运行时的状态,是变化万千的动态的程序。

而类型是静态的程序,是程序的结构。那么类型和对象什么更重要一些呢?

应该是类型type,因为这才是我们建造的程序,是有形的(有代码的)程序。

就如我们造一架飞机,是造出一架由零件组成的程序,而不是一架飞行时的飞机。

 

再看我们是怎样造出一个程序,或者是一架飞机的。

一、概念

首先,我们根据需求和我们的电脑技术能够实现的东西,首先在概念上产生一个软件系统,或者是一架飞机。

这个软件系统要满足一些需求,实现一些功能。这是运行时的功能。和对象有些关系。对于软件,就是“用例图”。

这相当于我们做数学题,物理题。我们已经给自己提出了要达到的目标。

 

然后,我们利用自己掌握的各种资源,构建出几个解决方案/设计方案,然后选优。   这也就是说,我们此时有了几个心目中的产品----软件,或者是下一代主力战斗机。

 

首先考虑的,肯定是一些全局的,方向性的问题----架构。是B/S架构,还是C/S架构,使用.net,还是java

飞机是单发还是双发,是隐形还是正常布局。

这就是架构!

选择好架构后,我们就考虑更细的结构。如软件是有那几个系统组成的:

表现层,业务层,数据访问层,数据库。  飞机是由推进系统,控制系统,侦查系统,通讯系统,武器系统等组成的。

 

之后,我们就可以把注意力集中到特定于这次需求的环节----业务上来了。这是这个软件系统的定制部分,而不是通用部分。一般,主要集中在业务层。表现层和数据访问层都是附带的。而通用部分,不是已经有了成熟的产品,就是我们的多个项目都是用到了这些技术。

对于飞机来说,也许发动机是外购的,不是这次飞机项目的自研部分。也许多个飞机设计项目都是用一种发动机。

 

二、业务层建模

好了,我们知道了“业务层”是我们软件开发的核心环节。

首先,我们根据我们大脑中设想的软件系统的运作流程,设计出软件的类型type系统。建立类type图。

类型type是什么?是真正的东西吗?不是!设计飞机时的设计图中的零件是真正的零件吗?当然不是!

所以类图中的零件type类型也不是真正的东西。它们和实现毫无关系!也许他们中有的部分永远无法实现,这就需要设计中的重构。

如果设计的太过超前,或者设计者技术不行,脱离现在的技术水平胡乱设计。那么,可能这个产品永远也造不出来。比如说,人工智能技术现在还很不成熟。如果对软件系统中的人工智能type类型的功能要求定得过高,那么也许要过1000年才能造出这样的零件!

 

设计好类型type图之后,我们仅仅是有了一个逻辑上的静态模型系统。要知道我们的类型图能不能实现用例图的要求,我们必须还要构建一个动态的逻辑模型----序列图。

所谓序列图,就是类型工作的过程图。工作的目标就是各个用例图。

 

这个过程除了验证和完善类型type的设计之外,也可以发掘出类型的方法和字段。让我们概念中的软件的要求和功能更趋完善。为我们的零件设计提供了一个更加明确的目标。

 

到目前为止,我们还处在画图纸的阶段,还在完善我们概念中的那个系统。

我们的零件type类型,是对象的模板,但还不能够生产对象,因为他们还是虚的。甚至更彻底的说,应该只是一个对零件的要求。

所以,这个零件应该是一个接口Interface

而接下来,我们的系统设计还是停留在概念上。所以,我们应该使用的零件,还是应该仅仅是类型/接口 type  Interface

这里,我把类型type和接口Interface作为同一个概念来看待。在我眼中,它们本来就是一个概念的2种叫法,是历史形成的。

注意,接口interface只能放置公共方法和公共静态fianl字段常量。其他的设计因素可以作为注释放在接口中。

 

什么是OOA面向对象/类型分析,OOD面向对象/类型设计,OOP面向对象/类型编程。它们之间并无明显的分界。

我们的目标是,让分析和设计尽量的往后拖延,让实现放到最后,缩到最少的时间。因为实现,是有着很大时代、条件约束的,是最容易过气的!

也许,2年之后,这些技术就已经开始被淘汰了。也许,这种发动机5年之后就落伍了。但是,设计方案确实可以跨越实现的技术----IT软件开发技术!

 

最好,最高水准的代码,就是一个个委托给其他方法来完成本方法任务的方法。  委托,而不是自己实现的代码越多,这个软件的水平就越高,就越可扩展,可修改。

 

Java之所以强大,就是因为JDK类库丰富,开源框架资源丰富。当我们编程要实现某个功能时,我们可以不考虑怎样实现------总有办法能实现的!!!

 

当我们分解、委派到不能分解之时,我们就可以查找JDK类库,开源框架,web上资源和简单的编码来实现功能。

 

 

委派,不论是委派给自己还是其他类型/接口interface的实例的方法,  是面向对象,也是面向过程的编程之道。

 

软件中,总是可以通过增加一个中间层来解决问题。  这实际就是分解问题,让问题简单,再简单!  简单到每一个方法,每一个变量,每一行代码都能够直接说明自己的功能!

 

 

不断设计的过程,就是类型type,接口interface不断增加的过程,不断明确的过程。  最后,我们能够得到一个接口的继承、调用关系详图。

 

 

三、实现  class-----最后10米!

 

 

实现,是最后的事情,也是最少的事情。因为,设计/interface的不断推进,已经把实现class类逼到了墙角。

 

只有到了胜利在望,不得不短兵相接了的时候,我们才需要打白刃战----实现接口。

 

实现接口的东西,你猜得不错,就是类class 注意,不是类型,型别type/interface。而是抽象或实际的类class

 

class 的实现有赖于类的继承和接口/类型type的调用/委派。

 

 

class只能够继承一个class----class的全部代码, 但能够实现多个接口------即能够属于/代表多个类型type/接口interface  或者说属于多个零件。

 

也许,这个实际的零件是多用途的,既能够当作a零件用,又能够当作b零件用。

 

而且,使用委派,将方法委派给实现类,这实际上一样是实现了多重继承的效果。

 

四、关注点的思考方法

面向过程的程序设计方法中,我们看到的是“过程”;

面向数据流的程序设计方法中,我们看到的是“数据流”;

面向对象的程序设计方法中,我们看到的是“对象”。

的确,万物都可以被看作是由“过程”组成的;由“数据流”组成的;由“过程”组成的。

但是,这些是本质吗?  显然不是,他们只是“盲人摸象”中摸到的一些片断,一些表象。

“编程是一门奇特的科学,它可以通过增加层来解决任何问题”。

编程的最根本解题方法,就是分解,把问题分解成一个个小问题,如此循环,直到分解的问题能够很容易的解决。

那么我们怎样划分问题成为一个个小问题呢?我们是按照某个标准来划分的。这个划分的标准,就是我们关注的是不同的东西,我们就据此把它们分开!

“关注点”,这就是我们所需要的!我们对问题的研究,总是根据分类的方法,来划分处很多不同的种类,分别加以关注。

这些关注点,又可以分为2大类,一类是业务核心的关注点,这是我们业务领域关注的东西,我们叫它“核心业务关注点”。另一类是为业务服务的关注点,这就是“横切关注点”。

所谓关注点,就应该是一个独立的,低耦合的概念。这可以用类型typeinterface来表示。这是设计层面上的东西。还记得否,OOP编程要求我们的类尽量低耦合,高内聚;我们在OOA分析时的概念,不应该和设计有关,设计时的概念,不应该考虑到实现。

OOAOOD是接近的,很难分开的。但是,OOD时,绝对不能够考虑实现。

好了,现在在分析和设计时,我们的关注点都是类型type

 

然后是实现,要考虑怎样实现我们的关注点了。 此时,我们发现,核心业务关注点,要和横切关注点一起发生作用。比如,日志。但是,我们不希望日志和业务类型混在一起实现。此时,AOP就可以实现将2者动态混合,而在开发时是分开的。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted on 2005-11-17 23:45  arm-linux  阅读(453)  评论(0编辑  收藏  举报