Dustin's Pages

Wednesday, May 30, 2012

One of the advantages of code generation is the ability to see how a specific language feature or framework is used. As I discussed in the post NetBeans 7.2 beta: Faster and More Helpful, NetBeans 7.2 beta provides TestNG integration. I did not elaborate further in that post other than a single reference to that feature because I wanted to devote this post to the subject. I use this post to demonstrate how NetBeans 7.2 can be used to help a developer new to TestNG start using this alternative (to JUnit) test framework.

NetBeans 7.2's New File wizard makes it easier to create an empty TestNG test case. This is demonstrated in the following screen snapshots that are kicked off by using New File | Unit Tests (note that "New File" is available under the "File" drop-down menu or by right-clicking in the Projects window).

Running the TestNG test case creation as shown above leads to the following generated test code.

The test generated by NetBeans 7.2 includes comments indicate how test methods are added and annotated (similar to modern versions of JUnit). The generated code also shows some annotations for overall test case set up and tear down and for per-test set up and tear down (annotations are similar to JUnit's). NetBeans identifies import statements that are not yet used at this point (import org.testng.annotations.Test; and import org.testng.Assert;), but are likely to be used and so have been included in the generated code.

I can add a test method easily to this generated test case. The following code snippet is a test method using TestNG.

This, of course, looks very similar to the JUnit equivalent I used against the same IntegerArithmetic class that I used for testing illustrations in the posts Improving On assertEquals with JUnit and Hamcrest and JUnit's Built-in Hamcrest Core Matcher Support. The following screen snapshot shows the output in NetBeans 7.2 beta from right-clicking on the test case class and selecting "Run File" (Shift+F6).

The text output of the TestNG run provided in the NetBeans 7.2 beta is reproduced next.

The above example shows how easy it is to start using TestNG, especially if one is moving to TestNG from JUnit and is using NetBeans 7.2 beta. Of course, there is much more to TestNG than this, but learning a new framework is typically most difficult at the very beginning and NetBeans 7.2 gets one off to a fast start.

Tuesday, May 29, 2012

In the post Improving On assertEquals with JUnit and Hamcrest, I briefly discussed Hamcrest "core" matchers being "baked in" with modern versions of JUnit. In that post, I focused particularly on use of JUnit's assertThat(T, Matcher) static method coupled with the Hamcrest core is() matcher that is automatically included in later versions of JUnit. In this post, I look at additional Hamcrest "core" matchers that are bundled with recent versions of JUnit.

Two of the advantages of JUnit including Hamcrest "core" matchers out-of-the-box is that there is no need to specifically download Hamcrest and there is no need to include it explicitly on the unit test classpaths. Before looking at more of the handy Hamcrest "core" matchers, it is important to point out here that I am intentionally and repeatedly referring to "core" Hamcrest matchers because recent versions of JUnit only provide "core" (and not all) Hamcrest matchers automatically. Any Hamcrest matchers outside of the core matchers would still need to be downloaded separately and specified explicitly on the unit test classpath. One way to get an idea of what is Hamcrest "core" (and thus what matchers are available by default in recent versions of JUnit) is to look at that package's Javadoc-based API documentation:

From this JUnit-provided documentation for the org.hamcrest.core package, we see that the following matchers (with their descriptions) are available:

Class

Javadoc Class Description

Covered Here?

AllOf<T>

Calculates the logical conjunction of two matchers.

Yes

AnyOf<T>

Calculates the logical disjunction of two matchers.

Yes

DescribedAs<T>

Provides a custom description to another matcher.

Yes

Is<T>

Decorates another Matcher, retaining the behavior but allowing tests to be slightly more expressive.

Is the value equal to another value, as tested by the Object.equals(java.lang.Object) invokedMethod?

Yes

IsInstanceOf

Tests whether the value is an instance of a class.

Yes

IsNot<T>

Calculates the logical negation of a matcher.

Yes

IsNull<T>

Is the value null?

Yes

IsSame<T>

Is the value the same object as another value?

Yes

In my previous post demonstrating the Hamcrest is() matcher used in conjunction with JUnit's assertThat(), I used an IntegerArithmetic implementation as test fodder. I'll use that again here for demonstrating some of the other Hamcrest core matchers. For convenience, that class is reproduced below.

In the Improving On assertEquals with JUnit and Hamcrest post, I relied largely on is() to compare expected results to actual results for the integer multiplication being tested. Another option would have been to use the equalTo matcher as shown in the next code listing.

Although not necessary, some developers like to use is and equalTo together because it feels more fluent to them. This is the very reason for is's existence: to make use of other matchers more fluent. I often use is() by itself (implying equalTo()) as discussed in Improving On assertEquals with JUnit and Hamcrest. The next example demonstrates using is() matcher in conjunction with the equalTo matcher.

The equalTo Hamcrest matcher performs a comparison similar to calling Object.equals(Object). Indeed, its comparison functionality relies on use of the underlying object's equals(Object) implementation. This means that the last two examples will pass because the numbers being compared are logically equivalent. When one wants to ensure an even greater identity equality (actually the same objects and not just the same logical content), one can use the Hamcrest sameInstance matcher as shown in the next code listing. The not matcher is also applied because the assertion will be true and the test will pass only with the "not" in place because the expected and actual results happen to NOT be the same instances!

It is sometimes desirable to control the text that is output from an assertion of a failed unit test. JUnit includes the core Hamcrest matcher asDescribed() to support this. A code example of this is shown in the next listing and the output of that failed test (and corresponding assertion) is shown in the screen snapshot of the NetBeans IDE that follows the code listing.

The contrived class whose code was just shown provides opportunities to use additional Hamcrest "core" matchers. As described above, it's possible to use all of these matches with the is matcher to improve fluency of the statement. Two useful "core" matchers are nullValue() and notNullValue(), both of which are demonstrated in the next JUnit-based code listing (and is is used in conjunction in one case).

Many of the Hamcrest core matchers covered so far increase fluency and readability, but I like the next two for even more reasons. The Hamcrest hasItem() matcher checks for the existence of the prescribed item in the collection and the even more useful Hamcrest hasItems() matcher checks for the existence of multiple prescribed items in the collection. It is easier to see this in code and the following code demonstrates these in action.

It is sometimes desirable to test the result of a certain tested method to ensure that it meets a wide variety of expectations. This is where the Hamcrest allOf matcher comes in handy. This matcher ensures that all conditions (expressed themselves as matchers) are true. This is illustrated in the following code listing, which tests with a single assert that a generated Set is not null, has two specific Strings in it, and is an instance of TreeSet.

Now I need to test that the sole method in the class above returns a valid integer representing a day of the week correctly. I'd like my test(s) to ensure that a valid integer representing a day Sunday through Saturday is returned, but the method being tested is such that it may not be the same day of the week returned on any given test run. The code listing below indicates how this can be tested with the JUnit-included Hamcrest "anyOf" matcher.

While Hamcrest's allOf requires all conditions to match for the assertion to be avoided, the existence of any one condition is sufficient to ensure that anyOf doesn't lead to an assertion of a failure.

My favorite way of determining which core Hamcrest matchers are available with JUnit is to use import completion in my Java IDE. When I statically import the org.hamcrest.CoreMatchers.* package contents, all of the available matchers are displayed. I can look in the IDE to see what the * represents to see what matchers are available to me.

It is nice to have Hamcrest "core" matchers included with JUnit and this post has attempted to demonstrate the majority of these. Hamcrest offers many useful matchers outside of the "core" that are useful as well. More details on these are available in the Hamcrest Tutorial.

Monday, May 28, 2012

There has been significant excitement about the beta release of NetBeans 7.2. In this post, I look briefly at what makes this release so exciting (including better performance, providing more hints, and integrating FindBugs).

The NetBeans 72 NewAndNoteworthy page provides additional information on the quicker performance. It states, "The indexes and indexing infrastructure were rewritten to use transactions. The project scanning and up to date check do not block editor features nor navigation. These features use the previous committed index. Also the write transactions are suspended by read transactions, so the background indexing has lower priority than user actions." That same page also states, "The binary indexers run in parallel which makes indexing of java project faster."

The following screen snapshots demonstrate the utility of the new NetBeans 7.2 hint for including underscores in integer literals to improve readability. As the first screen snapshot indicates, there is some configuration available related to this hint. Also note that in my case of upgrading from NetBeans 7.1.1 to NetBeans 7.2 beta, this hint was not enabled (not checked) in the Tools | Options | Editor | Hint area.

The FindBugs Integration Plugin can be installed on NetBeans 7.2 beta using the Tools | Plugins | Available Plugins approach shown in the next screen snapshot.

An alternative approach for acquiring and installing the FindBugs Integration Plugin is through the source code inspection process. This can be done by selecting Source | Inspect (shown in next two images).

Note that FindBugs Integration is one of the items that can be explicitly selected, but I prefer to use "All Analzyers." Click on the "Install" button to see what "additional plugins [are] required for the selected configuration." In the case of the newly installed NetBeans 7.2 beta, the following appeared when I clicked on that "Install" button.

There's a lot to like about NetBeans 7.2, even in its beta release. It is faster and more helpful than its direct predecessors and integrates with many of the most popular Java and software tools and frameworks available today. The NetBeans 7.2 beta fanfare even attracted a self-proclaimed Eclipse user to try it out. There is substance behind the fanfare in this case. As Chris Mayer has stated regarding NetBeans 7.2 beta, "The most inclusive IDE just got a little bit sweeter."

Court cases are never about right and wrong, they're about the law and what you can convince a jury of. For those of us at Sun who felt trampled-on and abused by Google's callous self-righteousness, I would have preferred a different outcome - not from the court case as much as from events of years past.

Comprehensive List of Java VM "Product" Options

On a completely unrelated note, I found the post Hotspot JVM Options - The complete reference to be interesting and worth bookmarking. The post's author talks about the limited nature of the Java HotSpot VM Options document and how he downloaded OpenJDK and extracted options details out of the open source. He lists the four categories of options (product, diagnostic, develop, and experimental) and then lists all of the options for one of those categories ("product"). This is a good example of a blog post that can be of high value to numerous other Java developers as a reference more thorough than that available in the standard documentation.

Although there are numerous tools and approaches for dealing with these other types of impedance mismatches, it seems we're woefully short on similarly powerful tools, approaches, and proven practices (my new preferred term for what I think "best practices" was originally intended to mean) for dealing with the developer/non-developer mismatch. In this post, I look at some of the most common areas of developer/non-developer mismatch and speculate as to why they occur and what can be done to address these specific areas of developer/non-developer impedance mismatch.

Sadly, we have much less control over the developer/non-developer impedance mismatch than we do over object-relational or object-XML impedance mismatches. Although in general things like improved communication and education can help, these answers are not as tangible as the ones we're used to for dealing with other types of software development impedance mismatches. As difficult as it is to deal with the developer/non-developer impedance mismatch, we must do so because there are numerous significant stakeholders in the software development process that are not necessarily developers (managers, clients, testers, customers, business analysts, sales people, and more).

DRY Principle / Modularity

Almost to a fault, developers have generally adopted (at least in a theory if not always in practice) the DRY (Don't Repeat Yourself) principles coined in the often-referenced book The Pragmatic Programmer: From Journeyman to Master. Although the term was coined in this 1999 book, the practice had been one that developers for decades had understood to some degree. Regardless of native spoken language or favorite programming language, developers today widely recognize virtues of some degree of DRY-ness. There may be some debate as to what level this should be taken (I've seen it taken past the point of common sense), but most of us agree with the perils of repeated documentation at different levels of the software product or of repeated code (copy-and-paste development).

Benjamin Denckla, in the post "Faith in DRY; no hope for software," writes, "Today we produce software through a laborious, undisciplined process that combines the low quality work of many with the heroic high quality work of a few. ... Not enough people believe in DRY and other good practices like it." I believe this is especially true when one considers the non-developers involved in a software development project. In my experience, the developers generally do see the value in some significant degree of DRY, but non-developer stakeholders see little value in DRY principles.

For purposes of this discussion, I'm including modularity in what I'm calling DRY practices. Most developers know there are numerous reasons to not copy-and-paste the same code into multiple places. For many decades, developers have known to place reusable code in methods, functions, modules, or other constructs that allow the same code to be used in multiple contexts and situations. It doesn't take long for this to become second nature to the experienced developer. Sadly, many non-developers seem to not acknowledge the risks and problems associated with redundant information copied from place to place or believe these risks and problems are more theoretical than real. Although it may not be code we're talking about when we discuss non-developers (it may be documentation, requirements, specifications, test procedures, or a host of other non-code things), the principle still applies: reproducing anything in multiple places leads to problems down the road in terms of maintenance and keeping the many versions synchronized with the latest and greatest. Developers seem to almost intrinsically "get it," but I see it less well received from many non-developers.

Readable and Maintainable Code

Many new software developers and even more non-developers do not recognize the value of code that is more readable and more maintainable. Perhaps the best experience a young developer can have is to maintain and reuse someone else's code. Doing so helps a young developer to recognize the value of writing code as cleanly as possible. Because non-developers never really get this experience, it is not surprising that they don't value cleanness, maintainability, and readability to the same degree as the experienced developer. Many legitimate cries for time to refactor a code base to improve its future maintainability and readability are ignored or promptly dismissed because such efforts' value is not obvious to those making the decisions.

Overbearing Processes and Management Decisions

I have occasionally seen non-developers in management roles trying to coerce developers into very narrow and specific behaviors that they (the managers) believe is best (or worse, that they perceive as giving them the power). These folks rarely have the experience to know the full ramifications of their decisions. Good managers listen to their developers (particularly those with significant experience and in technical leadership roles) before pushing out every "good idea" they have. Experienced developers usually know what it takes to write high-quality software, but it almost takes another experienced software developer to appreciate what they argue for. Alternatively, a manager lacking software development experience can sometimes make better decisions by choosing an experienced developer that he or she trusts with technical decisions. The best non-technical managers recognize their own lack of technical knowledge and work with a trusted technical expert to make good decisions.

Bean Counting and Pencil Pushing

Most software development is done as part of a business venture and it is often inevitable that some degree of bean counting and pencil-pushing will be required.. Clients or consumers directly or indirectly finance the creation of software. It can be difficult for developers to recognize and appreciate the legitimate management and metrics collection that goes on during these business-oriented phases. It can be equally difficult for managers and other non-developers to understand that some things are more subtle than the apparent "bottom line." Non-developers may over-emphasize short-term "bottom line" considerations at the expense of long-term quality and maintainability of the product while developers may overly neglect bottom line considerations and create software products that require too much time and investment to justify their likely return on investment.

The bean counter wants nothing more than to be able to count things like beans. He or she wants to use lines of code, number of defects in various states, number of requirements, and so forth to feel like he or she has a handle on the software development progress being made. It doesn't really matter that these are not created equally and should not be counted as if they are equal.

Battle for Control

It seems to be human nature and common in many relationships between humans to have battles for control. Tension can increase in the relationship between developers and non-developers as each group tries to exert control. Many non-developers, especially if they don't understand development or coding well, resent not being able to control what is added to the baseline. Many developers resent being told what they can put into the baseline, especially when they strongly believe that the non-developer is making arbitrary calls while lacking sufficient knowledge and background to make that call.

The battle for control can become very onerous when both sides are "know-it-alls." When either side is convinced of its superiority, it can be very difficult to get either to budge. Developers often feel their experience and skillset best qualifies them for making all software decisions while clients, managers, and others often feel their position does the same for them.

Coding: Job for a Craftsman or for a Technician?

Good software development managers recognize that software development can be a highly creative and challenging effort and requires skilled people who take pride in their work. Other not-so-good software managers consider software development to be a technician's job. To them, the software developer is not much more than a typist who speaks a programming language. To these managers, a good enough set of requirements and high-level design should and can be implemented by the lowest paid software developers. Some software development is easier than other software development, but the simple technician work has been largely replaced by automation and code generation at this point.

Perhaps the perceptions of technician versus craftsman explain why non-developers tend to be more likely to believe that all developers are plug-and-play while experienced developers realize that there can be a wide disparity in skillsets and knowledge between any two developers.

Appreciation of Software Development Nuances and Subtleties

It usually does not take long for a developer to realize that relatively little in software development is cut and dry. Software development often has a large amount of creativity to it and there are numerous judgment calls to be made. We sometimes call these design decisions or architecture trade-offs. Unfortunately, many who are not software developers do not understand that there are nuances and subtleties and even large amounts of creativity involved in software development. Without lack of these subtle shades, it's not surprising that many of these people without development experience can only think in extremes (technique "A" is good and must be be used by everyone all of the time or technique "A" is always wrong and should be absolutely avoided no matter what). New developers often exhibit this trait as well, but experience usually teaches them to be more willing to judge approaches and techniques against particular contexts and reduce the amount of generalization and assumptions.

Developers Aren't So Different from Others, But Then They Are

The Mythical Man-Month is one of the most often-quoted books in the areas of software development and software development management. One of its great quotes is made early in the work (first sentence of Preface to the First Edition): "In many ways, managing a large computer programming project is like managing any other large undertaking—in more ways than most programmers believe. But in many other ways it is different—in more ways than most professional managers expect." One of the key explanations of the impedance mismatch between developers and non-developer managers seems to lie in this profound statement. Developers, as a group, probably should be more willing to buy into certain proven "traditional" management approaches, but managers need to avoid falling into the trap of thinking that the tactics outlined in the latest business management book will be sufficient for managing software developers.

Opinions on What Values Most

Software developers are people too. As such, they do exhibit the same behaviors as other people. However, there are gross stereotypes of software developers that are not completely without some basis because of the high frequency of those stereotyped traits among software developers. There is great diversity in the software development community in terms of political opinions, interests, and so forth, but the idea of what is most important (quality design and code, work to be proud of, etc.) are fairly common across the industry. On the other hand, software developers (similarly to engineers in various engineering disciplines) seem to overly trivialize the need to respect the bottom line. They often cannot understand when an arguably adequate but not "best" or "perfect" solution is chosen over a better technical solution for non-technical reasons.

Conclusion

We in the software development community tend to deal with mismatches all the time. We often spend significant energy and time "gluing" things together that weren't necessarily designed to go together. Despite all of this technical experience we have making incongruent pieces work together, we still seem to have difficulty resolving perhaps the most difficult and most important mismatch of all: the mismatch between software developers and people who are not software developers. Although there are some positives that come from this (such as checks-and-balances on "science fair projects"), there is significant dysfunction, angst, resentment, and demoralization caused by this impedance mismatch.

Tuesday, May 15, 2012

Java IDEs have come a long way since the days of JBuilder (though JBuilder seemed like a welcome advance at the time). Today's Java IDEs (such as NetBeans, Eclipse, IntelliJ IDEA, and JDeveloper) are very advanced tools that most Java developers embrace for writing significant Java code. As advanced as these IDEs are, they all still have their own quirks and each seems better and easier to use when one understands some key tips (or "tricks") to using that IDE more efficiently. In this post, I look at some tips I have found useful when using NetBeans.

Disabling Automatic Scanning

A problem that can be especially onerous when using NetBeans on a large code base with many related projects open is the occasionally too-frequent automatic scanning that NetBeans performs. This is supposed to only occur intermittently and its intention is good, but sometimes the intended behavior's value is worth less than the performance-degrading cost justifies. Fortunately, this option can be disabled when its cost is greater than its benefit. In the NetBeans for PHP blog post Enable auto-scanning of sources - Scan for External Changes, Petr Pisl covers how to do this in NetBeans 6.9.

This feature is also supported in NetBeans 7.1 as shown in the following screen snapshot (window shown is accessible by selecting Tools ⇒ Options ⇒ Miscellaneous ⇒ Files).

If the benefits of automatic scanning are desired (because, for example, multiple people are changing source code underneath each other frequently or because different editors are being used on the same versions of files), but less of it is wanted, another tip is to reduce the number of NetBeans projects and files that are open in NetBeans.

Controlling Level of NetBeans Hints

NetBeans's Java hints can aid the Java developer in improving and modernizing his or her Java code. The hints cover topics as diverse as performance, safety, conciseness, coding standards, likely bugs, latest JDK standards, and best practices. I do not cover these useful hints in more detail here because I've already covered them in multiple previous posts. I introduced NetBeans hints and how to enable them , configure them as warnings or errors, and introduced seven of the most important hints in my blog post Seven Indispensable NetBeans Java Hints. In the blog post Seven NetBeans Hints for Modernizing Java Code, I discussed seven more hints that are useful for bridging legacy Java code forward to use the best features of newer SDKs (J2SE 5, Java SE 6, and Java SE 7). My post Creating a NetBeans 7.1 Custom Hint demonstrates writing custom hints to further expand NetBeans hinting capability beyond the out-of-the-box hints.

Setting Source/Target JDK Appropriately

In the blog post Specifying Appropriate NetBeans JDK Source Release, I looked at several advantages of setting the JDK level for the NetBeans projects' source/target JDKs appropriately. This can make a major difference for developers using JDK 7 as it helps the hints covered in the previous tip to show areas where pre-JDK 7 code can be migrated to JDK 7 constructs. However, even developers using JDK 6 or JDK 5 can find value to having this set appropriately. The appropriate setting not only advertises features that are available, but it also prevents developers from mistakenly using newer versions when they are not yet available in the actual version of code the developer should be using. NetBeans will warn the developer that certain features are not available for that JDK setting, so it is important to have it set properly.

Tuesday, May 8, 2012

One of the things that can be a little tricky for developers new to Java or even for experienced Java developers new to formatting with Java Dates, is the specification of a date/time format using SimpleDateFormat. The class-level Javadoc-based documentation for SimpleDateFormat is pretty thorough in its coverage of patterns representing various components of a date/time. However, unless one carefully reads and understands these various patterns, it can be tricky to remember the difference between lowercase 'd' for day in the month and uppercase 'D' for day in the year or to remember if it's lowercase 'm' or uppercase 'M' used for months versus minutes. In this post, I look at a simple application written in JavaFX that allows a developer to quickly try arbitrary patterns to see how SimpleDateFormat will render the current date/time given the arbitrary pattern. In theory, a developer could use this simple tool to quickly determine the effect of his or her date/time pattern, but it's really more of an excuse to apply JavaFX.

The simple JavaFX 2-based application shown above makes it easy to try out different date/time format patterns to see what SimpleDateFormat will do with each. A series of these used on the evening of Tuesday, 8 May 2012, are shown next. These examples demonstrate several key aspects of using SimpleDateFormat:

Uppercase 'M' is used for months while lowercase 'm' is used for minutes.

Uppercase 'D' is for the number of the day of the year (since January 1) while lowercase 'd' is the number of the day of the month (since May 1 in this case).

Two 'y' or 'Y' digits represent 2-digit year, but 3 or 4 'Y' or 'y' digits can be used for a 4-digit year.

The simple example highlighted in this blog post demonstrates the simplicity of JavaFX and provides an example of how JavaFX can provide graphical interfaces to make Java applications more intuitive. As part of this, mouse event handling in JavaFX and the common JavaFX idiom of using builders are both demonstrated. A practical use of this application is to quickly and easily determine the representation that is provided by SimpleDateFormat for a given pattern.

The "Inspect" field of the "Inspect and Transform" dialog allows the NetBeans user to tailor which project or file should be inspected. The "Use" portion of the "Inspect and Transform" dialog allows that NetBeans user to specify which hints to inspect for. In this case, I am inspecting using custom hints and I can see that by clicking on the "Manage" button and selecting the "Custom" checkbox. Note that if "Custom" is not an option when you first bring this up, you probably need to click the "New" button in the bottom left corner.

When I click on "Manage" and check the "Custom" box, it expands and I can see the newly created "Inspection" hint. If I click on this name, I can rename it and do so in this case. The renamed inspection ("CurrentDateDoesNotNeedSystemCurrentMillis") is shown in the next screen snapshot.

To create the hint and provide the description seen in the box, I can click on the "Edit Script" button. Doing so leads to the small editor window shown in the next screen snapshot.

If more space is desired for editing the custom inspection/hint, the "Open in Editor" button will lead to the text being opened in the NetBeans text editor in which normal Java code and XML code is edited.

The above code works properly, but could be more concise. When I tell NetBeans to associate my new inspection with this project in the "Inspect and Transform" dialog, NetBeans is able to flag this for me and recommend the fix. The next three screen snapshots demonstrate that NetBeans will flag the warning with the yellow light bulb icon and yellow underlining, will recommend the fix when I click on the light bulb, and implements the suggested fix when I select it.

As the above has shown, a simple custom hint allows NetBeans to identify, flag, and fix at my request the unnecessary uses of System.curentTimeMillis(). I've written before that NetBeans's hints are so handy because they do in fact do three things for the Java developer: automatically flag areas for code improvement for the developer, often automatically fix the issue if so desired, and communicate better ways of writing Java. For the last benefit in this case, the existence of this custom hint helps convey to other Java developers a little more knowledge about the Date class and a better way to instantiate it when current date/time is desired.

My example custom NetBeans hint works specifically with the Date class. An interesting and somewhat related StackOverflow thread asks if a NetBeans custom hint could be created to recommend use of Joda Time instead of Date or Calendar. A response on that thread refers to the NetBeans Java Hint Module Tutorial. Looking over that tutorial reminds me that the approach outlined in this post and available in NetBeans 7.1 is certainly improved and easier to use.

Incidentally, a hint like that asked for in the referenced StackOverflow thread is easy to write in NetBeans 7.1. There is no transform in this example because a change of the Date class to a Joda Time class would likely require more changes in the code than the simple transform could handle. This hint therefore becomes one that simply recommends changing to Joda Time. The next screen snapshots show the simple hint and how they appear in the NetBeans editor.

Each release of NetBeans seems to add more useful hints to the already large number of helpful hints that NetBeans supports. However, it is impossible for the NetBeans developers to add every hint that every team or project might want. Furthermore, it is not desirable to have every possible hint that every community member might come up with added to the IDE. For this reason, the ability to specify custom hints in NetBeans and the ability to apply those hints selectively to projects and files are both highly desirable capabilities.