Java API design guide (1)

Source: Internet
Author: User

Author: Eamonn McManus
Original address: http://www.artima.com/weblogs/viewpost.jsp? Thread = 1, 142428
Http://gocom.primeton.com/modules/newbb/forumtopic4585_4075_40.htm.
Translator: Wang Lei
Email: wl_95421@yahoo.com.cn

 

Java API design guide (2)

  Preface

There are so many books on the market about how to design and compile excellent Java code, which may be described by the experts. However, it is difficult and difficult to find a book on how to design APIs. Here I will share some of my experience on API design with you.

Sharing these experiences was due to a recent discussion I attended on javapois, which was initiated by elliotte Rusty Harold and was about some principles when designing XOM, I have benefited a lot from the brilliant exchange of ideas during the discussion. Although the topic of this discussion is related to XOM, most of the time we are discussing some principle issues when designing XOM APIs, which are common for API design. Over the past few years, Java has been widely used, and open-source projects are also booming. A good book that can guide developers in designing and writing APIs can help developers design and compile better APIs.

Over the past five years, I have been involved in the revision and adjustment of the JMX API, which has also benefited a lot. Particularly at this seminar, I held high hands to agree with some of the ideas put forward by elliotte.

The following content is a summary of some of the main points of view at the seminar, including some personal experience or experience from others, and some relevant documents, hoping to help you design APIs.

The following are some of my personal recommendations for reading and references.

The following url is an excellent document on API design on the netbeans website,

Http://openide.netbeans.org/tutorial/api-design.html

Josh Bloch's objective Java, one of the Bibles designed by Java, is never missed.

  Design needs to evolve

The value of an API lies in its ability to help you complete many functions, but do not forget to continuously improve it. Otherwise, its value will gradually decrease. In addition, it is important to improve the API, or to evolve the API based on user feedback. In addition, it is important to ensure compatibility between different versions to improve the API, it is also an important identifier for API success.

If a function is published as an API, its external interface will be fixed after it is released, and cannot be canceled in any case, and must be able to correctly execute according to the original agreed functions. If the API cannot maintain compatibility between versions, users will be unable to accept such an ever-changing API, the final result is to allow the user to abandon using your API. If your API is used by a large number of software or modules, or is used by large software, this compatibility problem becomes more and more serious.

Take a Java application as an example. If module1 uses the banana1.0 API, while module2 uses the banana2.0 API, deploy the two modules to a web application at the same time, if banana2.0 is compatible with banana1.0, the entire deployment will be very simple. You can simply use banana2.0. If banana2.0 and banana1.0 are not compatible, it is difficult to use module1 and module2 at the same time in a program (you may need to customize classloader or other methods, this is difficult for users ). The final result may be that you lose a user, and the API cannot provide any value to others ).

The APIS provided by the Java SE platform have strict compatibility control. The fundamental goal is to ensure that the code of a lower version cannot run during version upgrade. This again shows that after an API is released, elements such as methods and constants published by any API cannot be removed from the API. Otherwise, the value of the API is seriously reduced. Therefore, I have always doubted the value of deprecated because since all methods will not be deleted, even the methods and variables that are deprecasted will be retained, its functions should not be changed, so from this perspective, its method and variable usage are still safe .)

Speaking of compatibility, we must talk about binary compatibility. This means that for compiled code, the compiled code will not run properly due to version changes. For example, if you remove a public method from the API, it will fail to run normally and will throw nosuchmethodexception and other errors.

However, the compatibility of Source Code cannot be ignored. In some special circumstances, when you modify an API, source code compatibility issues may occur, leading to the failure of source code compilation. For example, if you add a method with the same name as an overload, the parameters are different, for example, getname (user) and getname (string). When you use getname (null), there will be ambiguity, A compilation error occurs. You must provide getname (string) null) to identify the method to be called. Therefore, you must find a way to maintain source code compatibility.

