Thursday, September 29, 2005

Mixing JSF and HTML

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.


A subject that comes up regularly is how to mix HTML with JSF. There are several gotchas and limitations you need to be aware of.


  1. The "content inter-weaving problem". The issue here is that if you mix and match JSF components and normal "plaintext", these are processed separately, and it's possible for the text to appear out-of-sync with the component. See this article for more information. However, the good news is that this issue is fixed in JSF 1.2! (Creator however is still using JSF 1.1; JSF 1.2 is not out yet.) You need to be aware of this issue, and obviously test your application thoroughly. The problem does not show up
    at designtime in Creator because we don't process the page using the normal JSP engine.

    • You can use a <f:verbatim> tag around your markup to make it "JSF friendly". This will force the embedded text to be processed by JSF rather than the JSP handler, so the right thing will happen.

    • In Creator 2 you can also use the <ui:markup> component. It's easier to use than <f:verbatim> for some use cases. It's in the Advanced palette.




  2. Components that render their own children frequently don't handle HTML child content. (Examples of these are the Data Table, and the Panel Grid components.) These are the UIComponents that return true from getRendersChildren.
    These components specifically state that they want to handle rendering of their children themselves, and unless they
    are really careful, they won't pick up the HTML markup children nodes (whereas the standard child iteration used for
    most components does get this right.)
    Thus, for these components you need to resort to the <f:verbatim> technique again.




  3. By now you may wonder why you wouldn't ALWAYS just put <f:verbatim> around your HTML tags - and all your problems would be solved. The problem is that what verbatim does what its name suggests - it renders its child content verbatim. That means you don't get to put other JSF components inside of it! You'll see your JSF tags emitted as text. In other words, you can't freely insert <div> tags around your JSF content to do normal HTML page layouts.




  4. Your HTML needs to be well formed XHTML. This isn't necessarily a JSF requirement, although it should be noted JSF emits XHTML, not HTML. However, Creator requires this. Specifically this means that you need to remember to close your tags - I've often seen people write <br> which is invalid XHTML. It needs to be <br/>. As another example, remember that your tags need to be lowercase - don't insert <STYLE>color:blue</STYLE>.




  5. The way you actually add HTML to your web pages is to switch to the JSP view and edit away.
    However, note that you don't get to write plain HTML there, because you're actually editing an XML-formatted JSP
    file. Tags work the same way as in HTML - you can for example add <hr> to add a horizontal ruler.
    But entities are different. They need to be "XML escaped". If you want to write the HTML entity for the Spanish n for example,
    ñ, you cannot simply write &ntilde;. You have to replace the & with &amp;. Thus, if you want the page to render in the browser as Piña Colada, in HTML you would have had to type, Pi&ntilde;na Colada, but in the JSP file you need to escape the & such that you end up with Pi&amp;ntilde;a Colada.




With all those potential problems, you may wonder why you should bother with HTML at all?
It would be ideal if you didn't have to.
However, if you restrict yourself to standard JSF components there is simply too much markup you cannot get to. For example, you cannot add a horizontal ruler since there's no component for that. In Creator 2 we have a new component library which adds a wide array of new components.






However, there are two remaining areas where you might find yourself resorting to HTML.


  • Flexible layouts. If you want to achieve a really advanced layout that offers good resize behavior etc. you may need to resort to old-school HTML tables with rowspans and colspans. However, I urge you to consider using CSS for your layouts instead. It may be a bit harder at first, but it will pay off. True, CSS is not supported well in older browsers, but many of these older browsers aren't supported for similar reasons in the existing markup rendered for many components already.



  • Pre-existing content. You may have existing HTML that you want to reuse directly - perhaps it was crafted by a web designer and you want the same look in your JSF app with no rewrite effort. You can import these into Creator using File | Add Existing Item. The screenshot on the right for example shows the java.net page imported into Creator. The import mechanism will not catch all the gotchas above however so you need to Test, Test, Test.




As should be evident from the gotchas list however, you need to consider this carefully.


Java Posse Episode #1, I mean #2

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.


A new
episode
of the Java Posse podcast is available. Episode #1 was an interview recorded a while back by Dick, so this episode is actually our first joint recording. It was a fun start.



Let me apologize in advance for using the phrase "you know" way too much. It's, you know, totally subconscious. Next time I'll try to slow down and reduce the you-knows. And Carl is getting a new microphone :-)



iTunes link


Wednesday, September 28, 2005

NetBeans 5.0 Beta

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 5.0 Beta is now
out. In my
blog entry
yesterday I wrote how easy the new plugin support made it to add
my own favorite debugging function to the debugger.
There's a long list of big improvements over 4.1. Click on the image to go to the "What's New"
page and see descriptions with screenshots of the new goodies!






Tuesday, September 27, 2005

Suggestion #5: Debugging with Undo

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.






Until now in this "column"
I've written about source code itself:
Don't use vanity tokens,
don't capitalize acronyms,
don't use tabs, and
don't (over)use logging.
Today I'd like to talk process instead: debugging.



The process of debugging usually involves mental verification:
you step through the code, and compare what you think
should be happening with what is actually happening.
As you do this, you frequently have to decide if you should
Step Into or Step Over method calls.
On the one hand, you don't want to step over a method in case
the bug is occurring within the method call. On the other hand,
if you don't know where the bug is yet, you can waste a lot of
time stepping through methods before the bug is triggered.



With the following technique however you get the best of both
worlds. The approach is as follows:
Always step over. If you detect
that the bug has happened (e.g. some return value from a method
is wrong, or a class field is changed into the bad value you're
looking for, etc. etc.) then simply Retry the method.
By retry, I mean pop the current stack frame and step back
into the method! This gives you a primitive "Undo" function.
Without restarting your program, you get to step through the method
again.



Many debuggers offer actions to pop the stack, so you can use this
technique today. What I really want however is a convenient action
which does both of these operations (pop followed by step into), and have
it located in a convenient place such as the debugging toolbar.



So I decided to try out the new NetBeans 5.0 module plugin
development support. Holy cow! - It was unbelievably easy!
In 25 minutes, I wrote a plugin (which adds a debugger toolbar action
which pops the stack and steps into in one step), I generated a plugin
bundle, installed it in the IDE and tested that it works on a simple
test program. And this was as
a first time user of the plugin support! I especially liked the "New | Action" wizard
which automatically handled everything from icon and displayname to positioning
the action in the menus and toolbars.



I'm not exaggerating - it
took just 25 minutes. And I'm not bragging either; doing all this in 25
minutes says something about the productivity of the tool, not about my programming
skills.
There's a quick-start
document
available with more information on how to build plugins in 5.0. But I
wrote the plugin while on the train commuting to work, and without a network connection
I figured it out anyway on my own.






You can download and install
the plugin yourself in
NetBeans 5.0.
As you can see, the main source file is
very trivial.



The screenshot on the right (click for full size) shows the IDE in action; notice the new action in the toolbar
(easily spottable by the ugly icon I supplied) as well as the plugin project in the navigator.



Anyway, you can use this retry technique as long as your IDE supports
Pop Topmost Stackframe. It sometimes requires a little work on your
part. If you're stepping through a method that has side effects
(such as initializing fields), you may have to account for
these. By "account for" I mean undo the side effect. Usually I handle it
by clearing out the fields in the watch window after popping the stack.
You did realize you can change values in the Value column and cause
assignment in the debugged process, right?






Monday, September 26, 2005

iTunes link is up

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.





The iTunes directory has been updated to include the Java Posse
podcast now. If you search for "Java" in the music store it's also the first match!



Click on the image on the left to subscribe. If you've already subscribed manually consider resubscribing
so you're counted in the iTunes statistics.






Thursday, September 22, 2005

Java Posse - the JavaCast reincarnated

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.





The Improved JavaCast is here: Java Posse. A wild band of Java mercenaries riding through the frontier of .... ah never mind. You get the idea: A group of people talking about Java.
The charter is the same: weekly programs covering the Java world. But the format will change. Less ranting. Shorter programs. Separate interviews. And the show will evolve based on feedback.



The set of anchors has changed too. The show will now be hosted by Dick Wall of New Energy, Carl Quinn of Google, and yours truly. I'm hoping Carl will use his insider status to get some of Google's A-list Java personalities on the air, and I will do the same at Sun... and by then the ball should be rolling!



There is already a first episode available. This one was recorded by Dick a while back under the JavaCast banner, but never got broadcast (JavaCast story
here.)
It's an interview with one of the people behind the IntelliJ IDE. I thought it was very interesting - and several of his metaphors work for me.



Unfortunately there's no subscription link up in the iTunes music store yet. I'll post it as soon as it's available. Please tune in, and if you have feedback on the format do share it. We'll record our first "new" show next week. For more details, subscribe to the javaposse blog at http://javaposse.com.



P.S. If you want, you can subscribe to the podcast manually now; in iTunes, go to the Advanced menu, select "Subscribe to Podcast" and paste in http://feeds.feedburner.com/javaposse






Better radio

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.


The morning commute. The San Francisco bay area has lots of radio stations to help you through it - provided of course you enjoy listening to commercials or "flipping stations". And despite the large number of software people in the area, the morning show topics are invariably the safe staple of morning shows anywhere: celebrity trash, traffic, and endless banter. Oh, and if there's ever a good segment, you can be sure it's right when you're about to lose reception as you're heading into a tunnel or the train is going underground.



One of my coworkers today asked me what the deal was with "podcasting". It is not named podcasting because people walk around recording their diaries on their iPods. Podcasts are basically radio programs. iTunes and your iPods have special support for podcasts, and treat them quite differently from regular music files. In particular, in any given program, it remembers where you left off. Therefore, if you come back to play the same program later (having played other music other podcasts in the meantime), it continues right where you left off. Podcasts are organized separately from other music, and is listed chronologically automatically. And today I discovered that if you hit pause, and later resume, it will back up a couple of seconds in the soundfile such that you don't miss a single word.



