Class and interface location

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux