Thứ Hai, 14 tháng 9, 2009

Beware Software Management Overreaction

One of the most sinking feelings one can feel in software development occurs when a client or management overreacts to some crisis or mistake with onerous new requirements, procedures, and processes. In this blog post, I look at why those in authority sometimes do overreact, describe why overreaction can be dangerous and costly, and outline some ideas regarding how to reduce or prevent overreaction.

Why Do People Overreact in Software Management?

There are several explanations for why people overreact in management of software projects. Most of these are applicable to general overreaction in any area, but do apply specifically to software development.

Emotional

By definition, overreaction is associated with an emotional response that is inappropriate to the circumstances. Emotion can cloud over or completely obscure logic. Many poor decisions in life have been made in the heat of the moment when emotions run high and logic runs low. Emotions are usually high as a direct result of the incident being overreacted to. Often these incidents are most glaring when we can least afford them and stress levels are already high.

Helplessness / At Least Do Something

Another reason one might overreact is out of fear of not knowing how to resolve the situation in a reasonable fashion. If there is a problem with no clear solution, it may feel better temporarily to at least do something even if that "something" is not rationale or even a good idea. Sometimes the best thing to do is to do nothing, at least at first. Calmer heads are more likely to come up with more useful ideas for dealing with a particular issue.

Punishment

Overreaction may be directed at one individual, a team, or even the entire staff as a form of punishment. This is a little different than the previously covered reasons because it is more calculated and deliberate. However, that does not mean emotion is not involved; the desire to punish is often emotionally driven.

Send a Signal

Another calculated reason a person in authority might overreact is that he or she wishes to send a signal to other developers that certain (mis)behaviors are not tolerated. As with the punishment motivation, the person overreacting may be doing so intentionally to send a "stronger signal."

Lack of Understanding of True Cost of Overreaction

In some cases, a person in authority might feel their newly imposed procedure or process is perfectly reasonable because he or she does not understand the true cost and true negative consequences of it. This typically happens when a person with little or no hands-on software development experience attempts to decide on extreme measures related directly to some stage of producing software without consulting people in the know.


How Costly is Overreaction?

The total cost of overreaction is nearly impossible to quantify because it is so highly dependent on the situation and on the degree of overreaction. However, there are many different costs to overreacting and some of them are listed here. To illustrate many of these points, I will be using a simple example of an incident such as breaking the build.

Direct Cost can Exceed Original Incident Cost

Suppose that the build is broken occasionally because of developers in a rush. It is not a frequent event, but does happen from time to time. If the estimated lost developer time is, hypothetical speaking still, about 5 person-hours per week, it makes little sense to impose new procedures and policies that prevent that build breakage that require 50 developers to spend an extra 30 minutes per day checking out their code before merging. That's because 50 developers multipled by 0.5 hours per week means 25 person hours are spent to avoid a 10 person hour problem. That is an overreaction. The cure is worse than the disease.

There are cases where the extra time to avoid the problem may be justifiable. I am especially thinking of situations where one deems the quality benefits of the additional steps to be an advantage. However, if the new procedure is instituted solely to deal with the hours wasted on a broken build, it is nonsensical and counterproductive to institute additional procedures that will take more time than the thing being avoided.

For me personally, it is often better to have one longer work stoppage now and then as opposed to transitioning on a daily basis between the work I really need to accomplish and the mind-numbing steps added to avoid "incidents."

Unintended Consequences

Besides the direct costs of any new initiative instituted as part of an overreaction, there will almost certainly be unintended (and often negative) consequences. I have written before about the dangers of unintended consequences. These are especially challenging to quantify, but always seem to apply. A newly enacted procedure might be intended to reduce a certain undesirable event, but in the process leads to one or more different undesirable events. This can be especially true if the concept sprung from overreaction leads to cloaking bad incidents rather than actually preventing them.

Collateral Damage

One of the reasons that overreaction can be so disheartening to software developers is that we often know that the innocent are going to be treated in the same way as the guilty. Even worse, highly skilled and very experienced developers can sometimes be forced to endure the same restrictions applied to newer and less experienced developers after an incident occurs. In many aspects of like it is a laudable ideal to treat everyone the same, but it is a mistake in software development to treat the craftsman the same as the apprentice. Even worse, it is really despicable to treat the craftsman the same as the incompetent. Processes, procedures, plans, and initiatives spawned from overreaction often lump everyone together and deal with the least common denominator. There are many costs associated with this: lower productivity from the most productive developers, dissatisfaction in the people that are most difficult to replace, and lack of attention on the people who really need it.


How do We Prevent / Reduce Overreaction?

Count to Ten

Often the best way to avoid overreaction is to take the emotion out of it. If you're in the authority position or can influence the person with authority, try to wait at least a day (or preferably over a weekend) to allow emotions to cool and to reconsider the true cost of the incident you are tempted to overreact to.

Understand the Direct Costs of Your Reaction

Some of the worst consequences of overreaction I have seen are those that occur because the person making the decisions did not really understand the costs or consequences of their decisions. Before a decision is made like, "Before doing procedure A, one must always do procedure B," the person forcing that procedure on others should do them in a realistic environment to see how painful and costly they are and to truly determine there effectiveness.

Consider Unintended Consequences

One of the hallmark characteristics of many decisions made in haste and with emotion is that only one consequence is being considered. The decision usually does directly deal with that considered consequence, but it is important to consider the other consequences. As an extreme example, not allowing developers to write code will eliminate the addition of new bugs into the system. However, there are other consequences of this action such as no new code being written or maintained.

Apply Tweaks Rather than Seismic Shifts

One of the problems with overreaction is that it often leads to decisions that are not appropriate in terms of degree of seriousness of the original incident. It can often be better to reduce the first idea one has for dealing with a crisis to a smaller, less significant change and measuring if that is sufficient to meet the problem. Often, if cooler heads prevail, this is what happens anyway.

Acknowledge that Not Everyone is Equal in Experience and Skill

If developers have different grade levels or other indicators of their experience, then why not tailor processes differently for each grade level. If feasible, it would be even better to tailor to each individual. Much of the more successful open source community uses meritocracy in a similar fashion.

Contingency Plans

A big part of overreaction is often due to fear, shock, and a sense of hopelessness. This can be mitigated by considering some of the common things that can happen in software (hardware failures, defects, delays, difficult to maintain code, etc.) and have plans in place beforehand regarding how to handle them. This may help identify small steps that can be taken to reduce the likelihood of the problems in the first place and can provide calm and logic when the incidents do occur. Being proactive allows one to be less reactive.

Admit Mistakes

If a bad plan is put into the place as part of overreaction, the worst thing that can be done is to leave it in place to save face. It is better to admit that a response was overly reactive and either temper it or remove it altogether. This can be difficult to do even though it is the correct thing to do.


Conclusion

It can be very easy to fall into the trap of committing an overreaction to a significant event or incident. Unfortunately, this often exacerbates the problem and exasperates the development team. In this blog posting, I've looked at why we are prone to overreaction, some of the costs of overreaction, and some techniques to reduce the frequency and severity of overreaction.

Please feel free to add in the comments any reasons, costs, or remedies you have observed related to overreaction in software development.

Thứ Bảy, 12 tháng 9, 2009

More Software Developers Should Write Blogs

With the pervasiveness of blogs focused on software development, it is sometimes easy to wonder if there are more bloggers than readers. There are so many software-related blogs that Jurgen Appelo recently started listing his Top 200 Blogs for Developers instead of the 100 he formerly listed.

The presence of so many blogs has helped me tremendously. There are three types of assistance these software development blogs have provided me.

1. Exposed to New Ideas, Concepts, Techniques, and Methodologies

Some blogs have provided me with information on a topic that I did not know much about. These are usually the blogs I run into when perusing DZone or similar sites.

2. Direct Answers

Some blog postings have helped me solve a particularly tricky problem by matching a search with Google or other search engine.

3. Links and References to Answers

A third category of assistance from software development blogs includes the blog posts that have not had the answer I sought directly, but have linked to or referenced material that did provide the answer. These can be especially helpful when I am searching on something and not quite using the appropriate term to have the search engines return the most popular related links.


Why Don't More Developers Write Blogs?

Even with all of these blog postings, I believe that we could all benefit from even more software developers writing blogs. The software development community would especially benefit in the second and third of the three categories of helpful blogs I mentioned above because more blogs would mean more potential sources of information for direct and indirect answers.

Some Many Most of the highest skilled and most experienced software developers that I know and work with personally do not write blogs. There are some obvious reasons for this such as lack of interest and lack of time (too busy with other projects, work, or other activities). However, I also know that at least part of the reason that some of these highly talented developers do not write blogs is that they underestimate the value of what they could contribute to the software development community. In the remainder of this blog post, I will look at why I think many of these developers who think they do not have anything to add are mistaken.


Software Development Blogs Present Lopsided View of Software Development

I have noticed a glaring difference between my perception of the software development world based on the blogs I see and the software development world that I experience firsthand through work, through discussions with attendees at software development conferences, and so forth. I think we as a software development community could benefit from more blogs from some of the "everyday developers" working in the trenches with many different languages, different operating systems, different project sizes, different problem domains, etc. We have all of these covered to some degree, but it feels like the blog coverage is tilted more to some areas than others.


Different Opinions and Perspectives Do Matter

Statements like "all opinions matter" can seem like politically correct lip service, but there is some truth to this, especially in terms of seeing both sides of the story when considering a new or different technology or language. In software development, we have a tendency to act like lemmings and follow trends and fads, sometimes without sufficient consideration of the negatives and costs associated with that fad. I have found that my best decisions are made when I combine my own experience and instincts with reading of well considered and articulated thoughts from proponents of all sides of an issue. I often see outstanding and thought-provoking feedback comments to a blog post and wonder why that commenter does not write his or her own blog post with that kind of insight.


It's All About the Little Things

I occassionally run into a particular problem with a particular language, library, or technology for which I am unable to find a solution via search engine. I have gotten so used to today's powerful search engines pointing me to a blog, forum thread, or article with the answer I am looking for that it is almost scary when there are no useful responses. This often happens when using very old technologies, very new technologies, or technologies without a large customer base. When a colleague knows how to resolve one of these problems, the first question I have to ask (to at least myself) is, "Why don't you blog about this?"


Nothing to Add

As I mentioned earlier, some of the blog posts that I have been very grateful for are those that did not directly answer my question, but which pointed me to the blog, article, or forum thread with the answer. In some cases, no particular source had what I was looking for, but the blog helped me arrive at the answer by triggering something in my mind or making me think about the problem in a different way. I think if more developers wrote blogs about the problems they have faced and how they have resolved them, our chances of finding these indirectly beneficial blogs would be greater.

Several years ago, I approached a respected colleague regarding assisting me with writing an article on software design. I respected his thinking process and was particularly impressed with his ability to think deeply regarding software design concepts and techniques. He had never written a technical article or blog post, but I felt that he would be a great asset in writing a highly useful article on software design. He was very interested in the proposed project, but felt inadequate from the very beginning. He wondered what he could add on top of what was already out there in terms of software development. As we had our initial discussions about the outline of the article and what we'd write, I became increasingly excited about the article's potential. Unfortunately, we ended up not writing that article as we got distracted by other things and I have always felt that at least part of the reason we never wrote that article is the overwhelming feeling of having nothing to add. To me, that's the community's loss because I really thought that some of the ideas he and I came up with together were just enough different in perspective from what was already available to add real value for readers.


Strong on Concept; Weak on Experience

