已阅读5页,还剩39页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
摘要 在程序设计开发领域,程序开发人员往往很少注意程序的存储空间或内存大小 的问题。 他们往往把精力投入到程序架构的设计和开发方法的研究上, 例如目 前的各 类软件工程方法的提出, 对存储空间或内存大小的考虑仅仅是一小部分的开发人员的 “ 专利” ,如此程序在设计过程中,开发人员为了获得更快的开发周期、更加可扩展 的、更加灵活的软件, 往往以牺牲程序的存储空间为代价, 但是在某些特定的应用领 域,内存的限制往往成为制约程序开发的最大问题之一。 本文首先探讨了内存受限系统的内存受限类型,并针对每种类型给出了其一般 的解决原则和方法,使开发人员对内存受限系统有一个初步的认识。 其次, 本文阐述了软件开发方法中的一种新的对代码的修改方法一一重构技术, 阐述了重构技术的目的是在不改变程序的外在行为的前提下调整软件内部的结构, 改 善软件的可理解性,提高软件的性能, 其实质是对软件的设计架构的调整优化。并指 出重构技术目前的所研究的局限性和其广阔的应用前景。 再次,本文阐述契约式程序设计的概念和契约的功能,研究并讨论了契约对于 解决重构中的一个根本性的问题一一行为保持的所起的作用。 并从理论上证明了契约 确实能够使在重构过程中行为保持不变, 且通过一个例子详细解释了在重构过程中如 何加入契约。 最后,本文研究并提出了应用于内存受限系统的重构方法,并结合实例具体的 分析了这些手法的应用方法,给出了应用于内存受限系统的重构的具体过程。 另外,本文还设计了一个应用于内存受限系统的重构工具的静、动态架构,给 出了重构工具的静态类图、时序图。 同时在文章的末尾,还探讨了应用于内存受限系统的重构方法在特定的应用领 域所起到的作用,特别是在j 2 me手机这一方兴未艾的、具有巨大发展潜力的应用领 域,这些重构方法必将起到巨大作用。 关键词:重构;内存受限:模式;软件工程;面向对象;j 2 m e ab s t r a c t i n t h e d e v e l o p m e n t o f p r o g r a m m i n g , t h e p r o g r a m m e r s u s u a l l y s e l d o m n o t i c e t h e p r o g r a m s m e m o ry s i z e . t h e y u s u a l l y p u t t h e i r e n e r g y in t o d e s i g n i n g t h e p r o g r a m s a r c h it e c t u re a n d r e s e a r c h i n g o n h o w t o d e v e l o p a p r o j e c t , f o r e x a m p le : s o m e k i n d s o f s o ft w a r e e n g i n e e r i n g m e t h o d b e i n g p u t f o r w a r d c u r r e n t l y . t h e m e m o ry s iz e o n l y i s a s m a l l p a r t o f p r o g r a m m e r s p a t e n t . i n s u c h p ro c e d u r e , t h e p r o g r a m m e r s u s u a l ly t a k e t h e m e m o ry o f t h e s a c r i f i c e a s t h e p r i c e i n o r d e r t o g e t t h e f a s t e r d e v e l o p m e n t p e r i o d , m o re e x p a n s i v e , m o r e v i v i d s o ft w a re . b u t i n s o m e p a rt i c u l a r a r e a , t h e m e m o ry l i m i t e d u s u a l l y b e c o m e t h e b i g g e s t p r o b le m t h a t re s t r i c t i n g p r o g r a m m i n g f i r s t t h i s t e x t d i s c u s s e d t h e t y p e o f t h e m e m o ry l i m it e d s y s t e m , a n d t o t h e e a c h c a t e g o ry t y p e , g a v e t h e p r i n c i p l e a n d m e t h o d s o f s o l v i n g g e n e r a l l y , m a k i n g d e v e l o p e r s t o u n d e r s t a n d t h e m e m o ry l i m i t e d s y s t e m . t h e n e x t i n o r d e r , t h i s t e x t e l a b o r a t e d a k i n d o f n e w s o ft w a r e d e v e l o p m e n t m e t h o d s 一一r e f a c t o r i n g t e c h n o lo g y , o n e o f t h e m o d i f i c a t i o n m e t h o d o f t h e c o d e , e l a b o r a t e d t h a t t e c h n i c a l p u r p o s e o f r e f a c t o r in g : u n d e r t h e p r e m i s e o f t h e o u t s i d e b e h a v i o r t h a t n o t c h a n g e , t h e p r o c e d u re a d j u s t e d t h e s t ru c t u r e o f t h e s o ft w a r e i n n e r p a r t , im p r o v e d a p p r e h e n s i b l e o f t h e s o ft w a re , t h e e x a l t a t i o n f u n c t i o n o f t h e s o ft w a r e , i n a c t t h e q u a l i t y i s t h e a d j u s t m e n t o f t h e d e s i g n s t ru c t u r e t o t h e e x c e l l e n t s o f tw a r e . a n d p o i n t e d o u t t h e s t u d y o n t h e r e f a c t o r i n g t e c h n iq u e a l s o h a d l im i t c u r re n t l y a n d i t s g r e a t l y a p p l i e d f o r e g r o u n d . a g a i n , t h i s t e x t e l a b o r a t e d t h e c o n c e p t o f t h e p rog r a m b y c o n t r a c t a n d t h e f u n c t i o n o f t h e c o n t r a c t s , s t u d i e d a n d d i s c u s s e d t h e f u n c t i o n t h a t t h e c o n t r a c t a l s o c a n res o l v e o n e o f t h e p r o b l e m一一 b e h a v i o r c o n s t a n t d u r in g t h e r e f a c t o r i n g . a n d p r o v e d t h a t t h e c o n t r a c t r e a l l y e n a b l e d t h e b e h a v i o r c o n s t a n t i n h e a v y p r o c e s s fr o m t h e t h e o r i e s , e x p l a in e d i n d e t a i l h o w t o j o i n t h e c o n t r a c t c o m b i n e d t o a n e x a m p l e . e n d , t h i s t e x t r e s e a r c h e d a n d p u t e d f o r w a r d t h e r e f a c t o r i n g m e t h o d a p p l i e d t o a t t h e m e m o ry l i m i t e d s y s t e m , a n d c o m b i n i n g t h e s o l i d e x a m p l e a n a l y z e s t h e s e s k i l l s i n a s p e c i f i c w a y , g a v e c o n c re t e p r o c e s s t h a t w as a p p l i e d r e f a c t o r i n g t o t h e m e m o ry l i m i t e d s y s t e m . mo r e o v e r , t h i s t e x t s t i l l d e s i g n e d a t o o l t h a t a p p l i e d r e f a c t o r in g t o t h e m e m o ry l i m i t e d s y s t e m , g a v e t h e d y n a m i c s t a t e s t r u c t u r e s , t h e s t a t i c s t a t e d i a g r a m s , a n d t h e c y c l e t i m e d i a g r a m o f t h e r e f a c t o r i n g t o o l . a t t h e s a me t i me , i n t h e e n d o f t h e r e f a c t o r in g a p p l i e d t o t h e m e m o ry l i m i t e d a r t i c l e , w e s t i l l d i s c u s s e d t h e f u n c t i o n o f t h e s y s t e m u s e d i n t h e p a rt i c u l a r a p p l i e d r e a l m , i i e s p e c i a l l y i n t h e c e ll u l a r p h o n e o f j 2 me , w h i c h r e a l m o f t h e h u g e d e v e l o p m e n t p o t e n t i a l , t h e s e h u g e f u n c t i o n n e c e s s a r i l y . i s o n e o f o n t h e u p a n d h a s t h e h e a v y r e f a c t o r i n g m e t h o d s w i l l a p p l i e d r i s e t h e k e y w o r d : r e f a c t o r i n g ; m e mo ry l i mi t e d ; p a tt e rn; e n g i n e e r ; o b j e c t - o r i e n t e d ; m e hi 独创性声明 本人声明所呈交的学位论文是本人在导师指导下进行的研究工作及取得 的研究成果。 据我所知, 除了文中特别加以标注和致谢的地方外, 论文中不包 含其他人已 经发表或撰写过的研究成果, 也不包含为获得东北师范大学或其他 教育机构的学位或证书而使用过的材料。 与我一同工作的同志对本研究所做的 任何贡献均己在论文中作了明确的说明并表示谢意。 学位论文作者签名4a 林 日 期 : 抛弃现在的系统;硬着头皮进行 维护,进行修改和扩充。 这就是 在软 件维护研究中 提出 的 软件嫡 ( s o f t w a r e e n t r o p y ) el 的 概念。 软 件墒是 软件的结构随着时间而变坏的现象。f r e d b r o o k s 说:所有维修都倾向于破坏结构,增 加了系统的嫡和凌乱3 1 。 在修理原始设计缺陷上所花的时间 越来越少, 越来越多的时间 是花在修理由早期修理所引入的错误上。 随着时间的流逝, 系统变得越来越混乱。 迟早 修理变得不可能而停止下来4 1 解决这个问题的最好方法就是在它出现之前,就阻止它的出现,即使出现了,也应 该有办法来解决。由 此开始t软件重构技术 ( s o f t w a r e r e f a c t o r i n g t e c h n o l o g y )的 研究。 如果编码时认真的对待每一步, 代码的结构和设计就没有机会变坏。 每次在修改 或者增加代码之前, 通过查看代码, 如果代码具有良 好结构和味道 ( c o d e s m e l l ) fi , 那么增加功能就没有困难; 如果理解代码要花很多时间,代码就应该先被重构 ( 重新组 织修改)以获得易维护属性,然后才容易扩展代码。当然,要阻止代码的腐化,人们也 需要付出额外的代价。 3 . 2 重构的基本概念 3 . 2 . 1 重构的定义 重构是以各种方式对一对象设计进行重新安排使之更灵活并且 / 或者可重用的过 程。 效率和可维护性可能是进行重构最重要的理由。 1 1 1 重构的一般定义: 1 3 1 重构 ( r e f a c t o r i n g , 名词) : 是对软件的内 部结构所作的一种改变, 这种改变在可观 察行为 ( o b s e r v a b l e b e h a v i o u r )不变的条件下使软件更容易理解,而且修改更廉价。 重构 ( r e f a c t o r ,动词) :应用一系列不改变软件可观察行为的重构操作对软件进行 重新组织( r e s t r u c t u r e ) . 定义中最重要的方面是不改变软件系统的可观察行为,并且改变软件结构是朝着更 好的设计和更能理解, 而且可重用的方向进行。 重构提供一种以更有效和受控方式清理 代码的技术 1 3 1 . m a r t i n f o w l e r 的名词形式就是说重构是对软件内 部结构的改变, 这种改 变的前提是不能改变程序的可观察的行为,这种改变的目的就是为了让它更容易理解, 更容易被修改。 动词形式则突出重构是一种软件重构行为, 这种重构的方法就是应用一 系列的重构操作。 “ 不能改变程序的可观察的行为”就是重构之前软件实现什么功能,之后照样实现 什么功能。 任何用户,不管是终端用户还是其他的程序员,都不需要知道某些内部的事 情发生了变化。 3 . 2 . 2 重构的原则 . 一个时刻只戴一顶帽子 1 4 1 k e n t b e c k 把重构和增加功能比喻为两顶帽子 ( t w o h a t s ) 。他说,如果你使用重构 开发软件,你把开发时间分给两种不同的活动:增加功能和重构。增加功能时,你不应 该改变任何已经存在的代码,你只是在增加新功能。这个时候,你增加新的测试, 然后 让这些新测试能够通过。当你换一顶帽子重构时, 你要记住你不应该增加任何新功能, 你只是在重构代码。你不会增加新的测试 ( 除非发现以前漏掉了一个) 。只有当你的重 构改变了一个原先代码的接口时才改变某些测试。 . 保持可观察行为 保持代码的可观察行为不变称为重构的安全性。重构工具用半形式化的理论证明来 保证重构的安全性。 自 动化的测试是检验重构安全性非常方便而且有效的方法。虽然不能穷尽整个系统 中所有的测试, 但如果在重构之前成功的测试现在失败了, 就会知道刚刚做的重构破坏 了系统的可观察行为。自 动化测试能够在程序员不进行人工干预的情况下自 动检测到这 样的行为破坏. 为了在重构工具中实现这一原则,需要在理论上证明应用某种方法系统的可观察行 为保持不变。 . 小步前进 重构的另一个原则是小步前进,即每一步总是做很少的工作,每做少量修改,就进 行测试, 保证重构的程序是安全的。如果你一次做了太多的修改, 那么就有可能介入很 多的错误, 代码将难以调试。 如果这时你发现修改并不正确,要想返回到原来的状态也 十分困难。 这些细小的步骤包括:确定需要重构的位置,编写并运行单元测试,找到合适的重 构并进行实施,运行单元测试,修改单元测试,运行所有的单元测试和功能测试等。 如果按照小步前进的方式去做重构,那么出错的机会可能就很小。正如 k e n t b e c k 所说9 . “ 我不是一个伟大的 程序员,但我是一个具有伟大习 惯的 好程序员, , 。 3 . 2 .3 重构的基本过程 目 前的程序设计一般是对源码形式的程序进行修改和增加。为了将重构集成到这样 的编程环境中, 在重构前首先必须将程序源码转换成一种抽象语法树的表示,并且重构 之后必须从抽象语法树的表示再次生成更新后的程序源代码。( 如图3 . 1 ) 表示了重构过 程的各个阶段。 在重构系统内,扫描器创建程序源码的语法树表示, 扫描树被传给重构 程序, 重构程序首先分析语法树,并添加类型和交叉引用信息, 重构程序然后根据来自 用户的命令对内部表示进行处理, 修改程序架构, 最后调用格式修改输出程序重新生成 并输出重构后的代码。 图3 . 1软件重构过程 以上是从编译器角度看重构过程的一个内部运作机理。从用户角度看重构软件系统 采取的步骤如下: ( 1 ) . 确定需要重构的位置。 可以 通过理解、 扩展、 或者重新组织系统来发现问题, 或者通过查看实际代码中的代码味道 ( c o d e s m e l l )来确定位置,或者通过某些代码分 析工具。 ( 2 ) .如果所考虑的代码的单元测试存在的话,就运行该单元测试看看能否正确的 完成。否则,编写所有必要的单元测试并运行它们。 ( 3 ) .通过思考或者查看重构分类目 录,找出能够明显被应用的重构操作。 ( 4 ) .遵循小步前进的原则实现重构操作。 ( 5 ) .在每步间运行测试以保证行为未被改变。 ( 6 ) .如有必要,对作过改变的接口 修改测试代码。 ( 7 ) .当重构操作被成功地用于重新组织代码,再次运行测试,集成并运行全部的 单元测试和功能测试。 在m a rt i n f o w l e r 的著作 1 3 1 中, 他提出了重构表示法的 标准, 这种标准表示法使任何 人都能容易地获得重构操作的主要思想, 后面跟有实例,以及一步步运用重构而不会引 入错误的用法。它由下列元素构成: . 名字 建立一个很像设计模式名那样的词汇 . 简要概述 关于该重构操作何时需要用以及它做什么的简单说明, 包括问题说明, 使用的反映, 以及最可能是以代码形式 ( 包括重构前和重构后的代码)或者一种u ml图的形式表示 的框架 . 动机 描述为什么应该使用的原因以及何时不应使用 . 用法 关于如何一步步执行重构操作的说明,以及使其容易被引用的简短注释 . 例子 显示该重构操作的一个简单应用 3 . 3 重构技术的优点 重构增加了具有某种缺点的程序的价值。 k e n t b e c k 指出: 难读的程序难修改。 具有 重复逻辑的程序难修改。带有复杂条件逻辑的程序难修改。重构虽然需要更多的“ 额外 工作” , 但是它给我们带来的各种好处显然值得做出 这样的努力 1 1 4 1 3 .3 . 1 、简化测试 重构的每一步都保持可观察的行为, 也就是保持系统的所有单元测试都能顺利通过。 所以只有发生改变的代码需要测试。 这种增量测试使得所有的后续测试都建立在坚实的 基础之上,整个系统测试的复杂性大大降低。 3 . 3 . 2 、增进软件可理解性 重构支持更小的类、更短的方法、更少的局部变量、更小的系统祸合,重构要求你 更加小心自己的命名机制, 让名字反映出你的意图。如果哪一块代码太复杂以至于难于 理解,那它就需要对它进行重构。 3 .3 . 3 、改善软件设计 很多方法学强调把注意力放在分析和设计阶段,把实现定义为按照设计进行编码, 以努力防止产生故障。 这些方法学认为通过分析和设计的严格化就能产生更高质量的软 件。 然而, 这仅仅是理论, 实际 上是不可能的。 正如b r a i n f o o t e 和j o s e p h y o d e r 在 b i g b a l l o f mu d 一文中指出,虽然许多作者提出了很多理想上非常完美的体系结构,如 l a y e r . p ip e l i n e 等等。 但在实践中, 几乎从来都不能 看到这么结构清晰的系统。这一方 面是由于分析和设计一个领域的应用程序需要对该领域丰富的知识, 而这种知识不是在 一开始都能获得的。通常需要在实践反馈的过程中才能一步步加深自己对该领域的理 解。因而,一开始的设计可能并不能正确反映系统的内在本质, 所以也不可能在代码中 得到很好的反映。在 f r e d e r i c k p . b r o o k s 的经典著作 人月神话中,他己经提出:在 软件开发中不可能有任何技术也就是 “ 银弹 s i l v e r b u l l e t ) ”来解决软件开发过程中的 效 率 ih 题。 1 5 重构和设计模式的结合可以很好的设计出具有良 好架构的软件。 3 . 3 . 4 、利于找出错误 软件调试中最困难和最费时间的工作是定位错误。重构不仅帮助理解代码,同时也 可以帮助发现错误。 因为故障隐藏在系统中一些非常微妙的地方, 清理设计和代码使故 障被带到明处。重构要求小步前进,并且对每一步都进行严格的测试,这样会使得错误 很容易地浮现出来。 3 . 3 . 5 、加速开发 重构支持好的结构、设计和理解性,它让人们更快地开发软件。因为它可以防止软 件的腐化,甚至用于改进设计。 3 .3 . 6 、有助于代码复审 重构也能对代码复审作出贡献。它能被用于使复审的代码更容易理解,这种范围更 广的理解导致更有用的建议。当把这些建议作为展开重构的起点,由复审者即刻进行实 现的话, 代码复审就能交付具体的结果。通过重构,重建设计的结构, 代码变得更容易 ,代码复审变得更成功。 、增加灵活性 m a r t i n f o w l e r指出:重构能通往更简单的设计而不牺牲灵活性。 这使设计过程更 简单, 而且不再那么强调过程。 如果你对事物进行了深入的理解, 你就能容易地进行重 构。 3 .4 流行编程语言对重构的支持 3 . 4 . 1 . c + + 语言对重构的支持 c 一具有一些语言特性,最著名的是它的静态类型检查,能简化程序分析和重构任 务。c 十 十 的静态类型特性使缩小对程序重构部分的可能引用变得相对容易。假如你想对 c + + 类的一个成员函数进行重新命名,为了正确地运用重命名重构操作,你必须改变函 数说明和所有对那个函数的引用。如果程序大的话,找到并改变这种引用可是困难的。 c 十 + 具有类继承和存取保护控制模式( 公有,保护,私有三种) 特性使对可能重命名 函数引用位置的确定更为容易。 在某些非常大的程序中, 具有相同名字的函数可能在程 序的不同地方被说明。 在 c 什中,当改变其中一个函数的名字时, 确定哪些是对重命名 函数的引用,哪些是对其它函数的引用几乎总是容易的。 因为c + + 使用子类实现子类型,变量或函数的作用范围通常能够通过使其在继承层 次中的上下移动来实现泛化或特化。分析程序并执行重构的工作是相当直接的。 在c + 十 中,用继承对泛化和特化层次建模是自 然的,这使得以后运用重构在继承层 次内移动成员变量和函数以泛化或特化它们的作用范围变得颇为直接。 此外,c 什环境中的特性支持重构。如果程序员重构程序时引进一个错误,c + + 编 译程序通常能标记出错误。许多 c + +软件开发环境提供交叉引用和代码浏览的强大能 力。 但是,c + + 有某些使重构复杂化的特性。使用诸如指针,构造操作 ( c a s t )和 s i z e o f ( o b j e c t ) 等此类语言特性的 程序难以 重构。 而且, 相对于 j a v a , c + + 是复杂得多的 语言。因此,建立对自 动化支援有用的各种程序结构代表就困难得多, 这些代表用于检 查一个重构对于执行重构是否安全。 不仅如此,因为c 十 十 在编译时解决大多数引用,重构一个程序通常需要至少重新编 译部分程序并在测试一变化的影响前链接可执行代码。相对于重新编译和重新测试而 言,c + + 程序每次迭代的成本要很高。因此程序员倾向于更不愿意做这些小的改变。 另外,许多应用使用数据库,在c + + 程序中对对象结构作出的改变可能要求相应的 数据库模式也要作出改变。 3 . 4 . 2 , j a v a 语言对重构的支持 j a v a 继承了c + + 的所有重构优点而避免了它的许多局限。j a v a 是一种纯面向对象语 言,而c + + 是一种混杂的面向对象语言。此外,它不需任何预处理器,消除了对一个成 功的c 十 十 实现的主要障碍。它不使用能简化被变换源程序装配过程的m a k e f i l e 工具。另 外,由于方法被存贮在属于类的一个文件中,简化了代码放置。j a v a 不像c + + 这样混杂 的面向对象语言,它没有任何自由漂浮的过程。 基于上面的分析比较,可以认为j a v a 是应用重构的最佳语言。目前最流行的重构文 献基本上都采用j a v a 语言作为范例, 其中包括m a r t i n 的 重构 。目 前市场上有数种支持 j a v a 和s m a l l t a l k 的重构工具,而c + + 的工具却几乎没有。 本文研究的是内存受限系统的开发问题, 考虑到目 前的内存受限系统开发语言之中, j a v a 语言的应用占了 绝大部分, 另外j a v a 语言的“ 一次编写, 到处运行” 的 特点非常 适合编写那些开发平台不确定的系统之中, 因此本文所研究的应用于内 存优化的重构的 开发语言就采用j a v a 语言。 3 .5 重构技术的发展与完善 尽管能从重构技术那里得到很多好处,但是重构还存在某些限制。在重构技术超越 学术目 的转向实用之前,需要开展进一步的 研究。 2 3 1 3 . 5 . 1 、重构技术不足之处 . 确认 ( v a l i d a t i o n ) . 怎 样才能知道被重构的程序是正确的。 在任何情况下这都是 一个困难的问题。我们期待重构工具能够像现在编译程序那样值得人们信赖, 使我们相信所作的变换是正确的。 . 行为保持 ( b e h a v i o r p r e s e r v a t i o n ) 。 重构是由于良 好的工程, 而非任何数学保证 而得以行为保持。识别确保行为保持所必要的所有可行条件是重构设计者的职 责。 . 商品 化重构 工具 ( c o m m e r c i a l r e f a c t o r i n g t o o l s ) 。 应该开 发商品 化程度更高的 重构工具以帮助程序员从事他们的日常活动。重构工具应该被集成到主流的开 发环境中,使变换后的代码能够立即显示在打开的窗口中。更高级的集成仍然 是可能的。例如,与r a t i o n a l r o s e 的集成使得当对u m l图操作时,许多重构 能被调用。 与源码控制系统的集成使得能对合适的文件进行检查, 变换和核实。 对被保护文件进行变换的企图会锁住重构并通知用户。 3 . 5 . 2 、重构应用领域的扩展 在目前的重构技术的应用研究方面,重构技术还仅仅局限于对语言层面的研究,如 对面向 对象的程序设计的重构技术研究,包括s m a l l t a l k , c + + , j a v a , c # 等,还有对于 非面向对象语言的研究,如c 语言的重构技术。 可喜的是, 现在还出现了把重构技术与其他领域的结合的研究,比如利用u ml 图进 行重构,在对系统进行静态架构设计时就进行重构,节省了后期对代码的重构的时间; 对测试用例的重构;重构面向方面的软件等等。 但是对于内存受限的系统重构的研究目前还没有,这不能不说是个遗憾,因为与通 常的重构技术相比,对内存受限的系统重构需要考虑的方面更多。 第四章契约式程序设计与重构技术 本章首先介绍了契约式程序设计的概念和实现方法,并探讨一种通过添加契约来保 证重构过程中不改变软件系统的可观察行为的方法。 4 . 1 契约式程序设计 4 . 1 . 1 、契约的概念 d e s i g n b y c o n t r a c t ( d b c , 契 约式设计) 是面向 对象软件大师b e rt r a n d m e y e r 对软件 构造方法的一个重大贡献, 无论是在形式化的数学证明中, 还是在实践运用中,都被证 明是大幅改善软件工程质量的有效手段。 在 e i ff e l 中,一个软件能够正常运作,正确完成任务,是需要一系列条件的。这些 条件包括客观运行环境良好,操作者操作正确,软件内部功能正确等等。因此,软件的 正确运行,是环境、操作者与软件本身三方面合作的结果。相应的,系统的错误,也是 由于三者中有一方没有正确履行自己的职责而导致的。 细化到软件内部, 每个软件都是 由若干不同的模块组成的,软件的错误,是由于某些模块没有正确履行自己的职责。要 彻底杜绝软件错误,只有分清各自 模块的责任,并且建立机制,敦促各模块正确履行自 己 的责任, 然后才有可能做到b u g - fr e e . 如何保证各方格守职责呢?e i ff e l 引入了契约 ( c o n t r a c t ) 这个概念。 契约所核查的, 是 “ 为保证正确性所必须满足的条件” ,也就是核查模块是否正确履行自己的职责。 契约式设计就是在设计和编码阶段向面向对象程序中加入断言 ( a s s e r t i o n ) 。所谓断 言,实际就是必须为真的假设,只有这些假设为真, 程序才可能做到正确无误。契约式 设计的主要断言包括先验条件( p r e c o n d i t i o n ) 、后验条件咖s t c o n d i t i o n ) 以及不变式 ( i n v a r i a n t ) : 先 验条 件针对方法 ( m e t h o d ) , 它 规定了 在调 用该 方法之前 必须为 真的 条件。 后验条件也是针对方法,它规定了方法顺利执行完毕之后必须为真的条件。 不变式针对整个类,它规定了该类任何实例调用任何方法时都必须为真的条件。 4 . 1 . 2 、契约式程序设计的优点和应用 使用契约式设计的优点大致分类如下: . 获得更优秀的设计。 , 提高可靠性。 . 得到更出色的文档。 . 帮助调试。 . 支持复用。 目 前,直接在语言层面上应用了契约式设计思想的程序设计语言只有 e i ff e l , 但对于 j a v a 和c + + , 则可以 通过添加工具的支持, 满足契约式设计的要求。 j a v a 语言的契约式 设 计的 支持y具主 要有i c o n t r a c t , j a s s , j c o n t r a c t , j m s a s s e rt , j a s s e rt , h a n d s h a k e , j a v a m o d e l i n g l a n g u a g e ( j m l ) ( 确切的讲不是d b c的 支持工具, 只是在思想上有些类似的 一种语言。 ) 。 4 . 2 重构过程中契约的引入 在重构定义里,有一个非常重要的前提条件:不改变软件系统的可观察行为。如果 在重构的过程中,系统的功能发生改变, 那么重构就会产生意想不到的结果,即使这种 改变是有意的行为, 重构必须保证系统的可观察行为不会被改变,为了满足这一前提条 件, 在d . b . r o b e r t s 的 文章2 0 1 里 他给出以 一 种形式 化的 证明。 这里可以利用契约来约束重构过程的进行, 使重构满足某种条件, 保证安全性重构。 在对一段程序进行重构之前, 先确定这段代码的作用, 及其与程序其他部分的联系,确 定重构的目 标。 在要重构的代码前加上契约,规定类、 方法、 变量的行为要求, 保证程 序所接收的是正确的值,并在代码后加上契约, 保证重构过程中程序的 “ 行为”不发生 变化。 这样做的目的是: 一方面建立优秀的重构前后程序文挡, 利于检查和修改。 另一 方面,确保重构之后得到合法的程序,使重构之后的程序的行为方式与重构之前等价。 在理解上,契约可以从某种程度上被视为一种 “ 程序代码” ,在代码本身被修改时, 契约也应当作出相应的修改。 在重构一段代码时,首先可以抽象出变化的模型,这个模 型除了可以用u m l 表示外, 也可以是契约的形式,以此来反映我们所需要的改变和结果, 然后在把契约写成代码进行重构。另外,注意:在类内引入一个新的m e t h o d 或变量时, 也应当使它们满足相应的类的契约。 为了保证重构过程中“ 不改变代码的外在的行为, , 在重构方法中, 添加契约式重构 的部分: 1 ) 、回答如下问题以确定重构的契约: ( 1 ) 、这段代码的作用是什么? ( 2 ) 、这段代码中需要被重构的属性有哪些?改变这些属性预期会出现哪些结 果? i 、正常的改变对这些属性的影响,如添加访问限制、更改名称、修改引用 等 h、非正常的改变对这些属性的影响,如对不存在的情况或事件的访问执行 等。 ( 3 ) ,源代码中要重构的代码段与其它部分之间的关系及影响结果。 1 6 ( 4 ) 、查找并确定要重构代码中基本查询和派生查询。 ( 5 ) 、根据代码的功能及可能产生的结果确定契约。 2 ) 、执行重构方法。 3 ) 、重构结束,运行测试并使用契约支持工具检测重构的行为保持。 4 . 3 一个实例 这是一个利用顺序表实现的城市数据库,每条数据库记录包括城市名 ( 任意长的字 符串) 和城市坐标 ( 用整数x ,y 表示) ) , 数据库允许插入记 录、 按照名字或者坐标删除 或检索记录,还支持打印在指定点给定距离内的所有记录。 第一个实现版本中的程序包含了许多的 “ 坏味道” ( s m e ll ). 下面对其进行重构并 在重构过程中加入契约。 首先需要区分开命令和查询,查询返回一个结果,但不改变对象的可见性质。命令 改变对象的状态,但不返回结果。 在这里s iz e o , v a lu e 0 f ( ) 是查询,r e m o v e o , i n s e rt ( ) 是命令。接着将基本查询同派生查询区分开,派生查询可以用基本查询来定义。对于每 一个命令都写一个后验条件,规定每个基本查询的值。 在重构的过程中, 注意到我们可以利用e x t r a c t c la s s 提取一个顺序表类a b lis t , 这时 保留 源代码不变, 因此不必添加契约。 接下来注意到变量d e f a u lt s iz e , m s iz e , n u m i n lis t 都应当属于类a b lis t , 先用m o v e f ie ld 将他们复制过去,不更改源代码中的相应变量。 下一步将 a b lis t 中变量的作用域更改为p u b lic , 接着更改源代码中相应的引用,使 它们引用a b lis t 中的变量。这些变量不必添加契约,但它们必须满足新类中的契约。 然后用m o v e m e t h o d 将 s iz e o , c le a r a llo , v a lu e 0 f o , i n s e rt o , r e m o v e o , it 个的 搬移到 a b lis t 中, 添加契约。 c le a r a llo 仍然应当 满足s iz e ( ) 二 二 0 的契约, 在这里为了节省篇 幅仅详细解释in s e rt ( ) 的契约: 首先, 添加的结果是要在顺序表里加入一个新的记录, 需 要被修改的 属性有s iz e( ) 、 n u m i n lis t , 改 变的结果会使n u m i n l is t 和s iz e ( ) 都增加了一个 相应量。 源代码中相应引用部分更改为新的 类方法。 确定契约为:前置条件 ( p r e ) 为n u m i n lis t p o s ; i - - ) a l i s t i = a l i s t i - 1 : a l i s t p o s = c i t y n u m l n l i s t + + ; * 重构之前的版本 p u b l i c c l a s s d b 一i t y f i n a l p r o t e c t e d a b l i s t c i t y a b l i s t ; /在位置p o s 插入一条城市记录 / * * qp r e c i t y a b l i s t . n u m i n l i s t c i t y a b l i s t . m s i z e * 即r e ( 1 = p o s ) 11 /z +* * 即o s t s i z e ( )= 二$ p r e y ( s i z e ( ) ) * p o s t v a l u e 0 f ( c i t y . n a m e ) = = p o s p u b l i c v o i d i n s e r t ( i n t p o s , c i t y c i t y ) c i t y a b l i s t . i n s e r t ( p o s , c i t y ) ; c l a s s a b l i s t / / 在位置p o s 插入一条记录 / * * * p r e n u m i n l i s t p o s - l ; i - - ) i 吕 a l i s t i = a l i s t i - 1 ; a l i s t p o s - 1 = c it y ; n u ml n l i s t + + ; * 重构之后的版本是一个比较好的代码 最后,在进行完成重构之后,取出代码段内的契约。 4 . 4 、本章小结 本章提出了应用契约式程序设计的方法保持重构过程的可观察行为不发生改变,为 下文将要提出的新的应用于内存受限系统的重构手法的行为保持提供了理论依据, 从而 保证新提出的重构手法通过加入契约不会改变软件系统的可观察行为。 第五章应用于内存优化的重构 在前面各章中, 对内存限 制、 重构技术的相关理论和技术进行了 探讨。 在此基础上, 在本文的研究过程中, 我们提出了应用于内存优化的重构技术, 并详细的给出了部分方 法的具体应用实例,优化内存的使用。 5 . 1 内存优化重构的特点 与 通常 意 义 上的 重 构 不同 的 是, 在 对内 存受限 系 统 ( 也就 是m e m o ry lim it e d ) 进
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 河南省农村信用社联合社秋季校园招聘笔试备考题库(浓缩500题)及完整答案详解
- 2026年安庆市农村信用社联合社秋季校园招聘笔试备考题库(浓缩500题)及答案详解(易错题)
- 2026年北京市农村信用社联合社秋季校园招聘笔试备考题库(浓缩500题)附答案详解(能力提升)
- 无锡市农村信用社联合社秋季校园招聘笔试备考题库(浓缩500题)带答案详解
- 珠海市农村信用社联合社秋季校园招聘笔试备考题库(浓缩500题)附答案详解(a卷)
- 邢台市农村信用社联合社秋季校园招聘笔试备考题库(浓缩500题)含答案详解(培优b卷)
- 汕尾市农村信用社联合社秋季校园招聘笔试备考题库(浓缩500题)及完整答案详解一套
- 商洛市农村信用社联合社秋季校园招聘笔试备考题库(浓缩500题)及参考答案详解一套
- 2026年湛江市农村信用社联合社秋季校园招聘笔试备考题库(浓缩500题)及答案详解(网校专用)
- 2026年贵阳市农村信用社联合社秋季校园招聘笔试备考题库(浓缩500题)及答案详解(名师系列)
- 2025年贵州省遵义市中小学生“π”节数学思维竞赛初赛ZYMC2数学试卷(六年级)(含解析)
- 2025年下半年四川省泸州市人力资源和社会保障局信息中心招聘3人重点基础提升(共500题)附带答案详解
- 佛山地库信号覆盖施工方案
- 2025贵州玉屏侗族自治县人民医院第一批招聘编外人员26人备考考试题库附答案解析
- 2025年国家开放大学(电大)《应用写作》期末考试备考试题及答案解析
- 学堂在线 高技术与现代局部战争 章节测试答案
- 新版苏教版四年级上册科学(全册教案及教学计划及进度表)
- 蓝豚医陪陪诊服务发展研究报告2025
- 国际压力性损伤-溃疡预防和治疗临床指南(2025年版)解读课件
- 住培教学病例讨论规范
- 生态系统的组成 完整版课件
评论
0/150
提交评论