`

TDD与重构

阅读更多

一.重构实践

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

单元测试案例:

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

 

  • 大小: 286.9 KB
分享到:
评论

相关推荐

    eclipse 重构

    "测试驱动开发及代码重构.ppt"很可能是一个幻灯片,详细阐述了TDD与重构的结合使用,可能包括TDD的步骤(编写失败的测试、编写最少的代码让测试通过、重构),以及在TDD循环中重构的重要性和时机。这份资料可能还...

    重构?测试?TDD?Ant?

    标题中的“重构”、“测试”、“TDD”和“Ant”是四个重要的IT概念,它们在软件开发领域中扮演着至关重要的角色。 1. **重构**:重构是改善软件设计和代码质量的过程,而不改变其外部行为。它通过消除代码异味、...

    junit-demo.zip

    【Junit-Demo.zip】是一个压缩包,包含了有关测试驱动开发(TDD)的示例代码,...在实践中,TDD与重构相结合(如描述中提到的"xp=tdd+重构"),能够促进代码结构的优化,降低维护成本,使得软件项目更易于扩展和维护。

    测试驱动开发 英文版

    6. **TDD与重构**:探讨如何在TDD中平衡代码的重构,以保持代码的整洁和可维护性。 7. **TDD在大型项目中的应用**:讨论在复杂项目中实施TDD的挑战和策略。 这本书对于希望深入了解TDD并将其应用于日常工作的开发者...

    Pro PHP Refactoring

    6. **测试驱动开发(TDD)与重构的关系** 7. **性能优化技术** 8. **最佳实践案例分析** #### 详细知识点解析 **1. PHP重构的基本概念与重要性** 重构是指在不改变软件外部行为的前提下,对其内部结构进行调整以...

    Manning The Art of Unit Testing with Examples in dot NET

    书中会讨论TDD的工作流程,如何使用TDD来改进设计,以及TDD与重构的关系。 4. **隔离技术**:为了有效地进行单元测试,通常需要隔离被测试代码,避免外部依赖的影响。书中会探讨模拟对象(mocking)、存根...

    单元测试与TDD实践

    单元测试与TDD实践 **一、单元测试之测试目的** 单元测试,作为软件开发过程中的重要环节,其核心目标在于确保代码的质量、可维护性和可扩展性。它通过独立测试软件中的最小可测试单元,如函数或方法,来验证其...

    Applying Domain Driven Design and Patterns

    模式、TDD与重构简介 本书开篇首先介绍了企业架构模式的基础概念、测试驱动开发的基本原理以及重构的重要性。这些章节为读者奠定了后续深入学习的基础。 ##### 2. 架构技巧提升软件质量 接下来,书中深入探讨了...

    TDD测试驱动开发

    TDD通常与持续集成配合使用,每次提交代码时,自动运行所有测试,确保新代码没有破坏现有功能。 5. **TDD实践** 文件名中的“测试驱动开发TDD培训讲义.ppt”、“TDD_测试驱动开发.ppt”和“测试驱动开发—1.1_...

    python-tdd-book

    8. **TDD与重构**:TDD不仅是编写测试,也是重构的保障。当测试已存在,重构可以更安全地进行,因为任何破坏现有功能的修改都会导致测试失败。 在"python-tdd-book-master"中,读者可能会发现详细的章节介绍这些...

    tddworkshop20151020:TDD研讨会于1020年举行

    5. **TDD与重构**:探讨在TDD过程中如何进行代码重构,以保持代码整洁和易于维护。 6. **模拟与依赖注入**:讲解如何使用Mockito等工具创建模拟对象,以及依赖注入的重要性。 7. **实战演练**:可能包含一些实践...

    Clean-Code-Study:TDD,重构,有效的Java,设计模式,框架

    TDD遵循“红-绿-重构”三步法则:首先编写失败的测试(红色),然后写代码使测试通过(绿色),最后对代码进行重构以优化和保持整洁(重构)。 **重构** 重构是改进代码结构而不改变其外在行为的过程。它有助于提高...

    <<重构>>的进阶版,修改代码的艺术

    6. **测试驱动开发(TDD)与重构的关系**:TDD是重构的重要伙伴,先编写测试用例,再重构代码,确保重构过程中功能的完整性。 7. **设计模式与重构**:设计模式提供了解决常见问题的通用方案,而重构可以帮助我们将...

    Test Driven: Practical TDD and Acceptance TDD for Java Developers (PDF英文版)

    TDD的核心流程可以概括为"红-绿-重构":首先,编写一个失败的单元测试(红色),然后编写最简单的代码使测试通过(绿色),最后重构代码以提高可读性和维护性。这种迭代过程确保了代码始终处于被测试覆盖的状态,...

    Ruby-TDD实战TestDrivenDevelopmentinAction

    在实际项目中,TDD也与其他实践相结合,如持续集成(Continuous Integration, CI)和持续部署(Continuous Deployment, CD)。例如,我们可以使用Jenkins、Travis CI或GitHub Actions设置自动化测试,每次代码提交后...

    镶金玫瑰Gilded Rose重构后项目

    【镶金玫瑰Gilded Rose重构后项目】是一个典型的软件工程实践案例,主要涉及了测试驱动开发(TDD)、Java编程语言以及代码重构这三个核心知识点。 首先,我们要理解**测试驱动开发(TDD)**的概念。TDD是一种软件...

    嵌入式 TDD

    #### TDD与嵌入式系统 **嵌入式系统**是专门用于执行特定任务的计算机系统,通常包含硬件和软件两部分。这类系统广泛应用于汽车、医疗设备、家用电器等多个领域。由于嵌入式系统的复杂性和对可靠性的高要求,采用...

Global site tag (gtag.js) - Google Analytics