My feeling is that the software development community has greater coverage in terms of software development theory and concepts in our blogs than we do in terms of practical, hard-earned experience and details. Some of my favorite blog postings have been those which have relayed a real-life, practical experience and the lesson learned from that experience. It is one thing to say, "You should always do it this way," but it is entirely more useful and convincing to explain in practical terms why you should do it that way. These posts can be difficult to write because they acknowledge mistakes and weaknesses, but they can be highly beneficial for others. After all, one can learn much from one's own mistakes, but it is even better (and less costly) to learn from the mistakes of others. Some examples of blog posts that fit into this category include Rotten Statics (related to Inconstant Constants in Java), Don't Ignore serialVersionUID, and The * Stupidest Things I Have Done in My Programming Job.

It is important to note here that some of the most popular blogs that are strong in theory and concept are so strong because the writer does have deep and broad practical experience behind the theory and concept. Still, in terms of convincing one of the value of the theory or concept and in terms of understanding the significance of theory or concept, it is difficult to be more effective than by telling a sad story based on real events. If more bloggers were willing to share their failures and disappointments, there would be more evidence to back up the conceptual blog postings.


Nobody Would Read It Anyway

Some highly skilled developers do not blog because they believe no one will read their words anyway. Admittedly, they are correct in this assumption, at least early on. It usually takes time to gain regular readers and there is no guarantee that one will ever gain any significant number of regular readers. If that is the only reason one wishes to blog, then it might not be worth the effort. However, even if a blog is only read by people searching for something and running into a blog post via search engine, the community will benefit from the existence of the blog post. For the early months of my own blog's existence, the vast majority of viewers of my blog came to it through search engines. That has gradually shifted to the vast majority coming to it from links, due at least in part to the syndication of my blog on JavaWorld.

I started my blog with the thought that even if no one else ever read it, it would at least serve as a glorified bookmark of principles, concepts, techniques, and ideas worth remembering. I have actually used it several times this way to quickly find something that I knew I had written about but could not quite recall the exact details about.


Selfish Motivations

Besides serving as a "glorified bookmark," a blog can be beneficial for other selfish reasons as well. It can serve as evidence to potential and current clients and employers of one's experience and familiarity with particular techniques. It can be a soapbox for one's opinions. If the folks you work with are tired of hearing your rants, consider a blog as another outlet. In fact, a blog can provide a way to let off a little steam about things that are bothering you. The act of writing a blog can even help one organize and articulate one's own thoughts better. The fact is that even these selfish motivations can lead to blogs that might challenge readers and improve the software development community discussion.


Online Tools Are Equalizers

I think the software development community would benefit tremendously from more blogs by a wider demographic of software developers. It's not that I have time to read any more blogs: I cannot even read all that I'd like to read as it is. However, there are many tools at our disposal that would help us benefit from more blogs from a wider set of personalities and experiences. First, sites like DZone help choose some of the most interesting articles. Even a first-time blog writer could post his or her blog posting to DZone and, if it was particularly good, could get some immediate attention. Second, the powerful search engines make nearly any blog post a potential hit. If we had more blog posts from a wider group, we'd be more likely to see their posts show up in niche searches. Because the search engines and social tools like DZone favor blogs with characteristics that typically imply a certain level of interest, new blogs that truly have nothing to add are largely ignored. This is important because it does reduce the noise.


Conclusion

There are many times when the herd of software developers start moving toward the siren's song and it would benefit all of us if we had a few more people trying to snap us out of their trance or at least slow us down enough to reconsider the real benefits and costs. Besides adding to the discussions regarding software development, more sharing of practical, real-life experience could help each other reduce loss, minimize bad decisions, and improve productivity.

Thứ Năm, 10 tháng 9, 2009

JDK7 java.util.Objects Utility Methods

In recent weeks, there has been news of various features once proposed for JDK 7 that no longer are slated for this release. Although it is not unusual to reduce the scope of a major software project (including a new version of the Java programming language) as its formal release nears, it can still be somewhat disappointing as the current poll results in Java.net's poll emphasizes.

Fortunately, it is not all bad news in terms of features being dropped from JDK 7. Joe Darcy's recent post What methods should go into a java.util.Objects class in JDK 7? could be the beginning of bringing back some enthusiasm regarding JDK 7. Although the addition of these methods may seem like a minor addition, I have found great benefit in using similar utility-heavy classes such as Collections, Arrays, and even the ubiquitous java.lang.System class.

Darcy's post begins with the sentence:

For JDK 7, I think it is high-time the platform included a class like
java.util.Objects to hold commonly-written utility methods.


I couldn't agree more! I have used several other languages that have similar utility methods collected in a class like this one and I miss these when using Java. It would be a welcome addition.

After listing three ideas (two-argument static equals method, static hash code method that handles null, and compareTo for primitives), Darcy concludes the post with this sentence:

What other utility methods would have broad enough use and applicability to go into a common java.util class?


The last quote implies that we could see some handy utility methods added to a java.util.Objects class that would be generally beneficial to a wide number of Java developers.

It is not difficult to come up with useful methods for a class like this. In fact, the difficulty will be constraining what is added and avoiding abuse of utility classes. We have all probably found ourselves writing certain functions routinely or adding projects such as Apache Commons to our system to provide extremely common functionality not provided by the SDK itself. Adding these most-used methods to a central class within the JDK would be beneficial because we could have standardly available well-tested methods for these most common of functions.

Besides our own experience developing homegrown methods, the most obvious sources of ideas for good candidates for a java.util.Objects class can be gleaned from third-party Java libraries fulfilling the same need (such as Apache Commons and OstermillerUtils). For example, I have blogged previously on some common methods provided by Apache Commons that I really like such as ToStringBuilder and EqualsBuilder and HashBuilder. The Apache Commons class ObjectUtils seems to be particularly useful in providing ideas for a java.util.Objects class.

Another obvious source of ideas includes experience with other languages that support similar functionality in a common object. For example, I have regularly appreciated ActionScript's ObjectUtil class that provides methods such as the toString(Object) method (pretty prints an object's representation even when the provided class does not have its own toString implementation).

