Tuesday, June 29, 2010

Don't Use Implicit Return Types

WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.


JavaFX, like Scala, is a fully statically typed language. However, unlike Java, it allows you to omit type declarations in many places, since it can infer it. Coupled with the fact that you can use expressions as statements, and that the last expression in a function will be the return value, this lets you write really simple and clear code.


def s = "Hello";
def len = s.length();
function product(a: Number, b: Number) {
a * b
}


The function above shows an "Implicit Return Type": The compiler figures out the return type, which in this case will be a Number, and that is the signature computed for the function.

Unfortunately, this can sometimes lead to trouble! Here's a real-world example:

public function clearSelection() {
selected = null;
}


This function clears the selection in a node. The intention of the developer was probably for this function to have a "void" return type. But that is not the return type! The last statement is an expression, an assignment, which has the type of the left hand side, which is actually a node.
So the return type here is a Node! And it could easily have leaked an implementation class too.

This may not seem like a big deal here, but what if a subclass wanted to override this function? It would try this:


override function clearSelection() {
super.clearSelection();
moreStuff();
}


And this would fail compilation, with a surprising error message:

File.fx:1: incompatible types
found : void
required: Node
override function clearSelection() {
1 error


That's right, your subclasses will now need to deal with this return type too! If it's an implementation class, they're in trouble!

There are other reasons implicit return types are bad too. Here's a function specifying a desired padding for a node:


public function padding() {
5
}


The user may have intended for this to be a Number, but since the default is "5" instead of "5.0", the implied type here is Integer, which means that subclasses will need to round their desired padding to an integer. And this is not always a good thing - see the pixel considerations article.



For all of the above reasons, our Coding Conventions Document states that you should not use implicit types, at least not for any non-private API. That includes package, protected and public functions. However, it's a simple mistake to make. We've all made it! For that reason, to help track these down, I've created a quickfix for NetBeans which identifies and fixes these problems. Here's what happens if you look at a function like the one described above:



The light bulb and underline warns you that there is a problem here. Clicking on the light bulb, or pressing Alt+Enter when the caret is on that line, shows this info:



It's telling you that you have an implicit return for a public function, and it's offering to insert the actual, current return type of the function. It's also offering to make the function Void.

Pressing return will fix the function:



There are certain return types you cannot express in JavaFX script - such as returns including generics signatures. The quickfix won't warn about those since there is nothing you can do.




You can find the module on the Plugin Center here. Hopefully it will be as useful to you as it has been to me!

P.S. We discussed this topic (implicit return types in JavaFX and Scala) for a while on the latest
Java Posse Podcast episode.


Thursday, June 17, 2010

NetBeans 6.9 Released

WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.



NetBeans 6.9 has been released.

There are important improvements for everyone here - whether you're a Java developer, JavaFX developer, Ruby developer, PHP developer, C++ developer, ... or all of the above :-)

Since I spend most of my time writing JavaFX and Java code, by far the biggest improvement in NetBeans 6.9 for me is the JavaFX support. While there is still room for improvement, editing works pretty well now. In particular, the source code formatter works well on most source files and constructs, so I've used it to reformat some of our large and complicated source files, though to be on the safe side I've checked the diffs carefully before checking in (and turned on whitespace diffing in the version control). I occasionally have to make manual tweaks, but it's really helpful in cleaning up poorly formatted source files. And Go To Declaration now works reliably! The debugger still needs work. Apparently this needs some help from the compiler so hopefully the combination of JavaFX 1.3.1 and NetBeans 6.9.1 will address that.

One huge improvement in 6.9 is the reduction of scanning delays. In addition to performance fixes in that area, there are two life saver features:


  1. Running is no longer blocked when a scan is in progress. Even if it's scanning, running starts immediately. This used to drive me crazy!
  2. I can turn off some of the extra aggressive scanning! There is an option for this now, so I can turn off automatic timestamp checking and instead perform scanning manually if I should need it:



    (In case it's not obvious -- I'm talking about the checkbox at the bottom of the above dialog.)

    If you turn off automatic scanning, you can invoke it explicitly:





There are many other new features, and I'll get back to some of them in some other posts, but for now I'll leave you with a link:
Git Plugin compatible with NetBeans 6.9.