Jason in a Nutshell

All about programming and whatever else comes to mind

The best tool for the job: Duck typing vs Interfaces

Posted by Jason Baker on December 11, 2008

A question on StackOverflow got me thinking today:  what are the advantages of duck typing in comparison to interface-based languages (like C# or Java) and vice versa?  Notice that I’m not talking about the differences between dynamic and static typing.  These two comparisons go hand-in-hand to be sure, but they are two different things in my opinion.

The basic idea behind duck typing is that “if it walks and talks like a duck, then it’s a duck.”  Thus, if you want to do an operation on a certain type of object, then you should do that operation on a certain type of object.  If the interpreter has a problem, then the interpreter/runtime will let you know (and hopefully you’ve got some error handling in place).

On the other hand, interface-based languages solve this problem by having a pre-established contract between objects and code.  Thus, an object will guarantee that it will implement certain methods if the client code will guarantee not to call anything else.  If that contract is broken, then the complier will likely let you know at compile time (though that isn’t always the case).

So what are the pros/cons of these two methods?

On first glance, it would seem that the benefits of type safety would make interface-based designs more worthwhile in almost all cases.  Indeed, interfaces have helped me prevent a lot of needless errors that I frequently encounter in using dynamic languages.  It does this by forcing you to think your class hierarchy a long way in advance.

This is where C# and Java get their enterprise-y reputations.  If you need to develop a complex hierarchy of classes, interface-based typing is the only way to go.

This is simultaneously interface-based typing’s greatest strength and greatest weakness.  Indeed, it’s also duck typing’s greatest strength and weakness.  As wrong as it feels, not every class hierarchy needs to be so well-planned.  Heck, sometimes you don’t need class hierarchies at all (there seem to be a lot of python programmers who are totally against inheritance altogether).  Of course this does require a lot more unit testing, but you’ve already signed onto the TDD bandwagon anyway, right?

This is where Python gets its famed extreme levels of productivity.  By having a good set of unit tests, a Python programmer can churn out good code at breakneck pace.

At any rate, both ways of programming have their strengths and weaknesses, and there’s not any good answer as to what way of thinking about it is the best way to go.  So go with your gut.  If your first reaction at tackling a task is to say “gee, it really would be nice to be able to write a lot of code fast without having to go through a lot of tedium” then go with Python or Ruby or most other dynamic languages.  If you find yourself saying “I need a very complex class hierarchy to do this” then chances are you should be using C# or Java.

2 Responses to “The best tool for the job: Duck typing vs Interfaces”

  1. Phil H said

    Personally, I’ve been pondering duck typing vs interfaces for a while. It seems that the choice is between a catch-all (duck typing) and a square hole (interfaces). Interfaces are great for static languages, but are more restrictive at design time than going for duck typing. At the same time, duck typing means that an increasing number of tests are needed to make sure the system copes with different usage.

    But what if we restrict ourselves to web services? A datastream (MIME, xml, etc) is passed in, and the service provider has an SLA contract for expecting it to ‘work’. But since we’re dealing with externally supplied input, we do all our input-checking at the start, to make sure it’s all sanitised. After that, we have effectively already done the checking we need (if we’ve done it well).

    Now, do you take the static+interface approach, because you already know what the input is like, or do you take the duck-typing approach, because we’ve already sanitised the input, and have our TDD tests aligned with our input sanitisation?

    My answer would be to go with duck-typing here. If we’ve defined our SLA well, we have excluded non-compliant input data, which will be turned down at the point of reception into the system. Thus we can dispense with the overheads of interfaces, since we can (Atwood style) throw hardware at the interpreted language speed issue.

  2. micha said

    There is a middle ground, GC++ calls them “signatures”. I don’t know if the compiler still supports them, but before templates were added to the spec, GNU implemented a number of possible ways to write generic methods. Among them was the signature; it’s like a Java interface (circa Java 8, with default implementations permitted), but you don’t need to actually declare your class as inheriting from it.

    E.g. Comparable is an interface. If it were a signature, then any class that happens to have a compareTo() could be used, regardless of inheritance.

    To be really powerful, you should have a “with” or some such to allow coercing the signature to fit. To explain by example syntax:

    map = new TreeMap { greater(x) ? 1 : lesser(x) ? -1 : 0; }, MyValueClass>();

Leave a comment