任务:使用测试驱动开发创建Fizz游戏。打印范围1-100的正确单词。
执行情况:
public class Main {
static final String FIZZ = "Fizz";
static final String BUZZ = "Buzz";
static final String FIZZ_BUZZ = "Fizz Buzz";
public static void main(String[] args) {
IntStream.range(1, 101).forEach((x) -> System.out.println(getWordForNumber(x)));
}
public static String getWordForNumber(int x) {
if (isDivisibleWithoutRemainder(x, 15)) {
return FIZZ_BUZZ;
} else if(isDivisibleWithoutRemainder(x, 3)) {
return FIZZ;
} else if(isDivisibleWithoutRemainder(x, 5)) {
return BUZZ;
}
return Integer.toString(x);
}
private static boolean isDivisibleWithoutRemainder(int dividend, int divisor) {
return (dividend%divisor == 0);
}
}
JUnit测试:
final class Number {
private final int n;
Number (int number) {
n = number;
}
final boolean isMatchedToWord(final String word) {
return Main.getWordForNumber(n).equals(word);
}
}
class MainTest {
@Test
public void numbersAreMatchedToWords_Works() {
assertTrue(new Number(1).isMatchedToWord("1"));
assertTrue(new Number(2).isMatchedToWord("2"));
assertTrue(new Number(3).isMatchedToWord("Fizz"));
assertTrue(new Number(4).isMatchedToWord("4"));
assertTrue(new Number(5).isMatchedToWord("Buzz"));
assertTrue(new Number(6).isMatchedToWord("Fizz"));
assertTrue(new Number(10).isMatchedToWord("Buzz"));
assertTrue(new Number(15).isMatchedToWord("Fizz Buzz"));
assertTrue(new Number(30).isMatchedToWord("Fizz Buzz"));
}
}
发布于 2018-05-11 10:48:35
IntStream.rangeClosed(1, 100)
而不是IntStream.range(1, 101)
if (isDivisibleWithoutRemainder(x, 3))
优于if(isDivisibleWithoutRemainder(x, 3))
(注意if
后面的空格)return (dividend%divisor == 0);
不需要括号,我也建议给它更多的空间。return dividend % divisor == 0;
assertEquals
而不是assertTrue
,以便在测试失败时显示更好的错误消息Number
类,例如testNumber(4, "4");
,它基本上是执行assertEquals(word, Main.getWordForNumber(n));
的。发布于 2018-05-11 11:45:54
在测试驱动的开发中,通过重复以下步骤让代码和测试发展:
这些步骤有不同的地方,但有一点是肯定的:最终您将有许多测试用例。发布的代码有一个,这意味着它不是真正使用TDD开发的。
一切都尽可能简单是很好的。在测试类中,是否真的需要一个Number
类来包装一个数字,以便创建一个实例,然后在该实例上调用一个方法?一个简单的方法就足够了,它接受一个整数作为参数,并返回一个字符串。
发布于 2018-05-12 04:49:16
FIZZ = "Fizz"
真的吗?我很惊讶没有人提到,以他们的价值命名变量将为你赢得一个特殊的地位,在来世。不要把名字和价值观结合起来。
我同意这里提到的大部分内容,但另一个被忽略的问题是15的代码。
尝试添加一个要求,在7的倍数上打印"Bazz“,我想你会明白为什么我不同意从15开始。
如果没有,这里有一篇关于Fizz的经过深思熟虑的博客文章,深入讨论了15期名为错误的FizzBuzz的问题。它几乎向你展示了解决这个问题的更好的方法。不幸的是,它犯了一个致命的错误,并改变了需求,使其更易于使用解决方案。
硬编码15的问题是,它是对新需求的邀请,从而导致代码的组合爆炸。有一个简单的方法来绕过它。只要把你的字符串当作是字母的集合,并添加到它。
public static String getWordForNumber(int x) {
String result = "";
if ( isDivisibleBy(x, 3) ) {
result += "Fizz";
}
if ( isDivisibleBy(x, 5) ) {
result += "Buzz";
}
if ( result.equals("") ) {
result = Integer.toString(x);
}
return result;
}
现在是的,就像博客一样,这不太管用。该死的空间搞砸了。但它只需要三个小的改变。修起来容易。
public static String getWordForNumber(int x) {
String result = "";
if ( isDivisibleBy(x, 3) ) {
result += " Fizz";
}
if ( isDivisibleBy(x, 5) ) {
result += " Buzz";
}
if ( result.equals("") ) {
result = Integer.toString(x);
}
return result.trim();
}
现在它通过了所有的测试,唯一需要提到的是素数。
https://codereview.stackexchange.com/questions/194188
复制相似问题