Friday, February 24, 2006

Code Advice #9: Avoid null - use objects

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.


(See intro for a background and caveats on these coding advice blog entries.)



When a method is supposed to return an object, and it returns "null",
the null is used to convey a number of meanings:


  • Empty (when it's supposed to return an array or a list, but the list is empty)

  • Can't (when some error happens and an object to be constructed failed; the caller
    is now supposed to gracefully handle the error)

  • Unknown (when a method is supposed to compute some result that it couldn't figure out)


...and probably many more.



Whenever possible, avoid using nulls. There are several better alternatives.





  1. When a method needs to return an array, and you know the array is empty,
    don't be lazy and just return null. Perhaps you're not being lazy, but believe
    you're being efficient, because by returning null you can communicate empty
    to the caller without having to construct an object (the empty array or list).
    However, the performance impact is minimal. It's very cheap to construct
    short-lived objects in Java - much less than malloc cost in C.
    However, you can use the following pattern if this is going to be frequent:

    class Window {
    private static final Window[] NO_WINDOWS = new Window[0];

    public getActiveWindows() {
    if (whatever) {
    return null;
    return NO_WINDOWS;
    }
    ...
    }
    ...

    An approach like this has the advantage that you can start simplifying your
    own code, since you won't be doing null checks everywhere. If you call the
    getActiveWindows() method above, you can simply iterate over
    the results directly rather than branching on null first.






  2. When the "null" return value means something like "unknown", it's even
    better to use a special marker object. This has a number of advantages.


    • The intent is more clearly communicated, so the code is easier to read.





    • The marker object can customize some of its methods such that it reacts
      appropriately. This allows you to move some handling code into the object
      itself rather than in the client code. (As a simple example, your
      toString method can be written to be more informative.)





    • The class containing the marker object can also be written to consider
      marker objects in a correct way; for example, the right equals()
      semantics can be written.





    The above is a bit abstract so let me illustrate with another example. Let's
    say we're writing a word processor. We have a Document class, representing a document,
    and a Caret class, representing a visual caret (text insertion cursor). The caret
    has an associated position in the document, and this is represented by a Position object.
    Thus, the caret has the following method:

    public Position getPosition();

    Sometimes a document doesn't have an associated caret position - for
    example, when the document does not have focus. We could simply have
    getPosition() return null for this. But that would mean that client
    code relying on positions would always need to check for null before calling methods
    on the position they receive. Instead, the Position class should have a static
    field representing a non-existent position:

    class Position {
    public static final Position NONE = new Position(xxx);
    ...

    Now, most client code can simply call Position methods without worrying whether
    it will be null or not. The Position class itself can be modified such that
    various methods handle the NONE case correctly: not only can
    toString() do something like this:

    public String toString() {
    if (this == NONE) {
    return "Position.NONE";
    } else {
    ...

    but for example position comparison methods can have special considerations for how
    to handle positions where one or more represent the nonexistent position.
    Yes, this could be achieved by consistent use of null instead, but it's a lot
    less readable, and harder to search.




Null handling has gotten some renewed attention recently. With the advent of
annotations, you can annotate whether a method is expected to return null or not
(e.g. with @notnull).
This allows tools to perform static analysis of your code and find potential
bugs. For example, if you indicate that a method cannot return null, the tool
can obviously flag any "return null" statements within that method (or returning
expressions calling methods that may return null). But they
can also flag code calling this method that unnecessarily check the return value
for null, and more importantly, flag missing return value checks in code calling
methods that may return null.



IntelliJ has added

this feature

already. Looks like it has
been
around
for at least 10 years with lint checkers in C. I look forward to getting this
in my favorite IDE
(why oh why isn't @notnull and @nullable part of the
standard annotations set?)
- but in any case, try to avoid nulls by using
place holder objects where appropriate.


Saturday, February 11, 2006

Make Your Comments Count!

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.


IDEs tend to de-emphasize comments. Visually, code is more prominent than comments. For example, while most IDEs use black for "code", in
NetBeans comments are light gray; in IntelliJ they are also light gray, in Eclipse they are light green and in Visual Studio they are also light green. In all cases, the comments have less visual weight than the surrounding code.



I have a new co-worker, and when I went over to his computer the other day I was shocked to see his modified syntax highlighting color scheme. He had basically turned everything to black - except comments. And the comments - bright red! His rationale is that comments are vital, and he wants them to jump out visually.



I decided I'd try out his scheme. Switching all comments over to red was too much - I like javadoc for methods to stay "quiet". So I settled on switching line comments over, and leave block comments alone (and these are always javadoc, because I use line comments in all other cases, even for comments that span multiple lines.)



I've tried it out for several days now and I think I might stick with it. Judge for yourself - if not by screenshot then in your own IDE.








(Click image for full size)


Tuesday, February 7, 2006

Web Page Image Blending

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.


I recently saw a Creator application somebody had made. It used a lot of background images, with text right on top of the backgrounds.
It looked nice, but it was hard to read the text. I suggested the user insert translucent masks between the text and the background. Then I realized that might make a good blog entry, since there are lots of little tricks to know about. So here goes.



Let's say you have a page which looks a little like this (click for full size):




screenshot - click to see full size



Notice how there is a text component at the bottom, for "Previous" and "Next" links. It's blending a bit with the background and is hard to read. What we want is to place a semi translucent rectangle behind this text, such that the background is still visible, but at the same time increasing the contrast between the white text and the photograph. Let's do that, by inserting a Graphic Image component that is simply a translucent gray block:




screenshot - click to see full size



Much better, right? (Yes, I inserted two more blocks showing 30% transluceny and 50% translucency, for comparison).



Doing this is pretty easy. The first thing you'll need is a translucent image. Here's a couple:










50% translucency30% translucency

Just right click on one and choose save as. Don't forget that you can drag it right to the designer. If you don't want to use one of these images, you can generate your own translucent image. It has to be in the PNG format, since GIF does not support translucency, only 100% transparency (e.g. opacity is either 0 or 1, not anything in between). You can use the http://apps.everamber.com/alpha/ web site to generate a suitable image, choosing your own color, size and transparency values.



Next, you'll need to ensure that the translucent image is the right size. It should be positioned right behind the text, and be slightly larger (e.g. such that it's a "bounding box"). These tips might help you:


  • You probably want to temporarily disable the snap to grid feature when dragging, such that you can place the rectangle top left corner precisely outside of the text top left corner. To do that, hold the Shift key while dragging and until you've released the mouse button. With the shift key pressed all dragging is per-pixel rather than per-grid-cell.

  • When you resize the image, don't drag the corner handles! Corner handles will ensure that all image aspect ratios are preserved. However, in this case we simply want to tile/stretch the translucent image to our exact right size. Therefore you should use the resize handles in the middle of the horizontal or vertical edges, not the corner edges.





Next, you'll need to ensure that the translucent image is behind the text. You can do that by setting the z order CSS property on the image and on the text component. But a much easier way to do it is to simply ensure that the image component appears earlier in the markup than the text. Do that by simply looking in the application outline, and dragging the image component up such that it preceeds the text component. When you do that you should immediately see the translucent image dimming the background image, but not your text.



Finally, for completeness, perhaps I should mention how you use background images in your pages. First, add the desired image to your web app (remember you can drag it on the designer - if you do, just delete the resulting graphic image component, and the image file itself will still be in your resources folder). Then open your stylesheet.css and add this rule:


body {
background-image: url(wallpaper1.png);
}



This should look fine in the browser too - here's how Safari renders it:




screenshot - click to see full size



Note however that you may not be as lucky with Internet Explorer! IE7 is reported to have great support for transparent PNGs. But earlier versions of IE were notoriously bad. There are however workarounds, and I -believe- our image component implements this workaround, by detecting when it's talking to IE and emitting various gross CSS (such as "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=...."). It would be nice to get confirmation from somebody whether this works since I don't have IE on this operating system. But I'm pretty sure it does, and this is why you want to use components - somebody else has debugged the various necessary browser workarounds, and browser specific markup is generated based on which client the server is talking to!


Thursday, February 2, 2006

Tools Strategy Revealed!

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.


I didn't know this stuff was public information. But I guess it is now... Bob Brewin was interviewed by Gregg Sporar with a series of specific questions about our strategy. Check it out!



For example, we will be open sourcing the Creator technology! (Q18) And, you'll get the Creator and Enterprise functionality as IDE plugins so you don't need to run multiple IDEs! (Q7, Q8) Bob also explains why we don't just roll over and yield the field to Eclipse (Q21).



Exciting times ahead!


Wednesday, February 1, 2006

New Creator Bloggers

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.


I
used
to
mention new bloggers on the Creator team when they started up - but I've missed a whole bunch of recent(?) additions.
Even my boss is blogging! Many of the Creator blogs are listed here. Take a look at Tutorial Divas for example for a wealth of Creator tips and howtos.



I was just talking to some customers yesterday about AJAX, and they were wondering about the performance impact of adding AJAX to your JSF application. Well, now it should be easy to measure it. In Marco's blog he shows how to use the profiler to profile your deployed application.



Finally, note that nearly all these blogs are on blogs.sun.com. In a recent bile blog Sun is criticized for too much cheerleading on java.net. From reading the blog entry it sounds like that guy should spend a little less time porn surfing and a little more time trying out our software :) Seriously though, I post regularly about Creator and NetBeans because I like these tools, because I think the message of Sun's tools resurgence hasn't really gotten out there, and because people who read my blog generally appreciate tips and tricks for these tools. Particularly on blogs.sun.com you'll see lots of talk about Sun products. That shouldn't be a surprise - we "fly our own airplanes" here - we use our own software, and therefore we end up talking about it. Others are welcome to do the same with their own blogs. Just stop reading blogs where you find the signal-to-noise ratio too low. I don't see a problem here.