Reputation: 3488
When using ES6 classes, why wouldn't you pass in dependencies via the constructor instead of listing them as an import/require at the top: e.g.
class DEF {
constructor(ABC) {
this.abc = new ABC();
}
}
instead of
const ABC = require('./abc');
class DEF {
constructor() {
this.abc = new ABC();
}
}
I'm trying to understand the difference between these programming styles and the implications of both?
Upvotes: 1
Views: 312
Reputation: 21110
This is extremely use-case dependent. The question here is where lies the decision making?
If it is the job of you class to decide which prototype method to use to instantiate a new object? Or do you want the caller to decide what prototype method to use? These questions should be asked and thought through when designing the application and responsibilities should be assigned based on the design dissensions.
Take for example a simple addition:
1 + 1 //=> 2
1 + '1' //=> '11'
In the above case the decision making lies by the internals. I can't provide type of object to return. The only responsibility I have is providing the correct objects. You could weigh this against a fictional variant:
1.add(1, Number) //=> 2
1.add('1', Number) //=> 2
1.add(1, String) //=> '11'
Neither of the two is right or wrong.
Upvotes: 0
Reputation: 8589
In the first example, you can use different versions of ABC, providing they implement the same interface. That provides looser coupling than the latter with the downside that you need full knowledge of how DEF will use ABC internally to make sure the interfaces match.
In the second example, you don't have to worry about which version of ABC is used. Both classes are now coupled tightly to each other, with the advantage of only needing to know how DEF works, no knowledge of ABC needed.
So both 'styles' solve different problems imho.
I would use the first style when I want to be able to 'plug in' different optional components into DEF. But I will use the second style when I extend a class.
Upvotes: 1
Reputation: 45121
This is a form of Dependency Injection which might be useful in various cases. For example for testing.
Usually you do something like
const DefaultABC = require('./abc');
class DEF {
constructor(ABC = DefaultABC) {
this.abc = new ABC();
}
}
And then provide custom ABC
implementation in test files. This might be simpler than mocking modules or otherwise hijacking module resolution and loading.
Upvotes: 2
Reputation: 138247
Cause sometimes it makes sense to pass in different classes:
new Vehicle(/*for*/ Animal)
new Vehicle(/*for*/ Human)
Upvotes: 0