A poet called James Whitcomb Riley once said:

“When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.”

Much probably referring to the Mallard (like the one of the above picture) that acts just like a duck, but isn’t a duck!

Well, in programing language we use the term “Duck Typing” to describe the “use a certain behaviour of an object, but defer the check to the runtime”. Ok, still confusing, let me try to simplify this.

Examples 🦆

A simple logger

Let’s suppose we’ve built a logger function in Node, which receives a target to output all the logs. It will call the “log” method, acting as a simple facade, doing the log calls for you.

The logger is a composed function that acts like a factory, build the log caller using the given target instance (storing it inside it’s context).

So, let’s see what happens if we create an instance which have some of the expected behaviour from the console:

And then, we just throw an instance of it inside our logger…

…and boom! We have “Hello world!” written on the log.txt file.

And here is the trick! The FileLogger don’t have anything more than the “log” behaviour from the console object. You can see that no “extends” were used, or any prototype shared too.

Ok, we still had to call the constructor and the close methods, but the good thing is, you can expose the “log” function to the entire application, without worrying what is being inside.

Now, thing on the possibilities, you can implement the info, warn, error and debug…

…and then, create a lot of different “targets”, other than “file”, like “websocket”, “printer”, “led terminal” or whatever you want. Use the strategy pattern to choose the right target for the right situation and you’re going to have a nice and powered log system for your app. Note again, the targets doesn’t share anything but the behaviour!