TDD与重构_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > TDD与重构

TDD与重构

 2014/9/21 15:32:32  bijian1013  程序员俱乐部  我要评论(0)
  • 摘要:一.重构实践实践题目:重构获取指定数值内的所有质数的方法重构前:packagetraining.generatPrimes;/***Refactorings:**ExtractFields.*ExtractMethods:initArrayOfIntegers,crossOutMultiples,putUncrossedIntegerIntoResult*Inlineswithf
  • 标签:

一.重构实践

实践题目:重构获取指定数值内的所有质数的方法

重构前:

class="java">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.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 {
	
	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).重构时只做重构,如果原来逻辑有问题,重构后再处理

?

  • 大小: 286.9 KB
  • 查看图片附件
  • 相关文章
发表评论
用户名: 匿名