热门标签 | HotTags
当前位置:  开发笔记 > 程序员 > 正文

对重构的理解

什么是重构重构,用最简单的一句话说:就是要在不改变系统功能的情况下,对系统的内部结构进行重新调整。重构的最直接目的在于改进软件系统的内部架
什么是重构



重构,用最简单的一句话说:就是要在不改变系统功能的情况下,对系统的内部结构进行重新调整。重构的最直接目的在于改进软件系统的内部架构。一个好的结构可以更加适应于需求的变化,更好的满足客户的需求,最大限度的延长软件系统的生命周期。



为什么要重构



在不改变系统功能的情况下,改变系统的实现方式。为什么要这么做?投入精力不用来满足客户关心的需求,而是仅仅改变了软件的实现方式,这是否是在浪费客户的投资呢?




重构的重要性要从软件的生命周期说起。软件不同与普通的产品,他是一种智力产品,没有具体的物理形态。一个软件不可能发生物理损耗,界面上的按钮永远不会因为按动次数太多而发生接触不良。那么为什么一个软件制造出来以后,却不能永远使用下去呢?




对软件的生命造成威胁的因素只有一个:需求的变更。一个软件总是为解决某种特定的需求而产生,时代在发展,客户的业务也在发生变化。有的需求相对稳定一些,有的需求变化的比较剧烈,还有的需求已经消失了,或者转化成了别的需求。在这种情况下,软件必须相应的改变。




考虑到成本和时间等因素,当然不是所有的需求变化都要在软件系统中实现。但是总的说来,软件要适应需求的变化,以保持自己的生命力。




这就产生了一种糟糕的现象:软件产品最初制造出来,是经过精心的设计,具有良好架构的。但是随着时间的发展、需求的变化,必须不断的修改原有的功能、追加新的功能,还免不了有一些缺陷需要修改。为了实现变更,不可避免的要违反最初的设计构架。经过一段时间以后,软件的架构就千疮百孔了。bug越来越多,越来越难维护,新的需求越来越难实现,软件的构架对新的需求渐渐的失去支持能力,而是成为一种制约。最后新需求的开发成本会超过开发一个新的软件的成本,这就是这个软件系统的生命走到尽头的时候。




重构就能够最大限度的避免这样一种现象。系统发展到一定阶段后,使用重构的方式,不改变系统的外部功能,只对内部的结构进行重新的整理。通过重构,不断的调整系统的结构,使系统对于需求的变更始终具有较强的适应能力。



拒绝变化 VS 拥抱变化



按照传统的软件设计方式,软件的生产分为需求调查、概要设计、详细设计、编码、单体测试、联合测试、现场部署几个阶段。虽说这几个阶段是可以互相渗透,但是总的来说是有一定次序的,前一个阶段的工作是后一个阶段工作的基础。这就向下面这样一种V形的模式:









往下的方向将系统进行分解,往上的方向将系统进行整合。这样的开发形式将软件开发分为设计前和设计后两个阶段,开发过程中存在一个重要的“里程碑”——设计说明书的。在设计说明书完成前,工程处于“设计”阶段,而在设计说明书完成之后,工程则进入“实施”阶段。一旦到了实施阶段,任何需求或者设计上的变更都是非常困难的,需要花费大量的成本。通常为了保证工程的顺利实施,开发人员常有这样一种冲动:按住客户的手,在需求说明书上签字。并且告诉客户:“从今天开始,任何需求变更都要停止,直到我们把现在这个东西做完。”这是一种拒绝变化的开发方式。




软件系统要保持与企业的目标一致。时代在发展,人们的要求在不断的提高,客户的业务在不断的发展。在这种情况下,传统的先设计、再施工的V形式已经不能适应日益复杂的业务需要。软件工程逐渐演化成下面这样的过程:









说明一下:


