I amQiana , WELCOME.

NO TRY , NO HIGH

Code Smell In JavaScript

之前看了马大叔的《重构》一书,第三章就是对Java code smell的总结。最近项目更多在用JavaScript,查询资料以及自己的些许经验总结下 JS 的 code smell。


  • code smell 是什么?
    Google关键词code smell,第一个就是维基百科的解释,关键部分如下:
    Code smell, also known as bad smell, in computer programming code, refers to any symptom in the source code of a program that possibly indicates a deeper problem.
    
    同样也少不了马大叔有名的博客,截取关键部分如下:
    A code smell is a surface indication that usually corresponds to a deeper problem in the system. 
    
    简单来说,code smell就是代码的坏味道,它是提示代码中某个地方存在错误的一个暗示,我们可以通过这个坏味道在代码中找到问题。常常标志代码应该被refactored或者全部的设计都应该被reviewed。
    需要注意的是,code smell只是一种“暗示”,并非一种“确定”。code smell更多是“直觉的,本能的”。

  • 《重构》中的 code smell
    要将书中第三章总结下一一罗列了。

    1.Duplacated Code(重复代码):顾名思义,在一个以上地方存在相同或相似代码,如果可以将其合二为一,代码会变得更好。这几乎是最常见的异味,也是Refactoring的主要目标之一。
    
    2.Long Method(过长函数):程序越长越难以理解。而小的函数拥有更好的解释能力,共享能力以及选择能力。小函数易理解的关键就是起一个好名字,让别人不必看具体实现就能知道这个函数的功能是什么。
    
    3.Large Class(过大的类):遵守单一职责原则,一个类最好只干一件事情。如果想利用单个类干太多事情,其内就会出现太多实例变量。就会出现重复代码了。
    
    4.Long Parameter List(过长参数列):过长参数难以理解,并且可能会造成前后调用不一致的问题。
    
    5.Divergent Change(发散式变化):即一个类受多种变化影响。针对某一外界变化的所有相应修改,都只应该发生在单一类中,而这个新类中所有内容都应该反映此变化。
    
    6.Shotgun Surgery(霰弹式修改):即一种变化会引发多个类做修改。最理想的状态是“外界变化”和“需要修改的类”能够达到一一对应。
    
    7.Feature Envy(依恋情节):函数对于某个类的兴趣高于对自己类的兴趣。一个类的方法频繁的使用get方法存取其他类的状态进行计算,那么就需要考虑把行为移到涉及状态数目最多的那个类。
    
    8.Data Clumps(数据泥团):某些数据通常像孩子一样成群玩耍:一起出现在很多类的成员变量中,一起出现在许多方法的参数中……,这些数据或许应该自己独立形成对象。
    
    9.Primitive Obsession(基本类型偏执):面向对象的新手通常习惯使用几个原始类型的数据来表示一个概念。譬如对于范围,他们会使用两个数字。对于Money,他们会用一个浮点数来表示。因为你没 有使用对象来表达问题中存在的概念,这使得代码变的难以理解,解决问题的难度大大增加。好的习惯是扩充语言所能提供原始类型,用小对象来表示范围、金额、 转化率、邮政编码等等。
    
    10.Switch Statements(switch 惊悚现身):OO的一个最明显特征就是:少用switch(或者case)。一看到switch,就可以考虑用多态来替代。
    
    11.Parallel Inheritance Hierarchies(平行继承体系):是shotgun surgery 的特殊情况。当你为某个类添加一个子类,就必须为另一个类相应添加一个子类时。
    
    12.Lazy Class(冗余类):如果一个类的存在不值其身价,它就应该消失。
    
    13.Specualtive Generality(夸夸其谈未来性):一个类实现了从未用到的功能和通用性。通常这样的类或方法唯一的用户是test case。不要犹豫,删除它。
    
    14.Temporary Field(令人迷惑的暂时字段):一个对象的属性可能只在某些情况下才有意义。这样的代码将难以理解。因为你通常认为对象在所有时候都需要它的所有变量。可以专门建立一个对象来持有这样的孤儿属性,把只和他相关的行为移到该类。也可以在“变量不合法”的情况下创建Null对象,从而避免写判断。
    
    15.Message Chains(过度耦合的消息链):消息链发生于当一个客户向一个对象要求另一个对象,然后客户又向这另一对象要求另一个对象,再向这另一个对象要求另一个对象,如此如此。这时,你需要隐藏分派。
    
    16.Middle Man(中间人):对象的基本特性之一就是封装,而你经常会通过分派去实现封装。但是这一步不能走得太远,如果你发现一个类接口的一大半方法都在做分派,你可能需要移去这个中间人。
    
    17.Inappropriate Intimacy(狎昵关系):某些类相互之间太亲密,它们花费了太多的时间去砖研别人的私有部分。
    
    18.Alternative Classes with Different Interfaces(异曲同工的类):做相同事情的方法有不同的函数signature,一致把它们往类层次上移,直至协议一致。
    
    19.Incomplete Library Class(不完美的库类):要建立一个好的类库非常困难。我们大量的程序工作都基于类库实现。然而,如此广泛而又相异的目标对库构建者提出了苛刻的要求。库构建者也不是万能的。有时 候我们会发现库类无法实现我们需要的功能。而直接对库类的修改有非常困难。这时候就需要用各种手段进行Refactoring。
    
    20.Data Class(纯稚的数据类):对象包括状态和行为。如果一个类只有状态没有行为,那么肯定是不对劲滴。
    
    21.Refused Bequest(被拒绝的遗赠):超类传下来很多行为和状态,而子类只是用了其中的很小一部分。这通常意味着你的类层次有问题。
    
    22.Comments(过多的注释):经常觉得要写很多注释表示你的代码难以理解。
    

  • Some JavaScript Code Smell
    以下只是个人总结,欢迎补充以及更正。

    1.Duplacated Code(重复代码):原因在于Copy And Paste。

    2.convoluted Code(复杂代码):Too Many Statements;Too Much Depth;Too Much Complexity;

    3.Switch Statements

    4.Magic String/Number