02-04-2011 08:59 AM
Another PlayBook-related but effectively generic AS3 question for the experts:
Is it possible in ActionScript3 to "shadow" components in the standard namespaces? I use the term "shadow" in the sense of "replace/overwrite with alternate having the same name and signature, so any calls to the original go to the replacement".
Doing this is quite feasible and common for testing purposes in the Python world, because everything is dynamic. You can overwrite, for example, the "time.sleep()" with your own function, with the result that any code (your own, or even standard library code) that calls time.sleep() (which normally blocks for the specified number of seconds) will go to your function instead, which can do anything including returning instantly, or varying the sleep duration, etc.
If this were possible in AS3, I would imagine it would be quite feasible to build a library of qnx.* replacements for some of the items which are not supported outside of the simulator. Things like qnx.pps.PPSChannel, for example...
Does anyone know whether this is possible and if so, how you'd go about doing it? (I suspect it's not feasible for some reason, because if it were then I think we'd see someone having done it already, and releasing the package as open-source.)
Solved! Go to Solution.
02-04-2011 10:53 AM
If you create a library that maps the same class path (used in the import), then all you would have to do is include a different library file. Assuming that the API of each class is the same too. Then it would just require a re-compile to the alternate library.
In terms of API, a class that extends another class, any public or protected method can override the base method to capture or provide an alternative behavior.
But AS is not a runtime interpretted launguage like Python or PHP or XYZ. It has has to be compiled to have an alternative behavior.
02-04-2011 11:03 AM
So does the compiler "cherry-pick" the code for individual classes out of the libraries, and I could make my replacement (e.g. qnx.pps.PPSChannel) come first in some list and thereby get it included rather than the standard one? Or would it have to be in the same library as everything else in the qnx.* namespace (in which case I'd presumably have to fake all qnx.* classes, which isn't desirable or feasible)?
By the way, note that Python is not interpreted at runtime in the way I suspect you think. It is compiled to bytecode, exactly like AS3 or Java, and executed in a virtual machine just like those languages. The beauty of it is that because it's so highly dynamic, everything is late-bound (as each import statement is executed) so you can replace anything at runtime, rather than merely at compilation. It's a huge boon for testing, even with third-party code that was absolutely not designed for testability.
02-04-2011 11:23 AM - edited 02-04-2011 11:24 AM
My backend experience comes from a PHP background which is a runtime thing, which is nice for that kind of work.
I dont think you can do it on an individual class basis. You will probably get a compile error if 2 libraries have the same class path. Maybe the compiler keeps in mind the order of the libraries added to the project. Just dont know. I wish AS3 had compiler directives like C/C++ has (and others assumed), then you could do some #ifdef/#define, etc. to choose which to include during compile, but it does not.
It would be an easy test to take any class for an exsiting library to see if the order of the libraries matter.
So you're thinking that if AIR had PPSChannel stubbed out that those runtime errors might go away? That would be cool. I did submit an issue ticket a couple of weeks ago asking that things like PPS be supported in some fashion so development could continue in AIR which makes it a lot faster than going to the simulator each time. Even if the simulator was reliable, it would still be faster to develop in AIR.
02-04-2011 11:30 AM
So you're thinking that if AIR had PPSChannel stubbed out that those runtime errors might go away? That would be cool.
Yes, definitely. You'd do whatever was needed to "get by", from a simple stub routine that ignores all its data (suitable for "write only" things like code that makes the virtual keyboard appear), right through to a collection of inter-related routines that fake a more complex operation using some shared state. In effect this gets into the whole area of mock objects and test-driven development.
I don't think either QNX or RIM is showing any particular signs of strength in terms of agile development, which may be one reason why this sort of thing (apparently) wasn't anticipated. If they had that philosophy, then even if they didn't have the resources to do it all themselves, they would simply expose enough pieces to the community that we could implement it ourselves.
02-04-2011 12:28 PM
That's one reason why I wrote a replacement to the dialog package. Agree about the agile development and the way the simulator works with the QNX API. I've started to work on a AIR simulator that can work with a QNX AIR application for things like swipes, GPS, Accelerometer, orientation changes, etc. Basically have an AIR application send messages to an AIR application on things that PB would do in an artificial way. It's still in development but it would allow for automated testing and test cases that would be hard to do either in the simulator or even the actual PB.
02-04-2011 12:34 PM
Alot of Flash/Flex developers call this Monkey Patching. Its much easier to do if you have the source code because you would just make a couple of the Class file (same package and same class name) in to your project and make your changes.
For this case if you really wanted to try it, you would have to create a PPSChannel class with the same name and package in your project and then implement (or mock) all the public (and probably protected method if PPSChannel is inherited by other class which it might not be). So doing it with out source is much harder but it could be possible.
Of course mocking up the classes to just get rid of errors doesn't help if those classes actual provide functionality that you want to test, but if to just test UI layout stuff I could see the benefit.
02-04-2011 12:52 PM
Renaun, thanks for the reply. It sounds like you're suggesting it could be done just to an individual class, without requiring that you effective replace the entire library in which the target class is found. Is that possible? Do you simply provide your replacement in another library that you include earlier in the search path? Can you even just implement it as .as code in the same project, without pre-packaging it into a library (which I assume is all a .swc file is)?
Depending on a few things I don't know yet, and assuming this is possible, it may well be possible to create your mock even without providing all the methods the original had. At least in other environments (generally with purely dynamic languages) you need provide only those which are actually called by anything external. So if a given class such as qnx.ui.text.TextInput did nothing with the PPS stuff except instantiating a PPS() object and calling open() on it, then pps.addEventListener(), then only a constructor, open(), and addEventListener() would be needed.
"Mocking" of course isn't used if you're trying to test functionality requiring the unmocked objects... by definition you do this when you want to remove that original code from the picture, and any remnants of its behaviour that you need to fake are exactly what you mock.
02-04-2011 02:59 PM
There are a few options but without the source its pretty much a shot in the dark. I went ahead and tried one method and it worked for the classes that error out because of PPSChannel. Basically I added a qnx.pps.PPSChannel class to my project and did nothing so the error would go away.
Again this will affect QNX classes functionality but it at least gives you the ability to do UI layout/design on the desktop instead of publishing out to the simulator a bunch of times.
Here is the full write up on how to do it:
02-04-2011 03:11 PM
It seems like, if QNX actually wants people to use their Dialog classes in more complex apps, they need to provide this to us anyways.
For now we've completely cut QNX Dialog's because of the drain they would have on our efficiency. Which is a shame, since it's a nice set of components.