Migrating OOP Libraries and Frameworks to PHP 5.3
With PHP 5.3 coming up on the horizon, I'm of course looking forward to using namespaces. Let's be honest, who wants to write the following line?
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
when the more succinct:
$viewRenderer = HelperBroker::getStaticHelper('viewRenderer');
could be used? (Assuming you've executed 'use
Zend::Controller::Action;' somewhere earlier...)
However, while namespaces will hopefully lead to more readable code, particularly code in libraries and frameworks, PHP developers will finally need to start thinking about sane standards for abstract classes and interfaces.
For instance, we've been doing things like the following in Zend Framework:
- Zend_Controller_Request_Abstract
- Zend_View_Interface
These conventions make it really easy to find Abstract classes and
Interfaces using find or grep, and also are
predictable and easy to understand. However, they won't play well with
namespaces. Why? Consider the following:
namespace Zend::Controller::Request
class Http extends Abstract
{
// ...
}
Spot the problem? 'Abstract' is a reserved word in PHP. The same goes for interfaces. Consider this particularly aggregious example:
namespace Zend::View
abstract class Abstract implements Interface
{
// ...
}
We've got two reserved words there: Abstract and Interface.
Stas, Dmitry, and I sat down to
discuss this a few weeks ago to come up with a plan for migrating to PHP
5.3. In other OOP languages, such as Python, C#, interfaces are denoted by
prefixing the interface with a capital 'I'; in the example above, we would
then have Zend::View::IView. We decided this would be a sane
step, as it would keep the interface within the namespace, and visually
denote it as well. We also decided that this convention made sense for
abstract classes: Zend::View::AView. So, our two examples
become:
namespace Zend::Controller::Request
class Http extends ARequest
{
// ...
}
and:
namespace Zend::View
abstract class AView implements IView
{
// ...
}
Another thing that looks likely to affect OOP libraries and frameworks is autoloading, specifically when using exceptions. For instance, consider this:
namespace Foo::Bar
class Baz
{
public function status()
{
throw new Exception(\"This isn't what you think it is\");
}
}
You'd expect the exception to be of class Foo::Bar::Exception,
right? Wrong; it'll be a standard Exception. To get around
this, you can do the following:
namespace Foo::Bar
class Baz
{
public function status()
{
throw new namespace::Exception(\"This is exactly what you think it is\");
}
}
By using the namespace keyword, you're telling the PHP engine
to explicitly use the Exception class from the current namespace. I also
find this to be more semantically correct -- it's more explicit that you're
throwing a particular type of exception, and makes it easy to find and
replace these with alternate declarations at a later date.
I'd like to recommend other libraries adopt similar standards -- they're sensible, and fit already within PEAR/Horde/ZF coding standards. What say you?
blog comments powered by Disqus