• 资源总数:14113个
  • 评论总数:1739次
  • 本月更新:1117个
  • 访问总数:8868553次
笑哥
  • 站长:笑哥
  • 89573952
    • 打造专业的干货基地
    • 分享实用的软件技术
    • 资源总数:14113个
    • 评论总数:1739次
    • 本月更新:1117个
    • 访问总数:8868553次

    重构-改善既有代码设计【8-9】章整理学习分享(重构手法:组织数据/条件表达式

    笑哥2017-12-18笑哥共享网
    大家好,今天继续给大家分享重构手法,以下是文章主要内容:

                  1. 更新的重构原则。
                  2. 重新组织数据系手法。
                  3. 简化条件表达式系手法。
                  4. 项目分享。
          
             随着“重构原则”的充实,整体收获并没有那么大了,因此项目分享在数据处理系后停更。相应给出比较好理解的一句话概括。
             这个编辑器有点难受,我复制自己写的发送的时候居然标题全变成1. 了。=

            一、重构原则更新:
                  
    为即将修改的代码建立一组可靠的测试环境。
    临时变量助长冗长而复杂的函数。
    最好不要再另一个对象的属性基础上运用switch语句。如果要switch也要在类自己的数据上使用。
    事不过三,三则重构。
    首先写出可调的程序,然后调整它以求获得足够速度。
    一个好的名字可以省去读函数内容的操作。
    每当需要注释说明时,可以被写进一个函数里,并以用途命名,关键不在函数长度,而在函数做什么,怎么做。
    条件和循环也是提炼信号。
    针对外界变化的所有相应修改,应该只发生在单一类中,这个类的所有内容随外界变化。
    一个函数使用几个类的功能,它应该被放在最多被此函数使用的数据一起。
    对于出现在不同类/方法内的一些绑在一起的数据,应该给它们设置对象。
    少用switch,switch代表重复。
    两个帽子原则:不要边写代码边重构,带上写代码的帽子,觉得需要重构了,再带上重构的帽子去做,如此反复。
    注释多写为什么这样,过多注释不一定是好,尝试重构。
    先编写测试代码可以将关注点放在接口而非实现。
    每当出现一个BUG,先写一个测试单元测试BUG。不要修改以前的测试单元,因为它可能会在修复BUG后出错。
    测试:异常,边界
    测试太多带来的效益呈现递减态势。但是我们尽量测试大多数BUG。
    小步前进,频繁测试。
    即使想要提炼的函数非常简单,只要新函数名能更好地示意代码意图,也应该提炼它。
    重构出来的函数优先使用private修饰,日后可以慢慢放开。
    重构时可能会有性能问题,但这不是主要问题,如果没有重构,好的优化方案就可能与你失之交臂。性能实在太糟糕,临时变量放回去也很容易。
    临时变量如果被赋值多次,尽量使它们只使用一次。
    JAVA只采用按值传递参数,因此对参数赋值一般不可取,不要对参数赋值。
    public不是java的全部,java值得封装的东西有很多。
    先写测试,再写类。
    去除控制标记,语句会清晰明了。
    “每一个函数只能有一个入口和一个出口”的观念会使人陷入代码的坏味道。
    条件反转有时候可以帮助写清晰的代码。
    if then else也代表重复,尽量不要写。
    [size=13.3333px]使用空对象可以方便的处理很多东西,它一定是常量。非常适合使用Singleton模式。

            
            二、重新组织数据系手法:

    Self Encapsulate Field自我封装字段 196
    直接访问一个字段,但字段之间耦合关系逐渐笨拙:为字段生成get/set方法,以函数访问。

       2. Replace Data Value with Object以对象取代数据值 200
    有一个数据项,需要与其他数据和行为一起使用才有意义:将数据变成对象。


       3. Change Value to Reference将值对象改为引用对象 204
    一个类衍生许多彼此相等实例,需要将它们替换为同一个对象:将这个值变为引用对象。
    使用Replace Constructor with Facotry Method->测试->决定对象负责提供访问新对象的途径->决定引用对象预先创建好还是动态创建->修改工厂函数,令其返回引用对象->测试

       4. Change Reference to Value将引用对象改为值对象 208
    有一个引用对象,很小且不可变,且不易管理:将它变成一个值对象。
    值对象的特性,它是不可变的。
    使用Remove Setting Method(300)将它变为不可变->建立equalss()和hashCode()->测试->考虑删除工厂,构造声明函数为public


       5. Replace Array with Object以对象取代数组
    有一个数组,元素格子代表不同东西:以对象替换数组,对于数组中每个元素,以一个字段表示。


       6. Duplicate Observed Data复制“被监视数据”
    有一些领域数据置身于GUI控件,领域函数需要访问这些数据:将数据复制到领域对象,建立Observer模式,用以同步领域对象和GUI对象内的重复数据。


       7. Change Unidirectional Association to Bidirectional将单向关联改为双向关联
    两个类需要使用对方特性,但其间只有一条单向连接:添加反向指针,并使修改函数能同时更新两条连接。
    使用不当的话,反向指针容易造成混乱,但只要习惯这种手法,其实并不太复杂。
    在被引用类中增加一个字段,保存反向指针->决定由哪个类(引用端还是被引用端)控制关联关系->在被控端建立一个辅助函数,命名应指出它的有限用途->如果既有的修改函数在控制端,让它负责更新反向指针->如果在被控端,就在控制端建立一个控制函数,并让既有的修改函数调用这个新建的控制函数。


       8. Change Bidirectional Association to Unidirectional将双向关联改为单向关联 225
    两个类之间有双向关联,但如今其中一个类不再需要另一个类的特性。
    找出该去除的指针->如果使用了取值函数,先用Self Encapsulate Field将待删除字段自我封装,然后使用Subsititute Algorithm对付取值函数。->如果客户未使用取值函数,直接修改带删除字段的所有被引用点。->如果没有任何函数使用待删除字段,移除所有对字段的更新逻辑。


       9. Replace Magic Number with Symbolic Constant以字面常量取代魔法数
    有一个字面数值,带有特别含义:创造一个常量,根据意义命名,并将上述字面数值替换为这个常量。
    声明一个常量->找出引用点->检查是否可使用新声明变量替换魔法数->魔法数替换完毕,整个程序应运转如常。


       10. Encapsulate Field封装字段
    类中存在一个public字段:将它声明为private,并提供相应访问函数。
    提供get/set。


       11. Encapsulate Collection封装集合
    有个函数返回集合:让这个函数返回集合的只读副本,并在这个类中提供添加/移除集合元素的函数。


       12. Replace Record with Data Class以数据类取代记录
    需要面对传统编程环境中记录结构:为该记录创建一个哑数据对象。
    新建一个类表示这个记录->对于每项数据,在新建类中建立对应private字段,并提供相应取值/设值函数。


       13. Replace Type Code with Class以类取代类型码
    类之中一个数值类型码,但并不影响类行为:以一个新的类替换该数值类型码。


       14. Replace Type Code with Subclasses以子类取代类型码 248
    有一个不可变类型码,它会影响类的行为:以子类取代这个类型码。



       15. Replace Type Code with State/Strategy以State/Strategy取代类型码 252
    有一个类型码,会影响类的行为,但无法通过继承消除:以状态对象取代类型码。
    类型码抽象成类,可进行的操作就会变多。


       16. Replace Subclass with Fields以字段取代子类 257
    各个子类的唯一差别只在“返回常量数据”函数上:修改这些函数,使它们返回超类中某个新增字段,然后销毁子类。
    复杂而冗余的类关系会导致代码的坏味道。


            三、简化条件表达式系手法:

        1. Decompose Conditional分解条件表达式 263
    有一个复杂的条件语句:从if then else 三个段落中分别提炼出独立函数。
    逻辑里的东西是非常难读的,与其加一个注释不如直接Extract Method。


        2. ConsolIDAte Conditional Expression合并条件表达式 265
    有一系列条件测试,都得到相同效果:将这些测试合并为一个条件表达式,并将这个条件表达式提炼成独立函数。
    有时候有一堆if的测试也很难读,干脆把它们一起提取了。
    一堆if 使用或 ;if嵌套使用 与


        3. Consolidate Duplicate Coditional Fragments合并重复的条件片段 268
    再条件表达式的每个分支上有相同的一段代码:将这段重复代码搬移到条件表达式外。
    去除重复代码。


        4. Remove Control Flag移除控制标记 270
    在一系列bool表达式中,某个变量带有“控制标记”作用:以break语句或return 语句取代控制标记。
    去除控制标记,语句会清晰明了。
    有时候会有副作用,使用Separate Query from Modifier将副作用移除。


        5. Replace Nested Conditinal with Guard Clauses 以卫语句取代嵌套条件表达式 275
    函数中条件逻辑使人难以看清正常执行路径:使用卫语句表现所有特殊情况。
    就是不用else,全部用if/return达成一步步过滤的状态。
    “每一个函数只能有一个入口和一个出口”的观念会使人陷入代码的坏味道。
    条件反转有时候可以帮助写清晰的代码。


        6. Replace Conditinal with Polymorphism 以多态取代条件表达式 280
    手上有个条件表达式,它根据对象类型不同选择不同行为。:将这个条件表达式的每个分支放进一个子类内的覆写函数中,然后将原始函数声明为抽象函数。
    就是使用多态把switch给拆开到类里面去了。


        7. Introduce Null Object引入null对象 285
    你需要再三检查某对象是否为Null: 将null值替换为null对象
    [size=13.3333px]使用空对象可以方便的处理很多东西,它一定是常量。非常适合使用Singleton模式。
    [size=13.3333px]用空对象继承原对象,原对象isNull为false空对象为true,以后.isNull()即可知道是否为空。甚至可以添加一个接口Nullable昭示大家这是一个空对象。
    空对象是一个特例类。


        8. Introduce Assertion引入断言 292
    某一段代码需要对程序状态做出某种假设:以断言明确表现这种假设
    使用断言“一定为真”的情况,可以帮助程序不出错,滥用断言会导致逻辑混乱。

    本站所有工具纯属免费共享,请学会感恩作者,无脑喷子永封IP段+删帐号所有评论 不喜欢请右上角X

    快快发表了一针见血的评论,你还等什么?
    用户名:
    验证码:点击我更换图片
    微信关注笑哥返利机器人
    微信号:blm737669552

    把宝贝分享给我(即宝贝链接),我会自动帮你找优惠券和返利的,领券购物立省钱!

    扫码加不上的加微信号blm737669552查看详情