一.重构实践
实践题目:重构获取指定数值内的所有质数的方法
单元测试案例:
package training.generatPrimes.test;
import static org.junit.Assert.*;
import org.junit.Test;
import training.generatPrimes.PrimeGenerator;
public class PrimeGeneratorTest {
@Test
public void testPrimes() {
int[] nullArray = new PrimeGenerator().generatePrimes(0);
assertEquals(0, nullArray.length);
int[] minArray = new PrimeGenerator().generatePrimes(2);
assertEquals(1, minArray.length);
assertEquals(2, minArray[0]);
int[] threeArray = new PrimeGenerator().generatePrimes(3);
assertEquals(2, threeArray.length);
assertEquals(2, threeArray[0]);
assertEquals(3, threeArray[1]);
int[] centArray = new PrimeGenerator().generatePrimes(100);
assertEquals(25, centArray.length);
assertEquals(97, centArray[24]);
}
@Test
public void testExhaustive() {
for (int i = 2; i < 500; i++) {
verifyPrimeList(new PrimeGenerator().generatePrimes(i));
}
}
private void verifyPrimeList(int[] list) {
for (int i = 0; i < list.length; i++) {
verifyPrime(list[i]);
}
}
private void verifyPrime(int n) {
for (int factor = 2; factor < n; factor++) {
assertTrue(n % factor != 0);
}
}
}
重构前:
package training.generatPrimes;
/**
* Refactorings:
*
* Extract Fields.
* Extract Methods: initArrayOfIntegers, crossOutMultiples, putUncrossedIntegerIntoResult
* Inline s with f.length
* Rename f to isCrossed
* Ensure for loop starts from 2
* Extract Methods: crossOutMultipleOf, numberOfUncrossedIntegers, notCrossed
* Rename methods to: uncrossIntegersUpTo
*/
public class PrimeGenerator {
/**
*
* @param maxValue
* is the generation limit
* @return
*/
public int[] generatePrimes(int maxValue) {
if (maxValue >= 2) { // the only valid case
// declarations
int s = maxValue + 1; // size of array
boolean[] f = new boolean[s];
// initialize array to true
for (int i = 0; i < s; i++) {
f[i] = true;
}
// get rid of known non-primes
f[0] = f[1] = false;
// sieve
for (int i = 2; i < Math.sqrt(s) + 1; i++) {
for (int j = 2 * i; j < s; j += i) {
f[j] = false; // multiple is not prime
}
}
// how many primes are there?
int count = 0;
for (int i = 0; i < s; i++) {
if (f[i])
count++; // bump count
}
int[] primes = new int[count];
// move the primes into the result
for (int i = 0, j = 0; i < s; i++) {
if (f[i])
primes[j++] = i;
}
return primes;
} else { // maxValue < 2
return new int[0]; // return null array if bad input.
}
}
}
重构后:
package training.generatPrimes;
/**
* Refactorings:
*
* Extract Fields.
* Extract Methods: initArrayOfIntegers, crossOutMultiples, putUncrossedIntegerIntoResult
* Inline s with f.length
* Rename f to isCrossed
* Ensure for loop starts from 2
* Extract Methods: crossOutMultipleOf, numberOfUncrossedIntegers, notCrossed
* Rename methods to: uncrossIntegersUpTo
*/
public class PrimeGenerator {
private boolean[] composite;
/**
*
* @param maxValue
* is the generation limit
* @return
*/
public int[] generatePrimes(int maxValue) {
initArrayOfIntegers(maxValue);
markAllMultiplesToComposite();
return getPrimes();
}
/**
* @param maxValue
*/
private void initArrayOfIntegers(int maxValue) {
composite = new boolean[maxValue + 1];
}
/**
* @return
*/
private int[] getPrimes() {
int[] primes = new int[numberOfPrimes()];
for (int i = 2, j = 0; i < composite.length; i++) {
if (!composite[i])
primes[j++] = i;
}
return primes;
}
/**
* @return
*/
private int numberOfPrimes() {
int count = 0;
for (int i = 2; i < composite.length; i++) {
if (!composite[i])
count++; // bump count
}
return count;
}
/**
* @param s
* @param composite
*/
private void markAllMultiplesToComposite() {
for (int i = 2; i < Math.sqrt(composite.length) + 1; i++) {
markMultiplesToComposite(i);
}
}
/**
* @param composize
* @param i
*/
private void markMultiplesToComposite(int i) {
for (int j = 2 * i; j < composite.length; j += i) {
composite[j] = true; // multiple is not prime
}
}
}
二.重构理论知识
1.什么样的代码需要重构
1).Don't Repeat Yourself
2).注释《会说话的代码》-王洪亮,注释代码的意图(写Why)
3).Naming命名
4).Long Method长方法
a.Performance Anxiety(性能)
b.Scattered Code Avoidance(避免锁碎的代码)
c.Rampant Growth(时间紧急)
d.Bind Conformity(团队环境就是长方法)
e.Pure lgnorance(我不知道什么是好代码,我也不知道怎么写好代码)
5).Large Class(巨类)
6).Dead Code(僵尸代码)
Kill the dead:Knowledge(知识)、Expenece(经验)、Tools(工具)、Coverage(覆盖)、complexity(复杂度)、Timing(时机)
7).Switch statuement(开关语句)
8).Inappropriate Intimacy(过度亲密),应该调对方的接口
9).复杂条件
10).Magic Number(魔法数字)
11).SingleTon单例(不利测试)
2.重构常用方法
1).重命名
2).抽取方法
3).内联变量
4).反转逻辑
5).移动
6).删除
3.重构注意事项:
1).不改变原功能
2).频繁运行测试案例
3).尽量使用工具
4).基于代码坏味道
5).步子要小
6).重构时只做重构,如果原来逻辑有问题,重构后再处理