1、软件开发的目标要与企业目标保持一致,一个开发周期不宜时间过长,一般控制在半年到一年。系统部署后,并不意味着开发工作结束了,而是进入了下一个周期。




2、工程以循环迭代的方式前进,这并不意味轻视了设计,不是要搞边调研、边设计、边施工的“三边”工程,相反,是更加重视设计的地位。软件开发的全过程都需要设计,软件开发是“持续设计”的过程。同时,设计工作也不只是简单过程分解、任务分配,而是概念设计、逻辑设计、物理设计等各个方面互相交织、齐头并进。




传统的软件开发方式使用一种非常理想化的流程——先与客户讨论项目的范围,确定哪些需要做,哪些不需要做,然后规划一个完美的设计,不仅可以满足现在的需求,还能很好的适应未来的需求,设计完成后开始编码,然后测试组装,送到现场安装调试运行。这一系列过程就类似与发射一颗炮弹,首先要找到目标,然后根据地形、风力、目标的位置、移动速度等各种因素,计算提前量、炮弹发射的角度,计算出一个抛物线轨道,最后在合适的时间把炮弹发射出去。这一切都符合最正确的物理定律,一切都听起来很理想。如果没有意外条件,当然是可以击中目标的。但是炮弹一旦发射出去,一切就失去了控制,任何环境的变化都会造成偏离目标。尤其是对于一个运动的目标来说,计算过程十分复杂,很多情况下只能靠人估计。对于不规则的运动目标只能碰碰运气。这样的方式,命中率是很低的。




新的软件开发过程不追求完美的、长期的、理想的计划,更加重视实际情况,重视需求的变化,提倡采用短期的计划。这是一种拥抱变化的过程。就象是在炮弹上安装了一个反馈装置,锁定目标后,确保大方向的正确,然后就将炮弹发射出去。炮弹在运行过程中不断的将目标位置偏移量输入反馈电路,根据反馈输出调整自己的运行路线,无限的逼近目标。这样,炮弹就拥有了制导能力,命中率大大增加。




重构就可以增加工程的调整能力,他可以把产品回复到一个稳定的状态,可以基于这个状态达到下一个目标。如此反复前进,更好的满足客户的需求。




保持兼容性



重构的目的在于改变系统的实现方式,而不改变原有的功能。这个过程中,判断兼容性就十分的重要。一个子系统、模块、类、函数是否与升级前保持兼容,如何判断这个兼容性,如何保持这个兼容性,这关系到重构的成本和重构的可能性。




程序员学习写程序代码时,会发现随着程序代码愈来愈多,许多的程序代码不断重复出现和被使用,因此很自然的开始使用例程、子程序或是过程、函数等机制帮助我们进行程序代码整理的工作。于是很自然的,字体的分析方式演化成这个样子:将客户的需求过程进行分解,一步一步的分解,直到可以直接的实现他。这就是面向过程的分析方式。




面向过程的分析方式对变化的能力是很弱的。为什么呢?因为面向过程的分析方式很容易造成一种倾向——不区分行动的主体。一个过程是没有主体的,他不是在为自己工作,而是在为“别人”工作。当我们修改了一个过程之后,我们很难判断这个过程是否保持向后兼容,其他过程会不会受到影响。因为这个过程对外界有意义的不仅是他的输入和输出,还包括每一步过程,每一步过程都可能含有一个非常隐讳的业务意义,对外界产生影响。




因此,修改一个过程是非常困难的,通常升级一个面向过程的系统,可以采用两种方式:


1、写新的过程;


2、在原有的过程上加开关参数。




除此以外的升级办法都很难保证原过程和新过程的兼容性,容易造成错误。




为了更好的保证升级后模块的兼容性,应该采用面向对象的分析方式。按照这样的分析方式,一个对象为“自己”工作,他有完整的、独立的业务含义。对象之间通过接口发生联系,一个对象对外界有影响的部分只有接口,至于他做什么、如何做、做的对不对,则不是外界需要关心的事情。




