November 24, 2009

Scripting Productivity

Now that I'm back in a Big Build environment which takes a while to rebuild and bounce a test server to test your change, I look back on my time using python/django and ask:

Is the productivity gain commonly reported in scripting languages because the language is lighter weight, or is it just because your feedback loop is supertight so you can maintain a laser like focus on the problem at hand?

Maybe if you count the time writing blog posts while rebuilding as productive you're just as productive in a compiled language.

8 comments:

  1. Intriguing question. Back in the day there were C interpreters in order to avoid the whole rebuild time problem, and also do a bit of safety checking so that your wild pointers would drop you into an inspector rather than seg faulting. It's hard to get that right; you pretty much have to let stuff scribble all over memory if it wants to.

    So I think there's still some basic level of safety that you need for productivity. The interesting question is what level of checking, where, is actually helpful? A colleague notes that most of the problems he's found maintaining our TRAC installation (written in Python) are basic type errors, often in the code of the distribution itself.

    ReplyDelete
  2. Having lived in the type-unsafe world, I found lack of type-safety as much of a productivity enhancer as a problem. Not having to slow down and write down what I already knew, basically.

    But then I'm one of the people that when java generics were added I didn't understand because I almost never got something out of a collection I was not expecting, and certainly never when the code was done. Plenty of people hailed generics as their saviors, no more cast exceptions!

    ReplyDelete
  3. The major thing java generics saved was explicit casting which made the code unreadable; I generally viewed them as a particularly smart form of syntactic sugar or a way of avoiding a preprocessing/codegen step, like C++ templates but thornier.

    Python's type unsafety has only really bit me a few times -- the "is this a list of lists or a list of lists of lists" problem can mostly be avoided in the modern age by using vaguely reasonable classes. The major annoyance is that errors are only found at runtime, and then only when the code path is exercised; type correctness is amenable to compile-time validation, and it sucks to lose that. I should probably explore some of the type-safety decorators out there.

    Frankly the lack of (reasonably efficient) const is far more annoying to me than the lack of type checking.

    ReplyDelete
  4. To address the original question -- I think scripting languages can reduce the cycle time a lot under moderately sloppy development practices (ie, without any automated testing), but less so under good practices.

    What slows down the write-build-test cycle with a compiled language is generally called the build phase, but really much of what the compiler is doing is stuff that in a scripting language you would call testing -- finding eg type safety errors that in a scripting language must be discovered at runtime. The situation is made more rather than less vague by the common good practice of running unit tests at "compile" time. Scripting languages save you the compilation time, but you still need just as much testing and, when you factor out the testing that the compiler's error checking is saving you, that's very little time.

    I think the big improvement in development speed of python over C++ or Java is simply that python is a better-designed language for communicating user desires. A hypothetical dialect of python intended for compilation, with e.g. compile-time enforcement of the existing type-safety decorators, would in my view give essentially the same development speed improvements as vanilla python.

    ReplyDelete
  5. Hm, I don't think I believe that the first level of unit tests is replaced by type checking - or at least if it is, I never write those unit tests. Types are checked enough in the unit tests you should write either way. I mean, you can write the unit test that checks that when you put a Monkey into your UntypedMonkeyMap you get one out, or you can just write some tests which use it for Monkey storage in the course of testing.

    ReplyDelete
  6. I agree that if your test coverage is 100%, that's true. But the static analysis a compiler will do is much more guaranteed to cover every case, and I don't like trusting myself to have hit all of those cases.

    I do readily admit that some of the jumping through your own armpit that you have to do in e.g. java generics to express type requirements is pretty goofy; the choice between that and no type safety is a bit of a toss-up. But I have the general impression that that's just Java being pointlessly obnoxious rather than some sort of deep theoretical truth that safe generics will always require a chunk of unreadable nonsense to declare properly.

    ReplyDelete
  7. The new version of Java is going to take a baby step towards being less stupid, you'll be able to leave out the type requirements in the constructor if you just stated them in the variable declaration.

    I played a tiny bit with Haskell over the summer and it's a) completely type safe and b) gets out of its own way about it.

    ReplyDelete
  8. Yeah, Haskell is very beautiful in its own way. I remember finding it profoundly impractical for every task I have actually faced, but that might be a failure of imagination on my part.

    ReplyDelete