9.Primitive Obsession(基本性别偏执)
Java以基本型别表示数值,以class表示字符串和日期------这两种型在其他语言中都是基本型别表示。作者说:面向技术的新手通常不愿意在小任务上运用小对象。像是结合数值和币别的moneyclass,含一个起始值和一个结束值的rangeclass,对于这些都可以运用Replace Data Vlue with Object(175,以对象取代数据值),进入炙手可热的对象世界。
比如说一个电话号码,通常在我们的设计里面它仅仅是一个字符串,但是后来发现又有了一些如[格式化],[抽取区号]的行为,在没有见到这则准则之前,我们通常是在哪个类里面用到电话号码就把这些方法放在哪里。但是这往往会引起Duplicate Code和Feature Envy,使用这个准则确实可以减去不少坏味道。
有时候这些数值是型别码,在C语言为基础的编程语言中,型别码是很常见的,但是在java中对于型别码有更好的处理方式。
对于那些不影响行为的型别码,也就是说不同的型别码并不需要不同的处理,不影响其他的一些行为,那么可以运用Replace Type Code with Class(128,以类取代型别码)。这里作者提到了一个很恰当的例子,就是血型,只有O,A,B,AB四种血型,这时可以使用一个BloodGroup血型类。
如果你有方法或者属性依赖于你的性别吗,那么使用Replace Type Code with SubClass(223,以子类型取代性别码)将会使很好的,借助多态来处理变化的行为,最大的好处在于:对不同行为的了解在class用户那儿转移到了class自身,当需要加入新的变化时,只需要加入一个subclass就行了。如果没有多态机制,我们就必须找到所有条件式。
在提到上面的重构准则的时候,作者都提到了一个一个方法就是Self Encapsulate Field(自封装值域),就是为值域设立set/get方法,好处就在于subclass可以通过[覆写一个函数]而改变获取数据的途径。
如果有一组总是被放在一起的值域,应该使用extract class,如果正在从array中挑选数据,可以运用Replace Array with Object(186,以对象取代数组)。比如,有时候我们并不是仅仅需要一个true/false的返回值而已,如果是false,我们可能还要得到false的原因(有多种),那么这时候你可能会想到以一个数组作为返回值,【0】代表true/fasle,【1】代表返回的具体信息。这确实是一种解决问题的方法,但是可读性确实是非常的差,这时我们可以建立一个专门的工具类,用来表示这种返回值。
10. Switch Statements(switch惊悚现身)
(通常我用的是if else)作者提到:面向对象程序的一个最明显的特性就是:少用switch(或case)语句。大多数情况下,一看到switch语句就应该考虑[多态]来替换它。
首先可以使用Extract Method将swutch语句提炼到一个函数中,再用move Method将他们搬移到需要多台机制的class里,此时在决定是否使用Replace Type Code with SubClass,一旦完成这样的继承结构之后,我们就可以运用Replace Conditional with Polymorphism(255,利用多态取代条件式)。这里面的东西有点复杂,我只能照抄了。
11.Parallel Inheritance Hierarchies(平行继承体系)
这其实是Shotgun Surgery的特殊情况。在这种情况下,每当你为某个class增加一个subclass,必须也为另一个class相应增加一个subclass。消除这种重复性的一般策略是:让一个继承体系的实体(instances)指涉另一个继承体系的实体。如果再接再厉运用Move Method(142)和Move Field(146),就可以将指涉端的继承体系取出。(不是很明白,照抄)
12.Lazy Class
项目中的某个class原本有一定的价值,但是重构使得它身形缩水,不再做那么多工作。总之,因为各种原因,这个Class已经没有存在的必要,那么应该果断的取出他。
如果某个subclass没有做没有做满足够的工作,可以使用Collapse Hierarchy(344,折叠继承体系),将subclass和superclass何为一体。这里主要用到的方法是pull up Field、pull up Method、push Down method、push down field,把想要溢出的class内的所有行为搬移到另一个class。对于几乎没用的组件,应该使用Inline class(154,将类内联化)
13.Speculative Generality(夸夸其谈未来性)
做过多的预先设计,通常会照成系统的难理解和维护。没必要的委托可以用Inline class(154,将类内联化)去除掉。如果函数的某些参数未被用上,可对他实施Remove Parameter(277,移除参数)
14.Temporary Field(令人迷惑的暂时值域)
对于某些特定情势而设置的变量,通常会让人不理解,这时候可以用extract class为这个实例变量找一个住所,然后把所有和这个变量相关的代码都放进这个新家.对于一些[条件式代码],还可以使用Introduce Null Object(260,引入Null对象)在[变量不合法]的情况下创建一个Null对象。
15.Message Chains(过度耦合的消息链)
可能有些用户从一个对象索求另一个对象,然后再向后者索求另一个对象,然后再索求另一个对象,这就是Message Chains。对于这种过度紧密的耦合,你应该使用Hide Delegate(157,隐藏委托关系)也就是在server端放置一个简单的委托函数(delegate method),将委托关系隐藏起来,变化将被限制在server端中,不会设计客户端。
16.Middle Man(中间转手人)
对象的基本特性之一就是—封装,对外部隐藏其北部细节,封装往往伴随着委托,但是过度运用delegation,可能会发现某个class接口有一般的函数都委托给其他的class,这就是过度运用delegation。这时候应该使用Remove Middle Man(160,移除中间人),有时候也可以运用Replace Delegation with Inheritance(355,以继承取代委托),对于这条准则,如果没有使用受托函数的所有函数(不是部分函数),那么就不该使用这个方法。
17.Inappropriate Intimacy(狎昵关系)
有时候你会看到两个class过于亲密,花费太多的时间去探究彼此的private成分。过分狎昵的classes必须拆散,可以使用move method 和move field帮他们划清界限。有时候也可以运用Change Bidirectional Association to Unidirectional(200,将双向关联改为单向关联)
继承往往照成过度的亲密,因为subclass对super class的了解总是超过superclass的主观愿望。这时候你可以使用Replace Inheritance with Delegation(352,以委托取代继承关系)
18. Alternative Classes with Different Interfaces(异曲同工的类)
做相同事情的方法有不同的函数signature,一致把它们往类层次上移,直至协议一致。
19. Incomplete Library Class(不完善的程序类库)
要建立一个好的类库非常困难。我们大量的程序工作都基于类库实现。然而,如此广泛而又相异的目标对库构建者提出了苛刻的要求。库构建者也不是万能的。有时候我们会发现库类无法实现我们需要的功能。而直接对库类的修改有非常困难。这时候就需要用各种手段进行Refactoring.
可以运用Introduce Foreign Method(162,引入外加函数)。当然如果一个server class建立了大量外加函数,就不应该使用本项重构,而应该使用Introduce Local Extension(164,引入本地扩张),建立一个新class,使它包含这些额外函数,让这个扩展成为Source class的subclass或wrapper(外覆类)。
20.Data Class(纯稚的数据类)
Data Class值:他们拥有一些值域(fields),以及用于访问(读写)这些值域的函数,除此之外没有其他东西。对于这些class,如果拥有public值域,请运用Encapsulate Field(206,封装值域),将他申明为private,并提供相应的访问函数。对于public类型的数据,其他对象有可能访问甚至修改这项数据,而拥有该数据的对象却毫无察觉。这就将数据和行为分开了。
如果这些classes内含容器类的值域,应该检查他们是否进行了恰当的封装。如果没有,就运用Encapsulate Collection(208,封装群集),让这个函数返回该群集的一个只读映件,宁在这个class中提供添加和删除群集元素的函数。
21. Refused Bequest
超类传下来很多行为和状态,而子类只是用了其中的很小一部分。这通常意味着你的类层次有问题。
22. Comments
如果有一段代码有长长的注释,那么通常这个代码是糟糕的,Comments可以带我们找到各种坏味道。
如果你不知道该怎么做,这才是注释的良好时机。除了用来标记将来的打算之外,注释还可以用来标记你并无十足把握的区域。你可以在注释里写下自己[为什么做某某事]。这类信息可以帮助你将来的修改者,尤其是那些健忘的人。
相关推荐
《一位可重构三值光学处理器的设计和实现》这篇文章主要探讨了一种新型的可重构三值光学处理器(Reconfigurable Ternary Optical Processor, RTOP)的设计与实现方法。该处理器基于三值逻辑系统,能够在光学层面进行...
【双旋光器结构的可重构三值光学处理器】是一种创新的光学计算技术,主要应用于三值光计算机中,旨在解决传统处理器在进行逻辑运算时数据位与像素位数量不匹配的问题。该技术由宋凯、金翊、欧阳山和王宏健等人提出,...
【标题】:“my_upload+第二次重构三个java文件”是一个关于Java文件上传的项目,其中包含了作者对Apache上传包的自定义实现和优化。这个项目可能是为了配合作者在博客上发表的系列文章“java之文件上传”,以帮助...
文中论述了三值光学处理器的重构原理、重构结构和重构操作,给出了三值光学运算器和运算基元的典型...最后描述了一位运算基元的重构实验,实验结果表明本文论述的可重构三值光学处理器原理正确,重构器件和重构指令有效.
本教程将深入探讨如何使用MATLAB进行云点的三维重构和建模。 首先,理解云点数据的处理至关重要。云点数据往往具有噪声,需要进行预处理,如滤波、去噪、平滑等操作,以便提取出有用的信息。MATLAB提供了多种滤波器...
一位可重构三值光学处理器的设计和实现,王宏健,金翊,本文对可重构三值光学处理器的原理和基本结构进行了详细的实验研究,证明了这种处理器的可重构性和重构电路的有效性。本次研究中
本实验的目的是从两幅图像中重构三维对象的结构信息。该实验可以分为四个步骤:①获取图像的特征点坐标;②计算视图之间的R、T位移;③根据深度约束确定R、T位移;④计算三维对象的结构信息。 二、实验步骤 1. ...
### Matlab将二维图像三维重构 #### 知识点解析 在本知识点中,我们将探讨如何使用Matlab将一张二维图像转换为三维模型的过程。通过分析提供的代码片段,我们可以了解到实现这一转换的基本步骤。 #### 图像读取与...
实验结果表明,该算法可以将强度传输方程得到的相位误差从 21.40% 降低为 5.26%,重构三维物体与模拟真实物体的相关程度为显著相关。 神经网络在该算法中扮演着关键角色,它可以对初始相位进行优化,提高三维重构的...
总之,"MATLAB 三维点云重构Surface reconstruction from scattered points cloud"项目涵盖了从数据处理到模型构建的整个流程,通过学习和实践,用户能够掌握如何利用MATLAB来处理和重构三维点云,从而在相关领域...
由于三值光学处理器在重构时可能需要较长的时间,所以优化重构命令字和电路设计以减少重构延迟是一个重要的研究方向。金翊等人在2010年提出的新重构电路设计,旨在解决重构命令字位数过多导致的重构用时过长的问题。...
三维重构 可以检测有效的系统缺陷,进行缺陷的定位,缺陷体积的测量等,如何进行三维重构(3D reconstuction)的输入是各种三维以下的数据,比如纯二维的RGB图像(序列)、带有深度信息的RGBD数据等,出来的是三维...
2. **特征检测与匹配**:在多个视角的二维图像中检测关键点(如SIFT、SURF、ORB等),并进行匹配,这是重构三维模型的基础。特征匹配有助于确定视图之间的对应关系,为三角测量提供条件。 3. **三维重建基础**:...