Confessions of a Converted PHP Developer: Animal Abuse

Sometimes the functionality of a library or set of classes that you’re working with is 99% perfect for the job, but the last 1% requires modification of some of the core assumptions made in the code. Altering code can cause maintenance frustrations down the track and extending code can cause maintenance frustration right away, but Ruby provides us with a flexible way to modify code with less damage.

In converting to Ruby I realized how strict PHP is in its class hierarchy. This surprised me as I’d always viewed PHP as a very loose language, mainly due to its loose typing and lack of formal code structure guidelines. The latter being inherently, in my opinion, due to the way that a lot of developers learn the language. I find most PHP developers learn starting by using inline PHP as a low learning curve entry point into dynamic web languages and then move on to fuller, more complex, applications.

With PHP, your class hierarchy is very much a linear progression, with the occasional injection from the side. What I mean by that is you will start with a class, possibly declared abstract, and work your way up to an end class with extension after extension, and along the way you might implement some interfaces (that’s the injection from the side bit). This is a very straight forward structure, without any way of dynamically altering this process.

Ruby provides the same extension inheritance structure, but it also allows you various not so rigid ways to alter classes — as we’ve seen in the past with the mixin structure. But Ruby goes even further and allows you to redeclare classes. If you did this in PHP, you’d get a rather strict telling off.

<?PHP
class foo
{
	public function hello_world()
	{
		echo "Hi";
	}
}

#somewhere else in my codebase
class foo
{
	public function hello_world()
	{
		echo "Hello world!";
	}
}

To start with I’ve created a class called foo, with a hello_world method. But then elsewhere in my code, I want to change my foo class and its hello_world method to output a slightly different message. Unfortunately, the above code will output PHP Fatal error: Cannot redeclare class foo. Not good. To get this behaviour, we would need to extend our class and, in doing so, introduce a lot more complexity.

<?PHP
class bar extends foo
{
	public function hello_world()
	{
		echo "Hello world!";
	}
}

Voila, we have now got a class called bar which has the correct hello_world method. This is perfect yea? No — it’s not.

The problem with this style of coding is that to acheive the outcome we want, we’ve had to create a completely new class to use. If we already have a codebase that is using the foo class, we’re up a creek without a paddle and would have to find / replace throughout the entire codebase. While this might be trivial for a small codebase, it could turn into quite an exercise for a larger codebase. Let’s have a look at a common scenario with a request / response situation — ignore the fact that this code calls functions which clearly don’t exist and wouldn’t work if they did!

<?PHP
class API_Request
{
	public function get($resource)
	{
		$content = magically_get_resource_content($resource);
		$status_code = magically_get_resource_status_code($resource);
		return	$this-&gt;_build_response($content, $status_code);
	}

	protected function _build_response($content, $code)
	{
		return new API_Response($content, $code);
	}
}

class API_Response
{
	protected $_response;
	protected $_status_code;
	public function __construct($content, $status_code)
	{
		$this-&gt;_response = json_decode($content);
		$this-&gt;_status_code = $status_code;
	}

	public function is_successful()
	{
		return $this-&gt;_status_code == 200;
	}
}

Here we can call get on API_Request, with a URL resource string, and get back an instance of API_Response with an is_successful method. This method will tell us if the status code of the http request was 200 or not. Now, say we wanted to change the functionality of the API_Response class to match the status code definitions of HTTP/1.1, and tell us that any status code in the 200’s is a success. To do this we’d have to either edit the underlying API_Response class, or extend it, and extend the API_Request class to call the newly extended API_Response class. All of this is a hell of a lot of work for such a simple change, especially when there’s the possibility of having to update code that uses these classes throughout your project.

Here I’m going to do this, replacing API_Response with API_Better_Response, and API_Request with API_Better_Request.

<?PHP
class API_Better_Response
{
	public function is_successful()
	{
		return $this-&gt;_status_code &gt;= 200 &amp;&amp; $this-&gt;_status_code &lt;= 299;
	}
}

class API_Better_Request
{
	protected function _build_response($content, $code)
	{
		return new API_Better_Response($content, $code);
	}
}

Now we have overwritten the _build_response method to correctly return the API_Better_Response class, but we’d also have to go through our application code and find all instances of API_Request and replace it with API_Better_Request.

Ruby to the rescue: Monkey Patching

