Refactoring-bad taste of code (1)

Source: Internet
Author: User
1. Duplicated code (repeated code)

Duplicated Code is the first among the stinks. If you see the same program structure in more than one location, the program will become better if you are sure to combine them into one.

The simplest duplicated code is [two functions in the same class contain the same expression]. At this time, you need to use the extract method to extract duplicate code, and then let the two locations call the extracted code.

Another common case is that [two mutual sibling (sibling) subclasses contains the same expression]. To avoid this situation, you only need to use the extract method for both classes, and then use the pull up method for the extracted code to push it into the superclass. If the code is similar but not completely the same, you must use the extract method to cut apart the similarity and difference parts to form a separate function. Then you may find that you can use form template method to obtain a template method design pattern. If some functions use different algorithms to do the same thing, you can choose a clearer one and use substitute algorithm to replace the algorithms of other functions.

If duplicated code appears in two unrelated classes, you should consider using extract class for one of them and refining repeated code into one independent class, then use the new class in another class. However, the function where the repeated code is located may indeed belong to only one class, and the other class can only call it, or this function may belong to the third class, the other two classes should reference the third class. You must decide where the function is most suitable and ensure that it will not appear anywhere else after it is placed.

2. Long method (long function)

Objects with [Short functions] (short methods) will be better and longer-lived. People who are not familiar with object-oriented technology often feel that the object program only has endless delegation (delegation) and does not perform any computing at all. After living with such programs for several years, you will know how valuable these small functions are. [Indirect layer] All benefits-interpreting, sharing, and selection-are supported by small functions.

A long time ago, programmers realized that the longer the program, the more difficult it is to understand. In early programming languages, [subprogram calling actions] requires additional overhead, which makes small method less desirable, modern OO language almost eliminates the [extra overhead of function calling actions] in the process. But the reader of the code is still a lot effort-consuming, because he must often switch the context to see what the subroutine has done. Some development environments allow users to see two functions at the same time, which helps you save some trouble, but the key to making small method easy to understand is a good name. If you can give a good name to a function, the reader can understand the function's role through the name, without having to look at what is written in it.

The final result is that you should break down functions more aggressively. We follow the principle that every time we feel that we need to annotate something, we write what needs to be explained into an independent function, it is named after its purpose (rather than implementation method. We can do this for a group or even just one line of code. Even if the replaced function call action is longer than the function itself, we should not hesitate to do so as long as the function name can explain its purpose. The key lies not in the function length, but in the semantic distance between the function [What to Do] and [How to Do.

In 99%, to reduce the function, you only need to use the extract method. Find the appropriate components in the function and extract them to form a new function.

If a function contains a large number of parameters and temporary variables, they will hinder your function extraction. If you try to use the extract method, many of these parameters and temporary variables will eventually be passed to the extracted new function, resulting in almost no readability improvement. Ah yes, you can use replace temp with query frequently to make too long parameter columns more concise.

If you have already done so and there are still too many temporary variables and parameters, you should come up with our killer: replace method with method object.

How can I determine which code to extract? A good trick is to look for comments. They usually point out the signal of [semantic distance between code usage and implementation techniques. If there is a line of comments in the Code preface, it reminds you that you can replace this code with a function, and you can name this function based on the comments. Even if there is only one line of code, if it needs to be annotated, it is worth extracting it into an independent function.

Conditional and loop are often extracted signals. You can use decompose conditional to process conditional expressions. As for the loop, you should extract the loop and its code into an independent function.

3. Large Class (over-category)

If you want to use a single class to do too many things, there will usually be too many instance variables in it. Once this happens, the duplicated code comes one after another.

You can use extract class to extract several variables into the new class. When refining, you should select variables related to each other in the class and keep them all the time. For example, "depositamount" and "depositcurrency" may belong to the same class. Generally, if several variables in the class have the same prefix or suffix, this means they have the opportunity to be extracted into a certain component. If this component is suitable as a subclass, you will find that extract subclass is often relatively simple.

Sometimes the class does not use all instance variables at all times. If so, you may use extract class or extract subclass multiple times.

Like [too many instance variables], if there are too many code in the class, it is also an excellent breeding place for [] Code repetition, chaos, and death. The simplest solution is to remove the excess from the class. If there are five [Hundred-line functions], many of them have the same code, maybe you can convert them into five [ten-row functions] and ten [double-row functions].

Like [having too many instance variables], if a class has too much code, it is often suitable for extract class and extract subclass. Here is a useful technique: first determine how the client uses them, and then use the extract interface to use an interface for each. This may help you understand how to break down this class.

If your large class is a GUI class, you may need to move data and behavior to an independent domain object. You may need to keep duplicate data on both sides and synchronize the data. Duplicate observed data tells you how to do this. In this case, especially if you use the old AWT component, you can remove the GUI class and replace it with the swing component.

4. long parameter list (too long parameter column)

At the beginning of learning programming, the teacher taught us to pass in all the things required by the function as parameters. This is understandable, because we can only select global data, and global data is evil. Object technology has changed this situation, because if you don't have what you need, you can always call another object for you. Therefore, with an object, you do not have to pass everything required by the function as a parameter, you just need to give it enough to let the function get everything you need. Most of the things required by a function can be found in the host class of the function. The parameter columns of functions in object-oriented programs are usually much shorter than those in traditional programs.

This is a good phenomenon, because too long parameter columns are hard to understand. Too many parameters may cause inconsistency and are not easy to use. Once you need more data, You have to modify it. If you pass an object to a function, most modifications are unnecessary, because you may only need to add one or two requests (within the function) to get more data.

If you [send a request to an existing object] to obtain a copy of the data originally in the parameter column, you should activate the reconstruction criterion replace parameter with method. The preceding object may be a value field in the class to which the function belongs, or it may be another parameter. You can also use the preserve whole object to collect a bunch of data from the same object and replace them with this object. If some data lacks a reasonable object ownership, you can use introduce parameter object to create a [parameter object] for them.

An important exception exists here. Sometimes you obviously do not want to create a certain dependency between the [called object] and [large object. At this time, it is reasonable to split the data from the object as a separate parameter. However, pay attention to the cost. If the parameter columns are too long or change too frequently, you need to reconsider your dependency structure.

5. Divergent change (divergent change)

We hope the software can be more easily modified-after all, the software should have been [Soft. Once modification is required, we hope to fall down to a certain point of the system and only make modifications here. If you cannot do this, you will find one of the two closely related pungent flavors.

If a class often changes in different directions for different reasons, divergent change appears. When you look at a class and say, "Well, if you add a new database, I have to modify these three functions. If a new financial tool appears, I have to modify these four functions ", at this time, it may be better to divide this object into two parts, so that each object can be modified only because of a change. Of course, you can only find this point after you join a new database or financial tool. All corresponding modifications to an external change should only occur in a single class, And all content in this new class should be reversed. To this end, you should find all the changes caused by a specific reason, and then extract them into another class using extract class.

6. Shotgun surgery (volume modification)

Shotgun surgery is similar to divergent change, but the opposite is true. If you encounter a change, you must make many small changes in many different classes to respond to it. The bad taste you face is shotgun surgery. If the code to be modified is spread around, it is not only difficult to find them, but also easy to forget an important modification.

In this case, you should use the move method and move field to put all the code to be modified into the same class. If there is no suitable class to place the code, create one. Generally, you can use inline class to put a series of related behaviors into the same class. This may cause a small amount of divergent changes, but you can handle it easily.

Divergent change refers to [a class is affected by multiple changes], and shotgun surgery refers to [a change causes multiple classes to modify]. In both cases, you may want to organize the code to achieve an ideal situation where [external changes] and [classes to be changed] present a one-to-one relationship.

7. Feature envy (Attachment)

All the main points of object technology are: This is a technology that [encapsulates data and the operational behaviors on it. The classic smell is that a function is more interested in a class than in its host class. The most common focus of this kind of sentiment is data. Countless times of experience, we can see that a function calls almost half a dozen value functions from another object to calculate a value. Therapy: Move this function to another location. You should use the move method to move it to the desired place. Sometimes only a part of functions suffer from this attachment. At this time, you should use the extract method to extract this part into an independent function, and then use the move method to take it to its dream home.

Of course, not all situations are that simple. A function often uses several classes, so where should it be placed? Our principle is: Determine which class has the most data [used by this function], and then put this function and that data together. If the extract method is used to break down the function into smaller functions and place them in different locations, the above steps will be easier to complete.

Several Complicated and sophisticated models have broken this rule. Speaking of this topic, the streategy and visitor of the [four giants] immediately jumped into my mind, and Kent Beck's self delegation was also popular. These modes are used to combat bad taste divergent change. The most fundamental principle is to put things that are always changing together. The behavior of [data] and [referencing this data] Always changes, but there are exceptions. If an exception occurs, we will move those actions and keep [changes only happen together]. Strategy and visitor allow you to easily modify function behavior because they isolate a small number of behavior that requires overwriting-and of course pay the price of [more than one indirect.

8. Data clumps (data dashboard)

Data items are like children: they like to stay together in groups. You can often see three or four identical data items in many places: the same value fields in two classes and the same parameters in many function signatures. These [always tied together with the data] should be put into their own objects. First, locate the vertices in the value form of the data and extract them into an independent object using extract class. Then focus on the function signature header and use introduce parameter object or preserve whole object to lose weight. The direct advantage of doing so is that many parameter columns can be shortened to simplify function call actions. Yes, because data clumps only cares about part of the value range of the new object, as long as you replace two (or more) value ranges with the new object, you will return the fare.

A good way to judge is to delete a large amount of data. Is other data meaningless? If they no longer have inquiries, this is a clear signal: You should create a new object for them.

Reducing the number of Value domains and parameter numbers can certainly lead to some bad taste, but more importantly, once you have a new object, you will have the opportunity to make the program a scent. After you get the new object, you can start looking for the feature envy, which helps you to point out various program behaviors in the [New Class. It doesn't take too long. All classes will make full use of their productivity in their small society.

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: info-contact@alibabacloud.com 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.