Epiphany

I just fully realized something that's been rattling around in my head for a while. Static typing in OO languages isn't the solution to software complexity, rather it's an enabler of it. Static typing is like giving a drunk a bunch of breath mints and saying "Don't drive drunk. But if you must, use these breath mints in case you get pulled over."

The problem is static typing tends to encourage large, complex framework-like interfaces, instead of the decoupled, modular interfaces everyone desires. The irony is, if your interfaces are small and simple, then static typing offers you very little benefit. Static typing works best when there is lots of complexity, but like breath mints for a drunk, we are just making it easier to get away with what we know to be a mistake anyway.

Posted June 10, 2008 7:06 PM

Comments

delayed-typechecking languages are 'you might be drunk, we dont care. if you get in a wreck we'll tell you what your level was..'

carmen, June 10, 2008 9:22 PM

Static typing is in no way related to large complex interfaces. Take a look at some Haskell-modules, which are typed using a type-system that's a lot stronger than, e.g. Java's, but still are super-expressive, concise and simple.

The other thing I like about types in Haskell is that they help you think about what your program should do. Once you have the types in place, the implementation follows trivially (most of the times). I can definitely recommend you to check it out, program in it for some time, and see if you convince yourself that, in some cases, static types are convenenient. Have fun!

Chris Eidhof, June 11, 2008 2:37 AM

Hey you. Don't go reading my mind. ;-)

Javascript don't needs to get every "feature" from the rest of the languages. If I need that I simply change to C++ or Java. Don't do Javascript a dirty language. Its simplicity has take it to what it's today. Ecmascripters: Select the 3 more javascripty features from the ecmascript proposal (like imports) and throw the rest to the paper bin. PLEASE!

alsanan, June 11, 2008 4:00 AM

I could not agree more. Types are things of the past. They used to be useful to improve quality and manage complexity.

Historically, first there were "micro" tests, using types. Compiler enforced. Some people still trust them.

Later came class level unit tests, using test suites, TDD and BDD. Socially enforced (not so much actually, getting better). "Where are your tests?" is becoming an insult!

But this is all rather primitive. What will be the next phase?

I think that next will come system level tests, where it is whole use cases that are tested, against regression. But not the "old way", manual. Tests are useful if run automatically only.

The number one benefit of automatized tests, either unit tests or system tests, is refactoring.

Tests are a safety net. Without tests refactoring is looking for trouble. "Why did you change it, it was working, now it is broken" is something you won't hear if you have good regression tests.

Refactoring is the only tool we have to grow a piece of complex software over time. Without it, software systems collapse under their own weight.

Type systems in compiler should be understood for what they truly are: Optimizations. Little more than the old C keyword "register".

Type inference, either at compile or run time, with user provided "hints" sometimes, is the only place where type should matter.

In Eiffel Bertrand Meyer introduced contracts, with pre/post conditions and asserts. That is a good thing too.

At the conceptual level, Duck typing is the right way to go. Static typing is a speed optimization.

JeanHuguesRobert, June 11, 2008 4:01 AM

http://digitta.com/2008/06/blog-post.html

translated to spanish, btw.

alsanan, June 11, 2008 4:20 AM

Damien,

Can you elaborate a little further on what you see is the problem with using a statically typed language and the relationship that compile time checking has to do with large, complex framework-esque interfaces?


I don't see the correlation but I'm more than open to discussion on it.

Al.

Al, June 11, 2008 4:26 AM

I counter with "How I lost three hours of my life to dynamic typing." http://timepedia.blogspot.com/2008/06/how-i-lost-3-hours-of-my-life-to.html

Here I use a simple, modular, dynamically typed Javascript API, Google's API Loader. It takes 3 arguments. Two are strings, the third is, well, that was the problem. It's a callback closure, only it's not. A simple typo, three hours up in smoke. Yeah yeah, RTFM you say. If only everyone was perfect at documentation recall.

Unit tests? Not helpful to this case. First, I am not responsible for the Google API loader, Google is, and I am not privy to their unit tests. My own tests of course could report failure, unless of course the test itself is written wrong because of a typo. The problem isn't just detecting the failure, it's diagnosing it in this case, when all tools of debugging are taken away from you. This is just one example of consuming a third party API written by someone else, an API that is extremely simple and modular, and a mistake that would never be made in a statically typed system.

