`
jorwen_fang
  • 浏览: 51644 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

代码重构总结(上篇)

    博客分类:
  • Java
阅读更多

重构手法千变万化,如果你看过《重构_改善既有代码的设计》这本书一定会很有感触,此文我从这本书中挑选个人觉得比较有用的几点,一些我在工作中觉得比较实用的重构手法。

 

(01) - 方法提炼

有句话叫,当你为了给一段代码写注释的时候,你就能考虑把他提炼一下了。 
来看一个实际例子,登录 
配合idea的Refactor->Extract->Method 


原始代码如下:
01.public String login()
02.{
03.//错误信息
04.String error = "";
05.//1 显示验证码框
06.flag = "1";
07.//2 检查用户名密码为空
08.returnInfoBean = new ReturnInfoBean();
09.if (StringUtils.isBlank(custId))
10.{
11.error = "用户名不能为空";
12.}
13.else if (StringUtils.isBlank(custPassword))
14.{
15.error = "登录密码不能为空";
16.}
17.if(StringUtils.isNotBlank(error))
18.{
19.returnInfoBean.setSuccess(false);
20.returnInfoBean.setReturnMessage(error);
21.return "login";
22.}
23. 
24.try
25.{
26.//3 调用恒生登录
27.HsDsApi hsApi = new HsDsApi(";P            003", "integrate/login", LOGGER);
28.hsApi.put("logtype", logtype);
29.hsApi.put("lognumber", custId);
30.hsApi.put("password", custPassword);
31.if (StringUtils.isNotBlank(certificateType)) hsApi.put("certificatetype", certificateType);
32.HsResponse respx = hsApi.callHsApi();
33.returnInfoBean.setSuccess(respx.isSuccess());
34.if (respx.isSuccess())
35.{
36.//3.1 保存用户基本信息存入session
37.String sessionKey = respx.getString("sessionkey");
38.ICTLoginBean lb = new CTLoginBeanImpl();
39.lb.setUserInfo(getUserInfo(sessionKey));
40.lb.setAccountUtil(getAccountUtil(sessionKey));
41.request.getSession().setAttribute(ICTLoginBean.sessionID, lb);
42.}
43.else
44.{
45.//3.2 登陆失败返回错误代码并处理
46.throw new RuntimeException("【" + respx.getCode() + "】" + respx.getMessage());
47.}
48.} catch (Exception r)
49.{
50.//3.3 调用失败
51.error = "系统异常,请稍候再试";
52.LOGGER.error("调用恒生登录失败", r);
53.}
54. 
55.//4 是否登陆成功
56.if (StringUtils.isNotBlank(error))
57.{
58.returnInfoBean.setSuccess(false);
59.returnInfoBean.setReturnMessage(error);
60.return "login";
61.}
62.else
63.{
64.return "first";
65.}
66.}
其中2和3.1提炼到了private方法, 3提炼到了别的类里,因为明显这是个公共方法 
01.public String login()
02.{
03.returnInfoBean = new ReturnInfoBean();
04.returnInfoBean.setSuccess(true);
05.//1 显示验证码框
06.flag = "1";
07. 
08.//2 检查用户名密码为空
09.if (!checkLogin()) return "login";
10. 
11.try
12.{
13.//3 调用恒生登录
14.HsResponse respx = HsCommonAPi.login(logtype, custId, custPassword, certificateType);
15.if (respx.isSuccess())
16.{
17.//3.1 保存用户基本信息存入session
18.saveInfoToSession(respx.getString("sessionkey"));
19.}
20.else
21.{
22.//3.2 登陆失败返回错误代码并处理
23.throw new RuntimeException("【" + respx.getCode() + "】" + respx.getMessage());
24.}
25.}
26.catch (Exception r)
27.{
28.//3.3 调用失败
29.returnInfoBean.setSuccess(false);
30.returnInfoBean.setReturnMessage("系统异常,请稍候再试");
31.LOGGER.error("调用恒生登录失败", r);
32.}
33. 
34.//4 是否登陆成功
35.return returnInfoBean.isSuccess()?"first":"login";
36.}

 

(02) - 分解临时变量

一个变量变用在多个地方,而且每次使用含义都不同,这个时候可以考虑把他分解 


 

重构后 

 

(03) - 以查询取代临时变量

如果一个临时变量在方法里赋值有点复杂,而且可能还会被复用。可以提炼到方法里可以说是第1话的子范例 


 
重构后 


 
 

(04) - 引入解释性变量

不解释自己看例子,目的为了代码有更好地可读性 


重构后 


 
 

(05) - 使代码更简洁

这部分功能,欢迎大家投稿
1.if ( flag == 1 ){
2.return true;
3.}
4.else{
5.return false;
6.}
重构后
1.return flag == 1;

(06) - 尽早结束非正常逻辑

1.if(taskList != null && !taskList.isEmpty()){
2. 
3.//正常逻辑代码
4. 
5.return count;
6.}
重构后
1.int count = 0;
2.if(taskList == null || taskList.isEmpty()){
3.return 0;
4.}
5. 
6.//正常逻辑代码
7. 
8.return count;
除了return,抛出异常也是种结束方式
 

(07) - 满足条件立刻跳出循环

01.public boolean contain(int year, Month month, int day) {
02.boolean found = false;
03.for (IPolyDate date : dateList) {
04.if (date.same(year, month.getMonth(), day)) {
05.found = true;
06.break;
07.}
08.}
09. 
10.return found;
11.}
重构后
01.public boolean contain(int year, Month month, int day) {
02.for (IPolyDate date : dateList) {
03.if (date.same(year, month.getMonth(), day)) {
04.return true;
05.}
06.}
07. 
08.return false;
09.}
不但代码简洁还能提高效率
 

(08) - 使用数据构分离公共逻辑,避免重复(坚持DRY原则)

DRY原则:不要重复粘帖你自己的代码。Don't repeat yourself 

01.public void testGetIntPart() throws Exception {
02.assertEquals("0", digitTransform.getIntPart("0.01");
03.assertEquals("1", digitTransform.getIntPart("1.2");
04.assertEquals("1234", digitTransform.getIntPart("1234");
05.assertEquals("1", digitTransform.getIntPart("1.01");
06.assertEquals("0", digitTransform.getIntPart("0.01");
07.assertEquals("11111", digitTransform.getIntPart("11111");
08.assertEquals("1000", digitTransform.getIntPart("1000.11");
09.}

重构后 

01. public void testGetIntPart() throws Exception {
02.  String[][] cases = new String[][] { { "0.01""0" }, { "1.2""1" },
03."1234""1234" }, { "1.01""1" }, { "0""0" },
04."11111""11111" }, { "1000.11""1000" } };
05. 
06.  for (int i = 0, len = cases.length; i < len; i++) {
07.   assertEquals(cases[1], digitTransform.getIntPart(cases[0]));
08.  }
09. }


(09) - 公共逻辑提炼

01.public int getRemainMinutes(int hour, int minute) {
02.if (this.fromAfterEqual(hour, minute)) {
03.return (toHour * 60 + toMinute) - (fromHour * 60 + fromMinute);
04.else if (this.toAfterEqual(hour, minute)) {
05.return (toHour * 60 + toMinute) - (hour * 60 + minute);
06.}
07.else {
08.return 0//(toHour * 60 + toMinute) - (toHour * 60 + toMinute);
09.}
10.}
重构后
01.private int getMinutes(int startHour, int startMinute, int endHour,
02.int endMinute) {
03.int minutes = 0;
04.minutes = (endHour * 60 + endMinute) - (startHour * 60 + startMinute);
05. 
06.return minutes;
07.}
08. 
09.public int getRemainMinutes(int hour, int minute) {
10.int startHour = toHour;
11.int startMinute = toMinute;
12. 
13.if (this.fromAfterEqual(hour, minute)) {
14.startHour = fromHour;
15.startMinute = fromMinute;
16.else if (this.toAfterEqual(hour, minute)) {
17.startHour = hour;
18.startMinute = minute;
19.}
20. 
21.return this.getMinutes(startHour, startMinute, toHour, toMinute);
22.}
 

(10) - 何时需要何时创建

01.public static Date parseDate(String date) throws ;P arseException {
02.SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
03. 
04.if ((date == null) || (date.equals(""))) {
05.return null;
06.}
07.else {
08.try {
09.return formatter.parse(date);
10.catch (ParseException pe) {
11.throw new ;P arseException(pe.getMessage(), pe.getErrorOffset());
12.}
13.}
14.}
重构后
01.public static Date parseDate(String date) throws ;P arseException {
02.if ((date == null) || (date.equals(""))) {
03.return null;
04.}
05.else {
06.try {
07.SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
08.return formatter.parse(date);
09.catch (ParseException pe) {
10.throw new ;P arseException(pe.getMessage(), pe.getErrorOffset());
11.}
12.}
13.}
 
  • 大小: 3.3 KB
  • 大小: 3.6 KB
  • 大小: 6.8 KB
  • 大小: 13.3 KB
  • 大小: 5.1 KB
  • 大小: 11.2 KB
分享到:
评论

相关推荐

    C#代码重构.docx

    总结,本篇文档涉及了C#编程中的关键重构技巧,包括封装集合以限制集合操作,移动方法以优化代码组织,以及使用面向服务架构来减少系统间的耦合。这些都是提升代码质量,保证软件可维护性的有效策略。在实际开发中,...

    重构你的Rails程式码

    在进行Rails版本升级时,重构代码是一个绝佳的机会。本文将深入探讨为何这是个好时机来进行重构,并提供一系列实用的方法帮助您优化代码。 #### 为什么这是一个好时机重构代码? 1. **信任度提升:** 如果您有足够...

    写出优雅代码(C#)篇[2].

    总结起来,优雅的C#代码需要遵循良好的命名规范,控制方法参数数量,合理使用注释,避免数值硬编码,巧用`string.Empty`,以及适时重构。这些实践不仅提升代码质量,还增强团队间的沟通效率,从而提高整体项目开发的...

    电子科技大学SOPC实验代码以及总结

    这篇文档集包含了电子科技大学唐续老师的SOPC实验代码与总结,为学习者提供了宝贵的实践经验和理论指导。 SOPC技术的核心在于FPGA(Field-Programmable Gate Array),这是一种可重构的数字逻辑器件,可以按照设计...

    OMP压缩感知重构方法

    本篇将深入探讨OMP算法在压缩感知重构中的原理、实现及应用。 一、压缩感知理论基础 压缩感知理论基于两个关键假设:稀疏性和可分解性。稀疏性是指大多数实际信号都可以用较少的非零元素表示,即在某种基下,信号是...

    代码分享基于二阶锥松弛的IEEE33节点配电网故障重构可视化

    - **可视化展示**:在MATLAB界面上,用户可以看到重构后的网络图。其中,红色线条表示被断开的支路,实线代表原有的33个节点间的线路,而虚线则代表了新增的联络线路。 #### 五、案例分析 - **IEEE33节点配电网**...

    C语言初学,近千行代码,word高亮总结,附有富文本下的word语法高亮模板

    这篇总结包含了这些核心知识点,通过近千行的代码实例帮助初学者深入理解C语言。以下是针对内容的详细解释: 1. **字符数组与字符串定义**: - 字符数组`arr1`用于存储整型数值,使用`printf`进行格式化输出。 - ...

    基于设计层次优化的软件自动化重构思考.pdf

    总结来说,这篇论文提供了一种新的视角来处理软件重构问题,特别是从设计层次出发,通过自动化工具和算法实现对软件结构的优化,旨在提高软件的可维护性、可读性和整体性能。这种方法为未来的软件开发和维护提供了有...

    一种高效的写代码方法,亲测可用

    例如,使用代码自动完成功能可以快速输入代码,重构工具可以帮助我们进行代码重构,而调试工具则可以方便地定位和解决问题。学习并熟练掌握IDE的快捷键和定制化设置,能极大地提高开发效率。 在团队协作中,版本...

    我的年终项目总结(2篇)

    标题中的“我的年终项目总结(2篇)”表明这是一份关于作者在过去一年中在IT领域项目经验的总结,可能涵盖了技术应用、项目管理、团队协作等多个方面。结合描述中的博文链接,我们可以推测作者可能在博客中分享了他...

    CS_OMP_omp_博士论文_论文matlab_matlab_重构算法_

    总结起来,这篇以“CS_OMP_博士论文_论文matlab_matlab_重构算法”为主题的压缩包内容,提供了一篇关于压缩感知重构算法——正交匹配追踪算法的matlab仿真代码,旨在帮助读者深入理解OMP算法的原理和实现过程,是...

    《代码之殇》迷你书

    这本书被视为《代码大全》的姊妹篇,承载了作者在微软公司超过十年的工作经验,是微软软件工程师必读之作。它深入探讨了软件开发流程、技术、方法论等多个层面的知识,旨在为软件开发者提供宝贵的经验教训。 首先,...

    代码行数统计小工具.zip

    - **重构指导**:在进行代码重构时,统计工具可以帮助开发者识别哪些部分的代码可能需要重点关注。 4. **注意事项** - **代码质量不完全依赖于行数**:虽然代码行数是评估的一个维度,但代码质量更重要的是结构...

    VC编程经验总结(非常实用!)

    10. **代码重构与设计模式**:遵循面向对象设计原则,运用设计模式(如单例、工厂、观察者等),并进行定期的代码重构,可以保持代码的清晰性和可维护性。 通过阅读“VC编程经验总结.chm”文件,你可以深入学习和...

    jQuery投票征名代码.zip

    本篇文章将详细解析一个名为“jQuery投票征名代码”的项目,该项目利用jQuery 1.4.2版本实现了一个鼠标悬停时动态展示征名释义的效果。这一功能在互动性强的投票系统或在线活动中,能够提供用户友好的体验,增强用户...

    代码统计工具

    本篇文章将详细探讨代码统计工具的功能、重要性以及如何使用SourceCounter这样的工具进行代码统计。 首先,代码统计工具的主要功能包括: 1. 计算总代码行数:这涵盖了源代码文件中的所有可执行语句,包括空格、...

    java编程风格总结

    #### 四、代码重构技巧 **原文摘要:** - **重构的重要性**:重构是提高代码质量和性能的有效手段之一。 - **重构策略**:在重构过程中,应保持原有功能不变的同时优化代码结构;重构之前应对原有代码进行全面测试...

    0代码实现viewcontroller

    5. **代码重构**:定期审查并重构代码,去除冗余和不必要的逻辑。 四、利用`NSObject`增强`UIViewController` `UIViewController`继承自`NSObject`,因此可以利用`NSObject`的一些特性来优化代码,如KVO(Key-Value...

    CS_MP.rar_CS MP matl_CS-MP_MP重构算法_matlab mp2d_压缩感知CS

    本篇文章将深入探讨MP重构算法及其在Matlab环境中的具体实现。 MP重构算法的核心思想是通过迭代的方式寻找信号中最具有代表性的元素,并逐步构建信号的近似解。在每一轮迭代中,算法选择与残差最相关的原子(或基...

Global site tag (gtag.js) - Google Analytics