Archive for May, 2008

Think globally, invoke locally

Recently, both Steve Vinoski (CORBA veteran) and Joe Armstrong (creator of Erlang) have come out strongly against Remote Procedure Calls (here and here).

First of all, it seems to me that when they say “RPC”, they really mean “remote procedure calls that try to pass up as local procedure calls”. Second, this message is not exactly new: ever since the seminal paper “A note on distributed computing” came out (in 1994!), we have known that trying to disguise remote calls as local calls is wrong, and some of the principles described in this paper were consolidated over the years into “The Fallacies of Distributed Computing”, which is also a must-read for anyone interested in this space.

This paper gave birth to RMI and to a whole generation of distributed frameworks based on this very principle: remote calls throw a checked exception in order to differentiate them from local calls and to force the caller to deal with the possible failures that can result from sending a call over a network.

The outrage justifying this string of blog posts is fourteen years overdue, but fine, after all, it’s an important lesson and it doesn’t hurt to repeat it.

Where I’m a bit stumped is that it seems to me that Erlang is built on exactly this false premise and therefore, repeating the errors we made before that paper came out.

The main point behind Erlang’s philosophy about distribution is that you never really know if a process you are calling is remote or local. In Erlang, you should assume that anything can potentially be remote. I’ve always been puzzled by this but I hadn’t put my finger on it until I read the blog posts mentioned above.

Joe seems aware of this problem:

If programmers cannot tell the difference between local and remote calls then it will be impossible to write efficient code.

So why can’t I differentiate a remote process call from a local one in Erlang?

Distributed computing is hard, but is the answer really that we should write our code assuming that *any* process call can potentially be remote? Isn’t this taking this idea to the extreme? One thing that I like with RMI and other similar distributed frameworks is that I have a very precise knowledge of what is remote and what is local, and I can optimize in consequence. On top of that, exceptions let me know when remote processes have died and I can act in consequence (like Erlang’s supervisors).

What am I missing?

Twitter business model idea:

… Display ads on the “Sorry we’re down” landing page.

You read it here first.

140 characters should be enough for everybody

Rails would do itself no harm by conceding that it isn

Return of the Statically Typed Languages

My good buddy Steve Yegge posted quite an article yesterday. It’s the transcript of a presentation he gave at Stanford a few days ago, and the overall idea is that dynamically typed languages are on the rise and statically typed languages are on their way out.

I highly recommend reading the entire transcript, it’s very entertaining and, like a lot of the stuff that Steve writes, filled with insight and provocative thoughts. Unfortunately, this time, just like a supervillain, Steve put his fantastic observation skills and remarkable breadth of knowledge to serve a lost cause. There’s no easy way to put it, Steve, but you’re just wrong :-)

I sent him a reaction email shortly after he posted his article, and he encouraged me to make it public in an attempt to document our two opposing viewpoint publicly. I’m happy to be the Luke Skywalker to his Darth Vader.

Evil shall not prevail.

Scala

First of all, I was initially very excited about Scala until I realized that two features were close to being deal breakers for me: implicits and pattern matching.

Have you taken a look at implicits? Seriously? Just when I thought we were not just done realizing that global variables are bad, but we have actually come up with better ways to leverage the concept with DI frameworks such as Guice, Scala knocks the wind out of us with implicits and all our hardly earned knowledge about side effects is going down the drain again.

As for pattern matching, it makes me feel as if all the careful data abstraction that I have built inside my objects in order to isolate them from the unforgiving world are, again, thrown out of the window because I am now forced to write deconstructors to expose all this state just so my classes can be put in a statement that doesn’t even have the courtesy to dress up as something that doesn’t smell like a switch/case…

About the difficulty to impose a non-mainstream language in the industry

this in the beginning: this is 80% politics and 20% technology, right? You know.

I find this very disingenuous. Steve, you know it’s not true, right? Most of the people around you would love to be able to use the language that they really like, but the cost for the company just doesn’t make sense. I would therefore revise your break down as follows: the reason for not using a non-mainstream language in a big company is 10% politics 10% technology and 80% common sense.

Let me turn the table on you and imagine that one of your coworkers comes to you and tells you that he really wants to implement his part of the project in this awesome language called Draco. How would you react?

