Thursday, April 10, 2008

Dream Programming Language: Optional Interface Methods

Yet again, I find myself disliking abstract classes. I was creating a subclass of Java's OutputStream called PathalogicallyBufferedOutputStream (for testing purposes). I wanted to implement flush, which Eclipse nicely autocompleted to look like this:
@Override
public void flush() throws IOException {
// TODO Auto-generated method stub
super.flush();
}
That gave me enough pause to wonder... do I actually need to call the super method. It seems that I have 2 choices:
  1. Check the documentation
  2. Read the source code
Fortunately, Eclipse makes it easy to browse the JDK source code. It only took 2 seconds to verify that the base implementation, in fact, does nothing. Without Eclipse, I probably would have ignored it.

The no-op method stub is in the base class so that consumers of any OutputStream can indicate when the bytes that they have written so far form a semantically meaningful chunk. Somebody might be waiting for some data; this allows you to get it to her. The problem that I have as a deriver of OutputStream is that, without source code or good documentation, I have no idea whether I should or should not call the base method. This is not a problem with JDK-provided classes, but it could be a real bear with a third party library.

Some people might claim that you should "always call the base method". If course, that raises the question of at what point one should call the base method. Should you call it before or after your code? Perhaps you call it in the middle. I prefer to assume that I never have to call the base method, because I shouldn't be deriving from concrete classes, and I like to assume that method that I am overriding is simply a stub that I am free to customize.

If I were designing a language, I would want some notion of "optional interface methods." I want methods that I can declare on an interface (or perhaps an abstract base class) which implicitly have a no-op implementation. If I choose to implement one in a subclass or interface implementor (because I want to be notified when something happens), I would get the benefit of code completion. The caller is not burdened with the need to check to see if I've implemented the method, and the implementor is not burdened with the uncertainty of whether or not to call the base method.

Why Message Passing?

Back at the end of March, I was starting some work on Ruby on Rails. I thought that a good April Fool's Day joke would be to release "Lua on a Luge" or "Lua on Skiis" (somebody came up with something even better). As the people that I work with know, I'm a big fan of Lua. I appreciate the things that it does well (prototype-based programming, and having very simple, consistent syntax). Even more interesting, though, are the things that it doesn't try to do:
Lua does not try to help you write programs with hundreds of thousands of lines. Instead, Lua tries to help you solve your problem with only hundreds of lines, or even less. - Programming in Lua - Preface
In any case, Lua doesn't directly support multithreaded programming. Normally, this would be fine. However, I've worked on some .NET and Java web apps that:
  1. Spawn a background thread to do some work
  2. Handle multiple requests at once
  3. Share some object / data between all of the request-handling threads
What kinds of things might we share? We might share configuration information, we might share connection pools (of connections, or threads, or whatever), we might share session information. Anything that is shared must be concurrency-safe.
Java and .NET provide synchronization mechanisms. Lua does not.

I started to think about various ways to solve this problem. One could expose a C threading library to Lua. You could expose both the thread management and synchronization primitives. Then, you could only share objects that are specifically written to use that threading library. You might also be able to inject metatables into arbitrary objects, but that would only go so far.

Then I realized that I already knew a better approach. If we relied on simple message passing between Lua processes, we could avoid the need to synchronize every shared objects - no objects would actually be shared (we might copy all values that get sent along on a message, or restrict the kinds of values that may be sent on a message).

It would probably not be as efficient as Erlang's message passing.  Also, I don't know of any Lua implementations other than the reference implementation and World of Warcraft's implementation, but I doubt that either support lightweight processes (instead, both implementations provide coroutines).  Incidentally, Ruby on Rails is currently not thread-safe (other Ruby web frameworks apparently are, according to the Mongrel FAQ). At least one Rails guy thinks that it should remain that way (see slide 115).

Dream Programming Language: No Static Fields

If I were to implement my own OO programming language, static data would be the first thing to go. I can't find any compelling reason to keep it around.

