Skip to content

Pre-RFC: Deprecate implicit injections (owner.inject) #508

@rwjblue

Description

@rwjblue

I'm defining "implicit injections" as the type of injection where nothing exists in the class body (or inherited from the parent class), but a property is magically present anyways. These types of implicit injects are nearly always done from initializers or instance-initializers (both of which should also die in a 🔥, but that is another issue). Examples of these implicit injections are using this.store from within an arbitrary Route / Service / Controller / Component without first specifying store: injectService().

Implicit injections have long been a source of confusion for new comers and old-timers alike.

Where does this.store come from?!

Since the advent of Ember.inject.service (from waaaaayyy back in Ember 1.9.0!) we have had a much better way to bring in external collaborating services like this. Explicit injections are massively easier to reason about since you can easily see that the class itself (or its ancestor) defines the injection.

As mentioned above the most used implicit injection is this.store (though there are others) which might indicate that this is "Ember Data's problem", but due to the nature of these implicit injections there is really no way that ember-data can actually deprecate usage of these implicit injections. If ember-data removes the initializer that sets up the implicit injections, it is clearly a breaking change. ember-data has no way to ensure that the store property emits a deprecation (but only if not "clobbered" by store: injectService()) which means that it can't even be removed in a major version bump due to Ember's unique SemVer commitment (to not remove any undeprecated public APIs in a major version bump).

We must provide a mechanism to deprecate these implicit injections wholesale. They are bad, they make our programs harder to understand, 🔥🔥🔥.


Concrete implementation suggestion:

  • Add an argument to owner.inject that allows the caller to specify that the injection is deprecated, which version it is deprecated until, a deprecation id, and a url for reading more about the deprecation. (For those of you following along, I've just described the options argument to @ember/debug's deprecate method 😉)
  • In debug builds, when this deprecation options argument is passed, Ember will automatically setup a getter for the deprecated injected property on the target object when the object is created.
  • Sometime later, issue a deprecation when the owner.inject is not provided that new extra "deprecations" object.

The goal of this pre-RFC is:

  1. To circulate the idea of pushing this forward
  2. Find an author that has the time to work with me on the final detailed design and put together the deprecation RFC
  3. Help with implementation of the RFC once landed

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions