Quicker, Easier, More Seductive: Names, Usage, and Intent

By | December 17, 2013

Yesterday’s post in this unexpected series on Dependency Injection vs Service Locator generated a lot of excellent and productive feedback in Twitter, on the PHP-FIG mailing list, and in the comments.

In that post, I opined that there was a significant difference between how Service Locator containers and Dependency Injection containers are implemented. This came from my sense that because they have different names they must be different things, and so I had been trying to find a way to discern the difference by looking at the implementations.

They’re Different Names For The Same Thing …

As the disucussion progressed, it became more clear to me that there really is no significant difference in how Dependency Injection containers and Service Locator containers are written. They are both Inversion of Control (IOC) containers, and are not distinguishable by their code, API, features, etc. (although some may have more or fewer features than others).

As such, the terms Dependency Injection and Service Locator appear to be interchangeable in the sense that a container is a container is a container. The difference in naming comes from how the container is used, not how the container is implemented:

  • When the container is used outside a non-Factory object, you are using the container for Depedency Injection.

  • When the container is used inside a non-Factory object, you are using the container as a Service Locator.

(Side note: Using the container inside a Factory object does not seem to be a case of either Dependency Injection or Service Locator specifically; it’s just a generic container usage at that point. This stems from the idea that object creation should be separated from every other type of object operation; that is, a class should either create an object, or it should operate on objects, not both. Factory, Builder, etc. classes are thereforce special cases.)

… But The Names Still Indicate A Difference

This still leaves me with a trio of related issues: usage, naming, and intent.

I am big on trying to use the right names for things. I think it’s important for clear, consistent communcation that when Developer A uses a word or phrase to describe something, Developer B should be able to understand what Developer A is getting at. The need for common understanding should be so obvious as to not require pointing out. With that in mind …

  • If an author creates a “Dependency Injection” container but his intent is for it to be injected into non-Factory objects so the objects can retrieve their dependencies, he has named it incorrectly. He can correctly call it a “Container” or “IocContainer” in general, or a “Locator” or “Service Locator” in specific, but his intent and usage are clearly at odds with his naming. (Closures and functions count here, too. Injecting a “Dependency Injection” container into a closure or function is a Service Locator usage of that container.)

  • Similarly, if a user uses something labeled as a “Dependency Injection” container by injecting it into his non-Factory objects so they can retrieve their dependencies, his use is at odds with the naming and intent of the container. He is using it as a Service Locator.

  • Conversely, if an author creates a “Service Locator” that is used only in Factory objects, and never in other kinds of objects, the name is at odds with the intent and usage as well. That’s a “Dependency Injection” container, or more generically a “Container” or “IocContainer”.

  • Finally, if a user uses something labeled as a “Service Locator” and never injects it into his non-Factory objects, his use is at odds with the naming and intent of the container. He’s using it for Dependency Injection.

Conclusion

As a result of all this, I am left with the conclusion that container authors should be very careful about their naming, and that container users should be disciplined about their usage, both based on the intent indicated by the container’s name:

  • If the author intends the container to be injected into non-Factory objects, including closures and functions, call it “Locator” or “Service Locator”. Users should honor that intent.

  • If the intent is that the container never be injected into non-Factory objects, including closures and functions, call it “DI” or “Dependency Injection”. Users should honor that intent.

  • If the author has mixed intent, call it a generic “Container” or “IocContainer”. Users can mix Dependency Injection and Service Locator in Factory and non-Factory objects and closures.

Again, the point here is to make sure that other people know what we’re talking about when we use these terms. Using the wrong names leads to confusion regarding usage and intent.

Afterword

Are you overwhelmed by a legacy PHP codebase? Do you want to improve it, but don’t know where to start? My upcoming book, Modernizing Legacy Applications in PHP, will lead you step-by-step through a series of small, incremental changes that will dramatically improve the quality of your legacy codebase. Subscribe to the mailing list below for pre-release chapters and more!

Sign up for Modernizing Legacy Applications in PHP:

First Name Email

