Question about class resolving

90 views
Skip to first unread message

Tero Tolonen

unread,
May 22, 2013, 12:36:21 PM5/22/13
to haxe...@googlegroups.com

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










Simon Krajewski

unread,
May 22, 2013, 12:45:32 PM5/22/13
to haxe...@googlegroups.com
Am 22.05.2013 18:36, schrieb Tero Tolonen:
>
> Is it possible to write a custom class-resolver using Haxe?

You could probably pull of something like that with a macro and
Context.onTypeNotFound:
https://code.google.com/p/haxe/source/browse/trunk/std/haxe/macro/Context.hx#181

Simon

Tero Tolonen

unread,
May 22, 2013, 1:38:02 PM5/22/13
to haxe...@googlegroups.com

That was as interesting reference, thanks for suggestion.

I'm not sure if onTypeNotFound works, since the type information should of course be available for the
compiler, because in most cases the class to be refactored already exists and removing it might left the compiler
sitting on top of nothing. If it can be done, then it's some kind of black magic I just can't understand :)

More or less, that was more like a proposal - in practical situations sometimes you need to quickly replace
some classes at one step to another. And sometimes it's good to have both versions available at the same time and
to have ability to roll the change back or clean up the code. It can be also handy for logging and creating security
restrictions on certain parts of the code.

PHP's approach of not declaring classes is quite silly actually. All the classes has to be named the same way
which can be very confusing to editors. But it is also very practical thing to have, if you know how to use it, while
being certainly more limited compared to real OO patterns.

Tero Tolonen

unread,
May 23, 2013, 2:17:43 AM5/23/13
to haxe...@googlegroups.com

Actually, that operator overloading idea was invented during writing the post, I have been looking for framework that would help in this matter but hadn't realised it would be possible to solve in such a simple way.

It has some advantages of aspect oriented programming, but does not break OOP paradigm, for example creating logging for a simple function
would be as easy as

1) inherit class to be observed
2) overload function to be observed and create logging code by wrapping / rewriting the function
3) create factory method for conditional overloading for the logging case
4) use resolver to overload new for the desired class/classes

I do not like aspect oriented programming because it introduces a lot of unnecessary syntax and creates non
local changes in a way that is not familiar to programmers, and it may be hard to test them modularly. This way you
might also enjoy some of the good parts of aspects in standard way. Only if some language would support it :)

Tero Tolonen

unread,
May 23, 2013, 7:40:08 AM5/23/13
to haxe...@googlegroups.com

Feels like I'm talking to myself here ;)  - but skip the thread if you do not like it.... I know it's difficult subject

Ok, perhaps I've said enough. Here's an old Dr.Dobbs article talking about this problem, which I find very annoying 


"There is a difference between requesting an object and creating one. The first is an abstraction; it should be designed into a class and should be under the class's control. The second is a low-level implementation detail. Java's new keyword, the standard way to obtain objects, provides only the latter. Thus, most requests for objects end up being nonpolymorphic heap allocations, whether this is a good idea or not. In short, new should be considered harmful for the same reason that goto is considered harmful — although it is an indispensable low-level tool, it must be used with care or hidden behind abstractions."

While the new -keyword dependency is a clear problem, I just fail to see why there's so little will or effort in trying to address it - perhaps it's 
too fundamental problem and while it's causing a lot of pain, people are just willing to live with it, because it's a traditional knowledge that
there exists software patterns to solve these problems. And don't we all just love software patterns?

But like I have written previously, this problem should be quite easy to fix with a simple compiler annotation - without introducing any
problems with existing code and also making all code ever created and using the "new" keyword refactorable -  perhaps the implementation
at the compiler level is not so trivial, but this could be something that fundamentally changes how programs are created. In short, what I'm proposing is:


 // if this or simpilar compiler annotation exists, directive name "resolver" or whatever
 
@resolver(MyClass, MyFactory)
 
// then if "new" for MyClass is found like:
 
var o : MyClass = new MyClass(...)
 
// replace it with this
 
var o : MyClass =  MyFactory.MyClass( .. )
 
// and compile code normally, compiler warnings will tell if the factory is ok and working as expected


I would really like to hear comments from people who have been involved in creationg of a "new" [sic] language like Haxe, since I have little
knowledge about compilers and easy / difficult it would be to implement something like this in a language?

Right now this is mainly academic exercise, but it could turn out to be something extremely useful.

Rocks Wang

unread,
May 23, 2013, 12:24:18 PM5/23/13
to haxe...@googlegroups.com
Sorry I did't read your post very carefully, but I think you are talking about something like DI (Dependency Inject) or in other term IOC (Inversion of control).
I just made a quick search in haxelib, and found there're already some very cool libraries, such as unject, minject

在 2013年5月23日星期四UTC+8下午7时40分08秒,Tero Tolonen写道:

Tero Tolonen

unread,
May 23, 2013, 2:11:30 PM5/23/13
to haxe...@googlegroups.com

What I'm looking for is just a very simple change on compile time, to make the standard new statements
for a given class to be delegated to factory method. 

Of course this is breathtakingly simple to solve in various standard OO -ways without IOC/DI ways. Just create
a function like
 
  class Foo {
     
public static Create() : Foo  {  return new Foo(); }
 
}

So, what you now only need to do is to always call
 
var o:Foo = Foo.Create()

Not so hard? Of course not, solves all the problems instantly, but what if the Foo is used in many places? You have to go
through the source code to look for places where Foo has been instantiated and manually replace all instances and replace
them manually.

But why not to have an annotation to tell compiler to do this automatically? This way programmers would just use the familiar
syntax everywhere and have the benefits of all the patterns and even more.

Tero Tolonen

unread,
May 23, 2013, 2:53:33 PM5/23/13
to haxe...@googlegroups.com

Ok, I can see one problem here, if the compiler would do that to all instantations of the class, then that class
could not be instantiated at all, even in the factory function, because it would recursively call itself :)

It is solvable problem, but a problem still.




Tero Tolonen

unread,
May 24, 2013, 3:25:02 AM5/24/13
to haxe...@googlegroups.com
Perhaphs i will try to adopt the way

o = TClass.Create(Params)

For instantiating objects in the Haxe code I write. Perhaps with inline keyword there would be no change in resulting performance even

Reply all
Reply to author
Forward
0 new messages