Code Book 2 Reading Notes 11-Chapter 24 refactoring

Source: Internet
Author: User

Chapter 24 refactoring

24.2 introduction to refactoring
Refactoring Overview

"Changing the internal structure of the software without changing the external behavior of the software makes it easier to understand and modify it" (Fowler

1999 ).
· Reasons to refactor
Repeated code almost always represents a mistake in thoroughly decomposing the original design. Repeated Code also violates the"

Dry principle ": Do not repeat yourself" don't repeat yourself .". Another more incisive sentence is: "copying and pasting is the paradox of Design ".
2. Lengthy childProgram
3. The loop is too long or nested too deep.
4. classes with poor cohesion.
If you see that a class package takes a lot of tasks unrelated to each other, this class should be split into multiple classes, each

Class is responsible for a group of internally associated tasks.
5. The class interface does not provide hierarchical abstraction.
6. There are too many parameter lists.
7. The internal modification of classes is often limited to a certain part.
8. changes cause the same changes to multiple classes.
9. The same modification to the inheritance system
10. The case statement must be modified in the same way.
11. The data used at the same time is not organized in the form of classes.
If you see that you often operate on the same group of data, you should also ask yourself whether you should put the data and its operations

Organized into a class.
12. member functions use more features of other classes than their own classes.
This implies that this subroutine should be put into another class and then called in the original class.
13. Excessive use of basic data types
Example: If an integer is used in a program to represent a common entity, such as a currency, consider creating

A simple money class, so that the compiler can perform a type check on the money variable, you can also add the value assigned to the money

Security check. If both money and temperature are plastic, the compiler will not use them incorrectly.

A warning is given when bankbalance = recordlowtemperature is an assignment statement.
14. A class does nothing
Sometimes refactoring will cause a class to have nothing to do. If a class looks non-real, ask yourself if you can

Function is transferred to other classes, and then this class is completely removed.
15. A series of subprograms that transmit stray data.
Check your code and pass the data to a subroutine. Do you just want this subroutine to transfer the data to another one?

Subprograms. The transmitted data is called "stray data/tramp data ". This is not the case, so the specific number is passed.

Whether it is consistent with the abstract concepts represented by each subroutine interface. If the abstract concepts of these subprogram interfaces are the same

There is nothing wrong with transmitting data between them. If this is not the case, consider other methods to make the interfaces of different subprograms more consistent.
16. The man-in-the-middle object has nothing to do
17. The relationship between a class and other classes is too close.
18. Improper subroutine naming
19. Data members are set to public.
Setting data members to public is definitely a bad idea. This will blur the boundaries between interfaces and Implementations

Limitation, which violates the encapsulation principle and limits the flexibility of the class in the future.
20. A derived class only uses a few member functions of the base class.
In this case, the relationship between the derived class and the base class is changed from "is-a" to "has-". Converts the base class to

Data member, and then only provide the required member functions for the original derived class.
21. Annotations are used to explain obscure code
Annotation plays an important role in the program, but it should not be used to defend the existence of poor code. Evidence of proverbs

: "Do not write a document for poor code -- rewrite the code" (kernighan and plauger1978)
22. Using global variables
23. The setup code is used before the subroutine call, or the takedown code is used after the call.

Such code should be considered as a warning:
C ++ example: Setup code and final code before and after a subroutine call-bad practices
Withdrawtransaction withdrawal;
Withdrawal. setcustomerid (customerid );
Withdrawal. setbalance (balance );
Withdrawal. setwithdrawalamount (withdrawalamount );
Withdrawal. setwithdrawaldate (withdrawaldate );

Processwithdrawal (withdrawal );

Customerid = withdrawal. getcustomerid ();
Balance = withdrawal. getbalance ();
Withdrawalamount = withdrawal. getwithdrawalamount ();
Withdrawaldate = withdrawal. getwithdrawaldate ();

Another warning is that you have created a special constructor for withdrawaltransaction to complete a series

Simple data initialization. Your code may be like the following:
C ++ example: Setup code and final code before and after a subroutine call-bad practices
Withdrawal = new withdrawaltransaction (customerid, balance, withdrawalamount,

Withdrawaldate );
Withdrawal. processwithdrawal ();
Delete withdrawal;