So, podcasting is really the ability to broadcast radio programs to pods - playing devices. This has some advantages. For example, since they don't rely on the airwaves for distribution, they don't have the same restrictions that radioprograms do, where the range is so limited they have to focus on topics of broad population interest. Instead, you can have highly specialized podcasts with listeners spread throughout the world. I've found it a great way to replace my constant radio frustration. Reception is perfect since you're not relying on an antenna. The topics are interesting since I picked them myself. And in addition to the special interest topics, I can get good radio programs like NPR's Nova and Jim Lehrer's Newshour.


Wednesday, September 21, 2005

Code Advice #4: Don't capitalize acronyms!

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.)



Remember how your ${NATIVE_LANGUAGE} teacher taught you to capitalize your acronyms? Please unlearn it. Thanks.



Seriously though... when you're writing code, you're not writing English. It makes perfect sense to choose symbol names that read well in your preferred human language. But CamelCase, the preferred capitalization scheme in Java code, is not proper English capitalization either. So don't carry over the acronym habit from English.



For example, use HtmlDocument instead of HTMLDocument. Use CssParser, not CSSParser.
Unfortunately, many existing APIs violate this rule. Even the JDK has many violations - acronyms like IO, UTF, EOF, XML, SQL, HTTP, URL and URI abound. However, I think the trend is towards uncapitalized acronyms in newer classes going through the JSR process.



So why precisely should acronyms not be capitalized? For readability reasons. The acronyms are treated as words, not as individual letters, so when you're scanning a CamelCase word you can quickly see that HtmlDocument contains the words "Html" and "Document". So it's easier to visually scan, and I think it just looks better.



Unfortunately, it may be tricky to rename existing classes in your code. If you use CVS, changing class names that vary only in capitalization will confuse CVS on some platforms. On Windows two filenames are considered identical if they only vary in case.



Eof.


Tuesday, September 20, 2005

Page Fragments, Entities and Characters

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.


Switch to your JSP, and inside the body tag, type

One Piña Colada, Please!

If you run, you should see the expected text in the browser.



Now try the same thing, but edit the text inside a page fragment.
If you deploy, you'll see this in the browser:

One Piña Colada, Please!



Uh oh! What happened?



Turns out the app server doesn't realize that the page fragment file, the jspf file,
should be interpreted as an XML-formatted JSP, just like the main document. As
a result, the source fragment file (which is just a static JSP include behind the
scenes) gets, well, mistreated. You can see a very similar thing with entities.
If you go and insert JSPX entities in your fragment, these will not be correctly
expanded and instead of spaces you'll see things like "&nbsp;".



Here's how you can fix this. You basically need to tell the deployment container
that it needs to treat .jspf files as XML formatted JSPs. Unfortunately, you
can only do that using JSP 2.0. That means this won't work on deployment containers
that don't support JSP 2.0. The bundled one, Sun Application Server 8.1, does (as
does 8.0 which we shipped with Creator 1.0, so this solution works for Creator 1.0
as well.)



Switch to the Files view (it's in the same window container as the project navigator),
drill into your project, then open web/WEB-INF/web.xml. Switch to the
XML view. Replace the root <webapp> element with the following:


<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">


And then inside the body, insert the following:

<jsp-config>
<jsp-property-group>
<url-pattern>*.jspf</url-pattern>
<is-xml>true</is-xml>
</jsp-property-group>
</jsp-config>



This is how this should look:






Now when you deploy, the page fragment text should be treated the way it's supposed to - and your Piña Colada will be on the way.



So why don't we just add this configuration info to the default web.xml we ship with Creator? Well, then you would no longer be able to use Creator with any older app servers. We're trying to hard to be compatible. However, we might be able to do something better here. I'll talk to Mr. Deployment to see what we can do.



New Creator Blogger

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.


Say hi to Winston Prakash - another Creator developer who now has a blog.
Winston wrote the new CSS editor in Creator 2 that I described a while back. I
sometimes call the CSS Editor the Winston Editor...


Saturday, September 17, 2005

JSF Refactoring Support

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.


Creator 2 EA2 now supports JSF refactoring. Take a look at this screenshot of the Refactoring window:






You might think supporting Refactoring is a slamdunk since we're built on top of NetBeans 4.1 which supports refactoring.
However, notice that we're doing a lot of JSF specific stuff here.


  • We update value binding expression references

  • We update navigation rules

  • We update managed beans definitions

  • We update web.xml if the start page has been renamed




Eric had to do a lot of work to get our Creator source modeller to play nice with
the NetBeans one. Yes, we're working to resolve this architectural redundancy - that was partly the agenda for the August
trip to Prague.
Here are some of the suspects at our favorite breakfast bistro in Prague:
Robert Brewin,
Tom Ball, and
Eric Arseneau. Yes, the Eric who did the Creator refactoring work.
This particular cafe serves the largest lattés I've ever seen; not quite "Big Gulp" size but certainly
a healthy morning dose to combat jet lag!





Wednesday, September 14, 2005

New Bits Available! New Features!

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.



An update to the early access version of Creator 2 is now available.



The high level changes in the update are described here.



Here's my own list of stuff to look for in the update - heavily skewed towards the changes in the designer and related areas!


  • It now runs on (and in fact, ships with) JDK 5.0.

  • Various memory leaks have been fixed so it doesn't deteriorate over extended use. However,
    performance work is still ongoing.
  • We now have inline editing of buttons, textfields and textareas as well. Note that when you
    drop a button you immediately edit its name. This is to strongly encourage you to provide a
    specific label rather than relying on defaults (which vary from browser to browser, and can interfere
    with your layout.) To enter inline editing mode (which is done by default for buttons, but not
    for text fields), click twice, or hit F2, or use the Edit <Property> context menu item.





    (Tip: When you're editing text in a multi-line text field, enter inserts a newline. To commit
    the text edits, hit Shift+Enter, or as with any other inline editing operation, click outside
    the inline editing component. Press Escape to cancel editing.)


  • Some new designtime behavior has been added for components. Check out the Tab Set for example.
    They now come pre-configured with an associated grid panel for each tab. The components placed in
    this grid panel will show up only when the associated tab is selected. Finally, easy tab panels
    without needing to create multiple pages!
    And in the designer you
    can click on the Tabs at designtime to automatically switch the rendered view so you can easily
    design each tab.

  • The property sheet shows values that are different from the defaults in bold! See screenshot; style and
    text properties have been changed, whereas the columns property, 20, is just an inherited default:





  • Page fragments work better now. I'll probably blog on that separately.


  • Component metadata can now specify the default text for event handlers. These are now more helpful, hopefully
    giving you some specific hints as to what you need to do. For example, if you add a validate event handler for
    a text field, the default method inserted in your page bean is this:





    Note also that the parameter names in the event handlers are much better (they used to be composed by simply
    taking the capital letters from the type name; e.g. a FacesContext parameter would be named fc.)
    As you can see, it's now named context, just like in the interface definition for Validator.

  • Creator now supports JSF refactoring. I'll wait a couple of days and see if Eric blogs
    on it (he did the work); if not I'll talk more about it.




Please take it for a spin and give us feedback.


Monday, September 12, 2005

Performance Tuning: Efficient CSS Handling

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.


We have an update to Creator 2 Early Access which should go out any day now. One of the big things we fixed in the update is closing various memory leaks which caused Creator to slowly run out of juice. There are lots of other important improvements too - for example, Creator will finally run on JDK 5.0. But one big thing is still missing before we can ship it: Speed tuning.



I finally got done with my other 2.0 tasks last week, and have now started the performance tuning work in earnest.



It's really fun! I perform various tasks, look for hotspots, study the code and decide if (a) the code is doing something stupid, and (b) if the code is getting called too often. I've found several easy things to fix, so I've integrated a couple of things, sent e-mail to some other people when the bottlenecks are in their code. And in one case filed a NetBeans issue with my analysis.



The right way to performance tune is to measure the code looking for hotspots, rather than using your intuition about code you've written which is probably slow. So that's what I did - and I measured an enormous bottleneck in the CSS handling code.



This bottleneck has been there since 1.0. However, the bottleneck is proportional to the number of rules in your stylesheets as well as the number of elements in your document, so it doesn't show up for most pages created with Creator 1.0. However, in Creator 2, with our new nice themes, we have really large stylesheets which trigger the slowdown. And if your document has a lot of elements, which is pretty easy now with some of our new complex components, the slowdown is significant. As pointed out by the profiler.



This performance bug was really fun to analyze and fix, so I'll explain the gory details to you.



The problem is this: For each element in the document, we need to figure out which rules apply to that element.
This was done by iterating over the rules, checking the selectors in each rule to see if they apply to the current
element, and if so, "apply" the rule to the element.



The problem is that in Creator, the new Theme stylesheet contains nearly 800 rules! And of course, most of those rules
contain multiple selectors, each of which must be checked! Then there's the possibility of additional stylesheets.
There's the builtin user-agent stylesheet (which assigns HTML semantics for the element) as well as the project default
stylesheet, and any stylesheets you've added yourself. Finally, some of the selector checks involved iterating up
node hiearchies (for example, the :link pseudo tag means we need to see if the element is enclosed within an <a> tag.)
To cut to the chase: some of the node iteration and selector check code would get called over a million times for a page render!



Clearly, this needs to be optimized. There is a straightforward technique to handle this which apparently
is used by Mozilla's layout engine. I learned about it from reading David Hyatt's blog.
That's right boys and girls - spending time reading blogs CAN benefit your daytime job!
Give yourself a pat on the shoulder and resolve to return to my blog regularly :)



