Zend certified PHP/Magento developer

RubySource: PHP to Ruby: Modules, Mixins and Ducks

If you have been writing PHP for a few years you will no doubt have come across Interfaces and Abstract classes. They were introduced in PHP5 object model and since have had medium usage in the PHP world. If you Google “PHP Interfaces” you will get some results on the official documentation and the rest saying how pointless they are.

Why the divide? I believe it is mainly down to lack of understanding to what interfaces give you. They imply what your classes should do, but that’s it. Yep, we are talking programming contracts.

Writing a contract

To fill in the gaps here, say we have an application that generates PDF documents from various reports (how very corporate). We have a PDF library that will accept objects as long as they have an interface of setFilename, setAuthor and render.


interface PdfCruncherInterface {
 public function setFilename($name);
 public function setAuthor($author);
 public function render();
}

That wasn’t so bad. Now we have defined an interface lets look at implementing it. We have a monthly report of the hundreds of meetings that our big corporation employees have, so something like this would work:


class Report implements PdfCruncherInterface {
 protected $filename = "";
 protected $author = "";
 public function setFilename($filename) {
   $this-filename = $filename;
 }
 public function setAuthor($author) {
   $this-author = $author;
 }
 public function render() {
   /* Specific implementation to render the report */
 }
}

Abstract classes

All is well with the world until the MD wants to produce an additional report of all the cat images he has copied off the Internet every month. So we are not dealing with just text anymore and will no doubt need to change the implementation slightly. Our interface is good, as only the implementation of render has changed, hence we can bring abstract classes into the mix.

For the uninitiated of this design pattern dance an abstract class, like an interface define what methods our classes must have. However an abstract class will also provide partial implementation for us.


abstract ReportAbstract {
 protected $filename = "";
 protected $author = "";
 public function setFilename($filename) {
   $this-filename = $filename;
 }
 public function setAuthor($author) {
   $this-author = $author;
 }
}

Now we can create 2 classes (one for pointless text and the other for useful images) that extend our Report abstract and implement our PdfCruncherInterface


class ImageReport extends ReportAbstract implements PdfCruncherInterface {
 public function render() {
 }
}
class TextReport extends ReportAbstract implements PdfCruncherInterface {
 public function render() {
 }
}

Hopefully that illustrates how we can build flexibility into our applications using interfaces and abstract classes. Is it just me or was that a lot of code for a simple fictional example? Isn’t there a better way? Well, yes. Don’t use interfaces. In fact, Ruby as a language does not have an equivalent to interfaces. And you can understand why when you look at duck typing and modules.

Duck Typing

I love duck typing. Not only is it fun to say but it also gives me as a developer the intellectual respect I deserve (still not much though). In essence “If it walks like a duck and talks like a duck, chances are it’s a duck”.

This simple phrase evolves developers from the primordial ooze and actually acknowledges we have brains. Who would really just grab a class that calculates how many “OMG”s per minute on Facebook and throw it into the PdfCruncher without making sure it will work. We are problem solvers, we write tests we refactor our code and move on to the next problem. So in Ruby we forget this interface lark and say:


class ImageReport {
 def set_filename(filename)
   @filename = filename
 end
 def set_author(author)
   @author = author
 end
 def render
   # our render implementation
 end
}

Mixins

As PDFCruncher library hasn’t changed, it still needs a filename, author and render. And we give them that. Our class ImageReport walks and talks like our old PdfCruncherInterface so it must be just that. Simple. Hold on, so we haven’t covered all that potential duplication. Well, in Ruby we use modules. Modules are (if we look up the Programming Ruby bible):

Modules are a way of grouping together methods, classes, and constants.

So we can create a Module that handles the shared code like so:


module PdfMeta
 def set_filename(filename)
   @filename = filename
 end
 def set_author(author)
   @author = author
 end
end
class ImageReport
 include PdfMeta
 def render
   # our render implementation
 end
end

We have eliminated duplicate code and have all the methods we need to generate a PDF, all without a single piece of inheritance. You could not ask for a more loosely coupled piece of code. So why then are alarm bells are ringing? Contracts. Yep a year down the line some bozo needs to create a new pdf report. He creates a class and includes the PdfMeta module (shouldn’t be enough?) and boom, it doesn’t work and he is not sure why. How can we ensure he defines a render method? We like the idea of having all our pseudo pdf interface in a module, but obviously it cant be responsible for the specific rendering of text, images layouts for all the different reports. We need an interface!?

After a moment of calm reflection we realize there is another way. If I want to ensure a method is declared in a class mixing in my module I simply and effortlessly do this.


module PdfMeta
 def render
   raise "I must haz render method"
 end
 def set_filename(filename)
   @filename = filename
 end
 def set_author(author)
   @author = author
 end
end

There we go. Now if we have tests, and we really should, unless the mixing in class, mixee, includer, base class whatever you want to call it overwrites the render method, we will have it raising that dumb exception all over the place. Hopefully this has helped you see programming Interfaces are not important (shock!) contracts. If you get contracts via PHP interfaces then great, but the power of modules in ruby gives us the ability to specify contracts (loosely albeit), provide partial implementation and its all loosely coupled.