Starting some time around 2005, under the influence of Perl, Python, Erlang, and Ruby, I became convinced that application programs should be written in dynamically-typed languages. You get it built faster, there’s less code to maintain, and the bugs are no worse. I’ve felt negative not just about statically-typed tools in general, but about the Java programming language in particular. Living in the Android world has forced me to think about this more.
The Old Argument · It’s remarkable that, fifty or so years after “Software Engineering” joined the mainstream, we have so little consensus on these issues. There are many people, including some here at Google, who think that doing large-scale software engineering without recourse to static typing is unprofessional, verging on malpractice. There are others, particularly in the community of Web builders, who think that static typing in general and Java in particular are evidence of old thinking and low skill.
Millions of words have been spent on this debate, but here are a few of the highlights as bullet points; I’ll use “dynamic” and “static” as a shorthand.
Dynamic gets systems built faster.
Static gives you a richer toolset for specifying interfaces, which encourages modularity, particularly in large systems.
Dynamic produces less code. Less code is better.
Static programmers use more advanced IDEs with strong refactoring support; this eases maintenance and reduces the burden of the extra code.
Dynamic developers have a strong unit-testing culture, partly because they lack the static-typing crutch; this supports fearless refactoring.
The Java language in particular suffers from excessive ceremony and boilerplate. Also it lacks important constructs such as closures, first-class functions, and functional-programming support.
Static software supports optimizations that allow faster performance.
Static software typically exposes shared-mutable-state threads, and experience shows that application developers have difficulty understanding and using these correctly.
Recent News · All that aside, I kept noticing that while I was working on Android apps, the fact that I was writing Java code wasn’t bothering me that much. But I couldn’t work out why.
Then, in the last few months, I’ve been working on a revision of LifeSaver, which involves Android code (in Java of course) and App Engine code, which is in Ruby (Sinatra-based, via JRuby). The contrast between the two couldn’t be sharper. And somehow I’m comfortable on both sides.
This had been rattling around in the back of my mind like a poorly packed object in the trunk of your car. Then last September a gentleman named Ricardo Bánffy, whom I haven’t met, tweeted It’s really interesting how writing Java for Android is not painful like writing Java for web apps.... Which dragged it into the spotlight where I couldn’t not think about it.
These days I’d never consider using Java for a significant Web-dev project; but it seems a comfy fit for my Android app code.
What’s the Difference? · I mean between mobile-device and Web-side programming. Let’s start with API surfaces. In a Web app, at a minimum you have to deal with:
The low-level OS interfaces: files, processes, memory, sockets, and so on.
A persistence layer; files or SQL or postrelational distributed hashes or some combination.
The Web machinery itself: HTTP and cookies and ETags and authentication.
Here’s a picture:
Now you can, if you choose, load up on tangled towers of ORM and dependency-injection abstraction and FactoryFactoryFactory joy, but these are often part of the problem not the solution, and you can do anything the Web can do without going near them.
On the mobile side, things are different. In order to use the device’s facilities fully, you have to deal with those same three basic things and a lot more besides:
More radio interfaces, potentially: WiFi, NFC, and BlueTooth.
A GPS and compass and maybe altimeter.
Audio gear, including speakers and a microphone.
A camera, with a sensor and lots of controls.
Last but not least, a vibrator.
Testing · Another observation that I think is partially but not entirely a consequence of API scale is testing difficulty. In my experience it’s pretty easy and straightforward to unit-test Web Apps. There aren’t that many APIs to mock out, and at the end of the day, these things take data in off the wire and emit other data down the wire and are thus tractable to black-box, in whole or in part.
On the other hand, I’ve found that testing mobile apps is a major pain in the ass. I think the big reason is all those APIs. Your average method in a mobile app responds to an event and twiddles APIs in the mobile framework. If you test at all completely you end up with this huge tangle of mocks that pretty soon start getting in the way of seeing what’s actually going on.
Criteria · Let’s call them the Bánffy-Bray criteria for selecting between static and dynamic type systems.
Static typing’s attractiveness is a direct function (and dynamic typing’s an inverse function) of API surface size.
Dynamic typing’s attractiveness is a direct function (and static typing’s an inverse function) of unit testing workability.