Friday, December 16, 2005

Inflammatory Ruby Questions

I have some honest questions for Ruby experts to help me understand where I am on this Ruby debate. Not that any Ruby experts, or anyone reads this blog, but it makes me feel good, ok?
I honestly want to understand why and how Ruby is going to be a revolution. I absolutely love Java, but I am deathly afraid I will my love for it will blind me from seeing the next big thing.

I'd like to seperate Ruby and Ruby on Rails for clarification.

What is it about this language that seperates it from the dynamically-typed crowd? Does it hit the sweet spot between loose typing and "true" OO features? Is it fair to Ruby a great dynamically typed language, and short circuit this half of the discussion as the ancient "staticly versus dynamically typed languages" debate? My point is I dont see much of a difference between "Ruby v. Java" and "Static v. Dynamic typing" debates. Is there something novel Ruby adds to that debate? Perhaps Ruby does for dynamically typed languages what Java did for statically typed languages?

Ruby On Rails:
What does Ruby on Rails provide that other language web frameworks cannot? I'm sure "convention over configuration" is a fantastic innovation for small, simple webapps, but what precludes another framework from mimicking this, such as Trails? I understand Ruby ensusiasts' frustration w/ "XML hell", but that's not a function of Java in the least, but in the frameworks they choose.

If these were both true statements:
"Ruby is the best dynamically typed language available"
"Ruby on Rails is an innovative web framework for writing simple webapps with very little work"
I see plenty of room left for Java.

Tuesday, December 13, 2005

Simple logging improvement

No matter how clever you are about logging, you will run in to problems in production where you need more information. Often times, I'll resort to access logs to try to understand more. I recently made two changes to the default access log format in Tomcat which have drastically increased the utility of these logs. I added session ID (%S) and "Time taken to process the request" (%D). If you take care to log session ID in your normal logs, you'll have a nice "foreign key" into the access logs.

Monday, December 12, 2005

Tiger Beat!

1. Enhanced for loop is pure coding joy, especially in nested loops, but you will be suprised at how often you can't use it: you need the index, special exit condition (I'm not a "break" man), or you have an iterator.

2. Generics will improve your API dramatically. The rap on them is that creating your own generic classes can get messy, and that's true. But it's not _that_ bad, and 99% of the time you are simply using generic classes, which is completely simple.

Before generics, we often deliberated about what type to return when a method produced a group of objects (Not a group of "expensive" objects, like objects read from a database - they pretty much necessitate an Iterator). Arrays were succinct and type-safe. Collections were what the method often used internally and were more flexible, but lacked type safety. For us, in a big system, readability won out, and we chose arrays. Overall, I was happy with the choice, but it didn't sit well how often we'd convert a List to an array at the end of the method. Generics resolved this completely. Now all methods return "generified" collections objects, and we get the best of both worlds.

Map.get/containsKey/remove and Set.contains are NOT generic. Good discussion:

It takes a while to really get used to the fact that generics info is not available at runtime. Once you understand that, you'll find yourself more a user of generics classes than an author of generics classes.

3. java.util.concurrent - Great libraries change how you think about problems. java.util.concurrent is no exception. Simple concurrency problems are now actually simple to solve. I'm able to express amazingly powerful concurrent problems in simple and safe code. I don't know how I lived before ConcurrentHashMap, Executor, Callable, and Future. I now look forward, rather than dread, the next concurrency programming problem.

4. @Override - Love it. Even though I haven't programmed Perl in 8 years, I still get a thrill when the compiler points out a problem I never would have noticed. Errors that @Override solve are pretty rare, but they've saved me once, and that's enough for the "Love it" designation. While I understand it would be trickier, an @Implements would be cool to. @SuppressWarning allows to turn certain compiler warnings on which I avoided in the past, because I didn't want warnings for the handful of "special cases" of a warning.

5. String.contains - Can you believe it? I feel like a Programmer of the Future every time I use this baby.

6. OutOfMemory actually TELLS you what kind of memory we ran out of! Before 1.5, you had to figure out what kind: heap? perm heap? thread stack? They were clearly emboldened by the rejoicing of this fix, and tackled an even MORE amazing problem in Mustang: ClassCastException will tell you what was casted!

7. Thread.getStackTrace/getAllStackTraces. If you run into race condition/locking problems, and don't have the luxury of reproducing in your IDE, a JSP that displays Thread.getAllStackTraces is pretty useful.

8. enums - Typesafe enums are essential for clarity in big APIs, and I hope they get more attention now that they're first class in Java. If you are leary of Generics introducing clutter to API, you won't like this:
public abstract class Enum>
I tried writing a utility method for enums, and it actually set my brain on fire.

Eclipse has a neat compiler option - to warn/error if a switch statement doesn't cover every member of the enum. This is a wonderful tool, as you often want to take an action based on the value of an enum, and it's imperative to cover every possible value of the enum. However, I haven't used switches or breaks since I was a C programmer. I was torn between the joy of a new compiler warning, and the mess that is "switch". I tried and tried, and eventually just had to drop the switch. Its freaky scoping and flow was just too much to swallow.

9. Monitoring - Anybody who's had problems in production will love JConsole and You'll also love System.nanoTime if you've ever tried timing operations with System.currentTimeMills. currentTimeMillis could not measure down to the millisecond, so any "fast" operation would result in times of 0, 16 or 32 milliseconds. Not a problem with nanos!

I'm sure I'm forgetting quite a bit, but in short, I'm in love. Tiger represents a good balance between Sun's traditional conservatism and the pressure they face from their emerging competition. I hope they maintain their discipline as well as their fear.