The technique is as follows: preprocess the stylesheet when it's first loaded, by setting up some
extra datastructures which will make the later (frequently called) "find-rules-for-element" perform faster.



Consider the following sample rules:


.Tab1Div table {border-collapse:collapse}
.WizMst {background:#C6D6DF}

The first rule can obviously only match Elements where the tagname is table, and the
second rule can obviously only match an element that has a class attribute which includes WizMst.



Therefore, when I preprocess the stylesheet I split up the set of rules into four categories.
First, for any rules where I can identify a "tag name requirement", I add the rule to a hashmap
indexed by the tag name. Then, for any rules that have a "class attribute requirement",
I place these in a hashmap indexed by the class attribute. Similarly for the element id condition.
Then I have a list of all the "remaining" rules, which don't have obvious tag/class/id requirements.
These will need to be checked the old way against all elements.
But amazingly, out of the 800 rules in the theme stylesheet, only 5 fit into this last category!



Now, whenever I need to compute matching styles for an element, I first look up its tagname,
check for applicable rules in the hashmap, then do a full selector check on each one of
these rules. Then I check the styleclasses in the class attribute with the class hashmap, and
so on. Finally, I do the old-style iteration of the "remaining" rules. This effectively partitions
the rules up into small buckets, one for each of the tag names, and one for each of the attribute names,
so for each element I get to do a lot less work.



This does however add one complication: cascade order. I cannot simply process all tag-related rules
followed by all class-attribute rules. Later rules in the stylesheet should "overwrite" earlier
rules (modulo various cascade rules etc.). So after matching rules from my hashmaps and
the remainder-list, I need to sort the rules into the right cascade order again.



The first thing to do was to verify that the optimization works - that pages still render correctly.
They appear to. Check. Then I measured the performance differences to make sure I actually get an
improvement and remove the bottleneck. To make it easy to check,
I put the new code path under a global flag I could turn on and off. Then I ran style attribution
with the optimization on, then with the optimization off, and compared the results.
And the effort definitely paid off.
For smallish pages, style attribution got a speedup of 12x. For large pages, I got a speedup of 8x!



Note that these speed improvements are not in EA Update - which has been out of our hands for a while now.


Rejected Ads

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.


Check out

these ads
eventually rejected by "top business publications". clientjava.com claims it was Wall Street Journal -
I have no inside information.













(There are more ads at the marketing site)


Sunday, September 11, 2005

Code Advice #3: No Tabs! Ever!

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.)



Should you use spaces or tab characters when indenting your code?
This question has been debated at length in the past, with a fervor similar to the "emacs versus vi" editor debate.
But unlike "emacs versus vi", we cannot just agree to disagree. We can each choose to use a different IDE.
But the source code is often shared, and if there's one thing that's worse than a source file indented with tabs, it's a source
file partially indented with tabs and spaces. This is typically the result of a file edited by multiple users.



My advice is simple: Always use spaces to indent. That doesn't mean you can't use the Tab key in your keyboard to indent - most tools will automatically do the right thing with spaces instead. In other words, the Tab key is the Indent key, not the Tab character key.



So why is it bad to use tabs instead of spaces?



There are several reasons. Obviously, there's the reason I started out with: that we really need to pick one convention. Spaces for indentation is the most common scheme used to today, so it's a reasonable choice on that basis alone.



One of the problems with tabs is that a tab character needs to be converted into whitespace by the editor when displaying the file. How much whitespace should each tab character be replaced with? In an ideal world, the old typewriter functionality could be used, where each tabstop had a certain pixel position. That way people could even use proportional width fonts in their editors (instead of the blocky monospace fonts used by practically all code editors today), and the code would still indent nicely. However, no editor that I'm aware of supports this, so that's not a practical venue. Instead, editors typically make an assumption that a tab is either 8 characters (common in ye old days) or 4 characters (common in Java editors today). Some editors will stick with the 8 character assumption, but support 4-character indents in Java (which is common), so when indenting to level 3, they will insert a tab, followed by 4 characters, to get a 12 character indent using an 8-character tab.



Why is this bad? Because code is viewed in more than one tool. In the presence of tabs, code often gets misaligned. Code integration e-mail diffs, code viewed in other editors, code edited by other tools which treats tabs in a different way will easily get "mangled" (e.g. start getting mixed spaces and tabs).



