To be honest, I would do this the way jzut is suggesting. I do realise that you want to avoid letting others know where Users come from, but do you see that this is already a disconnect with the requirement to have others tell Lookup::Remote where to find Users? I think that this is already an abstract problem - concrete code can't fix an abstract problem.
Solution #1: give the User package a list of Lookup objects, all pre-configured, which is the order that the lookup is done. The advantage here is that the User object doesn't need to change just because you add more lookup objects to the queue. Of course, in your scenario, this could be a completely useless advantage, I'll leave that judgement call to you.
Solution #2: have Lookup::Remote be completely self-contained. This means it has to statically or dynamically figure out where to look stuff up. Either this means that it has the URI(s) hardcoded in it, or it has its very own config file/table/whatever which it uses to look up this type of thing. The problem with dynamics here is that the caller still needs to be aware of this if only to properly configure it indirectly.
In my big project at work, since it's all one big inter-connected mess, I usually put module configurations in global config files, which are represented in perl through singleton objects, and then other objects can query the singleton (MyGlobals::fetch()->get_value('User_URI') as an example). It's actually an XML-like file where I can have subsections for different areas of the code, but still a single config file for everyone.
In the rare occasion where I feel a module really is just a utility function that has little to nothing to do with the project (other than it's used by the project just as File::Spec or File::Copy are used by the project), the constructor to the object takes the info it needs, and the caller needs to set it up.
However, I don't generally have multiple layers of it. ;-)
New thought. You can still have the caller initialise the User package - the caller doesn't need to realise that the User package uses Lookup::Remote to pass in URIs. This is keeping in line with the way that CGI::Session or DBI work - you pass in something which is parsed and a subclass is dispatched to do the work. Nothing says you can't use something that isn't a subclass as a factory based on the input - nor that the input must be passed in to the constructor vs being pre-set via some package method.
|