The Perils of Duck Typing?

In The Perils of Duck Typing Cedric writes about some fears he has related to duck typing.

He says

Duck Typing is a big time saver when you write code, but is it worth it? Don’t you pay this ease of development much later in the development cycle? Isn’t there a risk that you might be shipping code that is broken?

The answer is obviously yes.

The proponents of Duck Typing are usually quick to point out that it should never happen if you write your tests correctly. This is a fair point, but we all know how hard it is to guarantee that your tests cover 100% of the functional aspects of your application.

There is certainly a risk that you will ship broken code. In fact, you will almost certainly ship broken code. But you will ship broken code regardless of typing model you use. Static typing is no solution to the problems of defects. But the fact that you saved a lot of time by using duck typing in development means that a) you can send a little more time on testing and there by reduce number of defects you ship, b) get to market earlier or c) both. The fact of the matter is that type related error do not happen often enough in practice to make them worth worrying about (when is the last time you got a ClassCastException while working Java collections).

Cedric goes on to describe the use of interfaces as documentation (using interfaces to document what methods must exist for a piece of code to work) while implying that duck typing prevents this. Interfaces as documentation is a nice use of interfaces but duck typing does not preclude this. Smalltalk has SmallInterfaces. In Ruby, MixIns are commonly use to define the set of methods that are required. But both of the environments are duck typed. In Ruby, for example, if I create a MixIn to define an interface, you can “implement” my interface merely by implementing the appropriate methods, regardless of whether you include my MixIn or not. Interfaces as documentation should be treated just like all other documentation — when it is helpful use it, when it is not ignore it.

To be fair, Cedric likes Ruby because you can used MixIns to define interfaces, but I think his has conflated two completely separate issues. Duck typing does not preclude well documented interfaces. You can poorly design and document an interface a statically typed language just as easily as you can in a duck typed one. You should take care to reasonably document the interfaces you use, regardless of the type system.

5 thoughts on “The Perils of Duck Typing?

  1. Interfaces have to be the most overrated, useless feature in programming history, and we have Java to thank for it.

    It’s weird how all the Java folks coming to Ruby or Python immediately start clamoring for interfaces. Eventually I think they’ll grow out of it once their mind bends to a dynamic, rather than static, mindset.

  2. Daniel,

    I don’t think I agree. They are certainly overused in Java world, because the language practically demands their use in inappropriate places. But I think a published interface is a useful tool in many situations. It gives single place where people can go to see what methods they need to implement to work with your code. It is really no different than writing a really good method or class comment but I think a MixIn or equivalent can often be easier to understand. And you can often implement most of the needed methods based on just one or two base methods, so that people who want to implement the interface only need to provide a few methods but get the rest of the interface for free.

  3. “It gives single place where people can go to see what methods they need to implement to work with your code.”

    How is this different than putting “You need to define methods X, Y and Z in your class” in a text document? If you need to *force* the issue, then you simply provide a generic test suite that your class must pass, with the appropriate documentation that says, “Your class must pass this test suite”. This is the approach Rails took with regards to creating DB adapters.

    In the ideal case, you just mixin a module, and don’t have to define any methods – they’re not only defined, they actually *do* something. Interfaces are a straightjacket that just don’t have any place in dynamic languages.

    BTW, I wrote an “interface” package (with much help) just to show the Java folks that you *can* do interfaces in Ruby if you *really* want to, though I don’t recommend it. It’s listed on the RAA if you want to take a look. ;)

  4. I think a interface is not different than “You need to define methods X, Y and Z in your class” but in the comments is it sometimes nicer to say “this arg needs to look like Foo” rather than “You need to define methods A, B, C D, …, X, Y and Z in your class” and then providing a reasonable descriptions of the behavior of all of those methods.

    The idea of using unit tests to define an interface is a very nice idea. It is probably quite a bit better than a “simple” interaface definition like you find in Java, etc. because it would allow you to test, and thereby specify, required aspects of the implementation that are hard, or impossible, to describe in the particular language.

    As for mixin with abstract methods… I find this pattern quite helpful. And it is used in the Ruby core libraries. For example, Enumerable requires that classes that include it define each and <=>. This allows my Enumerable class to get a nice set of functionality, and a known interface, by only implementing two methods.

    In most cases I lean toward using mixins if I can implement any of the interface genericly. And I will probably start providing compatiablity unit tests for all “interafaces” I need.

Comments are closed.