h1

Is Eclipse Bloated?

June 29, 2006

Ed Burnette at ONJava.com has a nice article about what’s new in Eclipse 3.2 Java Development Tools.

I like most of the new features but it occurred to me that I don’t use most of what Eclipse already offers. In fact, I’m probably unaware of much of Eclipse’s time saving tools. Part of being a good developer is knowing the tools you use, so I realize I should spend more time getting to better know the tool I use every day.

But is Eclipse, touted as “an IDE for anything and nothing in particular,” becoming “an Everything for everything and all things in particular?” Is Eclipse becoming so full of “stuff” that it’s nearly impossible to know and use all of its useful gadgets? If not, at what point does it become Word-like, in that 80% of its users utilize only 20% of its features?

I don’t want to start any IDE flames. Eclipse is an incredible tool and the fact that it’s free is astounding. I’ll continue to use it as long as the “fluff” doesn’t get in my way.

h1

Inventing the Wheel

June 25, 2006

APIs: Howto – O'Reilly ONJava Blog
"…every time I look at JavaMail or Swing I can’t help but think that there should be a set of minimalist top-level classes that provide a simple, clean and obvious way to meet 80:20 requirement that I can then cast to more complicated objects if I need to get real fancy."

Amen. Sun's philosophy has always been that their responsibility was to provide low-level APIs and let programmers do the rest. This result is that developers waste so much precious time re-inventing (in some cases, inventing) the wheel. It's one of the major reasons folks are starting to take a look at Ruby, Groovy, et. al.

h1

FindBugs and More

May 24, 2006

I discovered FindBugs today and just for fun, I ran it against our current project. Among many, many other things, BugFinder flagged code that created new instances of Boolean rather than use Boolean.TRUE or Boolean.FALSE. This method was tagged as one of the offenders:

public Boolean validateMinLength(String value, int length) {
 try {
     if (value == null || value.length() == 0) {
         return new Boolean(true);
     }
     if (value != null && value.length() >= length) {
         return new Boolean(true);
     }
 } catch (Throwable e) {
 }
 return new Boolean(false);
}

I quickly fixed the offending code:

public Boolean validateMinLength(String value, int length) {
 try {
     if (value == null || value.length() == 0) {
         return Boolean.TRUE;
     }
     if (value != null && value.length() >= length) {
         return Boolean.TRUE;
     }
 } catch (Throwable e) {
 }
 return Boolean.FALSE;
}

There were still several problems. In fact, it reeked with code smells. A healthy dose of refactoring was in order. Most blatant was the unnecessary and ill-advised try-catch block that silently ignored an unchecked exception. All I can say here is, “huh?”

public Boolean validateMinLength(String value, int length) {
 if (value == null || value.length() == 0) {
     return Boolean.TRUE;
 }
 if (value != null && value.length() >= length) {
     return Boolean.TRUE;
 }
 return Boolean.FALSE;
}

Poorly named methods and method parameters are a pet peeve of mine mostly because I use code completion not only to minimize keystrokes but also to jog my memory about the parameters needed by methods. “arg0″ and “arg1″ don’t cut it. “value” was a bit too generic, as was “length.” The method name, “validateMinLength,” implied that the method validated the length parameter instead of checking if the string was a certain length or longer. Eclipse made renaming a breeze:

public Boolean isMinimumLength(String anyString, int minimumLength) {
 if (anyString == null || anyString.length() == 0) {
     return Boolean.TRUE;
 }
 if (anyString != null && anyString.length() >= minimumLength) {
     return Boolean.TRUE;
 }
 return Boolean.FALSE;
}

It wasn’t perfect, but the method’s purpose was significantly clearer. An important function of refactoring is separating the intent from the implementation or, in other words, the “what” from the “how.” Without looking at the code, I now had a better idea what the method did but still not how it worked. So let’s take a closer look at the “how.”

Is the intent of the first if statement really to return true when the String parameter is null or an empty string? That’s what the code said, but I was inclined to think it was a bug; logically, null has no length, so how could it meet a minimum length? Not too long ago, I would have added a reassuring comment along the lines of, “// return true if value is null or nill.” I reason that the second if statement actually checked if the string had at least “minimumLength” number of characters but I shouldn’t have to guess. Since I’m a better programmer than I was six months ago :-) I extracted new methods to make it more “human readable”:

