魔数(magic number)

魔数是编程中我们需要尽量避免使用的,但是很多人不去管也不清楚。
 
百度百科中解释如下:
        很多类型的文件,其起始的几个字节的内容是固定的(或是有意填充,或是本就如此)。根据这几个字节的内容就可以确定文件类型,因此这几个字节的内容被称为魔数 (magic number)。此外在一些程序代码中,程序员常常将在代码中出现但没有解释的数字常量或字符串称为魔数 (magic number)或魔字符串。
 
我今天要说的魔数是后一种情况:
        所谓魔数和魔字符串就是指在代码中出现但没有解释的数字常量或字符串。如果在某个程序中你使用了魔数,那么在几个月(或几年)后你将很可能不知道它的含义是什么。
 
维基百科中解释如下:
程序设计中所谓的魔数是指直接写在代码里的具体值(如"10","123"等以数字直接写出的值)。虽然程序作者写的时候自己能够了解数字的意义,但是对其它 程序员而言,甚至制作者本人经过一段时间后,会难以了解这个数值的用途,只能苦笑讽刺“这个数值的意义虽然不懂,不过至少能让程序运行,真是个魔术般的数字”而得名。
因为下述理由,一般认为代码中不应该包含魔数:
  • 数值的意义难以理解。
  • 数值需要变动时,可能要改不止一个地方。
 
 
 
下面是一个网友的理解: http://yunli.blog.51cto.com/831344/265730 
        魔数不推荐用的原因有两个,一个是难以理解,一个是难以全部修改。
        对于第一个情况,虽然可以用注释来解决,但是如果真是采用加注释的方式,那为什么不将其定义成一个常量呢?要知道查看注释的效率肯定没有直接看代码来得快和方便,也不存在不同步的问题(代码与注释有可能不同步)。
        对于第二种情况,当一个项目较大时,魔数的存在会使得程序维护非常、非常困难。
由此看来,这里的“魔”不应理解成象“魔法(magic)”那样神奇,而应理解为象“魔鬼(monster)”那样可怕。
 
 
 
下面是举例:

譬如一个很简单的根据职位计算薪水的方法

 
在这个方法里面,"Programmer","Tester"和"Analyst"是所谓的魔字符串(Magic String),而500, 700,800和1000就是所谓的魔数(Magic Number)了。 咋一看,代码这样写也没有什么问题,但是,仔细思考一下就会发现,如果这种随手捻来的字符串和数字散布于程序当中,随处可见的话,是会有很多弊病的。我们先来分析三个魔字符串。虽然三个Magic String的意义很明显,并不影响到代码的可读性,但是这样却增加了出错的概率,并且忽略了具体的语义环境。我们很容易就会想到,像"Programmer"这个单词散布在多个方法中,一个大小写的笔误就会产生bug。同时,"Programmer"在计算薪水的方法中代表着职位,但是在统计公司订阅的杂志的方法中,也许就要代表一本杂志的名称了。然而这种语义环境是无法通过一个单纯的"Programmer"就能体现出来的。

Magic Number

而Magic Number的问题就更大了,首先是影响了代码的可读性,谁会知道500和800是薪水基数,700是补贴呢?而且更糟糕的是,如果薪水基数发生改变的时候,那么就得找人把这些500,700,800的数字找出来一个一个地update,那可是一件够郁闷的事情了。
如果我们拥有一个常量定义的interface,代码就会变漂亮起来了:
 
 
 
从以上的分析,在一个Project里面,避免使用魔数(Magic Number)和魔字符串(Magic String)是相当必要的。通过定义的常量去access特定的字符串和数字也已经是软件开发的standard。那么是不是所有的数字和字符串都应该定义成常量呢?或许有朋友会认为所有的数字和字符串都应该定义成常量,但是我觉得,每个字符串确实是应该定义成常量的,但是对于数字而言,如果数字本身的语义没有得到延伸,那么就不应该定义成常量。譬如数组的index就不应该定义成变量。 像这样的代码:
 
 
你一定会觉得这样的代码就是画蛇添足, 因为ONE就是1,它没有其他特别的含义,不像上面代码中的500和700。而且如果真的要这样定义的话,出现了有上百个元素的数组的时候,那么你就得定义上百个没有任何意义的常量了。是不是很FT呢?
在程序中除了0,1,2这几个有特殊用处的数字,其它的都要声明为常量。总之,任何策略的使用,还是一个度最重要。
 
 

<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">

posted @ 2018-03-02 17:09  刍荛采葑菲  阅读(1887)  评论(0编辑  收藏  举报