Ruby has the ability to reopen a class anywhere, and override or add methods. It’s an extremely easy process — you simply declare the class again. Let’s have a look at the equivalent Request and Response classes in Ruby — again ignoring the magical mystery code which doesn’t exist.

module API
	class Request
		def get(resource)
			content = magically_get_resource_content(resource)
			status_code = magically_get_resource_status_code(resource)
			API::Response.new(content, status_code)
		end
	end

	class Response
		def initialize(content, status_code)
			@response, @status_code = ActiveSupport::JSON.decode(content), status_code
		end

		def is_successful
			@status_code == 200
		end
	end
end

Here we’ve got the same code, with the same incorrect is_successful method. Instead of doing any annoying class extension and alteration like we had to in PHP, we can simply reopen the class and change the method to do what we really want it to do.

module API
	class Response
		def is_successful
			(200...300) === @status_code
		end
	end
end

Now is_successful will return true if any 2xx http status code is returned. We’re asking if the range 200-300 (not including 300) loosely equals the status code of the request. Note that we haven’t touched any of the other methods and they will still be in their original form — we just overwrote the is_successful method.

This type of dynamic class alteration is often called Monkey Patching or, according to Wikipedia, Duck Punching. Apparently the naming is in the form of [animal] [past participle verb]. You can read up on the origins of the name at Wikipedia.

So we’ve seen that Ruby allows for easy and flexible dynamic alteration of classes at runtime, which is extremely useful. You can also make multiple monkey patches, but only calls to the code after it is patched will be affected.

I must note that Monkey Patching is often a quick fix solution that can create headaches for future developers (or for yourself, if your memory is like mine) for several reasons:

  • Class logic that is expected to be in the original file, is no longer where it’s anticipated to be — and is difficult to track down.
  • Code that you patch may no longer work if the underlying library or code is updated and the methods you patch are removed, or their behaviour changed.

I guess what I’m trying to say here is: Use at your own risk! You may find that with a little thought and refactoring you can achieve the same results in a cleaner way, and save future you, or future other developers from a few headaches along the way.

