Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If Aurelia understands "import", why use dependency injection?

Tags:

aurelia

I don't understand.. if I can use import in Aurelia, why do I have to wire up the constructor with @autoinject() and all that? I'm sure I'm missing something, but, from what I can tell, I can just use my imported module whenever I want.

import something from "whatever"

export class SomeViewModel {
    activate() {
        // use something
    }
}
like image 758
Alex Dresko Avatar asked Dec 05 '22 00:12

Alex Dresko


2 Answers

Typically, in an Aurelia application, the thing you are importing isn't an instance of Something it's the class Something. To actually use whatever has been imported, you need an instance of it.

import Something from 'whatever';

let something = new Something();

When you use Aurelia's Dependency Injection system, you are utilizing a design pattern called "Inversion of Control." Instead of your class (or you) being in charge of instantiating its dependencies, it lists what dependencies it has and then has instances of the dependencies injected in to its constructor function.

This helps with testability, as now you can pass mocked instances of the dependencies to a class in your test fixtures (note that in your tests, your tests will pass the mocks to the constructor, and not rely on Aurelia's DI container).This also allows you to tap in to the Dependency Injection container's ability to be configured to create dependencies using different object lifestyles such as singletons and transient.

--- Edits to answer OP's questions from comments ---

If I import a module defined as export default class Something into an aurelia view model using constructor injection, it does not need to be instantiated. It is an instance of the class Something.

This is because Aurelia's Dependency Injection container is instantiating an instance for you. This is why your code looks like this:

import {inject} from 'aurelia-framework';
import Something from 'somewhere';

@inject(Something)
export class Foo {
  constructor(something) {
    this.something = something;
  }
  //...
}

and not

import Something from 'somewhere';
export class Foo {
  constructor(Something) {
    this.something = something;
  }
  //...
}

You are telling Aurelia "I need one of these, please give it to me," and Aurelia says "Sure thing, I've created one or I already had one lying around, here it is."

In other words, it appears that aurelia's constructor DI only works with class exports, and it does instantiate the class. It looks like if I want to import something like moment js into my aurelia view model, I should just continue doing things the way I've always done them (not using aurelia's DI). Does that sound correct?

This is correct. Libraries like moment give you a function to use, and not a class that can be instantiated by Aurelia. For these you would continue to use them as in the past.

like image 126
Ashley Grant Avatar answered May 04 '23 23:05

Ashley Grant


Well technically you can use the imported modules without Aurelia's DI, but in most situations that would be a bad thing. The Dependency Injection layer gives you so much versatility and flexibility. It handles caching, it supports singleton and transient dependencies, handles lifetime and makes thing neater from an architectural perspective.

like image 45
Dwayne Charrington Avatar answered May 05 '23 01:05

Dwayne Charrington