Download (direct link):
¦¦ Wrong level of abstraction. Many APIs are layered over other software (like the operating system or native code) in order to simplify or aggregate functions. In layering, you must make a trade-off between simplicity and granularity of control. Thus, when setting the abstraction level, you must balance these appropriately for the particular context and target audience. Too high a level of abstraction (like URLConnection, Item 17) frustrates users with weak control mappings, while a too low level of abstraction reduces the average user's efficiency by over-cluttering the most common case.
¦¦ Weak separation of concerns. When an API tries to do too much, it often mixes metaphors and addresses its multiple concerns in a mediocre fashion. An example of this is the JAXR API that attempts to combine the diverse information models of UDDI and ebXML (Item 47).
¦¦ Other deficiencies. Too many method invocation sequences and dependencies will lead to incorrect ordering. Poor naming and weak parameters (object instead of a specific type) steer programmers toward dead ends.
Language Complexity. The Java language has many improvements over its predecessors yet also struggles with its own set of tradeoffs and idiosyncrasies. The cleanest language features are its strict object orientation, automatic memory management, and interfaces; while some overly complex areas are threading and synchronization, the tension between primitives and objects, and the effective use of exceptions.
Weak Implementation of Platform Areas. The most oft-cited example is poor performance. An example of this is the rewrite of the input/output facilities in the NIO package for performance reasons. Besides performance, there are thin APIs that ruin the Write Once, Run Anywhere (WORA) guarantee like the File.renameTo() (Item 20) method and the Runtime.exec() method (Item 1).
There are also incomplete APIs where the programmer assumes complete functionality exists. These problems are fixable and often are resolved with each new release of the Java Development Kit (JDK).
The categories of pitfalls associated with the programmer are as follows:
Shallow Knowledge. Experience increases the depth of one's knowledge. It takes time to learn the underlying concepts, interactions, and nuances of a system.
This is often manifest in choosing a weak implementation when a better alternative exists (like applets versus Web Start, Item 26), misunderstanding the internal workings of an API (like the consequence of instance variables in servlets, Item 31), and shock when implementations fail to meet your expectations of behavior (characterized as an impedance mismatch in Figure i-1). Such an impedance mismatch can occur with multiple concurrent result sets (Item 41).
Bias. Without many years of experience, a programmer can weigh previous experience too heavily to the point where it unfavorably biases him or her in a particular direction. Examples of this are to not take advantage of tools to automate the development process like Ant (Item 11) and JUnit (Item 12). Another example is to stick with legacy APIs over new ones for collections (Item 21) and regular expressions (Item 30). Lastly, one more effect of bias is to bring past habits into a new context like J2ME programming (Item 22).
Invalid Assumptions. A programmer can incorrectly base decisions on invalid assumptions—for example, assuming the most direct path to the solution is the best path. This often arises in designing larger systems with JSP (Item 24) and J2EE (Item 37).
Pitfalls can be extremely frustrating to programmers. We've experienced first hand this frustration. Our goal is to help you to avoid some situations we struggled through. So now that we understand pitfalls, let's see our method for exploring them.
Dissecting a Pitfall
There are three distinct parts of a pitfall:
The Symptom or Problem. The medium by which the pitfall manifests itself. We demonstrate this with a program entitled "BadXXX.java," where "XXX" refers to the type of pitfall in question.
The Root cause of the Problem. By far, this is the most important part of revealing the pitfall. Here, we go under the hood and explain the detailed internal workings, invalid assumptions, or API deficiencies that cause programmers to stumble into the trap. Usually this explanation is supported with a diagram.
The Solution or Workaround. The final part of the pitfall is to demonstrate a fix for the problem. This is done with a program entitled "GoodXXX.java" that is the reciprocal of the "BadXXX.java" program. The solution program will often be accompanied with a run of the results, or a table or graph, which proves the problem was indeed solved.
This method of dissecting a pitfall has proven an effective way to present these programming hazards.
How This Book Differs from Java Pitfalls
This book borrows all the good features from the first book and improves upon it in three ways:
Broader Coverage. The first book focused on the lang, util, io, and GUI packages, whereas this book covers the J2ME, J2SE, and J2EE platforms.