I spent the last two years working on software for two 8-meter telescopes. To paraphrase Alan Cooper: When you cross a computer with a telescope, you end up with a computer with some mirrors. (I’m sure the dozens of mechanical, electrical, laser and optical engineers who point and focus the 300-ton instruments would disagree, but they’d be wrong.) The observatory had an impressively large codebase of several millions lines of code, ranging from hard real-time to Web applications.
As with all scientific organizations, funding is highly constrained, and the observatory for which I worked was hit hard by the U.K.’s evisceration of its science funding. With fewer than a dozen software engineers divided among operations, real-time, and high-level evolution and development, the observatory had a capacity problem.
All technical problems are people problems, and the observatory admirably pushed toward agile software processes, even in an environment where “governance,” “oversight” and “audit” are at the tip of every manager’s tongue. (And it’s difficult to pull off “software is uniquely challenging” to people developing multi-ton scientific instruments that do stuff like “take photos of planets orbiting other stars.”)
At the technical level, though, there was the feeling that new software ought to be developed in something other than Java, the organization’s historical high-level language. The observatory’s software architect was a big believer in the power of functional programming. In my previous column, I pointed out that, by the straightforward criterion of “functions as first-class properties,” every mainstream programming language either is or will shortly be a “functional programming” language.
Python has first-class functions and was popular with the scientists. So one of the more, let’s say, “passionate” discussions we had was whether Python should be adopted by the high-level software engineering team or whether we should go with Scala. (Long-term readers can rest assured that I tediously mentioned Ruby as an additional option.)
If you read my previous column, you know that Scala was the choice. Last time, I discussed my quite-favorable impression of Scala as a “Java.Next” for programmers. On the other hand, what was compelling about Scala that justified forgoing the familiar, powerful and well-liked Python, and the advantages of a cross-discipline programming language that could be shared between science and engineering divisions? If the answer was not first-class functions, what was it?
And so we get to static typing. Forget all the hand-waving about improved quality and productivity due to category theory and monads and Kleisli arrows; that’s a bunch of crap. (It’s not crap that they allow mathematically rigorous thinking about certain problems. It’s a bunch of crap that productivity and quality follow, as supported in less emphatic terms by Pankratius, Schmidt and Garreton.)
Also, forget all that stuff about “weak vs. strong” or even “explicit vs. implicit” typing. The issue worth debating is the trade-off between static typing (with which the compiler can determine, at compile-time, the range of values and operations of a variable) and dynamic typing (where only at run-time are those aspects fully specified). To me, after two years of statically typed Scala as my primary language, I have come to the following dramatic conclusion: Meh.
Static typing has advantages. The biggest, by far, is the quality of code completion (i.e. IntelliSense), the ability of an IDE to quickly and accurately pop up appropriate functions and parameter lists, and so forth. For a decade we’ve been told that real soon now we’ll have IDEs for dynamic languages with equally good code completion, but the quality gap is still very evident with even the best current IDEs.
Other advantages of static typing include easier comprehension and reading of function signatures, and there is no doubt that this occasionally prevents defects and improves productivity.
On the other hand, static typing has disadvantages. First, there’s the simple observation that the edit-run-debug cycle, at least with Scala and the JVM, is much slower than with a dynamic language. Scala has an interactive REPL, but it’s a far cry from a professional programming environment, and the application on which I primarily worked took about two and a half minutes to build and start. That’s a lot of thumb-twiddling and attention-wandering.
Compilation time is an implementation detail, though, and I think the more fundamental criticism is that static typing forces a certain workflow on the developer. When you change a signature, you must then make satisfying the compiler your next order of business, and you must do this across the entire test suite and module, if not the entire application. You lose the ability to try out a restructuring with one or two tests, or to casually ask a client, “Do you mean this? Or this other thing?” This forced workflow is a real disadvantage; quality-wise, I’ll trade more flexible testing and faster user feedback for “improved mathematical rigor” any day of the week.
Larry O’Brien is a technology consultant, analyst and writer. Read his blog at www.knowing.net.