---
title: "PHP里的神奇数字"
url: https://www.exakat.io/php%e9%87%8c%e7%9a%84%e7%a5%9e%e5%a5%87%e6%95%b0%e5%ad%97/
date: 2015-07-06
modified: 2015-07-07
author: "David 戴炜"
description: "[caption id=\"attachment_572\" align=\"alignleft\" width=\"320\"] 神奇数字,它应该被替换为常量[/caption] 神奇数字式一个没有解释其意义的字面值，而且它出现在代码里多次。这样的值将会显示没有任何意图，它应该被替换为常量:常量的名字将会使代码更可读，在未来更加容易更新。 ç 让我们来看看一些代码，并且把它的神奇数字分离出来来试图理解它的情况。这是一个真实的数字的例子，来源于最近发布的一个关于120 kLOC的开源应用。       Value Number of occurrences 0.0 1 1.0E-08 1 0.05 1 0.33 1 1.0 10 1.7 4 2.0 1..."
categories:
  - "Company"
image: https://www.exakat.io/wp-content/uploads/2015/03/number-5.320.jpg
word_count: 126
---

# PHP里的神奇数字

[![Magic numbers should be turned into constants](http://178.62.231.40/wp-content/uploads/2015/03/number-5.320.jpg)](http://178.62.231.40/wp-content/uploads/2015/03/number-5.320.jpg)神奇数字,它应该被替换为常量

神奇数字式一个没有解释其意义的字面值，而且它出现在代码里多次。这样的值将会显示没有任何意图，它应该被替换为常量:常量的名字将会使代码更可读，在未来更加容易更新。

## ç

让我们来看看一些代码，并且把它的神奇数字分离出来来试图理解它的情况。这是一个真实的数字的例子，来源于最近发布的一个关于120 kLOC的开源应用。

 

 

 

| Value | Number of occurrences |
| ----- | --------------------- |
| 0.0 | 1 |
| 1.0E-08 | 1 |
| 0.05 | 1 |
| 0.33 | 1 |
| 1.0 | 10 |
| 1.7 | 4 |
| 2.0 | 1 |
| 2.3 | 1 |
| 3.2 | 1 |
| 4.0 | 1 |
| 4.199999 | 1 |
| 4.299999 | 1 |
| 5.0 | 1 |
| 5.2 | 2 |
| 7.3 | 1 |
| 8.0 | 1 |
| 365.25 | 3 |
| 3600.0 | 1 |

用眼快速地扫一下显示:

- 0.33 看上去像是 1/3, 有点取一个近似值。它可以被取代为用被除数3的除法。
- 365.25 看上去像一个一年的时间用天表示。另外一个可疑的地方时整数365和366在应用中使用了多次。
- 几个整数被表达为实数(0, 1, 2, 4, 5, 8, 3600)。
- 有一个小数点的浮点数看上去像版本号但也可能是其他的东西。我们能识别出PHP版本PHP version (5.0, 5.2), 或其他。

 

## 把字面值转变成常量

只使用一次的数字可以安全的被忽略。它们可能是用来做测试的目的或边缘用例，只有微小得重要性。只有至少2次出现的情况才值得创建一个常量。

另一个方面，使用多次的数字也可能显示不同代码之接有关系。当远程(如git版本控制）代码改变时，任何的更新突然变得困难起来。所有那些值必须被搜索和查阅。让我们来看看对于1.7的情况。

1.7 在代码里显示了4次。没有任何对这个值的意义的说明：最好的猜测是它可能是个版本号。Grep命令显示它在代码中出现了19次"1.7"：它真的有必要来使用审计工具来得到那些值。这是写实际的情况：

backend/external/misc/class.captcha.php#70: $fontsize = $this->height/1.7;
backend/external/misc/class.captcha.php#124: $fontsize = $this->height/1.7;
backend/external/misc/class.captcha.php#186: $fontsize = $this->height/1.7;
backend/external/pear.php.net/HTML/Common.php#97:
function apiVersion()
{
return 1.7;
} // end func apiVersion

有3次计算字体尺寸的出现平率。最后一个是被一个pear类返回的类的版本值。这里有两个相互冲突（不一样）的使用同一个数字的情况，通过常量来代替它们将会很有利。

## 推荐

- 查找出字面值，特别是那些用于算术的（像上面的计算字体大小的例子）并使用多次的。最主要的目标是常量化constantization (如果这个是个已存在的词的话).
- 神奇数字有可能是实数（很少），整数(很多），字符串（非常多）。按这样的顺序来处理它们来提高代码的可读性。
- 常量也许是类的常量（在类中使用）或接口（在多个接口相关的类）常量，或全局常量（为了测试目的）。记住，const关键字将会使常量更有效率，但是没有define灵活。
- 相同的字面值可以被定义为不同的常量：这是可能的而且很平常。
- ““全都是常量而且没有字面值”是一个坏主意。特别的，0, 1 和只使用了一次的字面值可以放着它们不管。

最后, 用常量来写下面的代码是非常漂亮的：
mkdir('path/to/new/dir', MODE_ALL_READ | MODE_ALL_EXEC)
而不要用：
mkdir('path/to/new/dir', 0770).

[![uk](http://178.62.231.40/wp-content/uploads/2015/06/uk.png) In English : Magic numbers in PHP](http://178.62.231.40/magic-numbers-in-php/)