实践题目:分解质因数
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;
}
敏捷教练:
http://www.maiyuan.me/