关于《31重构》(原书名为《31DaysRefactoring》)这本书,是从张逸前辈(51CTO博客地址为:晴窗笔记http://wayfarer.blog.51cto.com/)的一篇推荐该书的文章(“31天速成重构http://wayfarer.blog.51cto.com/1300239/280198”)中看到的。

这是一本免费可下载的 pdf 格式电子书,张逸前辈评价该书“是重构技术的经验荟萃”,可点击这里下载,或点击这里在线阅读。

我也是初初接触重构这个话题,虽然之前早就在图书馆翻过《重构——改善既有代码的设计》这本经典,但并未着手去“开发”它。现在有了《31天重构》这本书,想试着边读代码边用自己的理解翻译一下每一篇文章,并从中学习到关于重构的知识。

关于重构,在《重构》这本经典的中文版底面有这样几句话“每个重构的步骤都十分简单——简单到了似乎不值得去做的程度。…这些个别步骤虽然可能十分基本,积累下来的影响却能够彻底改善设计。重构已经被证明可以阻止软件的腐朽与腐败。

直到现在才写这篇文章,是因为之前被原书中的第一篇中的一个点子给卡住了,今晚从图书馆借来了《重构》中文版,对比了一下才明白原文意思。开始重构吧。

 

有时候我们并不希望对外提供一整个集合(在 Java 中有ArrayList 等丰富的集合类),因为这样很可能会被用户不经意或者恶意地修改集合中的内容,导致意想不到的错误。为了避免这种情况,我们只需要对外提供不可缺少的方法操作(例如 add 、remove),同时还要将该集合对象对外提供一个“只读”权限的引用,之所以是“只读”,就是限制使用者修改该集合的内容。

重构前的代码例子:

class Course {
	private String name;
	public Course (String name) {
		this.name = name;
	}
}

class Student {
	// 每个 Student 都包含一个课程集合
	private Set courses;
	
	public Student() {
		this.courses = new HashSet();
	}
	
	// 如此直接返回原始的集合对象,危险!!!
	public Set getCourses(){
		return this.courses;
	}
	
	public void addCourse(Course course) {
		this.courses.add(course);
	}
	
	public void removeCourse(Course course) {
		if(this.courses.contains(course)) {
			this.courses.remove(course);
		}
	}
}


我们已经对外提供了操作集合的必要方法 add 、remove ,如上所述,直接返回原始集合对象是应该避免的,应该进行重构。

重构后的代码:

class Course {
	private String name;
	public Course (String name) {
		this.name = name;
	}
}

class Student {
	// 每个 Student 都包含一个课程集合
	private Set courses;
	
	public Student() {
		this.courses = new HashSet();
	}
	
	// 如此直接返回原始的集合对象,危险!!!
	public Set getCourses(){
//		return this.courses;
		
		// 使用 Java 类集中的 Collections 类的静态方法 unmodifiableSet(),
		// 使得返回的集合被限制是不可修改的,否则抛出
		// UnsupportedOperationException 不可操作异常
		return (Collections.unmodifiableSet(this.courses));
	}
	
	public void addCourse(Course course) {
		this.courses.add(course);
	}
	
	public void removeCourse(Course course) {
		if(this.courses.contains(course)) {
			this.courses.remove(course);
		}
	}
}


 

哈…就是因为看了《重构》这本经典,我才第一次得知 Collections 类中 unmodifiableSet() 这一系列保证集合内容不被修改的方法。而我之前不理解《31天重构》第一篇文章中的是:它使用的是 C# 代码例子,对此用了枚举 IEnumerable 来实现,而我不懂 C# ,呼…幸好《重构》是用 Java 讲述的,里面花了整整7页来讲述清楚“封装集合”这一重构方式的动机、做法,很详细,大家也可以看看。