Discussion for Drip #12 - Duck Typing to Avoid Conditionals

84 views
Skip to first unread message

Joshua Clanton

unread,
Apr 3, 2013, 8:11:46 AM4/3/13
to js-drip-d...@googlegroups.com
Discuss! :-)

Benjamin Miller

unread,
Apr 4, 2013, 12:21:02 PM4/4/13
to js-drip-d...@googlegroups.com
All right!
Very happy to have a place to author my thoughts on the weeks subject.
Before I get started I'm going to point out that in the description area for the discussion group you have the link "A Drip of JavaScript" going to JSfiddle.
Could be intentional, but I'd expect it to go to your lovely weekly informative.


Duck typing reminds me greatly of the Strategy Design Pattern, as well as this Drip from a few weeks ago regarding dispatch tables.
Avoiding conditionals is, in my opinion, a great way to produce very clean, explicit code. A very nice technique to separate your logic from your data.

Joshua Clanton

unread,
Apr 4, 2013, 4:18:35 PM4/4/13
to js-drip-d...@googlegroups.com
Whoops! I've fixed that link now. :-)

I agree that there are a lot of similarities. Though I would point out that Duck typing doesn't necessarily have to involve invoking functions/methods at all. You might for instance, have something like this:

function Color(r, g, b) {
   
this.r = r;
   
this.g = g;
   
this.b = b;
}


function averageColor (color) {
   
return (color.r + color.g + color.b) / 3;
}


var red = new Color(255, 0, 0);


blue
= {
    r
: 0,
    g
: 0,
    b
: 255
};

averageColor
(red);
averageColor
(blue);

This is an example of duck typing, because all that averageColor expects is for the color object to have properties r, g, and b. Whether or not it is an instance of Color is irrelevant.

Benjamin Miller

unread,
Apr 9, 2013, 11:53:01 AM4/9/13
to js-drip-d...@googlegroups.com
Yes, you are correct.
While similar they are still pretty different. They both have a "plug-and-play" feel, but differ in execution.
While I think your example is better suited for duck typing, I've written it out as one would using the strategy pattern.

function ColorStrategy(r, g, b) {

   
this.r = r;
   
this.g = g;
   
this.b = b;
}
ColorStrategy.prototype.averageColor = function(){
 
return (this.r + this.g + this.b) / 3;
}

function colorClient(strategy){
 
return strategy.averageColor()
}

var red = new ColorStrategy(255, 0, 0);

var blue = {
  r
: 0,
  g
: 0,
  b
: 255,
  averageColor
: function(){
      return (this.+ this.+ this.b) / 3;
    }
}

colorClient(red);
colorClient(blue)

in this example it is bit more code doing it this way, we needed to define an extra function, colorClient, and we had to declare/assign averageColor twice (if we wanted to make it an object literal like you did, real world we wouldn't do this.)

Stragety pattern's advantage comes in to play when things are not all the same. for example, if our blue had an alpha value that we wanted to include in our average.

var alphaBlue = {
  r
: 0,
  g
: 0,
  b
: 255,
  a: 0.5,
  averageColor
: function(){
      return (this.+ this.+ this.b + this.a) / 4;
    }
}

colorClient(alphaBlue)

Using the strategy pattern we can now define as many colors as we want. We are not limited to rgb, and we can become as abstract with our averageColor method as we need to and still get the value in exactly the same way.
 




Reply all
Reply to author
Forward
0 new messages