Would You like a Dynamic "extends"?
So, where would this be a problem? Well, lets say you have a set of base classes shared between n-projects in a framework. Now lets assume you have a combination of objects (some at the framework level, some at the project level) that need to be able to extend those base classes. And finally imagine that you'd like the ability to overload the base classes for some projects but not others. So in project A UserObject extends BaseObject, but in project B, UserObject extends ProjectBaseObject which extends BaseObject. In addition, the UserObject may be in project B, but it may also be an object stored in the framework directory that is shared between different projects and needs to extend a different object depending on which project it is being called from.
I would like to be able to describe the "extends" logic in LightWire and to dynamically control extends in the same way I dynamically control injection of properties and dependencies.
Right now, the only solution I can think of is to ask LightWire to copy the beans into a temporary directory, Regex the appropriate dynamically agreed extends attribute into the
I know there are other ways of solving the problem of being able to overload shared base classes on a project by project basis, but for my proposed outcome this is the "least inelegant" solution I've come across to date. Obviously there would have to be both an application wide and bean specific control to switch this on so it's only used on applications and beans that need it.
This is pretty unexplored territory in CF (to the best of my knowledge). Apart from general grumbling when people first find out that extends can't be dynamic I haven't really heard anything about people playing with this (and I can get why - it's probably quite an edge case and you could argue against the whole approach).
So, anyone any opinions on this pro or con? Would anyone else be interested if such a feature made its way into LightWire? For anyone who likes the idea, any preferences on how it would work or the syntax it might use?
Any input gratefully received.



At first glance, this seems like a batch mixin. I know you have good reasons for why you want this. I am trying to grasp the implications of your proposal.
If you copied the bean innards into a temporary directory and then added your dynamic extends piece, it would require a file read and a file write, or maybe two. This might be something you could get away with for singleton objects, I would be loath to use such a thing for transients.
Maybe you could extend a generic object and have the generic object composed of the proper pieces through your DI framework? Sort of a proxy for the extended object.
DW
If you "had" to do this, you might be able do it using auto-generated code in "reactor"-type fashion. Let's say you have a base framework "B", and your customized code "C", which normally extends "B", but "B" could be anywhere.
To combat that let's say that there's a a factory "F", and set of generated classes, "G", such that "C" extends "G", which extends "B". You ask the factory for an object based on your custom class "C", and it tries to create it, and fails because the "G" class is missing or invalid. It then generates the "G" class file based on a configuration value so it points to the current location of "B", and tries to instantiate "C" again.
Since "C" extends "G", which now points to the correct location of "B", everything works. I think I'd prefer this type of intermediate class approach as opposed to attempt to correctly read, parse, and rewrite a user's cfc to "extend" properly.
I guess you're right that the other approach would be to dynamically build the base class using runtime mixins - that's actually a pretty interesting approach, so I need to go think about that for a while :->
@Michael, It isn't so much that the base code needs to be in a specific place, but that some of the base code must be smart enough to extend project specific base classes. Lets say the product object is different between each project, but the user object is the same for most projects. So, I keep the user object as part of the framework (I can overload it for the few projects that need a custom user object). BUT, for some of the projects, user should extend #project#.com.BaseObject and in others it should extend com.baseobject, and I want it to be smart enough to go look and see if there is a #project#.baseobject - if so, use it - else extend the framework base class. That's what I'm looking to do.
Does this information actually change at runtime? If not, why not just have your generator generate the appropriate code?
The idea greatly interests me, but I don't know that I'd use it here (of course, since I don't know how your system works, it may be the case that it completely makes sense to do so).
I think you guys already covered the options pretty well - those are the only 2 ways I can think of to do it at runtime.
To me only reasons to generate code are for higher levels of reuse (click a button to gen an entire site), for limitation sin language or for performance considerations (where there are many caching strategies - code gen just being one of them). So, for me gen is becoming as thin a layer as possible on top of a really rich dynamic framework. Seems to be working pretty well so far, will keep you posted!
Me too...
"So, for me gen is becoming as thin a layer as possible on top of a really rich dynamic framework."
That's what I've been calling "synthesis" as opposed to generation all this time.. I don't know if there is an official term for it, and if there is, I don't know if that is it...
I see the good point to having it. I didn't realize you were taking that route - I always thought you were just generating the files outright and not doing as much dynamic stuff as you could have been. =)
This might be woolgathering, but what about adding support for pseudo-interfaces instead? If I'm reading your use case right, making extends dynamic is like saying, "My object has this implementation". If you can end run extends, I think it would be more value to add "implements" instead. Project classes always extend their (Abstract) Base classes, but can also "implement" another class at the Base or Project level. Just wondering...
I could use composition, but then I'd have to write either a generic delegate or a set of delegate methods so suddenly my code isn't so dry as each business object would need to have a delegate method for each method in the base object. The whole reason I'm using base objects is so I can drop in a new mbase method and it is available to all of my business objects - makes major refactorings a breeze.
Make sense?
I see the app generation outpost across the gorge, but I haven't completely bridged the gap. ;)
Carry on....
In dev, there's one big web root i.e. wwwroot/bsgs, wwwroot/lights
to access via browser http://mySever.com/bsgs/ or http://mySever.com/lights/
In test, some of the sites have virtual hosts
to access the site http://bsgs.myServer.com
Using getContextRoot() you can figure out what the correct path to use in your extends attribute, except that this value can't be a variable . . . :(
This is an older lists of posts, if something's come a long that makes this possible, I'd love to know.
Everyone... EVERYONE has said time and time again "it can't be dynamic because it's a compile-time directive/attribute"... and well... everyone is wrong.
And I have proof.
Here's the zip of a sample to show you how it's done: http://ontap.riaforge.org/blog/enclosures/test1%2Ezip
And here's my own blog article where I talked about the discovery:
http://ontap.riaforge.org/blog/index.cfm/2008/5/27...
I will say it's not 100% bulletproof. I was toying around with it a little earlier today trying to make it work with some ColdBox event handlers and it seemed oddly that it wasn't finding methods that should have been in them. My best guess (without having looked into it or tested it further, 'cause this was just a few hours ago), is that the missing methods were previously injected into the parent class or some other ancestor class and that method of injection causes those methods to be unseen when you use a cfinclude like this to create a dynamic extends. But that's the first time it's just flat out not worked for me.
If you're able to work this into Lightwire somehow, awesome! :) If not, then at least hopefully it may help Trip and a few others with their problems. :)
http://ontap.riaforge.org/blog/enclosures/test1.zi...