Making Java less Difficult
I’m sure that you’ve heard this before, but I’ll say it anyway: Why do Java developers make simple problems difficult? There are plenty of people who have written on that topic, and I have no desire to further expound the point. I think we all get it. What I do want to talk about is how to make things less difficult, in particular how to make web application development as easy in Java as it is in Perl, PHP, Python, or Ruby.
I challenge that the answer is not to build Yet Another Crappy Web Framework ™. I for one, am terribly sick of complicated frameworks that are more work to configure than a web application is to create manually.
What I’ve noticed, is that developing in Perl is often faster than Java mostly due to the built-in regular expression handling Perl offers; and this is despite the fact Java offers a comparable regular expression engine.
Two things that slow me down as developer:
1) Staring at code that involves a StringTokenizer, while loops, and several nested substring statements where I’m counting characters on my figners. Why do Java programmers continue to write code like this? I suspect the reason is because of the next issue.
2) Wanting to use a regular expression, you first create a Pattern object, followed by a Matcher object, remember to compile your pattern, and then finally match the pattern using the Matcher object. Your matched object can use the group method, which is implemented from the MatchResult interface. I’m going to repeat myself, as this bears repeating, why do Java programmers make simple problems difficult?
These two issues cover 90% of the cause for Java development to be slower than Perl. Solving these two problems should then speed up my development in Java to be on par with my development in Perl!
Let’s look at some sample Perl code:
if (/a(.*)b/) {
print "$1 is between a and b";
}
We could do this fairly easily in Java, but let’s be honest, the real strength of Perl is when I start doing things like:
@bar = split(/:/, $_);
@foo = grep(/^#/, @bar);
print join(':', @foo)
While that example is simple to any Perl programmer, it is, admittedly less intuitive and less clean than a Java version. Although it is only three lines rather than the twenty or more it would take in Java. But what about something like this:
XYZ bar = XYZ.split(":", arg);
XYZ foo = bar.match("^#");
System.out.print( foo.join(":") );
This seems easy, and perhaps clean enough not to bewilder the Java developer the way Perl code tends to. Perhaps we can create a utility Java class that supports the needed data structure and methods to write code like that. What other methods would we need to empower Java developers to stop writing the usual tokenizer/substring mess? Consider just the basics:
join - join the values of an array into one string split - split a string into parts match - match the parts matchAll - match repeated patterns trim - trim the ends of a string
This much is already provided in Java in one class or another. The String class already lets me match and split, but it’s not enough. I need more than just a String class, I want an array of Strings. No, I want a dynamically sized array of Strings that I can easily get and put from. While I’m at it, I want it to be associative array, where I can treat it like a normal array and it will retain index order, or I can add my own keys (similar to PHP arrays). Given a data structure like that, add in the above methods to that data structure, and I think we’d be in business.
The scripting languages provide a default context that includes regular expressions, hashtables, dynamically sized arrays and various string manipulation features. I can do all of that in Java, but it’s not conveniant creating a different object for multiple data structures and methods, especially since they’re almost always part of the same context.
Let’s create one class that contains the data structure and the methods. This should solve both of my issues, making it easy to do what once was difficult and speeding up development for most all applications.
Even better, we can leverage what Java is good at to get this done. Let’s extend a Java Hashtable which solves most of the data structure part.
public class Preg extends Hashtable {
public Object get( int inInt ) throws NullPointerException {
Integer cast = new Integer(inInt);
return this.get(cast);
}
public void put( Object value ) {
Integer key = new Integer( this.size() );
this.put( key, value);
}
}
I’ve added the ability to put values without providing a key, this will allow us to use this object as both a HashTable and a Vector (i.e. a resizable array). For those of you who are upset that this is inefficient, you’re absolutely right. Although I would argue that it’s a negligible difference. But since we’re speeding up development, this will more than compensate since I’ll actually have time to optimize my code and do some refactoring before the deadline (a luxury I rarely see Java developers having time for).
The next step is to create the methods, we should also provide static versions of the methods to gain maximum convenience. For example, I may only implement one “join” method, but I’ll provide several prototypes:
public String join() {
return Preg.join("", this);
}
public String join( String glue ) {
return Preg.join(glue, this);
}
public static String join( Preg src ) {
return Preg.join("", src);
}
public static String join( String glue, Preg src ) {
... the actual implementation
}
After I do this for all of the methods, I’m left with a very powerful object that allows me to accomplish the previous Perl example:
Preg bar = Preg.split(":", arg);
Preg foo = bar.match("^#");
System.out.print( foo.join(":") );
Three lines of Java that for once is equal to three lines of Perl!
All the fancy trickery that we do in Perl or PHP can be done in Java with just the right mashup of HashTable, Pattern, and Matcher. You can split a string into parts, filter, trim, and arrange to your hearts desire without ever having to count a character offset for a substring!!
Note: I have all of this working for one of my projects, which will hopefully move as fast as it would in Perl or PHP (it’s a web application, so I suspect this will in fact compensate for that 90% slowdown I mentioned earlier). If there’s interest, I can provide the source and/or Javadoc.
Even with my extremely verbose Javadoc it’s surprisingly not that much code.
