Don't Use Implicit Return Types


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.

Comments:

Very nice Tor! Thanks for creating this plugin - it's going to be very useful indeed!

Posted by Jonathan Giles on June 30, 2010 at 06:08 AM PDT #

I don't understand why you need to type an extra colon to specify the return type, what you gain by not having a return keyword and why the heck you can do without the return type in the first place.

Idiotic.

It saves a few keystrokes, like THAT is the cost driving part in a project and not fixing the bugs that follow.

Posted by Matt on June 30, 2010 at 07:00 AM PDT #

Thanks Jonathan!

Hi Matt, I'm not sure what you mean by an "extra" colon; in JavaFX types are listed AFTER the identifier, just as it is in Scala and ActionScript. I think the primary reason for that is that it makes making optional typing easier.

Not having to specify types is often useful. For example, when it comes to overrides, it's nice to not have to repeat things; since there is an explicit "override" keyword, you just have to name the parameters, you don't have to restate their types. This makes actually changing the code more convenient, and in the case of access modifiers, you don't end up with subclasses accidentally widening the access.

The reason JavaFX allows as much type inference as possible is that its main/target market isn't API designers and large codebases, but actual -script- and GUI glue code, where you want to get the job done quickly and you aren't worried about anyone else calling into your code etc.

Not having a return keyword is something that I think grows on you after using it for a while. We always offset the last line with a whitespace to help readability. This is how Ruby has worked for years and I think people like it there as well. Certainly JavaFX allows you to use the return keyword if you want, so your coding conventions could require it, but in practice I don't think it's a problem - except for in combination with implicit returns. But this isn't the only problem which triggers implicit return problems - in my second example, if you had "return foo()" you might not be returning what you think you are. So for any -public- APIs I think you should specify the type, and arguably the compiler could enforce it. But until it does, having the IDE point out these issues help.

Posted by Tor Norbye on June 30, 2010 at 07:12 AM PDT #

"in JavaFX types are listed AFTER the identifier, just as it is in Scala and ActionScript"

Yeah, Scala and ActionScript are successful languages. Where are they on Tiobe index now again? That's right, < 1% usage. Together.

"you just have to name the parameters, you don't have to restate their types"

Yeah, you save a few ms on key strokes, you lose the readability.

"Not having a return keyword is something that I think grows on you after using it for a while."

Yeah, those six keystrokes really made our projects fail ROI. You even have to make a quick fix to fix the problems related to it.

"We always offset the last line with a whitespace to help readability."

Ok, now we're down to saving five keystrokes.

Sorry for the snarky tone. But JavaFX is designed by language geeks for language geeks that seem to think that a saved keystroke is somehow translated to saved time and that all are language geeks. Just look at Scala, it will never grow above 3% usage (from current 0.253%).

Scala is Linux. Geeky, cool, but not mainstream and will never be anything important. JavaFX is Ubuntu, thinking it's all that. But still it only have < 1% market, just as Ubuntu.

Use what works. Fix Java instead. Fix Swing instead of inventing a new GUI layer with other problems. Do it.

Posted by Matt on June 30, 2010 at 08:29 AM PDT #

A Editor plugin to correct a mistake in the language :)

Thank you, We surely need this plugin, more than that I learned about the potential problem.

Posted by Kishore on June 30, 2010 at 04:10 PM PDT #

"A Editor plugin to correct a mistake in the language :)"

Just as JavaFX needs a EDI plugin to correct the "we'll handle null for you" mistake.

Don't get me wrong here, I think JavaFX is a great language and platform and I really hope it will catch on. But I always get those itchy red bumps on my back when too much automagical stuff happens. And these two topics make my back all rocky mountains like.

Posted by Tbee on June 30, 2010 at 04:45 PM PDT #

Hello dear Norbye's Weblog,

Please tell me about these codes that are concerning at node point project, and how can I to make any help to you into JavaFX, tell me in details .Thanks

Posted by Alfonso Franco on July 01, 2010 at 02:01 AM PDT #

my e-mail is developfranco@yahoo.com.Thanks

Posted by Alfonso Franco on July 01, 2010 at 02:06 AM PDT #

