Java 测试1,2,…的幻数常量名称约定,。。一百对一,二,一百

Java 测试1,2,…的幻数常量名称约定,。。一百对一,二,一百,java,testing,coding-style,naming-conventions,magic-numbers,Java,Testing,Coding Style,Naming Conventions,Magic Numbers,所以我正在做一些代码重构/声纳修复,有一些测试包含神奇的数字,5,123,567或其他什么,我想创建一个NumberConstant类,我们保存测试中使用的数字,一切都很好,我们有这样的东西 public static final int ZERO = 0; public static final int ONE = 1; public static final int TWO = 2; public static final int THREE = 3; public static final

所以我正在做一些代码重构/声纳修复,有一些测试包含神奇的数字,5,123,567或其他什么,我想创建一个NumberConstant类,我们保存测试中使用的数字,一切都很好,我们有这样的东西

public static final int ZERO = 0;
public static final int ONE = 1;
public static final int TWO = 2;
public static final int THREE = 3;
public static final int FOUR = 4;
public static final int FIVE = 5;
 public static final int _0 = 0;
 public static final int _1 = 1;
 public static final int _2 = 2;
 public static final int _3 = 3;
 public static final int _4 = 4;
 public static final int _5 = 5;
问题是在进行重构时,SonarQube的代码是“ok”的,但似乎有些不对劲,代码不知何故变得“凌乱”

我的意思是比较这两条线

以前

private LocalDateTime endtDateOfFiscalYear2018 = LocalDate.of(2018, Month.DECEMBER, 31).atTime(LocalTime.MAX);
之后

我认为一个好的折衷办法是:

private LocalDateTime endtDateOfFiscalYear2018 = LocalDate.of(_2018, Month.DECEMBER, _31).atTime(LocalTime.MAX);
还有像这样的数字恒常类

public static final int ZERO = 0;
public static final int ONE = 1;
public static final int TWO = 2;
public static final int THREE = 3;
public static final int FOUR = 4;
public static final int FIVE = 5;
 public static final int _0 = 0;
 public static final int _1 = 1;
 public static final int _2 = 2;
 public static final int _3 = 3;
 public static final int _4 = 4;
 public static final int _5 = 5;

这是一个好的折衷方案还是整个方案都不正确?你用什么方法来保持你的测试清晰易懂

我认为整个方法是不正确的

如果引入一个命名常量,而该名称只是对值进行了重新表述,那么您从中获得了什么

从文字值引入常量通常有一些好处:

  • 你看到的不是一个神奇的数字,而是一个有意义的名字
  • 它将非常相同的值具有相同含义的情况组合在一起。例如,您可能会遇到许多使用数字10的地方,一些地方用作数字表示基数,一些地方用作对数值的基数,一些地方表示十月,等等
  • 如果您后来发现不同的值更能代表预期的含义,您可以在一个中心位置更改该值
如果用名为TEN或_10的常量替换所有出现的文字10,所有这些都不起作用。例如,希望您永远不会将10更改为20

因此,我们需要的不仅仅是一些自动化的、盲目的价值替换。您需要理解该文本的具体出现意味着什么,然后为该概念引入一个合适的名称,用一个通用名称替换同一概念的所有出现

最初的开发者应该这样做。如果现在你只是盲目地引入像十这样的名字,你只是隐藏了缺陷,它永远不会得到改善。所以我宁愿让声纳永远提醒我这个问题,而不是永远隐藏它


有时,特别是在测试用例中,我甚至更喜欢看到一个文字4711,而不是一个名为随机四位数的常量。

我认为整个方法是不正确的

如果引入一个命名常量,而该名称只是对值进行了重新表述,那么您从中获得了什么

从文字值引入常量通常有一些好处:

  • 你看到的不是一个神奇的数字,而是一个有意义的名字
  • 它将非常相同的值具有相同含义的情况组合在一起。例如,您可能会遇到许多使用数字10的地方,一些地方用作数字表示基数,一些地方用作对数值的基数,一些地方表示十月,等等
  • 如果您后来发现不同的值更能代表预期的含义,您可以在一个中心位置更改该值
如果用名为TEN或_10的常量替换所有出现的文字10,所有这些都不起作用。例如,希望您永远不会将10更改为20

因此,我们需要的不仅仅是一些自动化的、盲目的价值替换。您需要理解该文本的具体出现意味着什么,然后为该概念引入一个合适的名称,用一个通用名称替换同一概念的所有出现

最初的开发者应该这样做。如果现在你只是盲目地引入像十这样的名字,你只是隐藏了缺陷,它永远不会得到改善。所以我宁愿让声纳永远提醒我这个问题,而不是永远隐藏它


有时,特别是在测试用例中,我甚至更喜欢看到一个文字4711,而不是一个名为随机四位数的常量。

你错误地认为SonarQube是正确的。原始代码没有问题
2018
不是一个神奇的数字。这显然是一年,但它甚至不相关,因为除了构建您感兴趣的实际对象之外,您没有使用它,即
enddateoffscalyear2018
。这是声纳的误报,不是真正的魔法数字。正如@Kayaman所说,你的代码没有错。如果你想摆脱“幻数”,只需在它们习惯于使用正确命名的局部常量的地方提取它,比如“expectedYear”或类似的东西,你就犯了错误,认为SonarQube是正确的。原始代码没有问题
2018
不是一个神奇的数字。这显然是一年,但它甚至不相关,因为除了构建您感兴趣的实际对象之外,您没有使用它,即
enddateoffscalyear2018
。这是声纳的误报,不是真正的魔法数字。正如@Kayaman所说,你的代码没有错。如果你想摆脱“幻数”,只需在它们习惯于使用正确命名的局部常量的地方提取它,比如“expectedYear”或类似的东西