让维护者浪费时间看显而易见的注释。
这部分的原则是维护者看完注释后觉得“代码比注释容易读多了”,目的就是误导读代码的人。维护者在看代码时,上眼一看代码很清晰,但又一看竟然还有注释。
此时读代码的人心里肯定是要嘀咕下:看来这代码没我想的这么简单。
然后我们的注释要写的长一些,最后是要阅读者看不懂,改的时候犹豫不决。 如果有余力的话可以在注释中教维护者怎么编程,这种一般杀伤力要比上面写的会高一些,程序员最反感的可能就是你要教他怎么编程了,尤其是教他这么简单的编程,杀伤力加倍。
下面看个例子:
public class Program{ static void Main(string[] args) { /* This is a for loop that prints the * words "I Rule!" to the console screen * 1 million times, each on its own line. It * accomplishes this by starting at 0 and * incrementing by 1. If the value of the * counter equals 1 million the for loop * stops executing.*/ for (int i = 0; i < 1000000; i++) { Console.WriteLine("I Rule!"); } }}
废弃代码注释
字面意思已经很清楚了,正常情况下代码中不用的部分我们一般会注释掉或者直接删除掉,即使这段代码将来会使用到也不影响,可以从版本控制工具中再找回来。
针对性的做法就是给删掉的代码加个长长的注释,写明这段代码为什么会被注释起来,也向维护者传达了一个信息,即这段代码不是被”废弃”的,而是”临时”先不用。
这样做的杀伤点就在,如果只注释了代码没加注释说明,根据实际经验大家多数会直接略过被注释的代码,而给代码加了注释后看代码的人可能就要看看这个注释了,不然会漏掉什么关键信息,毕竟代码不是他写的。
样板代码:
public class Program{ static void Main(string[] args) { /* This block of code is no longer needed * because we found out that Y2K was a hoax * and our systems did not roll over to 1/1/1900 */ //DateTime today = DateTime.Today; //if (today == new DateTime(1900, 1, 1)) //{ // today = today.AddYears(100); // string message = "The date has been fixed for Y2K."; // Console.WriteLine(message); //} }} 二、这个地方将来会修改
这种注释就是我们经常提到的“TODO”型注释。正常情况下TODO注释并非一无是处,比如在初始化项目的时候TODO注释还是非常有用的,到项目release 时一般是建议去掉的,如果必须要留着一般需要写明在具体什么日期会处理掉。一般是不推荐TODO型注释长期存在于项目的代码中,正常的处理逻辑一般是遵循有Bug尽快Fix,无Bug则去掉注释。
通过上面的描述相信大家已经知道这块具体要怎么应对了。个人建议是对于有待修改的多写点TODO注释,且不注明更改的原因以及计划更改的时间,这样后面的维护人员在看的时候可能连这块到底是不是已经改过了都搞不清楚,所以杀伤效果也是有一些的。
样板代码:
public class Program{ static void Main(string[] args) { //TODO: I need to fix this someday – 07/24/1995 Bob /* I know this error message is hard coded and * I am relying on a Contains function, but * someday I will make this code print a * meaningful error message and exit gracefully. * I just don’t have the time right now. */ string message = "An error has occurred"; if(message.Contains("error")) { throw new Exception(message); } }} 三、错误注释信息
这部分的意思是造成代码和注释的不匹配,也就是注释的信息不正确。 我们要做的就是改完代码后不改注释就行了,此种方式比较省事,额外工作一点也不用多做,但是稍微有些代价,需要注意的是最好是在此类注释中加个特殊的标记,防止自己后续看的时候把自己也绕进去。
样板实例这块就不用加了吧,场景太多了,大家在自己的一亩三分地上耕作时临场发挥即可。 四、讲故事
简单说来就是写明这段代码为什么要这样写,当然肯定不是单纯的原因。除了原因一般建议在注释中写上当时的情况,比如某年某月和某人在某地讨论了这个问题,某人说这个问题应该怎样处理,你说这个问题不该这样处理应该那样处理,后来某某人又加入了讨论,某某人对俩的讨论做了某某的评价,最后决定要用现在的代码去实现这块的功能。
总之,原则就是把事情的细节描述清楚,越细越好。有些同学可能会建议将当天的天气情况也写上,还有讨论中那个气死人的S*名字也要带上,我个人认为天气可以酌情添加,但写上S*名字是不太鼓励的,毕竟同事一场,要相互爱护的,大家按照自己公司的实际情况来选择具体的处理方式吧。
样板代码:
public class Program{ static void Main(string[] args) { /* I discussed with Jim from Sales over coffee * at the Starbucks on main street one day and he * told me that Sales Reps receive commission * based upon the following structure. * Friday: 25% * Wednesday: 15% * All Other Days: 5% * Did I mention that I ordered the Caramel Latte with * a double shot of Espresso? */ double price = 5.00; double commissionRate; double commission; if (DateTime.Today.DayOfWeek == DayOfWeek.Friday) { commissionRate = .25; } else if (DateTime.Today.DayOfWeek == DayOfWeek.Wednesday) { commissionRate = .15; } else { commissionRate = .05; } commission = price * commissionRate; }} 五、不要写原因
按照注释的规范,注释时不但要解释程序的表述的意思,更重要的是写明为什么写,即代码这么写的原因是什么。
这样应对之策也已经显而易见了,对于复杂程序,比如一些特殊的边界条件判断,只写下程序的字面意思,具体边界值判断为什么要这样写,为什么是这个值可以忽略掉,让维护的人尽情去猜吧。 六、琐碎
在这需要注明的是大部分程序注释一般是用不到这种情况的,一般是推荐放在一些复杂算法的解释上,越是复杂的算法越是推荐,原则就是把这部分应该写到文档中的内容写到代码中。 一定要把算法的所有的详细设计都写上,注释内容分段落,段落之间要分级,每个段落建议加上编号,这样就基本可以保证代码的注释和文档的内容保持一致。后续的维护看到这样的注释的时候基本可以保证头大一圈,如果此类注释存在多处的话效果更佳。
鉴于样板示例中注释篇幅太长就不加示例了。 七、单位问题
单位这部分和具体的业务场景相关,比如时间相关的一般会有毫秒、秒、分钟、小时、天、月、年等,涉及尺寸的场景如像素、英寸等,涉及文件大小的场景如字节、KB、MB、GB等。
这一类的代码中我们的原则是不对单位进行注释,只管使用,如果可以在代码中各种单位混用,那自然是更加优秀。
比如在关于文件处理的场景中,KB、MB、GB多个单位混合使用,这样后来的维护人员要想搞懂这部分代码中单位的真正含义就要下一番功夫了。
按照我们的正常逻辑,后面的人要想改这部分的代码的逻辑首先要先弄懂各个数据的单位,搞清楚之前肯定是不敢随意修改的,一般这种情况只有一种解决办法那就是一遍遍的调试、测试程序来推算各个数据实际的单位,花费的时间自然是相当的多。 八、恐吓
这一招可以说是杀手锏级别的注释,可以在程序中加一部分可有可无的代码,而且是很明显可有可无的那种,然后给这段程序加个注释,注释中写明“千万不要注释掉或者删除这段代码,否则程序会出现异常!!!”,需要注意的是不要解释会出现什么样的异常。
这样维护人员在看到这段代码的时候肯定首先会联想到自己以前看过的一些文章,并坚信这段“废话代码”肯定是不能删除的。代码中如果存在多处这种注释的话效果更佳。