Stephen Colebourne has provided a lengthy list of Apache Commons Lang-inspired utility methods in his blog post JDK 7 - Method suggestions. Some other responses to Darcy's original request for ideas include toString, a lessons learned response from developing Google Collections's Objects class, a debug utility class, and another version of Colebourne's post.

Not everyone wants to see this java.util.Objects class added as demonstrated by this post. If you would like to see this utility class added and have some ideas for it, now is your opportunity to recommend generic utility classes that you would like to see in a standard central location.

Thứ Tư, 9 tháng 9, 2009

Inconstant Constants in Java

In their 2009 JavaOne presentation Return of the Puzzlers: Schlock and Awe (PDF), Joshua Bloch and Neal Gafter presented seven more puzzlers and extracted lessons learned from each of these puzzlers and their solutions. These lessons learned include old standbys such as read the documentation, ensure you are calling the correct methods, preferring composition over inheritance, and never call an overridable method from constructor. Not surprisingly, many of the lessons learned also tie into Joshua Bloch's Effective Java recommendations.

One of the interesting nuances of the Java programming language highlighted in this presentation is the concept of constant variables in Java. The presentation highlights three sections of the Java Language Specification (JLS) Third Edition (HTML/PDF): 4.12.4 ("final Variables"), 13.4.9 ("final Fields and Constants"), and 15.28 ("Constant Expression"). Section 4.12.4 ("final Variables") defines and warns about constant variables at the very end of that section (links/references to other sections of JLS omitted; emphasis included in original text):

We call a variable, of primitive type or type String, that is final and initialized with a compile-time constant expression a constant variable. Whether a variable is a constant variable or not may have implications with respect to class initialization, binary compatibility and definite assignment.


The specification and this JavaOne presentation point out that only primitives and String can be constant and that null is not a constant. They also point out problems that can occur between code binaries when constants are inlined and not all code is re-compiled together. For example, if the final keyword is added to a field and the pre-existing binaries try to set the field, an IllegalAccessError will be thrown. Going the other way, removing final behaves the same way as changing the value of a final field: the pre-existing code will not break, but it also won't realize that there is a new value.

This is demonstrated with a simple example. Suppose you have a simple class called Constants as defined below.

Constants.java - First Version

package dustin.examples.puzzlers;

/**
* The main purpose of this class is to demonstrate the problems with inlined
* constants when they are not really constant.
*/
public class Constants
{
public static final String ONE = "Uno";
public static final String TWO = "Dos";
public static final String THREE = "Tres";
public static final String FOUR = null;
public static final String FIVE = "Cinco";
}


Four of the five constants defined above have String values. However, one of them, the constant FOUR, is assigned to null.

Suppose that the Constants.java class was edited or replaced with the code below:

Constants.java - Second Version

package dustin.examples.puzzlers;

/**
* The main purpose of this class is to demonstrate the problems with inlined
* constants when they are not really constant.
*/
public class Constants
{
public static final String ONE = "Un";
public static final String TWO = "Duex";
public static final String THREE = "Trois";
public static final String FOUR = "Quatre";
public static final String FIVE = "Cinq";
}


The second version of this class maps English number names to French names for the same numbers. In this case, all five constants had Strings defined. Now suppose there was a "client" class that makes use of Constants.java with code as shown in the next listing.

NumbersTranslator.java - Client Using Constants.java

package dustin.examples.puzzlers;

import static java.lang.System.out;

public class NumbersTranslator
{
public static void main(final String[] arguments)
{
out.println("One is " + Constants.ONE);
out.println("Two is " + Constants.TWO);
out.println("Three is " + Constants.THREE);
out.println("Four is " + Constants.FOUR);
out.println("Five is " + Constants.FIVE);
}
}


If the above class, NumbersTranslator, was recompiled every time the Constants.java class it depends on was recompiled, we would not see any discrepancies. However, if we compiled NumbersTranslators against the first version (Spanish) of Constants.java and then recompiled only the second version (French) of Constants.java without recompiling NumbersTranslators, an interesting result occurs when we run the NumbersTranslators.main(). That output is shown next.



The interesting observation here is that even though the code was run with the "French version" of Constants.java, four of the five lines printed still show the Spanish versions (from first version of Constants.java file). However, the value printed for the fourth constant is the French version.

This output demonstrates two principles. First, true constant variables are inlined. This is why the Spanish versions of the constants remained for four of five lines remained despite having the French version of Constants.java on the classpath. The fact that the fourth line displayed the French version illustrates the second point: null is not a constant variable and thus is not inlined and so the actual constant on the classpath is used in that case.

The JavaOne presentation and the JLS both recommend the same two practices for dealing with this subtlety. The first recommendation, in this case from the specificaition, is: "The best way to avoid problems with 'inconstant constants' in widely-distributed code is to declare as compile time constants only values which truly are unlikely ever to change." In other words, only designate a field as static final if the field will truly never change. The specific suggests that mathematical constants fit well here. This makes sense because we don't expect these physical constants to change (or will they?). The specification goes further: "Other than for true mathematical constants, we recommend that source code make very sparing use of class variables that are declared static and final."

The second recommendation provided by both the JLS and the JavaOne presentation is to, as the JLS states, "declare a private static variable and a suitable accessor method to get its value." The specification demonstrates this with a code snippet similar to the following:


private static String ONE;
public static int getOne() { return ONE; }


Bloch and Gafter propose a similar concept. They demonstrate a general static ident method that accepts the type of the constant and returns the passed-in parameter. It would look something like this:


private static String ident(String stringConstant)
{
return stringConstant;
}

public static final String ONE = ident("uno");


The reason that both of these related approaches work is that the calling of the respective methods (getXXXX or ident) prevents inlining of the constant variables involved.

The next code listing shows the first version of Constants.java re-written to use the Bloch/Gafter approach.


package dustin.examples.puzzlers;

/**
* The main purpose of this class is to demonstrate the problems with inlined
* constants when they are not really constant.
*/
public class Constants
{
private static String ident(final String stringConstant)
{
return stringConstant;
}

public static final String ONE = ident("Uno");
public static final String TWO = ident("Dos");
public static final String THREE = ident("Tres");
public static final String FOUR = ident(null);
public static final String FIVE = ident("Cinco");
}


