Saturday, November 29, 2008

ActionScript toString() with Interfaces

ActionScript 3.0 includes many object-oriented features that have an obvious Java-like syntax, but there are some nuances of ActionScript's object-oriented support that are not so Java-like. In this blog entry, I'll look in some detail at the use of ActionScript's toString() method in conjunction with ActionScript interfaces.

The value of the toString() in Java development and debugging is generally accepted and widely understood (see Item #10 in Joshua Bloch's Effective Java, Second Edition, or Item #9 in the First Edition). Similarly, use of toString() in ActionScript can provide similar advantages as discussed in Debugging Basics in Flex 3 (beta).

While an ActionScript toString() looks similar to a Java toString and while use of the toString() can be highly beneficial in working with both Java and ActionScript, there are some important differences to understand. I have previously covered some nuances of the ActionScript toString() implementation in Flex: ObjectUtil.toString() Versus Inherited Object's toString() and When An ActionScript Object Does Not Provide toString(). I'll briefly summarize some points from those two previous blog entries before demonstrating use of ActionScript's toString specifically in conjunction with an ActionScript interface.


Characteristics of the ActionScript Object.toString()

* ActionScript classes that directly extead the Object class (don't extend any other ActionScript class) and provide a toString() implementation do not need to use the override keyword.

* Related to the first point above, ActionScript's Object.toString() is not inherited by descendant ActionScript classes.

* The static utility class mx.utils.ObjectUtil provides a toString() that is highly useful for displaying String representations of ActionScript class instances that do not have their own implemented toString() methods).


The observations summarized above play out when using ActionScript interfaces and implementing those ActionScript interfaces. The remainder of this blog entry will be focused on the relationship of toString() to the ActionScript interface.

ActionScript makes use of the interface concept throughout its standard library. The blog entry ActionScript 3 Class Interface Implementations lists the ActionScript classes that implement interfaces in the Flex 3 API, the AIR 1.0 API, and the Flash API.

The ActionScript interface syntax is pretty straightforward for anyone familiar with the Java interface. The next code listing demonstrates a simple interface in ActionScript and uses the commonly adopted Flex coding convention of having an interface's name begin with "I".

IState.as


package examples
{
/**
* Simple interface example demonstrating use of interfaces in Flex 3.
*
* Methods defined in a Flex interface cannot have any modifiers.
*/
public interface IState
{
/**
* Provide name of the state.
*
* @return Name of the state.
*/
function getStateName():String;

/**
* Provide the state's abbreviation.
*
* @return Abbreviation of the state.
*/
function getStateAbbreviation():String;

/**
* Provide the capital of the state.
*
* @return Capital of the state.
*/
function getStateCapital():String;
}
}



Most Java developers should have very little trouble reading this interface. Like a Java interface, the "public" modifier is not required for the methods defined as part of the interface. In fact, these method modifiers are not even allowed in the ActionScript interface. The interface keyword is the same as in Java and the concept of method signatures without implementations is the same for both languages' interfaces.

ActionScript uses the same implements keyword that Java uses to designate when a class implements an interface. This is demonstrated in the next code listing, for the State class which implements the IState interface.


State.as


package examples
{
/**
* Implementation of IState interface that is mainly intended to demonstrate
* use of interfaces in Flex.
*/
public class State implements IState
{
/** Name of the state. */
private var stateName:String;

/** State's abbreviation. */
private var stateAbbreviation:String;

/** Capital of the state. */
private var stateCapital:String;

/**
* Constructor.
*
* @param newStateName Name of the state.
* @param newStateAbbreviation State two-digit abbreviation.
* @param newStateCapital Capital of the state.
*/
public function State(
newStateName:String,
newStateAbbreviation:String,
newStateCapital:String)
{
this.stateName = newStateName;
this.stateAbbreviation = newStateAbbreviation;
this.stateCapital = newStateCapital;
}

/**
* Provide name of the state.
*
* @return Name of the state.
*/
public function getStateName():String
{
return this.stateName;
}

/**
* Provide the state's abbreviation.
*
* @return Abbreviation of the state.
*/
public function getStateAbbreviation():String
{
return this.stateAbbreviation;
}

/**
* Provide the capital of the state.
*
* @return Capital of the state.
*/
public function getStateCapital():String
{
return this.stateCapital;
}
}
}



To demonstrate behavior of ActionScript interfaces in conjunction with the toString() method, I will use a simple Flex application to invoke an object's toString() implementation directly and to also expose the object's contents via the ObjectUtil.toString() method. The simple Flex application is shown next.


Main.mxml (without use of interface)


<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
width="900" height="900"
applicationComplete="runExample();">
<mx:Script>
<![CDATA[
import mx.utils.ObjectUtil;
import examples.IState;
import examples.State;

/** Set up a state for the interface example. */
public function setUpState():State
{
const state:State = new State("Colorado", "CO", "Denver");
return state;
}

/**
* Display state information.
*
* @param state State whose information is to be displayed.
*/
public function displayState(state:State):void
{
stateNameText.text = state.getStateName();
stateAbbreviationText.text = state.getStateAbbreviation();
stateCapitalText.text = state.getStateCapital();

stateToStringText.text = state.toString();
stateObjectUtilToStringText.text = ObjectUtil.toString(state);
}

/**
* Set descriptive information on this example type. This is a
* convenience function related to demonstration of principles in
* a blog entry, but is not significant to the functionlity of this
* class.
*/
private function setExampleType():void
{
exampleTypeText.text = "No toString() method implemented in class.";
}

/** Run the example of using Flex interfaces. */
public function runExample():void
{
setExampleType();
displayState( setUpState() );
}
]]>
</mx:Script>

<mx:Panel id="mainPanel" title="State Example: Using Flex Interfaces">
<mx:Form id="stateForm">
<mx:FormItem id="stateNameItem" label="State Name">
<mx:Text id="stateNameText" />
</mx:FormItem>
<mx:FormItem id="stateNameAbbreviation" label="State Abbreviation">
<mx:Text id="stateAbbreviationText" />
</mx:FormItem>
<mx:FormItem id="stateCapital" label="State Capital">
<mx:Text id="stateCapitalText" />
</mx:FormItem>
<mx:FormItem id="exampleType" label="Example Description">
<mx:TextArea id="exampleTypeText" height="75" />
</mx:FormItem>
<mx:FormItem id="objectToString" label="toString()">
<mx:TextArea id="stateToStringText" />
</mx:FormItem>
<mx:FormItem id="objectUtilToString" label="ObjectUtil.toString()">
<mx:TextArea id="stateObjectUtilToStringText" />
</mx:FormItem>
</mx:Form>
</mx:Panel>
</mx:Application>



The above MXML file displays the results of calling a toString() directly on the provided object (instance of State) as well as the results of calling ObjectUtil.toString() on the provided object (instance of State). The IState interface is not used in the code above.

The mxmlc complier does not allow this code to compile, but instead reports the error message "Error: Call to a possibly undefined method toString through a reference with static type examples:State." and specifically cites the following line of code: "stateToStringText.text = state.toString();" This is shown in the following screen snapshot:



This error message makes it fairly obvious that a toString() implementation needs to be added to the State class. This also is evidence of the point made earlier about a class extending Object not being able to explicitly access toString() without an implementation of it. In other words, the State class that extends Object without an explicit toString() implementation cannot have toString() called explicitly. This is definitely different than in Java where the toString() would call Java's root Object's toString() in this situation.

We'll add a toString() implementation to the State class and try it again. The method looks like this:


toString() added to State.as


/**
* Provide String representation of me.
*
* @return String representation of me.
*/
public function toString():String
{
return "The capital of " + this.stateName + " ("
+ this.stateAbbreviation + ") is " + this.stateCapital;
}



With this toString() implementation in place, the Flex application Main.mxml (which has been modified only to change the text returned from the setExampleType() method) compiles. When this compiled SWF is executed, it appears as shown in the next screen snapshot.




Based on the above, we see the need to implement the toString() on the class directly rather than relying on it to get that method from its Object parent class. Now it is time to look at what happens when we try to call toString on the interface this State class implements. Note that the interface does not define a toString() method. In Java, this does not matter and the appropriate toString() gets called on an object even if its interface doesn't specifically call out a toString(). To try this out the Main.mxml application is changed to use IState interface rather than the State class. The slightly modified Main.mxml is shown next.


Main.mxml (using interface)


<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
width="900" height="900"
applicationComplete="runExample();">
<mx:Script>
<![CDATA[
import mx.utils.ObjectUtil;
import examples.IState;
import examples.State;

/** Set up a state for the interface example. */
public function setUpState():IState
{
const state:IState = new State("Colorado", "CO", "Denver");
return state;
}

/**
* Display state information.
*
* @param state State whose information is to be displayed.
*/
public function displayState(state:IState):void
{
stateNameText.text = state.getStateName();
stateAbbreviationText.text = state.getStateAbbreviation();
stateCapitalText.text = state.getStateCapital();

stateToStringText.text = state.toString();
stateObjectUtilToStringText.text = ObjectUtil.toString(state);
}

/**
* Set descriptive information on this example type. This is a
* convenience function related to demonstration of principles in
* a blog entry, but is not significant to the functionlity of this
* class.
*/
private function setExampleType():void
{
exampleTypeText.text =
"toString() method implemented in class but not interface; "
+ "call attempted via the interface.";
}

/** Run the example of using Flex interfaces. */
public function runExample():void
{
setExampleType();
displayState( setUpState() );
}
]]>
</mx:Script>

<mx:Panel id="mainPanel" title="State Example: Using Flex Interfaces">
<mx:Form id="stateForm">
<mx:FormItem id="stateNameItem" label="State Name">
<mx:Text id="stateNameText" />
</mx:FormItem>
<mx:FormItem id="stateNameAbbreviation" label="State Abbreviation">
<mx:Text id="stateAbbreviationText" />
</mx:FormItem>
<mx:FormItem id="stateCapital" label="State Capital">
<mx:Text id="stateCapitalText" />
</mx:FormItem>
<mx:FormItem id="exampleType" label="Example Description">
<mx:TextArea id="exampleTypeText" height="75" />
</mx:FormItem>
<mx:FormItem id="objectToString" label="toString()">
<mx:TextArea id="stateToStringText" />
</mx:FormItem>
<mx:FormItem id="objectUtilToString" label="ObjectUtil.toString()">
<mx:TextArea id="stateObjectUtilToStringText" />
</mx:FormItem>
</mx:Form>
</mx:Panel>
</mx:Application>



The mxmlc compiler will not allow this to compile for the same reason that it did not allow compilation before toString() was added to the State class. The reason for this is that the IState interface does not have toString() defined in it.




The following can be added to the IState interface:

toString() Definition to Add to IState Interface


/**
* Provide String representation of me.
*
* @return String representation of me.
*/
function toString():String;


With this toString() defined in this interface, the code compiles. The resultant SWF renders as shown in the next screen snapshot.




What can be gleaned from this is that the interface must spell out toString() as an available method if any class implementing that interface is expected to provide its String representation via the interface. Rather than adding a toString() method to every interface one might ever implement in ActionScript, a slightly cleaner approach is to define a base interface with toString() and have all interfaces extend it. For example, one could define the IBase.as as shown in the next code listing.


IBase.as


package examples
{
/**
* Base interface providing a toString definition for all child interfaces
* to use.
*/
public interface IBase
{
/**
* Provide String representation of me.
*
* @return String representation of me.
*/
function toString():String;
}
}



With IBase.as defined above, the IState.as code becomes slightly simpler because it no longer needs to define toString(). The new and improved IState that extends IBase is shown next:


package examples
{
/**
* Simple interface example demonstrating use of interfaces in Flex 3.
*
* Methods defined in a Flex interface cannot have any modifiers.
*/
public interface IState extends IBase
{
/**
* Provide name of the state.
*
* @return Name of the state.
*/
function getStateName():String;

/**
* Provide the state's abbreviation.
*
* @return Abbreviation of the state.
*/
function getStateAbbreviation():String;

/**
* Provide the capital of the state.
*
* @return Capital of the state.
*/
function getStateCapital():String;
}
}


As with Java, ActionScript classes can implement multiple interfaces, so this approach will often work very well, even if other interfaces need to be implemented.


Other Possibilities

Another possible approach for getting to a toString() implementation on a class is to cast the interface to the specific class that implements that interface. In this example, this would mean casting the IState interface to State and then calling toString() on that State instance.

The casting approach is demonstrated by the following modified version of the Main.mxml's displayState() method.

Main.mxml displayState() Method Using Casting


/**
* Display state information.
*
* @param stateInterface State whose information is to be displayed.
*/
public function displayState(stateInterface:IState):void
{
const state:State = stateInterface as State;
stateNameText.text = state.getStateName();
stateAbbreviationText.text = state.getStateAbbreviation();
stateCapitalText.text = state.getStateCapital();

stateToStringText.text = state.toString();
stateObjectUtilToStringText.text = ObjectUtil.toString(state);
}


This example demonstrates ActionScript's alternative casting syntax (use of 'as'). Note that I could have used "const state:State = State(stateInterface);" in place of "const state:State = stateInterface as State;".

Although casting obviously works, I am generally against casting because it is often a red flag of bad design. Perhaps even more significant is the possibility of the cast throwing a runtime error or returning a null. It is uglier and more dangerous to cast than to simply provide the toString() definition in the interface.

Another alternative would be to make the properties of State public. If this was done, then the ObjectUtil.toString() would print these public attributes of that class as shown in the next screen shapshot.



I don't like this approach because it requires the properties to all be public, which defeats some of the purpose of class-based encapsulation. So, I still prefer the approach of using a super interface with a toString() method defined.

A nice side effect of having toString() specified in an interface is that implementing classes must implement it. Perhaps the biggest drawback I've seen with Java toString() is that it is often not implemented by developers. Although Java does give Object's toString() representation in such cases, that is often not very useful.

Conclusion

The use of toString on an ActionScript class accessed by its interface is somewhat different from the same situation in Java. However, it is easy to address this issue by providing a basic super interface that provides for toString() and having all business interfaces extend that super interface. The side benefit of this is that classes which implement the super interface or any of its extended interfaces will be forced to implement a toString() method.

Friday, November 28, 2008

Flex Error Handling: A Simple Example

I have recently read and heard about situations in which Flex error handling is misunderstood. In this blog entry, I'll attempt to demonstrate, with a simple example, how Flex error handling works and attempt to drive out some of the sources of confusion. To keep this entry a reasonable size, I'll focus specifically on the Flex handling of errors (synchronous) and won't address Flex handling of error events (asynchronous).

Before I get into the actual example of throwing, catching, and "handling" (printing error contents in this simple case) a synchronous error in Flex, I need to point out the significance of using the Flash Player Debugger Version. My example will demonstrate that an error will provide some information regardless of whether it is used with a regular Flash Player or a Debugger Flash Player, but the Error class's getStackTrace() method will only return a not-null value if run in a debugger version of the Flash Player.

As I explained in my blog post on the command-line fdb debugger, it makes sense to me to only be able to see the stack trace in the debugger player because you probably don't want to spill too much error information (including ugly stack traces) all over your average client's application. On the other hand, when you have debugging turned on and are running a debugger version of the Flash Player, you probably do want the ability to see the stack trace as provided by Error.getStackTrace().

Flex provides several pre-defined ActionScript-based error classes that a Flex developer can explicitly throw when appropriate and can also expect certain Flex methods to throw when the related exceptional condition is encountered. These error classes provided by Flex out of the box include ECMAScript-mandated errors and some Flash-specific errors. All errors should extend the Error class. For Java developers, extending Flex's Error class and catching thrown Flex errors (either Error or any of its children) will seem very similar to exception handling in Java. Even the try-catch-finally syntax is remarkably similar.

Let's look at some code. The following is the code listing for the simple example.


<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
width="900" height="900"
applicationComplete="testException()">

<!-- This example demonstrates a simple example of Flex error
handling. One of the main illustrated points in this
example is that the Error.getStackTrace() method returns
null when the regular Flash Player is used and only returns
a not-null value when run in a debugger Flash Player. The
ObjectUtil class is used to make it more obvious that a null
is returned from Error.getStackTrace() when not running in
the debugger Flash Player.

This example is associated with the blog "Dustin's Software
Cogitations and Speculations."

The Flash Players, regular and debugger, can be downloaded
at http://www.adobe.com/support/flashplayer/downloads.html. -->

<mx:Script>
import mx.utils.ObjectUtil;

/**
* Test Flex exception handling.
*/
public function testException():void
{
try
{
intentionallyThrowException();
}
catch (error:Error)
{
stackTraceText.text = ObjectUtil.toString(error.getStackTrace());
messageText.text = error.message;
toStringText.text = error.toString();
nameText.text = error.name;
errorIdText.text = String(error.errorID);
}
finally
{
// I get called whether an exception is caught or not.
}
}

/**
* Intentionally throw an exception for use in Flex exception
* testing.
*/
public function intentionallyThrowException():void
{
throw new SyntaxError("That was some bad syntax!");
}
</mx:Script>

<mx:VBox id="mainDisplay">
<mx:Form>
<mx:FormItem id="stackTraceItem" label="Exception Stack Trace">
<mx:Text id="stackTraceText" />
</mx:FormItem>
<mx:FormItem id="messageItem" label="Message">
<mx:Text id="messageText" />
</mx:FormItem>
<mx:FormItem id="toStringItem" label="toString">
<mx:Text id="toStringText" />
</mx:FormItem>
<mx:FormItem id="nameItem" label="Name">
<mx:Text id="nameText" />
</mx:FormItem>
<mx:FormItem id="errorIdItem" label="Error ID">
<mx:Text id="errorIdText" />
</mx:FormItem>
</mx:Form>
</mx:VBox>

</mx:Application>


A significant portion of the above code is actually comments. If you remove the explanatory comments, the code is pretty small. Either way, the code is straightforward, especially if you have written Java exception handling code before.

The example code presents key properties (ID, message, and name), a key method (getStackTrace()), and the toString() representation of an Error class in the Flex form for easy viewing. When the compiled Flex application (.swf file) is executed with a normal (non-debugger) Flash Player, the output appears as shown in the next screen snapshot:



Even without the debugger player being used, the "message" and "name" properties (the combination of which is provided by the Error's toString()) provide useful information. However, the stack trace is a null because we are not using a debugger player.

With a debugger player being used, the results are different as shown in the next screen snapshot:



Without making any changes to my code and, in fact, the only change being the use of a debugger Flash Player instead of the regular Flash Player, I now have access to the stack trace!

It is also worth mentioning here another advantage of the Flash Player Debugger version when working with errors in Flex development. The example above demonstrated a case where an error was anticipated and code was written to catch it. Flex, unlike Java but like most other languages, does not have checked exceptions/errors. This means that a developer is never required to catch a particular error. This also implies that unanticipated errors can and do get thrown. What happens to these differs depending on which Flash Player is being used. If the regular Flash Player is being used, there is usually no sign of an error condition, but often things don't work as they should either (because the underlying error is preventing something necessary from happening). With the debugger version of the Flash Player, a stack trace is automatically presented in a pop-up for any uncaught errors. Again, it makes sense that one would want this in development but would not necessarily want the average end-user with a regular Flash Player to see it.

To illustrate the uncaught error scenario, I am adding a method to the above example that calls the same method that intentionally throws the error. This second code listing also differs from the first because I made a concerted effort to rename things from Exception to Error to be more in line with Flex terminology.


<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
width="900" height="900"
applicationComplete="testErrors()">

<!-- This example demonstrates a simple example of Flex error
handling. One of the main illustrated points in this
example is that the Error.getStackTrace() method returns
null when the regular Flash Player is used and only returns
a not-null value when run in a debugger Flash Player. The
ObjectUtil class is used to make it more obvious that a null
is returned from Error.getStackTrace() when not running in
the debugger Flash Player.

A second central point of this example is to demonstrate
handling on an unanticipated (and hence uncaught) error in
the regular Flash Player and in the Debugger Flash Player.

This example is associated with the blog "Dustin's Software
Cogitations and Speculations."

The Flash Players, regular and debugger, can be downloaded
at http://www.adobe.com/support/flashplayer/downloads.html. -->

<mx:Script>
<![CDATA[
import mx.utils.ObjectUtil;

/**
* Test error handling with and without explicit capture
* of an error.
*/
public function testErrors():void
{
testError();
testWithoutErrorHandling();
}

/**
* Demonstrate what happens when an error is not explicitly
* caught.
*/
public function testWithoutErrorHandling():void
{
intentionallyThrowError();
}

/**
* Test Flex Error handling.
*/
public function testError():void
{
try
{
intentionallyThrowError();
}
catch (error:Error)
{
stackTraceText.text = ObjectUtil.toString(error.getStackTrace());
messageText.text = error.message;
toStringText.text = error.toString();
nameText.text = error.name;
errorIdText.text = String(error.errorID);
}
finally
{
// I get called whether an exception is caught or not.
}
}

/**
* Intentionally throw an error for use in Flex error handling
* testing.
*/
public function intentionallyThrowError():void
{
throw new SyntaxError("That was some bad syntax!");
}
]]>
</mx:Script>

<mx:VBox id="mainDisplay">
<mx:Form>
<mx:FormItem id="stackTraceItem" label="Exception Stack Trace">
<mx:Text id="stackTraceText" />
</mx:FormItem>
<mx:FormItem id="messageItem" label="Message">
<mx:Text id="messageText" />
</mx:FormItem>
<mx:FormItem id="toStringItem" label="toString">
<mx:Text id="toStringText" />
</mx:FormItem>
<mx:FormItem id="nameItem" label="Name">
<mx:Text id="nameText" />
</mx:FormItem>
<mx:FormItem id="errorIdItem" label="Error ID">
<mx:Text id="errorIdText" />
</mx:FormItem>
</mx:Form>
</mx:VBox>

</mx:Application>


When the SWF compiled from the code immediately above is executed against the regular Flash Player, there is no visual evidence of the uncaught exception in the newly added ActionScript method testWithoutErrorHandling(). However, there is a dramatic difference when using the debugger Flash Player. It places the stack trace in an pop-up as shown in the next screen snapshot.



As the above screen snapshot shows, we did not need to add any extra code to see this stack trace. Simply using the debugger Flash Player led to the unanticipated error having its stack trace displayed.

Side Note: Because of advantages such as access to the stack trace via Error.getStackTrace() call, access to the stack trace automatically when an unanticipated error is not captured, and the ability to trace statements to the fdb debugger, I recommend to anyone considering working with Flex that they use the Flash Player debugger version by default during Flex development.

The results shown above were run on SWF files compiled with mxmlc using its default options as specified in the flex-config.xml file. I now move onto looking at how tweaking one of the settings in the flex-config.xml file can affect error handling in Flex.

There is an entry in the flex-config.xml file that looks like this:


<!-- Turns on the display of stack traces for uncaught runtime errors. -->
<verbose-stacktraces>false</verbose-stacktraces>'


Changing the "false" to "true" leads to more verbose output in the pop-up that appears for uncaught errors when run in the Flash Debugger Player as shown in the next screen snapshot. Similarly, this change leads to the same extra verbosity in the Error.getStackTrace() results. In short, the stack trace associated with an Error and available either implicitly for uncaught errors or explicitly for captured errors via the Error.getStackTrace() call, can have its level of verbosity controlled with this verbose-stacktrace setting.



If the two pop-ups are compared, it is obvious that the turning the option from "false" to "true" really did increase the stack trace verbosity. If the application is run in a regular, non-debug Flash Player, there is still no indication of an uncaught error ever occurring and null is still returned from Error.getStackTrace().


Conclusion

Flex provides error handling mechanisms that have many similar characteristics as Java exception handling, including the syntax. However, there are also some differences in the treatment of errors in ActionScript and Flex as compared to Java (such as no checked exceptions). Using a debugger version of the Flash Player for development of Flex is always a good idea, but this is particularly true when dealing with Flex error handling.

Wednesday, November 26, 2008

Software Developers' Guilty Pleasures

The term guilty pleasure is often used to describe music, television, movies, or other entertainment that we might (often somewhat secretly) like even when many around us (especially in our peer group) mock that same specific entertainment. You have to be pretty comfortable with these guilty pleasures to acknowledge them to those around you.

I believe there are guilty pleasures in software development just as there are in so many other aspects of life. These software development guilty pleasures arise from situations such as the following:

* Writing code that does not conform to the expected conventions and standards.
* Writing code that is challenging, interesting, or helps learn something new even though the plain, old-fashioned approach might be satisfactory or even superior.
* Writing less code at any cost.
* Forcing certain design patterns, implementation patterns, or other design/implementation approaches on situations that don't warrant them.
* "Improving" or "refactoring" someone else's code to "fix it."
* "Improving" or "refactoring" our own code when it really is not necessary or requested.
* Favoring and using a product that is not used in our normal development environment.
* Having the ego stroked.

There are probably many more manifestations of guilty pleasures of software developers, but I will limit the remainder of this blog entry to discussing some illustrative examples of each of these types of software development guilty pleasures.


Rebellious Coding

I think most of us appreciate the value and benefits of certain coding conventions and standards. That being said, many of us can probably readily provide a wide list of times where we felt the imposed standard or convention was either not worth enforcing or actually a negative practice. It is difficult in these cases to not succumb to the guilty pleasure of simply doing it "the correct way" despite what the convention calls for. James Dean doesn't have anything on us.


The Allure of Resume-Driven Development and the Magpie Effect

Many of us just cannot help ourselves when it comes to avoiding this guilty pleasure and the examples of this are plentiful. In How to Use Groovy without Management Finding Out, the author provides a clear example of this guilty pleasure and even points out that the IDE could already do what the blog entry was about. Still, the author (and many of us reading the entry) cannot help but be fascinated by the ability to do the same thing with Groovy scripts.

Other examples I have seen of this effect include gratuitous and unwarranted use of recursion (where an iterative approach would actually be easier to understand and better performing, but lacked the coolness of recursion), needless use of EJB 2.x despite its complexity, and using a new product or tool that's only real known advantage is that it is new instead of using a well-understood tool.


Less Code is More Fulfilling

As with the two above, this is a guilty pleasure I can easily fall into. Part of the problem here is that it often is a good thing to write less code. One of my great sources of satisfaction in development is refactoring a large chunk of code (especially if there is lots of copy-and-paste development built into the code) into a much smaller, more maintainable piece of code.

Unfortunately, this generally "good" practice can be taken to the extreme. I have been the unfortunate person tasked with maintaining or adding to some extremely terse code with no comments and it was a time-consuming process to figure out what the intent of the code was. I definitely think it is better to have code speak for itself than to have comments try to describe what the code is doing. However, less code and descriptive code are not always the same thing. While fewer lines of code is generally better, fewer characters per line is not generally better.

Besides descriptive names, other situations sometimes require a little extra code. For example, while I like Java's ternary operator in several common cases, I don't like nesting these too deeply because too many people find those difficult and even exhausting to unravel. Similarly, I am not afraid to add an extra set of parentheses on occasion to better communicate the intent of the conditional even if I know that the operator order of precedence will be okay without the parentheses. On the other hand, I've known some developers who secretly enjoy seeing the struggles of others trying to read their terse code and/or their code that relies on nuances of the programming language. I think that qualifies as a guilty pleasure.


Maslow's Golden Hammer

Maslow's Golden Hammer describes the situation in which a person applies a single approach or tactic to every problem he or she encounters. In software, for example, many of us wanted to use inheritance for everything when we first learned the basics of object-oriented programming. Articles such as Allen Holub's Why Extends is Evil have helped changed this over-arching viewpoint for the better, but I definitely remember trying to force everything into an inheritance hierarchy.

Design patterns are a notorious example of where a developer learns one design pattern (such as Singleton) and everything becomes a problem suitable for that pattern. We'd never want to admit that we always applied the same solution to every problem almost without thinking, but it is actually really easy to do and there is a comfort (hence the pleasure) in doing the familiar.


"Improving" Code that Doesn't Really Need Improvement

As with many of these categories, I am as guilty as the next developer in finding pleasure in improving code even when it realistically probably does not need it. I have seen many situations where one developer changes even the smallest things they don't care for in another's code: curly brace placements might be "fixed," grammar in comments might be "corrected," and even slightly more substantial but still very inconsequential changes get made for things that are often more a matter of taste than of any real significant benefit. I find it mentally painful to realize there is a way to improve my code, but not be allowed to change it because it works fine the way it is. In many of these cases, there is nothing really "wrong" with it, but I have thought of a better way to approach it or new information has helped me to see a new approach. There are times when the improvement is worth the effort, but sometimes the improvement is of such little value that it cannot be rationally justified. This is where the guilty pleasure comes in: it is still tempting to "improve" the code just because one wants it to be improved even if it doesn't need to be.


Playing Favorites

I have seen over and over again examples of developers who criticize certain products that they don't like or can never find any fault whatsoever with products they do like. This is often the case when comparing two implementations of the same functionality. Two otherwise intelligent and skillful developers can become so enamored with a given product or given vendor or can become so hostile towards a given product or given vendor that they cannot see that even their favorite product has disadvantages.

We see this on the web all the time. If someone points out why they don't like a particular product or framework, it is very common for numerous developers to jump all over them for obviously not understanding the product or framework well enough. It is just assumed that everyone who knows anything about the subject should know that this product is inherently good and should like it. To not like a product, in their viewpoint, is to not understand it.

I think the guilty pleasure here is thinking to oneself that I know all the right answers. If someone else doesn't like the product I've been using and evangelizing, it is easy to fall into the trap of thinking that either something is flawed in my own experience and judgment or something is flawed in the experience and judgment of the person critical of my favorite product. The guilty pleasure is thinking that I'm always correct and I always know the best way to do things.


Fame without Fortune

With the recent economic turmoil, it is easier than ever to think of being wealthy as some far-off distant mirage. However, many of the most successful developers that I have known have responded to praise and recognition equally to or even more than they have responded to monetary incentives. I have long felt that the most successful developers tend to be those who are confident without being arrogant. It should come as no surprise, then, that many developers do find pleasure in fame, even if they do not want to acknowledge that pleasure from fame.

There are many examples of this that directly benefit all of us. I have heard several people who are not software developers ask the question, "Why do so many people contribute so much of their own time, creativity, and effort to open source products for which they earn no compensation?" There are several reasons such as needing to include that particular developed product in their commercial product and doing it just for the fun of it, but I also believe that there is a strong motivation to be known for their contribution to the product and to the community.

The need for fame and accolades is evident in blogs such as this one. What benefit do I receive from writing this blog? I do like it when a reader responds via feedback and tells me that a particular tip helped them or saved them significant time. But that alone would probably not be enough to warrant the time I spend on this blog. Although I hate to admit it publicly because it is a guilty pleasure, I am forced to conclude that some of my motivation for writing a blog is the "fame" associated with doing so. (Stating opinions from a soapbox is a close second motivation.)

Any developer who has ever searched for his or her own name on Google, Yahoo, Cuil, or other search engine has shown at least a degree of this particular guilty pleasure. Even people who don't write public blogs, articles, books, or presentations can exhibit this guilty pleasure on a daily basis. The "fame" can be enjoyed even among a small group of fellow developers.


Conclusion

We as software developers certainly have our share of guilty pleasures. Many of these can actually be traced in general terms back to guilty pleasures that all human beings share. However, these general guilty pleasures correspond to concrete and observable behaviors in our work. We may not always want to admit to some of these guilty pleasures, but I think we can at least secretly acknowledge to ourselves that we do have them.

Finally, not all guilty pleasures are necessarily a bad thing. For example, many of the movies, television shows, and musical artists cited as common guilty pleasures actually are truly appreciated by large audiences. Similarly, there are some guilty pleasures in software development that actually have proponents who can and will argue for why these should not be "guilty" pleasures, but instead should bring everyone happiness. Most "guilty pleasures" in the entertainment sense really have more to do with taste and personal preferences than with any measurable or quantifiable value or quality. In some ways, the same could be said for the software development guilty pleasures.


UPDATE (28 November 2008): DrStrangeLug has added a nice software development guilty pleasure to the above list: automating chores that do not need to be automated (implying that they only need to be done once). I definitely find myself falling into this guilty pleasure. I justify it with the same rationale provided by DrStrangeLug: I might be able to use it again some day. As with most of the guilty pleasures above, there is a line between a very good practice (automating routine tasks is an obvious good thing) and spending far more time automating a one-time thing than it would take to do it once. Also, as with the other practices, there can still be some good even from this guilty pleasure: the developer's script or other automation skills get sharpened.

Monday, November 24, 2008

Flex: More Like HTML or More Like Java?

Joshua Partogi recently posted Why You Might Not Want to Use Flex on his blog. I found this blog entry particularly interesting because Joshua does not focus on the usual criticisms of Flex (which often are actually of the Flash Player) and because Joshua's experience is almost exactly opposite of mine. While I have generally found Flex to be significantly easier to use than any other web development frameworks that I have used, Joshua seems to have found both Tapestry and JavaServer Faces easier to use than Flex. As Joshua alludes to in both his blog entry and the linked-to presentation Switching Paradigms: From Regular Web to Flex, it is really a matter of experience and perspective.

I consider myself first and foremost an application developer with my primary interests, experience, and skillset focused on things like Java EE. I have, of course, written many web front-ends with JavaServer Pages, Struts, and several other web frameworks to a lesser degree. All of these web frameworks offered advantages and I appreciated the abstraction they provided me. However, the real problem was not the frameworks themselves. The one area that still felt like I was hacking stuff together was the implementation of dynamic behavior in the web browser via JavaScript and DOM manipulation. I also grew increasingly frustrated with the world's most popular web browser not fully supporting some of my favorite Cascading Style Sheet effects. For me, Flex was a breath of fresh air with its hiding of browser idiosyncrasies and the ease of implementing stunning new interfaces with highly dynamic behavior. I was hoping that Java would get a framework as compelling as Ruby on Rails and, for me, this was it.

This brings me back to perspective. While Flex itself is obviously not Java, it shares so may characteristics with Java and is so easy to integrate with Java that it almost feels like an extension to Java. Because I have always strongly preferred Java over JavaScript/DOM/CSS, it is no surprise that I found Flex and even ActionScript to be so refreshing and liberating.

I appreciate Joshua posting this blog entry because it reminds me that not everyone thinks the same or shares the same experiences. No framework or tool or product can be everything to everyone all the time. However, Flex has really left an impression on me, on the vast majority of my colleagues who have given it a shot, on and many others whose blogs I read. We all come from similar backgrounds with strong Java experience and have been spoiled by the ability to write code once and run it on virtually any operating system. For us, the idea of a web application written in Flex that can run on virtually any web browser is "how things should be done." Having to write code to take into account different browser vendors and even different versions of the same vendor's browser and having to test our applications every time on several different web browsers seems unnecessarily time-consuming.

I can appreciate how Flex/ActionScript's static typing, class-based object-orientation, and obvious Java-influenced characteristics can be foreign to someone who spends most of their web development in the HTML/CSS/DOM world. While Flex does offer support for these specifications to varying degrees, it certainly is not exactly like these and does require some learning and a new way of doing things.

I'm a strong believer in "to each his own." For me and for many people like me, Flex is the best thing to come to web development in a long time. For others, they may be perfectly happy with what they're using and have grown comfortable with. I have found that the best motivator for me to learn a new language, technology, toolkit, framework, or other product is some pain with my current language, technology, toolkit, framework, or product. The pain has to be consistent enough and of sufficient degree to motivate me to look at something new. While I have found some corner cases with Flex that are a little tricky and have found some things I'd prefer to see implemented another way, I have not experienced enough pain to really consider an alternative at this time unless something revolutionary comes along.

Joshua's last paragraph provides the advice that I'd reiterate to anyone who is unhappy with their current web development experience: don't take my word, the word of other Flex enthusiasts, or the word of people unhappy with Flex as the final word. Because we're all different, we have to find what we each like. I think most people who give Flex a fair try will like what they see.

Michael Martin, a fan of both Flex and Linux, informed me of the recent release of an alpha version of Flash Player 10 for 64-bit Linux. He is excited about this and has been happy with its performance so far.

Software Development Bloopers

Throughout my career, I have either directly experienced and/or witnessed developers around me lose significant development time because of little things that might be referred to as software development bloopers. I like the term blooper for these because the class of actions that lead to this time lost are the kinds of things that even highly intelligent and skilled developers can make from time to time. Just as bloopers at the end of films gives the audience a chance to see some of the silly errors made during production that were (usually) intentionally hidden for the actual delivered film, we also tend to not want to highlight our software development bloopers during development, but can laugh at them afterward.

While I like to think that I personally encounter these bloopers less frequently and that they cost significantly less time when I do make them then when I started my career, the truth is that I still do commit them from time to time. This should not be surprising when considering that even the best of actors and actresses also commit bloopers. I was planning originally to title this blog entry "Boneheaded Software Development Maneuvers." However, the definition of boneheaded implies incompetence and lack of intelligence. Most of these bloopers that I will be describing were made by very bright and highly skilled software developers. This is a key differentiator between bloopers and boneheaded maneuvers.

I begin describing software development blooper by what, in my mind, a software development blooper is not. If I am having trouble using a product or library because of a bug in that product or library or lack of support for standardization in that product, I don't classify this as a software development blooper. Rather this is a serious problem inherent in the product being used. Likewise, poor designs, poorly implemented code, lack of testing, lack of experience in a given programming language, and so forth are better classified as bad development practices or lack of training rather than as software development bloopers. Software development bloopers tend to be smaller in nature than these previously mentioned items, but can still cause significant loss of development time.

Examples of Software Development Bloopers

My focus now moves to discussing some concrete examples of software development bloopers that I have seen and/or directly experienced. I'll use these examples to form some conclusions about the characteristics of software development bloopers, to outline some specific methods for reducing the frequency and cost of these software development bloopers, and to identify some general areas where software development bloopers are most like to occur. I also hope that anyone reading this might be able to laugh or at least smile at some of their own personal software development bloopers.

Not Running the Latest Built Software

It is difficult to think of anything more frustrating than when the software you are running does not reflect the changes you know you just made. This may occur when one thinks that the JAR, WAR, EAR, .exe, .swf, or other file to be executed is being built in a certain location. No matter how the developer changes the source code, the running application does not seem to reflect those changes.

This situation most often occurs in very large projects or in cases where the developer has been away from a project for a while. In such situations, build scripts can change without the developer's knowledge.

A remedy for this particular blooper is to look closely at the dates associated with generated JAR, WAR, EAR, and other executable files.

Even when making sure that the WAR or EAR is generated as new, this issue can still arise if that newly created file is not deployed. For example, if the newly generated WAR file is not deployed to the web server or the newly generated EAR file is not deployed to the application server, the changes won't be seen. This situation can arise when a developer gets interrupted and forgets that the latest changes were not deployed. It is even more insidious when redeployment does not succeed because of an error during deployment, but the developer does not realize that it is still the old version that is deployed. This can happen when undeployment of the previous version fails or redeployment fails and the only significant warning is buried in the logs.

There are several other things that can prevent the develop from seeing changes made to the their application. These include web browser caching and inadvertent building and running from local file systems on different machines.

Most of these issues can be easily dealt with by paying close attention to what is happening in one's development environment. This sounds easy, but can be problematic when one is in a hurry and/or has several different things going on at once that distract the developer and detract from the ability to focus.

In addition to examining dates of files more closely, another obvious tactic used to narrow down whether the latest software is being executed is to add logging or standard output messages to the areas of code one expects to be run. The debugger can also be used to detect exactly what is happening, but use of these approaches is time-consuming and thus contributes to the time cost associated with running different versions of software than most recently constructed.

An approach that can be used to prevent or reduce the chances of having executable software become out of sync with the latest software additions or modifications is to automate as much as possible. Development effort placed into comprehensive Ant or Maven or other types of scripts pays off handsomely in preventing or reduces this type of software development blooper.


Editing the Wrong Code

Related to the software development blooper above, this one has to do with editing the wrong source code file (without realizing it obviously) and then wondering why the changes don't show up. There are several situations in which this might occur. An obvious case is in conjunction with version control systems. If the branching system is complex, it can be very easy to edit the wrong version of a file.

It can also be easy to start editing a generated file without even thinking about it and then have those changes wiped out when the regeneration process is run again. For example, when one generates Java classes from XML via JAXB or similar Java-to-XML binding approach, it can be easy to start looking at the generated code and even start changing it, forgetting that it is generated and likely to be overwritten the next time it is generated. Other examples of this include editing the NetBeans build-impl.xml Ant file and several types of IDE-generated code (such as GUIs with Matisse).

This is another case where this is most often a problem when the developer is distracted by too many things going on at once or is in too much of a hurry to think about the file that is being changed. Many of the popular tools that generate code place many comments and warnings in the generated code about it being generated in an attempt to reduce this happening.

The worst thing about editing generated code unintentionally is that all of the work is often wiped out with the next clean and build. The clean process will typically remove the generated file and then the build process will regenerate files. All changes made to the generated file are then lost. So, in addition to time lost by editing the wrong file, all remnants of the work are lost.


IDE-Assisted Software Development Bloopers

Java IDEs have become very powerful and highly useful in improving developers' productivity. However, there are multiple costs to the widespread use of the IDE. Most of us have decided that the benefits outweigh the costs, but we still must deal with those costs. One cost of using an IDE is that it can be easy to fall into the trap of letting the IDE do the thinking and/or accidentally approving an IDE recommendation that is not appropriate.

For example, when writing a "get" method on a class, the IDE might recommend that very "get" method as a return type because it does return the expected return type. If the developer selects that recommendation because he or she is in a hurry and is assuming that the data member associated with the "get" method will be the default recommendation, the developer will instead get a recursive "get" method that calls itself without end. This may not be discovered until the code is reviewed by someone else, run against a unit test, or actually used in an application.


Failure to Commit

Another really easy software development blooper to fall into relates to relational databases (or any other transaction-based product) and failure to commit when it is desired that another client can see the latest changes. This often manifests itself when a developer is using a database's tool for accessing the database directly (such as SQL*Plus for Oracle) and is also running an application against the same database. Before one realizes this common blooper is in progress, it can be disconcerting to see certain table values in the database tool but to not have those values present in the application using that database.

This situation is often very easy to fix; one simply commits the changes in the first tool and then the second tool or application can now "see" those changes. However, before running into this one the first time, it can be very disheartening to see this seeming discrepancy between views of the database.

In most cases, one should not turn on any autocommit features in an effort to avoid this issue. This is because, in most cases, one wants the ability to have a transaction span multiple statements. The preferable way of dealing with this, especially for people who are new to the potential problem, is to either commit the recent changes or provide a prompt instructing the person running the script to commit the changes if appropriate.


Static State

When one is used to dealing with instance-level objects and data, there can be some unexpected surprises when dealing with class-level (static) state. It is easy to fall into the trap of wondering why a class does not behave how it is supposed to behave from an instance-based point of view. The problem is that an instance-based point of view is not correct in these circumstances.

An example of this might occur when one runs a series of JUnit tests in the same test suite against different instantiations of the same class, but each test assumes that some portion of that class's static state is the same for each test. Because each preceding test in the suite may have changed the static state, the next test's assumption is erroneous and its results will almost certainly be invalid.


Common Characteristics of Software Development Bloopers

The examples of software development bloopers defined above help to draw out some conclusions regarding the nature of these bloopers. Software development bloopers tend to have these characteristics:

* Everyone's Doing It: Experience has certainly helped me to reduce both the frequency and the duration of software development bloopers such as those described above. Almost instinctively, even when talking to someone else about a problem they are having, I immediately consider one of the above situations where the symptoms merit that. However, even with experience, I cannot always control distractions and the temptation to try to do too much at once. This can lead me into bloopers like those identified above. Fortunately, I usually only lose a few seconds to a few minutes on these. However, that is a few minutes lost at a time in which minutes were already precious (hence doing too many things at once). This is much better than when I first started in my career. In those days, some of the bloopers described above could have cost me development time measured in hours rather than in minutes or seconds.

* Hindsight is 20/20: When we hear a specific example of a software development blooper as described above, it is easy to think, "How could a developer ever allow that to happen?" This illustrates the simple problems that are often at the root of software development bloopers. This is because software development bloopers are easier to identify and are more obvious the observer is not entrenched in the problem itself. A common reaction for a developer who resolves one of these software development bloopers is a mixture of relief (the time-consuming and perplexing problem is resolved) and of frustration at not identifying the "obvious problem" earlier. Hindsight is 20/20.

* Product of Distraction: Many of these software development bloopers occur because the developer is unusually busy; is unusually new to the language, domain, or environment; has too many things going on at once; or is otherwise distracted. The developer might not fall into this blooper the vast majority of time, but significant distraction increases the chances of running into one of these software development bloopers.

* Embarrassing: These software development bloopers can happen to anyone, especially to anyone new to a particular language or development environment. However, the developer cannot help but feel a little sheepish when the cause of lost productivity is discovered. It is nice if we can personally discover the issue and quietly move on, the lesson hopefully learned.

* Cost/Frequency Reduced with Experience: These software development bloopers can happen to anyone, even with significant experience. However, the more experienced developer is more likely to take steps to avoid these issues in the first place, is likely to identify the potential blooper condition much more quickly, and is more likely to resolve the blooper condition and move on than the less experienced developer. The good news here is that each of these bloopers usually only need be experienced once by the developer for the lesson to be learned. Generally, the more expensive the lesson (the more productivity lost), the more likely the developer is to remember it.

* Advantage of a Second Pair of Eyes: It is often true with these software development bloopers that a second pair of eyes is particularly useful in resolving them. The downside of this is that it opens the developer up to increased embarrassment cited above, but there are several advantages to having another person look at the issue. First, that person has fresh perspective and has not tried a bunch of different things or felt the desperation of grasping at straws. Second, I have found that the person dealing with the blooper actually identifies the problem himself or herself once he or she tries to explain what is happening to the second person. In the act of explaining, the person reasons through the problem and realizes why there is a disconnect.



Common Costs of Software Development Bloopers

There are multiple types of costs to software development bloopers. Fortunately, many of these are reduced on a per-developer basis with experience.

Time Lost Due to Application Not Working: This is the most obvious cost and has to do with the delay in finishing a feature because of the blooper.

Code Refactored for the Worse: This refers to the cost of adding logging and standard output to code or otherwise changing source code or build scripts or other development artifacts in an effort to discover the problem. There is a cost to adding these, a cost to removing them, and the cost associated potentially with junk (or even negative changes) leftover from the process.

Cost to Other Developers: While having a second person look at an issue is an effective method for identifying software development bloopers, it does come at the cost of that second person's time.


Advantages Associated with Software Development Bloops

Software development bloopers can actually produce long-term benefits despite short-term costs. These provide the silver lining for the clouds of software development bloopers.

Hard-earned Experience is Hard to Forget: Developers who have lost significant time to a particular software development blooper will rarely forget the lessons learned from the experience. That particular blooper and other related bloopers are less likely to happen in the future and should be less costly when they do happen.

Code Refactored for the Better: In the struggle to figure out why things aren't working as they should, the developer's dealing with a blooper can actually lead to positive changes to the code baseline. If, in a desperate attempt to identify and resolve a blooper, the developer improves the readability of the code, build scripts, and other artifacts, these changes can be left in place once the blooper is resolved for the overall benefit of the application.

Bloopers Can Teach Software Principles: I definitely learn best through hands-on experience. It is also true that I often learn at least as much from mistakes as I do from success. So, it is no surprise that one benefit of dealing with software development bloopers is that the developer can learn many things through hands-on experience dealing with the blooper. For example, a developer who lacks expertise with transactional databases might benefit from the concrete experience gained dealing with the failure to commit blooper described above. Similarly, the developer who is new to Java and is not clear on the difference between static and instance variables might learn this concept from the static state bloops discussed above than he or she could ever hope to learn just by reading.


Conclusion

Software development bloopers can be frustrating at the time, but hopefully are something we can look back on later and laugh at. While software development bloopers do cost us in several ways, we can turn these into valuable learning activities as well and possibly even improve our code and related artifacts in the process.

Saturday, November 22, 2008

VisualVM: jinfo and So Much More

The 16 November 2008 edition of the JavaTools Community Newsletter includes a Tools Tip regarding the jinfo command-line tool provided with Sun's JDK. The same tool tip also points out that jps can be used to identify the identifiers of the Java processes. The command-line tools such as jinfo are useful and it is nice to see quick tips like this one that remind us of their existence (or point out their existence).

The jinfo tool does have disadvantages for some situations. For example, it is not supported in Windows for J2SE 5 and only supports limited functionality in Java SE 6 on Windows. The Diagnostics Tools and Options section of the Troubleshooting Guide for Java SE 6 with HotSpot VM document also points out that jinfo is experimental (subject to change or not even be available in future versions of Sun's Java implementation). See jinfo's Detailed Tool Description for a very clear single-sentence description of the significantly broader jinfo support available in Linux and Solaris OS than the very limited Windows jinfo support.

A final disadvantage of jinfo is its command-line nature. While there are cases where this is advantageous, some people prefer a graphical interface. Finally, another disadvantage of jinfo and the other highly useful command-line tools provided with Sun's JDK is that they are separate tools. It would be nice to have all these tools in one place. That's where VisualVM comes in.

The functionality of jinfo along with several other similar command-line tools and JConsole is now available in the implementation of VisualVM included with the Sun JDK since Java SE 6 Update 7.

One of the nice features of jinfo is the ability to see what System properties are in play for a given Java application. The next three screen snapshots demonstrate how easy it is to see this information with VisualVM (started by running jvisualvm). After that, I'll show an even easier way to see System Properties and JVM Arguments with VisualVM.


Selecting Application and Heap Dump from VisualVM

The first image demonstrates that a Java application (in this case VisualVM itself) needs to be selected and then that application needs to be right-clicked on to select and see the Heap Dump tab (the second screen snapshot).




VisualVM Heap Dump Tab

This screen snapshot demonstrates the Heap Dump tab. There is a link to click on to see System Properties. The next screen snapshot demonstrates a piece of the tab when the System Properties has been selected.




System Properties Displayed in VisualVM




System Properties Via VisualVM Overview

It turns out that it is even easier to see the System Properties with VisualVM than with the Heap Dump process described above. As the next screen snapshot indicates, one can simply use the "Overview" tab after clicking on a particular Java process. The "System properties" sub-tab can be selected to see the system properties.




JVM Arguments

VisualVM also makes it easy to see JVM arguments. The same "Overview" tab in VisualVM just shown has sub-tab for "JVM arguments." When selected, the JVM arguments are shown as depicted in the next screen snapshot.



The previous screen snapshot demonstrates that VisualVM provides the JVM arguments via its "Overview" tab. This same information can also be seen in JConsole in its "VM Summary" tab.


Conclusion

The command-line tools provided with the Sun JDK are very useful. VisualVM offers many of the benefits of these tools with features of its own. In this particular example, VisualVM makes it really easy to access the same type of data that jinfo provides and in addition works well on Windows operating systems. In fact, all of the screen snapshots in this blog entry were taken from VisualVM running on Windows.

Friday, November 21, 2008

RMOUG Training Days 2009 Schedule/Registration Posted

RMOUG has posted the RMOUG Training Days 2009 schedule (subject to change) along with online registration.

My two presentations are both scheduled for the second full day (Thursday, February 12, 2009) of the conference when I begin and end that day with a presentation. My sessions are scheduled as follows:


REST from Web Services Frustrations
Thursday, February 12, 2009, 8:30 am - 9:30 am

Bringing Web to the Desktop with Adobe AIR
Thursday, February 12, 2009, 4 pm - 5 pm


As I look at the currently planned RMOUG Training Days 2009 schedule, several presentations stand out as particularly interesting to me. These include (in no particular order and with speakers' names in parentheses):

* Oracle JDeveloper 11g—New and Noteworthy (Lynn Munsinger)
* Ajax and DoJo for Dynamic Web Pages (Julie Johnson)
* Building Google Gadgets for Your Company (Peter Laird) [I believe that I attended this 30-minute presentation at Collaborate08]
* Implementing an AJAX Enabled UI with Little Effort (Kurt Kellner) [ADF]
* Web Services 101 (Chris Ostrowski)
* Introduction to Cloud Computing (Peter Laird)
* Drilling into JSF/ADF (Michael Fons)
* Unix Tips and Tricks for the Advanced Developers and DBAs (Sumit Sengupta)
* Changing the World with Oracle Web Services and the Service Oriented Architecture (Bradley Brown)

There seem to be more topics tied to products and technologies other than the database than I recall in any previous editions of this conference. There are many more interesting database and non-database topics included in the schedule.

I didn't see anything on Flex or OpenLaszlo, but I will be introducing Flex at least briefly in my AIR presentation, which I believe will focus more on AIR from a Flex approach than from a DHTML/JavaScript background.

Monday, November 17, 2008

More Effective Javadoc

Andrew Binstock's recent review of the book Clean Code: A Handbook of Agile Software Craftsmanship got me thinking about what I like and dislike about working with Javadoc. The specific comment that started me thinking about this was the observation that the both authors (primary author of the book and author of the blog review) feel that "Javadoc should not contain HTML." I am somewhat torn on this and often compromise with minimalistic HTML (such as <p> tags to separate paragraphs in package and class descriptions rather than allowing the text to be all munged together in HTML).

There is really a bigger issue at the heart of this: who is your Javadoc intended for? In this blog entry, I intend to discuss some of the things I have found that have made the Javadoc I generate or consume (others' documentation) to be more effective. The audience for the Javadoc is often the most significant consideration when considering what should go in the Javadoc comments.


The Case for Javadoc

I'll start by saying that I do think there are times when Javadoc is essential, times when it is helpful, and times when it is just about useless. Even worse, it can be harmful if allowed to become stale and overcome by events as the code changes. Useless Javadoc is often written as a result of mandated conventions or processes, but the other extreme is writing no Javadoc at all. I find myself writing very simplistic Javadoc comments for routine things such as get/set methods and no-argument constructors, but I do tend to write some Javadoc for all public methods and other publicly available Java constructs.

Documenting all publicly exposed APIs of a class is one of the items that Joshua Bloch calls out in Effective Java (Item 44 in the Second Edition and Item 28 in the First Edition). In addition, he points out the usefulness of documenting exceptions (Item 62 in Second Edition/Item 44 in the First Edition) and documenting thread safety (Item 70 in Second Edition/Item 52 in First Edition).

The most common argument against writing Javadoc is that clean code should speak for itself and that comments are only needed to act like deodrant when the code is smelly. There is certainly truth to this for comments in general, but I think some comments are appropriate some of the time and I have found Javadoc comments to be very helpful in my work.

The value of Javadoc comments certainly depends on the use of the code being documented and its audience. I rarely look at the source code of the JDK. Instead, I use its Javadoc-generated API documentation. Why do I use the Javadoc instead of looking directly at the source code? There are numerous reasons. I have it bookmarked in my favorite browser, so it is easy to access. My favorite IDE references Javadoc for me automatically as I use the IDE's code completion and other functions. Finally, I rarely need more detail than what is provided in the Javadoc for the standard Java libraries. Similarly, I find myself using the Javadoc for other open source products (Spring Framework, JFreeChart, etc.) far more than I actually look into their code. I usually only look at the code of these products if I need to explain an unexpected behavior, need to know exactly how something is being done rather than what is being done, or am curious about the implementation. This is even true of the non-Java frameworks I use. For instance, I heavily use the Javadoc-like Flex 3 Language Reference.

Other perspectives on the value of Javadoc are available in The Importance of Humble Javadoc, To Javadoc or Not Javadoc That is the Question..., and The Value of Javadoc.


Tips for More Effective Javadoc

With the case for useful Javadoc comments made above, it is time to look at a few detailed tips that I have found useful in writing effective Javadoc documentation. I realize that there are many more tips and useful practices related to Javadoc that I am not covering here. Feel free to add any you have found useful to the comments section.


You Don't Necessarily Need to Javadoc Everything!

There are situations where the boss, the client, the process, the code convention, or someone or something else requires you to write Javadoc comments for every thing in your code. These types of edicts are often what turn developers away from writing truly useful Javadoc. Often, the baby (good and useful Javadoc) is thrown out with the bath water (time-consuming and largely useless Javadoc).

I'm a strong believer that efficient Javadoc is often effective Javadoc. If one has documented data members and chosen to employ the -private option when generating Javadoc, then get/set methods for that particular data member likely do not need to be documented. For external purposes, Java developers may not want to expose the intentionally private, protected, or package level data members in the public API documentation. In this case, documenting the get/set methods can add value because this can be one of the easiest places to advertise to client code the valid values (range), units, and whether null is allowed or possible for that data member.

If I'm developing code for internal use only by other developers within the organization, I might favor documenting the data members and turning on private documentation generation. However, if my audience is an external one, it might be preferable to document the accessors and mutators. Adding Javadoc commenting to a no-arguments constructor may be superfluous at times, but it can also be useful when explaining why that constructor is not public and what constructor or builder should be used instead.

Some situations I find myself writing very little Javadoc for include JUnit tests and for the data members of nested builder classes as outlined in Item #2 of the Second Edition of Effective Java. In the latter case, the data members of the nested class essentially mimic the data members of the enclosing class, so rather than document those data members in both places, I prefer to reference the comments of the enclosing class's data members.

Sometimes, the code can speak for itself. Other times, there is no good way to communicate the intricacies or decisions made that led to something in the code without comments (especially Javadoc). Finally, it is worth noting that Javadoc becomes more important in situations where non-developers (test personnel, for example) might be using your Javadoc to better understand the application. I try to think about who will be using my Javadoc rather than just my own perspective when deciding if Javadoc for a particular element is useful or not.


The First Sentence Matters

Not all text within a particular Javadoc is created equal. The first sentence of the Javadoc for packages, classes, and methods is especially vital because that is what appears in summary information about those respective Java elements. Therefore, it makes sense the effort should be placed in making that first sentence as concise and useful as possible. Often for simpler cases, the most efficient Javadoc can be written with just a single sentence, satisfying both the previous recommendation regarding minimalistic Javadoc and satisfying this recommendation to make the first sentence matter.


Use -linksource for Source Code Accessibility

This is another tip that depends on the audience. Because the debate on whether to use Javadoc or code that speaks for itself (I try to do both as much as possible with emphasis on minimalistic but useful Javadoc), using the -linksource option can increase the value of the Javadoc-generated documentation for both sides of the debate.

The -linksource Javadoc option allows the class names in the Javadoc-generated documentation to link to a copy of the source code itself. By clicking on the class's name, the viewer is taken to that class's source code with line numbers. A good example of this is the JFreeChart API documentation. One can select any of the classes in that library (such as the highly significant JFreeChart class) and then click on the class name after "public class" to see the source code.

An important caveat here is that all source code is made available via the -linksource option regardless of whether -private is used or not. This caveat is a reminder about the importance of considering the audience of your Javadoc comments.


Document All Thrown Exceptions

It is useful to advertise to a method's potential clients what exceptions the method might knowingly throw. This is more obvious for checked exceptions due to the throws clause on the method definition, but that clause only indicates what type of checked exception will be thrown. The @throws Javadoc tag can be used to explicitly specify the checked exceptions that might be thrown and why they might be thrown. The @throws tag can also be used to document unchecked (or runtime) exceptions in the same way even those these are not documented in the method definition.


Document Parameter Details

The @param Javadoc tag allows one to specify what each parameter to a method represents. This is where significant information about the parameter can be specified such as allowed range, whether null is allowed or not, and any relevant units for that parameter (such as if the expected unit is seconds or minutes). Some of this can be specified by parameter name (such as secondsUntilOperationIsFinished), but it actually becomes less readable to include every detail about the parameter in the name (secondsUntilOperationIsFinishedCannotBeNullMustBeBetweenZeroAndSixtySeconds).

Much of this discussion also applies to the @return tag, where range, null or not null, and units considerations are often important.


Document Package and Class Usage

More recent Java packages and classes in the JDK seem to have better descriptions of how to apply those packages and classes. A good example of this at the class/interface level is the highly informative Javadoc documentation for the JAXB Marshaller and Unmarshaller interfaces. Each of these interfaces demonstrates how the respective interface can be used respectively to write out XML from bound Java objects and read XML into bound Java objects. The javax.management package description similarly provides an example of a highly informative description of how a package and its significant classes are used.

Many of the SDK descriptions provide links to non-Javadoc references on the subject and the Spring Framework does the same thing with links to its reference documentation from its API documentation. This is often accomplished with {@link}, available since JDK 1.2 with closely related {@linkplain} available since JDK 1.4. Overview and package-level documentation can provide a valuable pointer to where to start with the library or framework being documented.

It is not surprising that the JAXB interfaces and JMX package referenced above have such highly information Description sections because these are likely to be used by Java developers of many different skill levels. The audience here is Java developers of a wide variety of skill levels in terms of both breadth and depth and so it is helpful to provide relatively introductory information into how to use these interfaces, packages, and APIs. Such descriptive details may not be as important for a small team consuming their own code and its Javadoc documentation.


Use HTML Carefully in Javadoc

Javadoc allows HTML tags to be embedded in the Javadoc comments. While this is handy for nicely formatted and styled HTML presentation of the comments, it can be distracting for the person trying to read the comments directly in the code. Many of the IDEs mitigate this problem to a certain degree by doing their own representation of the tags rather than listing the tags directly. However, too many HTML tags can still be a burden for the reader and maintainer of those comments, especially when they are using a text editor or IDE that doesn't process the Javadoc tags in any special way. On the other hand, the nature of HTML is such that even basic things like white space beyond a single space noting be respected in the output can lead to ugly and hard-to-read HTML if no tags are used.

It definitely seems more like art than science to find the happy medium between too little HTML and too much HTML in Javadoc comments. If you know your audience is primarily developers reading the code directly, you might be best suited to writing little or no HTML in your Javadoc. If, however, you are delivering a framework or library or are in some other context where people without access to the source code or without a desire to read source code will be significant users of the HTML version of your Javadoc, the HTML tags might be more important. This is especially true if the goal is to reduce documentation to the code itself with little or no external design or implementation documentation. In that case, you almost certainly will have clients, managers, testers, or other stakeholders who prefer the HTML documentation over readable in-code Javadoc.

I have found that a few general principles have helped me to determine how much HTML to embed in Javadoc. However, I also need to point out that I still struggle with this now and then. Generally, in light of the value of efficient Javadoc, I tend not to use HTML in any Javadoc comments that can adequately describe the Java element in one paragraph or less. This is often the lion's share of my data members and methods and even applies to a large percentage of my classes. When I need more than one paragraph in a Javadoc comment, I don't want it all munged together on the web browser, so I use the <p> and </p> tags to separate paragraphs. These are minimalistic and, because they go on the very beginning and very end of each paragraph, have little impact on the readability of the text between them.

Some other preferences I have observed include preferring use of {@code} over <code> for specifying a code font. I also prefer {@code} or {@literal} for representing text that should not be parsed by the parser when generating the HTML representation of the Javadoc. For example, I think it is far clearer to read the Javadoc comment {@code Map<String,Object>} than it is to read <code>Map&lt;String,Object&gt;</code>. Both {@code} and {@literal} have been available in Javadoc since J2SE 5.

One final observation I've made regarding HTML in Javadoc is that it bothers me less to have HTML embedding in Javadoc when I am immersed in a task that is heavily web-oriented. My only explanation for this is that in such cases I am often working in HTML or related web languages anyway and so the HTML in the Javadoc comments is less distracting. In other words, I get better at quickly scanning and almost subconsciously skipping the HTML portions of the comments.


Consider Javadoc Extensions

In some situations, the reluctance to use Javadoc might stem from feeling like the Javadoc documentation is repetitive of the code itself or of other external documentation. As described above, this can be partially resolved by writing concise Javadoc comments that reference external documentation for much greater detail. Javadoc can also be extended as described in Documenting Java Member Functions to use custom tags that allow you to specify things such as concurrency concerns that are not easily included naturally in the code itself. Finally, there are many creative ideas out there for extending Javadoc's usefulness with third party tools. These include Javadoc tools (including IDEs) that make creation and maintenance of Javadoc comments easier, but they also include things like the ability to embed UML diagrams (see also UMLGraph) in the Javadoc-generated documentation.


Maintain the Javadoc Comments

One of the biggest arguments against comments of any kind is that they can (and often do) become obsolete quickly as the code changes. To help deal with this, the idea of minimalistic Javadoc is again appealing. Carefully chosen smaller amounts of Javadoc are less likely to contain something that becomes obsolete and will be easier to update when necessary. In addition, any developer changing a Java element described by a Javadoc comment should always verify the Javadoc comment as part of the maintenance process rather than assuming it is still okay. That being said, I'll freely admit that this is easier said than done and is often ignored in the heat of meeting deadlines, meeting tight schedules, and simply not wanting to deal with Javadoc because it is less fun than executable code.


Use Standard Javadoc Conventions

Javadoc can be more easily maintained and read when it is consistent and based on standards. The document How to Write Doc Comments for the Javadoc Tool is a good place to start. The articles I Have to Document THAT? and Documenting Java Member Functions also provide insight into what should be documented with Javadoc and how to best accomplish that.


Conclusion

Many of the recommended practices based on my observations depend on the audience. Whether to use HTML and how much HTML to use depends on who will use the Javadoc comments the most and in what contexts. Similarly, how and what is documented depends on the audience. However, even for developer-centric Javadoc where the HTML output is of little importance, Javadoc is still useful for documenting things like thread safety, exception handling expectations, ranges and valid values for parameters and return types, and other information related to the contract that cannot be easily expressed by the code itself. While many comments can be eliminated via highly readable code, well-chosen and well-written Javadoc comments tend to be among those that I prefer to complement the code with.


Feedback is Welcomed!

I would like to hear any suggestions of things you have found useful in making more efficient or effective use of Javadoc. It would also be interesting to hear of any tools you like to use in conjunction with Javadoc or hear about any alternative mechanisms you prefer for documenting your code.