您的位置:首页 > 编程语言

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

2005-11-17 23:45 281 查看
测试驱动的面向接口编程的开发流程
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界,有一个很突出的现象,那就是“炒概念”。2000年IT业狂飙之际,“注意力经济”成为一个新的经济学名词。
炒作各种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大类,一类是业务核心的关注点,这是我们业务领域关注的东西,我们叫它“核心业务关注点”。另一类是为业务服务的关注点,这就是“横切关注点”。
所谓关注点,就应该是一个独立的,低耦合的概念。这可以用类型type,interface来表示。这是设计层面上的东西。还记得否,OOP编程要求我们的类尽量低耦合,高内聚;我们在OOA分析时的概念,不应该和设计有关,设计时的概念,不应该考虑到实现。
OOA和OOD是接近的,很难分开的。但是,OOD时,绝对不能够考虑实现。
好了,现在在分析和设计时,我们的关注点都是类型type。



然后是实现,要考虑怎样实现我们的关注点了。 此时,我们发现,核心业务关注点,要和横切关注点一起发生作用。比如,日志。但是,我们不希望日志和业务类型混在一起实现。此时,AOP就可以实现将2者动态混合,而在开发时是分开的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: