引子
过度设计,是指代码的灵活性和复杂性超出所需。他们之所以这样做,是希望今天就把方案设计得更加灵活、更复杂,以适应明天的需求。如果预计中的需求分配不会成为现实,浪费的将是宝贵的时间和金钱。为了避免这一问题,分头负责系统的各个部分。但是每个人都在自己的小天地里工作,很少看别处代码是否已经完成了自己需要的功能,最后产生大量的重复代码。
模式万灵药,模式代表的是一种灵活、精妙,非常优雅的面向对象设计方法。模式的强大容易使人对简单的代码编写方式视而不见。把精力放在短小、简单和直截了当的代码上,可以使你减少过度设计。
设计不足,这个比过度设计要常见得多。产生原因有以下几种:
- 程序员没有时间,没有抽出时间,或者时间不允许重构。
- 程序员在好的软件设计方面知识不足。
- 程序员被要求在既有系统中快速地添加新功能。
- 程序员补充被迫同时进行太多的项目。
长期的设计不足,可能造成如下后果:
- 系统的1.0版本很快就交付了,但是代码质量很差。
- 系统的2.0版本也交付了,但质量低劣的代码使我们慢了下来。
- 在企图交付未来版本时,随着劣质代码的倍增,开发也越来越慢,最后人们对系统、程序员乃至使大学陷于这种境地的整个过程都失去了信心。
- 到了4.0版或者之后,我们意识到这样肯定不行,开始考虑推倒重来。
测试驱动和持续重构,两个实践能帮助降低过度设计和设计不足的几率。
演进式设计,关于软件设计的资料更多的集中在讲授优秀的解决方案上,而对于这些解决方案的演变过程不够重视。演变所得到的设计结构虽然有些帮助,但是不知道设计如何发展而来的,在一下项目中你就很可能错误的应用,或者陷入过度设计的误区。
了解优秀软件设计的演变过程比学习优秀设计本身更有价值。
Extract Method
Turn the fragment into a method whos name explains the purpose of the method.
将这段代码放入一个独立的方法中,让方法名来解释方法的用途。
void printOwing(double amount) {
printBanner();
// print details
System.out.println("name" + _name);
System.out.println("amount" + _amount);
}
void printOwing(double amount) {
printBanner();
printDetails(amount);
}
void printDetails(double amount) {
System.out.println("name" + _name);
System.out.println("amount" + _amount);
}
Inline Method
Put the method's body into the body of its callers and remove the method.
int getRating() {
return (moreThanFiveLateDeliveries()) ? 2 : 1;
}
boolean moreThanFiveLateDeliveries() {
return _numberOfLateDeliveries > 5;
}
int getRating() {
return (_numberOfLateDeliveries > 5) ? 2 : 1;
}
InlineTemp
double basePrice = anOrder.basePrice();
return (basePrice > 1000);
return (anOrder.basePrice() > 1000);
Replace Temp with Query
public double getPrice () {
double basePrice = _quantity * _itemPrice;
if (basePrice > 1000)
return basePrice * 0.95;
else
return basePrice * 0.98;
}
public double getPrice () {
if (basePrice() > 1000)
return basePrice() * 0.95;
else
return basePrice() * 0.98;
}
double basePrice() {
return _quantity * _itemPrice;
}
Introduce Explaining Variable
if ((platform.toUpperCase().indexOf("MAC") > -1)
&& browser.toUpperCase().indexOf("IE") > -1
&& wasInitialized() && resize > 0) {
// do something
}
final boolean isMacOs = platform.toUpperCase().indexOf("MAC") > -1;
final boolean isIEBrowser = browser.toUpperCase().indexOf("IE") > -1;
final boolean wasResized = resize > 0;
if (isMacOs && isIEBrowser && wasInitialized() && wasResized) {
// do something
}
Split Temporary Variable
double temp = 2 * (_height + _width);
System.out.println(temp);
temp = _height * _width;
System.out.println(temp);
final double perimeter = 2 * (_height + _width);
System.out.println(perimeter);
final double area = _height * _width;
System.out.println(area);
Remove Assignments to Parameters
int discount(int inputVal, int quantity, int yearToDate) {
if (inputVal > 50)
inputVal -= 2;
if (quantity > 100)
inputVal -= 1;
if (yearToDate > 10000)
inputVal -= 4;
return inputVal;
}
int discount(int inputVal, int quantity, int yearToDate) {
int result = inputVal;
if (inputVal > 50)
result -= 2;
if (quantity > 100)
result -= 1;
if (yearToDate > 10000)
result -= 4;
return result;
}
Replace Method with Method Object
class Account {
int gamma(int inputVal, int quantity, int yearToDate) {
int importantValue1 = (inputVal * quantity) + dalta();
int importantValue2 = (inputVal * yearToDate) + 100;
if ((yearToDate - importantValue1) > 100)
importantValue2 -= 20;
int importantValue3 = importantValue2 * 7;
// and so on
return importantValue3 - 2 * importantValue1;
}
}
class Account {
int gamma(int inputVal, int quantity, int yearToDate) {
return new Gamma(this, inputVal, quantity, yearToDate).compute();
}
}
class Gamma {
private Account _account;
private int inputVal;
private int quantity;
private int yearToDate;
public Gamma(Account _account, int inputVal, int quantity, int yearToDate) {
this._account = _account;
this.inputVal = inputVal;
this.quantity = quantity;
this.yearToDate = yearToDate;
}
int compute() {
int importantValue1 = (inputVal * quantity) + _account.dalta();
int importantValue2 = (inputVal * yearToDate) + 100;
if ((yearToDate - importantValue1) > 100)
importantValue2 -= 20;
int importantValue3 = importantValue2 * 7;
// and so on
return importantValue3 - 2 * importantValue1;
}
}
Substitute Algorithm
String foundPerson(String[] people) {
for (int i = 0; i < people.length; i++) {
if (people[i].equals("Don")) {
return "Don";
}
if (people[i].equals("Jonh")) {
return "Jonh";
}
if (people[i].equals("Kent")) {
return "Kent";
}
}
return "";
}
String foundPerson(String[] people) {
List<String> candidates = Arrays.asList(
new String[] { "Don", "Jonh", "Kent" });
for (int i = 0; i < people.length; i++) {
if (candidates.contains(people[i]))
return people[i];
}
return "";
}
……
分享到:
相关推荐
通过对以上案例的学习,我们不仅了解了重构的基本原则和实践方法,还深入探讨了如何通过具体的编码技巧来提高代码质量和系统的整体性能。这些知识对于每一位软件工程师而言都是非常宝贵的,无论是初学者还是资深...
重构是软件开发过程中的一个重要环节,它涉及到对现有代码的改进,目的是为了提高代码的可读性、可维护性和设计质量,而不改变其外部行为。本文主要围绕重构的关键概念、原则、时机以及面临的挑战展开讨论。 首先,...
本文主要讨论了如何通过重构来优化代码,避免将集合的全部操作暴露给调用者,以提高代码的安全性和可维护性。 在原始代码中,`Order` 类公开了一个 `IList<OrderLine>` 类型的属性 `OrderLines`,这允许外部代码对...
.NET 快速重构学习笔记是针对开发者提升代码质量和可维护性的重要指南。重构是一个系统性的过程,旨在改善软件设计,优化代码结构,而不改变其外在行为。在.NET开发环境中,重构是不可或缺的技能,它可以帮助开发者...
- "31天重构学习笔记"可能提供了每日重构技巧和案例,帮助深入理解重构过程。 - "Java重构示例"系列文档可能展示了Java代码重构的具体步骤和实践。 - "SVN搭建和使用手册"及"SVN中文教程"提供了关于SVN的详细指南...
《31天重构系列笔记》是一本专注于C#编程语言重构技术的教程,该资源以免费高清PDF的形式提供。重构是软件开发过程中的一种重要实践,它旨在改进代码结构,提高可读性和可维护性,而不会改变外部行为。在31天的时间...
### Eclipse开发学习笔记知识点解析 #### 一、Eclipse工作台(Workbench) Eclipse工作台是Eclipse提供的集成开发环境的核心部分,旨在为开发者创建一个无缝集成的工具集,以便于管理和导航工作空间资源。它是开发...
《重构》是一本深入探讨软件开发过程中的代码优化与改进的经典著作。重构,简单来说,是在不改变软件外部行为的前提下,对其内部结构进行改进,以提高代码的可读性、可维护性和可扩展性。这一过程并非依赖于个人天赋...
《JSP & Servlet学习笔记(第2版)》是作者多年来教学实践经验的总结,...《JSP & Servlet学习笔记(第2版)》以“微博”项目贯穿全书,将JSP & Servlet技术应用于实际项目开发之中,并使用重构方式来改进应用程序架构。
**Eclipse 开发学习笔记** Eclipse是一款强大的集成开发环境(IDE),主要用于Java应用程序的开发,但通过插件也可以支持其他编程语言,如C++, Python等。这份《Eclipse开发学习笔记》是针对想要深入理解和掌握...
本学习笔记旨在深入解析JDK 8的关键特性,帮助初学者快速掌握这一版本的核心知识。 1. **lambda表达式**:JDK 8引入了lambda表达式,简化了函数式编程。它允许将匿名函数作为方法参数,或者用作方法返回值。Lambda...
《重构笔记》主要探讨的是软件开发过程中的一个重要实践——重构,它是提高代码质量、可维护性和...通过深入阅读这份文档,开发者可以学习如何在实践中提升自己的重构能力,从而打造出更加优雅、易于维护的软件系统。
### Spring Boot 学习笔记概览 #### 一、Spring 的发展历程 1. **Spring 1.x 时代:** - 在Spring框架发展的初期(即Spring 1.x时代),主要采用XML作为配置文件来管理Bean的声明周期。这种方式在项目规模较小的...
《重构:改善既有代码的设计(第2版)》是一本由马丁·福勒(Martin Fowler)编著的经典软件工程书籍,...通过学习和实践书中的重构技巧,我们可以更好地理解和改善我们的代码,从而创造出更加健壮、可维护的软件系统。
### ActiveMQ学习笔记知识点梳理 #### 一、ActiveMQ简介 **定义:** - **ActiveMQ**是由Apache出品的一款功能强大的开源消息中间件。作为消息队列(Message Queue,简称MQ)的一种,它主要用来在分布式系统之间...
这篇学习笔记将引导新手入门,通过创建第一个简单的案例来了解Android Studio的基本操作。 首先,让我们了解一下Android Studio的核心功能。它基于IntelliJ IDEA,具备代码自动补全、重构、调试等强大的开发特性。...
前端Bootstrap+Es6+vue学习笔记 Bootstrap 框架是一种基于 HTML/CSS/JS 的开源框架,由 Twitter 公司的两名技术工程师研发。其主要特点包括: 1. 跨设备跨浏览器:Bootstrap 支持多种设备和浏览器,可以在不同的...
### C#学习笔记知识点解析 #### 面向对象编程的理解 标题中提到的“面向对象是本本主义、洁癖的体现”这句话反映了一种对面向对象编程(Object-Oriented Programming, OOP)的看法。面向对象编程是一种程序设计范式...