Well, you’re a pragmatic kind of guy and even though the idea seems wacky, I’m sure you would start by doing some homework (which would show you that Draco was an awesome language used back in the days on the Amiga). Reading up on Draco, you realize that it’s indeed a very cool language that has some features that are a good match for the problem at hand. But even as you realize this, you already know what you need to tell that guy, right? Probably something like “You’re out of your mind, go back to Eclipse and get cranking”. And suddenly, you’ve become *that* guy. Just because you showed some common sense.

Tools

Not harder to build dynamic tools than for static languages, just different.

I still strongly disagree with that. It is different *and* harder (and in some cases, impossible). Your point regarding the fact that static refactoring doesn’t cover 100% of the cases is well taken, but it’s 1) darn close to 100% and 2) getting closer to it much faster than any dynamic tool ever could. By the way, Java refactorings correcting comments, XML and property files are getting pretty common these days, but good luck trying to perform a reliable method renaming in 100 Ruby files.

Generics

I no longer bother trying to understand why complex Generic examples are so… well, darn complex. Yes, it’s pretty darn hard to follow sometimes, but here are a few points for you to ponder:

  • 90% of the Java programmers (including myself) only ever use Generics for Collections.
  • These same programmers never go as far as nesting two Generic declarations.
  • For API developers and users alike, Generics are a huge progress.
  • Scala still requires you to understand covariance and contravariance (but with different rules. People seem to say that Scala’s rules are simpler, I’m not so sure, but not interested in finding out for the aforementioned reasons).

Performance

I’m actually surprised you spend so much time defending the performance of dynamic languages, because I don’t think it’s worth it. Yeah, they’re slower overall but in the same margin as Java used to be slower than C++, and we know how that turned out. Not much to argue about here in my opinion.

What will keep preventing dynamically typed languages from displacing statically typed ones in large scale software is not performance, it’s the simple fact that it’s impossible to make sense of a giant ball of typeless source files, which causes automatic refactorings to be unreliable, hence hardly applicable, which in turn makes developers scared of refactoring. And it’s all downhill from there. Hello bit rot.

I hate giving anecdotal evidence to support my points, but that won’t stop me from telling a short story that happened to me just two weeks ago: I found myself in this very predicament when trying to improve a Ruby program that 1) I just wrote a few days before and 2) is 200 lines long. I was staring at an object, trying to remember what it does, failing, searching manually in emacs where it was declared, found it as a “Hash”, and then realized I still had no idea what the darn thing is. You see my point…

Javascript

Javascript is on the verge of becoming part of the assembly language family, and toolkits like GWT are making sure that this will happen before too many developers join the pool of low level language victims. I’m sure you can relate to that stigma.

Also, I think you are vastly overestimating how the optimization work on Javascript is going to advance the science in that area. I’m sure thousands of very smart researches are busy doing that right at this moment, but come on: Javascript has become very much good enough for a lot of apps.

And what’s interesting is that, as opposed to Java, Javascript has an upper bound where it no longer matters to make things go faster, because there is only so much you want to do on the client anyway. Gears is even showing us that we can do a decent amount of processing on the client, but so few applications need that that I think the backdoor tricks that GWT uses (such as image bundles) are much more clever and much more useful than any of the stuff that you show in these slides.

Emacs

You know, even Emacs has to evolve.

No: it’s Emacs users who have to evolve.

Error messages

And the weird thing is, I realized early in my career that I would actually rather have a runtime error than a compile error.

You probably already know this, but you drew the wrong conclusion. You didn’t want a runtime error, you wanted a clear error. One that doesn’t lie to you, like CFront (and a lot of C++ compilers even today, I hear) used to spit in our faces. And once I have a clear error message, I much prefer to have it as early as possible, thank you very much.

Trace trees

The PDF link is broken.

The dynamic nuclear winter

And everybody else went and chased static. And they’ve been doing it like crazy. And they’ve, in my opinion, reached the theoretical bounds of what they can deliver, and it has FAILED.

Quite honestly, words fail me here.

Flamewar

Finally, the largest flamewar that I ever witnessed involving Stallman was when he dissed XEmacs on comp.lang.emacs and it quickly turned out in the discussion he hadn’t even launched the darn thing. Get your history facts straight!

Conclusion

Interestingly, I am currently working on a brand new presentation on this very topic that I’ll be making at Jazoon next month. I’m still working out the details, but this presentation will take a quick tour of the dynamic landscape, contrast it with Java and argue that statically typed languages in general and Java in particular have never been in a stronger position to remain the language of choice for large scale software for the decade to come.