Moreover, far too many people confuse manifestly typed languages without type inferencing with static typing in general. Take a language like Scala, type inferenced, and better than Ruby in DSL creation, and you can get away with writing what looks like duck-typed code that turns out to be strongly typed. You can do the same in ML or Haskell (even better than Scala at inferencing)

. It turns out there's a kind of Freudian slip, let's call it Knuthian-slip, going on, when people, especially Ruby/Python devs criticize "static typing" what they really are saying is "Java typing" :) I think many people will agree that Java's type system is a pig, but you can't use it to condemn all of static typing.

Personally, I think framework-itis is a symptom of platform maturity, not typing. There is no shortage of web frameworks for dynamic languages either. There's a kazillion for Javascript alone.

Ray Cromwell, June 11, 2008 5:24 AM

The flip side to "dynamic typing cost me three hours" is that explicit static typing is costing me several hours every week, by design. As I write this I am procrastinating before creating yet another named class with a couple of named fields so that I can get the equivalent of what in Python wold be a list of tuples, requiring zero lines of declaration and constructed with a simple [] rather than "new List()". This adds up to hundreds of lines of extra code so that I can tell the compiler what it should be able to work out for itself.

Static typing is not a problem in languages like Haskell that allow for implicit typing with inference. Haskell's type system is also sophisticated enough that thinking about types can give you insights in to the problem you are working on. The type systems in Java and C# mostly get in the way.

Damian Cugley, June 11, 2008 6:15 AM

In my previous comment, for "new List()" please read "new List‹TemporaryTupleType›()".

Damian Cugley, June 11, 2008 6:22 AM

After being both an author and consumer of libraries in Scala, I've found that as a consumer, I worry very little about types because the type inferencer takes care of most of the work for me and the ScalaDocs tell me that a particular method takes a String, a List, etc.

As a library author, I care very deeply at types. I care about making sure that when I want a time span, the consumer can send me lots of things and I "do the right thing". When I want to make sure query parameters are right, that the consumer can only pass in the right things (Strings for Strings, Dates for Dates, etc.) But, I do make sure that things can be logically coerced so the consumer sees the flexibility.

Scala's type system (and what I've seen of Haskell's) really does make one think. I've had amazingly productive days writing 3 or 4 lines of code as a library author because I've gotten the types right. When I (and others) go to consume those libraries, I'm more productive than I am in Ruby.

David Pollak, June 11, 2008 9:54 AM

Java's type system seems designed to discourage difficult concepts rather than complexity. It encourages systems that are understood through a gradual connect-the-dots style of comprehension rather than the eureka! moment of grokking smaller more purpose-built architectures.

Gabe da Silveira, June 11, 2008 11:02 AM

There is no need for the temporary tuple type if you don't want type checks, for example, for a homogenous tuple, you can just

return Arrays.asList("Foo", "Bar", "Baz")

or with static imports just

return asList("Foo", "Bar", "Baz");

You could also make a heterogeneous utility constructor

public static List list(Object... items) {
ArrayList a = new ArrayList();
for(Object o : items) a.add(o);
}

Then, with a static import you can write

return list("John Smith", 85000, Sex.MALE);

Needless to say, this stuff is trivial in Scala.

Ray Cromwell, June 11, 2008 11:57 AM

As I've said before: Static typing prevents certain kinds of failures, unfortunately it also prevents certain kinds of successes.

Ned Batchelder, June 12, 2008 7:43 AM

I get the best of both worlds by using a dynamic language but enforcing type-checking when it's important. For a lot of methods, you don't care if you are passing in an object of a specific type (or you only care a little as in it should be an array or a hash but it doesn't matter which).

In languages that have strong typing, I have no option except create a method for each type of argument that I expect. Sometimes this works, but it gets impossibly cumbersome when you have lots of different combinations of arguments. Some of the APIs are riduculous because of this.

I'm using Ruby but I built a nice little library that helps.

def some_method( name, friends )
name.arg.is( String, Symbol )
friends.arg.is( Array, Hash )
end

You still get the flexibility of doing no type checking. I also built in more advanced type-checking including the ability to set defaults, check hash keys, check for nil (null) values, etc.

I agree with the poster that said he wasted part of his life due to a type error. I like catching things early too but I hate the complexity added by enforced type checking on everything. I prefer to control when/when not to do it.

Sunny Hirai, June 23, 2008 1:10 AM