- 浏览: 231076 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
飞出四季做的茧:
只是转移了恶心的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 2767oyhk 学习笔记 用spring mvc 已经有一段时间 ... -
Spring Data MongoDB 去掉_class属性字段
2013-02-08 10:03 12656oyhk 学习笔记 Spring Dat ... -
springMvc 三种接收客户端参数方法
2013-02-04 12:23 2516oyhk学习笔记springMvc 三种接收客户端参数方法 ... -
spring MongoDB 集成(分页)
2013-01-26 08:42 15191oyhk 学习笔记 spring MongoDB 集成(分 ... -
spring MongoDB 集成crud操作(简单封装)
2013-01-23 08:35 7635oyhk 学习笔记 这两 ... -
elasticsearch结合spring springmvc jest 使用做成WEB架构
2013-01-17 12:16 5259oyhk 学习笔记 上一篇文章,说到了先利用jest ju ... -
elasticsearch RESTful搜索引擎-(java jest 使用[入门])
2013-01-14 10:01 21199oyhk学习笔记 elasticsearch简称ES ... -
eclispe freemarker ide 插件安装
2013-01-12 11:44 2303oyhk学习笔记 由于本网站(http://blog. ... -
elasticsearch RESTful搜索引擎-安装
2013-01-11 09:53 1824oyhk 学习笔记... 1.首先下载e ... -
elasticsearch RESTful搜索引擎-简介
2013-01-10 11:31 1694oyhk学习笔记 搜索了一些资料...关于elasti ... -
java把html标签字符转普通字符(反转换成html标签)
2013-01-09 08:28 13546oyhk 学习笔记 下面是java把html标签字符转 ... -
spring 结合 Redis 例子,简单入门例子
2013-01-07 09:25 11293oyhk 学习笔记 好了费话不多说了,介绍下sprin ... -
java 代码重构-第一章(使用策略模式,把恶心的switch代码去掉...) 二
2013-01-07 09:13 2991上一篇文章:java 代码重构-第一章(使用策略模式,把 ... -
java 代码重构-第一章(使用策略模式,把恶心的switch代码去掉...) 一
2013-01-06 09:49 5757上一篇文章:java 代码重构-第一章(终于…我们来到继 ... -
java 代码重构-第一章(终于…我们来到继承(Inheritance))
2013-01-05 09:18 1741上一篇文章:java 代码重构-第一章(运用多态(Pol ... -
java 代码重构-第一章(运用多态(Polymorphism)取代与价格相关的条件逻辑)
2013-01-04 18:40 2053上一篇文章:java 代码重 ... -
java 代码重构-第一章(提炼代码)
2013-01-04 01:39 1124上篇文章说了,类做回自己的事 上一篇文章:jav ... -
java 代码重构-第一章(去除临时变量)
2013-01-04 01:33 1225上一篇文章:java 代码重 ... -
java 代码重构-第一章(分解并重组statement())
2012-12-28 11:34 1322上一篇文章:java 代码重构-第一章(起点) 下一篇 ... -
java 代码重构-第一章(起点)
2012-12-27 12:57 1572oyhk 学习笔记 对于重构,大家应该都一些认识了吧. ...
相关推荐
第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 为何重构 ...
#### 第2章:代码重构的方法 **2.1 重构的基本概念** - **提炼函数**:将函数的一部分代码抽取出来,形成一个新的独立函数。 - **搬移字段**:将一个类中的字段移动到另一个类中。 - **封装类**:为类中的字段和...
第1章 重构,第一个案例 1.1 起点 1.2 重构的第一步 1.3 分解并重组Statemen 1.4 运用多态取代与价格相关的条件逻辑 1.5 结语 第2章 重构原则 2.1 何谓重构 2.2 为何重构 2.3 何时重构 2.4 怎么对经理说 2.5 重构的...
- 第一章“代码质量”讨论了代码质量的重要性,包括可读性、可维护性和可扩展性。 - 第二章“规划重构”讲述了如何在项目早期进行代码结构的规划,以及如何通过重构来改进代码。 - 第三章“设计原则”介绍了 ...
总结来说,"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章的全部示例项目,旨在帮助读者通过实际操作...