判断一个接口升级后是否保持兼容性就是一件比较容易的事情了。我们可以判断接口的输入输出是否符合下面两条规则:


1、升级后的输入是升级前的输入的超级;


2、升级后的输出是升级前的输出的子集。




只要符合这两点,他就仍然可以在系统中运行,不会对其他对象造成危害。在实际的工程中,判断这个兼容性有一个更好的办法:
自动化的单元测试





在重构的过程中,自动化的单元测试是非常好的保障。采用自动化的单元测试,不断运行测试,可以保证系统的结构改变的过程中,业务行为不发生改变。

推荐阅读
  • 2018年人工智能大数据的爆发,学Java还是Python?
    本文介绍了2018年人工智能大数据的爆发以及学习Java和Python的相关知识。在人工智能和大数据时代,Java和Python这两门编程语言都很优秀且火爆。选择学习哪门语言要根据个人兴趣爱好来决定。Python是一门拥有简洁语法的高级编程语言,容易上手。其特色之一是强制使用空白符作为语句缩进,使得新手可以快速上手。目前,Python在人工智能领域有着广泛的应用。如果对Java、Python或大数据感兴趣,欢迎加入qq群458345782。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文内容为asp.net微信公众平台开发的目录汇总,包括数据库设计、多层架构框架搭建和入口实现、微信消息封装及反射赋值、关注事件、用户记录、回复文本消息、图文消息、服务搭建(接入)、自定义菜单等。同时提供了示例代码和相关的后台管理功能。内容涵盖了多个方面,适合综合运用。 ... [详细]
  • 本文介绍了2019年上半年内蒙古计算机软考考试的报名通知和考试时间。考试报名时间为3月1日至3月23日,考试时间为2019年5月25日。考试分为高级、中级和初级三个级别,涵盖了多个专业资格。报名采取网上报名和网上缴费的方式进行,报考人员可登录内蒙古人事考试信息网进行报名。详细内容请点击查看。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • 从零学Java(10)之方法详解,喷打野你真的没我6!
    本文介绍了从零学Java系列中的第10篇文章,详解了Java中的方法。同时讨论了打野过程中喷打野的影响,以及金色打野刀对经济的增加和线上队友经济的影响。指出喷打野会导致线上经济的消减和影响队伍的团结。 ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • 本文介绍了程序员最美的情人节礼物,即使用JS渲染的3D玫瑰,通过在QQ空间和人人网上分享这个特殊的礼物,可以给情人带来惊喜和喜悦。 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • 本文介绍了一种处理AJAX操作授权过期的全局方式,以解决Asp.net MVC中Session过期异常的问题。同时还介绍了基于WebImage的图片上传工具类。详细内容请参考链接:https://www.cnblogs.com/starluck/p/8284949.html ... [详细]
  • 本文介绍了在Mac上安装Xamarin并使用Windows上的VS开发iOS app的方法,包括所需的安装环境和软件,以及使用Xamarin.iOS进行开发的步骤。通过这种方法,即使没有Mac或者安装苹果系统,程序员们也能轻松开发iOS app。 ... [详细]
  • 如何在跨函数中使用内存?
    本文介绍了在跨函数中使用内存的方法,包括使用指针变量、动态分配内存和静态分配内存的区别。通过示例代码说明了如何正确地在不同函数中使用内存,并提醒程序员在使用动态分配内存时要手动释放内存,以防止内存泄漏。 ... [详细]
  • 本文介绍了自动化测试专家Elfriede Dustin在2008年的文章中讨论了自动化测试项目失败的原因。同时,引用了IDT在2007年进行的一次软件自动化测试的研究调查结果,调查显示很多公司认为自动化测试很有用,但很少有公司成功实施。调查结果表明,缺乏资源是导致自动化测试失败的主要原因,其中37%的人认为缺乏时间。 ... [详细]
author-avatar
beng83790si
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有