Re: require_once vs. no require_once - please read, critical information
| From: | Gregory Beaver | Date: | Mon, 24 Sep 2007 03:45:32 +0000 |
| Subject: | Re: require_once vs. no require_once - please read, critical information | ||
| References: | 1 2 | Groups: | php.pear.dev |
| Request: | Send a blank email to pear-dev+get-48145@lists.php.net to get a copy of this message | ||
Alan Knowles wrote:
> While I don't want to re-hash the old arguments - this again concludes
> on very thin evidence same same rather faulty conclusions.
Would you care to provide some of your own evidence that is thicker than
the above sentence?
> - Maintainability - having a description of where a class comes from
> near where it is used is always going to be simpler, no mater what you
> come up with.
Correct. In PEAR, we do not have a description of where a class comes
from near where it is used, unless you mean:
<?php
require_once 'PEAR.php';
class MyError extends PEAR_Error {}
?>
I am using PEAR_Error. Where is the description of its location? OK,
that's a straw man because PEAR2 won't allow that :). Let's try this:
<?php
require_once 'MDB2.php';
$mdb2 = MDB2::connect('mysqli://user:pass@localhost/database');
?>
I want to use mysqli. The error says "Not found" Where is the
description of its location? How do I know that I need
MDB2_Driver_mysqli package to get MDB2/Driver/mysqli.php?
The new proposal would provide what is missing from PEAR now:
<?php
/**
* @uses PEAR2::PEAR_Error located in PEAR2/PEAR/Error.php
*/
namespace PEAR2::Fake;
import PEAR2::PEAR_Error; // humor me - it's an example
class MyError extends PEAR_Error {}
?>
<?php
/**
* @uses PEAR2::MDB2 located in PEAR2/MDB2.php
* @uses PEAR2::MDB2::Driver::mysqli located in PEAR/MDB2/Driver/mysqli.php
*/
import PEAR2::MDB2::Driver::mysqli;
import PEAR2::MDB2;
$mdb2 = MDB2::connect('mysqli://user:pass@localhost/database);
?>
> - Performance improvements, are negligible compared to that of a real
> life application.
based on what evidence exactly? How do you define "real life
application?" An app that does database activity on every request?
In my experience, performance-conscious apps do as much as possible to
cache, and that includes database query result sets. For these real
life applications, small latency issues actually cause real problems,
which is why Gopal is practically obsessed with latency.
Additionally, until an application is benchmarked, there is no certainty
of the tired mantra "it's all about your database." Rasmus discovered
in the work preceding PHP 5.2 that the startup code was consuming about
twice as much time as a complex mysql query when he benchmarked,
overturning the assumptions we all have.
With a less complex application (not as many cross-linked $a = &new
blah), the performance difference between using require_once with
relative paths and an allfiles approach approached 11% of the total
running time, which is a realistic representation based on a real-life
app that does caching.
> I have no idea why you can't create a package, PEAR2_StripRequires
> which removes all the requires and let's you use autoload or allfiles.
> If someone want's to try this out, and see all the long term
> maintenance problems they will end up with, let them, but please dont
> force it on everyone..
Because I am concerned with maintainability.
Having the same code without modification makes it far easier to
collaborate and remotely debug a problem that a user experiences. It
also cuts down on the number of possible vectors for things to go wrong.
Allowing the user to include the code in multiple ways is very hard to
screw up - you might forget a file, but the error is quite obvious when
it happens, and unmistakable. I am puzzled that you would recommend
introducing more vectors to screw up maintenance long-term and short-term.
Sure, everything should be done to avoid long-term maintenance problems,
but the irony here is that require_once is in fact causing a long-term
maintenance problem for much of the work that I and many others do with
PEAR packages.
If you really want to convince me and the other who are voting +1 for
removing require_once that it is a bad idea, please provide some valid
up-to-date evidence based on actual attempts to develop without using
require_once that show the long-term maintenance issues. I frankly
don't see them. In my experience, here are things that happen which
cause long-term issues:
1) package renaming
This happens when a package breaks BC. At this point, a replace needs
to be done on both class names *and* require statements. The chance of
error doubles compared to the system being proposed. This issue only
affects the PEAR developer doing the package rename.
2) class splitting
This often happens when it becomes clear that a class is getting too
complex, and should in fact be something like a factory or driver
pattern (or even command). The same issue presents itself, but it is
more insidious. Now, conditional require_once must be added inside the
factory/driver method, which means that performance begins to suffer
from the bloat syndrome. Even using an allfiles solution is not a
problem if one uses an __autoload() fallback that loads the class and
logs the missing require for addition to the code. __autoload()-based
apps wouldn't even blink, they would just load the needed class. With
require_once, this actually results in more long-term maintenance
issues. This issue indirectly affects the end-user and affects the PEAR
package developer.
3) multiple local PEAR repositories
When one has multiple PEAR installs for separate applications, working
with include_path becomes a serious issue as one might accidentally load
dependencies from the wrong location if include_path is set up in the
wrong order. This is very common, especially when people are using the
PEAR installer to upgrade PEAR, and it continues to report that it is in
fact version 1.3.6, I'm sure you've seen the messages on pear-general.
I experienced the same problem when running Chiara_PEAR_Server on my
pear.chiaraquartet.net channel server, in that it was using the older
system-wide PEAR installation rather than my local install. Had I been
using an explicit autoload with properly initialized include_path, there
would never have been an issue. Instead, this has caused some seriously
difficult to debug problems. This affects everyone writing applications
that use PEAR.
4) deprecated packages disappearing or packages breaking BC
This has nothing to do with require_once or autoload or allfiles, but
causes a problem with maintenance for legacy apps. For instance PHPUnit
disappearing caused problems with apps that depended on it for the test
files. This has already been fixed in PEAR 1.x with occasional blips
like the PHPUnit thingy.
5) using PEAR_Error
Because PEAR_Error is optionally caught, the number of subtle
waiting-to-explode-in-your-face problems I continue to run into with
PEAR_Error is unknown, but causes continual headache when maintaining
legacy code. This also has nothing to do with require_once, autoload,
or allfiles, and is fixed in PEAR2.
These are my top 5, and as you can see, 3 of the 5 result directly from
problems with relative path require_once. Is there something left off
of that list that concerns you more?
Greg