Wednesday, October 31, 2012

phP is tWistEd nAIls

Suppose you've got a class that makes a database connection (forgive the mysql_ interface - alas, for I am stuck in 5.2.9 land):

class App {
  public function __construct() {
    $this->link = mysql_connect( blah blah blah );

Then suppose that we've just included this class into another application. Perhaps it is a component or a framework. In any case, we don't expect to have any interaction with the internals.

Tough luck. You've already violated encapsulation big time, introduced a hidden serial ordering dependency, and established a crunchy fixed point in the code.

You might do this:

require_once "";

$link = mysql_connect( blah blah, true); // new link regardless of connect strings
$fu = new Klass();

require_once "";

mysql_query("select something from somedb where blah blah");

Well, OK. If that's your idiom, then you can't do anything really interesting.  It is going to fail if anything deep within the bowels of invokes mysql_connect. That's because mysql_connect scribbles all over the internal buffer that holds the last link connected, as if it were a single global variable.

PHP's default connect link idiom is a little worse than useless, because it seduces naive users into writing a lot of this kind of fragile, easy to break and difficult to fix code.  When invoking mysql_connect, you are not expressing the intent "use this link and database by default" - the built-in default behavior is merely a side-effectual accident of requesting another connection. Any subsequent call to mysql_connect changes the implicit connection link.

You could instead use an explicit link in the call to mysql_query:

mysql_query("select something from somedb where blah blah", $link);

And that works. Sort of. But now we need to rewrite all queries to use a global value, provide gratuitous function arguments to pass gratuitous links around, or provide a centralized query object with a stack to manage the links ourselves. Each case has its shortcomings, and none is really sufficient to deal with the underlying structural flaws in the interface design.

Such structural flaws in PHP libraries make me imagine I'm framing a house with recycled nails. You can make them work if you whack the hell out of them, but even then they are twisted and you'll end up with a world of hurting fingers to show for it. It is just a stupid way to build stuff.