Generally, if the source code is incompatible, the code compilation will fail. You must modify the source code to ensure that the program runs normally. However, this is not a good solution. Taking javax. Management. standardmbean in j2se6 as an example, the constructor of this class has adopted generics. This will cause some classes to encounter compilation failures when creating this bean, but the solution is sometimes very simple, it is often necessary to add a cast for forced type conversion to solve such a compilation problem. But more often, more complicated solutions are required to solve these compilation problems. For example, if a third-party API method is called in a method, if one day the parameters of this API method are modified, when modifying the source code, you may find that your method does not contain the parameters required by the API method. In this case, you need to modify the method parameters. The following is the sample code for this situation.

Public void callapi (parameter1 P1, parameter2 P2)
{
// Do some operations
New thirdclass (). docallthirdapi (P1 );
}

Currently, third-party APIs are now docallthirdapi (parameter1 P1, parameter3 P3)

In this case, you may need to change the method:

Public void callapi (parameter1 P1, parameter2 P2, parameter3 P3)
{
// Do some operations
New thirdclass (). docallthirdapi (P1, P3 );
}

Such an API change may trigger a domino event.

Generally, you do not know how to use APIs to complete your work. You can consider modifying the API unless you are sure that the API modification will not cause any damage to your code ., If API changes affect your current code, you must have enough reasons. Only when you realize that the modification to the API seriously damages your existing code can you exercise caution when modifying the API and try to ensure API compatibility. When modifying an API, try to avoid the following situations to avoid damages to your code:

Reduce the visibility of methods, such as changing public to package or proteced, or changing protected to private.

Modify the parameters of a method, such as deleting a parameter, adding a parameter, or changing the parameter type.

Just like the experience in the industry-"Do not use software earlier than version 3.0 .), The same situation is true for APIs. The first few versions of Apis often contain a large number of errors, which should not be hidden, even at the bottom of the iceberg, there will also be a day to come. Therefore, do not forget to provide several 0. x versions before the official release of API 1.0. For 0. users of Version X will have a clear description. Users will clearly know that the API published in the current version is not stable and may change it at the official release, 0. version X does not guarantee compatibility. Take visual studio2000 beta2 as an example. It differs greatly from the official version. Therefore, version 0. X is generally used for learning or technical prediction, but cannot be used in products ). However, once version 1.0 is officially released, remember to make a formal commitment to API compatibility. Before the JCP organization releases a formal version of a specification, it usually releases several draft versions (such as drafts, public previews, and final recommended versions ). If it is convenient, the provision of an API during API publishing for normative content may be more effective in implementing the specification: because the normative content is more interface-based API release, you can refer to interface and abstract class. Therefore, it is better to provide an implementation. For example, when sun releases the J2EE specification, A default implementation is provided .).

After a certain stage of API design and development, you may find that some problems have occurred in the previous version, or you need to add new functions, at this time, the designer can completely re-create a new API and put it in the new package, so that users who use the old version can easily port it to the new version, without issues. Remember: Add new features. do not modify the original content.

  API design goals

What is the goal of designing an API? In addition to compatibility, we also put forward some goals from the discussion of elliotte.

API correctness must be ensured:

Taking XOM as an example, no error XML document should be generated no matter how you call the API. For example, in JMX, whether registering an incorrect mbean or performing some operations concurrently, or using some special names for mbeans, mbean server must maintain state consistency, the entire system cannot provide services after an incorrect mbeans operation.

Ease of use of Apis:

The API must be easy to use. Ease of use is often hard to evaluate. However, there is a way to effectively improve ease-of-use, that is, to write a large number of sample code and organize it together, so as to provide users with API reference. I personally think that a good FAQ can provide examples of using various APIs .)

The following principles can also be used to determine the ease of use of Apis:

Is there always a set of operation code? NOTE: If multiple lines of code are repeatedly called, they should be put into a method to avoid repeated code writing .)

When using APIs, do you need to refer to javadoc or source code frequently to know which method to call? (Note: most operations can be understood only by the class name and method name ).

Call a method by name, but what the method does is not what the user wants. For example, a command method is called to execute an operation, but the result is that the method is used for backup .)