Matt, JavaFX is -not- designed to save you keystrokes! The productivity gains does not come from typing. The automatic null checking (the compiler compiles in a null check and then performs short circuit evaluation for variables where it doesn't know for sure that the value is not null) isn't just there to save you typing - yes, it makes the code more readable, but more importantly it means your GUIs don't run into NPEs.

Regarding "fix Swing instead of inventing a new GUI layer" - what exactly is it you want fixed in Swing? Personally, having worked with a real scenegraph for a while now I really don't want to go back to a component-based architecture with immediate paint mode; having arbitrary geometry and effects and having this be able to be mapped to an OpenGL and to a Direct3D graph is just better.

Posted by Tor Norbye on July 01, 2010 at 02:11 AM PDT #

Tor,

Sure, null handling can be nice, but that´s another thing and could be added to Java with an elvis operator. Removing the return keyword and the need for explicit return types was the issue here.

Swing is a scengraph as well actually. Java2D is not though. JavaFX scenegraph tries to be both a GUI scenegraphs and a primitive scenegraph. That´s not going to be good however you do it. The use cases are too not alike.

Swing can´t be fixed in place of course, but it could improve (now it´s all but abandoned). But with modules a new Swing module which used a scenegraph (for primities) could´ve been made instead. That would´ve gotten more users in a day than JavaFX will get in a year.

Posted by Matt on July 01, 2010 at 02:36 AM PDT #

Tor,
This is really good advice. I personally have adopted the practice of using explicit types for variables as well. I find that there are cases when you want to change code and get some really confusing error messages due to implicit typing.

One thing that surprises me though is the following case:

var t = Timeline{
keyFrames: KeyFrame{
action: function(){
t.stop();//compile error here
}

}
}

You get this error:
This is the cyclic reference to t that prevents type inference

which makes sense I guess from a compiler perspective, but it seems to me that:

var t = Timeline{}

could count as an explicit definition, since it is a new variable and has to be at least of type Timeline.

anyway, my two cents.
-Lucas

Posted by Lucas Jordan on July 01, 2010 at 03:37 AM PDT #

If anything software must behave predictably, which means no behavior that can change on its own. If something is supposed to contain an integer, I want to make sure it contains exactly that and not all of a sudden changes to something different without me defining so.

Type inference is a somewhat gray area. It is ok in order to prevent duplicate code, like in Java's generics. The main point is that with generics the type is specifically mentioned somewhere, as with the return in JFX the type it is derived.

So IMHO inference is ok as long as at the end of the inference the type is explicitly coded.

Posted by Tbee on July 01, 2010 at 04:02 AM PDT #

Hi Tor,

Thanks for your clarifications on this post.
I'm with Tbee here, "software must behave predictably".
These should never be sacrificed with the removal of important information that the coder needs to specify in the language. If implicit return types can be such a problem then remove them altogether. Give compile errors whenever the return type is not explicit. You may lose a bit readability but having the program behave the way you intend far outweighs the disadvantages. Just think of the time this kind of bugs may make you loose.

And also related to this kind of issues, I don't understand why javafx doesn't throw NPEs. I've lost literally days of debugging trying to fix problems caused by null relaxing of JavaFX. And all of my problems with these could never be identified by tools on the IDE.

I really like javafx, and I think it is very promising platform, but please hear the developers opinions and don't be afraid to break up with the past.

Thanks, keep up the good work. Looking forward to the authoring tool.

Posted by Pedro Duque Vieira on July 02, 2010 at 08:52 PM PDT #

Despite all the pros and cons, the more I read about "modern" paradigms in new languages, the more I tend to accept some boilerplate in Java.

This post shows very well, how many additional potential bugs could be introducud by less experienced developers. And even if everybody around learned and experienced enough there are always coming new younger less experienced developers. What you get is 80 % of code written by less experienced developers. The language must lead to writing good and stable code. I think, Java is still the best.

Matt wrote on June 30, 2010 at 03:29 PM PDT:
| Use what works. Fix Java instead.
| Fix Swing instead of inventing a new
| GUI layer with other problems. Do it.

I tend to fully agree although I find Java not so broken to be generally "fixed". I am currently developing a new Swing application - Swing is more powerful than everything I used prior my move to Java. However, the initial work is maybe a little more than elsewhere (e.g. implementing a useful table model that fits 90 % of the use cases).

Tbee wrote on July 01, 2010 at 11:02 AM PDT:
| If anything software must behave predictably,
| which means no behavior that can change on its
| own. If something is supposed to contain an
| integer, I want to make sure it contains
| exactly that and not all of a sudden changes
| to something different without me defining so.

Fully agree.

I think the language that will replace Java in the long term is not yet invented.

Posted by Martin Wildam on July 04, 2010 at 06:48 PM PDT #

Does that mean that Java FX is not a type safe language? in that case why it is not?

Posted by Java on August 19, 2010 at 08:40 PM PDT #

Post a Comment:
Comments are closed for this entry.
About

Tor Norbye

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today