代码规范建议

注意
本文最后更新于 2023-07-30,文中内容可能已过时。

命名规范

# 1. 属性/成员 命名

  • 静态常量属性 即使用 static final 修饰的属性, 属性名全部大写并添加javadoc的注释。 比如下面的例子

    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      
          /**
           * 消息的线程数量
           */
          public static final int MSG_THREAD_NUM = 8;
      
          /**
           * redis 连接池的 线程数量
           */
          public static final int REDIS_CONNECTION_POOL_SIZE = 4;
  • 私有的实例属性 采用 驼峰命名法。 并需要使用单行注释 简单说明下含义、

    • 经常出现的变量名可以不写注释。
    • Map Or MapSubMap 需要写明 keyvalue的含义。
    • 如果是关键字开头的命名,比如 do ,for 可用_ 下划线开头, 比如_forConsole, _doWorkTime 尽量不要使用这种关键字开头的命名 😄
  • 方法名采用 驼峰命名法, 并需要添加 javadoc 注释, 在必要的时候 也需要写明参数的含义。

  • 公有静态变量, 首字母大写。 私有的静态属性采用驼峰命名法。

# 2. 选取有意义的命名

  • 要选取有意义的名称。
    • 下面的名称是可取的 👍👍👍
      • PlayerInfo getPlayer(String roleId); // 1
      • PlayerInfo getPlayerByRoleId(String str); // 2
    • 下面的名称是 不可取的 🙅‍♂️🙅‍♂️🙅‍♂️
      • PlayerInfo getPlayer(String str); // 3
      • PlayerInfo getPlayerByString(String str); // 4
  • 上述示例中, 1和2 都是自解释的方法签名, 一看就知道该方法的作用是根据roleId获取一个玩家对象。
  • 3和4 则不是自解释的。 我们目前无法得知参数需要的是roleId 还是 roleName, 亦或是其他什么属性。
    • 这时候如果方法还没有注释, 我们就必须要打开源代码去确认方法的作用了。
  • 有意义的类名也比较重要。
    • ConfigManagerSessionManager 就是比较有意义的名称。 如果我们需要一个配置文件的数据,我们将会知道从ConfigManager中获取,而非SessionManager
    • 同样,如果我们需要给某个玩家发送消息,则我们知道SessionManager类里面应该有这样一个方法。
    • 如果你看不懂上述说明, 则你可能需要加强一下你的英语了。
      • Config - 配置; 配置文件; 布局;
      • Session - 会话; 会议; 会期;
      • 上述内容来自 网易有道词典
    • 相对来说, 如果把玩家会话相关的内容放到一个叫做BananaManager 的类里面, 看到的人可能就会非常困惑: 我们项目里面有香蕉吗? 为什么要管理香蕉? 而在使用的时候,也增加了记忆的负担。
  • 如果一个类里面的功能过于复杂, 起一个有意义的类名 可能就比较困难了。此时,较好的做法是根据逻辑或者其他规则划分类的内容 进行重构。
  • 还有一种做法是笔者特别讨厌的。。 即 复制代码的时候只修改内容,不修改名称。
    • 如果一个方法的内容和你的需求类似, 但不完全相同。 首选的处理方式是 以添加参数或者拆分方法的形式进行处理, 而非复制一份,然后稍微修改下。
    • 如果你非要复制一份进行修改, 也是可以的(非常勉强的情况下 才能视为 可以)。 当出现这种情况的时候,你一定要修改方法的名字。
    • 比如一个在类A里方法:List<PlayerInfo> findPlayers(String roleId); 你将它复制到了类B里面的时候,把检测roleId的地方换成了 roleName, 但是你却没有修改方法名。 当这种情况出现的时候, 别人在使用这些方法的时候就会出错, 他们同样也会很困惑。
    • 笔者有个同事简直更离谱,有时候方法名和方法内容会出现完全没有关系情况, 当笔者问他的时候,他会回答说『哦,我复制的』😶 😶 😶

# 3. 类似功能的方法命名

  • 看下面几个方法
    • void setFlag(int v, int index);
    • bool hasFlag(int v, int flag);
    • void clearFlag(int v, int index);
  • 不知道读者有没有发现, hasFlag方法的第二个参数是一个flag ,而不是一个index。
  • 这就存在一些问题了, 在使用hasFlag的时候需要把index先转换成flag, 而其他两个方法则不需要。
  • 笔者不建议写这样的代码。 最好把hasFlag的第二个参数也做成index。 这样可以减少误会。

其他要点

# 1.注释

