Rules for code reuse

Source: Internet
Author: User
CodeReuse is the vast majority ProgramWhat members expect is also one of OO's goals. To maximize code reuse, we should pay special attention to the following aspects.

Programming interfaces

"Interface programming" is the first basic principle of object-oriented design (OOD. It means that the interface is used to communicate with components of the same type, that is, for all components that have completed the same function, an interface should be abstracted and they all implement this interface. Specifically in Java, it can be an interface or abstract class. All components that complete the same function implement this interface or inherit from this abstract class. Our customer code should only communicate with this interface. In this way, when we need to use other components to complete the task, we only need to replace the implementation of this interface, the rest of our code does not need to be changed!

When the existing component cannot meet the requirements, we can create a new component to implement this interface, or directly expand the existing component to complete the expansion function by subclass.



Back to Top

Object combination is preferred, rather than class inheritance

"Preferential use of object combination, rather than class inheritance" is the second principle of object-oriented design. It doesn't mean that inheritance is not important, but because every person who learns OOP knows that inheritance is one of the basic features of OO, so that inheritance has been abused, and object combination technology is often ignored. The following describes the advantages and disadvantages of inheritance and combination:

Class inheritance allows you to define the implementation of a Class Based on the implementation of other classes. This type of reuse by generating sub-classes is usually called white box reuse (white-box reuse ). The term "white box" is relative visibility: In the inheritance mode, the internal details of the parent class are visible to the Child class.

Object combination is another reusable choice beyond class inheritance. New and more complex functions can be obtained by combining objects. Object combination requires that the object has a well-defined interface. This reuse style is called black-box reuse because the internal details of the combined object are invisible. The object only appears in the "black box" format.

Each inheritance and combination has its own advantages and disadvantages. Class inheritance is statically defined during compilation and can be directly used. class inheritance can easily change the implementation of the parent class. However, class inheritance also has some shortcomings. First, because inheritance is defined at the Compilation Time, the implementation of inheritance from the parent class cannot be changed at the runtime. Worse, the parent class usually defines at least some behavior of the Child class. Any change to the parent class may affect the behavior of the Child class. If the inherited implementation is not suitable for solving the new problem, the parent class must be overwritten or replaced by other more suitable classes. This dependency limits flexibility and ultimately limits reusability.

Object combinations are dynamically defined at runtime by obtaining references to other objects. Because the combination requires that the object has a well-defined interface, and the object can only be accessed through the interface, we do not destroy encapsulation. As long as the types are consistent, at runtime, you can use one object to replace another object. Furthermore, because the implementation of the object is written based on the interface, there is less dependency on the implementation.

The preferential use of object combinations helps you maintain that each class is encapsulated and only complete a single task in a centralized manner. In this way, the Class and Class inheritance layers will remain relatively small and are unlikely to grow into uncontrollable giants (this is the consequence of misuse of inheritance ). On the other hand, the Design Based on Object combination has more objects (but only a few classes), and the system behavior will depend on the relationship between objects rather than being defined in a class.

Note: Ideally, we do not need to create new components for reuse. Instead, we only need to use object combination technology to obtain the required functions by assembling existing components. However, this is rare because the available component sets are not rich. Inheritance reuse makes creating new components easier than assembling existing components. In this way, inheritance and object combination are often used together. However, as mentioned above, do not abuse inheritance and ignore object combination technology.

Related design patterns include:Bridge, composite, decorator, observer, and strategy.

The following example demonstrates this rule. The premise is that we need to output the same data structure in any format.

In the first example, we use an inheritance-based framework. We can see that it is difficult to maintain and expand.

Abstract class implements actexampledocument {// skip some code... public void output (example structure) {If (null! = Structure) {This. Format (structure) ;}} protected void format (example structure );}

In the second example, we use the Framework Based on Object combination technology, and each object's task is clearly separated. We can replace and extend the format class without considering anything else.

Class defaultexampledocument {// skip some code... public void output (example structure) {exampleformatter formatter = (exampleformatter) manager. Lookup (roles. formatter); If (null! = Structure) {formatter. Format (structure );}}}

Here, the component creation mode similar to "Abstract Factory" is used, which submits the component creation process to the Manager for completion; exampleformatter is the abstract parent class of all formats;



Back to Top

Detach a mutable part from an immutable part

"Separating mutable and immutable parts" is the third principle of object-oriented design. If we use the inherited reuse technology, we can define the immutable part in the abstract base class, and the variable part is implemented by its subclass. the immutable part does not need to be defined repeatedly, it is easy to maintain. If we use the Reuse Technology of object combinations, we can define the immutable part, and the variable part can be implemented by different components and dynamically configured at runtime as needed. In this way, we have more time to focus on the variable part.

For object combination technology, each component only provides relatively small functions, loose coupling between each other, and a high reuse rate. Through combination, new functions can be obtained.



Back to Top

Reduce the length of a Method

Generally, our method should only have as few lines as possible, and the method that is too long will be hard to understand, and, if the method is too long, it should be re-designed. This can be summarized into the following principles:

    • Thirty seconds principle:
      If another programmer cannot understand what your function has done in 30 seconds, how and why it has to do so ), it indicates that your code is difficult to maintain and must be improved;
    • One screen principle:
      If the code length of a function exceeds one screen, the function may be too long and should be split into smaller subfunctions;
    • A line of code should be as short as possible, and ensure that only one line of code does one thing

The seemingly tricky and lengthy Code only increases the difficulty of code maintenance.



Back to Top

Eliminate case/IF Statements

Try to avoid the occurrence of judgment statements in the code to test whether an object is an instance of a specific class. Generally, re-design may be helpful if you need to do so. I encountered a problem in my work: When we used Java for XML parsing, we mapped a Java class to each label and used SAX (simple XML interface API: simple API for XML) model. As a result, a large number of judgment statements appear repeatedly in the code to test the current tag type. To this end, we re-designed the DTD (Document Type Definition: Document Type Definition), and added a fixed attribute for each Tag: classname, in addition, the Java class interfaces mapped to each tag are re-designed to unify the operations of each object:Addelement (element aelement); // Add a child element
Addattribute (string attname, string attvalue); // adds an attribute;

Then, all the judgment statements for testing the current tag type are completely eliminated. Each object passes throughClass. forname (aelement. Attributes. getattribute ("classname"). newinstence ();Dynamic Creation,



Back to Top

Reduce the number of parameters

There are a large number of parameters that need to be passed, which is usually difficult to read. We can encapsulate all parameters into an object to complete object transfer, which is also conducive to Error Tracking.

Many programmers, because too many layers of object packaging have an impact on system efficiency. Yes, but we prefer packaging compared to the benefits it brings. After all, "encapsulation" is also one of the basic features of OO, and "every object has as few (and simple) functions as possible" is also a basic principle of OO.



Back to Top

The highest level of the class level should be an abstract class

In many cases, providing an abstract base class is advantageous for feature extension. In abstract base classes, most of the functions and actions have been defined, making it easier for us to understand what the intent of the interface designer is.

Because Java does not allow "Multi-inheritance", it cannot inherit from other base classes because it inherits from an abstract base class. Therefore, it is a good idea to provide an abstract interface. A class can implement multiple interfaces to simulate and implement "Multi-inheritance", providing more flexibility for class design.



Back to Top

Minimize direct access to variables

The Data encapsulation principle should be standardized. Instead of exposing the attributes of a class to other classes, we should protect them through access methods, which is conducive to avoiding the ripple effect. If the name of an attribute changes, you only need to modify its access method, rather than modifying all relevant code.



Back to Top

Subclass features to complete special functions

If a subclass only turns a component into a component manager, instead of implementing the interface function, or reload a function, an external container class should be used instead of creating a subclass.

Suggestion: the class hierarchy chart should not be too deep;

For example, the following interface defines the function of the component: Send messages; Class transceiver implements this interface; its subclass pool only manages multiple transceiver objects, but does not provide its own interface implementation. We recommend that you use combination instead of inheritance!

Public interface itransceiver {public abstract send (string MSG);} public class transceiver implements itransceiver {public send (string MSG) {system. out. println (MSG) ;}}// implement the public class pool extends transceiver {private list pool = new vector (); Public void add (transceiver atransceiver) {pool using the inheritance method. add (atransceiver);} public transceiver get (INT index) {pool. get (INDEX) ;}// public class pool {private list pool = new vector (); Public void add (transceiver atransceiver) {pool. add (atransceiver);} public transceiver get (INT index) {pool. get (INDEX );}}


Back to Top

Split a large class

If a class has too many methods (more than 50), it may have to do too much work. We should try to split its functions into different classes, similar to rule 4.



Back to Top

Different objects should be split.

In the process of building, you sometimes encounter the following problem: You have different views for the same data. Some attributes describe how the data structure is generated, while some attributes describe the data structure itself. It is best to split the two views into different classes and distinguish them from the class names.

Class fields and methods should also have the same considerations!



Back to Top

Minimize implicit parameter transfer

The two methods process the same data (domain) in the same class, which does not mean that they process the data (domain. In many cases, the data (field) should be used as the parameter input number of the method instead of directly accessing it. In the design of the tool class, pay special attention to it. For example:

Public class test {private list pool = new vector (); Public void testadd (string Str) {pool. add (STR);} public object testget (INT index) {pool. get (INDEX );}}

Both methods operate on the list object pool. However, we may only want to perform access Tests on different implementations of the List interface, such as vector and arraylist. Therefore, the code should be written as follows:

Public class test {private list pool = new vector (); Public void testadd (list pool, string Str) {pool. add (STR);} public object testget (list pool, int index) {pool. get (INDEX );}}

References

Design Mode

The Apache team's Jakarta project's aveon sub-project (http://jakarta.apache.org/) is about code reuse, and the Commons Sub-Project (http://jakarta.apache.org/commons/index.html) also has some content.

Thinking in Java

About the author

Li Wei: He is currently the product technology department manager of Beijing Jiehe weiye software company. He graduated from the computer department of Sichuan University in 1996 and has 5 years of software development experience. He is mainly engaged in Internet-based B/S structure Java Development and specializes in object-oriented technology, communication, and database.

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.