- 浏览: 230332 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
飞出四季做的茧:
只是转移了恶心的switch吧,并没有去除掉
java 代码重构-第一章(使用策略模式,把恶心的switch代码去掉...) 一 -
niqingyang:
https://www.cnblogs.com/xueduan ...
百度搜索url编码解密(url encode decode) -
niqingyang:
function urldecode(str, charset ...
百度搜索url编码解密(url encode decode) -
ttdeye:
private Jedis getJedis(){if(jed ...
spring 结合 Redis 例子,简单入门例子 -
adair_java:
最近手机baidu,搜索关键字编码好像加密了比如这个:http ...
各搜索引擎referer关键字,编码
重构小提示:重构技术系以微小的步伐修改程序。如果你犯下错误,很容易便可发现它。
上一篇文章:java 代码重构-第一章(分解并重组statement())
下一篇文章:java 代码重构-第一章(提炼代码)
上次重构了statement(),类看起来,感觉舒服了很多是吧?那下面我们再一步步的做下去...
现在,我已经把原本的函数分为两块,可以分别处理它们。我不喜欢amountFor() 内的某些变量名称,现在是修改它们的时候。
下面是原本的代码。
private int amountFor(Rental each) { // 计算一笔租片费。 int thisAmount = 0; switch (each.getMovie().getPriceCode()) { case Movie.REGULAR: // 普通片 thisAmount += 2; if (each.getDaysRented() > 2) thisAmount += (each.getDaysRented() - 2) * 1.5; break; case Movie.NEW_RELEASE: // 新片 thisAmount += each.getDaysRented() * 3; break; case Movie.CHILDRENS: // 儿童。 thisAmount += 1.5; if (each.getDaysRented() > 3) thisAmount += (each.getDaysRented() - 3) * 1.5; break; } return thisAmount; }
下面是易名后的代码:
private double amountFor(Rental aRental) { // 计算一笔租片费。 double result = 0; switch (aRental.getMovie().getPriceCode()) { case Movie.REGULAR: // 普通片 result += 2; if (aRental.getDaysRented() > 2) result += (aRental.getDaysRented() - 2) * 1.5; break; case Movie.NEW_RELEASE: // 新片 result += aRental.getDaysRented() * 3; break; case Movie.CHILDRENS: // 儿童。 result += 1.5; if (aRental.getDaysRented() > 3) result += (aRental.getDaysRented() - 3) * 1.5; break; } return result; }
下面是重构后,整个类的代码
package com.mkfree.refactoring.shap1; import java.util.Enumeration; import java.util.Vector; /** * 顾客 * * @author hk * * 2012-12-25 下午10:59:03 */ public class Customer { private String name; private Vector<Rental> rentals = new Vector<>(); public Customer(String name) { this.name = name; } /** * 添加 * * @param rental */ public void addRentals(Rental rental) { rentals.add(rental); } public String getName() { return name; } /** * 通计清单 * * @return */ public String statement() { double totalAmount = 0;// 合计 int frequentRentePoints = 0; Enumeration<Rental> enu_rentals = rentals.elements(); String result = "Rental Record for " + this.getName() + " \n"; while (enu_rentals.hasMoreElements()) { double thisAmount = 0; Rental each = enu_rentals.nextElement(); thisAmount = amountFor(each);// 计算一笔租片费 frequentRentePoints++; if ((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) && each.getDaysRented() > 1) { frequentRentePoints++; } result += "\t" + each.getMovie().getTitle() + "\t" + String.valueOf(thisAmount) + "\n"; totalAmount += thisAmount; } result += "Amount owed is " + String.valueOf(totalAmount) + "\n"; result += "You earned " + String.valueOf(frequentRentePoints) + " frequent renter points"; return result; } /** * 把计算一笔租片 * * @param each * @return */ private double amountFor(Rental aRental) { // 计算一笔租片费。 double result = 0; switch (aRental.getMovie().getPriceCode()) { case Movie.REGULAR: // 普通片 result += 2; if (aRental.getDaysRented() > 2) result += (aRental.getDaysRented() - 2) * 1.5; break; case Movie.NEW_RELEASE: // 新片 result += aRental.getDaysRented() * 3; break; case Movie.CHILDRENS: // 儿童。 result += 1.5; if (aRental.getDaysRented() > 3) result += (aRental.getDaysRented() - 3) * 1.5; break; } return result; } }
易名之后我需要重新编译并测试,确保没有破坏任何东西。
更改变量名称是值得的行为吗?绝对值得。好的代码应该清楚表达出自己的功能,变量名称是代码清晰的关键。如果为了提高代码的清晰度,需要修改某些东西的名字,大胆去做吧。
重构小提示:任何一个傻瓜都能写出计算机可以理解的代码。惟有写出人类容易理解的代码,才是优秀的程序员。
代码应该表现自己的目的,这一点非常重要。阅读代码的时候,我经常进行重构。这样,随着对程序的理解逐渐加深,我也就不断地把这些理解嵌入代码中,这么一来才不会遗忘我曾经理解的东西。
搬移「金额计算」代码
观察amountFor() 时,我发现这个函数使用了来自Rental class 的信息,却没有使 用来自Customer class 的信息。
class Customer... private double amountFor(Rental aRental) { double result = 0; switch (aRental.getMovie().getPriceCode()) { case Movie.REGULAR: result += 2; if (aRental.getDaysRented() > 2) result += (aRental.getDaysRented() - 2) * 1.5; break; case Movie.NEW_RELEASE: result += aRental.getDaysRented() * 3; break; case Movie.CHILDRENS: result += 1.5; if (aRental.getDaysRented() > 3) result += (aRental.getDaysRented() - 3) * 1.5; break; } return result; }
这立刻使我怀疑它是否被放错了位置。绝大多数情况下,函数应该放在它所使用的数据的所属object(或说class)内,所以amountFor() 应该移到Rental class 去。为了这么做,我要运用Move Method。首先把代码拷贝到Rental class 内, 调整代码使之适应新家,然后重新编译。像下面这样。
class Rental... double getCharge() { double result = 0; switch (getMovie().getPriceCode()) { case Movie.REGULAR: result += 2; if (getDaysRented() > 2) result += (getDaysRented() - 2) * 1.5; break; case Movie.NEW_RELEASE: result += getDaysRented() * 3; break; case Movie.CHILDRENS: result += 1.5; if (getDaysRented() > 3) result += (getDaysRented() - 3) * 1.5; break; } return result; }
在这个例子里,「适应新家」意味去掉参数。此外,我还要在搬移的同时变更函数名称。
现在我可以测试新函数是否正常工作。只要改变Customer.amountFor() 函数内容,使它委托(delegate)新函数即可。
class Customer... private double amountFor(Rental aRental) { return aRental.getCharge(); }
好了下面是三个类的最终代码
Rental 类
package com.mkfree.refactoring.shap1; /** * 租凭 * * @author hk * * 2012-12-25 下午10:57:00 */ public class Rental { private Movie movie; private int daysRented; public Rental(Movie movie, int daysRented) { this.movie = movie; this.daysRented = daysRented; } public Movie getMovie() { return movie; } public int getDaysRented() { return daysRented; } double getCharge() { double result = 0; switch (getMovie().getPriceCode()) { case Movie.REGULAR: result += 2; if (getDaysRented() > 2) result += (getDaysRented() - 2) * 1.5; break; case Movie.NEW_RELEASE: result += getDaysRented() * 3; break; case Movie.CHILDRENS: result += 1.5; if (getDaysRented() > 3) result += (getDaysRented() - 3) * 1.5; break; } return result; } }
Customer 类
package com.mkfree.refactoring.shap1; import java.util.Enumeration; import java.util.Vector; /** * 顾客 * * @author hk * * 2012-12-25 下午10:59:03 */ public class Customer { private String name; private Vector<Rental> rentals = new Vector<>(); public Customer(String name) { this.name = name; } /** * 添加 * * @param rental */ public void addRentals(Rental rental) { rentals.add(rental); } public String getName() { return name; } /** * 通计清单 * * @return */ public String statement() { double totalAmount = 0;// 合计 int frequentRentePoints = 0; Enumeration<Rental> enu_rentals = rentals.elements(); String result = "Rental Record for " + this.getName() + " \n"; while (enu_rentals.hasMoreElements()) { double thisAmount = 0; Rental each = enu_rentals.nextElement(); thisAmount = each.getCharge();// 计算一笔租片费 frequentRentePoints++; if ((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) && each.getDaysRented() > 1) { frequentRentePoints++; } result += "\t" + each.getMovie().getTitle() + "\t" + String.valueOf(thisAmount) + "\n"; totalAmount += thisAmount; } result += "Amount owed is " + String.valueOf(totalAmount) + "\n"; result += "You earned " + String.valueOf(frequentRentePoints) + " frequent renter points"; return result; } }
Movie 类
package com.mkfree.refactoring.shap1; /** * 电影类 * @author hk * * 2012-12-25 下午10:55:14 */ public class Movie { public static final int CHILDRENS = 2; public static final int REGULAR = 0; public static final int NEW_RELEASE = 1; private String title; private int priceCode; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public int getPriceCode() { return priceCode; } public void setPriceCode(int priceCode) { this.priceCode = priceCode; } }
现在我可以编译并测试,看看有没有破坏了什么东西。
做完这些修改之后(图1.3),下一件事就是去掉旧函数。编译器会告诉我是否我漏掉了什么。然后我进行测试,看看有没有破坏什么东西。
本文章来自:http://blog.mkfree.com/posts/21
发表评论
-
springMvc 注解配置例子(hello world)
2013-02-21 10:53 2757oyhk 学习笔记 用spring mvc 已经有一段时间 ... -
Spring Data MongoDB 去掉_class属性字段
2013-02-08 10:03 12637oyhk 学习笔记 Spring Dat ... -
springMvc 三种接收客户端参数方法
2013-02-04 12:23 2507oyhk学习笔记springMvc 三种接收客户端参数方法 ... -
spring MongoDB 集成(分页)
2013-01-26 08:42 15162oyhk 学习笔记 spring MongoDB 集成(分 ... -
spring MongoDB 集成crud操作(简单封装)
2013-01-23 08:35 7627oyhk 学习笔记 这两 ... -
elasticsearch结合spring springmvc jest 使用做成WEB架构
2013-01-17 12:16 5244oyhk 学习笔记 上一篇文章,说到了先利用jest ju ... -
elasticsearch RESTful搜索引擎-(java jest 使用[入门])
2013-01-14 10:01 21187oyhk学习笔记 elasticsearch简称ES ... -
eclispe freemarker ide 插件安装
2013-01-12 11:44 2299oyhk学习笔记 由于本网站(http://blog. ... -
elasticsearch RESTful搜索引擎-安装
2013-01-11 09:53 1811oyhk 学习笔记... 1.首先下载e ... -
elasticsearch RESTful搜索引擎-简介
2013-01-10 11:31 1683oyhk学习笔记 搜索了一些资料...关于elasti ... -
java把html标签字符转普通字符(反转换成html标签)
2013-01-09 08:28 13531oyhk 学习笔记 下面是java把html标签字符转 ... -
spring 结合 Redis 例子,简单入门例子
2013-01-07 09:25 11287oyhk 学习笔记 好了费话不多说了,介绍下sprin ... -
java 代码重构-第一章(使用策略模式,把恶心的switch代码去掉...) 二
2013-01-07 09:13 2976上一篇文章:java 代码重构-第一章(使用策略模式,把 ... -
java 代码重构-第一章(使用策略模式,把恶心的switch代码去掉...) 一
2013-01-06 09:49 5740上一篇文章:java 代码重构-第一章(终于…我们来到继 ... -
java 代码重构-第一章(终于…我们来到继承(Inheritance))
2013-01-05 09:18 1727上一篇文章:java 代码重构-第一章(运用多态(Pol ... -
java 代码重构-第一章(运用多态(Polymorphism)取代与价格相关的条件逻辑)
2013-01-04 18:40 2042上一篇文章:java 代码重 ... -
java 代码重构-第一章(提炼代码)
2013-01-04 01:39 1095上篇文章说了,类做回自己的事 上一篇文章:jav ... -
java 代码重构-第一章(去除临时变量)
2013-01-04 01:33 1191上一篇文章:java 代码重 ... -
java 代码重构-第一章(分解并重组statement())
2012-12-28 11:34 1294上一篇文章:java 代码重构-第一章(起点) 下一篇 ... -
java 代码重构-第一章(起点)
2012-12-27 12:57 1540oyhk 学习笔记 对于重构,大家应该都一些认识了吧. ...
相关推荐
第1章 重构,第一个案例 1 1.1 起点 1 1.2 重构的第一步 7 1.3 分解并重组statement() 8 1.4 运用多态取代与价格相关的条件逻辑 34 1.5 结语 52 第2章 重构原则 53 2.1 何谓重构 53 2.2 为何重构 ...
第1章 重构,第一个案例 1.1 起点 1.2 重构的第一步 1.3 分解并重组Statemen 1.4 运用多态取代与价格相关的条件逻辑 1.5 结语 第2章 重构原则 2.1 何谓重构 2.2 为何重构 2.3 何时重构 2.4 怎么对经理说 2.5 重构的...
#### 第2章:代码重构的方法 **2.1 重构的基本概念** - **提炼函数**:将函数的一部分代码抽取出来,形成一个新的独立函数。 - **搬移字段**:将一个类中的字段移动到另一个类中。 - **封装类**:为类中的字段和...
- 第一章“代码质量”讨论了代码质量的重要性,包括可读性、可维护性和可扩展性。 - 第二章“规划重构”讲述了如何在项目早期进行代码结构的规划,以及如何通过重构来改进代码。 - 第三章“设计原则”介绍了 ...
总结来说,"Java第9章 管理类文件含源代码"这一主题涵盖了Java类加载机制、类路径配置、源代码管理和调试等多个方面。通过研究提供的源代码,开发者可以更好地理解和实践这些概念,从而在实际项目中更有效地管理类...
#### 第一章:简介 **代码重构与性能优化概述** - **代码重构**:是指在不改变软件外部行为的前提下,对内部结构进行调整,以提高代码质量的过程。这通常涉及到对代码结构的改善、减少冗余、提高可读性和可维护性...
木书是·木重构指南( guide to refacaoring ),为专业程序员而写。我的目的是告诉你如何以一种可控制且高效率的方式进行重构。你将学会这样的重构方式:不...我把最后一章〔第15章)留给重构技术的顶尖大师,Kent Beck.
**第一章 综述** 代码审查是软件开发流程中的一个环节,它涉及同行对代码进行检查,以找出潜在的缺陷、不一致性和优化空间。在Java项目中,这通常包括对命名规范、代码格式、性能影响、系统稳定性和编程错误等方面...
本章介绍的内容还包括如何安装和使用Xtext框架,以及在Eclipse中创建第一个DSL示例。Xtext利用了Eclipse平台强大的插件和扩展机制,提供了对DSL的全方位支持,包括语法定义、语法高亮、代码补全、错误检查、代码重构...
Java代码规范是软件开发过程中不可或缺的一部分,它不仅有助于提高代码的可读性和可维护性,还能促进团队协作,确保项目的一致性和质量。以下是对给定文件中的几个关键章节进行的详细解读,涵盖了一般规则、格式规范...
这是java15本必读读物的第三本书,重构----改善既有代码的设计,扫描版,找了很久呢,至于第一本编程思想太大了没法上传,第二本agile java只有前四章,喜欢的还是买实物吧
【Java测试驱动开发第5章】是关于使用TDD(测试驱动开发)方法在Java环境中进行软件设计的一个章节。TDD是一种敏捷开发实践,强调先编写测试,再编写实现代码,以此来确保代码质量并降低维护成本。在这个章节中,...
6. 在生成的类文件中,编写第一个Java程序的标准输出语句:`System.out.println("Hello, World!");`。 7. 运行程序,通过点击工具栏中的运行按钮或右键选择“Run As”,选择“Java Application”来运行程序。 8. ...
3.6 MyEclipse中的Java代码重构支持 59 3.6.1 Java元素重命名 59 3.6.2 Java元素移动 60 3.6.3 Java元素复制 61 3.7 本章小结 61 第4章 Java开发的版本控制及SVN 62 4.1 版本控制与SVN 62 4.2 SVN服务器的安装与配置...
第一章:MyEclipse简介 这一章主要介绍了MyEclipse的基本概念,它是一款强大的Java集成开发环境(IDE),支持多种开源技术,如Java、J2EE、Web、AJAX等。此外,还讨论了MyEclipse相对于其他IDE的优势,以及如何下载...
本课程“数据结构:Java语言”第一章主要探讨了数据结构和对象的基础,并引入了一个关键概念——预条件(preconditions)和后条件(postconditions),这对于理解和编写高质量的代码至关重要。 预条件和后条件是...
第一版以OOP为主 针对书本的核心部分6-11章做了思维导图可视化。 突然发现第二版上个月上市,直接下单了精装版,把这个坑填完我就自己去读第二版了哈哈 Link 第二版安利 为什么决定再版《重构》? 虽然这本书已经...
在第一章“初识Java”中,我们将更深入地学习Java的基本语法,包括变量、运算符、流程控制语句(如if、for、while)以及数组。此外,我们还会探索Eclipse的更多功能,如代码自动完成、重构和错误检查,以提高开发...
《精通Eclipse(第二版9-23章)光盘源代码》涵盖了Eclipse IDE的高级使用技巧和开发实践,是深入理解并掌握Eclipse这一强大开发工具的重要资源。源代码包含了从第9章到第23章的全部示例项目,旨在帮助读者通过实际操作...