My point with this article is to document my thought process in choosing a development platform. I am not out to start a language war. I’m pretty comfortable that my facts are correct, and I know that my opinions are correct, because they are just opinions and they are mine. You may choose to disagree with my opinions, if you wish. If you do find a factual error in here, please do add a comment to the posting.
Ahh,… wide-open, blue sky development, with no legacy to hold you down. Legacy code can be handy because it incorporates a lot of useful knowledge about your problem domain, even if the way it’s implemented makes you cringe. On the other hand, when you’re entering a whole new area, you get complete freedom to explore and to use the best current tools and practices.
What could be better than doing fresh development with no legacy? Having no legacy and being the boss, of course! Technology choices can be made on technical (and business) merit without politics getting in the way. If given a complete choice of tools platforms, would developers truly go for Java or .NET (or “legacy” Microsoft APIs) or would they choose LISP or Python or OCAML?
I would imagine that developers would be all over the map in terms of their ideal choices. Some would certainly pick one of the dominant platforms. Choosing Java for a project is not unreasonable, for a programmer that’s familiar with it. Java is reasonably high-level (most importantly, you don’t have to manage your own memory) and has lots of good open source libraries.
I’ve been largely working in Java for the past four years. There’s also been plenty of Perl mixed in there, and even a little PHP. Having worked in several languages, choosing Java straight away is not a slam dunk. Here are the characteristics of my app:
- Has a component that runs on desktops (consumer/individual business user)
- Likely maintaining a database in the tens of megabytes
- Has a web-based component
- Needs to support some level of plugins/scriping
- Needs to be cross-platform (I use both Macs and PCs)
- The app is not free.
Running on the desktop means that the application should not be too resource hungry, and the download size should be kept reasonable. I don’t think everyone has a JVM installed. It may not be too onerous to require people to install one, but that’s one more headache. People are a lot less inclined to buy something if they need to jump through hurdles. I can probably get away with static compilation with gcj so that people don’t need a JRE. It’s nice to have that option.
Lots to choose from
Embeddable databases are available for Java (Derby, Axion, HSQL, plus a number of non-SQL databases). Embedding a webserver with Java is easy. Supporting scripting and plugins is easy, with the many good choices. Java is certainly cross-platform.
So, Java meets all of the criteria required for the app. So does Perl. So does Python. So does Ruby. Heck, so does Squeak Smalltalk. CompSci is all about tradeoffs, so I need to look at the tradeoffs between these choices.
I love Perl for quick, one-off scripts. I hate it for anything else. Perl is very easy to write, because there are so many ways to accomplish something. Just use the first that comes to mind. Perl is a pain to read because of that same reason. Your mind actually has more work to do to figure out what that piece of code you wrote three months ago does. And, if you didn’t write that code, it takes even more thought.
Ruby looks nice and Rails is attracting a lot of attention for good reason. Seaside on Squeak should be attracting attention, because it looks like a very productive way to put together apps. There are two problems with both of these: 1) I don’t know them, and 2) they are less mature and have smaller communities than Python or Java. I can certainly overcome (1), but that would slow me down initially. The clock is ticking, because I need to generate money to pay my mortgage and all that… The second point also means slower velocity: there are fewer places to turn for help. There are fewer prepackaged modules, and those modules may be less-tested.
That brings me to Python. I’ve used Python on and off since ’95, so I have a comfortable familiarity with it. My last go at self-employment was based on work in Python. That was five years ago, though, so there are some new things I need to pick up. I think there are some Java-isms to unlearn as well. But, the ramp-up time with Python would not be as great as with a language that I haven’t worked in.
A bit of opinion: Java sucks. Not Java-the-platform, but Java-the-language. First of all, there’s the whole static vs. dynamic typing argument. Going beyond that, though… static typing in Java is not as safe as it could be. Until Java 5, Collections were dynamically typed constructs (with the annoying extra typing of doing a cast). Autoboxing in Java 5 is a nice convenience feature to avoid manual casting and conversion, but it leaves some ambiguity about what happens if you have a null value.
Java is practically unusable without an IDE, because Java’s implementation of static typing requires a lot of keyboard typing on the part of the programmer. It doesn’t have to be that way. Some statically typed languages use type inference, because the compiler can often figure out exactly what you mean without requiring you to type it in. Here’s an example:
String foo = bar.toString();
The compiler knows that bar.toString() returns a String, and yet you still have to type String at the beginning of the line.
Java doesn’t support operator overloading. Many people call this a good thing, largely because operator overloading can be and certainly has been abused. But, because of this, using a Map requires mapName.get(key) and mapName.put(key, value), rather than the more natural mapName[key] and mapName[key] = value.
Java doesn’t have first-class functions and reflection can be somewhat painful to use. You’re forced to create an interface for every kind of operation that you might want to be able to perform (for example, Comparator). If you use reflection, you have to deal with the painful syntax and you lose your static typing.
Java doesn’t have any kind of multiple inheritance, so mixing in behavior requires using AOP, static utility methods, or using composition and delegation. I do understand how multiple inheritance complicates things, but Java doesn’t provide any convenient mechanism for sharing behavior. Java 5 static imports do provide one mechanism to help here, which is a good start.
Making the distinction between Java-the-language and Java-the-platform is an important distinction. The Nice language fixes all of these Java language problems with the exception of operator overloading. Groovy even includes operator overloading and the ability to be dynamically typed. I’ll come back to these two choices.
What about performance
Java is fast. That’s the bonus you get from static typing… many operations can just become a quick lookup or jump to a memory location. In Python, every name lookup essentially requires a hash lookup. While this is an O(1) operation, it’s still going to be slower than memory referencing.
I can’t find the reference now, but I recently saw someone write that making a language choice based upon performance is the ultimate premature optimization. As long as there are ways to get acceptable performance, the language should be chosen based upon the expected level of productivity.
So, what about Python’s performance? Many people have called it “slow”. I don’t think Python is slow. Sure, it’s slower than Java. But, it’s fast enough on even late-’90s hardware to do many tasks at a speed that is comfortable to users. Depending on your specific needs, Ian Bicking offers some tips for improving your performance without leaving Python.
Let’s assume that Python is still too slow for something you’re trying to do. If you’re using an x86 machine, you can use Psyco to speed up parts of your code with a trivial amount of work. I’m not only targeting x86, though. For me, there’s Pyrex, which looks kinda like Python, but compiles into C extension modules.
Finally, it’s worth pointing out that a lot of heavy lifting in Python is done in C code (and much of that C code is tried-and-true, having been around for a long time). Python itself is written in C, so things like hashtable lookup are as fast as they’re likely to get. If you want to add something like encryption to your app, that would most likely be done by adding a C extension module. This helps contribute to the notion that putting together an app in Python is likely to be fast enough. In fact, Python is popular in scientific circles because it’s easy to write code in and experiment, while the parts that need to be fast are written in C and are plenty fast.
The JVM is fast. Dynamic languages, like Groovy, incur the same kind of overhead that Python does, since name resolution needs to be done at runtime. One nice thing about JVM languages is that if you need more performance, you just switch that bit of code over to Java. That would certainly seem easier than moving that bit of code into C. (Pyrex mitigates this a bit, though.)
The JVM has been shown to be almost as fast as C, but not quite. So, a dynamic language on the JVM will likely be a little slower than a dynamic language implemented in C. Similarly, optimized modules in C will likely be faster than those written in Java. Despite the fact that Python is, without question, slower than Java, I think there are enough optimization options that most apps can reach the performance level needed.
Sun really wants people to have a JVM installed (just as Microsoft wants everyone to have the .NET Runtime). Maybe there are enough people with the JVM installed now that it really isn’t an issue.
Sun has improved desktop integration considerably, which is important for making usable, consumer-oriented products. Kudos on that count.
Though Sun may not like it, the Azureus folks have shown how good Java packaging can be. They used GCJ and SWT to create a solid app that feels like it belongs on the Mac or PC that you’re using.
Python has great desktop integration (you can call Windows and Mac APIs directly, and wxPython provides cross-platform GUIs). Extra nice, though, is that people have put together py2exe and py2app that create standalone Windows and Mac apps, respectively. Since the Python interpreter is bundled right into the executable, you don’t lose any of Python’s dynamic nature.
I’m sure it’s clear by now that I chose Python to implement my project. Of key importance is productivity, and I think that dynamic languages win in that regard. Though I’m using Python, there are plenty of good languages to choose from. Even if you’re targeting the Java platform, I’d recommend checking out the dynamic languages that are available. Some of them are more mature than you might expect and, since they’re written in Java, it’s usually quite easy to figure out how they work and decide if you like the implementation.
Every project has its own requirements. If you’re lucky, you’ll be free to choose the right tools for the job.