Something that people may or may not undestand is that static really means "global". Seriously, I wish that languages like Java and C# simply used global as the keyword instead. Static methods are simply global methods that have a long name with a period in the middle (well, I suppose they are also scoped and are subject to access control). Static, final references to immutable objects are just that - they're global constants. Keeping a single definition of PI around is generally a good thing. And, you guessed it, static fields are simply global variables in disguise.

"But!" I hear you say. "But I need static fields to implement singletons!" Why do you want singletons? Sure, you might think that you will only ever want a single instance of a class. I think you're wrong. What happens when you want to do some unit testing? What happens when the requirements change.

At one point, I'm sure that Windows assumed that it had exactly one display. If singletons had been widely used then, I would not have been surprised if there were some singleton which kept the display's information (in actuality, it may have simply been a global variable). Today, we might not only have several physical displays, but we might also have multiple active windowing sessions on a single Windows server. How about mice? Surely, a system has no more than one pointer. Well, that's kinda true, but my coworkers and I wish that we could get a second pointer on the screen for our pairing sessions. What about my Wacom tablet? And my friend prototyped a game that was controlled by using two mice. Singletons are the antithesis of what the Dependency Injection folks have been telling us.

If I were designing a language, I would want the programming language to encourage good programming practice. Since I'm the one designing this language, I get to choose what is good and bad. And I say, "down with singletons!"

Sunday, April 06, 2008

Message Passing

Anybody who has tried to do multithreaded programming in Java, C#, or most any C-based language finds that it can quickly become nightmarish. Deadlocks, race conditions, lock management - all of these issues will occur. In Java, all threads are able to share objects. As a result, the programmer is responsible for ensuring that his objects can't be put into an invalid state. Java provides per-object monitors to enable this. However, working with such monitors can be a nightmare. Using notifyall when you should have used notify, or forgetting to add the synchronized keyword to a method declaration, or incorrectly assuming that a class was thread-safe when it wasn't; these are all examples of simple problems that can cause your application to fail (perhaps only sometimes).

Erlang, on the other hand, does not suffer the same problems. Instead of sharing things, Erlang processes (which are the Erlang unit of concurrency) do not share anything. As a result, the need for synchronization goes away. Erlang processes send messages to each other. Each process has a mailbox. Each process can retrieve and process messages from its mailbox. You can imagine that a message is copied when it is put into another process' mailbox, but in actuality, since data in Erlang is immutable, the system is probably able optimize that away.

One of Java's founding principles was that manual memory management is complex, and thus easy to get wrong. Far simpler was to provide a system where the programmer didn't need to worry about such things. Erlang does for concurrency what garbage collection did for memory management - it removes that responsibility from the developer. Instead of asking every developer to handle any threading issues that might arise, it provides an abstraction that hides all of them. Behind the scenes, Erlang's mailbox system does whatever synchronization it needs to do in order to be completely thread safe.

Of course, Erlang's approach isn't perfect. Just as Java's garbage collection can sometimes allow memory to leak (when you are holding onto a reference longer than you need to), Erlang's system could still be susceptible to problems such as deadlocks. However, it is less likely to occur, and should be more obviously solvable when it happens.

Erlang's approach is so radical, yet so simple, that it's definitely worth learning more about. I hope to see Java and C# projects adopt Erlang's philosophy when appropriate. In performance-critical applications, manual concurrency management might be the way to go. For most purposes, though, the safety provided by Erlang's approach outweighs any negative side effects.

Wednesday, April 02, 2008

GameStop culture

Unlike some people, I actually have a decent GameStop nearby. The people who work there are intelligent, useful, and just generally pleasent. I was there tonight, picking up a copy of Condemned, which I have heard good things about.

In any case, the clerk was telling me that its sequel is also good, and noted that it is more of a horror game (Condemned being more of a thriller). As I was leaving, he suggested that, if I beat it in less than a week, I could trade it in towards its big brother. I thought he said something about full credit.

This struck me as odd. Here was a Gamestop employee essentially offering to loan me a game for a week, with no risk to me. Well, I suppose I would be turning $17 of hard currency in GameStop store credit, which is good for them, but it still seems odd. Then again, their whole business model is odd.

On the other hand, perhaps I simply misheard him.