zoukankan      html  css  js  c++  java
  • IT餐馆—第十三回 重构

        今天上午,老杜给雨辰打了电话,说他们公司之前买了雨辰所开发产品的商业授权。最近准备在该产品的最新开源版本基本上加入自己的商用逻辑。雨辰听了之后,不禁锁起了眉头。因为产品最近刚进行了一次大的重构,而之前最新的开源版本还是8个月前的那个Copy。所以雨辰马上询问了老杜关于要加入的代码的情况。 

        老杜说:“目前主要已改动的代码主要是前台页面显示方面的。因为你们的产品使用了模板机制,所以变成的主要是模板上的内容,同时我们也在相关的.aspx.cs文件中改动了一些逻辑。” 

        雨辰连忙说:“如果刚开始修改不久的话,那马上停下。因为我们产品三个月前刚行了一些大的重构,主要的前台业务逻辑和业务逻辑层代码都有变动。眼下我们还没有发布这个重构过的源码。所以最后先停一下二次开发。” 

        老杜在电话那头抱怨说:“不会吧,你可坑苦了我了。我和手下两个人已改了一个多星期了。真晕,这样行不行,我中午吃完饭下午去一下你们公司,让你看看我们改动的地方,能不能对付着用。顺便看看你们倒底重构成什么样了,哎,刚摸出点门道,又要变了。” 

        雨辰笑着说:“也怪你,改之前为啥不通知我一下,我也好给你们通通风,现在快生米成熟饭了,才来问我,你也真沉得住气。” 

        老杜:“得了,得了。有这回教训了,下次一定先问问你老弟。好吧,咱们下午见。” 

        就这样,下午130,老杜就到了雨辰所在的公司,雨辰之前已在前台预订了小会议室,就连忙带着老杜过去了。 

        在会议室里,老杜打开笔记本电脑,给雨辰讲了他们已修改过的部分代码。雨辰看了之后,感觉问题还不是很大。就告诉老杜先停止对业务逻辑层的修改,先把前台模板和相关aspx.cs文件保留一下,因为雨辰在这两方面重构的内容不是很多,变化不大。接着,老杜就报怨起来说:“代码好好的在那儿,你们非要折腾,重构个什么劲。” 

        雨辰就笑着说:“你老兄有所不知。在我刚来公司之前,产品就已写了不少代码,当时因为产品急于上线,所以导致前台copy严重,有些页面基本上只是名字不同,而cs代码重复的过于严重,这就造成了当我们解决bug时,虽然修正了当前页面,但同样有问题的代码还寄宿在别的页面中。而等于别的页面中也出现了类似问题时,因为解决之前bug的人不是同一人(有的已离职),而后来的人解决方法又采用了自己的方式,导致代码的可维护性越来越难。同时,原来我们产品的业务逻辑层分的不够清晰,导致很多原本应放在逻辑层的代码都被堆到的前台,这直接导致代码的可复用性差。”  

        雨辰就笑着说:“举个例子说吧,之前我们产品中对资源访问权限的业务代码就普遍写在了前台页面,直接导致了可复用性不强。所以我们在这个版本中就专门将权限控制封装起来,提供统一的访问接口。这一方面便于代码的维护管理,而消除了不少前台重复的代码。” 

        老杜听着有些道理,就接着问:“那你们这次变动的主要都是那些方面的内容呀。” 

        雨辰说:“前台的.aspx.cs文件,以及业务逻辑层,数据访问层都变了,为了这次重构,公司专门给了我们两个半月的时间,从以往的经验看,这次机会真的很难得。” 

        老杜听这么说:“这到是,按说重构都是平时开发和维护时做的工作,而像你们这样专门拿时间来重构的情况确不多见,呵呵。” 

        雨辰说:“没办法,都是历史积累的问题,如果在这个版本再不下大力气好好整一下的话,以后就更难办了。其实早在1年前我就向公司反映了情况,只因为当前为了抢占市场,就一直舍不得拿时间出来做,必定这个活是变像给人或自己‘擦屁股’吧,我也是一开始就给团队中的成员讲了问题的严重性之后,才最终得到公司和成员的一致认可,并最终实施的。” 

        老杜听着很好奇,问:“那你就给我详细说说你们这次重构使用的方法吧。我之前看过MARTIN的那本书,重构方面的经验还不是很多。” 

        雨辰说:“你客气了吧,其实我也是把那本书带到团队中让大家边看边做的,遇到问题时我会去把关,同时我也感觉到书中的大部分内容还是很有帮助,特别是前四章,比如说局部变量使用,公用方法的抽取等。不过我也是灵活把所握,没完全按书中的步骤一步步来,那样太慢了,我跟大家说,只要清楚重构的边界,并熟悉里面的代码,就可以重构了,当然这次我们采用结对的方式来做,避免因出现个人头脑发晕而出现错误的情况。” 

        雨辰边说边找了支墨水笔,在玻璃黑板上画出了一个三层架构图。并指着其中的数据访问层接着说:“其实如果之前看过数据的业务逻辑层的话,你就会发现一个问题,就是里面混合了大量的数据绑定代码,比如从IDataReader获取数据绑定到对象实例。” 

        老杜:“是有这么回事,我开始看的时间还有点犯晕呢,必定这种代码与业务逻辑实在是扯不上太大关系,应该放到别处。” 

        雨辰说:“我们这次这把它移到了数据访问层,这样通过该层方法所最终获取的都是对象实体或实体集合。业务逻辑层直接使用这些实体就行了。这就有点像.. 

        老杜:“LINQORM 

        雨辰:“是呀,呵呵,其实我这样做的目的,也是为了日后当有第三方的数据访问框架或LINQ进来之后,只要变动这一层的代码就可以了,而不是把业务逻辑层甚至前台页面也要翻一遍。” 

        老杜点了点着:“说是这么说,不过有个问题,就是这一层的每个方法可能代码比较少,有的只是一个sql语句而已,而主要就是数据绑定了,会不会出现重复代码,比如绑定时。” 

        雨辰:“的确是这样,所以我们将绑定代码专门抽出来做成一个私有方法放在该层,以IDataReader为了参数(类型)来使用。当然在重构的过程中我们也发现了不少数据访问方法中存在重复或类似的SQL语句,所以也稍带脚给重构或删除了。呵呵。介绍完了数据访问层,就该说业务逻辑层的重构了,这次重构的主要内容都是针对这一层的。” 

        雨辰喝了口水,接着说:“之前将数据绑定代码迁移到了数据访问层之后,业务逻辑层轻快了一些,但还是有不少重复的代码,这主要还是当初开发人员为了赶进度Copy的‘恶果’,并且有的方法最后发现前台压根儿就没有使用,属于严重的过度开发,所以这次也都被拿下了。而有些方法因为其自身可以被其他方法代替或以组给的方法‘代替’,也被拿下了。比如说‘判断指定用户名是否存在’的方法,它的判断条件就与‘获取指定用户名信息’的方法有重叠,所以就将其方法注释,全部使用‘获取指定用户名信息’的方法了。另外除了将本应放在数据访问层中的代码迁走(我管这叫‘腾地儿’)之外,还有就是将前台本应放在业务逻辑层中的代码迁入了进来(我管这叫‘安家’)。比如之前跟你说的权限那块,还有不少其它的方法也按业务逻辑被封装,组合。而这时我们得到的一个业务逻辑层才是真正有价值的东西。现在我们在找BUG时,基本上就很容易发现并修改了,并且可以说,只要改动一处,就顺便把其它页面中的业务逻辑BUG也改了(以前重复代码造成的)。另外还有一点就是这次对业务逻辑层的重构有个要求:为下一步开放API提供更好‘可用’‘好用’的方法。因为将来API所暴露出的方法主要会来自于此。” 

        老杜:“如果按你所说的这样,的确是不错,重构所花的时间也算是有所偿了。” 

        雨辰接着说:“下面接着说一下前台表现层了。其实在我们产品1.0发布时,前台的页面.cs文件就有很多大流水的代码,基本都放在了相应页面的‘构造方法’中,让人乍一看就像是‘asp时期’的代码,根本就像是asp.net代码。这些代码中有对前台页面数据的绑定,也有本应属于业务逻辑层代码,当然还有很多重复的代码,它们都被杂居混合到了一起给开发者和阅读代码带来了很大的‘困扰’,思维总在流水代码中左蹦右跳,经常会被干扰打断,甚至看了两三遍之前才敢下手改动,最后因为代码的耦合过紧不能很好的加以分离成更多可复用的方法,导致所谓的开发修改只能是加重了这一‘病情’现象,最终流水越来越长。所以这次重构也尽可能的从前台页面cs中迁移走业务逻辑层代码。同时将大流水的代码按逻辑功能分划成一些方法,保证每个方法在当前IDE窗口一屏内显示完毕,避免滚屏阅读,而对于实在难以分割成方法的代码,用#region的方式加以标记。同时对重复代码量较大的页面抽取出一个公共的基类,将那些页面继承自它。经过这一番折腾,前台代码的可读性得以保证。同时当前台页面出现BUG时,也能够快速定位了。” 

        说着,雨辰用VS2008打开了产品的sln文件,对重要的重构代码又给老杜解释了一遍。然后接着说:“目前你所修改的主要还是在前台页面上,如果你们眼下急于修改的话,我只能临时把你们需要的重构过的文件发给你们来做参考了。” 

        老杜叹了口气:“得了,还是放一放吧,尽管领导那边急着要。但如果按你刚所说的情况来看,目前还是不太适合进行二次开发,我想还是等你们正式版出来开源之后再说吧。不过听你这么说,还是挺值得期待的。呵呵。对了,我记得在重构书中提到过重构到模式,不知道这回你们有没有从代码中提练出‘模式’来呀” 

        雨辰说:“这次没有,因为都是工作量上的东西,没有出现那种需要高度抽象和提练的情况。其实之前我在这个产品代码中的确提练出了一些模式,比如产品中使用了‘模板生成机制’,就原理就是基于Template Method方法来生成相应模板,这也算是‘门当户对’吧。而另一个是在产品的聚合页面上,我们需要一种机制:当后台数据源信息修改之后,要能够自动通知前台页面‘数据的修改情况’,所以就提练出来了observer模式,这在我的blog中都写了,不知道你看过没有。”说着,雨辰就打开了自己的blog地址,把链接用msn传给了老杜。 

        老杜说:“这个还没看,回去参考一下,呵呵。其实我觉得重构只要在确保‘程序正常运行的情况下提升代码的可读性’就可以了,我想这也是重构书中所提过的。而使用什么方法倒不必严格参照书中的进行。” 

        雨辰拍拍老杜肩膀,说:“是呀,其实这次如果按书中的方式去重构,或将书中所说的所谓‘bad smell’,就去搞一把的话,有些地方根本就是生搬硬套了。不过我们重构之前统一了代码规范,包括变量,方法的名称定义长度,属性的大小写方式,参数的格式等,这样也让重构有了一些切实可行的标准。另外,也希望你能再等些时候,半年多都忍过来了,也不怕再等上一时三刻。我们这次的努力应该不会让你失望。” 

        …………………


          原文链接:http://www.cnblogs.com/daizhj/archive/2009/08/17/1541378.html

          作者: daizhj, 代震军

          Tags: IT餐馆,重构

          网址: http://daizhj.cnblogs.com/
  • 相关阅读:
    (原创)C++ IOC框架
    【教训】为什么不作备份?!
    【教训】php pcntl_fork无法在web服务器环境下使用
    PHP多进程处理并行处理任务实例
    mysql数据库授权
    PHPUnit学习03使用Mock对象解决测试依赖
    [Inside] How to solve one problem?
    [Inside] What’s the assumptions you are making
    算法面试题解答(六)
    [Inside] System Thinking
  • 原文地址:https://www.cnblogs.com/daizhj/p/1541378.html
Copyright © 2011-2022 走看看