规则

  • 注释部分是一定要写的, 但是不必写的特别详细。
  • 一般来说, 除非方法名是自解释的,否则一定要加上注释。 参数名若有歧义也需要加上注释。
  • 类的实例属性也需要加上注释。 使用 // 的单行注释即可
  • 类,类的实例方法, 静态方法,静态属性尽量加上注释, 注释采用 javadoc的风格。 若名称带有歧义,则一定 要加上注释。
  • 方法内的逻辑若十分复杂, 流程较长也需要添加注释。
  • 数据库里的数据表字段, 也需要适当的添加注释。
  • 对于部分int类型字段, 可能需要添加释义。 比如性别: 0未知,1女,2男等
  • 对于部分Map 类型的字段, 需要指定Key以及Value的含义。 比如玩家会话map, key: 玩家id, value: 会话信息

好处

这里用小A代指一个写了注释的同事。

  • 在同事B接手小A的工作的时候,同事B不需要和小A有太多交流就可以完成他的工作。 这样节省了小A和同事B两人的时间。 ⏱️⏱️⏱️

  • 在同事B需要调用小A写的接口的时候,也不需要打扰到小A。 这同样会节省较多时间。

  • 节省了时间意味着什么呢?

    • 你完全可以不用加班, 或者只需要少量加班。
    • 当你在上班的时候空闲了下来, 你可以去学习一些新技术, 去聊天群吹水, 甚至看看小说漫画。
    • 项目周期可能会缩短一些, 也可能会提前拿到一些奖金。
  • 注释可以帮助小A 更好的回忆几个月之前写的逻辑。

  • 在小A因为某些原因辞职的时候,甚至不需要写交接文档,辞职需要的时间也大大的缩减了。 虽然可能会因为交接时间变少,而在离职前做更多的工作😂 😂

其他

  • 关于上方的注释和 右方的注释。 笔者偏好于上方的注释, 因为右边的注释在看的时候可能不太方便。
  • 如果读者更想看代码, 而非注释, 那么注释应该写在右边。
  • 按照笔者的分块想法, 注释和代码块往往是一起的。有时候浏览代码,看了注释就可以跳过代码块的部分了。 如果代码有bug 或者注释写的问题,这种情况是不太好。🤔 🤔

# 2.代码块

  • 代码分块, 不要全部的逻辑写在一起, 不要写成一大坨的样子。
    • 基本的分块逻辑是按照类别和功能划分, 比如声明语句放在一些, 一个小功能的内容放在一起。 中间使用一行空行分割。 声明语句块之外的其他代码块 应该适当的添加一些单行注释,表明下面的代码是用来做什么的。
    • 如果可以的话, 分成若干个小方法也可以。
    • 这样做的好处是 便于观看,修改。 (我想,你也不愿意修了1个bug,又添加了3个把。。
  • if,else, while, for 等关键字,都需要添加 {}用于区分。 即使关键字后只有一条语句也需要添加。
    • 这样做会使代码风格统一, 且不会出现不必要的麻烦或者问题。
    • 使用Idea的时候,快捷键CMD/CTRL+SHIFT+ENTER 会自动追加 {} 也不需要手动添加。

# 3. 杂项

  • Tab 设置成 4个空格 , 部分IDE默认情况应该是这个,不需要修改。
  • 2个空格4个空格相比,笔者更偏好4个空格/tab毕竟手打4个空格是有点麻烦啊😆 😆
  • 笔者觉得8个空格是很难接受的一件事, 因为实在是太长了。
  • 但是每个项目组的要求可能不一样,如果不是规则的制定者, 那么建议读者遵循规则即可。

# 4. 空行

  • 笔者的代码风格是比较随意的那种, 即笔者之前是不怎么在乎空行问题的。 换句话说就是, 笔者会在想空行的时候空行, 空一行,两行都有可能。
    • 后来在一家公司工作的时候, 同事提醒我说这种格式不规范。 应该统一规范, 什么地方空行,什么地方不空行。
    • 因为提醒笔者的是笔者的头头,所以没办法只好遵从了 😅 😅 😅
    • 后来笔者发现, 注意了空行之后确实会显得代码比较规范。
  • 笔者现在建议, 适当空行即可。

# 5. 代码可读性和强规范

  • 笔者是比较排斥强规范的。
    • 首先, 需要适应这个规范
    • 其次, 如果换了工作, 这个规范可能就需要重新适应
    • 再者, 这个规范并不会对逻辑产生什么太多影响。
    • 还是那句话,如果做小弟,就只能遵守规范。。。
  • 笔者写代码除了注意组织结构之外, 还会考虑阅读性。 笔者会为了方便阅读而刻意做一些行为。
    • 比如, 在声明方法的时候, 如果参数所占的字符过多, 笔者会换行。 参数类型名过长,或者参数个数过多的情况。
    • 在进行方法调用的时候, 如果参数个数较多且每个参数的表达式较长, 或者大部分的参数表达式过长, 那么笔者会使用换行处理, 每行一个参数。
    • 在进行stream/linq方法调用的时候, 如果语句过长, 笔者偏好于每次方法调用分开写。 即一行写一个调用。 笔者认为这样更清晰。
  • 笔者会刻意让一行的代码不要过长。
  • 笔者的代码风格是比较松散的风格。
0%