public Boolean isMinimumLength(String anyString, int minimumLength) {
 if (isNullOrNill(anyString)) {
     return Boolean.TRUE;
 }
 if (meetsMinimumLength(anyString, minimumLength) {
     return Boolean.TRUE;
 }
 return Boolean.FALSE;
}

private boolean isNullOrNill(final String anyString) {
    return anyString == null || anyString.length() == 0;
}

private boolean meetsMinimumLength(final String anyString, final int minimumLength) {
    return anyString != null && anyString.length() >= minimumLength;
}

Now there’s no question that the method really should return true for a null or empty string and when the string has at least minimumLength characters.

Next, using multiple returns violated my rule of one entry point and one exit point for a method. I’ve been in arguments with others who think it’s silly to worry about one exit point, but had the rule been followed, only two Boolean objects would have been instantiated instead of three.

public Boolean isMinimumLength(String anyString, int minimumLength) {
    boolean b = false;
 if (isNullOrNill(anyString)) {
        b = true;
 }
 if (meetsMinimumLength(anyString, minimumLength) {
        b = true;
 }
 return Boolean.valueOf(b);
}

One last step: while this method was not very complex, there’s no reason it couldn’t be simplified. Also, whenever possible I prefer to avoid using a default return value. Here’s my final refactoring:

public Boolean isMinimumLength(String anyString, int minimumLength) {
 boolean b = isNullOrNill(anyString) || meetsMinimumLength(anyString, minimumLength)
 return Boolean.valueOf(b);
}

private boolean isNullOrNill(final String anyString) {
 return anyString == null || anyString.length() == 0;
}

private boolean meetsMinimumLength(final String anyString, final int minimumLength) {
 return anyString != null && anyString.length() >= minimumLength;
}

The public method is readable, even by a non-programmer. It’s faster to gleam the method’s purpose. How the funcionality is implemented is only one method declaration away. This will all come in handy if someone not familiar with the code has to dig in and find out what it does. Lines of code (not counting method signatures) have been reduced from 10 to 4 so bugs are less likely and easier to fix should they occur.

One method down, oh so many to go.

h1

NoFluffJustStuff Conference Takes Omaha by Storm

April 2, 2006

Unsurpassed Quality
NoFluffJustStuff just concluded the Greater Nebraska Software Symposium, its first-ever stopover in Omaha, NE. It couldn't have turned out better, despite the stormy weather. The presenters are all first rate–they don't just talk about this stuff; most all have invaluable real-world experience they are willing to share. There is honestly not a dud in the bunch. I'm invigorated (if not a little brain-sore) and anxious to implement some of the techniques and ideas that I walked away with. Seriously, if you are a Java web developer, you owe it to yourself to attend one of these conferences, even if you have to foot the bill yourself.

Test First
The first Saturday of the month the city tests its tornado warning system. This happened while I was in a session given by Venkat Subramaniam. Hearing the siren, Venkat asked what the noise was. We told him it was the tornado warning. The look on Venkat's face was priceless as he looked to duck and cover. "Don't worry, it's just a test," we told him. Without skipping a beat he said, "You should say, 'test' first!"

Happy News
One of the highlights was definately the announcement that they'll be back in Omaha next year. Hoo-rah, I'm going to No Fluff!

h1

Bar and Grill Lab Notes: Groovlets

March 8, 2006

It seems whenever I read discussions about JSF, Struts, etc., someone invariably claims they’re happiest foregoing frameworks and writing Servlets by hand. I have an inexplicable aversion to HTML code in println() statements so I’ve hand-coded a grand total of one simple “Hello World!” Servlet. I even once wrote a Java tool that converted the pointy-bracket output from a WYSIWYG HTML editor to all those PrintWriter.println() statements. JSPs put a quick and merciful end to that project.

There are some valid points to the Servlet-by-hand approach, not the least of which is avoiding the unnecessary overhead of a bloated framework, which can presumably translate to better performance. For small and even some medium-size web apps, an industrial strength framework might very well be overkill.

With all that in mind, I looked at Groovy’s version of Servlets: Groovlets. The sample on Groovy’s site is markedly minimal, so I decided to write my own to explore the capabilities of a Groovlet. The following example, IMHO, better demonstrates the power of Groovlets. Without further adieu, here is my 1.0-jsr-05 Groovlet, which displays historical stock quotes for a given ticker symbol, in two parts (to break up the monotony):

Part 1

import groovy.xml.MarkupBuilder;

def symbol = request.getParameter('symbol')
if (symbol == null) {
 symbol = '^DJI'
}
def today = new Date()
def end = new GregorianCalendar()
end.setTime(today)
def beg = new GregorianCalendar()
beg.setTime(today.minus(7))

// this line broken up for clarity
def url = 'http://ichart.finance.yahoo.com/table.csv?s=${symbol}&a=${beg.get(Calendar.MONTH)}
   &b=${beg.get(Calendar.DAY_OF_MONTH)}&c=${beg.get(Calendar.YEAR)}
   &d=${end.get(Calendar.MONTH)}&e=${end.get(Calendar.DAY_OF_MONTH)}
   &f=${end.get(Calendar.YEAR)}&g=d&ignore=.csv'.toURL()

def text = url.getText()
def list = text.tokenize("n")

Things of note:

  • request is an implicit reference to the ServletRequest.
  • The def keyword is not required in scripts but it’s probably best practice to use it anyway.
  • It’s easy to initialize a page the first time in. Here, I look at the value of the symbol parameter and initialize it if necessary.
  • Though Groovy has slightly enhanced java.util.Date, GregorianCalendar still rears its ugly head.
  • A mere 3 lines of code retrieve a CSV table of quote history from Yahoo and parses it into a List.

Part 2

html.html {
head {
 title('Groovlet Example')
}
body {
 form (method:'get', action:'index.groovy') {
   div {
     label (for:'symbol', 'Symbol: ')
     input (type:'text', name:'symbol', value:symbol, size:'5', maxlength:'5', '')
     input(type:'submit', value:'Submit', '')
   }
 }
 table (cellpadding:'10') {
   tr {
     list[0].tokenize(",").each {
       th(it)
     }
   }
   list[1..5].each {row ->
     tr (align:'right') {
       row.tokenize(",").each {
         td(it)
       }
     }
   }
 }
}
}

Things of note:

  • GroovyMarkup is very cool—no pointy brackets.
  • The input tags didn’t render properly without the empty string.
  • value:symbol can be replaced with value:”${symbol}”–not sure which is best practice.
  • Nested closures. suh-weet!
  • In nested closures, it has to be renamed in at least one closure.

Groovlets definately won't take over the JSP/Servlet stack any time soon, but they do provide an easy technology for quick solutions to small and perhaps even some mid-size projects.

h1

Why JavaServer Faces will Dominate

March 5, 2006

Javalobby Readers’ Choice: Top Java Books consists of 112 books with a total of 72,079 pages. Rick Ross, founder of Javalobby, writes,

…if you read fifty pages per day every day, then you would finish reading this collection sometime in the middle of January, 2013! Of course, there’s some question whether all of this material would still be relevant by then, and there’s also the small issue of whether you’d really want to fork over the $5,238.66 this library would cost if you paid full price for every title.

For those reasons, one would be inclined to derive some means by which to pare down the list. It’s a good bet the top five or ten are excellent reads and should be on every developer’s shelf. Word of mouth from a trusted colleague or by recommendation from an industry expert might also be good reasons to consider ownership of one or more of these books. Whatever the choice, it is most certainly not based on personal experience, but somewhat arbitrary.

The same can be said for adopting a technology. (A Google search on java web development frameworks turns up over 22,000,000 hits–admitedly unscientific, but telling none-the-less.) There are simply too many frameworks, tools, and techniques to absorb enough knowledge to make an intelligent decision when it comes to selecting technology for a development team. Some may be so overwhelmed by the staggaring number of choices, they stick with the tried and true. Most, I suspect, will decide to adopt the latest, especially for new projects. The decision to select one technology over the others most likely will be based on whatever will be around for at least the typical life span of a system. So a great guessing game ensues and inevitably the answer is, “whatever the industry leaders are pushing.”

Thus, JSF will be, if it isn’t already, the dominate web development framework for at least the next 5 years. Not because it’s a superior framework, or that it cuts development time or increases quality, or even because it’s (arguably) innovative, but because it’s a standard and Sun is behind it.

Sorry, Tapestry fans, but it’s Betamax v. VHS all over again, and you’re behind Betamax.

h1

Well Done Software

December 11, 2005

Not long ago, a friend told me about the excellent food at a frou-frou steakhouse that recently opened downtown. I tend to favor frugality, but he assured me the bacon-wrapped filet medallions were worth the second mortgage. My wife, Barbara, and I did a cost-benefit analysis and decided the budget could take the hit if we postponed our Branson vacation until next summer. I made dinner reservations for two.

I, for one, believe a steak done well is a steak well done. Many a waiter has reminded me this is atypical, so I was not surprised when I ordered my filet medallions well done, our waiter leaned in close, and whispered, “Are you sure?” I wanted to say, “Look pal, I’ve eaten enough steak to know I don’t like it bleeding all over my plate,” but Barbara has me conditioned to smile and nod confirmation.

At this point, our dining experience took a detour to the twilight zone. The chef himself burst through the kitchen doors and made a bee-line to our table. In no uncertain terms, he chided me for making him ruin a perfectly succulent cut of meat and urged me to reconsider my preferences. It seems his rigorous training, years of experience, and meticulous reading of trade journals made him better qualified to know how I wanted my steak. He only backed down when I threatened to take my vacation money elsewhere.

I stewed about the chef’s arrogance for days, and the incident was still fresh in my memory when I read this from Technology Review:

“Users are tremendously non-self-aware,” Myhrvold adds. At Microsoft, he says, corporate customers often demanded that the company simultaneously add new features and stop adding new features. “Literally, I’ve heard it in a single breath, a single sentence. ‘We’re not sure why we should upgrade to this new release-it has all this stuff we don’t want-and when are you going to put in these three things?’ And you say, ‘Whaaat?’” Myhrvold’s sardonic summary: “Software sucks because users demand it to.”

Myhrvold believes his rigorous training, years of experience, and meticulous reading of trade journals make him better qualified to know what users want in their software. Like the chef, Myhrvold thinks the end product is his and users should recognize their non-self-awareness and listen to the experts. In fact, software exists to fulfill users’ needs, not developers’.

My own sardonic summary: “Software sucks when developers demand it to.”

h1

Dilly Bar Architecture

December 4, 2005

A few years back, my wife and I participated in a treasure hunt as part of a social event/fund raiser for an organization. One clue led us to the local Diary Queen where we had to tell the clerk behind the counter a password (derived from a previous clue), after which we were each given a Dilly Bar as our next clue. For those who don’t know, a Dilly Bar is the Dairy Queen version of an ice cream bar. After wracking our brains we eventually figured out we should eat the Dilly Bar. Sure enough, the next clue was written on the part of the stick that had been embedded in the ice cream.

I faced a similar scenario at work a couple of weeks ago. Our team uses Jakarta Commons Digester to read XML files and create objects based on the files’ contents. As part of a refactoring, I created an XML file and had to write code to process it. Having never used Digester, I looked to existing code for guidance. I was quickly left scratching my head (a common occurrence, I assure you). Most of my consternation was caused by several levels of indirection. Here’s the existing code, modified to protect the innocent, namely me.

String filename = MyPropertyUtil.getProperty(Constants.CONFIG);
File input = new File(filename);
filename = MyPropertyUtil.getProperty(Constants.DIGESTER);
File rules = new File(filename);
Digester digester = DigesterLoader.createDigester(rules.toURL());
MyClass mc = (MyClass) digester.parse(input);

Long on brevity, short on pithiness; I discerned what the code did quickly enough, but I had little idea how it did so. This in itself is not a Bad Thing, but the adumbrative structure unnecessarily obfuscated code. The major offender is embedded Digester method calls in a digester_rules.xml file. It’s a level of indirection that, in most cases, hinders maintenance and code comprehension. There is scant reason to hide code in allegorical ice cream.

Here’s a simple version of the digester_rules.xml processed by the code above:

<digester-rules>
    <pattern value=”*/node”
        <object-create-rule classname=”com.mycompany.MyClass” />
    </pattern>
</digester-rules>

Here’s what the code as written in a Java class would look like:

Digester digester = new Digester();
digester.addObjectCreate(“*/node”, “com.mycompany.MyClass”);
MyClass mc = (MyClass) digester.parse(new File(input));

If I were to do a rewrite (I won’t), I would change the existing code to look more like this:

MyClass mc = loadMyClass();
…
private final MyClass loadMyClass() {
    Digester d = new Digester();
    d.addObjectCreate(“*/node”, “com.mycompany.MyClass”);
    return (MyClass) digester.parse(new File(“config.xml”));
}

Yes, the file name is hard-coded. Code in loadMyClass() is specific to a certain file—it is not, nor should it be, generic. The roundabout method of using a constant as a key to a value in a .properties file might sometimes be useful, but not in this case. The file name is not going to change (if it did, that would justify the use of a property file) and it’s not likely to be used anywhere else in the system (if it was, that would justify the constant value).

Embedding code in XML is rarely a good idea. The search for clues is fun on a treasure hunt, but there’s no place for it in software development.

h1

Selling Groovy to Luddite Tech Leads

November 20, 2005

On my current project, I refactored hard-coded data to a simple XML file similar to the following:

<test>
<parent code="A">
<child>a</child>
<child>b</child>
</parent>
<parent code="B">
<child>b</child>
<child>c</child>
</parent>
</test>

Currently, we use Jakarta Commons Digester to parse XML. For this example, the code looks something like this:

Digester d = new Digester();
d.push(new ArrayList());
d.addObjectCreate("test/parent", "test.Code");
d.addSetProperties("test/parent");
d.addSetNext("test/parent", "add", "java.lang.Object");
d.addObjectCreate("test/parent/child", "test.Code");
d.addSetNestedProperties("test/parent", "child", "code");
d.addSetNext("test/parent/child", "addChild", "test.Code");
List parent = (List) d.parse(new File("test.xml"));

If you’re already familiar with Digester, it may be apparent what’s going on. If not, you’ll have to do a little reading to determine what the Digester methods do.

So, I thought I’d simplify things with (gasp) Groovy:

import org.codehaus.groovy.sandbox.util.XmlSlurper
import test.Code

class XmlLoader {
def List getCodes() {
 def list = new ArrayList()
 def xml = new XmlSlurper().parse(new File("test.xml"))
 xml.parent.each {
   def parent = new Code("code":it["@code"])
   it.child.each { parent.addChild(new Code("code":it)) }
   list.add(parent)
 }
 return list
}
}

Now, even if you don’t know Groovy, I daresay it’s easier to read the Groovy code than the Digester code.

I foresee these issues when trying to convince the former tech lead (who thinks he still is the tech lead) the Groovy solution might be better:

  • He already groks Digester, so he won’t understand the “easier to read” argument.
  • He won’t like the import from a “sandbox” package.
  • Groovy is in its infancy; Digester is time-tested.

So, I’ll write a Digester solution just to be prepared, but (woe is me) it’s tough wanting to be on the cutting edge.

h1

Beyond Ruby

November 6, 2005

Are personal programming languages the “Next Big Thing?” Not “personalized,” but “personal”—each programmer with his own language. It’s possible if Dr. Gregory V. Wilson’s vision is realized. In Extensible Programming Systems for the 21st Century, Dr. Wilson expresses the belief

that next-generation programming systems will store source code as XML, rather than as flat text. Programmers will not see or edit XML tags; instead, their editors will render these models to create human-friendly views, just as web browsers render HTML. For example, a program might be stored on disk like this:

<doc>Only replace below threshold</doc>
<cond>
<test>
 <compare-expr operator="less">
   <field-expr field="age"><evaluate>record</evaluate></field-expr>
   <evaluate>threshold</evaluate>
 </compare-expr>
</test>
<body>
 <invoke-expr method="release"><evaluate>record</evaluate></invoke-expr>
</body>
</cond>

but it will be viewed and edited like this:

// Only replace below threshold
if (record.age < threshold) {
 record.release();
}

If this doesn’t nearly blow your mind, read no further. Now, think of a shop where each programmer has his own language. John, an old curmudgeon who only knows Java, writes this bit code:

// notify user that process has completed
System.out.println(“Done.”);

What he commits to the source repository might look something like this:

<doc>notify user that process has completed</doc>
<field-expr field=”out”>
  <evaluate>System</evaluate>
     <invoke-expr method=”println” param=”Done.”>
        <evaluate>out</evaluate>
     </invoke-expr>
</field-expr>

Rita, fresh out of a tech school that taught Ruby, loads John’s code into her editor expecting to see:

# notify user that process has completed
puts “Done.”

The problem is that her editor chokes on the Java-specific code in the XML, so the XML output must be revised to indicate what the code should do, not how:

<doc>notify user that process has completed</doc>
<write output-stream=”stdout” param=”Done.” />

Now Rita’s editor can properly translate. Let’s assume she adds another comment to the code:

# notify user that process has completed
# John has a long moustache
puts “Done.”

This XML is changed to:

<doc>notify user that process has completed</doc>
<doc>John has a long moustache</doc>
<write output-stream=”stdout” param=”Done.” />

When John loads the code into his editor, the comments most probably appear like this:

// notify user that process has completed
// John has a long moustache

John prefers multi-line comments enclosed in /* */, so he changes the code:

/*
notify user that process has completed
John has a long moustache
*/

The XML <doc> tag must contain meta data that the Ruby editor can ignore but has meaning to the Java editor:

<doc meta=”line-1”>notify user that process has completed</doc>
<doc meta=”line-2”>John has a long moustache</doc>

The “Next Big Thing” may very well not be a new language or methodology but new storage mechanism in concert with code editors that allow easy adaptation and customization of existing and new languages. With a standardized XML model, each programmer could have his own language, or view. The problem is going to be nailing down the model standard, but that’s what the guys in the ivory towers are for.