重构 改善既有代码的设计_如何写出让同事膜拜的漂亮代码?

9524b2a4319db9dcaec439a44c0132e9.png

33d7744941eb7e092469b0ba2f573606.png
JAVA交流群:8515318105

“代码千万行,注释第一行;编程不规范,同事两行泪”;"道路千万条,安全第一条。代码不规范,亲人两行泪。"在技术圈广为盛传,可见代码不规范让程序员们是多么的头痛。

如何让你的代码整洁而优雅?如何写出让同事膜拜的漂亮代码?

01何谓重构

重构(名词):对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。

重构与性能优化有很多相似之处:两者都需要修改代码,并且两者都不会改变程序的整体功能。两者的差别在于其目的:重构是为了让代码“更容易理解,更易于修改”。这可能使程序运行得更快,也可能使程序运行得更慢。在性能优化时,我只关心让程序运行得更快,最终得到的代码有可能更难理解和维护,对此我有心理准备。

02两顶帽子

Kent Beck提出了“两顶帽子”的比喻。使用重构技术开发软件时,我把自己的时间分配给两种截然不同的行为:添加新功能和重构。

添加新功能时,我不应该修改既有代码,只管添加新功能。通过添加测试并让测试正常运行,我可以衡量自己的工作进度。

重构时我就不能再添加功能,只管调整代码的结构。此时我不应该添加任何测试(除非发现有先前遗漏的东西),只在绝对必要(用以处理接口变化)时才修改测试。

03为何重构

我不想把重构说成是包治百病的万灵丹,它绝对不是所谓的“银弹”。不过它的确很有价值,尽管它不是一颗“银弹”,却可以算是一把“银钳子”,可以帮你始终良好地控制自己的代码。重构是一个工具,它可以(并且应该)用于以下几个目的。

  • 重构改进软件的设计
  • 重构使软件更容易理解
  • 重构帮助找到bug
  • 重构提高编程速度

04何时重构

在我编程的每个小时,我都会做重构。有几种方式可以把重构融入我的工作过程里。

  • 预备性重构:让添加新功能更容易
  • 帮助理解的重构:使代码更易懂
  • 捡垃圾式重构
  • 有计划的重构和见机行事的重构
  • 长期重构
  • 复审代码时重构
  • 何时不应该重构

05重构的挑战

每当有人大力推荐一种技术、工具或者架构时,我总是会观察这东西会遇到哪些挑战,毕竟生活中很少有晴空万里的好事。你需要了解一件事背后的权衡取舍,才能决定何时何地应用它。

我认为重构是一种很有价值的技术,大多数团队都应该更多地重构,但它也不是完全没有挑战的。有必要充分了解重构会遇到的挑战,这样才能做出有效应对。

06重构,第一个示例

在本书第1版中,我使用的示例程序是为影片出租店的顾客打印一张详单。放到今天,很多人可能要问了:“影片出租店是什么?”为了避免过多回答这个问题,我翻新了一下示例,将其包装成一个仍有古典韵味又尚未消亡的现代示例。

设想有一个戏剧演出团,演员们经常要去各种场合表演戏剧。通常客户(customer)会指定几出剧目,而剧团则根据观众(audience)人数及剧目类型来向客户收费。该团目前出演两种戏剧:悲剧(tragedy)和喜剧(comedy)。给客户发出账单时,剧团还会根据到场观众的数量给出“观众量积分”(volume credit)优惠,下次客户再请剧团表演时可以使用积分获得折扣—你可以把它看作一种提升客户忠诚度的方式。

该剧团将剧目的数据存储在一个简单的JSON文件中。

plays.json…

1{
2  "hamlet": {"name": "Hamlet", "type": "tragedy"},
3  "as-like": {"name": "As You Like It", "type": "comedy"},
4  "othello": {"name": "Othello", "type": "tragedy"}
5}

他们开出的账单也存储在一个JSON文件里。

invoices.json…

 1[
 2  {
 3    "customer": "BigCo",
 4    "performances": [
 5      {
 6        "playID": "hamlet",
 7        "audience": 55
 8      },
 9      {
10        "playID": "as-like",
11        "audience": 35
12      },
13      {
14        "playID": "othello",
15        "audience": 40
16      }
17    ]
18  }
19]

下面这个简单的函数用于打印账单详情。

 1function statement (invoice, plays) {
 2  let totalAmount = 0;
 3  let volumeCredits = 0;
 4  let result = `Statement for ${invoice.customer}n`;
 5  const format = new Intl.NumberFormat("en-US",
 6                        { style: "currency", currency: "USD",
 7                          minimumFractionDigits: 2 }).format;
 8  for (let perf of invoice.performances) { 
 9    const play = plays[perf.playID];
10    let thisAmount = 0;
11    switch (play.type) {
12    case "tragedy":
13      thisAmount = 40000;
14      if (perf.audience > 30) {
15        thisAmount += 1000 * (perf.audience - 30);
16      }
17      break;
18  case "comedy":
19      thisAmount = 30000;
20      if (perf.audience > 20) {
21        thisAmount += 10000 + 500 * (perf.audience - 20);
22      }
23      thisAmount += 300 * perf.audience;
24      break;
25    default:
26        throw new Error(`unknown type: ${play.type}`);
27    }
28    // add volume credits
29    volumeCredits += Math.max(perf.audience - 30, 0);
30    // add extra credit for every ten comedy attendees
31    if ("comedy" === play.type) volumeCredits += Math.floor(perf.audience / 5);
32    // print line for this order
33    result += ` ${play.name}: ${format(thisAmount/100)} (${perf.audience} seats)n`;
34    totalAmount += thisAmount;
35  }
36  result += `Amount owed is ${format(totalAmount/100)}n`;
37  result += `You earned ${volumeCredits} creditsn`;
38  return result;
39}

用上面的数据文件(invoices.jsonplays.json)作为测试输入,运行这段代码,会得到如下输出:

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

更多重构手法推荐大家有时间看下这本书,写出更漂亮的代码,京东、当当链接都给你准备好了。

9eecbc197b2b783ccd56a66a20b6206a.png

《重构:改善既有代码的设计(第2版)》作者:马丁·福勒(Martin Fowler)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值