The output is shown next. I followed the same steps as before (building and rebuilding only the once-Spanish version of Constants.java file with the new French version), but the results are different (which is better in this case):



As the output shows, the recommended "indent" approach prevents inlining of the constant variables and allows the updated Constants.java constants to be fully reflected in the executed code.

This may not be a big deal in a development environment in which full clean and rebuild processes prevent these binary mismatches, but it has potential to lead to nasty and not-so-obvious bugs in "widely-distributed code" situations described in the specification.


Additional References

Java Constants - A nice post on this subject

Rotten Statics - Nice overview of where this bit a development team "in real life"

Thứ Hai, 7 tháng 9, 2009

Latest on Java Developers' Feelings Regarding Java SE 7

Java.net's current poll question asks, "What's your reaction to the JDK 7 feature list?" The poll is still relatively new, but with nearly 230 responses, the results are already interesting. Currently, eighty percent of the votes come down into three questions that fall into the respective categories of positive, neutral, and negative. The remaining twenty percent of the responses are either "Other" or "I don't care."

Of the responses that fall into one of the three questions that are not "Other" or "I don't care," the current majority has chosen the neutral option of "Some handy buy insignificant features." This is probably what best describes my reaction as well with a little positive and a little negative. Following close behind, the next most popular choice is the outright negative option "Disappointed; when do we get JDK 8?" I definitely feel at least a little this way. The enthusiastically positive response "I love it and can hardly wait" is the third of the three committed responses, but is a little too enthusiastic for me to select.

There are some features I look forward to in Java SE 7 (modularization, Indexing Access Syntax for Lists and Maps [see also my related post], automatic resource management, and improved generics type inference, G1 garbage collector, and VM improvements for better dynamic language support), but some of the features I looked most forward to have been taken out of consideration for Java SE 7 (reified generics, Elvis operator and null safe operators, JMX 2, improved exception handling, BigDecimal operators).