(Sidenote: In the old days, source files sometimes included a comment at the top of the file, with special "tokens" (-*-) intended for Emacs. These tokens would identify the language mode as well as the intended tab size for the file. When loading the file, emacs would use the specified tab size. Thus, the source files actually carried the tab information needed to edit the file as intended. However, this solution doesn't really solve the problem since all other tools which process and display the file would also need to be aware of this metadata.)



I've heard people put forward two arguments in favor of using the tab character:


  1. If a file uses ONLY tab characters for indentation, it is easy for users to read code at their own favorite indentation level.
    In other words, I can read your source file with tabs=4, you can read it with tabs=2

  2. It's easier to move back and forth indentation levels, since a single left/right keystroke will jump across tab characters, e.g.
    whole indentation levels.



Regarding argument 1: There are lots of other things I want to customize when I read other people's code too. You see, people don't all agree with my code rules that I'm putting forth in these blog entries :-) So if I read code that is indented poorly, or worse yet put spaces between function calls and the parenthesis, or other horrible coding sins, I hit Shift-F10 to reformat the source properly first anyway. This solution is more comprehensive than simply adjusting the indentation depth.



Regarding argument 2: I don't see a big usecase for being able to move the caret up and down indentation levels. These only apply at the beginning of the code line, and the Home key should alternate between jumping to the beginning of the line and the first nonspace character on the line. Why would you ever need to go somewhere else? Perhaps you want to move some code up an indentation level. That's what the Reformat feature is for. Just reformat the buffer instead.


(Minor sidenote: In
Emacs, and I believe in JBuilder, the Tab key was bound to a reindent action, NOT inserting indentation. This is a much better use of the Tab key. When you're on a new line, pressing Tab should move the tab to the correct indentation level (reindent), NOT inserting say 4 characters. If you're on a line with existing code, hitting Tab should NOT insert 4 characters where the caret is located, it should adjust the line indentation such that it's correctly indented. Thus, if I put an if block around a piece of code, I can just hit Tab, Arrow Down a couple of times to indent the block correctly. I submitted a

patch
for NetBeans to do this a while ago but this behavior is apparently a bit controversial. For a previous XEmacs user like myself it's indispensable.)




Therefore, in my opinion, these potential advantages do not make up for the massive problems and ugly code that result.
Let's all use the same convention - no tabs.



All IDEs let you do this. (I even believe most IDEs default to using spaces. Please double check in your own.)
Here's the option in the new NetBeans 5.0 options dialog:






The people who seem to rely the most on Tabs today are people using old-style editors where Tab characters are still the default.
If you're using Emacs, add the following to your .emacs file:


(custom-set-variables
'(indent-tabs-mode nil)
'(tab-width 4))

Here's how you do the same thing in Vim.


Saturday, September 10, 2005

JavaCast - will be baakk

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.


Brandon Werner, one of the two guys who started the JavaCast, and apparently the one guy who owns the JavaCast name and web site, decided Java is soooooo boring. As is programming. As is the entire tech industry.



So even though the JavaCast has over 30,000 descriptions and a large number of separate downloads (perhaps by people who haven't seen the light with iTunes), not only did he quit -- he took the web site down with him. Not even a postscript telling people what happened.



I just talked to
Dick Wall,
the other JavaCast guy. He's about as confused and disappointed as I am, and definitely wants to continue the broadcasts. He's working on finding bandwidth etc. So good news - the JavaCast will be back in some form, but probably with a different name.



Here's a suggestion: JavaCats?



P.S. Dick has described the situation himself here.


Friday, September 9, 2005

NerdTV

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.





PBS is making available online NerdTV: a series of hour-long programs where Cringely interviews various technology luminaries. The format is a lot like the Charlie Rose show. I just "watched" the first program this morning while sifting through my e-mail. It's with Andy Hertzfeld, of Apple++ fame. Episode #3 will be with Bill Joy; I'm especially looking forward to that one.



So I'm definitely bookmarking
the URL.


Thursday, September 8, 2005

First Day of School II

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.





It's been a very hectic week in my personal life. This week school started - my daughter in first grade, my youngest son in preschool, and my oldest son in kindergarten. He's in the picture on the right outside his new classroom - the same room his sister had last year.



It was a nightmare balancing the equations such that they're all taken care of from 8 until 5 every day. School only runs until 2:35 (first grade) and 11:20 (kindergarten) so I had to find an after-school program right next to the school - and the school-provided one isn't available for kindergarteners. And of course the after school programs won't take preschoolers.



Filling out all the paperwork was a Dostoyevskian effort. For each child there was form upon form, all asking the same information over and over again. Whatever happened to the paperless office? Reducing red-tape? There's definitely an opportunity here!



(First Day Of School I)



Tuesday, September 6, 2005

Code Advice #2: No Vanity Tokens

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.)



Some programmers like to tag their code modifications with their
own initials:



//!FB Shouldn't we compare with MIME type?


I've been told the format shown here, using the explamation
point in front of the initials, is/was the preferred format
at Borland. They even had a tool to go and strip these
types of comments out before releasing source code to customers.



Having people "sign" their comments doesn't contribute to
make the comment more readable. Real projects should be using
some kind of version control system, and information about
which line was written by whom (as well as when)
belongs in the version control system, not inline in the source.
The comment should be able to stand on its own feet.



There are some standard tokens that should be used.
TODO, FIXME, and XXX are
standard tokens used to mark code that needs to be revisited.
They are "standard" in the sense that many editors and IDEs automatically
highlight and search for these tokens. In fact, they are even
documented in section 10.5.4
of the standard Java code style document:


Use XXX in a comment to flag something that is bogus but works.
Use FIXME to flag something that is bogus and broken.


They left out TODO, which should be used where something hasn't
been implemented in the first place.



By the way, @todo is a reserved javadoc tag and
means the same as TODO in comments. (Speaking of javadoc tags,
@author is obviously okay and does not fall under the no-vanity-tokens
guideline.)



In addition to these, I use some additional tokens to mark code
for other purposes:




  • JDK15 is a token I attach next to code or comments
    which should be revisited when we drop JDK 1.4 support and can
    start using JDK 5.0 APIs. For example, I have code in the designer
    which tracks the current mouse position (such that pressing Ctrl-V
    to paste a component from the clipboard places it under the mouse
    position). In JDK 5.0 there is a new API which lets me look up
    the mouse pointer position directly (yay!! Thanks!) so I can rip
    out the old-style code.




  • NOI18N is a code marker which indicates that any String
    literals on the same code line are deliberately not internationalized.
    This is used for Strings which not be localized, such as the name
    of a Java class used in Reflection-related code for example.



I'm sure there are other useful tokens too. What makes these different
from "author signatures" in comments is that they are added specifically
to facilitate locating this code fragment in the future (when looking
for JDK 5.0 migration possibilities for example) or for processing
by tools (such as the String localization checker).



Including bug ids in comments falls in roughly the same category.
Code segments full of bug database numbers are hard to read. It's much better
if the various corner cases that were exposed by bugs are explained
inline in the code. This is less of an absolute however in cases
where there truly is a lot of value for a developer to be able to
look up associated bug reports and history.
And of course, code which was added as a specific workaround for
a bug elsewhere (such as a OS or JDK bug) should have the associated
bug id included, such that future developers can look up the status of
the bug and easily determine if the code is still necessary.


Saturday, September 3, 2005

Code Advice #1: Don't Log, Debug!

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.)




Rule number one: Don't Log, Debug!



One of my pet peeves in code is gratuitous logging.
Gratuitous logging is where every little thing happening in your code is also sent as a log message.
In other words, logging is used to record program events, rather than program errors!



The rationale for this is usually that logging is inserted to help find bugs later. "Just turn on
logging and comb through the output to trace execution and discover the problem."



I don't buy the above argument, but before I go into that, let me state why I think logging is bad:
It reduces code readability.
You've probably heard that you shouldn't sprinkle your code with comments that are obvious (and therefore
redundant). Sprinkling your code with logging calls describing what's going on is essentially the same
thing, only it's even harder to mentally filter these out while reading the code, since they don't have the
visual "I can ignore this" property that comments have in syntax highlighting.



There's a much better way to find bugs than by using logging: Use a debugger! I will admit that I used
to rely on logging myself, since in the early days restarting the application, and even single stepping
the debugger, was frustratingly slow.
But with the introduction of
Hotswap,
and general improvement in features and speed of Java debuggers,
there's no good excuse for not using a debugger to track down program bugs today.



The argument that's usually thrown out in defense of logging is that you need it to track down
bugs in a deployed environment, for example at a customer's site, where you don't have physical access
and cannot debug it yourself. You want to enable logging and use the log from the customer to figure out
what's going on.



In my experience, that sounds good in theory but never works in practice. The logging never has all the
information you need. To track down a specific bug you typically need fine grained
information that you hadn't thought you needed when you wrote the code.



Let me also point out that this is a really rare scenario. Usually, if a customer reports a bug, they
can tell you how to reproduce it, and once you can reproduce it locally you don't need to debug it
via logs on their system - use a debugger locally.



The scenario has come up once for me. In Creator 1.0, some customers reported that after using
the IDE for a while, the IDE would suddenly stop updating the source files even though components were
added and properties changed. There were no direct instructions to reproduce, and it was rare - nobody
internally had ever seen it. Finally a case for customer site logging! What I did was add a number
of targeted logging calls; anything having to do with buffer manipulation was heavily "instrumented".
I also developed a couple of hypotheses about what the problem might be, and added special code for
checking these hypotheses, adding log messages if they succeeded. I then provided a custom jar to
two customers who had reported seeing this problem regularly - and a few days later I had confirmation
of one hypothesis.



The key point I want to make here is that even though this actually is a scenario which called for
logging, it didn't have to be put in the product a priori. The logging calls were only added temporarily
in one of my source trees. And furthermore, to get useful logging data I added a lot more tracking
than would have been feasible to do in a product version.



So when should you use logging? To record errors and unexpected conditions - especially non-fatal ones
where you don't want to get the user's attention, you simply want to know about it yourself such that
you can check your assumptions and improve your program quality later.



If you're not convinced and still want to use logging, here's a tip for how to do it efficiently.
There's always the option of statically compiling out all logging:



private static final boolean LOGGING_ENABLED = false;
...

if (LOGGING_ENABLED) {
log("foo = " + bar);
}


By using a final boolean here which is false, the compiler knows that everything, including the if block, can
never be executed, so it will be completely eliminated - the class file will not contain any of the byte code;
the class String table will not include the string in the log call, etc.
This is zero-overhead logging, when logging is disabled.
The disadvantage of this approach of course is that it cannot be enabled by the customer, so
it's only useful internally. And for that of course, use a debugger!



A modification to this scheme which works well, is to use the assertion facility.
This is what I used before I finally removed all non-error-related logging from my code.
Create a log function like this:



public boolean log(String message) {
// log calls here - perhaps delegate to a logging library

return true;
}


Now you can use logging as follows in your code:



assert log("foo = " + bar);


This is using assertions for a side effect: the assertion will always be true
(since the logging call unconditionally returns true) so no AssertionError will be thrown.
However, the logging method parameters get evaluated and the logging method called.



This solution gets the best of both worlds: When turned off it has nearly zero
overhead (because the class loader will throw away the assertion statements when
loading the class), but it can still be turned on in those rare scenarios where
you need a customer to provide you with logging calls.
(It does however increase the size of your String pools etc. so there is a small
cost.)



But again,


  • In practice this scenario comes up very rarely

  • Even when it does your existing logging calls probably aren't sufficient anyway

  • You can get the data you need by providing the customer with a special enhanced logging build

  • Logging calls makes your code less readable

  • Logging calls makes your source files, and class files, larger

  • Without any significant pros, and a significant con, the choice should be easy!




Don't forget - logging is appropriate for logging errors! Don't start writing
empty catch blocks and blaming me! For example, in an application built on top of
the NetBeans RCP (see a
tutorial of the new
RCP support
), a catch block that doesn't do anything else should at least call


} catch (WhateverException ex) {
ErrorManager.getDefault().notify(ex);
}

Code Advice "Column"

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've discussed coding style a couple of times before in this blog, and it invariably generates a lot of interest and discussion.
It seems I'm not the only one who cares a lot about these issues.



I recently tried to explain the coding style I've used in the Creator designer source base, to somebody else on the team.
When I tried to provide references I came up short.
There are several coding style guidelines - and I tend to follow
the JDK one - but the problem with the official coding
style document is that it leaves out a lot! For example, it does not address the Tabs versus Spaces issue (cowards!).

I found some other good ones, but I disagree vehemently
with some of their rules (like open braces on a separate line,
and underscore suffixes and fields, and indentation level 2).



So, I intend to start blogging my opinions on how to write good code. Some will be controversial - especially my first "rule"
regarding logging!
Note that no rule is absolute - there are always exceptions and you need go consider the tradeoffs and apply good judgement.



I also shouldn't take "full credit". I have not invented most of these practices. Some I have learned from developers whose
style I admire. Others have come about as the result of (sometimes heated) discussions with other programmers.
And finally, some have I have learned from my own past mistakes.



Take everything with a grain of salt - but I hope you will find these entries, at least some of them, helpful.



Update 10/15/06: Here are the entries as of today:


Friday, September 2, 2005

In Alignment

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 just fixed the part of the designer layout engine which aligns inline boxes.
Specifically, I'm now computing the baseline of form components like
buttons and textfields, such that rather than aligning the bottom of
these with the text baseline, the baseline within the components are
baseline aligned.



This looks a lot better - especially for things like radiobuttons.
Take a look at the before and after shots. And unlike most weight-loss
advertisements, I promise I'm using the same lighting and lens when
taking these two snapshots:









Before










After


There's a lot to point out here. First, notice how the radio and check boxes now
seem centered next to the text. Second, and more importantly, notice how the labels
in front of the text field and dropdowns are properly aligned with the text
inside these components. This points right to something else you should know
about: the Label property of many of these components. If you set the label directly
on the component, it's rendered along with the component and gets proper baseline
alignment as shown here. If you drop a separate Static Text or Label yourself, it's
not "one" with the component and won't move as a single unit, render into a single
<span> rendered by the browser, etc.



Tip: Notice also that by setting the Required property on the dropdown and text fields,
the label automatically got rendered with a little red asterisk indicating to the
user that it's a required value. This even works when you use a separate Label component;
as soon as you bind it to another component (by ctrl-click and dragging from one
component to the other to link them) the required property will propagate to the label.



As another example of where the alignment bug shows up, take a look at the bottom row
of the new table component once pagination has been added in its customizer.
Notice how the Page text field is really misaligned from its "Page:" label.
This was the bug that inspired me to fix this.






Here's how the bottom looks now - pretty darn close to what browsers will show:






I just put this fix in, so it will not be in the EA 2 bits. EA2 has left development engineering
and is getting some TLC from the QA organization right now. Stay tuned.