Sunday, February 11, 2007

Part 4: The Killer App

Technologies get adopted when there is a compelling reason. People bought PCs for the killer app; game consoles sold for the killer game. Programming languages take off because they have a killer feature. Philip Wadler pointed this out nine years ago:
Instead, experience shows that users will be drawn to a language if it lets them conveniently do something that otherwise is difficult to achieve. Like other new technologies, functional languages must seek their killer app.
Java was adopted largely because it was easy for C++ developers to pick up, and offered killer features like cross-platform development and garbage collection. So what is the killer feature of the next language? I'll take a shot: the complete and final eradication of undefined behavior.

No Behavior Left Undefined
"Undefined behavior" is the biggest euphemism in software engineering. It even beats out "non-trivial problem". It's why your code works great on your laptop, but every one of your users runs a DeathStation 9000. Amazingly, most mainstream languages still have areas where behavior is undefined and unpredictable.

Fortunately, modern languages have made great strides as compared to, say, C++. However, we still have a long way to go. The big problem these days is race conditions caused by improperly synchronized code. And it looks like concurrent programming will only become more common.

What makes undefined behavior particularly evil is not that it might fail; it's that it might succeed. We want incorrect code to consistently fail. This way every time we find a bug we can isolate it with a unit test and ensure it never happens again. But undefined behavior shoots a hole in this: we can have incorrect code that passes every possible unit test. The result is bugs showing up in the worst possible place, production.

Consider the practical implications of working in a language without undefined behavior. If we can create a reliable unit test for any bug we find, we can guarantee that bug never recurs. Good development practices can cause defect counts to trend towards zero. It also makes development itself easier by strengthening our firewall against complexity. Although we'll never eliminate buggy code, hopefully we can create enough stability to prevent bugs from spiraling out of control, which has led to the death of many projects.

Where is our new language?

The first three posts and this one describe an ideal for a new programming language. Many details were intentionally left out to focus on the essence, so many language styles might work. Now I have a question for you: what current or upcoming language best meets these ideals? Much of this exists in part in Haskell, Erlang, Ruby, Scala, F# or others, but I know of no language meeting them all. I hope that will change soon.

Thanks to everyone who made it through these posts. I do want to hear your thoughts.

4 comments:

noah said...

Earlier you implied that OOP was good because of the physical meaphor it makes available for talking and reasoning about code. Unfortunatly that same physical metaphor tells us what happens when you unleash a lot of independent interacting parts, either something trivially boring or in the context of todays article terrifingly undefined. Functional languages get around this with type constraints but adding those to an OOP system would create strongly coupled objects the consequences of which would be worse then the complexity. Do you have a third way or do you think a non-OOP language can come to dominate given the current political landscape?

Sid said...

In a related vein, check out Steve Yegge's post on what the "Next Big Language" needs to have to succeed.

Ryan Brush said...

In response to Noah's remarks, I do belive the physical metaphor in Object-Oriented languages helped them get adopted, but we can still do Object-Oriented constructs a lot better. It may come down to co-opting OO ideas into a functional languages, but restrict shared mutable state of objects, reducing the number of moving parts. I talk a little bit about this in the post on building a firewall against complexity.

There isn't anything inherently wrong with objects, as long as we can find a way to bound the state space like functional languages.

Sid, thanks for the link to Steve Yegge's post. That post is focused on different aspects of language design than the set I posted, and is definitely worth reading.

Mathias Gaunard said...

I don't erally see what the problem with objects is.
You just need to use scope-bound resource management, also known as RAII.