There are several good sources of information on what is coming with Java SE 7. The OpenJDK site hosts a page with JDK 7 Features that categorizes features currently slated for Java SE 7 in categories of Virtual Machine, language, core, client, and Enterprise (the last entails upgrading the JDK's built-in versions of JAXP, JAXB, and JAX-WS to the latest stable releases).

Sun provides the JDK 7 Preview Page with a link to download a preview Java SE 7 SDK and a link to the Java SE 7 API documentation. Alex Miller's Java SE 7 page also provides a useful collection links to blogs and articles related to Java SE 7.

I have not heard of an overarching Java Specification Request (JSR) for Java SE 7 yet, but we already know several of the constituent JSRs that will likely be included:
JSR 203: More New I/O APIs for the JavaTM Platform ("NIO.2")
JSR 292: Supporting Dynamically Typed Languages on the JavaTM Platform
JSR 294: Improved Modularity Support in the JavaTM Programming Language
JSR 296: Swing Application Framework
JSR 308: Annotations on Java Types

Java Arrays: Copying, String Representations, and Collections

Since the introduction of the Java Collections Framework with JDK 1.2, I have used Java arrays significantly less frequently than I used to. However, I still use arrays occasionally, often because a library or API I am using makes heavy use of arrays. When working with arrays, the Arrays class can be particularly helpful. In this posting, I'll look at how this class simplifies the copying of arrays and providing String representation of arrays. I'll also look at how the use of the method Collection.toArray(T[]) is often used to access the first element of a Java collection without explicit iterating.


Copying Arrays

As demonstrated in the Arrays section of the Java Tutorials, the System class provides an arraycopy method that can be used to copy the contents from one array into another.

The method below shows use of System.arraycopy to copy an entire source array to a destination array. The parameters to this method allow for various ranges of the original array to be copied to the target array.


/**
* Copies the contents of the provided array into a new array that this method
* returns to the caller. This method is implemented with System.arraycopy.
*
* @param originalArray Array to be copied.
* @return Copy of the provided array.
*/
public static String[] copyCompleteStringArrayOldFashionedWay(final String[] originalArray)
{
final int originalArraySize = originalArray.length;
String[] destinationArray = new String[originalArraySize];
System.arraycopy(originalArray, 0, destinationArray, 0, originalArraySize);
return destinationArray;
}


This method works fine, but I prefer to use one of the overloaded Arrays.copyOf or Arrays.copyOfRange methods for copying array contents. I'll look briefly at my reasons for preferring the approach after demonstrating their use. The following method shows copying an entire array using Array.copyOf.


/**
* Copies the contents of the provided array into a new array that this method
* returns to the caller. This method is implemented with Arrays.copyOf.
*
* @param originalArray Array to be copied.
* @return The copy of the provided array.
*/
public static String[] copyCompleteStringArrayNewFangledWay(final String[] originalArray)
{
return Arrays.copyOf(originalArray, originalArray.length);
}


The several overloaded versions of Arrays.copyOf were introduced with Java SE 6. This is just one of the many advances Java SE 6 has brought to Java development and I have covered several of them in this blog.

As the code snippets above demonstrate, the Arrays.copyOf approach results in leaner, more concise code than use of System.arraycopy. Perhaps most important in this difference in terms of required code is that Arrays.copyOf and Arrays.copyRange do NOT require the developer to pre-allocate memory for the array that is the destination of the copying procedure. This may seem like a minor thing, but it reduces the possibility of running into a NullPointerException or other problem associated with improper sizing of the destination array. This appeals to me and my general aversion to unnecessary NullPointerExceptions.

Another thing that I prefer about use of Arrays.copyOf or Arrays.copyRange over System.arraycopy is the location (class) in which these utility methods are found. Functionality for copying arrays just feels out of place in the System class while array copying seems a perfect fit for the Arrays class. The Arrays class's Javadoc-based documentation starts with this sentence in its class-level comments: "This class contains various methods for manipulating arrays (such as sorting and searching)." Copying of arrays seems to fit naturally here and, in fact, I think adding "copying" to "sorting and searching" in the Javadoc sentence would be appropriate.


Printing Contents of Arrays

Once one gets used to easily printing the contents of a Java Collection (or Map) by passing that Collection (including Map in this context of "Collection") to System.out, System.err, or other stream, it can be a little bit disappointment to return to what is printed out for an array when trying to do the same thing. To illustrate, the code snippet below shows methods for printing the contents of an array, of a List, of a Set, and of a Map. Although they all look very similar in code, the output for the array is quite different from that of the Collections.


/**
* Print contents of provided Array directly to standard output using
* System.out directly.
*
* @param array Array to be printed directly to standard output with
* System.out.
*/
public static void printStringArrayDirectly(final String[] array)
{
out.println(INDENT + "DIRECT: " + array);
}

/**
* Print the provided List of Strings to standard output.
*
* @param stringsToPrint List of Strings to be printed.
*/
public static void printStringList(final List<String> stringsToPrint)
{
printHeader("List Directly (" + stringsToPrint.getClass().getCanonicalName() + ")");
out.println(INDENT + stringsToPrint);
}

/**
* Print the provided Set of Strings to standard output.
*
* @param stringsToPrint Set of Strings to be printed.
*/
public static void printStringSet(final Set<String> stringsToPrint)
{
printHeader("Set Directly");
out.println(INDENT + stringsToPrint);
}

/**
* Print the provided Map of Strings to Strings to standard output.
*
* @param stringsToPrint Map of String to String to be printed.
*/
public static void printStringMap(final Map<String,String> stringsToPrint)
{
printHeader("Map Directly");
out.println(INDENT + stringsToPrint);
}


The output for the Map, Set, and List appear in a reasonable and readable output format. The arrays's output is not nearly so readable or useful. Instead, it looks something like [Ljava.lang.String;@42e816. This output does tell us that it is an array of Strings and that its "unsigned hexadecimal representation of the hash code" (see Object.toString Javadoc for more on this) is 42e816 for this particular array instance.

One option for printing the contents of an array is to iterate over the array explicitly and print each element as iteration occurs over that element. Fortunately, an easy convenience method (Arrays.toString()) was added to the previously discussed Arrays class in J2SE 5 to make printing of array contents easier. This is demonstrated in the next code snippet.


/**
* Print contents of provided Array directly to standard output using
* System.out with results of Arrays.toString() handling of provided array.
*/
public static void printStringArrayUsingArraysToString(final String[] array)
{
out.println(INDENT + "ARRAYS'S TOSTRING: " + Arrays.toString(array));
}


As shown in the above code snippet, it is easy to invoke Arrays.toString on the array. In fact, it is an overloaded method that supports arrays of all of the primitive types as well as general objects as used in this example. The output of this static method is strikingly similar to the output when a List of Strings is printed directly.

Although my preference is to use Arrays.toString to print contents of an array, another approach one could take is to first convert the array to a Collection and then take advantage of the fact that Collections are converted to a readable String format implicitly. This is done with another static Arrays method, Arrays.asList(). This method directly provides a List based on a provided array. If a Set is desired, the resultant List can be passed to the constructor of a Set implementation that accepts a Collection as a parameter (such as HashSet).


Using Arrays to Retrieve Specific Element of Collection

Although I predominately use collections today rather than arrays, there are times when array syntax is highly useful. A common example of this is when I need to access a specific element in a collection. This seems to occur for me mostly when in a situation in which I know there is only one element in the collection and I need to access it directly. I don't want to iterate over the collection to simply obtain the first element. An easy way to get this first element without explicit iteration over the collection is to use the toArray methods on List and Set to first get an array handle to the elements underlying the collection and then to access the element by array index. The following code shows how this can be done. As noted in the comments, Java arrays employ C-like zero-based indexes and so using an index of 0 obtains the first element.


/**
* Extract the first element from the provided List of Strings. This is
* accomplished by using List's toArray method to access the List as an
* array and then the first element of that array is simply accessed with
* zero for the index (zero-based arrays means zero is index of first element
* in array).
*
* @param list List of Strings from which to extract first String element.
* @return First String element of the provided List of Strings.
*/
public static String extractFirstStringElementFromList(final List<String> list)
{
return list.toArray(new String[0])[0];
}

/**
* Extract the first element from the provided Set of Strings. This is
* accomplised by using Set's toArray method to access the Set as an array
* and then the first element of that array is simply accessed with zero for
* the index (zero-based arrays means zero is index of first element in array).
* WARNING: 'Order' in a Set is a tricky business. The use of the "first
* element" of a Set is probably mostly useful in situations where the calling
* code happens to know that the Set is a single element Set, perhaps because
* it is returned from a call using Collections.singleton().
*/
public static String extractFirstStringElementFromSet(final Set<String> set)
{
return set.toArray(new String[0])[0];
}


Of course, the array syntax allows any element in the Collection-turned-array to be accessed with the integer representing the array index. I just used zero here for the first element because it is the case I most commonly run into. It is also worth noting that List.get(int) already allows one to easily access a specific element in the List (my preferred approach). There is no similar method for Set presumably because this often doesn't make any sense in a Set context because some Set implementations (most notably HashSet) do not have the "predictable iteration order" of the LinkedHashSet.

I have stated previously that I'm a little disappointed with the list of features that appear to have made it into Java SE 7. However, it is interesting to see that it Index Access for Syntax for Lists and Maps appears on its ways into Java SE 7.


Conclusion

The Arrays class makes use of arrays in Java more convenient and easier than direct manipulation of those arrays. In this blog post, I have focused on use of overloaded Java SE 6 methods Arrays.copyOf (and corresponding Arrays.copyRange), J2SE 5's overloaded Arrays.toString() methods, and the Arrays.asList() method. I include the complete class containing above code snippets below.


Example Code - JavaArrays.java


package dustin.examples;

import static java.lang.System.out;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* This class demonstrates some Java utility functions related to Java arrays.
*/
public class JavaArrays
{
/** New line/carriage return/form feed. */
private static final String NEW_LINE = System.getProperty("line.separator");

/** Represents tab or indentation for output. */
private final static String INDENT = "\t";

/**
* Copies the contents of the provided array into a new array that this method
* returns to the caller. This method is implemented with System.arraycopy.
*
* @param originalArray Array to be copied.
* @return Copy of the provided array.
*/
public static String[] copyCompleteStringArrayOldFashionedWay(final String[] originalArray)
{
final int originalArraySize = originalArray.length;
String[] destinationArray = new String[originalArraySize];
System.arraycopy(originalArray, 0, destinationArray, 0, originalArraySize);
return destinationArray;
}

/**
* Copies the contents of the provided array into a new array that this method
* returns to the caller. This method is implemented with Arrays.copyOf.
*
* @param originalArray Array to be copied.
* @return The copy of the provided array.
*/
public static String[] copyCompleteStringArrayNewFangledWay(final String[] originalArray)
{
return Arrays.copyOf(originalArray, originalArray.length);
}

public static Map<String, String> generateMapToUppercase(final Collection<String> keys)
{
final Map<String, String> map = new HashMap<String, String>();
for (final String key : keys)
{
map.put(key, key.toUpperCase());
}
return map;
}

/**
* Extract the first element from the provided List of Strings. This is
* accomplished by using List's toArray method to access the List as an
* array and then the first element of that array is simply accessed with
* zero for the index (zero-based arrays means zero is index of first element
* in array).
*
* @param list List of Strings from which to extract first String element.
* @return First String element of the provided List of Strings.
*/
public static String extractFirstStringElementFromList(final List<String> list)
{
return list.toArray(new String[0])[0];
}

/**
* Extract the first element from the provided Set of Strings. This is
* accomplised by using Set's toArray method to access the Set as an array
* and then the first element of that array is simply accessed with zero for
* the index (zero-based arrays means zero is index of first element in array).
* WARNING: 'Order' in a Set is a tricky business. The use of the "first
* element" of a Set is probably mostly useful in situations where the calling
* code happens to know that the Set is a single element Set, perhaps because
* it is returned from a call using Collections.singleton().
*/
public static String extractFirstStringElementFromSet(final Set<String> set)
{
return set.toArray(new String[0])[0];
}

/**
* Print contents of provided Array directly to standard output using
* System.out directly.
*
* @param array Array to be printed directly to standard output with
* System.out.
*/
public static void printStringArrayDirectly(final String[] array)
{
out.println(INDENT + "DIRECT: " + array);
}

/**
* Print contents of provided Array directly to standard output using
* System.out with results of String.valueOf() handling of provided array.
*/
public static void printStringArrayUsingStringValueOf(final String[] array)
{
out.println(INDENT + "STRING'S VALUEOF: " + String.valueOf(array));
}

/**
* Print contents of provided Array directly to standard output using
* System.out with results of Arrays.toString() handling of provided array.
*/
public static void printStringArrayUsingArraysToString(final String[] array)
{
out.println(INDENT + "ARRAYS'S TOSTRING: " + Arrays.toString(array));
}

/**
* Print provided array to standard output using several different mechanisms
* of accessing String contents of array.
*
* @param array Array to be printed.
* @param label Label to be printed above printed array contents.
*/
public static void printStringArray(final String[] array, final String label)
{
printHeader(label);
printStringArrayDirectly(array);
printStringArrayUsingStringValueOf(array);
printStringArrayUsingArraysToString(array);
}

/**
* Print the provided List of Strings to standard output.
*
* @param stringsToPrint List of Strings to be printed.
*/
public static void printStringList(final List<String> stringsToPrint)
{
printHeader("List Directly (" + stringsToPrint.getClass().getCanonicalName() + ")");
out.println(INDENT + stringsToPrint);
}

/**
* Print the provided Set of Strings to standard output.
*
* @param stringsToPrint Set of Strings to be printed.
*/
public static void printStringSet(final Set<String> stringsToPrint)
{
printHeader("Set Directly");
out.println(INDENT + stringsToPrint);
}

/**
* Print the provided Map of Strings to Strings to standard output.
*
* @param stringsToPrint Map of String to String to be printed.
*/
public static void printStringMap(final Map<String,String> stringsToPrint)
{
printHeader("Map Directly");
out.println(INDENT + stringsToPrint);
}

/**
* Print the single provided String along with a header using the provided
* label.
*
* @param stringToPrint String to be printed.
* @param label Label to be used in header printed with this String.
*/
public static void printSingleString(final String stringToPrint, final String label)
{
printHeader(label);
out.println(INDENT + stringToPrint);
}

/**
* Prints provided label String as part of simple header to standard output.
*
* @param label Label to be included in header.
*/
public static void printHeader(final String label)
{
out.println(NEW_LINE);
out.println(
"====================================================================");
out.println("===== " + label + " ======");
out.println(
"====================================================================");
}

/**
* Main function for running demonstrations of Java array utility functions.
*
* @param arguments Command-line arguments; none expected.
*/
public static void main(final String[] arguments)
{
// Use fruits-oriented String array to demonstrate copying of arrays with
// System.arraycopy. Will also demonstrate multiple ways to print array.
final String[] fruitsSourceArray =
{"Apple", "Banana", "Grape", "Orange", "Strawberry", "Tomato", "Watermelon"};
final String[] fruitsDestinationArray =
copyCompleteStringArrayOldFashionedWay(fruitsSourceArray);
printStringArray(fruitsSourceArray, "Fruits SOURCE Array");
printStringArray(fruitsDestinationArray, "Fruits DESTINATION Array");

// Use vegetables-oriented String array to demonstrate copying of arrays
// with Arrays.copyOf. Will also demonstrate multiple ways to print array.
final String[] vegetablesSourceArray =
{"Asparagus", "Broccoli", "Carrot", "Green Bean", "Pea", "Spinach", "Tomato"};
final String[] vegetablesDestinationArray =
copyCompleteStringArrayNewFangledWay(vegetablesSourceArray);
printStringArray(vegetablesSourceArray, "Vegetables SOURCE Array");
printStringArray(vegetablesDestinationArray, "Vegetables DESTINATION Array");

// Demonstrate simplified printing of Java collections
final List<String> fruitsList = Arrays.asList(fruitsSourceArray);
printStringList(fruitsList);
final Set<String> fruitsSet = new HashSet<String>(Arrays.asList(fruitsSourceArray));
printStringSet(fruitsSet);
final Map<String, String> fruitsMap = generateMapToUppercase(fruitsList);
printStringMap(fruitsMap);

// Extract 'first' element of List and Set using toArray
final String firstListElement = extractFirstStringElementFromList(fruitsList);
printSingleString(firstListElement, "First Element from List");
final String firstSetElement = extractFirstStringElementFromSet(fruitsSet);
printSingleString(firstSetElement, "First Element from Set");
}
}

Thứ Ba, 1 tháng 9, 2009

Java's goto

There is an old programmer joke that goes something like this: One programmer in anger says to the second programmer, "Go to Hell!" The second programmer replies in obvious repulsion, "Ugh, you used goto!" The point of this nerdy humor is that to many programmers, use of "goto" is just about the worst offense one can commit.

There are several reasons that the goto is held in such low esteem among software developers. Edsger W. Dijkstra's paper A Case Against the GO TO Statement is a relatively early treatise on the evils of GOTO abuse. In that article, Dijkstra states, "[I became] convinced that the go to statement should be abolished from all 'higher level' programming languages." Dijkstra's Go To Statement Considered Harmful letter not only lambasted the goto statement, but also started a popular computer science trend of using the phrase "considered harmful" (though those two words were apparently used outside of programming before that).

Many programmers since Dijkstra have been bitten by some of the maintainability problems associated with use of goto statements in certain languages. Other programmers have heard these stories or have had the "Thou shalt not use goto" pounded into them so much that they don't need to experience its drawbacks firsthand to believe that they should not use GOTO.

Although the goto statement appears to have a generally bad reputation, it is not without its supporters. Frank Rubin wrote a response to Dijkstra's Go To Statement Considered Harmful (March 1968) called GOTO Considered Harmful' Considered Harmful (March 1987). In that letter, Rubin wrote about Dijkstra's letter having an effect on programmers so dramatic that "the notion that the GOT0 is harmful is accepted almost universally, without question or doubt." Of this observation, Rubin wrote, "This has caused incalculable harm to the field of programming, which has lost an efficacious tool. It is like butchers banning knives because workers sometimes cut themselves." Note that Dijkstra responded to Rubin's letter with On a Somewhat Disappointing Correspondence. The Cunningham & Cunningham Wiki page Go To says this about the goto statement: "The apprentice uses it without thinking. The journeyman avoids it without thinking. The master uses it thoughtfully."

There are numerous other resources that cover the pros and cons of using the goto statement. I don't intend to rehash that debate here other than the brief presentation of the early history of the controversy already covered. I have heard some Java developers stating that Java does not have a goto statement and that is what I want to discuss in the remainder of this blog post.

Java does reserve "goto" as a reserved keyword. However, it is an unused keyword. What this means is that although the keyword does not actually do anything productive, it is also a word that cannot be used in code for names of variables or other constructs. For example, the following code will not compile:


package dustin.examples;

/**
* Class demonstrating Java's goto-like functionality.
*/
public class JavaGotoFunctionality
{
/**
* Main executable function.
*
* @param arguments Command-line arguments: none expected.
*/
public static void main(final String[] arguments)
{
final String goto = "Go to bed!";
}
}


If I try to compile that code, I see an error like that shown in the next screen snapshot.



The error message "<identifier> expected" with a pointer at the space before "goto" gives an experienced Java developer enough of a clue to quickly realize that there is something wrong about using "goto." However, it may not be as obvious to someone new to Java.

I generally do not use the goto construct, but I also recognize that there are situations in which its use makes for code that is more readable and uses less crazy work-arounds than not using it. In Java, this has also been realized and support is provided for some of the most common situations in which a goto statement would be most useful and would likely actually be preferable to alternatives. The most obvious examples of this are the labeled break and labeled continue statements. These are discussed and demonstrated in the Java Tutorials section Branching Statements.

The ability to label a particular statement and then have the break or continue apply to that statement rather than its most immediate statement (as an unlabeled break or continue does) is especially useful in cases where nested loops would otherwise require more code and more complex code to accomplish the same thing. I have found that I can often redesign my data structures and code to avoid such situations, but this is not always practical.

Another good resource related to use of goto-like functionality in Java is the 13 June 2000 JDC Tech Tip Goto Statements and Java Programming. As this tip points out, the labels can actually be used to any block and are not limited to break and continue. However, it is my experience that necessity of this approach outside of break and continue is far less common.

One important observation about labels is that code execution does not literally return to that label when the break somelabel is executed. Instead, execution flow goes to the statement immediately following the labeled statement. For example, if I had an outer for loop called "dustin:", then a break to that would actually go to the first executable statement following the end of that labeled for loop. In other words, it acts more like a "goto the statement following the labeled statement" command.

I don't provide any examples of using these labeled break or labeled continue statements here because there are plenty of good examples easily located online. Specifically, the two resources that I have already mentioned (Java Tutorials Branching Statements and Goto Statements and Java Programming Tech Tip) include simple illustrative examples.

The more I work in the software development industry, the more convinced I become that there are few absolutes in software development and that extremist positions will almost always be wrong at one point or another. I generally shy away from use of goto or goto-like code, but there are times when it is the best code for the job. Although Java does not have direct goto support, it provides goto-like support that meets most of my relatively infrequent needs for such support.