On Wed, 2011-01-19 at 01:07 -0600, Larry Garfield wrote: > Hi all. I'm trying to come up with a solution to an architectural problem I > could use some extra eyes on. > > I have (or will have) a large code base with lots of classes, spread out over > many optional plugin components. These classes, of course, will have > interfaces on them. These classes will, of course, lazy-load using PHP's > autoload capability. > > What I need to know is which classes implement which interfaces, so that I can > load and use "all classes that implement interface Foo". > > There are a couple of approaches that I've considered, all of which I dislike > for one reason or another. > > 1) Magic file naming. That is, any class that implements interface Foo lives > in a $something.Foo.inc file, or some similar pattern. This has a number of > problems. First, it means a huge number of file_exists() calls to determine > if a given potential class exists, and then disk hits to load those files. > While that information is possible to cache, it also means that we cannot have > a class that implements two of the interfaces I'm interested in (a feature I > will need) because then it would have to live in two files, which is clearly > impossible. > > 2) Reflection. PHP makes it quite easy to get a list of all loaded classes, > and to get a list of all interfaces that a loaded class implements. The catch > there is "loaded". Reflection only works once you've loaded the code file > into memory. Once you've done so, you cannot unload it. That means the code > is sitting there in memory wasting space. Given the size of the code base in > question, that could easily blow out the process memory limit. Even if we > cache that information we derive from reflection we still have to load it the > first time (or periodically when rebuilding the cache), which will blow the > memory limit. The only alternative would be to have some sort of incremental > rebuild across a multi-request batch process, the complexity of which makes my > skin crawl. > > 3) Static analysis. Instead of reflection, either tokenize or string parse > all files to determine what classes implement what interfaces and then cache > that information. We are actually using this method now to locate classes, > and it works surprisingly well. Because we never parse code into memory it > does not ever spike the memory usage. However, it is impossible to determine > if a class implements a given interface by static analysis unless it declare > so itself with the implements keyword. If it does so indirectly via > inheritance, either via the class or via the interface, it would not find it. > That necessitates that any "detectable" classes must explicitly themselves > declare their interfaces, even if it is redundant to do so. I don't like that > approach, but it's the first one that strikes me as even viable. > > 4) Explicit declaration. In this approach we detect nothing and rely on the > plugin developer to do everything. That is, they must provide somewhere > (either in code or a configuration file) an index of all classes they offer, > the interfaces they implement, and the file in which they live. While this > makes the implementation easy, it is a huge burden on the plugin developer and > I'm quite sure they'll forget to do so or get it wrong on a regular basis. > > 5) Wave a wand and let the magic ponies figure it out. I wish. :-) > > Can anyone suggest a better alternative? At the moment option 3 seems like > the most viable approach, but I'm not wild about the implied performance > impact nor the potentially redundant interface definitions it would require. > > --Larry Garfield > My suggestion, would be for #5. The magic ponies do wonderful work. :) Steve (TheStapler) Staples. -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php