Hope to see some of you there!

Breaking free from the tyranny of languages

I recently came across this documentation page from the .Net API.

I was investigating the possibility of creating a Map that would allow String keys to be case insensitive in Java. Neither the language nor the standard libraries allow you to do this easily at this moment, because 1) hashCode and equals are methods that are defined on Object and 2) all the collection classes use these methods directly. Therefore, I was wondering how hard it would be to extract these two methods in an external class (you could use a Trait in Scala) and delegate these calls there instead of on the objects themselves.

This idea is not exactly new and it would be pretty easy to implement, and as you can see from this page, it is already supported in .Net.

But that’s not what caught my eye.

Do you notice anything special on this page? Look again.

The key here is to realize that this is not a “C# page” or a “Visual Basic page”. It’s “.Net documentation page”. And for this reason, it describes the functionality in general terms and then it gives specific examples in not one but five languages.

Maybe I’m easily impressed, but I find this amazing.

Here is the deal: I have always been a fan of COM. Since day one. Well, not exactly day one since the early days of COM in C and C++ were extremely painful, but I certainly saluted the ambition behind the idea: trying to make all Windows applications 1) accessible from the outside and 2) from any language. Until Microsoft created COM, this goal had never really been achieved by any technology.

Fast forward thirteen years: COM has morphed into .Net, the complex COM binary interface is now hidden behind a neat virtual machine with a powerful bytecode set, and the dream of writing applications independently of languages is a reality on the Windows platform. Hats off to Microsoft.

Now, where does that leave us, Java developers?

Well, we have achieved an independence of sorts, although it happened much more by accident.

Microsoft built its framework with a clear vision that was spelled out around 1995 and that took many years to carry out. Java, on the other hand, started with a clear focus on the language, with the JVM and the bytecode as a simple foundation to make it easier to run Java programs on several platforms (actually, event the intent for the JVM has changed over the years: it was first designed to run on embedded devices, then in web browsers as applets, and it finally found its true vocation on the server, something that Sun never saw coming).

What’s interesting in this story is that not only did Java emerge as a superstar of languages, but it slowly and surely dragged the JVM and its bytecode into the spotlight as well. The versatility of the original design should certainly be saluted, but it’s eventually the formidable Java ecosystem and its users that took the JVM to heights never envisioned.

It started innocently with a few experiments that generated bytecodes to alter existing classes or to create new ones on the fly, and it’s now culminating with not only some of the most innovative frameworks I’ve seen in years, but the JVM has also the foundation for a multitude of new languages that not only run JVM bytecodes but that also interoperate seamlessly with the Java platform.

In a way, Java has enabled language independence as well. It’s not as extensive as .Net, but it certainly runs on many more platforms.

First steps with GWT

I recently spent some time porting a SWT application to GWT, and it’s been a real pleasure. Ever since I heard about GWT, I have been very eager to put my hands on it and try it for real. Pity it took so long.

First of all, why all this interest on my part? It’s simple really, and I can summarize it in one sentence: I love the idea behind AJAX and dynamic web pages but I don’t like Javascript.

Don’t get me wrong: I know it’s a great language and I’ve always had good success and rewarding results whenever I have taken the time to write a few lines of code to solve a few minor problems on my web sites, but the perspective of writing entire applications in this language has been a very big turn off for me, so I’ve been avoiding it. Anyway, I’m not going to go into details since it’s not the topic of this post. Let’s get back to GWT.

Ever since AJAX became popular, I have waited for the second generation to emerge. By “second generation”, I mean whatever tools or languages that would save me the trouble of having to 1) program in Javascript and 2) deal with browser compatibility hell. In other words, to me, Javascript and XmlHttpRequest is assembly language, and I draw a lot more satisfaction writing code at a higher level.

Enters GWT, which promises to let me use my favorite development tools (Java and Eclipse) to the fullest (well, almost) while leveraging AJAX without any restrictions. Sign me up!

In the coming days, I’m planning on posting in more details about my experience with GWT, both philosophically and technically. GWT has been out for quite a while now, and there are plenty of tutorials, books and articles describing all its features, so in an attempt not to repeat all of this material, I’ll try to stick to a few original details and tidbits that I came across.