First, let me explain the title for those of you who live in Java world. The term Duck Punch comes from
Ruby programmers and refers to the concept of duck typing
used by Ruby and other languages;
if it walks like a duck and quacks like a duck, I would call it a duck.
With that being said, duck punching is summed up nicely by Patrick Ewing with the following:
Well, I was just totally sold by Adam, the idea being that if it walks like a duck and talks like a duck, it’s a duck, right? So if this duck is not giving you the noise that you want, you’ve got to just punch that duck until it returns what you expect.
It is slightly violent, but makes for a good article title. Now, getting to the point, metaprogramming is writing programs that write or manipulate programs, including themselves, at runtime. This type of programming can be accomplished in many languages but is currently a pretty hot topic in languages such as Ruby and Groovy. Java has a similar concept known as Aspect Oriented Programming (AOP), which introduces pointcuts to a program that can then be modified at runtime via bytecode manipulation or dynamic method proxies.
My example library/method below allows a Prototype-enabled class to have every one of its methods wrapped with a before and/or after method to introduce additional functionality at runtime. This concept is demonstrated by this example, note that the modification occurs on the class level and any existing or future instances of that class are affected. Thanks to Prototype JS, this code is pretty simple:
get a list of all class member names using the Prototype
as shown on line 4. Once we have the member names, we loop through all members (line 5) of the class.
For each member we check if it is a function (line 7).
If it is, we alias the function (line 9) and create a new function (line 10) in its place that wraps the aliased function
with calls to the before (line 11) and after (line 20) functions we pass in. Notice the use of
starting on line 9, the
prototype keyword is necessary to modify the class. If you rewrote this method
slightly and didn’t specify the
prototype keyword you could modify an individual instance of the class
instead of all running instances. Also notice the
on line 16, currying is a metaprogramming technique (provided as a helper
by Prototype JS) where a function is modified with each call so that the arguments passed into it
become part of the function and are no longer necessary. This allows us to pass an arbitrary number of arguments into the
The above code can be called on any class in the document by running the following code, assuming before and after are pre-existing functions and SampleClass is the desired class:
So, where is this useful? Since we’re simulating AOP, we can use this for any
cross-cutting concern, a perfect example being logging
or profiling. Watch for a future article where I use this technique to automatically implement
I did in my article on the dollar function using this technique. One final note for the Prototype geniuses out there,
Prototype does provide a
wrap method that provides