Is it possible to write a custom class-resolver using Haxe?
If there is two or more classes that could act as myClassType, usually you create something like:
var obj : myClassType = Factory.createMyType();
The problem with this is that:
1) it requires creating a local depenency to the Factory class at the code level at each point of usage
2) if class is used by libraries not under your control, changing the new to Factory may not be possible
3) you have to give up using the "new" statement for something that only compiles with your Factory code
4) there's no easy way to check all dependencies has been solved (i.e. some place still is using new)
5) there's no easy way to roll back the change, if you want to go back using the standard "new"
With class resolver you might say that class myClassType is @resolvableby(MyResolver) like
@resolvableby(myClassType, MyResolver);
And then just instantiate the object:
var obj : myClassType = new myClassType(a,b,c);
The compiler could then check if there exists some resolver called MyResolver for this class type and create
the required code (which would be actually the same as abstract factory code) in place. It might be something like
class MyResolver {
public static function myClassType( a,b,c ) : MyClassType {
// do some checks etc... has the user right to use this class, are we in staging environment, do we need logging etc.
return new myClassType(a,b,c);
}
}
The good thing is that compiler would make sure all lines of code using this class are actually using the resolver,
which is important if you are refactoring existing code. The default would of course be that no Resolver found and
code works as previously. Perhaps the resolver class could also be resolvable by another resolver, don't know.
The class resolver could then act as abstract factory and return class instance of myClassType.
Using modified like @resolvable would prevent compiler creating unreasonable overhead over
classes that do not need actual resolving. Basicly compiler would only replace the line with new to something like:
var obj : myClassType = MyResolver.myClassType(a,b,c);
Thus the change would be quite minimal and require only implementing the @resolvableby and checking of existence
of the class returning class of correct type. If I don't like the change or want to use some other factory I can either
just remove the directive or change or rename the factory to something else or even use it with compiler directives
to be included on some platforms and to be removed on some others.
The point of this is simply that sometimes you want to simply upgrade bunch of classes to a new version(s),
and do not want to pollute your code with creating abstract factories all over the code nor create
global bindings between your code and the factory. This is quite practical in server side, where you first
want to test previous version in staging environment and then replace the old module - or to do rollback
if the change failed. There are also many other usage patterns, many of which I can't even imagine.
The problem with this approach is that it hides the implementational detail that the actual version
of the object may or may not be determined run-time. However, it does not prevent using the normal
Abstract Factory Pattern in any way, so it's up to the programmer to decide.
NOTE: PHP has this so called "autoloader" -feature, which can be used to autoload classes partially to the
same effect. However, because in PHP new autoloaders can be registered run-time the behaviour of the PHP's
autoloader can be unreliable - the first autoloader who find's the class wins. Furthermore, because the classes
are loaded at run-time, this approach requires "magical" runtime. Having the OOP based factory created
during compile time would make possible using this approach with a bit more stability and even on
environments not having any magical runtimes. The PHP's "autoloader" is also lacking in the sense that
it only works once: after the class has been loaded, it simply uses the same version throughout the execution
of a single file. The real abstract factory pattern should of course be able to select the correct class each
time the "new" command is executed. The PHP version also bring unnecessary overhead to classes that
do not need to be "autoloaded", because the autoloader is called whether you want it or not. When the
resolver is injected compile-time, you don't have any unnecessary code