Many people are dabbling in functional programming these days. Haskell is more popular than it ever has been, OCaml has it's adherents, and we are starting to see common functional idioms spread throughout the industry.
Why am I not happy?
Here's why. I think that most functional programming languages are fundamentally broken with respect to the software lifecycle. I realize that's a bold statement. Let me back it up.
Imagine these lines of code in any object-oriented language (I'll use Java here because it is familiar to most people, even if they dislike it):
public class X {
public void method() {
...
badMethod();
...
}
...
}
Class X has a method named badMethod. The method isn't bad because it does something awful while the system is running; it's bad because it does something painful during testing. It could be anything. The method could make a call to our production database and update it, or it could communicate with another system across a socket. It could even touch some low level hardware that causes a mechanical machine arm to do something that it shouldn't be doing over and over again while we are testing.
In an ideal world, people would design their systems so that classes and clusters of classes could be tested independently; the industry is slowly rediscovering the utility of unit testing. But, stuff happens. People make mistakes. They think that they've got it all under control until they discover that they have a big wad of code that they can't easily change and don't understand. At that point, they wish that they could write little tests that help them understand what the hell their code does before and after they change it.
The nice thing, so far, is that most of the object-oriented languages out there leave you an “out.” You can use the features that were built in to provide flexibility to give yourself enough maneuverability to test. In short, we can do this:
public class TestableX extends X {
void badMethod() {
// do nothing
}
}
We can override functionality and build ourselves a wedge that makes testing easy.
The fact that badMethod is a non-final, override-able method makes it something I call a seam. A seam is a place where you can substitute one piece of functionality for another without editing. Most languages provide seams. The C programming language is rich with them. You can use the preprocessor, function pointers, and link substitution to replace awkward functionality during testing, but it isn't quite as easy as it is in OO.
Virtual function calls in OO languages are a common seam. Java is easy. C++ is a bit more awkward. Ruby and Python are a breeze. The power of these seams is in the fact that you can get between around around the pieces of your application when testing. It isn't just a big hard-coded mass.
What about Haskell, OCaml, and Erlang?
Yes, you can provide alternative modules to link against, but it's clunky. Sure, you can use virtual in OCaml, but who really organizes all of their OCaml code in classes?
Haskell is a bit nicer, most of the code that you'd ever want to avoid in a test can be sequestered in a monad, and I expect that half of the Haskellers reading this will argue that functional purity obviates any need to unit test; it can all be done in QuickCheck. I hear you, but there's distance between here and there and that distance can be a quagmire.
No, the fact is, the late-binding that OO languages provide makes code written in them more easily recoverable. And, this is important because entropy happens. Count on it.

