-
-
Notifications
You must be signed in to change notification settings - Fork 407
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Injection Hook Normalization #467
Conversation
details. There are several ways we could move forward with disconnecting | ||
these: | ||
|
||
1. We could move the container in a more annotation based direction, as |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sure a lot of thought has gone into the form factor here, but I'm going to offer my less-deeply-considered 2¢ anyway 🙂
My gut reaction to this proposal is that normalizing injection across the board is excellent for API consistency, but I have a fairly strong preference for something akin to @start
and @teardown
over didCreate
and willDestroy
.
One of the things I really like about the Glimmer component API is that it relieves a lot of the cognitive burden that the classic API placed on developers in the form of special method names they needed to be aware of. Moving those things to be explicit opt-in annotations in the template eliminates a lot of implicit "magic" and makes it much easier for someone new to Ember to understand why a particular method is being called.
Explicitly annotating methods that should be invoked as part of the container lifecycle feels like the moral container equivalent of the move to render modifiers for component lifecycle events. Putting aside the hypothetical @glimmer
and constructor parameter @service
decorators (which I agree would be a much bigger shift), it feels like @start
and @teardown
could fit neatly into the injection system we have today?
I'm not a fan of two phase setup ( From a more small details perspective adding |
If DI and properties are not ready until after the constructor, then it would seem that the constructor would be useless in most cases, right? |
@btecu the constructor would still be implicitly used for setting up class fields, and more generally for setting up the class instance - e.g. shaping, setting initial properties, etc. But yes, in most cases users would likely want to use @rtablada that's definitely a fair point, I agree the confusion would be annoying. I think the long term goal here is that we would get to explicit constructor injections: class Foo {
constructor(@service store) {
//...
}
} Which would give users control over the DI in their classes, instead of locking us into an API where we always pass the owner as the first parameter. Unfortunately, I think @dfreeman's point makes some sense in that regard - it's a larger delta, but adding decorators that allow you to specify if a function is a hook at least means users can name the hooks whatever they want: class Foo {
@start
setupWebsocketConnection() {}
@destroy
teardownWebsocketConnection() {}
} Or, alternatively, we could standardize on always passing the |
01c1c13
to
d7bab7e
Compare
I think the "How we teach this" section would benefit from a quick writeup of what the API docs entry should be, plus showing what an example in the Guides would be updated to look like. It's a little hard to tell currently what the proposed solution is. |
`init`. Since the `owner` and arguments are assigned before `init`, it won't be | ||
necessary to add any assignment code for these. | ||
|
||
Importantly, _only_ classes that are constructed by the container will have |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is .create
is manually called but ownerInjection
is provided?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If someone manually creates a class like this, then it is not being created by the container, so it will not trigger the conatiner lifecycle hooks
I am definitely against breaking glimmer components at this point, even if it is not technically a violation of semver. |
We ended up updating the Injection Parameter Normalization RFC and FCPing that, which means we will not be breaking GlimmerComponent. This RFC will be updated in the near future to reflect that. |
I really like the flexibility that the decorators afford with native classes and splitting out the setup/ tear down logic related to DI. |
I feel like this is trying to fix an issue that Ember created for itself. It's very confusing even for someone who used Ember for about ~3 years. 3 ways to init an object, Look at how React introduce My main issue with this proposal is probably that it compromises the future API of Ember (by making it overly complicated), just to satisfy what I would call "legacy API". |
While these new decorators would solve the issue. I think having a mild breaking change here would be easier to accept instead of increasing API surface. |
@piotrpalek the discussion we had at the face-to-face actually reflected a lot of what you just said. There were a lot of concerns that this was too complicated as a user facing API, and that it would be problematic to teach and convert forward too. What came out of that discussion is that for Ember base classes and objects, such as Components, Routes, Services, etc. we want to have a simple, uniform API for component lifecycle. We landed on:
You can follow that in #451, which has been FCP'd. However, building our DI system around this contract is not super flexible, should it need to change in the future. It also means we can't easily inject any other code from the JS ecosystem. For instance, say you wanted to register a Redux store - you would have to create an Ember class that wrapped the store, which is probably less than ideal (more code + maintenance work whenever APIs need to be updated). This RFC will be updated soon, but the idea now is that these decorations will be low-level APIs that we use to setup Ember's base classes, but can also be used by advanced users to setup their own classes that are registered on the container. |
@pzuraq This design speaks to me :) I don't understand the drawbacks entirely. When you say "create Ember class" you mean one based on |
The contract in #451 is actually a bit more general than that. It means that for all classes that we provide to users to extend, this is the API that the class will have. Glimmer components, for instance, don't extend from As for the Redux store, the issue at the moment is that you would need to extend the store and add a static |
Thanks! I think I get it now. I'll wait for the updated RFC with more questions :) |
DANGIT! Sorry y'all, totally messed that up, I crossed my wires... |
Rendered