- 浏览: 227777 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
飞出四季做的茧:
只是转移了恶心的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 代码重构-第一章(类自己该做自己的事)
- 博客分类:
- java
重构小提示:重构技术系以微小的步伐修改程序。如果你犯下错误,很容易便可发现它。
上一篇文章: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 2704oyhk 学习笔记 用spring mvc 已经有一段时间 ... -
Spring Data MongoDB 去掉_class属性字段
2013-02-08 10:03 12546oyhk 学习笔记 Spring Dat ... -
springMvc 三种接收客户端参数方法
2013-02-04 12:23 2460oyhk学习笔记springMvc 三种接收客户端参数方法 ... -
spring MongoDB 集成(分页)
2013-01-26 08:42 15074oyhk 学习笔记 spring MongoDB 集成(分 ... -
spring MongoDB 集成crud操作(简单封装)
2013-01-23 08:35 7566oyhk 学习笔记 这两 ... -
elasticsearch结合spring springmvc jest 使用做成WEB架构
2013-01-17 12:16 5189oyhk 学习笔记 上一篇文章,说到了先利用jest ju ... -
elasticsearch RESTful搜索引擎-(java jest 使用[入门])
2013-01-14 10:01 21122oyhk学习笔记 elasticsearch简称ES ... -
eclispe freemarker ide 插件安装
2013-01-12 11:44 2258oyhk学习笔记 由于本网站(http://blog. ... -
elasticsearch RESTful搜索引擎-安装
2013-01-11 09:53 1758oyhk 学习笔记... 1.首先下载e ... -
elasticsearch RESTful搜索引擎-简介
2013-01-10 11:31 1631oyhk学习笔记 搜索了一些资料...关于elasti ... -
java把html标签字符转普通字符(反转换成html标签)
2013-01-09 08:28 13472oyhk 学习笔记 下面是java把html标签字符转 ... -
spring 结合 Redis 例子,简单入门例子
2013-01-07 09:25 11238oyhk 学习笔记 好了费话不多说了,介绍下sprin ... -
java 代码重构-第一章(使用策略模式,把恶心的switch代码去掉...) 二
2013-01-07 09:13 2931上一篇文章:java 代码重构-第一章(使用策略模式,把 ... -
java 代码重构-第一章(使用策略模式,把恶心的switch代码去掉...) 一
2013-01-06 09:49 5651上一篇文章:java 代码重构-第一章(终于…我们来到继 ... -
java 代码重构-第一章(终于…我们来到继承(Inheritance))
2013-01-05 09:18 1673上一篇文章:java 代码重构-第一章(运用多态(Pol ... -
java 代码重构-第一章(运用多态(Polymorphism)取代与价格相关的条件逻辑)
2013-01-04 18:40 1988上一篇文章:java 代码重 ... -
java 代码重构-第一章(提炼代码)
2013-01-04 01:39 1011上篇文章说了,类做回自己的事 上一篇文章:jav ... -
java 代码重构-第一章(去除临时变量)
2013-01-04 01:33 1100上一篇文章:java 代码重 ... -
java 代码重构-第一章(分解并重组statement())
2012-12-28 11:34 1204上一篇文章:java 代码重构-第一章(起点) 下一篇 ... -
java 代码重构-第一章(起点)
2012-12-27 12:57 1460oyhk 学习笔记 对于重构,大家应该都一些认识了吧. ...
相关推荐
关于如何重构java代码的。看过好一定很有感触。
第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 重构的...
第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 为何重构55 2.3 何时重构57 2.4 怎么...
第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 为何重构55 2.3 何时重构57 2.4 怎么...
木书是·木重构指南( guide to refacaoring ),为专业程序员而写。我的目的是告诉你如何以一种可控制且高效率的方式进行重构。你将学会这样的重构方式:不...我把最后一章〔第15章)留给重构技术的顶尖大师,Kent Beck.
这是java15本必读读物的第三本书,重构----改善既有代码的设计,扫描版,找了很久呢,至于第一本编程思想太大了没法上传,第二本agile java只有前四章,喜欢的还是买实物吧
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服务器的安装与配置...
第一版以OOP为主 针对书本的核心部分6-11章做了思维导图可视化。 突然发现第二版上个月上市,直接下单了精装版,把这个坑填完我就自己去读第二版了哈哈 Link 第二版安利 为什么决定再版《重构》? 虽然这本书已经...
和函数式编程一书中示例和测验的所有源代码。 您可以在这里购买这本书:或在亚马逊上 所有示例的源代码都可以在目录中找到 第 1 章:Java 8:你为什么要关心? 第 2 章:通过行为参数化传递代码 第 3 章:Lambda ...
和函数式编程一书中示例和测验的所有源代码。 您可以在这里购买这本书:或在亚马逊上 所有示例的源代码都可以在目录中找到 第 1 章:Java 8:你为什么要关心? 第 2 章:通过行为参数化传递代码 第 3 章:Lambda ...
和函数式编程一书中示例和测验的所有源代码。 您可以在这里购买这本书:或在亚马逊上 所有示例的源代码都可以在目录中找到 第 1 章:Java 8:你为什么要关心? 第 2 章:通过行为参数化传递代码 第 3 章:Lambda ...
和函数式编程一书中示例和测验的所有源代码。 您可以在这里购买这本书:或在亚马逊上 所有示例的源代码都可以在目录中找到 第 1 章:Java 8:你为什么要关心? 第 2 章:通过行为参数化传递代码 第 3 章:Lambda ...
同时自己也做了一些扩展使用,修复了源码中的bug。 例如 Java 8 In Action 中的源代码可以在目录中找到: 第 1 章 Java 8:你为什么要关心? 第 2 章 使用行为参数化传递代码 第 3 章 Lambda 表达式 第 4 章 介绍流 ...
和函数式编程一书中示例和测验的所有源代码。 您可以在这里购买这本书:或在亚马逊上 所有示例的源代码都可以在目录中找到 第 1 章:Java 8:你为什么要关心? 第 2 章:通过行为参数化传递代码 第 3 章:Lambda ...
和函数式编程一书中示例和测验的所有源代码。 您可以在这里购买这本书:或在亚马逊上 所有示例的源代码都可以在目录中找到 第 1 章:Java 8:你为什么要关心? 第 2 章:通过行为参数化传递代码 第 3 章:Lambda ...
本书前第5章介绍了演进式数据库开发的基本思想和技术,后6章详细描述了每一类重构,包括结构、数据质量、参照完整性、架构、方法的重构;另外还描述了不属于重构范畴的转换技术。 书中的示例代码是用Java、...
和函数式编程一书中示例和测验的所有源代码。 您可以在这里购买这本书:或在亚马逊上 所有示例的源代码都可以在目录中找到 第 1 章:Java 8:你为什么要关心? 第 2 章:通过行为参数化传递代码 第 3 章:Lambda ...
本书前第5章介绍了演进式数据库开发的基本思想和技术,后6章详细描述了每一类重构,包括结构、数据质量、参照完整性、架构、方法的重构;另外还描述了不属于重构范畴的转换技术。 书中的示例代码是用Java、...