前言

近期上了大神的課,學了滿多重構技巧,還在目瞪口呆慢慢消化吸收中,而手邊又剛好有跟朋友借來的書,決定紀錄一下。

本文

以前常遇到寫了一個 Class 裡面有很多方法,一眼看下去很難理解內容在做甚麼;而在考慮要拆分的時候就可以使用 Extract Class 這個技巧,在一整個 Class 內可以試著尋找可以歸類成一塊的部分,慢慢地進行拆分。

首先按照書上介紹我們先建立 Person 這個類別。

    public class Person
    {
        private string _name;
        private string _officeAreaCode;
        private string _officeNumber;

        public string GetName()
        {
            return this._name;
        }

        public void SetName(string input)
        {
            this._name = input;
        }

        public string GetOfficeAreaCode()
        {
            return this._officeAreaCode;
        }

        public void SetOfficeAreaCode(string input)
        {
            this._officeAreaCode = input;
        }

        public string GetOfficeNumber()
        {
            return this._officeNumber;
        }

        public void SetOfficeNumber(string input)
        {
            this._officeNumber = input;
        }

        public string GetTelePhoneNumber()
        {
            return $"{this._officeAreaCode}{this._officeNumber}";
        }

    }

確保都是正確寫個測試。

    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            var person = new Person();
            person.SetOfficeAreaCode("02");
            person.SetOfficeNumber("2222-2222");

            var telePhoneNumber = person.GetTelePhoneNumber();

            telePhoneNumber.Should().Be("022222-2222");
        }
    }

這邊是在重構前基本的保護措施,為了確保我們的程式碼在更動後仍然會正確的執行。

接著我們可以發現電話相關的部分可以拆分,把跟電話有關的部分搬到一個新建的 TelePhone Class。
這邊 VisualStudio 就沒有甚麼快速的方式可以搬取了,如果是要擷取基底內別可以直接使用 Cirl + . 但這邊不是,而使用 Rider 的朋友就可以快速達成, 可恨R

    public class TelePhone
    {
        private string _officeAreaCode;
        private string _officeNumber;

        public string GetOfficeAreaCode()
        {
            return this._officeAreaCode;
        }

        public string GetOfficeNumber()
        { 
            return this._officeNumber;
        }

        public string GetTelePhoneNumber()
        {
            return $"{this._officeAreaCode}{this._officeNumber}";
        }

        public void SetOfficeAreaCode(string input)
        {
            this._officeAreaCode = input;
        }

        public void SetOfficeNumber(string input)
        {
            this._officeNumber = input;
        }
    }

原先 Person Class 使用到的地方我們改成。

    public class Person
    {
        private string _name;
        private TelePhone _telePhone;

        public Person()
        {
            this._telePhone = new TelePhone();
        }

        public string GetName()
        {
            return this._name;
        }

        public void SetName(string input)
        {
            this._name = input;
        }

        public string GetOfficeAreaCode()
        {
            return this._telePhone.GetAreaCode();
        }

        public string GetOfficeNumber()
        {
            return this._telePhone.GetAreaCode();
        }

        public string GetTelePhoneNumber()
        {
            return this._telePhone.GetTelePhoneNumber();
        }

        public void SetOfficeAreaCode(string input)
        {
            this._telePhone.SetAreaCode(input);
        }

        public void SetOfficeNumber(string input)
        {
            this._telePhone.SetNumber(input);
        }
    }

執行一下測試確保這樣搬沒有出錯

接下來我就可以來修改一下命名,首先 TelePhone Class 中 Office 對它本身來說不太有甚麼意義,我們把它拿掉。

這邊可以使用選取後在 VisualStudio 內快捷鍵 Cirl R + R 。

現在 TelePhone Class 變成

    public class TelePhone
    {
        private string _areaCode;
        private string _number;

        public string GetAreaCode()
        {
            return this._areaCode;
        }

        public string GetNumber()
        { 
            return this._number;
        }

        public string GetTelePhoneNumber()
        {
            return $"{this._areaCode}{this._number}";
        }

        public void SetAreaCode(string input)
        {
            this._areaCode = input;
        }

        public void SetNumber(string input)
        {
            this._number = input;
        }
    }

再執行一下測試確保更名過程沒有任何出錯。

接著回到 Person Class 我們會發現 GetTelePhoneNumber 這個方法有點奇怪。

我們已經知道要拿取的是 TelePhoneNumber 了,在 TelePhone 內的 GetTelePhoneNumber 就顯得有點雞肋。

把它改成

        public string GetTelePhoneNumber()
        {
            return this._telePhone.Get();
        }

改完後一樣執行測試確保一切正常。

參考連結