You only need to use the setup code before sending a sub-program call, or use the final code after the call, you should ask yourself

Whether the interface of this subroutine reflects the correct abstraction. In this example, the processwithdrawal parameter list may be as follows:

C ++ example: Setup code and final code before and after a subroutine call-Good Practice
Processwithdrawal (customerid, balance, withdrawalamount, withdrawaldate );
Note that, if the problem is the opposite of the previous case, similar problems also exist. If you find that you have

After the withdrawaltransaction object, you often need to pass multiple values of the object to call a sub-program, just like in this example.

Similarly, you should consider refactoring the processwithdrawal interface by passing the withdrawaltransaction pair

Object, rather than a separate object member.
C ++ example: subprograms that need to be called by several member functions
Processwithdrawal (withdrawal. getcustomerid (),
Withdrawal. getbalance (),
Withdrawal. getwithdrawalamount (),
Withdrawal. getwithdrawaldate ());
These methods may be correct or wrong. It depends on the abstract interface of processwithdrawal (): The subroutine call is

Four independent data items are required, or a withdrawaltransaction object is required.

24. Some code in the program seems to be used at some time in the future.
Programmers are notorious for figuring out which functions the program may use in the future. "Advanced Design

(Designingahead) "is often subject to many foreseeable problems.

24.3 specific refactorings
Specific refactoring

· Data-level refactorings data-level Reconstruction
1. The appliance name constant replaces the mysterious Value
2. Make the variable name clearer and pass more information
3. concatenate expressions
Replace an intermediate variable with the expression that assigns a value to it.
4. Replace the expression with a function (in this way, the expression will not be repeated in the Code .)
5. Introduce intermediate Variables
6. replace a multi-purpose variable with multiple single-purpose Variables
7. Use local variables instead of parameters for local purposes
If a subroutine parameter used for input is used as a local variable internally, create a local

Variable to replace it.
8. Convert the basic data type to a class.
9. convert a group of type codes to a class or enumeration type.
10. convert a group of type codes into a base class and its corresponding Derived classes.
For example, for the outputtype base class, you can create a derived class such as screen, printer, and file.
11. convert an array to an object
If you are using an array with different elements of different types, you should use an object instead.

It. Convert each element in the array to each member of the class.

12. encapsulate the collection.
If a class returns a cluster, Multiple Cluster instances distributed everywhere will cause synchronization problems. Please let your type return

A read-only cluster that provides corresponding subroutines for adding and deleting elements to the cluster.
13. Use data classes to replace traditional records

· Statements-level refactorings statement-level Reconstruction
1. Break down the Boolean expression
2. convert a complex Boolean expression to a Boolean function with the correct name
3. duplicate code snippets in different parts of the merge Condition Statement
If identical code appears in the IF statement block and else statement block of a conditional statement

The code is moved to the end of the entire if-then-else statement block.
4. Use break or return instead of loop control variables
If a variable similar to done is used in a loop, replace it with break or return.
5. In the nested if-then-else statement, return immediately once the answer is known, rather than assigning a return value.
6. Replace conditional statements with polymorphism (especially repeated case statements)
The logic of many case statements in a structured program can be put into the inheritance relationship and implemented through multi-state function calls.
7. Create and use null objects instead of checking null values.

· Routine-level refactorings subroutine-level Reconstruction
1. Extract subroutines or methods
2. concatenate the subprogram code.
If the program of a subroutine is simple and its meaning is self-explanatory, you can directly use the code when using it.
3. Convert lengthy subprograms into classes
4. Easy to useAlgorithmReplacing complex algorithms
5. Add Parameters
If the subroutine needs more information from the caller, you can add its parameters to provide information for it.
6. Delete Parameters
If the subroutine no longer uses a parameter, delete it.
7. Separate the query operation from the modification operation.
Once a gettotals ()-like Operation changes the object state, the query function should be independent from the State change function.

. Provides two independent subprograms.
8. Merge similar subprograms and differentiate their functions through Parameters
9. Split the behavior dependent on the parameter subroutine
10. Pass the entire object instead of a specific Member
If multiple values of the same object are passed to a sub-program, check whether the interface can be modified to receive integers.

11. Pass a specific member instead of the entire object.
If you find that the only reason for creating an object is to pass it into a subroutine, consider whether the object can be repaired.

