Rental
16 | {
17 | get
18 | {
19 | return this._rentals;
20 | }
21 | }
22 |
23 | public string Name { get; set; }
24 |
25 | public string GetTotalFrequentRenterPoints()
26 | {
27 | throw new NotImplementedException();
28 | }
29 |
30 | public string GetTotalCharge()
31 | {
32 | throw new NotImplementedException();
33 | }
34 | }
35 |
36 | public class Rental
37 | {
38 | public Movie Movie { get; set; }
39 |
40 | public decimal Charge { get; set; }
41 | }
42 |
43 | public class Movie
44 | {
45 | public string Title { get; set; }
46 | }
47 |
48 | public abstract class Statement
49 | {
50 | public string Value(Customer customer)
51 | {
52 | string result = this.HeaderString(customer);
53 | foreach (var rental in customer.Rental)
54 | {
55 | result += this.EachRentalString(rental);
56 | }
57 | result = this.FooterString(customer);
58 | return result;
59 | }
60 |
61 | public abstract string HeaderString(Customer customer);
62 |
63 | public abstract string EachRentalString(Rental rental);
64 |
65 | public abstract string FooterString(Customer customer);
66 | }
67 |
68 | public class TextStatement : Statement
69 | {
70 | public override string FooterString(Customer customer)
71 | {
72 | var result = "Amount owed is" + customer.GetTotalCharge() + "\n";
73 | result += "You earned " + customer.GetTotalFrequentRenterPoints() + "frequent renter points";
74 | return result;
75 | }
76 |
77 | public override string EachRentalString(Rental rental)
78 | {
79 | return rental.Movie.Title + "\t" + rental.Charge + "\n";
80 | }
81 |
82 | public override string HeaderString(Customer customer)
83 | {
84 | return "Rental Record for" + customer.Name + "\n";
85 | }
86 | }
87 |
88 | public class HtmlStatement : Statement
89 | {
90 | public override string FooterString(Customer customer)
91 | {
92 | var result = " You owe " + customer.GetTotalCharge() + "
\n";
93 | result += "On this rental you earned " + customer.GetTotalFrequentRenterPoints()
94 | + " frequent renter points
";
95 | return result;
96 | }
97 |
98 | public override string EachRentalString(Rental rental)
99 | {
100 | return rental.Movie.Title + ":" + rental.Charge + "
\n";
101 | }
102 |
103 | public override string HeaderString(Customer customer)
104 | {
105 | return "
Rentals for " + customer.Name + "
\n";
106 | }
107 | }
108 | }
109 | }
--------------------------------------------------------------------------------
/RefactorPractice/DealWithGeneralization/FormTemplateMethod/README.md:
--------------------------------------------------------------------------------
1 | ## 塑造模板函式(Form Template Method)
2 |
3 | 有一些subclass,其中相應的某些函式以相同順序執行類似的功能,但各功能有些不同
4 |
5 | 將各功能分別放進獨立函式中,並保持他們相同的署名,於是原函式也變得相同。然後將原函式上移至superclass
6 |
7 | ## 優點:
8 | * 繼承是避免重複的強大工具
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/DealWithGeneralization/PullUpConstructorBody/PullUpConstructorBody.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.DealWithGeneralization.PullUpConstructorBody
8 | {
9 | public class PullUpConstructorBody
10 | {
11 | public class Employee
12 | {
13 | protected string _name;
14 |
15 | protected string _id;
16 |
17 | protected Employee(string name, string id)
18 | {
19 | this._name = name;
20 | this._id = id;
21 | }
22 | }
23 |
24 | public class Manager : Employee
25 | {
26 | private int _grade;
27 |
28 | public Manager(string name, string id, int grade) : base(name, id)
29 | {
30 | this._grade = grade;
31 | }
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/RefactorPractice/DealWithGeneralization/PullUpConstructorBody/README.md:
--------------------------------------------------------------------------------
1 | ## 建構式本體上移(Pull Up Constrctor Body)
2 |
3 | 在各個subclass中擁有一些建構式,他們的本體幾乎一致
4 |
5 | 在superclass中新建一個建構式,並在subclass建構式中呼叫他
6 |
7 | ## 優點:
8 | *
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/DealWithGeneralization/PullUpField/README.md:
--------------------------------------------------------------------------------
1 | ## 欄位上移(Pull Up Field)
2 |
3 | 兩個subclasses擁有相同的欄位
4 |
5 | 將此一欄位移至superclass
6 |
7 | ## 優點:
8 | * 如果subclass都有重複的特性,移到superclass使用
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/DealWithGeneralization/PullUpMethod/README.md:
--------------------------------------------------------------------------------
1 | ## 函式上移(Pull Up Method)
2 |
3 | 有些函式,在各個subclass中產生完全相同的結果
4 |
5 | 將該函式移至superclass
6 |
7 | ## 優點:
8 | * 只要系統發現有兩個重複的函式,就提升函式到superclass,避免重複。
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/DealWithGeneralization/PushDownField/README.md:
--------------------------------------------------------------------------------
1 | ## 欄位下移(Push Down Field)
2 |
3 | superclass中的某個欄位只被部分(而非全部)subclass使用
4 |
5 | 將這個欄位移到需要他的那些subclass去
6 |
7 | ## 優點:
8 | *
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/DealWithGeneralization/PushDownMethod/README.md:
--------------------------------------------------------------------------------
1 | ## 函式下移(Push Down Method)
2 |
3 | superclass中的某個函式只與部分(而非全部)subclasses有關
4 |
5 | 將這個函式移到相關的那些subclass去
6 |
7 | ## 優點:
8 | * 當有必要把某些行為移到subclass就使用此手法。
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/DealWithGeneralization/ReplaceDelegationWithInheritance/README.md:
--------------------------------------------------------------------------------
1 | ## 以繼承取代委託(Replace Delegation With Inheritance)
2 |
3 | 兩個class之間使用委託關係,並經常為整個介面編寫極簡單的請託函式
4 |
5 | 讓請託class繼承受託class
6 |
7 | ## 優點:
8 | * 如果沒有全部使用受託class的所有函式,就不該使用此守則
9 | * 如果受託物件不只被一個物件共享,而受託物件是可變的,就不可使用此守則
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/RefactorPractice/DealWithGeneralization/ReplaceDelegationWithInheritance/ReplaceDelegationWithInheritance.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.DealWithGeneralization.ReplaceDelegationWithInheritance
8 | {
9 | internal class ReplaceDelegationWithInheritance
10 | {
11 | public class Employee : Person
12 | {
13 | public string GetName()
14 | {
15 | return base.Name;
16 | }
17 |
18 | public void SetName(string name)
19 | {
20 | base.Name = name;
21 | }
22 |
23 | public string ToString()
24 | {
25 | return "Emp:" + base.LastName;
26 | }
27 | }
28 |
29 | public class Person
30 | {
31 | public string Name { get; set; }
32 |
33 | public string LastName
34 | {
35 | get
36 | {
37 | return this.Name.Substring(this.Name.LastIndexOf("") + 1);
38 | }
39 | }
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/RefactorPractice/DealWithGeneralization/ReplaceInheritanceWithDelegation/README.md:
--------------------------------------------------------------------------------
1 | ## 以委託取代繼承 (Replace Inheritance With Delegation)
2 |
3 | 某個subclass只使用superclass介面的一部分,或是根本不需要繼承來的資料
4 |
5 | 在subclass中新建一個欄位保存superclass,調整subclass使他改而委託superclass,然後去掉兩者之間的繼承關係
6 |
7 | ## 優點:
8 | * 以委託取代繼承,可以清楚的表明,只需要受託類別的哪一些部分
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/DealWithGeneralization/ReplaceInheritanceWithDelegation/ReplaceInheritanceWithDelegation.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace RefactorPractice.DealWithGeneralization.ReplaceIngeritanceWithDelegation
9 | {
10 | internal class ReplaceInheritanceWithDelegation
11 | {
12 | public class MyStack
13 | {
14 | private ArrayList _arrayList;
15 |
16 | public void Push(Object obj)
17 | {
18 | this._arrayList.Insert(0, obj);
19 | }
20 |
21 | public Object Pop()
22 | {
23 | var result = this._arrayList[0];
24 | this._arrayList.RemoveAt(0);
25 | return result;
26 | }
27 |
28 | public int Size()
29 | {
30 | return this._arrayList.Count;
31 | }
32 |
33 | public bool IsEmpty()
34 | {
35 | return this._arrayList.Count == 0;
36 | }
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/AddParameter/README.md:
--------------------------------------------------------------------------------
1 | ## 添加參數(Add Parameter)
2 |
3 | 某個函式需要從呼叫端得到更多資訊
4 |
5 | 為此函式添加一個物件參數,讓該物件帶進函式所需資訊
6 |
7 | ## 優點:
8 | * 使用時要注意,過長的參數列不是一個好現象,可以適時使用Parameter Object來減少過長的參數列
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/EncapsulateDowncast/EncapsulateDowncast.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.MakingMethodCallsSimpler.EncapsulateDowncast
8 | {
9 | public class EncapsulateDowncast
10 | {
11 | public class Reading
12 | {
13 | private List _readings = new List();
14 |
15 | public Reading LastReading()
16 | {
17 | return this._readings.LastOrDefault();
18 | }
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/EncapsulateDowncast/README.md:
--------------------------------------------------------------------------------
1 | ## 封裝「向下轉型」動作 (Encapsulate Downcast)
2 |
3 | 某個函式傳回的物件,需要由函式呼叫者執行「向下轉型」(downcast)動作
4 |
5 | 將向下轉型(downcast)動作移到函式中
6 |
7 | ## 優點:
8 | * 盡量避免由使用者來承擔向下轉型的責任,要提供準確的型別給使用者
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/HideMethod/README.md:
--------------------------------------------------------------------------------
1 | ## 隱藏某個函式(Hide Method)
2 |
3 | 有一個函式,從來沒有被其他任何class用到
4 |
5 | 將這個函式修改為private
6 |
7 |
8 | ## 優點:
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/IntroduceParameterObject/IntroduceParameterObject.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.MakingMethodCallsSimpler.IntroduceParameterObject
8 | {
9 | public class IntroduceParameterObject
10 | {
11 | public void Sample()
12 | {
13 | var account = new Account();
14 | var flow = account.GetFlowBetween(new DateRange(new DateTime(2017, 10, 12), new DateTime(2017, 10, 12)));
15 | }
16 |
17 | public class Entry
18 | {
19 | private double _value;
20 |
21 | private DateTime _chargeDate;
22 |
23 | public double Value
24 | {
25 | get
26 | {
27 | return this._value;
28 | }
29 | }
30 |
31 | public DateTime ChargeDateTime
32 | {
33 | get
34 | {
35 | return this._chargeDate;
36 | }
37 | }
38 |
39 | public Entry(double value, DateTime chargeDate)
40 | {
41 | this._value = value;
42 | this._chargeDate = chargeDate;
43 | }
44 | }
45 |
46 | public class Account
47 | {
48 | private List _entries = new List();
49 |
50 | public double GetFlowBetween(DateRange range)
51 | {
52 | double result = 0;
53 | foreach (var entry in _entries)
54 | {
55 | if (range.InCludes(entry.ChargeDateTime))
56 | {
57 | result += entry.Value;
58 | }
59 | }
60 |
61 | return result;
62 | }
63 | }
64 |
65 | public class DateRange
66 | {
67 | private DateTime _start;
68 |
69 | private DateTime _end;
70 |
71 | public DateTime Start
72 | {
73 | get
74 | {
75 | return this._start;
76 | }
77 | }
78 |
79 | public DateTime End
80 | {
81 | get
82 | {
83 | return this._end;
84 | }
85 | }
86 |
87 | public DateRange(DateTime start, DateTime end)
88 | {
89 | this._start = start;
90 | this._end = end;
91 | }
92 |
93 | public bool InCludes(DateTime arg)
94 | {
95 | return arg >= this._start || arg <= this._end;
96 | }
97 | }
98 | }
99 | }
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/IntroduceParameterObject/README.md:
--------------------------------------------------------------------------------
1 | ## 引入參數物件(Introduce Parameter Object)
2 |
3 | 某些參數總是很自然的同時出現
4 |
5 | 以一個物件取代這些參數
6 |
7 | ## 優點:
8 | * 用參數物件可以縮短參數長度
9 | * 新物件的存取函式使程式碼更一致
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/ParameterizeMethod/ParameterizeMethod.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.Remoting.Channels;
5 | using System.Text;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 |
9 | namespace RefactorPractice.MakingMethodCallsSimpler.ParameterizeMethod
10 | {
11 | internal class ParameterizeMethod
12 | {
13 | private class Employee
14 | {
15 | protected double BaseCharge()
16 | {
17 | double result = UsageInRange(0, 100) * 0.03;
18 | result += UsageInRange(100, 200) * 0.05;
19 | result += UsageInRange(200, Int32.MaxValue) * 0.07;
20 | return result;
21 | }
22 |
23 | private double UsageInRange(int start, int end)
24 | {
25 | if (this.LastUsage() > start)
26 | {
27 | return Math.Min(this.LastUsage(), end) - start;
28 | }
29 | return 0;
30 | }
31 |
32 | private double LastUsage()
33 | {
34 | throw new NotImplementedException();
35 | }
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/ParameterizeMethod/README.md:
--------------------------------------------------------------------------------
1 | ## 令函式攜帶參數(Parameterize Method)
2 |
3 | 有幾個函式做了類似的工作,但在函式本體中包含了不同的值。
4 |
5 | 建立單一函式,以表達那些不同的值
6 |
7 | ## 優點:
8 | * 這樣可以去除重複的程式碼,提高靈活性。
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/PreserveWholeObject/PreserveWholeObject.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.MakingMethodCallsSimpler.PreserveWholeObject
8 | {
9 | internal class PreserveWholeObject
10 | {
11 | public class Room
12 | {
13 | public bool WithinPlan(HeatingPlan plan)
14 | {
15 | return plan.WithinRange(this.DaysTempRange());
16 | }
17 |
18 | private TempRange DaysTempRange()
19 | {
20 | return new TempRange();
21 | }
22 | }
23 |
24 | public class HeatingPlan
25 | {
26 | public bool WithinRange(TempRange roomRange)
27 | {
28 | return (roomRange.Low > roomRange.Low && roomRange.High <= roomRange.High);
29 | }
30 | }
31 |
32 | public class TempRange
33 | {
34 | public int Low { get; set; }
35 |
36 | public int High { get; set; }
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/PreserveWholeObject/README.md:
--------------------------------------------------------------------------------
1 | ## 保持物件完整(Preserve Whole Object)
2 |
3 | 從某個物件中取得值,將他們作為某一次函式呼叫的參數。
4 |
5 | 改為傳遞整個物件
6 |
7 | ## 優點:
8 | * 可以使參數列更穩固,還能提高可讀性。
9 | * 但傳遞整個物件,參數物件與被呼叫函式物件就有依存關係,如果會使依存結構惡化,就不要用這個原則。
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/RemoveParameter/README.md:
--------------------------------------------------------------------------------
1 | ## 移除參數(Remove Parameter)
2 |
3 | 函式本體不再需要某個參數
4 |
5 | 將該參數去除
6 |
7 | ## 優點:
8 | * 當不需要參數的時候一定要移除,不然會造成程式碼閱讀者混淆。
9 | * 對於多型函式,先要了解參數是不是被其他多型函式所使用,這時候就不能移除,或是建立另一個函式來使用。
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/RemoveSettingMethod/README.md:
--------------------------------------------------------------------------------
1 | ## 移除設值函式(Remove Setting Method)
2 |
3 | 某個Class中的某個欄位,應該在物件初創時就被設值,然後就不再改變
4 |
5 | 去掉該欄位的所有設值函式(setter)
6 |
7 | ## 優點:
8 | * 如果不希望欄位值在初創之後還會被變更,就不要提供設值函式
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/RemoveSettingMethod/RemoveSettingMethod.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.MakingMethodCallsSimpler.RemoveSettingMethod
8 | {
9 | public class RemoveSettingMethod
10 | {
11 | public class Account
12 | {
13 | private string _id;
14 |
15 | public Account(string id)
16 | {
17 | this._id = id;
18 | }
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/RenameMethod/README.md:
--------------------------------------------------------------------------------
1 | ## 重新命名函式(Rename Method)
2 |
3 | 函式的名稱未能揭示函式的用途。
4 |
5 | 修改函式名稱
6 |
7 | ## 優點:
8 | * 函式的名稱應該準確表達他的用途,程式是人寫的,所以需要良好的命名,提高程式的可讀性。
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/RenameMethod/RenameMethod.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.MakingMethodCallsSimpler.RenameMethod
8 | {
9 | public class RenameMethod
10 | {
11 | private string _officeNumber;
12 |
13 | private string _officeAreaCode;
14 |
15 | public string GetTelephoneNumber()
16 | {
17 | return GetOfficeTelephoneNumber();
18 | }
19 |
20 | private string GetOfficeTelephoneNumber()
21 | {
22 | return $"({_officeAreaCode}){_officeNumber}";
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/ReplaceConstructorWithFactoryMethod/README.md:
--------------------------------------------------------------------------------
1 | ## 以「工廠函式」取代「建構式」(Replace Constructor With Factory Method)
2 |
3 | 創建物件時不僅僅是對它做簡單的建構動作
4 |
5 | 將constructor(建構式)替換為factory method(工廠函式)
6 |
7 | ## 優點:
8 | *
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/ReplaceConstructorWithFactoryMethod/ReplaceConstructorWithFactoryMethod.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace RefactorPractice.MakingMethodCallsSimpler.ReplaceConstructorWithFactoryMethod
9 | {
10 | public class ReplaceConstructorWithFactoryMethodByTypeCode
11 | {
12 | public void Sample()
13 | {
14 | var employee = Employee.Create(Employee.ENGINEER);
15 | }
16 |
17 | public class Employee
18 | {
19 | private int _type;
20 |
21 | public const int ENGINEER = 0;
22 | public const int SALESMAN = 1;
23 | public const int MANAGER = 2;
24 |
25 | private Employee(int type)
26 | {
27 | this._type = type;
28 | }
29 |
30 | public static Employee Create(int type)
31 | {
32 | return new Employee(type);
33 | }
34 | }
35 | }
36 |
37 | public class ReplaceConstructorWithFactoryMethodByString
38 | {
39 | public class Employee
40 | {
41 | private int _type;
42 |
43 | public const int ENGINEER = 0;
44 | public const int SALESMAN = 1;
45 | public const int MANAGER = 2;
46 |
47 | public static Employee Create(string name)
48 | {
49 | var result = Assembly.GetExecutingAssembly();
50 | return result.CreateInstance(name) as Employee;
51 | }
52 | }
53 |
54 | public class SalesMan : Employee
55 | {
56 | }
57 |
58 | public class Manager : Employee
59 | {
60 | }
61 |
62 | public class Engineer : Employee
63 | {
64 | }
65 | }
66 |
67 | public class ReplaceConstructorWithFactoryMethodByExplicitMethod
68 | {
69 | public void Sample()
70 | {
71 | Person person = Person.CreateFemale();
72 | Person person2 = Person.CreateMale();
73 | }
74 |
75 | public class Person
76 | {
77 | public static Person CreateMale()
78 | {
79 | return new Male();
80 | }
81 |
82 | public static Person CreateFemale()
83 | {
84 | return new Female();
85 | }
86 | }
87 |
88 | public class Male : Person
89 | {
90 | }
91 |
92 | public class Female : Person
93 | {
94 | }
95 | }
96 | }
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/ReplaceErrorCodeWithException/README.md:
--------------------------------------------------------------------------------
1 | ## 以異常取代錯誤碼(Replace Error Code With Exception)
2 |
3 | 某個函式傳回一個特殊代碼(Special Code),用以表示某種錯誤狀況
4 |
5 | 改用異常(Exception)
6 |
7 | ## 優點:
8 | * Exception清楚的將一般程式與錯誤處理分開了,使得程式更加容易理解
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/ReplaceErrorCodeWithException/ReplaceErrorCodeWithException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.MakingMethodCallsSimpler.ReplaceErrorCodeWithException
8 | {
9 | public class ReplaceErrorCodeWithException
10 | {
11 | private int _balance;
12 |
13 | public void Withdraw(int amount)
14 | {
15 | if (amount > _balance)
16 | {
17 | throw new Exception("錯誤");
18 | }
19 | this._balance -= amount;
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/ReplaceExceptionWithTest/README.md:
--------------------------------------------------------------------------------
1 | ## 以測試取代異常(Replace Exception With Test)
2 |
3 | 面對一個呼叫者可預先加以檢查的條件,你拋出一個異常
4 |
5 | 修改呼叫者,使它在呼叫函式之前先做檢查
6 |
7 | ## 優點:
8 | * 提供一個測試,呼叫函式前先進行測試
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/ReplaceParameterWithExplicitMethod/README.md:
--------------------------------------------------------------------------------
1 | ## 以明確函式取代參數(Replace Parameter With Explicit Method)
2 |
3 | 有一個函式,其內完全取決於參數值而採取不同的反應。
4 |
5 | 針對該參數的每一個可能值,建立一個獨立函式
6 |
7 |
8 | ## 優點:
9 | * 如果某個參數有離散取值,而函式內又以條件式檢查這些參數,並根據不同參數值做不同反應,就使用此原則。
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/ReplaceParameterWithExplicitMethod/ReplaceParameterWithExplicitMethod.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | using RefactorPractice.OrganizingData.ReplaceTypeCodeWithStateOrStrategy;
8 |
9 | namespace RefactorPractice.MakingMethodCallsSimpler.ReplaceParameterWithExplicitMethod
10 | {
11 | internal class ReplaceParameterWithExplicitMethod
12 | {
13 | public void Sample()
14 | {
15 | //Employee kent = Employee.Create(Employee.ENGINEER);
16 | Employee kent = Employee.CreateEngineer();
17 | }
18 |
19 | public class Employee
20 | {
21 | public const int ENGINEER = 0;
22 |
23 | public const int SALESMAN = 1;
24 |
25 | public const int MANAGER = 2;
26 |
27 | public static Employee CreateEngineer()
28 | {
29 | return new Engineer();
30 | }
31 |
32 | public static Employee CreateSalesMan()
33 | {
34 | return new SalesMan();
35 | }
36 |
37 | public static Employee CreateManager()
38 | {
39 | return new Manager();
40 | }
41 | }
42 |
43 | public class Engineer : Employee
44 | {
45 | }
46 |
47 | public class SalesMan : Employee
48 | {
49 | }
50 |
51 | public class Manager : Employee
52 | {
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/ReplaceParameterWithMethods/README.md:
--------------------------------------------------------------------------------
1 | ## 以函式取代參數(Replace Parameter With Methods)
2 |
3 | 物件使用某個函式,並將結果作為參數,傳遞給另一個函式。而接受該參數的函式也可以使用某個函式
4 |
5 |
6 | ## 優點:
7 | * 如果某個參數有離散取值,而函式內又以條件式檢查這些參數,並根據不同參數值做不同反應,就使用此原則。
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/ReplaceParameterWithMethods/ReplaceParameterWithMethods.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.MakingMethodCallsSimpler.ReplaceParameterWithMethods
8 | {
9 | internal class ReplaceParameterWithMethods
10 | {
11 | private int _itemPrice;
12 |
13 | private int _quantity;
14 |
15 | public double GetPrice()
16 | {
17 | return DiscountedPrice();
18 | }
19 |
20 | private int GetBasePrice()
21 | {
22 | return _quantity * _itemPrice;
23 | }
24 |
25 | private int GetDiscountLevel()
26 | {
27 | int discountLevel;
28 | if (_quantity > 100)
29 | {
30 | discountLevel = 2;
31 | }
32 | else
33 | {
34 | discountLevel = 1;
35 | }
36 |
37 | return discountLevel;
38 | }
39 |
40 | private double DiscountedPrice()
41 | {
42 | if (GetDiscountLevel() == 2)
43 | {
44 | return this.GetBasePrice() * 0.1;
45 | }
46 | else
47 | {
48 | return this.GetBasePrice() * 0.05;
49 | }
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/SeparateQueryFromModifier/README.md:
--------------------------------------------------------------------------------
1 | ## 將查詢函式和修改函式分離(Separate Query From Modifier)
2 |
3 | 某個函式傳回物件狀態值,又修改物件狀態。
4 |
5 | 建立兩個不同函式,其中一個負責查詢,一個負責修改
6 |
7 | ## 優點:
8 | * 如果函式只向你提供一個值,沒有修改物件狀態,那可以很容易的將函式搬離。
9 | 若函式向你回傳物件又修改物件狀態,容易產生副作用
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/RefactorPractice/MakingMethodCallsSimpler/SeparateQueryFromModifier/SeparateQueryFromModifier.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace RefactorPractice.MakingMethodCallsSimpler.SeparateQueryFromModifier
9 | {
10 | internal class SeparateQueryFromModifier
11 | {
12 | public void CheckSecurity(string[] people)
13 | {
14 | this.SendAlert(people);
15 | string found = FoundPerson(people);
16 | SomeLaterCode(found);
17 | }
18 |
19 | private void SomeLaterCode(string found)
20 | {
21 | throw new NotImplementedException();
22 | }
23 |
24 | public void SendAlert(string[] people)
25 | {
26 | if (!FoundPerson(people).Equals(""))
27 | {
28 | this.SendAlert();
29 | }
30 | }
31 |
32 | public string FoundPerson(string[] people)
33 | {
34 | for (int i = 0; i < people.Length; i++)
35 | {
36 | if (people[i].Equals("Don"))
37 | {
38 | SendAlert();
39 | return "Don";
40 | }
41 | if (people[i].Equals("John"))
42 | {
43 | SendAlert();
44 | return "John";
45 | }
46 | }
47 | return "";
48 | }
49 |
50 | private void SendAlert()
51 | {
52 | throw new NotImplementedException();
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/RefactorPractice/MovingFeaturesBetweenObjects/ExtractClass/ExtractClass.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace RefactorPractice.MovingFeaturesBetweenObjects.ExtractClass
7 | {
8 | public class ExtractClass
9 | {
10 | public class Person
11 | {
12 | private TelephoneNumber _officeTelephone = new TelephoneNumber();
13 |
14 | public string Name { get; set; }
15 |
16 | public string GetOfficeTelephoneNumber()
17 | {
18 | return $"({this._officeTelephone.AreaCode}) {this._officeTelephone.Number}";
19 | }
20 | }
21 |
22 | public class TelephoneNumber
23 | {
24 | public string AreaCode { get; set; }
25 |
26 | public string Number { get; set; }
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/RefactorPractice/MovingFeaturesBetweenObjects/ExtractClass/README.md:
--------------------------------------------------------------------------------
1 | ## 提煉類別(Extract Class)
2 |
3 | 某個Class做了應該由兩個類別做的事,建立一個新類別,將相關的欄位和函式從舊Class搬到新Class
4 |
5 | ## 優點:
6 | * Class之間的職責更為清楚
7 | * 分解成小Class提高了可維護性
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/RefactorPractice/MovingFeaturesBetweenObjects/HideDelegate/HideDelegate.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace RefactorPractice.MovingFeaturesBetweenObjects.HideDelegate
7 | {
8 | public class HideDelegate
9 | {
10 | public void Sample()
11 | {
12 | var person = new Person();
13 | var manager = person.GetManager();
14 | }
15 |
16 | public class Person
17 | {
18 | public Department Department;
19 |
20 | public Person GetManager()
21 | {
22 | return this.Department.Manager;
23 | }
24 | }
25 |
26 | public class Department
27 | {
28 | public string ChargeCode { get; set; }
29 |
30 | public Person Manager { get; }
31 |
32 | public Department(Person manager)
33 | {
34 | this.Manager = manager;
35 | }
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/RefactorPractice/MovingFeaturesBetweenObjects/HideDelegate/README.md:
--------------------------------------------------------------------------------
1 | ## 隱藏委託關係(Hide Delegate)
2 |
3 | 用戶端直接呼叫服務物件的委託Class,在服務物件建立用戶端所需的所有函式,隱藏委託關係
4 | (意義就是「封裝」)
5 |
6 |
7 |
8 | ## 優點:
9 | * 每個物件都盡可能的少了解系統的其他部分,一旦發生變化,了解變化的物件會比較少,變化會比較好進行
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/RefactorPractice/MovingFeaturesBetweenObjects/InlineClass/InlineClass.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace RefactorPractice.MovingFeaturesBetweenObjects.InlineClass
7 | {
8 | public class InlineClass
9 | {
10 | public class Person
11 | {
12 | public string Name { get; set; }
13 |
14 | public string Number { get; set; }
15 |
16 | public string AreaCode { get; set; }
17 |
18 | public string GetTelephoneNumber()
19 | {
20 | return $"({this.AreaCode}) {this.Number}";
21 | }
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/RefactorPractice/MovingFeaturesBetweenObjects/InlineClass/README.md:
--------------------------------------------------------------------------------
1 | ## 行內類別 (Inline Class)
2 |
3 | 某個Class沒有承擔太多職責,將Class的所有特性搬移到另一個Class中,並移除原本Class
4 |
5 | ## 優點:
6 | * 如果一個Class不再承擔足夠的職責、不再有單獨存在的理由,就將Class搬移並移除。
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/RefactorPractice/MovingFeaturesBetweenObjects/IntroduceForeignMethod/IntroduceForeignMethod.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.MovingFeaturesBetweenObjects.IntroduceForeignMethod
8 | {
9 | public class IntroduceForeignMethod
10 | {
11 | public void Sample()
12 | {
13 | DateTime previousEnd = DateTime.Now;
14 | var newStart = GetNextDay(previousEnd);
15 | }
16 |
17 | private static DateTime GetNextDay(DateTime previousEnd)
18 | {
19 | return new DateTime(previousEnd.Year, previousEnd.Month, previousEnd.Day + 1);
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/RefactorPractice/MovingFeaturesBetweenObjects/IntroduceForeignMethod/README.md:
--------------------------------------------------------------------------------
1 | ## 引入外加函式 (Introduce Foreign Method)
2 |
3 | 用戶端程式碼使用的服務類別需要一個額外的函式,但你無法修改這個Class,
4 | 在用戶端的程式碼中建立一個函式,並以服務類別實體作為參數。
5 |
6 | ## 優點:
7 | * 這個函式最好的方式是在服務類別中建立,有時考量到程式碼擁有權的問題,才需要使用這個原則
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/RefactorPractice/MovingFeaturesBetweenObjects/IntroduceLocalExtension/README.md:
--------------------------------------------------------------------------------
1 | ## 引入區域性擴展 (Introduce Local Extension)
2 |
3 | 你所使用的服務類別需要一些額外的函式,但你無法修改這個Class,
4 | 建立一個新的Class,使他包含這些額外的函式。
5 | 讓這個擴展品成為來源Class的子類別(SubClass)或Wrapper(外覆類別)
6 |
7 | ## 優點:
8 | * 擴展類別不一定和來源類別有強烈的繼承關係,只要能夠提供所有特性即可
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/RefactorPractice/MovingFeaturesBetweenObjects/MoveField/MoveField.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace RefactorPractice.MovingFeaturesBetweenObjects.MoveField
7 | {
8 | public class MoveField
9 | {
10 | public class Account
11 | {
12 | public AccountType _type;
13 |
14 | public double InterestForAmonuntDays(double amount, int days)
15 | {
16 | return this._type.InterestRate * amount * days / 365;
17 | }
18 | }
19 |
20 | public class AccountType
21 | {
22 | public double InterestRate { get; set; }
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/RefactorPractice/MovingFeaturesBetweenObjects/MoveField/MoveFieldWithSelfEncapsulation.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace RefactorPractice.MovingFeaturesBetweenObjects.MoveField
7 | {
8 | public class MoveFieldWithSelfEncapsulation
9 | {
10 | public class Account
11 | {
12 | public AccountType _type;
13 |
14 | public double InterestRate
15 | {
16 | get
17 | {
18 | return this._type.InterestRate;
19 | }
20 | set
21 | {
22 | this._type.InterestRate = value;
23 | }
24 | }
25 |
26 | public double InterestForAmonuntDays(double amount, int days)
27 | {
28 | return this.InterestRate * amount * days / 365;
29 | }
30 | }
31 |
32 | public class AccountType
33 | {
34 | public double InterestRate { get; set; }
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/RefactorPractice/MovingFeaturesBetweenObjects/MoveField/README.md:
--------------------------------------------------------------------------------
1 | ## 移動欄位(Move Field)
2 |
3 | 某個欄位被所在的Class的以外Class引用,
4 | 在目標Class建立一個新的Field,修改所有引用點至新的Field
5 |
6 | ## 優點:
7 | * 如果發現別的Class更多的引用這個欄位,就移動它。
8 |
--------------------------------------------------------------------------------
/RefactorPractice/MovingFeaturesBetweenObjects/MoveMethod/MoveMethod.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace RefactorPractice.MovingFeaturesBetweenObjects.MoveMethod
7 | {
8 | public class MoveMethod
9 | {
10 | public class Account
11 | {
12 | private AccountType _type;
13 |
14 | private int _daysOverdrawn;
15 |
16 | public double BankCharge()
17 | {
18 | double result = 4.5;
19 | if (this._daysOverdrawn > 0)
20 | {
21 | result += this._type.OverDraftCharge(this);
22 | }
23 | return result;
24 | }
25 |
26 | public int GetDaysOverdrawn()
27 | {
28 | return this._daysOverdrawn;
29 | }
30 | }
31 |
32 | public class AccountType
33 | {
34 | public bool IsPremium()
35 | {
36 | return true;
37 | }
38 |
39 | public double OverDraftCharge(Account account)
40 | {
41 | if (this.IsPremium())
42 | {
43 | double result = 10;
44 | if (account.GetDaysOverdrawn() > 7)
45 | {
46 | result += (account.GetDaysOverdrawn() - 7) * 0.85;
47 | }
48 | return result;
49 | }
50 | else
51 | {
52 | return account.GetDaysOverdrawn() * 1.75;
53 | }
54 | }
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/RefactorPractice/MovingFeaturesBetweenObjects/MoveMethod/README.md:
--------------------------------------------------------------------------------
1 | ## 移動函式(Move Method)
2 |
3 | 有個函式與其所駐的Class與另一個Class進行更多交流,呼叫後者或被後者呼叫。
4 |
5 | 在該函式最常引用的Class中建立一個有著類似行為的新函式。
6 | 將舊函式變成一個單純的委託函式,或是將舊函式完全移除
7 |
8 | ## 優點:
9 | * 如果一個class與另一個class有太多的合作,而形成高度耦合,
10 | 透過移動函式,讓class變得更簡單。
11 |
--------------------------------------------------------------------------------
/RefactorPractice/MovingFeaturesBetweenObjects/RemoveMiddleMan/README.md:
--------------------------------------------------------------------------------
1 | ## 移除中間人(Remove Middle Man)
2 |
3 | 某個Class使用了過多的簡單委託動作,直接讓用戶端呼叫受託類別(delegate)
4 |
5 | ## 優點:
6 | * 一旦簡單委託動作過多,會增加程式碼複雜度,服務物件會完全變成一個中間人,這時候直接讓用戶端呼叫受託類別即可。
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/RefactorPractice/MovingFeaturesBetweenObjects/RemoveMiddleMan/RemoveMiddleMan.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace RefactorPractice.MovingFeaturesBetweenObjects.RemoveMiddleMan
7 | {
8 | public class RemoveMiddleMan
9 | {
10 | public void Sample()
11 | {
12 | var person = new Person();
13 | var manager = person.Department.Manager;
14 | }
15 |
16 | public class Person
17 | {
18 | public Department Department;
19 | }
20 |
21 | public class Department
22 | {
23 | public string ChargeCode { get; set; }
24 |
25 | public Person Manager { get; }
26 |
27 | public Department(Person manager)
28 | {
29 | this.Manager = manager;
30 | }
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/ChangeBidirectonalAssociationToUnidirectional/ChangeBidirectonalAssociationToUnidirectional.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.OrganizingData.ChangeBidirectonalAssociationToUnidirectional
8 | {
9 | public class ChangeBidirectonalAssociationToUnidirectional
10 | {
11 | public class Order
12 | {
13 | public Customer Customer { get; set; }
14 |
15 | public void SetCustomer(Customer arg)
16 | {
17 | if (Customer != null)
18 | {
19 | Customer.FriendOrders().Remove(this);
20 | }
21 |
22 | Customer = arg;
23 | if (Customer != null)
24 | {
25 | Customer.FriendOrders().Add(this);
26 | }
27 | }
28 |
29 | public double GetDiscountedPrice(Customer customer)
30 | {
31 | return GetGrossPirce() * (1 - customer.GetDiscount());
32 | }
33 |
34 | private double GetGrossPirce()
35 | {
36 | throw new NotImplementedException();
37 | }
38 | }
39 |
40 | public class Customer
41 | {
42 | private List _orders = new List();
43 |
44 | public List FriendOrders()
45 | {
46 | return this._orders;
47 | }
48 |
49 | public double GetDiscount()
50 | {
51 | throw new NotImplementedException();
52 | }
53 |
54 | public double GetPriceFor(Order order)
55 | {
56 | return order.GetDiscountedPrice(this);
57 | }
58 |
59 | private void AddOrder(Order arg)
60 | {
61 | arg.SetCustomer(this);
62 | }
63 | }
64 | }
65 | }
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/ChangeBidirectonalAssociationToUnidirectional/README.md:
--------------------------------------------------------------------------------
1 | ## 將雙向關聯改為單向 (Change Bidirectonal Association To Unidirectional)
2 |
3 | 兩個Class之間有雙向關聯,當其中一個Class不再需要另一個Class的特性。
4 |
5 | 就去除不必要的關聯。
6 |
7 | ## 優點:
8 | * 雙向關聯必須確保物件能正確的被創建與刪除
9 | * 大量的雙向關聯也容易產生殭屍物件
10 | * 雙向關聯迫使兩個Class之間有相依性,過多的相依性會造成緊耦合。
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/ChangeReferenceToValue/ChangeReferenceToValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.OrganizingData.ChangeReferenceToValue
8 | {
9 | public class ChangeReferenceToValue
10 | {
11 | private void Sample()
12 | {
13 | var instance = Activator.CreateInstance(typeof(Currency), "USD");
14 | }
15 |
16 | public class Currency
17 | {
18 | private string Code { get; set; }
19 |
20 | private Currency(string code)
21 | {
22 | this.Code = code;
23 | }
24 |
25 | public override bool Equals(object obj)
26 | {
27 | if (!(obj is Currency))
28 | {
29 | return false;
30 | }
31 | return Code.Equals(((Currency)obj).Code);
32 | }
33 |
34 | public override int GetHashCode()
35 | {
36 | return Code.GetHashCode();
37 | }
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/ChangeReferenceToValue/README.md:
--------------------------------------------------------------------------------
1 | ## 將參考物件改為實值物件 (Change Reference To Value)
2 |
3 | 有一個參考物件,很小且不太會變動,而且不易管理。
4 |
5 | 將它變成一個實值物件
6 |
7 | ## 優點:
8 | * 在分布系統和併行系統中,使用實值物件就不需要考慮同步的問題
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/ChangeUnidirectionalAssociationToBidirectonal/ChangeUnidirectionalAssociationToBidirectonal.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.OrganizingData.ChangeUnidirectionalAssociationToBidirectonal
8 | {
9 | public class ChangeUnidirectionalAssociationToBidirectonal
10 | {
11 | public class Order
12 | {
13 | public Customer Customer { get; set; }
14 |
15 | public void SetCustomer(Customer arg)
16 | {
17 | if (Customer != null)
18 | {
19 | Customer.FriendOrders().Remove(this);
20 | }
21 |
22 | this.Customer = arg;
23 |
24 | if (Customer != null)
25 | {
26 | Customer.FriendOrders().Add(this);
27 | }
28 | }
29 | }
30 |
31 | public class Customer
32 | {
33 | private List _orders { get; set; }
34 |
35 | public List FriendOrders()
36 | {
37 | return _orders;
38 | }
39 |
40 | public void AddOrder(Order arg)
41 | {
42 | arg.SetCustomer(this);
43 | }
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/ChangeUnidirectionalAssociationToBidirectonal/README.md:
--------------------------------------------------------------------------------
1 | ## 將單向關聯改為雙向 (Change Unidirectional Association To Bidirectonal)
2 |
3 | 兩個Class都需要用到對方的特性,但其中只有一條單向連結。
4 |
5 | 增加一個反向指標,並修改函式能夠同時更新兩條連結。
6 |
7 | ## 優點:
8 | * 當一個參考物件需要知道引用物件的某些特性來進行操作,就需要建立雙向引用關係
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/ChangeValueToReference/ChangeValueToReference.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.CompilerServices;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace RefactorPractice.OrganizingData.ChangeValueToReference
9 | {
10 | public class ChangeValueToReference
11 | {
12 | public class Customer
13 | {
14 | private static Dictionary _instances = new Dictionary();
15 | public string Name { get; set; }
16 |
17 | private Customer(string name)
18 | {
19 | this.Name = name;
20 | }
21 |
22 | public static void LoadCustomers()
23 | {
24 | new Customer("Lemon Car Hire").Store();
25 | new Customer("Associated Coffee Machines").Store();
26 | new Customer("Bilston Gasworks").Store();
27 | }
28 |
29 | public static Customer Create(string name)
30 | {
31 | return _instances[name] as Customer;
32 | }
33 |
34 | private void Store()
35 | {
36 | _instances.Add(this.Name, this);
37 | }
38 | }
39 |
40 | public class Order
41 | {
42 | public Customer Customer { get; set; }
43 |
44 | public Order(string customerName)
45 | {
46 | this.Customer = Customer.Create(customerName);
47 | }
48 |
49 | public static int NumberOfOrdersFor(List orders, string customer)
50 | {
51 | var result = 0;
52 | foreach (var order in orders)
53 | {
54 | if (order.GetCusomterName().Equals(customer))
55 | {
56 | result++;
57 | }
58 | }
59 | return result;
60 | }
61 |
62 | public string GetCusomterName()
63 | {
64 | return this.Customer.Name;
65 | }
66 | }
67 | }
68 | }
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/ChangeValueToReference/README.md:
--------------------------------------------------------------------------------
1 | ## 將實值物件改為參考物件 (Change Value To Reference)
2 |
3 | 有一個Class,衍生出許多相等實體,你希望將他們替換成單一物件。
4 |
5 | 將這個實值物件變成一個參考物件
6 |
7 | ## 優點:
8 | * 可以給這個物件加入一些資料,又可以確保所有引用的地方會一併修改。
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/DuplicateObservedData/README.md:
--------------------------------------------------------------------------------
1 | ## 複製被監視的資料 (Duplicate Observed Data)
2 |
3 | 有一些Domain Data在GUI介面中,而Domain Method需要使用。
4 |
5 | 將該筆資料複製到一個Domain Object中。建立一個Observer範式,用以對Domain Object和GUI內的重複資料進行同步
6 |
7 | ## 優點:
8 | * 同一筆資料有可能需要於GUI中,也可能在Domain Model中,所以還必須提供相對應的同步機制。
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/EncapsulateCollection/README.md:
--------------------------------------------------------------------------------
1 | ## 封裝群集(Encapsulate Collection)
2 |
3 | 有個函式回傳一個群集(Collection)。
4 |
5 | 讓這個函式傳回該群集的一個唯獨映件,並在這個Class中提供添加/移除(add/remove)群集元素的函式
6 |
7 | ## 優點:
8 | * 在C#中,就是泛型集合的實作
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/EncapsulateField/EncapsulateField.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace RefactorPractice.OrganizingData.EncapsulateField
9 | {
10 | public class EncapsulateField
11 | {
12 | private string _name;
13 |
14 | public string Name
15 | {
16 | get
17 | {
18 | return this._name;
19 | }
20 | set
21 | {
22 | this._name = value;
23 | }
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/EncapsulateField/README.md:
--------------------------------------------------------------------------------
1 | ## 封裝欄位 (EncapsulateField)
2 |
3 | 你的Class存在一個public欄位。
4 |
5 | 將它宣告成private,並提供相對應的存取函式
6 |
7 | ## 優點:
8 | * 物件導向的首要原則就是封裝,又稱為資料隱藏。如果資料開放成public,
9 | 那任何使用到的物件都可以隨意修改資料,會造成資料與行為不一致。
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/ReplaceArrayWithObject/README.md:
--------------------------------------------------------------------------------
1 | ## 以物件取代陣列 (Replace Array With Objects)
2 |
3 | 有一個陣列,其中元素各自代表不同東西。
4 |
5 | 以物件替換陣列。對於陣列中每個元素,以一個欄位表示。
6 |
7 | ## 優點:
8 | * 陣列應該只用於某種順序容納的一組相似物件。
9 | 如果一個陣列容納了很多物件,會給程式碼閱讀者帶來麻煩。
10 | 而物件有欄位名稱與函式可以詮釋,還可以將資訊加以封裝。
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/ReplaceArrayWithObject/ReplaceArrayWithObject.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.OrganizingData.ReplaceArrayWithObject
8 | {
9 | public class ReplaceArrayWithObject
10 | {
11 | public void Sample()
12 | {
13 | Performance row = new Performance();
14 | row.Name = "Liverpool";
15 | row.Wins = 15;
16 | int wins = row.Wins;
17 | }
18 |
19 | public class Performance
20 | {
21 | public string Name { get; set; }
22 |
23 | public int Wins { get; set; }
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/ReplaceDataValueWithObject/README.md:
--------------------------------------------------------------------------------
1 | ## 以物件取代資料值 (Replace Data Value with Object)
2 |
3 | 你有一個資料項,需要額外的行為和資料。
4 | 將這個資料項變成物件
5 |
6 | ## 優點:
7 | * 以往用簡單的資料項來表示簡單的行為,隨著開發的進行,會出現不夠用的情況,這時候就需要將資料值變成物件。
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/ReplaceDataValueWithObject/ReplaceDataValueWithObject.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.OrganizingData.ReplaceDataValueWithObject
8 | {
9 | public class ReplaceDataValueWithObject
10 | {
11 | public class Order
12 | {
13 | private Customer _customer;
14 |
15 | public Order(string customerName)
16 | {
17 | this._customer = new Customer(customerName);
18 | }
19 |
20 | public string GetCustomerName()
21 | {
22 | return this._customer.Name;
23 | }
24 |
25 | private static int NumberOfOrderFor(List orders, Customer customer)
26 | {
27 | var result = 0;
28 | foreach (var order in orders)
29 | {
30 | if (order._customer.Equals(customer))
31 | {
32 | result++;
33 | }
34 | }
35 | return result;
36 | }
37 | }
38 |
39 | public class Customer
40 | {
41 | public string Name { get; set; }
42 |
43 | public Customer(string name)
44 | {
45 | this.Name = name;
46 | }
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/ReplaceMagicNumberWithSymbolicConstant/README.md:
--------------------------------------------------------------------------------
1 | ## 以符號常數(字面常數)取代魔術數字 (Replace Magic Number With Symbolic Constant)
2 |
3 | 有一個字面數值,帶有特別含意。
4 |
5 | 創造一個常數,根據其意義命名,並將上述的字面數值替換成這個常數
6 |
7 | ## 優點:
8 | * 魔術數字是指有特殊意義,但又不能明確表達意義的數字。
9 | 用有意義的常數取代,會大幅提升可讀性。
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/ReplaceMagicNumberWithSymbolicConstant/ReplaceMagicNumberWithSymbolicConstant.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.OrganizingData.ReplaceMagicNumberWithSymbolicConstant
8 | {
9 | public class ReplaceMagicNumberWithSymbolicConstant
10 | {
11 | public const double GRAVITATIONAL_CONSTANT = 9.81;
12 |
13 | public double PotentialEnergy(double mass, double height)
14 | {
15 | return mass * GRAVITATIONAL_CONSTANT * height;
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/ReplaceRecordWithDataClass/README.md:
--------------------------------------------------------------------------------
1 | ## 以資料類別取代紀錄(Replace Record With Data Class)
2 |
3 | 你需要面對傳統編程環境中的Record Structure。
4 |
5 | 為該record(紀錄)創建一個啞資料物件(dumb data object)
6 |
7 | ## 優點:
8 | * Record Structure是許多編程環境的共同性質
9 | ,在物件導向的語言中用Data object替換他們。
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/ReplaceSubclassWithFields/README.md:
--------------------------------------------------------------------------------
1 | ## 以欄位取代子類別(Replace Subclass With Fields)
2 |
3 | 各個subclasses的差別在於傳回常數的函式身上。
4 |
5 | 修改這些函式,使他們傳回superclass中的某個(新增欄位),然後銷毀subclass
6 |
7 | ## 優點:
8 | * 若subclass中只有常數函式,沒有足夠的存在價值,可以在superclass中設計一個與常數函式回傳值相應的欄位,
9 | 從而完全去除這樣的subclass。
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/ReplaceSubclassWithFields/ReplaceSubclassWithFields.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Net.Http.Headers;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | using RefactorPractice.MovingFeaturesBetweenObjects.ExtractClass;
9 |
10 | namespace RefactorPractice.OrganizingData.ReplaceSubclassWithFields
11 | {
12 | internal class ReplaceSubclassWithFields
13 | {
14 | public class Person
15 | {
16 | private bool _isMale;
17 |
18 | private char _code;
19 |
20 | protected Person(bool isMale, char code)
21 | {
22 | this._isMale = isMale;
23 | this._code = code;
24 | }
25 |
26 | public bool IsMale()
27 | {
28 | return this._isMale;
29 | }
30 |
31 | public char GetCode()
32 | {
33 | return this._code;
34 | }
35 |
36 | public static Person CreateFemale()
37 | {
38 | return new Person(true, 'M');
39 | }
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/ReplaceTypeCodeWithClass/README.md:
--------------------------------------------------------------------------------
1 | ## 以類別取代型別代碼(Replace TypeCode With Class)
2 |
3 | Class之中有一個數值型別代碼(numberic type code),但它不影響class行為。
4 |
5 | 以一個新的class替換該數值型別代碼(type code)
6 |
7 | ## 優點:
8 | * 符號名稱只是別名,編譯器會進行型別檢驗的還是背後的那個數值。
9 | 任何會接受type code作為引數的函式,所期望的還是一個數值,無法強制使用符號名稱,這會降低程式可讀性
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/ReplaceTypeCodeWithClass/ReplaceTypeCodeWithClass.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.OrganizingData.ReplaceTypeCodeWithClass
8 | {
9 | public class ReplaceTypeCodeWithClass
10 | {
11 | public void Sample()
12 | {
13 | Person thePerson = new Person(BloodGroup.A);
14 | var code = thePerson.BloodGroup.Code;
15 | thePerson.BloodGroup = BloodGroup.AB;
16 | }
17 |
18 | public class Person
19 | {
20 | private BloodGroup _bloodGroup;
21 |
22 | public BloodGroup BloodGroup
23 | {
24 | get
25 | {
26 | return this._bloodGroup;
27 | }
28 |
29 | set
30 | {
31 | this._bloodGroup = value;
32 | }
33 | }
34 |
35 | public Person(BloodGroup bloodGroup)
36 | {
37 | this._bloodGroup = bloodGroup;
38 | }
39 | }
40 |
41 | public class BloodGroup
42 | {
43 | public static BloodGroup O = new BloodGroup(0);
44 |
45 | public static BloodGroup A = new BloodGroup(1);
46 |
47 | public static BloodGroup B = new BloodGroup(2);
48 |
49 | public static BloodGroup AB = new BloodGroup(3);
50 |
51 | private static BloodGroup[] _values = { O, A, B, AB };
52 |
53 | private int _code;
54 |
55 | public int Code
56 | {
57 | get
58 | {
59 | return this._code;
60 | }
61 | }
62 |
63 | public BloodGroup(int code)
64 | {
65 | this._code = code;
66 | }
67 |
68 | private static BloodGroup GetCode(int arg)
69 | {
70 | return _values[arg];
71 | }
72 | }
73 | }
74 | }
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/ReplaceTypeCodeWithStateOrStrategy/README.md:
--------------------------------------------------------------------------------
1 | ## 以State/Strategy取代型別代碼(Replace Type Code With State/Strategy)
2 |
3 | 有一個type code,它會影響class的行為,但你無法使用subclassing。
4 |
5 | 以state object(專門描述狀態的物件)取代type code
6 |
7 |
8 | ## 優點:
9 | * 如果type code的值在物件生命週期中發生變化,或其他原因使得宿主類別不能被subclassing,就使用這個原則。
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/ReplaceTypeCodeWithStateOrStrategy/ReplaceTypeCodeWithStateOrStrategy.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Linq;
5 | using System.Net.Http.Headers;
6 | using System.Net.NetworkInformation;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace RefactorPractice.OrganizingData.ReplaceTypeCodeWithStateOrStrategy
11 | {
12 | public class ReplaceTypeCodeWithStateOrStrategy
13 | {
14 | public class Employee
15 | {
16 | private EmployeeType _type;
17 |
18 | private int _monthlySalary;
19 |
20 | private int _commission;
21 |
22 | private int _bonus;
23 |
24 | public int Type
25 | {
26 | get
27 | {
28 | return this._type.GetTypeCode();
29 | }
30 | set
31 | {
32 | switch (value)
33 | {
34 | case EmployeeType.ENGINEER:
35 | this._type = new Enginer();
36 | break;
37 |
38 | case EmployeeType.MANAGER:
39 | this._type = new Manager();
40 | break;
41 |
42 | case EmployeeType.SALESMAN:
43 | this._type = new SalesMan();
44 | break;
45 |
46 | default:
47 | throw new ArgumentException();
48 | }
49 | }
50 | }
51 |
52 | public Employee(int type)
53 | {
54 | this._type = EmployeeType.NewType(type);
55 | }
56 |
57 | private int PayAmount()
58 | {
59 | switch (this.Type)
60 | {
61 | case EmployeeType.ENGINEER: return _monthlySalary;
62 | case EmployeeType.SALESMAN: return _monthlySalary * _commission;
63 | case EmployeeType.MANAGER: return _monthlySalary * _bonus;
64 | default:
65 | throw new ArgumentException();
66 | }
67 | }
68 | }
69 |
70 | public class Enginer : EmployeeType
71 | {
72 | public override int GetTypeCode()
73 | {
74 | return ENGINEER;
75 | }
76 | }
77 |
78 | public class Manager : EmployeeType
79 | {
80 | public override int GetTypeCode()
81 | {
82 | return MANAGER;
83 | }
84 | }
85 |
86 | public class SalesMan : EmployeeType
87 | {
88 | public override int GetTypeCode()
89 | {
90 | return SALESMAN;
91 | }
92 | }
93 |
94 | public abstract class EmployeeType
95 | {
96 | public const int ENGINEER = 0;
97 |
98 | public const int SALESMAN = 1;
99 |
100 | public const int MANAGER = 2;
101 |
102 | public abstract int GetTypeCode();
103 |
104 | public static EmployeeType NewType(int code)
105 | {
106 | switch (code)
107 | {
108 | case ENGINEER:
109 | return new Enginer();
110 |
111 | case SALESMAN:
112 | return new SalesMan();
113 |
114 | case MANAGER:
115 | return new Manager();
116 |
117 | default:
118 | throw new ArgumentException();
119 | }
120 | }
121 | }
122 | }
123 | }
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/ReplaceTypeCodeWithSubclasses/README.md:
--------------------------------------------------------------------------------
1 | ## 以子類別取代型別代碼(Replace Type Code With Subclasses)
2 |
3 | 有一個不變的type code,它會影響class的行為。
4 |
5 | 以一個subclass取代這個type code。
6 |
7 | ## 優點:
8 | * 如果你面對的type code會影響其宿主類別的行為,最好的辦法就是借助多型來處理變化行為。
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/ReplaceTypeCodeWithSubclasses/ReplaceTypeCodeWithSubclasses.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.OrganizingData.ReplaceTypeCodeWithSubclasses
8 | {
9 | internal class ReplaceTypeCodeWithSubclasses
10 | {
11 | public class Employee
12 | {
13 | private int _type;
14 |
15 | public int Type
16 | {
17 | get
18 | {
19 | return this._type;
20 | }
21 | }
22 |
23 | public const int ENGINEER = 0;
24 |
25 | public const int SALESMAN = 1;
26 |
27 | public const int MANAGER = 2;
28 |
29 | protected Employee(int type)
30 | {
31 | this._type = type;
32 | }
33 |
34 | public static Employee Create(int type)
35 | {
36 | switch (type)
37 | {
38 | case Employee.ENGINEER: return new Engineer();
39 | case Employee.MANAGER: return new Manager();
40 | case Employee.SALESMAN: return new SalesMan();
41 | default: throw new ArgumentException();
42 | }
43 | }
44 | }
45 |
46 | public class Engineer : Employee
47 | {
48 | public Engineer() : base(Employee.ENGINEER)
49 | {
50 | }
51 |
52 | public int Type
53 | {
54 | get
55 | {
56 | return Employee.ENGINEER;
57 | }
58 | }
59 | }
60 |
61 | public class Manager : Employee
62 | {
63 | public Manager() : base(Employee.MANAGER)
64 | {
65 | }
66 |
67 | public int Type
68 | {
69 | get
70 | {
71 | return Employee.MANAGER;
72 | }
73 | }
74 | }
75 |
76 | public class SalesMan : Employee
77 | {
78 | public SalesMan() : base(Employee.SALESMAN)
79 | {
80 | }
81 |
82 | public int Type
83 | {
84 | get
85 | {
86 | return Employee.SALESMAN;
87 | }
88 | }
89 | }
90 | }
91 | }
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/SelfEncapsulateField/README.md:
--------------------------------------------------------------------------------
1 | ## 自我封裝欄位 (Self Encapsulate Field)
2 |
3 | 你直接存取一個欄位,但與欄位之間耦合關係逐漸加重。
4 | 為這個欄位建立取值/設值(get/set),並只以這些函式來存取欄位。
5 |
6 | ## 優點:
7 | * 直接存取欄位的程式碼比較好閱讀
8 | * 間接存取欄位的好處是,可以覆寫一個函式而改變取得資料的途徑。
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/OrganizingData/SelfEncapsulateField/SelfEncapsulateField.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.OrganizingData.SelfEncapsulateField
8 | {
9 | public class SelfEncapsulateField
10 | {
11 | public class IntRange
12 | {
13 | public int Low { get; set; }
14 |
15 | public int High { get; set; }
16 |
17 | public IntRange(int low, int high)
18 | {
19 | this.Low = low;
20 | this.High = high;
21 | }
22 |
23 | public bool Includes(int arg)
24 | {
25 | return arg >= this.Low && arg <= this.High;
26 | }
27 |
28 | public void Grow(int factor)
29 | {
30 | this.High = this.High * factor;
31 | }
32 | }
33 |
34 | public class CappedRange : IntRange
35 | {
36 | public int Cap;
37 |
38 | public int High { get { return Math.Min(base.High, this.Cap); } }
39 |
40 | public CappedRange(int low, int high, int cap) : base(low, high)
41 | {
42 | this.Cap = cap;
43 | }
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/RefactorPractice/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using RefatorPractice.Ch1Lab;
5 |
6 | namespace RefatorPractice
7 | {
8 | internal class Program
9 | {
10 | private static void Main(string[] args)
11 | {
12 | var customer = new Customer("Bryan");
13 | var rental = new Rental(new Movie("Movie1", 0), 2);
14 | customer.AddRental(rental);
15 | var result = customer.GetStatement();
16 | Console.WriteLine(result);
17 | Console.Read();
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/RefactorPractice/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 組件的一般資訊是由下列的屬性集控制。
6 | // 變更這些屬性的值即可修改組件的相關
7 | // 資訊。
8 | [assembly: AssemblyTitle("RefactorPractice")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("RefactorPractice")]
13 | [assembly: AssemblyCopyright("Copyright © 2017")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 將 ComVisible 設為 false 可對 COM 元件隱藏
18 | // 組件中的類型。若必須從 COM 存取此組件中的類型,
19 | // 的類型,請在該類型上將 ComVisible 屬性設定為 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 下列 GUID 為專案公開 (Expose) 至 COM 時所要使用的 typelib ID
23 | [assembly: Guid("dc520388-fbcd-4a58-98bc-ebc9beda2588")]
24 |
25 | // 組件的版本資訊由下列四個值所組成:
26 | //
27 | // 主要版本
28 | // 次要版本
29 | // 組建編號
30 | // 修訂編號
31 | //
32 | // 您可以指定所有的值,或將組建編號或修訂編號設為預設值
33 | // 指定為預設值:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/RefactorPractice/RefactorPractice.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {DC520388-FBCD-4A58-98BC-EBC9BEDA2588}
8 | Exe
9 | RefactorPractice
10 | RefactorPractice
11 | v4.5.2
12 | 512
13 | true
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
--------------------------------------------------------------------------------
/RefactorPractice/RefactorPractice.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27004.2009
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RefactorPractice", "RefactorPractice.csproj", "{DC520388-FBCD-4A58-98BC-EBC9BEDA2588}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RefactorPractice.UnitTest", "..\RefactorPractice.UnitTest\RefactorPractice.UnitTest.csproj", "{65544821-9A45-4209-900D-CE53136B51D8}"
9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{55D9128D-433F-40A1-9061-91B261BB6E93}"
11 | ProjectSection(SolutionItems) = preProject
12 | ..\README.md = ..\README.md
13 | EndProjectSection
14 | EndProject
15 | Global
16 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
17 | Debug|Any CPU = Debug|Any CPU
18 | Release|Any CPU = Release|Any CPU
19 | EndGlobalSection
20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
21 | {DC520388-FBCD-4A58-98BC-EBC9BEDA2588}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
22 | {DC520388-FBCD-4A58-98BC-EBC9BEDA2588}.Debug|Any CPU.Build.0 = Debug|Any CPU
23 | {DC520388-FBCD-4A58-98BC-EBC9BEDA2588}.Release|Any CPU.ActiveCfg = Release|Any CPU
24 | {DC520388-FBCD-4A58-98BC-EBC9BEDA2588}.Release|Any CPU.Build.0 = Release|Any CPU
25 | {65544821-9A45-4209-900D-CE53136B51D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
26 | {65544821-9A45-4209-900D-CE53136B51D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
27 | {65544821-9A45-4209-900D-CE53136B51D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
28 | {65544821-9A45-4209-900D-CE53136B51D8}.Release|Any CPU.Build.0 = Release|Any CPU
29 | EndGlobalSection
30 | GlobalSection(SolutionProperties) = preSolution
31 | HideSolutionNode = FALSE
32 | EndGlobalSection
33 | GlobalSection(ExtensibilityGlobals) = postSolution
34 | SolutionGuid = {11FF58F1-48FE-48E9-B6D4-544096BAAE07}
35 | EndGlobalSection
36 | EndGlobal
37 |
--------------------------------------------------------------------------------
/RefactorPractice/SimplifyingConditionalExpressions/ConsolidateConditionalExpression/ConsolidateConditionalExpression.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.SimplifyingConditionalExpressions.ConsolidateConditionalExpression
8 | {
9 | internal class ConsolidateConditionalExpression
10 | {
11 | public class LogicOR
12 | {
13 | private int _seniority;
14 |
15 | private int _monthsDisabled;
16 |
17 | private bool _isPartTime;
18 |
19 | private double DisabilityAmount()
20 | {
21 | if (IsNotEligibleForDisability())
22 | {
23 | return 0;
24 | }
25 |
26 | return 1;
27 | }
28 |
29 | private bool IsNotEligibleForDisability()
30 | {
31 | return _seniority < 2 || _monthsDisabled > 12 || _isPartTime;
32 | }
33 | }
34 |
35 | public class LogicANDs
36 | {
37 | public double Sample()
38 | {
39 | return this.OnVacation() && this.LengthOfService() > 10 ? 1 : 0.5;
40 | }
41 |
42 | private int LengthOfService()
43 | {
44 | throw new NotImplementedException();
45 | }
46 |
47 | private bool OnVacation()
48 | {
49 | throw new NotImplementedException();
50 | }
51 | }
52 | }
53 | }
--------------------------------------------------------------------------------
/RefactorPractice/SimplifyingConditionalExpressions/ConsolidateConditionalExpression/README.md:
--------------------------------------------------------------------------------
1 | ## 合併條件式(Consolidate Conditional Expression)
2 |
3 | 有一系列的條件測試,都得到相同的結果
4 |
5 | 將這些測試合併為一個條件式,並將這個條件式提煉成一個函式
6 |
7 | ## 優點:
8 | * 可以讓一次檢查的用意更清晰。
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/SimplifyingConditionalExpressions/ConsolidateDuplicateConditionalFragments/ConsolidateDuplicateConditionalFragments.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.SimplifyingConditionalExpressions.ConsolidateDuplicateConditionalFragments
8 | {
9 | internal class ConsolidateDuplicateConditionalFragments
10 | {
11 | public void Sample()
12 | {
13 | var total = 0.0D;
14 | var price = 0.0D;
15 | if (IsSpecialDeal())
16 | {
17 | total = price * 0.95;
18 | }
19 | else
20 | {
21 | total = price * 0.98;
22 | }
23 | this.Send();
24 | }
25 |
26 | private bool IsSpecialDeal()
27 | {
28 | throw new NotImplementedException();
29 | }
30 |
31 | private void Send()
32 | {
33 | throw new NotImplementedException();
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/RefactorPractice/SimplifyingConditionalExpressions/ConsolidateDuplicateConditionalFragments/README.md:
--------------------------------------------------------------------------------
1 | ## 合併重複的條件片段(Consolidate Duplicate Conditional Fragments)
2 |
3 | 在這個條件式的每個分支上有著相同的一段程式碼。
4 |
5 | 將這段重複的程式碼搬移到條件式之外
6 |
7 | ## 優點:
8 | * 如果發現條件式分支內都執行了相同的某段程式碼,應該要把這段程式碼搬移到條件式外,
9 | 這樣才能清楚表達那些東西是會變化,那些不會。
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/SimplifyingConditionalExpressions/DecomposeConditional/DecomposeConditional.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.SimplifyingConditionalExpressions.DecomposeConditional
8 | {
9 | internal class DecomposeConditional
10 | {
11 | private double _winterRate;
12 |
13 | private double _winterServiceCharge;
14 |
15 | private double _summerRate;
16 |
17 | public void Sample()
18 | {
19 | double charge = 0.0D;
20 | double quantity = 0.0D;
21 |
22 | if (NotSummer(DateTime.Now))
23 | {
24 | charge = SummerCharge(quantity);
25 | }
26 | else
27 | {
28 | charge = WinterCharge(quantity);
29 | }
30 | }
31 |
32 | private double WinterCharge(double quantity)
33 | {
34 | return quantity * _summerRate;
35 | }
36 |
37 | private double SummerCharge(double quantity)
38 | {
39 | return quantity * _winterRate + _winterServiceCharge;
40 | }
41 |
42 | private static bool NotSummer(DateTime now)
43 | {
44 | DateTime SUMMER_START = new DateTime();
45 | DateTime SUMMER_END = new DateTime();
46 | return now <= SUMMER_START || now >= SUMMER_END;
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/RefactorPractice/SimplifyingConditionalExpressions/DecomposeConditional/README.md:
--------------------------------------------------------------------------------
1 | ## 分解條件式(Decompose Conditional)
2 |
3 | 有一個複雜條件式(if then else)。
4 |
5 | 從if、then、else三個段落中分別提煉獨立函式
6 |
7 | ## 優點:
8 | * 複雜的條件邏輯是最常導致複雜度上升的原因,可以將它分解成多個獨立函式,並為新函式命名,能夠表達函式的意思
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/SimplifyingConditionalExpressions/IntroduceAssertion/README.md:
--------------------------------------------------------------------------------
1 | ## 引入斷言(Introduce Assertion)
2 |
3 | 某一段程式碼需要對狀態做出某種假設
4 |
5 | 以Assertion(斷言)明確表現這種假設
6 |
7 | ## 優點:
8 | * Assertion是一個條件式,應該總是為真。如果他失敗,代表程式有發生問題。
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/SimplifyingConditionalExpressions/IntroduceNullObject/IntroduceNullObject.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.SimplifyingConditionalExpressions.IntroduceNullObject
8 | {
9 | internal class IntroduceNullObject
10 | {
11 | public void Sample()
12 | {
13 | Customer customer = (new Site()).Customer;
14 | BillingPlan plan = new BillingPlan();
15 | customer.Plan = plan;
16 | var customerName = customer.Name;
17 | int weeksDelinquent = customer.History.GetWeeksDelinquentInLastYear();
18 | }
19 |
20 | public class Site
21 | {
22 | private Customer _customer;
23 |
24 | public Customer Customer
25 | {
26 | get
27 | {
28 | return this._customer == null ? Customer.NewNull() : this._customer;
29 | }
30 | }
31 | }
32 |
33 | public class Customer
34 | {
35 | public string Name { get; set; }
36 |
37 | public BillingPlan Plan { get; set; }
38 |
39 | public PaymentHistory History { get; set; }
40 |
41 | public bool IsNull()
42 | {
43 | return false;
44 | }
45 |
46 | protected Customer()
47 | {
48 | }
49 |
50 | public static Customer NewNull()
51 | {
52 | return new NullCustomer();
53 | }
54 | }
55 |
56 | public class BillingPlan
57 | {
58 | }
59 |
60 | public class PaymentHistory
61 | {
62 | public int GetWeeksDelinquentInLastYear()
63 | {
64 | return 0;
65 | }
66 |
67 | public static PaymentHistory NewNull()
68 | {
69 | return new NullPaymentHistory();
70 | }
71 | }
72 |
73 | public class NullCustomer : Customer
74 | {
75 | public bool IsNull()
76 | {
77 | return true;
78 | }
79 |
80 | public string Name
81 | {
82 | get
83 | {
84 | return "occupant";
85 | }
86 | }
87 |
88 | private BillingPlan _plan;
89 |
90 | public BillingPlan Plan
91 | {
92 | set
93 | {
94 | this._plan = value;
95 | }
96 | }
97 |
98 | public PaymentHistory History
99 | {
100 | get
101 | {
102 | return PaymentHistory.NewNull();
103 | }
104 | }
105 | }
106 |
107 | public class NullPaymentHistory : PaymentHistory
108 | {
109 | public int GetWeeksDelinquentInLastYear()
110 | {
111 | return 0;
112 | }
113 | }
114 | }
115 | }
--------------------------------------------------------------------------------
/RefactorPractice/SimplifyingConditionalExpressions/IntroduceNullObject/README.md:
--------------------------------------------------------------------------------
1 | ## 引入Null Object(Introduce NullObject)
2 |
3 | 需要反覆檢查某個物件是否為null value。
4 |
5 | 將null value替換成null object
6 |
7 | ## 優點:
8 | * 可以不必再關注物件是什麼型別,只要關注呼叫該行為即可。
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/SimplifyingConditionalExpressions/RemoveControlFlag/README.md:
--------------------------------------------------------------------------------
1 | ## 移除控制旗標(Remove Control Flag)
2 |
3 | 在一系列布林運算式中,某個變數帶有控制旗標。
4 |
5 | 以break或return取代旗標
6 |
7 | ## 優點:
8 | * 去除控制旗標會讓條件式真正的用途會清晰許多。
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/SimplifyingConditionalExpressions/RemoveControlFlag/RemoveControlFlag.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.SimplifyingConditionalExpressions.RemoveControlFlag
8 | {
9 | internal class RemoveControlFlag
10 | {
11 | public class WithBreak
12 | {
13 | private void CheckSecurity(string[] people)
14 | {
15 | for (int i = 0; i < people.Length; i++)
16 | {
17 | if (people[i].Equals("Don"))
18 | {
19 | SendAlert();
20 | break;
21 | }
22 | if (people[i].Equals("John"))
23 | {
24 | SendAlert();
25 | break;
26 | }
27 | }
28 | }
29 |
30 | private void SendAlert()
31 | {
32 | throw new NotImplementedException();
33 | }
34 | }
35 |
36 | public class WithReturn
37 | {
38 | private void CheckSecurity(string[] people)
39 | {
40 | var found = FoundMiscreant(people);
41 | SomeLaterCode(found);
42 | }
43 |
44 | private string FoundMiscreant(string[] people)
45 | {
46 | for (int i = 0; i < people.Length; i++)
47 | {
48 | if (people[i].Equals("Don"))
49 | {
50 | SendAlert();
51 | return "Don";
52 | }
53 | if (people[i].Equals("John"))
54 | {
55 | SendAlert();
56 | return "John";
57 | }
58 | }
59 |
60 | return "";
61 | }
62 |
63 | private void SomeLaterCode(string found)
64 | {
65 | throw new NotImplementedException();
66 | }
67 |
68 | private void SendAlert()
69 | {
70 | throw new NotImplementedException();
71 | }
72 | }
73 | }
74 | }
--------------------------------------------------------------------------------
/RefactorPractice/SimplifyingConditionalExpressions/ReplaceConditionalWithPolymorphism/README.md:
--------------------------------------------------------------------------------
1 | ## 以多型取代條件式(Replace Conditional With Polymorphism)
2 |
3 | 有個條件式,根據物件型別不同而選擇不同的行為。
4 |
5 | 將這個條件式每個分支放進一個一個subclass內的複寫函式中,然後將原始函式宣告成抽象。
6 |
7 | ## 優點:
8 | * 多型可以根據物件的不同型別採取不同的行為,可以不必寫明顯的條件式。
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/SimplifyingConditionalExpressions/ReplaceConditionalWithPolymorphism/ReplaceConditionalWithPolymorphism.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.SimplifyingConditionalExpressions.ReplaceConditionalWithPolymorphism
8 | {
9 | internal class ReplaceConditionalWithPolymorphism
10 | {
11 | public class Employee
12 | {
13 | public const int ENGINERR = 0;
14 | public const int SALESMAN = 1;
15 | public const int MANAGER = 2;
16 |
17 | private EmployeeType _type;
18 |
19 | public int MonthlySalary { get; set; }
20 |
21 | public int Commission { get; set; }
22 |
23 | public int Bonus { get; set; }
24 |
25 | public int PayAmount()
26 | {
27 | return this._type.PayAmount(this);
28 | }
29 |
30 | public int Type
31 | {
32 | get
33 | {
34 | return this._type.GetTypeCode();
35 | }
36 | }
37 | }
38 |
39 | public abstract class EmployeeType
40 | {
41 | public abstract int GetTypeCode();
42 |
43 | public abstract int PayAmount(Employee emp);
44 | }
45 |
46 | public class Engineer : EmployeeType
47 | {
48 | public override int GetTypeCode()
49 | {
50 | return Employee.ENGINERR;
51 | }
52 |
53 | public override int PayAmount(Employee emp)
54 | {
55 | return emp.MonthlySalary;
56 | }
57 | }
58 |
59 | public class SalesMan : EmployeeType
60 | {
61 | public override int GetTypeCode()
62 | {
63 | return Employee.SALESMAN;
64 | }
65 |
66 | public override int PayAmount(Employee emp)
67 | {
68 | return emp.MonthlySalary + emp.Commission;
69 | }
70 | }
71 |
72 | public class Manager : EmployeeType
73 | {
74 | public override int GetTypeCode()
75 | {
76 | return Employee.MANAGER;
77 | }
78 |
79 | public override int PayAmount(Employee emp)
80 | {
81 | return emp.MonthlySalary + emp.Bonus;
82 | }
83 | }
84 | }
85 | }
--------------------------------------------------------------------------------
/RefactorPractice/SimplifyingConditionalExpressions/ReplaceNestedConditionalWithGuardClauses/README.md:
--------------------------------------------------------------------------------
1 | ## 以衛述句取代巢狀條件式(Replace Nested Conditional With Guard Clauses)
2 |
3 | 函式中的條件邏輯使人難以看清正常的執行路徑。
4 |
5 | 使用衛述句(Guard Clauses)表現所有特殊情況
6 |
7 | ## 優點:
8 | * 衛述句代表的意義是`這種情況很罕見,如果有發生請做必要的工作,然後退出`。
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/RefactorPractice/SimplifyingConditionalExpressions/ReplaceNestedConditionalWithGuardClauses/ReplaceNestedConditionalWithGuardClauses.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace RefactorPractice.SimplifyingConditionalExpressions.ReplaceNestedConditionalWithGuardClauses
8 | {
9 | internal class ReplaceNestedConditionalWithGuardClauses
10 | {
11 | private bool _isDead;
12 |
13 | private bool _isSeparated;
14 |
15 | private bool _isRetired;
16 |
17 | public double GetPayAmount()
18 | {
19 | if (_isDead)
20 | {
21 | return DeadAmount();
22 | }
23 | if (_isSeparated)
24 | {
25 | return SeparatedAmount();
26 | }
27 | if (_isRetired)
28 | {
29 | return RetiredAmount();
30 | }
31 | return NormalPayAmount();
32 | }
33 |
34 | private double NormalPayAmount()
35 | {
36 | throw new NotImplementedException();
37 | }
38 |
39 | private double RetiredAmount()
40 | {
41 | throw new NotImplementedException();
42 | }
43 |
44 | private double SeparatedAmount()
45 | {
46 | throw new NotImplementedException();
47 | }
48 |
49 | private double DeadAmount()
50 | {
51 | throw new NotImplementedException();
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------