Do you use monkey patching in your code? Avoid it at all costs? Feel free to comment below with your reasons.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://chytanya.com Chaitanya

    Nice read. But I guess it makes debugging a nightmare for new developers!!

  • Adam Flynn

    This isn’t a feature specific to Ruby… you can do the exact same thing in PHP. The runkit PECL extension (http://ca2.php.net/manual/en/book.runkit.php) gives you the power to change all sorts of structures at runtime. The syntax is not as simple as in Ruby where you simply redeclare the thing, but, honestly, I’d argue that’s a good thing (especially in a language like PHP where, as you pointed out, the way it’s learned tends to lead to less well-structured coding… promoting these sort of “quick fixes” is probably a bad thing).

    Like most of these sorts of programming tricks (which I’d put in the same class as “goto”), there are times when they’re incredibly useful and powerful. However, it’s rare that something like this is really the “cleanest” option. For example, if you’re building a unit test framework, the ability to mess around with functions at runtime is actually a good thing done for the right reasons.

    But, if you’re just trying to special-case some functionality along certain runtime paths or impose a modification on some external library, I’d argue that it’s frequently the wrong solution. It might “just work” in the immediate-term, and for the reasons you briefly pointed out it is incredibly risky going forward. In the API example you give, I think subclassing or simply modifying the underlying library would absolutely be more appropriate, despite the find/replace effort.

  • http://joshadell.com Josh

    This type of functionality can be very useful. You also see it in Javascript all the time. However, like any other tool, it can and will be abused more often than it helps.

    The biggest concern I have with it is that it violates “coding by contract.” If I monkey patch a new method on to a class, how can any component that consumes that class know about it? Code ends up littered with calls like `if method_exists($someObject, ‘shinyNewMethod’)`.

    I’d much rather see something like multiple inheritance, or runtime injection of Traits into a class that still works with method argument type-hinting and the instanceof operator. That way, I can at least know that an object meets some criteria without having to care how or where the implementation came from.

  • http://www.dotevan.com Evan

    It seems that the example illustrated above could easily be handled by properly implementing dependency injection in the PHP class structure. It would be just as easy to tell class API_Response to use API_Better_Response directly through DI. This has a clear debugging path, and only is a little bit of effort on the developer’s part to implement. Even more, it involves thinking through all the use cases the class may be used in rather than patching it in as an afterthought.

    I’m sure monkey patching has its uses. However, it seems that the use case you’re advocating here stems from inadequate planning. Granted, we all have jobs that might not allow us the time to go back and add dependency injection into an entire layer of the application, but in a perfect world, I would not recommend monkey patching. Seems like it would be hard to track down bugs and a general pain to deal with if it’s not documented extremely well. There’s a reason it’s called monkey patching and not brain surgery patching.

    • http://mal.co.nz Mal Curtis

      Hey Evan,

      As with all my examples, they’re purely examples. It’s hard to create an example with enough complexity to actually warrant the code we’re looking at without making it unnecessarily verbose. I’m definitely not advocating using monkey patching for such a simple exercise as this.

      The main point was that sometimes we just don’t have control of the code libraries we’re using — and it might not be just as simple as ‘change libraries’ — so saying that the developer should have implemented it better only gets us so far. Down in the trenches where you’ve got to get your code deployed by deadline it doesn’t help.

  • Iain

    As the other commentors (and yourself) have mentioned this just seems to me to encourages bad coding practice, which ironically enough is what PHP gets the most stick for. One of the major benefits of OOP is removing software interdependencies, something that leaving class definitions scattered throughout your code definetly does not help.

    I’m sure this trick can be very useful when you’ve got a deadline looming and a stack of things left to implement, but that’s also it’s main flaw. It strikes me as something that’ll be joining register_globals and inline code as one those handy timesavers we’ll be getting shouted at by webdev bloggers for using in a couple of years.

  • http://dilber.info ivanhoe

    All nice & great but it slightly kills the OOP idea of an object being a black box that you work with using the designed interfaces. While I agree class decoration is really a cool thing, it can almost always be avoided or worked around with proper planning and design.

    Overriding methods also can be very confusing for other people looking at your code, we usually expect methods to always work in a certain way, so it can be a nightmare to debug (even for you in 2-3 years).

    I’m not saying it’s a bad thing, actually i love it in ruby, just that it should be used carefully (and well commented)

  • James Smith

    What you are talking about it NUTS – complete and utter NUTS – do you really think that this is a good idea if you do you then I’ll come and visit you in asylum…. Say you use an authentication/authorisation class, and someone creates a module with the same name else where – and you pick that up by mistake you will get there authentication methods!

    This is yet another reason to avoid Ruby!

    The protection in PHP (and most other oo languages) which you are saying is bad is there for a very good reason! So why are you hailing a serious bug in Ruby as an advantage!

  • Nathan

    Hi,

    I think this may have it’s uses but I would be steering well clear. It seems like a way to make debugging harder and I would rather the headache upfront.

    This is exactly what extension is for. It would be better to extend and then refactor existing code rather than add a level of complexity that will cause headaches later and could result in duplicate code.

  • Halil

    “I’d always viewed PHP as a very loose language” and yet you introduce something even more loose! Is this the best stick you use to beat PHP?

  • PHP Donkey

    All these Ruby website talk about PHP this PHP that, and they are all using WordPress CMS….Hmmm

  • Karl

    Can’t a lot of the problems you describe be solved by dependency injection being used from the outset in large PHP projects?

  • Bert

    I tried to learn PHP for about a month and couldnt grasp it very well..i did like the fact that it easily tied in with html and dreamweaver but couldnt get past creating sessions just got to be to much repeating code. Then decided to try RoR and in 30 min i created the same webpage i was trying to do in PHP…the only main negative i have is support for 3.0 its like not there at all…even basic stuff like the script/server from 2.0 chnaged to rails s..which for noobs is almost a deal breaker because there are 20 different ways to call the same server in PHP…but once you grasp the self generated skeleton and workflow then you see RoR beauty…also code seems to be more self explantory not alot of {}{}{}{}}{}{{}}{}{}{}{}{}}[][][][]]{[]}[{}[]}][{}[{}[();;():(); crap going on once RoR gets the support it deserves its going to blow up

  • Craig S

    Um… punching and patching are present continuous verbs, not past participles. This isn’t Nazi nitpicking, it’s not even close. Past participle would be ‘had punched’ for example. I don’t get what was even on the author’s mind

  • http://www.iAchieve.in Onkar Parmar

    Advantages are already listed so will not try to disagree. But the code that uses this methodology will be bad to maintain. When the code is large and user is searching for the class/function definition, he will take longer to ensure he has found the ‘right’ one to modify.