什么是神奇数字?
为什么要避免呢?
有没有合适的情况?
什么是神奇数字?
为什么要避免呢?
有没有合适的情况?
当前回答
魔术数字是在代码中直接使用数字。
例如,如果你有(在Java中):
public class Foo {
public void setPassword(String password) {
// don't do this
if (password.length() > 7) {
throw new InvalidArgumentException("password");
}
}
}
这应该被重构为:
public class Foo {
public static final int MAX_PASSWORD_SIZE = 7;
public void setPassword(String password) {
if (password.length() > MAX_PASSWORD_SIZE) {
throw new InvalidArgumentException("password");
}
}
}
它提高了代码的可读性,也更容易维护。想象一下我在GUI中设置密码字段大小的情况。如果我使用一个神奇的数字,每当最大大小发生变化时,我必须在两个代码位置进行更改。如果我忘记了一个,就会导致不一致。
JDK中有很多例子,比如Integer, Character和Math类。
PS:像FindBugs和PMD这样的静态分析工具可以检测到代码中使用的神奇数字,并建议进行重构。
其他回答
你看过维基百科上关于魔法数字的词条了吗?
它详细介绍了魔术数字引用的所有方式。下面是关于魔术数字是一种糟糕的编程实践的引用
“魔数”一词也指在源代码中直接使用数字而不作解释的糟糕编程实践。在大多数情况下,这会使程序更难阅读、理解和维护。尽管大多数指南对数字0和1做了例外处理,但在代码中将所有其他数字定义为命名常量是个好主意。
那么返回变量呢?
我发现在实现存储过程时尤其具有挑战性。
想象下一个存储过程(我知道语法错误,只是举个例子):
int procGetIdCompanyByName(string companyName);
如果该公司存在于特定的表中,则返回该公司的Id。否则,返回-1。 不知何故,这是一个神奇的数字。到目前为止,我读到的一些建议说,我真的必须设计这样的东西:
int procGetIdCompanyByName(string companyName, bool existsCompany);
顺便问一下,如果公司不存在,它应该返回什么?它会将existesCompany设为false,但也会返回-1。
Antoher的选择是做两个独立的功能
bool procCompanyExists(string companyName);
int procGetIdCompanyByName(string companyName);
因此第二个存储过程的先决条件是公司存在。
但是我害怕并发,因为在这个系统中,一个公司可以由另一个用户创建。
顺便说一句,最重要的是:你对使用这种相对已知和安全的“神奇数字”来判断某事不成功或某事不存在有什么看法?
值得注意的是,有时您确实希望在代码中使用不可配置的“硬编码”数字。有许多著名的,包括0x5F3759DF,它用于优化的平方根反算法。
在极少数情况下,我发现需要使用这种神奇的数字,我将它们设置为我的代码中的const,并记录为什么使用它们,它们是如何工作的,以及它们来自哪里。
@eed3si9n:我甚至认为“1”是一个神奇的数字。: -)
与神奇数字相关的一个原则是,代码处理的每个事实都应该声明一次。如果您在代码中使用神奇的数字(例如@marcio给出的密码长度示例),那么您很容易复制该事实,当您对事实的理解发生变化时,您就会遇到维护问题。
魔术数字是在代码中直接使用数字。
例如,如果你有(在Java中):
public class Foo {
public void setPassword(String password) {
// don't do this
if (password.length() > 7) {
throw new InvalidArgumentException("password");
}
}
}
这应该被重构为:
public class Foo {
public static final int MAX_PASSWORD_SIZE = 7;
public void setPassword(String password) {
if (password.length() > MAX_PASSWORD_SIZE) {
throw new InvalidArgumentException("password");
}
}
}
它提高了代码的可读性,也更容易维护。想象一下我在GUI中设置密码字段大小的情况。如果我使用一个神奇的数字,每当最大大小发生变化时,我必须在两个代码位置进行更改。如果我忘记了一个,就会导致不一致。
JDK中有很多例子,比如Integer, Character和Math类。
PS:像FindBugs和PMD这样的静态分析工具可以检测到代码中使用的神奇数字,并建议进行重构。