Reconstruction Method-Simplified function call [2], reconstruction method-Simplified Function
Total returned directory
Directory of this section
- Separate Query from Modifier (Separate the Query function from the modification function)
- Parameterize Method (parameters included in the function)
4 Separate Query from Modifier (Separate Query functions from modify functions) Summary
A function returns the object status value and modifies the object status (side effects ).
Create two different functions, one for query and the other for modification.
Motivation
No function with returned values should have any side effects. If a function "has both returned values and side effects", you should try to split the query action from the modification action.
Example
There is a function: once someone invades the security system, it returns the name of the intruder and sends an alarm:
class Security{ void CheckSecurity(string[] people) { string found = FoundMiscrent(people); } string FoundMiscrent(string[] people) { foreach (var person in people) { if (person == "Don") { SendAlert(); return "Don"; } if (person == "John") { SendAlert(); return "John"; } } return string.Empty; } void SendAlert() { }}
To separate the query action from the modification action, first create an appropriate query function so that it returns the same value as the modification function, without causing any side effects.
string FoundPerson(string[] people){ foreach (var person in people) { if (person == "Don") { return "Don"; } if (person == "John") { return "John"; } } return string.Empty;}
Then, replace all the return statements in the original function one by one, and call the new query function:
string FoundMiscrent(string[] people){ foreach (var person in people) { if (person == "Don") { SendAlert(); return FoundPerson(people); } if (person == "John") { SendAlert(); return FoundPerson(people); } } return FoundPerson(people);}
Now modify the caller and replace the original single caller with two calls: Call the modify function first, and then call the query function:
void CheckSecurity(string[] people){ FoundMiscrent(people); string found = FoundPerson(people);}
After replacement, change the return value of the modified function to void and modify the function name:
void SendAlert(string[] people){ foreach (var person in people { if (person == "Don") { SendAlert(); return; } if (person == "John") { SendAlert(); return; } }}
Of course, in this case, a lot of repeated code is obtained, because the same code as the query function is used in the modification function. Now we implement Substitute Algorithm to modify the function and try to make it more concise:
void SendAlert(string[] people){ if (FoundPerson(people) != "") { SendAlert(); }}
Summary
If a function only provides you with a value without any side effects, you can call this function at Will or move the call action to other places of the function. In short, there are fewer things to worry about.
5 Parameterize Method (parameters included in the function) Summary
Some functions do similar work, but they contain different values in the function ontology.
Create a single function to express those different values with Parameters.
Motivation
There are two functions: They do similar work, but the behavior varies slightly due to a few values. At this time, we can unify these separated functions and process those changes through parameters to simplify the problem.
Example
Let's take a look at a simple example:
class Employee{ public double Salary { get; set; } void TenPercentRaise() { Salary *= 1.1; } void FivePercentRaise() { Salary *= 1.05; }}
This code can be replaced with the following:
class Employee{ public double Salary { get; set; }
void Raise(double factor) { Salary *= 1 + factor; }}
Let's take a look at a slightly complex example:
class Dollars{ public Dollars(double result) { }}class Charge{ private Dollars BaseCharge() { double result = Math.Min(LastUsage(), 100) * 0.03; if (LastUsage() > 100) { result += (Math.Min(LastUsage(), 200) - 100) * 0.05; } if (LastUsage() > 200) { result += (LastUsage() - 200) * 0.07; } return new Dollars(result); } private int LastUsage() { return 201; }}
The above code can be replaced with the following:
class Charge{ private Dollars BaseCharge() { double result = UsageInRange(0, 100) * 0.03; result += UsageInRange(100, 200) * 0.05; result += UsageInRange(200, Int32.MaxValue) * 0.07; return new Dollars(result); } private int UsageInRange(int start, int end) { if (LastUsage() > start) { return Math.Min(LastUsage(), end) - start; } return 0; } private int LastUsage() { return 201; }}
The main point of this refactoring is to find code with repetition based on "a small number of values can be regarded as parameters.
Summary
This refactoring can remove duplicate code and improve flexibility, because this parameter can be used to handle more changes.
To Be Continued ......