《重构 改善既有代码的设计(第2版)》读书笔记

一、基本信息 

中文名:《重构 改善既有代码的设计(第2版)》
英文名:《Refactoring improving the design of existing code》

作者:Martin Fowler   作者网站链接:https://martinfowler.com/

        

译者:熊节 林从⽻

         

二、电子书链接

  • https://gausszhou.github.io/refactoring2-zh/
  • https://book-refactoring2.ifmicro.com/

三、书籍结构

本书的重点包含两部分:(1)识别代码中的“坏味道”;(2)重构手法

  • 第一章通过剧院售票结算程序来展示代码如何进行重构
  • 第二章介绍重构的原则
  • 第三章比较出名,介绍了24中代码的坏味道
  • 第四章介绍构建测试体系
  • 第五章介绍重构名录
  • 第六到十二章介绍了61种重构手法

四、第一章简要笔记

1. 示例程序

剧院售票结算程序;基本逻辑如下:

剧名类型
《哈姆雷特》
悲剧
《皆⼤欢喜》
喜剧
《奥塞罗》
悲剧
票价计算⽅式:观众数量x
积分计算⽅式:
悲剧
x <= 30: 40000
x > 30: 40000 + 1000 * (x - 30)
max(x - 30, 0)
喜剧
x <= 20: 30000 + 300 * x
x > 20: 30000 + 300 * x + 10000 + 50 * (x - 20)
max(x - 30, 0) + floor(x / 5)

计算并打印输出票价和积分

function statement(invoice, plays) {
      let totalAmount = 0
      let volumeCredits = 0
      let result = `Statement for ${invoice.customer}\n`
      const format = new Intl.NumberFormat("en-us",
        {
          style: "currency",
          currency: "USD",
          minimumFractionDigits: 2
        }).format

      for (let perf of invoice.performances) {
        const play = plays[perf.playID]
        let thisAmount = 0

        switch (play.type) {
          case "tragedy":
            thisAmount = 40000;
            if (perf.audience > 30) {
              thisAmount += 1000 * (perf.audience - 30)
            }
            break
          case "comedy":
            thisAmount = 30000;
            if (perf.audience > 20) {
              thisAmount += 10000 + 500 * (perf.audience - 20)
            }
            thisAmount += 300 * perf.audience
            break
          default:
            throw new Error(`unknown type: ${play.type}`)
        }

        volumeCredits += Math.max(perf.audience - 30, 0)
        if ("comedy" === play.type)
          volumeCredits += Math.floor(perf.audience / 5)

        result += ` ${play.name}, ${format(thisAmount / 100)} (${perf.audience} seats) \n`

        totalAmount += thisAmount
      }

      result += `Amount owed is ${format(totalAmount / 100)} \n`
      result += `You earned ${volumeCredits} credits\n`
      return result
    }

输入参数:

    let plays = {
      "hamlet": {
        "name": "Hamlet",
        "type": "tragedy"
      },
      "as-like": {
        "name": "As You Like It",
        "type": "comedy"
      },
      "othello": {
        "name": "Othello",
        "type": "tragedy"
      }
    }
    let invoices = [
      {
        "customer": "BigCo",
        "performances": [
          {
            "playID": "hamlet",
            "audience": 55
          },
          {
            "playID": "as-like",
            "audience": 35
          },
          {
            "playID": "othello",
            "audience": 40
          }
        ]
      }
    ]

    let result = statement(invoices[0], plays)

输出结果:

Statement for BigCo
  Hamlet: $650.00 (55 seats)
  As You Like It: $580.00 (35 seats)
  Othello: $500.00 (40 seats)
Amount owed is $1,730.00
You earned 47 credits

从数据结果看:已满足程序要求

若增加两项需求:

  1. 以HTML格式输出结果
  2. 再增加多种戏剧类型

当前的程序便无法满足新的需求,因此需要对代码进行重构。

需求的变化使重构变得必要。如果⼀段代码能正常⼯作,并且不会再被修改,那么完全可以不去重构它
如果你要给程序添加⼀个特性,但发现代码因缺乏良好的结构⽽不易于进⾏更改,那就先重
构那个程序,使其⽐较容易添加该特性,然后再添加该特性。

2. 重构步骤

第一步: 保证修改的代码拥有⼀组可靠的测试,这些测试必须有⾃我检验能⼒;
第二步:发现代码中⼀段⼩的“坏味道”,采用对应重构⼿法进⾏重构;
        举例: 中间switch, 可以采用提炼函数将其提炼出来
        
function statement (invoice, plays) {
  let totalAmount = 0;
  let volumeCredits = 0;
  let result = `Statement for ${invoice.customer}\n`;
  const format = new Intl.NumberFormat("en-US",
                        { style: "currency", currency: "USD",
                          minimumFractionDigits: 2 }).format;
  for (let perf of invoice.performances) {
    const play = plays[perf.playID];
    let thisAmount = 0;

    switch (play.type) {
    case "tragedy":
      thisAmount = 40000;
      if (perf.audience > 30) {
        thisAmount += 1000 * (perf.audience - 30);
      }
      break;
    case "comedy":
      thisAmount = 30000;
      if (perf.audience > 20) {
        thisAmount += 10000 + 500 * (perf.audience - 20);
      }
      thisAmount += 300 * perf.audience;
      break;
    default:
        throw new Error(`unknown type: ${play.type}`);
    }

    // add volume credits
    volumeCredits += Math.max(perf.audience - 30, 0);
    // add extra credit for every ten comedy attendees
    if ("comedy" === play.type) volumeCredits += Math.floor(perf.audience / 5);

    // print line for this order
    result += ` ${play.name}: ${format(thisAmount/100)} (${perf.audience} seats)\n`;
    totalAmount += thisAmount;
  }
  result += `Amount owed is ${format(totalAmount/100)}\n`;
  result += `You earned ${volumeCredits} credits\n`;
  return result;
}

第三步:编译并执⾏测试

重构技术就是以微⼩的步伐修改程序。如果你犯下错误,很容易便可发现它
第四步: 测试通过commit提交
重构的节奏感,每⼀步都保证代码处于编译通过和测试通过的可⼯作状
第五步:循环第二三四步直到重构结果令人满意

五、代码的“坏味道”

待整理.....

  • 12
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值