php[architect] logo

Want to check out an issue? Sign up to receive a special offer.

Analysis: Following Ruby Makes PHP Number Two

Posted by on September 23, 2010

These days, people sure seem to be coming up with some… interesting names for their projects. Dennis Hotson, for example, wrote in his blog today about PHP Object Oriented Programming Reinvented.

That’s right—PHPOOPR.

Dennis acknowledges that the name needs work. But, getting past that, his blog is about some creative experiments Dennis is working on.  He has come up with a pretty innovative way of creating objects dynamically in PHP that allows for some usage that conventional PHP coding techniques don’t support:

  • Classes can be hacked / patched / cloned. Methods can be added to classes at any time.
  • Classes can be scoped. They’re not global, unless you want them to be.
  • Classes can be temporary (and garbage collected).

In Dennis’s code, class definitions are objects themselves, created by a base class constructor function Obj().

$class = Obj();

A Factory is a design pattern for an object that can create more objects of various types.  Thus, Obj() is a factory method.

The only thing that differentiates one class instance from another is the methods it supports.  You can add new methods to any class by passing a PHP closure to a class object.

$class->fn('new', function ($class) {
  $newClass = Obj($class->methods)
    ->fn('new', function($class) {
      $obj = Obj($class->imethods);
      $args = func_get_args();
      array_shift($args);
      call_user_func_array(array($obj, 'init'), $args);
      return $obj;
    });
  return $newClass;
});

Now, $class can create instances of the respective type, so these class objects are also factories, making Obj() a factory factory.

$object = $class->new();

You can make a class support subclassing by adding a new method to return a new class object, a clone that has the same functions:

$class->fn('extend', function($t) { return clone $t; });
$subclass = $class->extend();
$object = $subclass->new();

Since all classes are factories, extensible classes are therefore also factory factories.  Which makes Obj() a factory factory factory.

You can add more methods to each class instance, of course.

This is a very clever experiment. But I wonder if Dennis wants to program in the paradigm of everything-is-an-object like Ruby or Python, why doesn’t he just use Ruby or Python?

His experiment mimics what those languages have already done, but he still has some parts of PHP that developers hate, such as the motley, non-OO built-in functions, and the need for the array() syntax for array literals.

There are a number of other features of PHP’s conventional OOP that go out the window in Dennis’ code:

  • Compile-time typehints: Classes don’t even have names, they only have instances, which aren’t created until runtime.
  • instanceof: Likewise, you can’t test an object’s class for its type or any of its supertypes because types don’t have names. An object doesn’t know what type it is, only what methods it has.
  • Interfaces: Dennis doesn’t show how one would force an object to have a certain set of methods to conform to an interface, or how to make any given method have a specified signature.
  • Reflection: PHP’s built-in functionality for reporting meta-information about types doesn’t work with Dennis’ objects, so he’d have to reinvent that wheel.
  • SPL: All the types in SPL rely on conventional class extension and interface implementation, so they’re incompatible with Dennis’ objects.
  • Autoloading: PHP loads a class automatically if you reference it by its name, but if classes have no name, you have to take responsibility for loading the code that creates classes yourself.
  • ===: The idea of type equivalence is blurred. Two objects are “the same” if they simply have the same set of methods.
  • Code completion: In the same way that an IDE can’t infer the methods of an object implemented through the magic method __call(), these dynamic objects have functions that are not known until runtime, so intellisense has no idea what methods exist or what their signatures are.

The experiment Dennis is coding is worthwhile, but not because it will be useful. Instead, it’s worthwhile because it illustrates how we rely on the concept of a type in a programming language. Types enforce structure and help us depend on certain assumptions (like the interface of a class), so we can write simpler code. If we have limitless flexibility, we can’t rely on any structure remaining in place, so we have to write more complex code to handle an increasing amount of uncertainty and variation.

[Updated 09/28@18:52ET to fix the spelling of Dennis’ last name (with our apologies)]


Tags: ,
 

Responses and Pingbacks

We are charging too much for a project that arose a few days. We must invest in the idea, the dynamics that it offers. If it really is worth investing, the factors you pointed out is only a matter of time that support them they will exist. But I agree with you when comparing this experiment with Ruby and Python.

Thanks Bill. You make some excellent points.

In my defense, I think it’s a pretty good result for 90 lines of PHP. There’s plenty of stuff I didn’t implement because I really just wanted to try out a few core ideas.

Also, in case I wasn’t clear: It’s just a hack and I wouldn’t recommend using it in any way. Please just enjoy it as a piece of code origami. 🙂

Hi Dennis, thanks for your comment. I sure did enjoy your code, it was a very clever exercise.

Another programming language that your experiment reminded me of is LISP. Have you ever looked into that seriously? You might enjoy it.

Greattt!!

When to use ruby + PHP?

thanks… your points were great…

i could use them on my research…

I think the same argument you are making about Ruby and Python could be applied to PHP itself. If you need all the structure (interfaces, abstracts, types, etc) of conventional OOP, shouldn’t you be using Java, or C#, or some other compiled language that can stand the overhead of all that structure without having a serious impact on application performance?

Edward: Excellent point, couldn’t agree more.

Bill: Was this blog post really necessary? It’s clearly intended to be an experiment, and as you said yourself, it’s a clever idea. The author never says we should all go out and start writing code that way.

Also, unless you have a fanboy’s attitude, there’s no war between PHP and Ruby. Tilting at windmills (and the attempt at a provocative title) just makes you look bitter.

@Edward Vermillion: Thanks, it’s true there are degrees of how the language deals with types. Java or C# are more strongly typed than most dynamic languages, and that means those languages can do some things that others can’t. But coding in these language is also more meticulous. So there are tradeoffs.

@Nate Abele: This blog post was not a disparagement against Ruby or Python. The idea behind this blog post is that no matter what programming language you use, types must have names. It’s crucial to the nature of being a type. Even in languages that favor duck-typing, like Ruby and Python, classes have metadata.

Talking about the code itself isn’t this similar to PECL runkit?

@Nate Abele: Make your words my.
@Bill Karwin: It’s only a experiment. Don’t take it so serious. Just like every day there are new frameworks with different proposals and dynamics, why Dennis Hotson can’t propose anything new? Use whoever, nobody is forced.

@Igor: Thanks for your comment. I agree with you, and I encourage people to make experiments. Nowhere did I say Dennis or anyone else must not experiment in this way. I only described the consequences if one does use his technique.

If you interpret my description as a prohibition against using the technique, then this just shows that its consequences are worth avoiding.

The information is very useful to me and to my students.

@Lloyd Watkin: Good point! PECL runkit provides some of the same features, such as the ability to add methods to a class at runtime. But classes remain compatible as native PHP classes, so you can still perform reflection and all the other features I mentioned.

“Good point! PECL runkit provides some of the same features, such as the ability to add methods to a class at runtime. ”
True!

http://www.smithmonitoring.com

Excellent point,Bill.I totally agree.

If you interpret my description as a prohibition against using the technique, then this just shows that its consequences are worth avoiding.

“Good point! PECL runkit provides some of the same features, such as the ability to add methods to a class at runtime. But classes remain compatible as native PHP classes, so you can still perform reflection and all the other features I mentioned.” You made excellent point here Bill.I can’t agree more with you!

The information is very useful to me and to my students.

Keep these ariltecs coming as they’ve opened many new doors for me.

Leave a comment

Use the form below to leave a comment: