3

Wikipedia explains:

A dependency is an object that can be used (a service). An injection is the passing of a dependency to a dependent object (a client) that would use it.

But studying AngularJS's DI implementation, I noticed it includes many different structures to be injected such as:

  • service
  • value
  • factory
  • provider
  • constant

How do these things other than "services" fit into the Dependency Injection pattern?

2
  • 1
    The wikipedia article is incorrect in suggesting that a dependency can only be a service. As you point out, there are plenty of other possibilities. – Jules Sep 27 '15 at 15:30
  • 1
    I think this is mostly an issue of terminology. You can see a “value” as a special kind of service that provides a value, a “factory” as a service that produces objects and so forth if so you want. – 5gon12eder Sep 27 '15 at 16:50
5

Everything fits into the Dependency injection pattern.

When ol' Wirth was proclaiming that every Pascal program should begin with

PROGRAM ProgramName(INPUT,OUTPUT)

it was dependency injection that he had in mind, albeit in a very rudimentary form, and we did not even have a word for it yet, so generations upon generations of programmers never understood it, and instead copied it from program to program as some apocryphal words that just had to be written this way for the magic to work.

Explicitly passing the input stream and the output stream to your program instead of having your program rely on some pre-determined, fixed, globally available entities is, in a sense, dependency injection.

Allegedly for the sake of convenience, modern languages offer many globally available features that are at your disposal simply with an #include or a using or an import statement. These import statements do not import just interfaces and primitive constants; they also import entire subsystems declared as public static, ready to be used by anyone.

Does your sorting routine sometimes become bored while sorting, and feels the need to check out its facebook account? Just have your sorting routine import the io.net package from the SDK, and it can now access any gossip all over the entire planet.

Do your web services feel that their job is kind of lackluster and they'd prefer to do something more glamorous while waiting for the remote host to respond? They can just import java.awt from the SDK, and display some slick 2D graphics for the amusement of whoever happens to walk by the server console at that moment.

All this insanity exists because the concept of dependency injection has not yet gained the traction it deserves.

Everything could, and in my opinion should, be done using dependency injection; instead of your console application's entry point being

int main( String args[] )

it could be

void main( ConsoleRuntimeEnvironment environment )

in which case you would be invoking the environment to get your arguments, and invoking it again to exit returning a result code.

If your application is a graphics application, it could be

void main( Graphical2DRuntimeEnvironment environment )

If it is a web service it could be

void main( WebServiceRuntimeEnviroment environment )

...and so on and so forth.

Whatever services, features, libraries, call them what you like you need, you should be able to obtain by asking your environment for them, and the public static keyword combination should be prohibited for anything but primitives.

But while nobody enforces this style of doing things, nothing prevents you from doing it voluntarily. You can inject anything as a dependency. Want some examples that you can use right now in applications that are currently sitting in your hard drive?

Come up with a Logger interface and pass it to all of your classes instead of magically using some omnipresent, omnipotent, and ultimately evil, statically available logging facility.

Come up with a Clock interface and pass it to any code that needs the current time, so that you do not obtain the current time using new Instance(), thus making your time-dependent code testable.

Come up with a FileSystem interface and pass it to any code of yours that needs to deal with files, so that it does not use the new operator to directly instantiate classes from java.io. This way, your file-manipulation code can be tested using a filesystem implemented in memory, so your tests can be much faster.

And the list goes on.

2

A Dependency is any piece of logic your code depends on. Its inversion of control because the alternative method of implementing the logic would be

dependency.Logic(myObject)

vs

myObject.Logic(dependency)

the first requires that dependancy knows about and has access to the properties of myObject, where as the second allows you to construct and use myObject in an OOP style way and still keep the dependency logic in a seperate class

2

Any object can be registered with DI. The various types of registration methods in angular are simply conventions. .service doesn't really have to register a service. Nor does .controller have to register a controller. Angular is targeted at user interface, so its registration methods target predefined types of components which are commonly used in angular.

All of these methods just register a function / object, and it doesn't matter if a service is really registered with .service. The only differences between them (generally) are:

  • Whether the object is new every time (called the object's lifetime here)
  • How the object is created

Lifetime

So an object registered with .service is created new only once during the whole application. That same object is kept in memory (with all its current values) and injected every time another component asks for it. Changes made by ComponentA can be seen by ComponentB and vice versa.

But a .controller object is created new every time before it is injected. ComponentA and ComponentB get their own copies of the object. If ComponentA sets a value on the controller, those changes only belong to ComponentA. ComponentB will never see them.

That's the difference in lifetimes. (In other frameworks there are additional lifetimes. Not sure if angular has more than these two.)

Object Creation

.service and .factory are both "new only once", but they differ in how the object is created. For a service, the angular framework uses new to create the object.

var createdObject = new MyService();

But a factory is called as a method.

var createdObject = FactoryFunction();

Other Frameworks

Many other DI containers are used more generically. Instead of having different registration methods to specify a combination of lifetime and creation, they allow you to provide them discretely when you register the object. Consider the following.

public class WarriorModule : NinjectModule
{
    public override void Load() 
    {
        // IWeapon will be created with: new Sword()
        // the same Sword will be used for every IWeapon requested
        // similar to angular's .service registration
        this.Bind<IWeapon>().To<Sword>().InSingletonScope();

        // will be created by calling a function
        // similar to .factory registration
        this.Bind<IWeapon>().ToMethod(context => new Sword()).InSingletonScope();

        // new sword created every time it is injected for IWeapon
        // similar to .controller registration
        this.Bind<IWeapon>().To<Sword>();
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.