Skip to content

Discussion: Rename DI Bindings into Providers #4416

Closed

Description

@vsavkin

Using the same word "binding" for two core ideas of the framework causes some confusion.

Proposal: Rename Binding into Provider, and bindings into providers.

@Component({
  providers: [
    // the constructor version  
    new Provider(Http, {toClass: CustomHttp}),

    // using builder
    provide(Http).viaFactory(customFactory),

    // using a different type of builder
    provide(Http, {value: customFactory})
  ]
})

Pros:

  • Similar to Angular 1
  • Binding means only data-bindings

Cons:

  • Different from other DI systems, which mostly use the word binding

@IgorMinar @mhevery

Activity

  1. hess-g commented on Sep 29, 2015

    @hess-g

    +1. I was just writing up my observations on my first 2+ week deep-dive into Angular 2, and one of them was:
    Overloaded terminology may cause confusion when learning the framework.
    “A component has property and event bindings” (ref)...but also has a property ‘bindings’ which is its private dependency injector.

    Related to this issue, this discussion about annotating for emitting metadata: this change might lean that in favor of something like:

    @ProviderConsumer
    class DataService {
      constructor(http: Http) {
      }
    }
    
  2. vicb commented on Sep 29, 2015

    @vicb
    Contributor

    I'm with @vsavkin on this.

    I think it would help with @HostBinding (we can then keep this name). I was thinking about this renaming when submitting the issue about HostBinding but didn't end up proposing because bind seems like a common terminology for DI (see Guice) - I personally don't mind dropping bind.

    We should rename toXXX as well: new Provider(Http, {toClass: CustomHttp}) does not sound right.

  3. 0x-r4bbit commented on Sep 29, 2015

    @0x-r4bbit
    Contributor

    Think it would be viaValue() and viaClass() then. I understand why
    renaming that concept (yet) again might be good. But we should keep in mind
    that people got used to the term "binding" now. Also, using the term
    "provider" might make people think that we have the concept of providers
    like in A1 again...

    Although otoh that's what a provider is somehow all about, even in A1.

    On Wed, Sep 30, 2015, 12:08 AM Victor Berchet [email protected]
    wrote:

    I'm with @vsavkin https://github.com/vsavkin on this.

    I think it would help with @HostBinding (we can then keep this name). I
    was thinking about this renaming when submitting the issue about
    HostBinding but didn't end up proposing because bind seems like a common
    terminology for DI (see Guice) - I personally don't mind dropping bind.

    We should rename toXXX as well: new Provider(Http, {toClass: CustomHttp})
    does not sound right.

    —
    Reply to this email directly or view it on GitHub
    #4416 (comment).

  4. 0x-r4bbit commented on Sep 29, 2015

    @0x-r4bbit
    Contributor

    @hess-google I think you're confusing two different things here. Providing
    a binding for DI and injecting something are not the same thing. I don't
    think that this renaming will help with the enforcing of emitting metadata
    in typescript.

    However, I do agree that "binding" is a heavily overloaded term in A2

    On Wed, Sep 30, 2015, 12:15 AM Pascal Precht [email protected]
    wrote:

    Think it would be viaValue() and viaClass() then. I understand why
    renaming that concept (yet) again might be good. But we should keep in mind
    that people got used to the term "binding" now. Also, using the term
    "provider" might make people think that we have the concept of providers
    like in A1 again...

    Although otoh that's what a provider is somehow all about, even in A1.

    On Wed, Sep 30, 2015, 12:08 AM Victor Berchet [email protected]
    wrote:

    I'm with @vsavkin https://github.com/vsavkin on this.

    I think it would help with @HostBinding (we can then keep this name). I
    was thinking about this renaming when submitting the issue about
    HostBinding but didn't end up proposing because bind seems like a common
    terminology for DI (see Guice) - I personally don't mind dropping bind.

    We should rename toXXX as well: new Provider(Http, {toClass: CustomHttp})
    does not sound right.

    —
    Reply to this email directly or view it on GitHub
    #4416 (comment).

  5. robwormald commented on Sep 29, 2015

    @robwormald
    Contributor

    I've long thought this was sort of confusing too. That said, I feel like "providers" as key sort of isn't much better.

    I've just been referring to things as "services" and "components", personally. So:

    @Component({
      services: [ 
        bind(Thing).toValue({foo: 'bar' })
      ]
    
    })
    

    Most ng1 users are quite happy with the term service, I think.

  6. mhevery commented on Sep 29, 2015

    @mhevery
    Contributor

    @wardbell and @matanlurey do you have comments? I am leaning towards changing this to providers

  7. IgorMinar commented on Sep 29, 2015

    @IgorMinar
    Contributor

    +1 for naming change, but we should take a look at the big picture view and see how this impacts all the public apis (e.g. hostBindings, bindings, is there more?)

  8. wardbell commented on Sep 29, 2015

    @wardbell
    Contributor

    I want to change it from bindings as well. Way overloaded.

    The problem with providers is that it introduces _yet another new concept_ ... something we don't need right now.

    I'm inclined toward @robwormald suggestion of services ... although that introduces a new concept as well albeit a familiar concept.

    We already teach "dependencies" as part of Dependency Injection.

    Why not call the property dependencies.

    The picayune might notice that we sometimes have to supply an explicit binding in the array rather than the name of a dependent thing. I don't mind. But if someone did, then all of the suggestions fail because none of them mention bindings of any kind.

    In which case, I would vote for the lengthy but accurate dependencyBindings.

  9. 0x-r4bbit commented on Sep 30, 2015

    @0x-r4bbit
    Contributor

    @wardbell I think dependencies would be too generic, since we also have a directives property in the @View() decorator, which are also some sort of dependencies. Ppl might wonder why those are not treated as "dependencies".

  10. mgechev commented on Sep 30, 2015

    @mgechev
    Member

    I agree that dependencies is too generic. services seems too specific. Especially if we bind to a value or a factory it doesn't make a lot of sense to me.

    I'm for providers although I realize it may create some confusion to the users who are familiar with AngularJS 1.x.

  11. ericmdantas commented on Sep 30, 2015

    @ericmdantas
    Contributor

    So, we wouldn't have viewBindings and bindings anymore, it'd be just providers?

    Also, even though it might cause some confusion at first:
    provide(Something).viaFactory(() => new SomethingElse('yay')) sounds cool.

  12. 0x-r4bbit commented on Sep 30, 2015

    @0x-r4bbit
    Contributor

    It really does.

    I think we'd have providers and viewProviders then.

  13. wardbell commented on Sep 30, 2015

    @wardbell
    Contributor

    As a matter of pure English and within the world of s/w, provider and dependency are equally generic.

    The biggest problem with provider is that it is yet another word in the Angular lexicon. We don't need more of those.

    What does a provider provide? How is it used? If you were to answer in this context, you would say it provides something that is injected into another thing.

    We have that word already. It is called a dependency. We teach that early to every would be Ng dev.

    When I read dependency my knee jerk reaction is "something that will be injected into the constructor, either tho component's constructor or the constructor of one of its dependencies."

    And that is precisely the reaction we want the dev to have here.

    Nothing new to learn. W seen this before. You're telling Ng what should be passes to a constructor. I get it. Done.

    For these reasons... familiar term, correct instinct (instinct, nor reason) about what to do and what will happen... I favor the unambiguous dependency

  14. wardbell commented on Sep 30, 2015

    @wardbell
    Contributor

    My phone mangled my text. "instinct, not reason". The point being that the dev doesn't have to understand or reason about "providers". She simply knows without thinking that she must supply a thing that goes into a constructor because that's what she learned to di she she leaned dependency injection.

  15. 25 remaining items

  16. added this to the alpha-41 milestone on Oct 10, 2015
  17. added a commit that references this issue on Oct 11, 2015
    c0474b8
  18. endash commented on Oct 11, 2015

    @endash

    I'm a bit late to this particular renaming party, but I'd be remiss if I didn't point out that the provide/as dichotomy is backwards... the as is what we're providing and the provide is the signifier, exactly the opposite of what we're communicating. When using "provide" in this particular sense, the direct object must be the thing that is being made available for use. In this case, we're not providing a token (which we already have), but rather the {class, value, factory} to which it is bound. This is true in both the sense of providing something to the injector as a developer, and in the sense of the injector providing something to the consuming classes.

    One solution is to subtly shift our understanding of provide from "making available for use" to "making adequate preparation for an eventuality." This is the same sense in which a person is a "provider" for his or her family, or provides for retirement by saving/investing. In the first case, we provide something, full stop. In the second case, we provide for something. We provide for [use of] a given token by registering the class/value/factory. By dropping as and prepending for we resolve any ambiguity:

    provideFor(Foo, {class: Foo});
    provideFor(Foo, {value: "foo"});
    provideFor(Foo, {factory: (bar) => { }, deps: [Bar]});
    

    |
    |

    Alternatively, some other verbs that might work better with the existing syntax, instead of provide:

    provision(Foo, {asClass: Foo});
    

    OK that's the only one I got.

  19. 0x-r4bbit commented on Oct 11, 2015

    @0x-r4bbit
    Contributor

    I'm not an english native, so for me it's prolly less of a problem than for others. But seeing your code sample @endash I see the problem that the actual token is always at the end of the line, which makes it hard to read, if you really just want to find out what you get for a certain token. I think that having the tokens at the beginning is the better way to go here.

  20. endash commented on Oct 11, 2015

    @endash

    @PascalPrecht I was just thinking about that. There's no reason it can't be at the beginning, since it's a hash. It's not so important IMO that it be "readable as natural english", rather that the natural english reading shouldn't imply the opposite of what it does. Granted, it's somewhat self-documenting (once you've seen a few examples) on account of the fully qualified names asValue, asClass, and asFactory, but the construction is so unnatural it is unnecessarily unclear what is actually going on.

    (I've edited my comment with some potential alternate forms, and I've settled on provideFor as the preferred form so far as provide is concerned)

  21. IgorMinar commented on Oct 11, 2015

    @IgorMinar
    Contributor

    @endash I think you have a fair point. I like your provision proposal. Could we still keep the provider term for the result of calling provision?

    @vsavkin @mhevery ?

  22. endash commented on Oct 11, 2015

    @endash

    @IgorMinar I don't think there's any obstacle to calling the result of provision a Provider. They have the same roots, and mean similar things. In a way, it actually makes more sense to call the result of a provision call a Provider than it does to call the result of a provide call a Provider, since at that point it seems, per the language used, that the providing's already been done, don't it?

    A third possibility is to tack an r on and have providerFor

  23. mhevery commented on Oct 11, 2015

    @mhevery
    Contributor

    If you want to call them provisions then the @Component({}) should take provisions like so:

    @Component({
      provisions: [
        provision(Foo, {asValue: 123})
      ]
    })
    

    At the end of the day I don't see any objective way of showing that provisions is better then providers. As long the Angular's documentation is consistent I don't think it makes much difference.

  24. endash commented on Oct 11, 2015

    @endash

    @mhevery did you read the comments? No one suggested renaming providers. The problem is currently we're misusing the verb provide in a way that is, yes, objectively incorrect.

  25. choeller commented on Oct 12, 2015

    @choeller
    Contributor

    Hi everybody,

    also a bit late, but I want to add my two cents again.

    For me using as also seems pretty misleading. IMH it's the complete opposite of what it is used in other parts of the framework, e.g. the Module-Syntax:

    import {Foo as Bar} from './my-crazy-module'

    so the as usually just means the target and not the source.

    so the following statement:

    provide("bar").asValue("foo")

    would let me think, that I could @Inject('foo') and get the value "bar", not the other way around!

    I really like @pkozlowski-opensource suggestion of "from":

    @provide("bar").fromValue("foo")

    IMO this is much clearer than 'as', there is no way of mixing things up with this expression...

  26. IgorMinar commented on Oct 13, 2015

    @IgorMinar
    Contributor

    just an update that we changed the api to be provide(Car, {useClass: Ferrari}, thanks for bringing this to our attention.

  27. ericmdantas commented on Oct 13, 2015

    @ericmdantas
    Contributor

    @choeller, very good point!
    @IgorMinar, awesome!

  28. angular-automatic-lock-bot commented on Sep 7, 2019

    @angular-automatic-lock-bot

    This issue has been automatically locked due to inactivity.
    Please file a new issue if you are encountering a similar or related problem.

    Read more about our automatic conversation locking policy.

    This action has been performed automatically by a bot.

  29. locked and limited conversation to collaborators on Sep 7, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions