Problems need to consider using refactoring
Shiyiying@hotmail.com) Zhejiang University Lingfeng Technology Development Company Director December 2001
This article
The second part, continue to tell questions that apply Refactoring should consider.
Any technology may have its own trouble. However, when we use a new technology, it may not be able to discover the problem that it brings, as Martin Fowler said: When learning a new technology that can greatly improve productivity, you can't see it can't Application occasion.
He compared the Refactoring's scenario and object-oriented appearance: the situation is just 10 years ago. It is not that I don't consider there is a restriction. Just because I don't know what the restrictions are, although I know the benefits of him.
But Martin Fowler and others have indeed observed some questions that Refactoring may trigger, we can take a look:
Database Many applications' code may be very strict with database structure. If you want to modify these code, you need to change the database structure and the original already existing.
O / R mapping can be used to solve this problem. Using a professional O / R mapping tool enables the migration of relational databases. However, even if this is, migration also needs to pay an additional price.
If you are not using a database, it is directly using the OO database, which can be smaller.
So, I recommend that every O / R mapping or OO database should be used every application application. The various enterprise application solutions that currently appear, such as J2EE itself provides such a framework.
If your code does not have such an isolation layer, you must manually or write a dedicated code to implement these migration.
Interface changes and publications have many refactoring operations (such as Rename Method Name "indeed changed the interface. Object-oriented promises to give you the freedom to achieve changes in the case of unchanged. But if the interface changes, then you have to be very careful.
In order to ensure that the observable behavior of the system is constant, you must ensure that changes in these interfaces will not affect the code you can't get. If you have the source code for all classes that use the interface, you can change these places simultaneously.
However, if you have no way to get all of these code, then you have to take additional ways. In fact, if your code is a code base (such as Sun JDK's collection framework) or an framework, then this is almost inevitable.
To make these code that depend on your old interface can continue, you must keep the old interface. Now you have two sets of interfaces, a set is old, a set of refactoring's new interface. You must assign calls to the old interface to the new interface. Don't copy the entire function body because it produces a lot of repetition code.
Although this method can solve the problem, it is very troublesome. Since Refactoring is usually involved, the transition between behavior is between different classes, if a method moves from one class to another class, then use this assigned method may require some unnecessary intermediate state or parameters. This will make your code make it difficult to understand and maintain, to a certain extent, to a certain extent, the role of the refactoring should play.
Therefore, this method should only be used in the transition period. Give the user a certain time, allowing the user code to gradually transfer to a new interface, after the forever, delete the old method, no longer support the old interface. This is also the meaning of the Java DepRecated API.
It is very difficult to protect the interface like this. You at least you need to maintain two sets of interfaces for a while to ensure that the customer code that uses your old interface can continue to use your new code, and Martin Fowler refers to the Published Interface. Although you can't avoid the publication of your part of the interface, no one can use your code, but premature announcement unnecessary interface will cause unnecessary trouble, just like Martin Fowler gives us Tips: Don't Publish Interface Prematurely With refactoring ideology armed their own design If you don't understand OO's thoughts, then you can't really use the OO language. Similarly, if you don't use Refactoring's thoughts through your development process, you can't use the refactoring.
Refactoring contains two ideas: it tells you to start from simple design, because even if the code has been implemented, you can still use it to improve your design. However, on the other hand, it is never telling you that you can believe in doodle. The advice I gave you is: Started Simple But Not Stupid.
If you design a stupid interface, even a wrong interface. This part may become the core of the system in the process of program evolution. To perform refactoring, it may take a lot of effort, and the operation of changing the interface and class may be the main content of these Refactoring. Changes to the core interface may quickly spread to all levels of the system, if your overall structure is good, then this kind of ripple may disappear at a level. (, Such as an annular and hierarchical architecture.) If you don't have such an abstract mechanism and protection system, the revision of the core class will directly lead to changes in the entire system, which is unacceptable.
So, when you design a class, you need to ask yourself a few questions. If you have changed this change, how will I modify it? If there is a change, how will I adapt? If you can think of a possible refactoring method, then prove that your design is feasible. This doesn't mean you have to achieve such a design, but to ensure that your design will not force yourself into the dead end. If you find that your code has almost no way refactoring to adapt to new needs, then you have to carefully consider other ideas.
Every time the company's programmer asks me whether a design is reasonable, I always ask a few questions: How do you adapt to this change and adapt to that possible changes. I also point out that there is no need to achieve these changes. I rarely answered him or gave him an answer, but after thinking about the question I asked them, the programmer always made a good judgment to her design, so I found a good solution. So, use refactoring ideas to consider your design.
The programming language is a method of programming language, but the programming language you use will often affect the efficiency of Refactoring, which affects the enthusiasm of Refactoring.
Refactoring initial research started from SmallTalk. With the extreme success of Refactoring on SmallTalk, more object-oriented communities began to extend Refactoring to other locale. But different characteristics of different languages sometimes provide convenience to Application Refactoring, sometimes It will make obstacles.
Support for Refactoring language features and programming style
Static Type Check and Access Protection Static Type Check can narrow down the possible reference range for the program part you want Refactoring. For example, if you want to change a class's member function name, you must change the declaration of the function and All references to this function. If the program is very large, then find this and change such a reference to more difficult.
Unlike the dynamic type language such as SmallTalk, the language for checking the static type (C , Java, Delphi, etc.) usually has class inheritance and related access protection (private, protected, public), which makes it look for a certain one The reference to the function becomes relatively simple. If the renamed function is previously declared as Private, the reference to this function can only be in his class or a friend class (C ), etc. if the class is. If the declaration is protected, then Only this class, subclass, and friends (same packages) can be referenced to the member function. If the declaration is public, then only other classes of this class, subclasses, friendships, and clear introduction of such classes can be introduced. (Include, import). I want to mention another question that you pay attention to. The design principle applied to the software project is an important factor in the success of a software project in the initial development of the software and the entire development process. Whether it is from the angle of the package or from the REFActoring perspective, define member variables and member functions should start from the highest protection level. In addition to very obvious examples, you'd better define the member variables and functions as private first. With the further deepening of software development, when other classes make "additional" requests, you slowly relax the protection. The principle is: If you can put it in Private, don't put it in protected, you can put it in protected, you don't put it in public.
Language features and programming styles complicated by Refactoring
Pre-processing instructions certain locales typically provide pre-processing instructions such as C . Because the pre-processing is not part of the C language, this usually makes the Refactoring tool implementation difficult. Studies have pointed out that programs often need to make better structural analysis after pre-treatment, and at this point, the pre-processing instruction information has no existence. Once Refactoring does not contact the source code, the programmer will be unlikely to understand the result of Refactoring.
Relying on the object size and implementation of code C inherits from C, which makes C quickly popular, and programmers' learning is greatly reduced. But this is a double-sided blade. C thus supports many programming styles, and some of them violates the basic principles of elegant design.
Using C pointers, CAST operations, and SizeOf (Object) These dependent object sizes and implementation of code are difficult to refactor. The concept of the pointer and CAST involves the alias, which makes you want to find all the code that is referenced to this Object is very difficult. A common feature of these features is that they expose the internal expression format of the object, thereby violating the basic principles of abstraction.
For example, C uses the V-Table mechanism to express the members variables in the executable. The inherited member variable is before, this class is defined. One we often use, and believe that safe refactoring is Push Up Fields, which is to move a member variable in the subclass to the parent class. Because the variable is now inherited from the parent class, the actual location of the variables in the executable executable after Refactoring has changed.
If all variables in the program are accessed by class interface, then this change does not have problems. However, if the variable is through the pointer operation (for example, a programmer has a pointer to the object, know the variable in the 9th byte of the class, then use the pointer operation to the 9th byte assignment), the above refacoting process Change the behavior of the program. Similarly, if programmers use IF (SizeOf (Object) == 15), the results of Refactoring are likely to have an impact on the size of the object, making it no longer safe.
The more complex language complexity, the formalization of language semantics is more difficult. Relative to SmallTalk and slightly complex Java, C can be called a very complex language, which makes the study of C program refactoring tools to lag behind SmallTalk and Java. Analysis of the reference mode Since C is in compilation is a resolution reference, it usually requires at least a part of the compiler after Refactoring, and connects the executable program to see the impact of the test Refactoring. Instead, SmallTalk and CLOS provide techniques that explain the implementation and incremental compilation. Although Java did not explain, it explicitly put a public class in a unit requirement, so that the cost of performing a series of refactoring is reduced. Due to the basic method of Refactoring is a small change in each step, each step is tested, for C , each iterative cost is relatively high, so that the programmer becomes less willing to do these small changes.
Reflection, META program analysis and changes this may make the researchers care rather than practitioners. C does not provide a good support for Meta-level program analysis and changes, you can't find a MetaObject protocol like Clos. These protocols sometimes useful to Refactoring, such as what we can change into another class of selected instances to another class, at this time, this reflective protocol can be used to automatically change all the references to the old object to point to new instances.
Although Java has not yet like CLOS such a powerful META function, JDK's development has shown that Java is very strong in this regard. As the example above, we can also do it on Java.
A summary is based on the above comparison, we think Java is the best language to apply Refactoring. The recent observation also confirmed this [Lance tokuda].
From the perspective of practitioners, the most popular refactoring documents are basically used as examples, including "Refactoring" of Martin. There are currently several reactoring tools that support Java and SmallTalk, while C tools are almost. This, the complexity of the language itself has a big impact.
Of course, this does not mean that C programmers should not use refactoring technology, but only need more effort. Refactoring technology has proven to be one of the best ways to evolve OO system, don't give up.