实践题目:分解质因数
Step1:
单元测试:
package com.bijian.study.factor.test; import java.util.Arrays; import junit.framework.Assert; import org.junit.Before; import org.junit.Test; import com.bijian.study.factor.Factor; public class FactorTest { private Factor factor; @Before public void setUp() { factor = new Factor(); } @Test public void test_factor() { Assert.assertEquals(Arrays.asList(2), factor.getFactors(2)); Assert.assertEquals(Arrays.asList(3), factor.getFactors(3)); } }
编写测试通过的代码:
package com.bijian.study.factor; import java.util.ArrayList; import java.util.List; public class Factor { public List<Integer> getFactors(int i) { List<Integer> resList = new ArrayList<Integer>(); resList.add(i); return resList; } }
Step2:
再编写一个不通过的单元测试案例:
Assert.assertEquals(Arrays.asList(2,2), factor.getFactors(4));
修改代码,让单元测试案例通过:
package com.bijian.study.factor; import java.util.ArrayList; import java.util.List; public class Factor { public List<Integer> getFactors(int i) { List<Integer> resList = new ArrayList<Integer>(); if(i % 2 == 0 && i != 2) { resList.add(2); i = i/2; } resList.add(i); return resList; } }
Step3:
再编写如下单元测试案例,发现最后一个案例不能通过
Assert.assertEquals(Arrays.asList(5), factor.getFactors(5)); Assert.assertEquals(Arrays.asList(2,3), factor.getFactors(6)); Assert.assertEquals(Arrays.asList(7), factor.getFactors(7)); Assert.assertEquals(Arrays.asList(2,2,2), factor.getFactors(8));
修改代码,如下:
package com.bijian.study.factor; import java.util.ArrayList; import java.util.List; public class Factor { public List<Integer> getFactors(int i) { List<Integer> resList = new ArrayList<Integer>(); while(i % 2 == 0 && i != 2) { resList.add(2); i = i/2; } resList.add(i); return resList; } }
Step4:
增加如下单元测试案例
Assert.assertEquals(Arrays.asList(3,3), factor.getFactors(9));
修改代码:
package com.bijian.study.factor; import java.util.ArrayList; import java.util.List; public class Factor { public List<Integer> getFactors(int i) { List<Integer> resList = new ArrayList<Integer>(); while(i % 2 == 0 && i != 2) { resList.add(2); i = i/2; } while(i % 3 == 0 && i != 3) { resList.add(3); i = i/3; } resList.add(i); return resList; } }
Step5:
增加单元测试案例如下,发现最后一个案例执行不通过:
Assert.assertEquals(Arrays.asList(2,5), factor.getFactors(10)); Assert.assertEquals(Arrays.asList(11), factor.getFactors(11)); Assert.assertEquals(Arrays.asList(2,2,3), factor.getFactors(12)); Assert.assertEquals(Arrays.asList(2,11,13), factor.getFactors(2*11*13));
修改代码如下:
package com.bijian.study.factor; import java.util.ArrayList; import java.util.List; public class Factor { public List<Integer> getFactors(int i) { List<Integer> resList = new ArrayList<Integer>(); for(int j=2;j<i;j++) { while(i % j == 0 && i != j) { resList.add(j); i = i/j; } } resList.add(i); return resList; } }
Step6:
随意增加单元测试案例,如下所示:
Assert.assertEquals(Arrays.asList(3,7,13,23), factor.getFactors(3*7*13*23));
测试通过,但这代码不易理解,我们来重构,重构后代码如下:
package com.bijian.study.factor; import java.util.ArrayList; import java.util.List; public class Factor { public List<Integer> getFactors(int factor) { List<Integer> resList = new ArrayList<Integer>(); for(int j=2;j<factor;j++) { while(factor % j == 0 && factor != j) { resList.add(j); factor = factor/j; } } resList.add(factor); return resList; } }
上面仅用到一个很简单的重构方法,重命名。
以上这些步骤或练习的过程就是Kata。Kata(路数练习)的思想就是通过反复练习来实践编码,在不断使用各种技能的过程中形成肌肉记忆。Kata从很多方面改善工作流程,比如编写测试、处理错误甚至编辑器的使用,更熟悉语言技巧。
附另一种分解质因数的方法:
public List<Integer> getFactors2(int factor) { List<Integer> resList = new ArrayList<Integer>(); for(int j=2;j<=factor;j++) { if(factor%j == 0) { resList.add(j); factor = factor/j; j=1; } } return resList; }