美文网首页
设计模式 - 编程规范

设计模式 - 编程规范

作者: Zeppelin421 | 来源:发表于2022-04-19 08:55 被阅读0次

    编程规范大部分都简单明了,在代码细节方面,能立竿见影地改善代码质量。持续低层次、小规模重构依赖的基本上都是编码规范,这也是改善代码可读性的有效手段。

    命名

    命名对于代码的可读性来说非常重要,甚至可以说起决定性作用的。对于影响范围比较大的命名,比如包名、接口、类名,一定要反复斟酌、推敲。

    • 命名多长最合适
      在足够表达其含义的情况下,命名是越短越好。
      对于一些默认的、大家都比较熟知的词(sec、str、num、doc)推荐用缩写。
      对于作用域比较小的变量可以使用相对短的命名,例如函数内的临时变量;
      对于类名这种作用域比较大的,推荐用更长的命名方式
      命名的一个原则就是以能准确达意为目标。对于编码者自己来说,总感觉用什么样的命名都可以达意,但对不熟悉代码的同事来说就不这么认为了。所以命名的时候一定要学会换位思考,假设自己不熟悉这块代码,从代码阅读者的角度去考量命名是否足够直观。

    • 利用上下文简化命名

    public class User {
        private String userName;
        private String userPassword;
        private String userAvatarUrl;
        //...
    }
    
    public void uploadUserAvatarImageToAliyun(String userAvatarImageUri);
    //利用上下文简化为:
    public void uploadUserAvatarImageToAliyun(String imageUri);
    
    • 命名要可读、可搜索
      “可读”指不要用一些特别生僻、难发音的英文单词来命名,例如:plateaux、eyrie。可以用一些易读的词,例如:inkstone。
      “可搜索”指用IDE编写代码时经常会用到“关键词联想”的方法来自动补全和搜索。因此在命名是最好能符合整个项目的命名习惯。比如:大家都用selectXXX,那就避免个人使用queryXXX;大家都用insertXXX,个人就不要使用addXXX

    • 如何命名接口和抽象类
      接口命名通常两种比较常见:一种加前缀“i”,比如 UserService implements IUserService,另一种不加前缀,比如 UserServiceImpl implements UserServiceImpl
      抽象类通常也有两种,一种加前缀“Abstract”,另一种不加
      对于接口和抽象类,选择那种命名方式都是可以的,只要项目里保持一致就行

    注释

    注释跟命名一样也很重要。很多人认为好的命名完全可以替代注释,如果需要注释,那说明命名不够好,这种观点有点太过极端。命名再好,毕竟有长度限制,不可能足够详尽,这时候注释就是一个很好的补充。

    • 注释该写什么
      注释的目的就是让代码更容易看懂。只要符合这个要求的内容,就可以写到注释里。注释的内容包括:做什么、为什么、怎么做。
    /**
     * (what) Bean factory to create beans. 
     * (why) The class likes Spring IOC framework, but is more lightweight. 
     * (how) Create objects from different sources sequentially:
     * user specified object > SPI > configuration > default object.
     */
    public class BeansFactory {
        // ...
    }
    

    很多人认为“做什么、怎么做”可以在代码中体现出来,所以不要写,其实不然:

    • 注释比代码承载的信息更多
      对于类来说,包含的信息比较多,一个简单的命名不够全面详尽,这个时候在注释中写明“做什么”就合情合理
    • 注释起到总结性作用、文档的作用
      在注释中,关于具体的代码实现思路,我们可以写一些总结性的说明、特殊情况的说明。这样能够让阅读代码的人通过注释就能大概了解代码的实现思路,阅读起来就会更加容易
    • 一些总结性注释能让代码结构更清晰
      对于逻辑比较复杂的代码或者比较长的函数,如果不好提炼、不好拆分成小的函数调用,可以借助总结性的注释来让代码结构更清晰、更有条理
    • 注释是不是越多越好
      注释本身有一定的维护成本,所以并非越多越好。类和函数一定要写注释,而且要写得尽可能全面、详细,而函数内部的注释要相对少一些,一般都是靠好的命名、提炼函数、解释性变量、总结性注释来提高代码的可读性

    代码风格

    在一个团队、项目中保持风格统一,让代码像同一个人写出来的,整齐划一,这才是最好的风格。这样能减少阅读干扰,提高代码的可读性。

    • 类、函数多大才合适
      函数代码行数不好超过一个显示屏的垂直高度(大约50行左右),因为超过一屏之后,在阅读代码的时候,为了串联前后的代码逻辑,可能需要频繁的上下滚动屏幕,阅读体验不好,还容易出错。
      对于类的代码行数的限制有个间接的判断标准:当一个类的代码读起来让你感觉头大;实现某个功能时不知道该用那个函数了;想用哪个函数翻半天找不到;只用一个小功能要引入整个类;此时就说明类的行数太多了。

    • 一行代码多长最合适
      Google Java Style Guide中,一行代码最长限制100字符。
      遵循一个原则:一行代码最长不能超过IDE显示的宽度。需要滚动鼠标才能查看一行的全部代码,显然不利于代码的阅读。

    • 善用空行分隔单元块
      对于比较长的函数,为了让逻辑更加清晰,可以使用空行来分隔各个代码块。在类内部,成员变量与函数之间、静态成员变量与普通成员变量之间、函数之间,甚至成员变量之间,都可以通过添加空行的方式,让不同模块的代码之间的界限更加明确

    • 四格缩进还是两格缩进
      不管是用两格缩进还是四格缩进,一定不要用tab键缩进。整个团队保持一致即可。推荐两格缩进,节省空间

    • 类中成员的排列顺序
      类中先写成员变量后写函数。成员变量之间或函数之间,先写静态成员变量或函数,后写普通变量或函数

    编程技巧

    • 把代码分割成更小的单元块
      大部分人阅读代码的习惯是先看整体再看细节。所以要有模块化和抽象思维,善于将大块的复杂逻辑提炼成类或函数,屏蔽掉细节,这样能极大地提高代码的可读性。

    • 避免函数参数过多
      函数包含的参数 >=5 时会影响到代码的可读性,使用起来也不方便。参数过多处理方法:考虑函数是否职责单一,能否通过拆分成多个函数的方式减少参数;将函数的参数封装成对象,如果函数是对外暴露的远程接口,将参数封装成对象还可以提高接口的兼容性。

    • 勿用函数参数来控制逻辑
      不要在函数中用布尔类型的标识参数来控制内部逻辑,true走A逻辑,false走B逻辑。这明显违背了单一职责原则和接口隔离原则。如果函数是private或者拆分后的两个函数经常同时被调用,可以酌情考虑保留标识参数。
      根据参数是否为null来控制逻辑的也应该将其拆分成多个函数。

    • 函数设计要职责单一
      函数的设计也需要满足单一职责原则,函数的粒度比较小,代码行数少,所以在应用单一职责时能多单一就多单一

    • 移除过深的嵌套层次
      代码嵌套最好不超过两层,过深的嵌套本身理解就比较费劲,而且嵌套过深很容易因为代码多次缩进导致语句超过一行的长度,影响代码的整洁和阅读

      • 去掉多余的 if else语句
      • 使用 continue、break、return提前退出嵌套
      • 调整执行顺序来减少嵌套
      • 将部分嵌套逻辑封装成函数调用,减少嵌套
    public List matchStrings(List strList,String substr) {
        List matchedStrings = new ArrayList<>();
        if (strList != null && substr != null) {
            for (String str : strList) {
                // 跟下面的if语句可以合并在一起 
                if (str != null) { 
                    if (str.contains(substr)) { 
                        matchedStrings.add(str); 
                    } 
                } 
            } 
        } 
        return matchedStrings;
    }
    
    • 学会使用解释性变量
    public double CalculateCircularArea(double radius) {
        return (3.1415) * radius * radius;
    }
    // 常量替代魔法数字
    public static final Double PI = 3.1415;
    public double CalculateCircularArea(double radius) {
        return PI * radius * radius;
    }
    
    if (date.after(SUMMER_START) && date.before(SUMMER_END)) { 
        // ...
    }
    // 引入解释性变量后逻辑更加清晰
    boolean isSummer = date.after(SUMMER_START)&&date.before(SUMMER_END);
    if (isSummer) { 
        // ...
    }
    

    相关文章

      网友评论

          本文标题:设计模式 - 编程规范

          本文链接:https://www.haomeiwen.com/subject/wthlyktx.html