deftjs / DeftJS

Extensions for Large-Scale Sencha Touch and Ext JS Applications
http://deftjs.org/
MIT License
285 stars 56 forks source link

Tweak factory function parameters and scope #35

Closed johnyanarella closed 11 years ago

johnyanarella commented 12 years ago

Per the Sencha Forum discussion and Deft JS mailing list discussion on this topic:

superstructor commented 11 years ago

I am currently working on this.

In preparation I have ported Deft.ioc.Injector specs from Jasmine to Mocha. This is based on the promises_aplus branch as master does not appear to have Mocha tests.

See https://github.com/superstructor/DeftJS/blob/feature/35/test/coffee/Deft/ioc/Injector.coffee

Next I will port Deft.mixin.Injectable specs.

Each spec file port will be in an independent commit, and so will the fix for this issue (3 commits total).

Do you want 3 pull requests with 1 commit each or just 1 with the 3 commits ?

Should I wait until promises_aplus is merged into master to open a pull request since I am based off that branch ? Obviously I'll rebase as appropriate.

Cheers

superstructor commented 11 years ago

Discussed with @johnyanarella

Will do

Cheers

superstructor commented 11 years ago

Deft.mixin.Injectable specs ported to Mocha are here https://github.com/superstructor/DeftJS/blob/feature/35/test/coffee/Deft/mixin/Injectable.coffee

superstructor commented 11 years ago

Changes for this issue with tests are done.

Just have two failing tests, that from debugging I don't believe are a bug in the code but a bug in the tests themselves.

The factory functions are executed in the targetInstance scope and passed all of the constructor arguments as parameters for automatic injection.

In addition to the original requirements of the ticket I pass targetInstance.getInitialConfig() to the factory function as a parameter when called via manual injection with .inject() on an existing targetInstance. This is as close to the automatic injection parameters I can get without writing a class pre-processor to capture initial constructor arguments and stash them somewhere for later "just in case" you manually inject something. My view is that would be an unnecessary performance and memory burden.

As soon as promises_aplus is merged I can make a pull request.

Cheers

superstructor commented 11 years ago

https://github.com/superstructor/DeftJS/tree/feature/35

johnyanarella commented 11 years ago

Excellent! This sounds great.

promises_aplus was just merged into master.

johnyanarella commented 11 years ago

I see your point about the complexity and overhead of capturing the initial constructor arguments. Agreed, that would be a very bad idea from a performance and memory perspective.

So, digging into Ext.Basefor both Ext JS and Sencha Touch, it turns out that instance.getInitialConfig() returns the merged configuration object (i.e. this.config), rather than the original configuration object that was passed to the constructor. However, Ext JS 4.1+ and Sencha Touch 2.0+ all have an instance.initialConfig property that does contain the original configuration object that was passed to the constructor.

Swapping out the use of targetInstance.getInitialConfig() in Deft.ioc.Injector for targetInstance.initialConfig makes those tests pass as expected.

However, the instance.initialConfig property is not available in Ext JS 4.0.7. @brian428 At this point - do we care about supporting 4.0.7? The documentation already refers to 4.1 as the oldest supported version.

johnyanarella commented 11 years ago

Awaiting feedback re: use of instance.initialConfig.

johnyanarella commented 11 years ago

It looks like instance.initialConfig is undocumented, so it could potentially disappear in future releases of Ext JS or Sencha Touch.

We could potentially solve this with an override for Ext.create() that mimics how instance.initialConfig is initialized, but with an instance property of our own (ex. instance.$initialConfig). Since it would be a reference to the same object instance.initialConfig is already holding on to, I'm not too worried about the memory impact.

johnyanarella commented 11 years ago

Crud. instance.initialConfig is only populated for classes that call initConfig(). (And Sencha's own classes don't consistently adhere to that convention.)

brian428 commented 11 years ago

John, we already have some unit tests that fail in versions prior to 4.1. I have no problem dropping support for it. Knowing that we would at some point was part of the reason I gave 4.1 as the "officially" supported version in the docs. No one's complained yet....I can't imagine there's many people left using 4.0.x.

johnyanarella commented 11 years ago

For the scenario where a factory function is fulfilling a dependency via a manual call to Deft.Injector.inject() on an already instantiated class instance rather than as part of the instance initialization via inject:, I'm inclined to omit the config parameter argument entirely. As @superstructor already noted, we can't send the factory function the rest of the original constructor parameters anyway.

We're talking about an advanced edge case here. A factory function being used in that manner would more likely inspect the target instance itself, rather than needing the original parameters that were passed to its constructor.

I'm also having second thoughts about breaking any existing factory functions in use today by changing the scope that factory function is executed in and no longer passing the instance as the first parameter.

At this point, I think I'd rather see us:

This gives some degree of consistency between the two scenarios - both are passed the target instance, and the constructor arguments are essentially optional parameters.

Thoughts?

superstructor commented 11 years ago

:+1: Agreed.

superstructor commented 11 years ago

Pull request made with requested changes.

Cheers

johnyanarella commented 11 years ago

Excellent work. Thanks again!