API must be easy to learn:

To a large extent, the ease of use and the ease of use of APIs are similar. In general, ease of use is also easy to learn. To make the API easier to learn, follow the following basic principles:

  • The smaller the API, the easier it is to learn;
  • There should be examples in the document;
  • If it is convenient, try to make the API consistent with some common APIs. For example, if you want to make an API for resource access, try to be consistent with the I/O usage in j2se, And it is naturally easy to learn.

If you want to close a resource, use close instead of destroy, just like file and connection in Java .)

The API must run fast enough:

It took a long time for elliotte to give this article. However, to ensure that the API is simple and correct, you must consider the API performance. When designing an API, you may first implement the API in a way that can be quickly implemented but has poor performance, and then modify the implementation of the API based on the actual situation to adjust the performance. As for how to adjust the performance, never use intuition to determine which method can achieve high performance. Performance bottlenecks can only be optimized after passing correct and rigorous tests. Early optimization is the root cause of all errors. This is a widely accepted idea, especially for Java programs, because its JVM is getting faster and smarter .)

The API must be small enough:

The small mentioned here refers not only to the small size of the compiled code file, but also to the smaller memory occupied during runtime. There is another reason for the concept of minimization: it is easy to add new content to the API, but it is very difficult to remove a content from the API, therefore, do not add content to the API. If you are not sure about the content, do not add it to the API. With this suggestion or restriction, an API designer can be reminded to pay more attention to the most important functions of the API, rather than some minor issues.

In many cases, this minimization principle is very difficult to follow. For example, a variable class is usually better than a variable class, but it occupies more memory, variable classes consume less memory, but they need to handle threads, concurrency, and other issues. Therefore, it is more often a trade-off. If it is large, it is not good, but it is also necessary to make it small ).

There is a common way to design an API, but the results are a headache. This method is to carefully consider the needs of each user before designing an API and design a corresponding method, you may need to design a bunch of protected methods in the implementation so that you can adjust the default implementation through inheritance. Why is this approach not good?

Because the details are too detailed, the functional boundary is increased, and the demand is increased. Therefore, the functions to be provided and the functions to be adjusted by users are even larger, that is to say, this method will make the API contain a lot of functions, and eventually the expansion of the API will increase.

In fact, the more functions an API contains, the more difficult it is to learn and use. In addition, the learning difficulty is often increased by a geometric level, rather than linear growth. Imagine that an API that understands and learns to use 10 classes and 100 methods is not difficult for a programmer. It can be completed in about one day, but for a 100 class, even for a very good programmer, it is estimated that 10 days is not enough to fully understand the API with 1000 methods.

In addition, in a large API, how to find the most important content as soon as possible and how to find the solution to complete the required functions has always been a challenge in API design.

The javadoc tool brings a lot of convenience to users, but it has never been a solution for learning and using a large api library. Javadoc places all classes in the specified package together, and places all methods in a class together (this refers to allclasses-frame.html, index-all.html). It is a genius, tens of thousands of methods and classes can only be seen. Now it seems that we can only hope that the jsr260 standard can be used to effectively enhance the javadoc tool, so that we can obtain a complete view of the API and be able to express the API more broadly, even a huge API package is not congested, making it easier to understand and use.

In addition, the larger the API, the more likely it will be to encounter errors. just as difficult as it was previously used, the number of errors also increases exponentially rather than linearly. For small APIs, you can get better output when you invest the same manpower for coding and testing.

If the designed API is too large, it will inevitably contain many unnecessary methods, at least many public classes and methods, which are not available to most users, it also occupies more memory and reduces the running efficiency. This violates a general design principle: "Do not let users pay for features that they cannot use ".

The correct solution is to design the API in the current example ). First, imagine what problems a user needs to solve using APIs and add enough classes and methods to solve these problems. Then, remove all irrelevant content so that you can check the usefulness of these Apis. This method also provides a useful additional function that can test code more effectively. You can also share these examples with your peers. This concept is very similar to testing first ).

Java API design guide (2)

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.