Re: require_once vs. no require_once - please read, critical information

From: 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

« previous php.pear.dev (#48145) next »