Modify this subroutine to receive specific data members rather than the entire object.
12. Downward transformation of Packaging

· Reconstruction of class implementation refactorings class implementation
1. convert a value object to a reference object
2. Convert the referenced object to a value object
3. Use Data initialization instead of virtual functions
4. Change the position of the member function or member data
Consider modifying the class inheritance system. These modifications can reduce the repetitive work of the derived class:
A. Move the subroutine to the base class.
B. Move the Member to the base class.
C. Move some code in the constructor to the base class.
The following changes can be used to specialize the derived classes:
A. Move the subroutine down to the derived class.
B. Move the Member to the derived class.
C. Move the constructor down to the derived class.
5. Extract special code as a derived class
6. Combine similar code and place it in the base class

· Class interface refactorings class interface Reconstruction
1. Put member functions in another class
Create a new member function in the target class, and then move the function body in the original class to the target class. Then in the old member

Function to call a new member function.
2. Change a class to two
3. delete a class
4. Remove delegation relationships
Sometimes Class A calls class B and class C, while Class A actually only calls Class B, and Class B should call class C. In this case

Consider whether a's abstraction of B's interface is appropriate. If B should call C, B should only call C.
5. Remove man-in-the-middle
Sometimes Class A calls class B and class B calls Class C, and sometimes it is better for Class A to directly call class C. Should I remove it?

Class B depends on how it works to maintain the integrity of Class B interfaces.
6. Use delegation instead of Inheritance
7. Use inheritance instead of delegation
8. introduce external member functions
9. Introduce extension classes
10. encapsulate exposed member variables
11. For Class Members that cannot be modified, delete the related set () member functions.
12. Hide member functions that are not used outside the class.
13. encapsulate unused member functions
14. Merge the base classes and derived classes with very similar implementations.

· System-level refactorings system-level Reconstruction
1. Create a clear index source for uncontrollable data.
2. Change one-way class contact to two-way class contact.
3. Change the two-way class contact to a single class contact.
4. Use the factory method mode instead of simply constructing functions.
5. Replace error handling code with exceptions.

24.4 refactoring safely
Security Reconstruction

Refactoring is a powerful technology to improve code quality. However, just like all powerful tools, if improperly used, refactoring gives you

It brings more benefits than it does. The following are some short suggestions to avoid incorrect refactoring.
1. Save the initial code
2. The pace of reconstruction should be smaller.
3. Only one rebuild at a time
4. list all the tasks to be done
5. Set a parking lot
6. Use multiple checkpoints
7. Use the compiler warning information
It is easy to escape small errors from the compiler's eyes. You 'd better set the warning level of the compiler to be as harsh as possible

. Once there are some small errors in the input, the compiler can immediately find them.
8. retest
9. Add test cases.
10. Check the modifications to the code.
11. Adjust the reconstruction method based on the risk level of reconstruction.

· Bad times to refactor should not be reconstructed
1. Do not use refactoring as a synonym for first writing and then modifying
2. Avoid using refactoring instead of rewriting

24.5 refactoring strategies
Reconstruction strategy
1. refactor when adding a subroutine
2. refactoring when adding classes
3. refactoring when fixing Defects
4. Focus on error-prone modules
5. Focus on high impurity modules
6. Improve the code you are processing in the maintenance Environment
7. Clearly define the boundary between the clean code and the poor code, and then try to move the code over this boundary.
Chaos in the real world does not mean that your code is as bad as it is. Think of your system as the ideal code.

The real world and the combination of interfaces from the former to the latter.

Key Points
1. modification is a task that the program will face throughout its life, including not only the initial development phase, but also after the first release.
2. The quality of the software in the Process of modification is either improved or deteriorated. The first rule of Software Evolution is that code evolution should improve the inherent quality of the program.

3. The key to successful refactoring is that programmers should learn to focus on the numerous warnings or "code stinks" that mark the need to refactor the code ".
4. Another factor for successful refactoring is that programmers should master a large number of specific refactoring methods.
5. the final point of successful reconstruction is to have a security reconstruction strategy. Some refactoring methods are better than other refactoring methods.
6. The best time to improve program quality during reconstruction in the development phase, because you can immediately turn your new dream of change into reality. Please Jane

We cherish the opportunity of these development stages.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.