After I showed a colleague a trick in my IDE he told me to write a blog post about it. I told him to write it himself. This all happened almost a year ago. The problem with this post is that it's about something that is a bit embarrassing. I'm losing my appetite for talking about it, but yet, I come across more setups that are wrong than setups that are right. This post is mostly about some settings in Eclipse (and also in IntelliJ IDEA) that are pretty moronic and that you should change asap to prevent bugs in your code. Otherwise you might be seen with an open fly and you wouldn't want that would you?
First a word on keyboard shortcuts
First of all: learn to use your tool! Here's a list of things that I see people wasting effort on:
- click through the menu (unless you're trying to find what the keyboard shortcut is you're looking for)
- declare a variable or field (use extract variable instead)
- type the skeleton of a method (your IDE can do that much faster using a quick fix)
- create a new type other than a test case yourself (generate everything from a test case, it's faster, trust me on this one)
There are many more variations on the same theme, the last point is arguable, some people are really fast if they start to hash out the model before beginning a test. My point is that it pays off to find the shortest path to a certain solution and figure out what shortcuts get you along that path fastest. The best way to train yourself to use the keyboard is to stick to the first point. There is even an eclipse plugin that can enforce keyboard usage (but that's a little too harsh for my taste). There are many blogs describing the keyboard shortcuts in great detail as well.
Templates
When you stop using your advanced typing skills and let the IDE do the typing for you, you will have moved on to using templates. In eclipse, if you look for templates under preferences (just type templates in the filter).
You will find quite a few templates that are useful, some that you'll never use and the best news is that you can create your own too. I can recommend renaming the JUnit4 template to tst (instead of the default Test in eclipse) and tweaking it a bit to your coding standards, but that's not why we're here now.
Not all these templates are sensible, and that is what I want to to fix.
New method body
A new method you can create by just trying to use the method and then asking Eclipse to create the missing method for you.
You'll end up with a method like this:
1 2 3 4 5 6 7 8 | public class Reverser { public void reverse(String string) { // TODO Auto-generated method stub } } |
Which is pretty bad because it will allow your code to run without complaining and leave a crappy piece of comment in there. It's not the end of the world though, and you'll notice later right? You probably won't, but you don't have to, more on that in a minute. First let's make the method return a String.
Stop, don't start modifying the method, just delete it. Eclipse will generate it correctly for you later.
Modify the test a bit so you need a String return value and try the quick fix again.
Now Eclipse gives you this:
1 2 3 4 5 6 7 8 | public class Reverser { public String reverse(String string) { // TODO Auto-generated method stub return null; } } |
This is not only pretty bad, its retarded. Just run the test case and see for yourself. The only plausible result of this will be a NPE, and the NPE will happen in another class so you have to retrace your steps to find out where you need to fix it. I want my test case to throw me a stack that starts exactly where I need to continue developing. Even worse, if you're generating methods that are not invoked directly from a test case, this might lead to NPE's flying around in production. This will not do.
So what can we do? Well, it's simple: just modify the template responsible. This template is called 'Method body' and should edit it to look something like this.
Now if you delete the generated method again and regenerate it, it should look better.
1 2 3 4 5 6 7 8 | public class Reverser { public String reverse(String string) { throw new UnsupportedOperationException( "Iwein left this implementation as an exercise to the reader"); } } |
If we run the test case now it will fail. But the big improvement is that it will fail correctly. What I mean by failing correctly is that the failure actually points out what is wrong: you have failed to implement a generated method. This is infinitely more informative than an NPE. As a bonus you can click the stack trace in the test and actually go to the method that you need to implement.
Just double click the line that is selected in the above screenshot. Pretty cool huh?
Catch blocks
There is one more template I want you to modify. Check out the 'Catch block body' template. This is the template that gets used when you use the 'Surround with try/catch' quick fix.
The resulting code looks like this:
1 2 3 4 | } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } |
I can tell you that there is plenty of code like that running in production systems. Granted, checked exceptions are hard to deal with, but surely we can do better than this.
This isn't going to make your program run any better, but it sure is going to make it fail better. And that, dear reader is what this post is all about. If things fail early with an informative message, you (and those that come after you) are going to spend less time in a debugger and more time fixing actual problems.
I've used Eclipse for the screenshots, but I can assure you that on my IDEA setup I have done the same fixes, and it wasn't very hard to figure out either. So now that you've read this there is no excuse to carelessly return null or print a stack trace anymore, even if you're not using Eclipse.
Don't be caught with an open fly again!
No comments:
Post a Comment