Refactoring Patterns: Part III
content:
Application Refactoring Needs to consider the database interface change and Publish Interface with refactoring ideology to armed their own design programming language supporting the language characteristics and programming style to make Refactoring complex language characteristics and programming style resolution Reflection, META program analysis and Change a summary about the author
related information:
Other parts of this series
Identification of questions need to consider, Shiyiying@hotmail.com, Zhejiang University, Lingfeng Technology Development Company, 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 come and see: Database Many applications 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.
Although Refactoring is a way independent of programming languages, the programming language you are using tends to affect the efficiency of Refactoring, which affects the enthusiasm of Refactoring. Refactoring started from SmallTalk With the extreme success of Refactoring on SmallTalk, more object-oriented societies began to extend Refactoring to other locale. However, different characteristics of different languages sometimes facilitate the application Refactoring, sometimes disorders. Support Refactoring Language features and programming style. Static type checks and access protection Static type checks can narrow down the possible reference range of the program part you want Refactoring. For example, if you want to change a class member function name, then you must Change the function of the function and all references to this function. If the program is large, then find this and change this reference to more difficult. Different dynamic type languages like SmallTalk, the language for checking the static type (C , Java, Delphi, etc.) typically have type inheritance and related access protection (private, protected, public), which makes it easy to find a reference to a function. If the renamed function is previously declared as Private, then The reference to the function can only be in his class or friend class (C ), etc., if the declaration is protected, only this class, subclass, and friends (the same package) can be referenced to the member function If it is declared as public, then only other classes of this class, subclass, friend, and explicit introduction (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. Make Refactoring Complex Language Features and Programming Prepared Instructions Some language environments 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. About the author Shi Yizhen, is currently the technical director of Zhejiang University Lingfeng Technology Development Company. Many years engaged in OO system analysis, design. The main research direction is refactoring and analysis mode. You can contact me via shiyiying@hotmail.com.