测试这个的最佳方法是什么? 4位二进制数
What is the best way to test this? Binary digits with 4 positions
考虑网络表面上的 4 个输入字段 A、B、C 和 D。用户可以任意填充这些。如何填写这些字段有 16 种组合。允许的是:
A B C D
-------
1 0 0 0
1 1 0 0
1 1 1 0
1 1 1 1
其中 1 表示 not null
,0 表示 null
。
我在 jsf 中使用 MVC 模式。我不希望逻辑在视图中,而是在控制器中。在 Java 中检查此内容的最佳方法是什么?
到目前为止我实施了两个解决方案:
解决方案 1:
@Override
public boolean isInputInvalid(Integer a, Integer b, Integer c, Integer d) {
if (isNotSet(a) && isNotSet(b) && isNotSet(c) && isNotSet(d) {
return true;
}
return (firstParameterDoesNotExistAndSecondDoesExist(a, b)) || (firstParameterDoesNotExistAndSecondDoesExist(b, c)) || (firstParameterDoesNotExistAndSecondDoesExist(c, d));
}
private boolean firstParameterDoesNotExistAndSecondDoesExist(Integer firstParameter, Integer secondParameter) {
return isNotSet(firstParameter) && !isNotSet(secondParameter);
}
private boolean isNotSet(Integer parameter) {
return parameter == null;
}
解决方案 2:
public boolean isInputValid(Integer a, Integer b, Integer c, Integer d) {
if (exists(a) && !exists(b) && !exists(c) && !exists(d) || //
exists(a) && exists(b) && !exists(c) && !exists(d) || //
exists(a) && exists(b) && exists(c) && !exists(d) || //
exists(a) && exists(b) && exists(c) && exists(d)) {
return true;
}
return false;
}
private boolean exists(Integer level) {
return level != null;
}
注:
第一种方法检查输入是否无效,而第二种方法检查输入是否有效(注意方法的名称) .
我写了 16 个单元测试用例,两个版本都 运行 绿色。
关于如何使代码更具可读性,您有什么hints/tips/tricks吗?
您可以使用二维数组创建图案。
优点是易于调整,并向其添加附加信息。
这是您的条件的一个小例子。
最后你只需要阅读在静态块中初始化的模式,这很容易阅读。
// Every boolean array in a dimension represents a valid pattern
private static boolean[][] pattern;
static {
pattern = new boolean[4][4];
pattern[0] = new boolean[]{true, false, false, false};
pattern[1] = new boolean[]{true, true, false, false};
pattern[2] = new boolean[]{true, true, true, false};
pattern[3] = new boolean[]{true, true, true, true};
}
public static void main(String[] args) {
// Testing an invalid combination
System.out.println(test(new Integer[]{1,null,3,null}));
// Testing a valid combination
System.out.println(test(new Integer[]{1,2,3,null}));
}
private static boolean test(Integer[] input) {
// cast the input to a boolean array that can be compared to the pattern.
boolean[] arr = createArr(input);
for(int i = 0;i<pattern.length;++i) {
if(Arrays.equals(pattern[i], arr)) { // Check if the pattern exists in the list of valid pattern. If it exists, then this is a valid combination
return true;
}
}
// the loop never found a valid combination, hence it returns false.
return false;
}
// This is just a helping method to create a boolean array out of an int array. It casts null to true and !null to false.
private static boolean[] createArr(Integer[] input) {
boolean[] output = new boolean[input.length];
for(int i = 0;i<input.length; ++i) {
output[i] = input[i] != null;
}
return output;
}
要解决任意数量参数的问题,请在此处传入 true
或 false
(如果不是 null / null):
static boolean isValid(boolean... params) {
boolean set = true;
for (boolean param : params) {
if (!set && param) return false;
set = param;
}
return params[0];
}
或者更酷(并且恕我直言可读),但性能较低,在数组的 toString()
:
上使用正则表达式
static boolean isValid(boolean... params) {
return Arrays.toString(params).matches("\[true(, true)*(, false)*]");
}
无论你使用哪种实现,你都会这样称呼它:
if (isValid(a != null, b != null, c != null, d != null))
Valid combinations are: 1000, 1100, 1110 and 1111
如果您只关心可读性:
public static List<String> validOptions = Arrays.asList("1000","1100","1110","1111");
public boolean isValid(Integer a, Integer b, Integer c, Integer d)
{
StringBuilder sb = new StringBuilder();
sb.append(a==null ? 0 : 1);
sb.append(b==null ? 0 : 1),
sb.append(c==null ? 0 : 1);
sb.append(d==null ? 0 : 1);
return validOptions.contains(sb.toString());
}
请注意,这不是最快或最干净的解决方案(浪费一些 CPU 和内存)
另一种解决方案。涉及更多代码,但对我来说更容易理解:
boolean isInputInvalid(Object ... args) {
int notNullDataIndex = -1;
for (int i = args.length - 1; i >= 0; i--) {
if (args[i] != null) {
notNullDataIndex = i;
break;
}
}
if (notNullDataIndex < 0) return false;
for (int i = notNullDataIndex; i >= 0; i--) {
if (args[i] == null) return false;
}
return true;
}
不花哨但又快又简单:
static boolean isValid(boolean a, boolean b, boolean c, boolean d) {
return a && (b || !c) && (c || !d);
}
通话:
isValid(a != null, b != null, c != null, d != null);
我真的不明白你为什么需要这个。比起测试输入是否有效的方法,首先只允许有效输入会好得多。
// This method is private, so you can't call it with arbitrary arguments.
private void privateMethod(Integer a, Integer b, Integer c, Integer d) {
// do something();
}
public void method(int a) {
privateMethod(a, null, null, null);
}
public void method(int a, int b) {
privateMethod(a, b, null, null);
}
public void method(int a, int b, int c) {
privateMethod(a, b, c, null);
}
public void method(int a, int b, int c, int d) {
privateMethod(a, b, c, d);
}
将此修改为任意数量的参数(不仅仅是 4 个)的方法是使用带有签名的方法
public void method(int... a)
那么,如果传入的数组长度小于要求的长度,剩下的输入只用null
即可。
如果这不能解决您的问题,我认为您应该考虑编辑您的问题以举例说明您的用例,因为我怀疑有更好的方法可以实现您的要求。
考虑网络表面上的 4 个输入字段 A、B、C 和 D。用户可以任意填充这些。如何填写这些字段有 16 种组合。允许的是:
A B C D
-------
1 0 0 0
1 1 0 0
1 1 1 0
1 1 1 1
其中 1 表示 not null
,0 表示 null
。
我在 jsf 中使用 MVC 模式。我不希望逻辑在视图中,而是在控制器中。在 Java 中检查此内容的最佳方法是什么?
到目前为止我实施了两个解决方案:
解决方案 1:
@Override
public boolean isInputInvalid(Integer a, Integer b, Integer c, Integer d) {
if (isNotSet(a) && isNotSet(b) && isNotSet(c) && isNotSet(d) {
return true;
}
return (firstParameterDoesNotExistAndSecondDoesExist(a, b)) || (firstParameterDoesNotExistAndSecondDoesExist(b, c)) || (firstParameterDoesNotExistAndSecondDoesExist(c, d));
}
private boolean firstParameterDoesNotExistAndSecondDoesExist(Integer firstParameter, Integer secondParameter) {
return isNotSet(firstParameter) && !isNotSet(secondParameter);
}
private boolean isNotSet(Integer parameter) {
return parameter == null;
}
解决方案 2:
public boolean isInputValid(Integer a, Integer b, Integer c, Integer d) {
if (exists(a) && !exists(b) && !exists(c) && !exists(d) || //
exists(a) && exists(b) && !exists(c) && !exists(d) || //
exists(a) && exists(b) && exists(c) && !exists(d) || //
exists(a) && exists(b) && exists(c) && exists(d)) {
return true;
}
return false;
}
private boolean exists(Integer level) {
return level != null;
}
注:
第一种方法检查输入是否无效,而第二种方法检查输入是否有效(注意方法的名称) .
我写了 16 个单元测试用例,两个版本都 运行 绿色。
关于如何使代码更具可读性,您有什么hints/tips/tricks吗?
您可以使用二维数组创建图案。 优点是易于调整,并向其添加附加信息。 这是您的条件的一个小例子。 最后你只需要阅读在静态块中初始化的模式,这很容易阅读。
// Every boolean array in a dimension represents a valid pattern
private static boolean[][] pattern;
static {
pattern = new boolean[4][4];
pattern[0] = new boolean[]{true, false, false, false};
pattern[1] = new boolean[]{true, true, false, false};
pattern[2] = new boolean[]{true, true, true, false};
pattern[3] = new boolean[]{true, true, true, true};
}
public static void main(String[] args) {
// Testing an invalid combination
System.out.println(test(new Integer[]{1,null,3,null}));
// Testing a valid combination
System.out.println(test(new Integer[]{1,2,3,null}));
}
private static boolean test(Integer[] input) {
// cast the input to a boolean array that can be compared to the pattern.
boolean[] arr = createArr(input);
for(int i = 0;i<pattern.length;++i) {
if(Arrays.equals(pattern[i], arr)) { // Check if the pattern exists in the list of valid pattern. If it exists, then this is a valid combination
return true;
}
}
// the loop never found a valid combination, hence it returns false.
return false;
}
// This is just a helping method to create a boolean array out of an int array. It casts null to true and !null to false.
private static boolean[] createArr(Integer[] input) {
boolean[] output = new boolean[input.length];
for(int i = 0;i<input.length; ++i) {
output[i] = input[i] != null;
}
return output;
}
要解决任意数量参数的问题,请在此处传入 true
或 false
(如果不是 null / null):
static boolean isValid(boolean... params) {
boolean set = true;
for (boolean param : params) {
if (!set && param) return false;
set = param;
}
return params[0];
}
或者更酷(并且恕我直言可读),但性能较低,在数组的 toString()
:
static boolean isValid(boolean... params) {
return Arrays.toString(params).matches("\[true(, true)*(, false)*]");
}
无论你使用哪种实现,你都会这样称呼它:
if (isValid(a != null, b != null, c != null, d != null))
Valid combinations are: 1000, 1100, 1110 and 1111
如果您只关心可读性:
public static List<String> validOptions = Arrays.asList("1000","1100","1110","1111");
public boolean isValid(Integer a, Integer b, Integer c, Integer d)
{
StringBuilder sb = new StringBuilder();
sb.append(a==null ? 0 : 1);
sb.append(b==null ? 0 : 1),
sb.append(c==null ? 0 : 1);
sb.append(d==null ? 0 : 1);
return validOptions.contains(sb.toString());
}
请注意,这不是最快或最干净的解决方案(浪费一些 CPU 和内存)
另一种解决方案。涉及更多代码,但对我来说更容易理解:
boolean isInputInvalid(Object ... args) {
int notNullDataIndex = -1;
for (int i = args.length - 1; i >= 0; i--) {
if (args[i] != null) {
notNullDataIndex = i;
break;
}
}
if (notNullDataIndex < 0) return false;
for (int i = notNullDataIndex; i >= 0; i--) {
if (args[i] == null) return false;
}
return true;
}
不花哨但又快又简单:
static boolean isValid(boolean a, boolean b, boolean c, boolean d) {
return a && (b || !c) && (c || !d);
}
通话:
isValid(a != null, b != null, c != null, d != null);
我真的不明白你为什么需要这个。比起测试输入是否有效的方法,首先只允许有效输入会好得多。
// This method is private, so you can't call it with arbitrary arguments.
private void privateMethod(Integer a, Integer b, Integer c, Integer d) {
// do something();
}
public void method(int a) {
privateMethod(a, null, null, null);
}
public void method(int a, int b) {
privateMethod(a, b, null, null);
}
public void method(int a, int b, int c) {
privateMethod(a, b, c, null);
}
public void method(int a, int b, int c, int d) {
privateMethod(a, b, c, d);
}
将此修改为任意数量的参数(不仅仅是 4 个)的方法是使用带有签名的方法
public void method(int... a)
那么,如果传入的数组长度小于要求的长度,剩下的输入只用null
即可。
如果这不能解决您的问题,我认为您应该考虑编辑您的问题以举例说明您的用例,因为我怀疑有更好的方法可以实现您的要求。