15 thoughts on “Quicker, Easier, More Seductive: Names, Usage, and Intent

  1. Pingback: Quicker, Easier, More Seductive: How To Tell A DI Container From A Service Locator | Paul M. Jones

  2. Matthieu

    I didn’t agree with your previous article, but this one I do.

    > The difference in naming comes from how the container is used

    Yes!

    Though I’d say a Service Locator is just a Container used as a Service Locator ;)

    The difference is very subtle, so I’d go with:

    – is your object going to be used for Dependency Injection? Call it a DI container, it may be used as a SL at some point anyway
    – are you going only to use it as a SL? Then don’t call it a container, that’ll be clearer for everybody

    Reply
    1. pmjones Post author

      “The difference is very subtle” — Apparently there *is* no difference; the difference is in the usage, not the implementation.

      “is your object going to be used for Dependency Injection? Call it a DI container, it may be used as a SL at some point anyway” — This is why I said the author should name it “Container” or “IocContainer” in that case. If a “Dependency Injection” container is used as a Service Locator, it’s in opposition to the intent indicated by the name.

      “are you going only to use it as a SL? Then don’t call it a container” — Apparently it *is* a container, though.

      Regardless, I’m glad we’re closer to agreement than previously.

      Reply
      1. Matthieu

        Yes good points.

        > “are you going only to use it as a SL? Then don’t call it a container” — Apparently it *is* a container, though.

        Yes, but for everybody’s sake, it’s easier to understand ;)

        Reply
        1. pmjones Post author

          “but for everybody’s sake, it’s easier to understand” — I don’t think *I’d* understand. It’s hard enough to tell as it is. If it’s intended to be used as a Service Locator, call it that. If it’s intended to be used for Dependency Injection, call it that. If it’s a generic Container for either use, call it by the generic name Container.

          Reply
  3. Andrei Gabreanu

    I completely agree with your article (the other one confused me a bit) .
    I would just like to add that I don’t agree with closures receiving the container means that the container is a SL. Not always anyway.
    In ZF2 you provide a config file where you can setup the closures, each receiving the container – and based on which you create your objects. Initially that striked me as a “doh – service locator” but… After refactoring out the closures and creating factories for my objects, I ended up with factories that receive the container and return you the object. Isn’t that exactly what you said? It’s a particular example yes, but still a viable one.

    I know zf2 “actually” calls it a SL but since the SL is an anti pattern (and the ZF team admitted it) I am using it strictly as a DiC for my factories and indirectly objects. Maybe I am wrong?

    Cheers!

    Reply
    1. pmjones Post author

      If the closure is acting as a Factory then I think you’re in the clear; the main concern here is non-Factory objects/closures/functions.

      Reply
  4. Rob Allen

    Nice article Paul.

    In an ideal world, everyone would use an IoC container as a Dependency Injector, but I think it’s much more common in the “real world” to see the container used for dependency injection in some cases and as service location in others. I suspect that this is transition phase as using IoC containers seems relatively new in the PHP world (outside of the computer scientists).

    I’d be interested to find out how many people use service location everywhere and if there’s a good justification for doing so.

    Regards,

    Rob…

    Reply
    1. pmjones Post author

      Hell, Solar used Service Locator everywhere, via the (misnamed) Solar::dependency() method. It is because of that experience that I recognize its many drawbacks and limited (but quite valid) benefits.

      Reply
    1. pmjones Post author

      Nice, dude.

      I continue to say that a Service Locator *specific to an individual library* can be useful, provided that it generates only one type of object, and gets injected itself. For things like helpers and plugins that are loaded at runtime, it’s quite nice, and the tradeoff strikes me as minimal.

      Reply
  5. Pingback: Paul Jones: Quicker, Easier, More Seductive: Names, Usage, and Intent | facebooklikes

  6. Pingback: PHPDeveloper.org: Paul Jones: Quicker, Easier, More Seductive: Names, Usage, and Intent

  7. Larry Garfield

    Too you a while, but I’m glad you finally ended up here. :-) The code is the same; it’s just the usage pattern that varies. You make a good point that the name the developer chooses should be taken as an indicator of how it’s intended to be used, not how it’s put together.

    (Which means that “Pimple” tells you absolutely nada. :-) )

    Reply
  8. Pingback: What Application Layer Does A DI Container Belong In? | Paul M. Jones

Leave a Reply

Your email address will not be published. Required fields are marked *