后端 [Day 9]Refactoring legacy code简介

innersmile · August 12, 2021 · 3 hits

到上一篇文章为止,TDD 中所需具备的基本测试知识,已经告一段落。

接下来要练习的,是重构的手法。

接下来几篇文章,会跟各位读者朋友介绍:

  1. 要怎么找到需要重构的部分
  2. 要怎么让代码会说话
  3. 要怎么与测试结合

这一篇文章则会先介绍,要如何找到代码中需要重构的地方。

上一篇文章:[Day 8] Integration Testing & Web UI Testing
本系列文章专区
@现况
我们所面临的系统状况,通常也就是Legacy Code(提到 Legacy Code,就要顺便介绍一本好书:Working Effectively with Legacy Code),就像下图一样:

图片来源:图片来源:http://www.chancedia.com/?p=41470

就像广告说的一样:「每个 Dev 都喜欢干净的 code,但是又喜欢把 code 弄脏。」脸红

@重构的目的
我们希望可以把杂乱无章的 code,干净整齐的放在它们所属的位置上。

图片来源:http://jung9572002.pixnet.net/blog/post/1733351-%E6%94%B6%E7%B4%8D%E9%81%94%E4%BA%BA

@重构的时机与目标
基本上最适合重构的时机有三类:

  1. Debug 完成后

图片来源:http://awards.gettyimages.com/awards.cfm?selCategory=all&display=photographer&workID=67&photographerID=7&photoID=70&sp\\_sortID=1

  1. 需求异动

图片来源:http://www.lykasal.com/2012/10/cats-that-pester-for-food-could-be.html

  1. 系统有 Bad Smell 的地方

图片来源:http://www.thetorontopost.net/2012/09/smell-test-total-fail-for-rob-ford-in.html

简单的说,就是要修改程序的时候,或是程序很脏的时候,适合重构。

但请记住:「一次只做一件事

@如何找出 Bad Smell
这边的范例,我创建了一个不同物流商会计算出不同运费的网站。

先以 SourceMonitor 为例,来找出系统中复杂度太高的 function,并将它当做我们重构的目标。(SourceMonitor 的介绍,有兴趣的朋友可以看之前这篇文章:[Tool] SourceMonitor - 代码扫瞄

扫描后,按照 Max Complexity 排序,可以看到 Prodcut_v0.aspx.cs,最大复杂度 14,最大深度 5。如下图所示:

再点开详细信息后,可以看到 btnCalculate_Click 这个方法,就是造成最大复杂度与最大深度的原因。如下图所示:

[注] 也可以使用 VS2012/VS2010 的代码度量,来找到复杂度过高的程序

接着,来看一下这个 function 的代码,如下所示:

protected void btnCalculate_Click(object sender, EventArgs e)
{
    if (this.IsValid)
    {
        if (this.drpCompany.SelectedValue == "1")
        {
            this.lblCompany.Text = "黑猫";
            var weight = Convert.ToDouble(this.txtProductWeight.Text);
            if (weight > 20)
            {
                this.lblCharge.Text = "500";
            }
            else
            {
                var fee = 100 + weight * 10;
                this.lblCharge.Text = fee.ToString();
            }
        }
        else if (this.drpCompany.SelectedValue == "2")
        {
            this.lblCompany.Text = "新竹货运";
            var length = Convert.ToDouble(this.txtProductLength.Text);
            var width = Convert.ToDouble(this.txtProductWidth.Text);
            var height = Convert.ToDouble(this.txtProductHeight.Text);

            var size = length * width * height;

            //长 x 宽 x 高(公分)x 0.0000353
            if (length > 100 || width > 100 || height > 100)
            {
                this.lblCharge.Text = (size * 0.0000353 * 1100 + 500).ToString();
            }
            else
            {
                this.lblCharge.Text = (size * 0.0000353 * 1200).ToString();
            }
        }
        else if (this.drpCompany.SelectedValue == "3")
        {
            this.lblCompany.Text = "邮局";

            var weight = Convert.ToDouble(this.txtProductWeight.Text);
            var feeByWeight = 80 + weight * 10;

            var length = Convert.ToDouble(this.txtProductLength.Text);
            var width = Convert.ToDouble(this.txtProductWidth.Text);
            var height = Convert.ToDouble(this.txtProductHeight.Text);
            var size = length * width * height;
            var feeBySize = size * 0.0000353 * 1100;

            if (feeByWeight < feeBySize)
            {
                this.lblCharge.Text = feeByWeight.ToString();
            }
            else
            {
                this.lblCharge.Text = feeBySize.ToString();
            }
        }
        else
        {
            var js = "alert('发生不预期错误,请洽系统管理者');location.href='http://tw.yahoo.com/';";
            this.ClientScript.RegisterStartupScript(this.GetType(), "back", js, true);
        }
    }
}

上面就是一陀摊在角落的 code,一眼望过去,每个字都认识,但却要动脑袋猜测,甚至动手测试才能了解这一段 code 是什么意思。除了难以理解以外,这样嵌套 if 的设计方式,健壮性(robustness)上也相当薄弱。

呈现的画面与功能,如下图所示:

@小结
要重构之前,得先了解重构的目的、意义,以及如何找到需要重构的程序。

期望重构之后,能对原本可以正常运行的结果完全没有影响,但代码因此具备了更高的可读性、扩充性、健壮性等等...

重构的基本原则是:

  1. 创建测试,确保安全
  2. 由小到大,绝不贪心
  3. 适可而止,绝不偏执

由于重构在 TDD 中,也占了很重要的一个角色,所以希望接下来几篇,可以帮助读者手把手的跟着练习一遍,这样看似简单、又像复杂、又没啥弹性的代码,如何从乱七八糟,变成最后一应俱全的健壮程序。

@补充
有读者朋友问到,什么样的代码算的上是 Bad smell?

这边列出笔者工作环境中的门槛值:

  1. 循环复杂度 > 10
  2. 继承深度 > 3
  3. 区块深度 > 4
  4. 相似代码 > 15 行
  5. 综合可维护性指数 < 75

以上,不代表超过标准就一定不好,但就像健康检查报告的指数一样,这些的确是需要被 highlight 出来说明的。

其他静态代码分析的工具与投视频简介,请参考这篇文章:[.NET][Tool] 静态代码分析工具简介


,

沙发
第一次认识 H 大大就是看到那乱乱的房间那张图~~ 真怀念...

,

叫你加就加,叫你改就改...

哈哈哈哈哈哈

No Reply at the moment.
You need to Sign in before reply, if you don't have an account, please Sign up first.