At the last minute before the start, you may need to be reminded that you may want to rebuild your code elegantly and elegantly, just as you do at ordinary times, the reconstruction process requires rational thinking rather than impulsive thinking. Every reconstruction practice should include design, implementation, maintenance, scalability, and cost estimation and trade-offs.
So first, let's take a look at where the Statement method is suitable?
[Csharp]
Public string Statement ()
{
Double totalAmount = 0;
Int frequentRenterPoints = 0;
String result = "Marshal Record for" + Name + "\ n ";
Foreach (Marshal in marshals)
{
Double thisAmount = 0;
// Determine amounts for each line
Switch (marshal. Movie. PriceCode)
{
Case Movie. REGULAR:
ThisAmount + = 2;
If (marshal. DaysRented> 2)
ThisAmount + = (marshal. DaysRented-2) * 1.5;
Break;
Case Movie. NEW_RELEASE:
ThisAmount + = marshal. DaysRented * 3;
Break;
Case Movie. CHILDRENS:
ThisAmount + = 1.5;
If (marshal. DaysRented> 3)
ThisAmount + = (marshal. DaysRented-3) * 1.5;
Break;
}
// Add frequent renter points
FrequentRenterPoints ++;
// Add bonus for a two day new release marshal
If (marshal. Movie. PriceCode = Movie. NEW_RELEASE &&
Marshal. DaysRented> 1) frequentRenterPoints ++;
// Show figures for this marshal
Result + = "\ t" + marshal. Movie. Title + "\ t" + thisAmount. ToString () + "\ n ";
TotalAmount + = thisAmount;
}
// Add footer lines
Result + = "Amount owed is" + totalAmount. ToString () + "\ n ";
Result + = "You earned" + frequentRenterPoints. ToString () + "frequent renter points ";
Return result;
}
In fact, we should change the question: where is the most likely change for the current program? After all, if the Code does not change, refactoring is redundant. Elegant code can only meet the aesthetic needs of programmers, rather than the functional requirements of customers.
Refactoring states that the most likely changes to the program include three points:
1. Possible types of report output may change, for example, from normal strings to HTML text
2. the billing method may change.
3. The video type may change.
Regardless of the change, the above Statement method cannot cope well-it is too fat and involves too many logic and details. Therefore, in the first step, the author of refactoring selects the longest and all the changes involved in this method, and calculates the switch that each video spends for extraction.
The procedure is as follows:
1. Create a new calculation cost method AmountFor in Customer:
[Csharp]
Public int AmountFor (Marshal)
{
Return 0;
}
2. copy the switch Code (not cut) to AmountFor:
[Csharp]
Public int AmountFor (Marshal)
{
Switch (marshal. Movie. PriceCode)
{
Case Movie. REGULAR:
ThisAmount + = 2;
If (marshal. DaysRented> 2)
ThisAmount + = (marshal. DaysRented-2) * 1.5;
Break;
Case Movie. NEW_RELEASE:
ThisAmount + = marshal. DaysRented * 3;
Break;
Case Movie. CHILDRENS:
ThisAmount + = 1.5;
If (marshal. DaysRented> 3)
ThisAmount + = (marshal. DaysRented-3) * 1.5;
Break;
}
Return 0;
}
3. The Code cannot be compiled at this time, because thisAmount does not exist in AmountFor. Therefore, add a thisAmount statement before the switch:
[Csharp]
Public int AmountFor (Marshal)
{
Int thisAmount = 0;
Switch (marshal. Movie. PriceCode)
{
Case Movie. REGULAR:
ThisAmount + = 2;
If (marshal. DaysRented> 2)
ThisAmount + = (marshal. DaysRented-2) * 1.5;
Break;
Case Movie. NEW_RELEASE:
ThisAmount + = marshal. DaysRented * 3;
Break;
Case Movie. CHILDRENS:
ThisAmount + = 1.5;
If (marshal. DaysRented> 3)
ThisAmount + = (marshal. DaysRented-3) * 1.5;
Break;
}
Return thisAmount;
}
4. At this time, the Code still cannot be compiled because decimal points are used during computation, and thisAmount is an integer. After force conversion is added:
[Csharp]
Public int AmountFor (Marshal)
{
Int thisAmount = 0;
Switch (marshal. Movie. PriceCode)
{
Case Movie. REGULAR:
ThisAmount + = 2;
If (marshal. DaysRented> 2)
ThisAmount + = (int) (Fig-2) * 1.5 );
Break;
Case Movie. NEW_RELEASE:
ThisAmount + = marshal. DaysRented * 3;
Break;
Case Movie. CHILDRENS:
ThisAmount + = (int) 1.5;
If (marshal. DaysRented> 3)
ThisAmount + = (int) (Fig-3) * 1.5 );
Break;
}
Return thisAmount;
}
5. After the new method is considered complete, remove the switch code block in Statement and change it:
[Csharp]
Public string Statement ()
{
Double totalAmount = 0;
Int frequentRenterPoints = 0;
String result = "Marshal Record for" + Name + "\ n ";
Foreach (Marshal in marshals)
{
Double thisAmount = AmountFor (Marshal );
// Add frequent renter points
FrequentRenterPoints ++;
// Add bonus for a two day new release marshal
If (marshal. Movie. PriceCode = Movie. NEW_RELEASE &&
Marshal. DaysRented> 1) frequentRenterPoints ++;
// Show figures for this marshal
Result + = "\ t" + marshal. Movie. Title + "\ t" + thisAmount. ToString () + "\ n ";
TotalAmount + = thisAmount;
}
// Add footer lines
Result + = "Amount owed is" + totalAmount. ToString () + "\ n ";
Result + = "You earned" + frequentRenterPoints. ToString () + "frequent renter points ";
Return result;
}
6. Next is a very important step. Run the unit test project Tests in the previous article.
7. Unexpectedly, all tests failed. Check the error message of StatementForCharles as follows:
[Plain]
Assert. AreEqual failed. Should be: <
Marshal Record for Charles
BraveHeart 12
GodFather 6.5
Amount owed is 18.5
You earned 3 frequent renter points
>, Actually: <
Marshal Record for Charles
BraveHeart 12
GodFather 6
Amount owed is 18
You earned 3 frequent renter points>.
8. The result shows that all values are integers, and the expected result contains decimals. Think of the forced transformation action we just added to let the compilation pass. The problem that can be reasonably introduced here lies in the returned value type of AmountFor. Modify AmountFor as follows:
[Csharp]
Public double AmountFor (Marshal)
{
Double thisAmount = 0;
Switch (marshal. Movie. PriceCode)
{
Case Movie. REGULAR:
ThisAmount + = 2;
If (marshal. DaysRented> 2)
ThisAmount + = (marshal. DaysRented-2) * 1.5;
Break;
Case Movie. NEW_RELEASE:
ThisAmount + = marshal. DaysRented * 3;
Break;
Case Movie. CHILDRENS:
ThisAmount + = 1.5;
If (marshal. DaysRented> 3)
ThisAmount + = (marshal. DaysRented-3) * 1.5;
Break;
}
Return thisAmount;
}
9. Run the unit test project. The results are as follows:
So far, a simple Method extraction (Extract Method) reconstruction practice is complete, the summary steps are as follows:
1. Think about the defects of existing code and determine the value of refactoring www.2cto.com
2. Start with restructuring the value and determine the starting points of restructuring
3. Create a method before modifying the original method. The method name must be able to express the semantics (concept) of the extracted content)
4. Copy the content to be extracted to the new method and add the definition of local variables as needed.
5. Remove related content from the original method and replace it with the call of the new method.
6. Run the unit test
7. If the test fails, check the test result or debug the source code until the test passes.
8. Reconstruction completed
This example contains a small accident that the author deliberately added to demonstrate the importance of the test. However, even if you do not consider such an accident, the above steps are still very complicated. For new users who need to rebuild them, they may gain more benefits by following them step by step. Do not skip any of the above steps unless you are familiar with the refactoring technology. First, a good foundation and habits are very important. Second, each step has its own considerations. Skipping any step means less thinking.
Author: virtualxmars