加入收藏 | 设为首页 | 会员中心 | 我要投稿 开发网_新乡站长网 (https://www.0373zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

代码中的注释

发布时间:2022-12-17 12:50:32 所属栏目:Linux 来源:
导读:  别给糟糕的代码加注释 -- 重新写吧。 Brian W.Kernighan 与 P.J.Plaugher

  有一个关于程序员的段子,说所有的程序员都讨厌两件事,一是别人不写注释,二是自己写注释。关于写注释,一直有人争论不休,有的
  别给糟糕的代码加注释 -- 重新写吧。 Brian W.Kernighan 与 P.J.Plaugher
 
  有一个关于程序员的段子,说所有的程序员都讨厌两件事,一是别人不写注释,二是自己写注释。关于写注释,一直有人争论不休,有的人认为写代码必须要写注释,而又的人认为代码就是注释,何必再写一遍?那么今天我们就聊一聊代码中的注释。
 
  写注释
 
  为什么要写注释?注释就是弥补我们在写代码的过程中,代码表达的含义不清或者容易造成混乱的时候才加上的,或者是对于代码可能存在的风险加以说明,或者警示函数调用者使用规范等。
 
  不写注释
 
  什么情况下不写注释?先举一个简单的例子:
 
  enum Week{
       Mon = 1, Tues, Wed, Thurs, Fri, Sat, Sun
  };
  switch(w))
  {
      // case Monday
      case Mon:
          break;
      // default case
      default:
          break;
  }
  很明显这种就是多余的注释,这种注释完全就是多余的,除了增加阅读人的难度,毫无任何意义。再比如:
 
  // Check to see if the employee is eligible for full benefits
  if ((employee.flags & HOURLY_FLAG) && (employee.age > 65) ){
  }
  这段代码看起来貌似没什么问题,注释写的也算明确,检查员工是否有资格获得全额福利,检查条件是标志flags为HOURLY_FLAG并且年龄大于 65 岁。但是实际上,上面的注释是完全没有必要写的,我们看下面修改后的代码:
 
  if (employee.isEligibleForFullBenefits()){
  }
  我们直接把这个判断条件封装成一个方法,这个方法名实际上就“等同于”注释了,所以说上面的注释完全可以不用加。
 
  好注释
 
  什么是好注释?有些地方是一定要写注释的,这些地方的注释一定要尽可能的详细,并且无歧义。比如在合作开发的时候,写的一些 API ,这些 API 的函数的参数、返回值、以及函数的作用。例如 C# 中 System.Math.Max 函数:
 
  ///
 
  /// Returns the larger of two 32-bit signed integers.
  ///
 
  /// The first of two 32-bit signed integers to compare.
  /// The second of two 32-bit signed integers to compare.
  /// Parameter val1 or val2, whichever is larger.
  public static int Max(int val1, int val2)
  这些注释是非常好的注释,并且非常的详细。如果你写的代码将来也是要封装成 API 的,建议也要写的非常规范,以方便调用者使用。有返回值的,一定要详细解释好返回值的含义,比如:
 
  ///
 
  /// Indicates whether the specified Unicode character is categorized as a decimal digit.
  ///
 
  /// The Unicode character to evaluate.
  /// true if c is a decimal digit; otherwise, false.
  public static bool IsDigit(Char c)
  判断一个字节是否是十进制数字。我们注意看返回值的注释,详细写道,true 表示是一个十进制数字,否则返回 false。工作中我见到过很多开发者写的类似返回 bool 值的方法的注释,都类似“是否是一个十进制数字”这样,这样就不是一个好注释,那么到底是 true 代表“是”还是 false 代表 “是” 呢?是不是容易混淆?
 
  还有,再比如有些方法内的函数调用必须要有严格的调用顺序linux注释,这时候注释也是一定要加的,比如:
 
  void Foo(){
      F1();
      F2();
      // The function FN must be called in the last step
      FN();
  }
  因为在后续功能扩展的时候,很有可能在其内部添加一些其他的函数调用,并且这个功能并不一定是当初开发这个函数的人继续扩展添加,如果调用顺序发生错误,很可能会出现很多麻烦。
 
  坏注释
 
  有一段非常经典的代码,求平方根倒数:
 
  float Q_rsqrt( float number ){
      long i;
      float x2, y;
      const float threehalfs = 1.5F;
  
      x2 = number * 0.5F;
      y  = number;
      i  = * ( long * ) &y;                       // evil floating point bit level hacking
      i  = 0x5f3759df - ( i >> 1 );               // what the fuck?
      y  = * ( float * ) &i;
      y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
  //      y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed
  #ifndef Q3_VM
  #ifdef __linux__
  assert( !isnan(y) ); // bk010122 - FPE?
  #endif
  #endif
      return y;
  }
  这段代码的经典之处除了以非常高效的速度算出来平方根的倒数,还因为其中的一句 wtf 的注释,很明显这个 0x5f3759df Magic Number 没人知道是干什么的。(有人通过数学公式推导出了这个魔法数字的由来,链接)。很明显这里的注释明显不足,至少这里要注释上推导过程或者是利用什么数学公式推算的,因为我们并不能保证所有的程序员都有这样的数学功底。
 
  还有一些注释,就是有些开发者喜欢在注释里添加姓名和日期,例如:
 
  // [20180909 Elynn] Bala Bala...
  加这种注释一般都是觉得方便以后他人遇到问题知道该和谁讨论,但是事实上,注释放了一年又一年,下一个人修改代码的时候很可能没有加日期和姓名,将来有问题的时候找到第一个加注释的人,他也看不懂为什么改成了这样。为什么没必要加这类注释?因为我们都会有代码版本控制的软件,这是最直接最方便找到修改者的方法,而不是看上面这段不一定准确的注释来找这段代码的开发者。
 
  说到这里,还要顺便说下一种坏注释,那就是错误的注释。误导性的注释比没注释更可怕。当我们修改一个函数的时候,如果函数的最初的注释和最新的实现不匹配,一定记得要修改一下注释,哪怕是删掉注释,也不要留着误导性的注释。
 
  总的来说,有些注释是必须要有的,而且于己于他都是有利的。不过函数内部的一些注释,最好的注释就是想办法不去写注释,让自己的代码成为最好的注释,一些函数的命名,最好让看代码的人不必进到函数实体内看具体实现就知道大概在干什么,这是最好的;变量命名一定不要有歧义,哪怕长一点,尽量不要用缩写,保证代码的可读性,这样你就可以和别人吹牛了:我写的代码还用加注释?
 
  不过说到底,注释就是辅助其他人来阅读代码用的,辅助提升代码的可读性。提高代码的可读性,是一条漫长的路,初学者可以看一下一些 IT 公司的代码规范,平时也要严格要求自己,让自己的代码更加整洁清晰。
 

(编辑:开发网_新乡站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!