Chang Wang

@cheapsteak

You don’t need to know “Dependency Injection”

I’ve recently been party to an interview for a front-end position where a colleague asked the candidate — “What do you know about Dependency Injection?”.

I had a feeling this may have been a “gotcha” question, but at the time couldn’t quite articulate why. We’ve since had some time to discuss and put into words why this isn’t a great question to ask a front-end developer. I’ll also provide a bit of advice for anyone who does come across this question in an interview.

So, what is Dependency Injection?

Martin Fowler initially coined the phrase in his 2004 article “Inversion of Control Containers and the Dependency Injection pattern” to explain the patterns that have developed around the concept of Inversion of Control (IoC) in the Java community and how it may be applicable to other object oriented environments. It boils down to — as much as possible, allow whatever isn’t core to what a module does to be pluggable, instead of internalizing (and thus tightly coupling) a specific implementation.

This concept was introduced to the front end via Angular, whose creator Miško Hevery was working at Google (largely a Java shop) at the time the library was open sourced.

The front-end landscape then would have seemed like barbarians wielding tangled messes of jQuery and MooTools. Angular swept through like Alexander over the asiatic hordes, bringing with it a wave of discussions around “Inversion of Control” and “Dependency Injection”.

But in the modern age of front-end development, with all frameworks having converged on “componentization” as the singular solution to both separating and wiring together pieces of complexity, “Dependency Injection” is now the standard operating procedure.

Every function passed in via props is an “injection of a dependency”, and every component that declares a prop for handling events or user interaction is observing “inversion of control”. The borrowed terms have now been rendered obsolete through ubiquity, save perhaps for use as shibboleth for JavaScripters who have lived through the reign of Angular.

That said, if you were to find yourself in an interview room where your interviewer quizzed you to say something of Dependency Injection, here are a few things you can say about how it relates to modern front-end frameworks that might at least raise an eyebrow —

“There are three main styles of dependency injection […] If you read about this stuff in the current discussions about Inversion of Control you’ll hear these referred to as type 1 IoC (interface injection), type 2 IoC (setter injection) and type 3 IoC (constructor injection). I find numeric names rather hard to remember, which is why I’ve used the names I have here. “ — Martin Fowler

Numeric names indeed are hard to remember, but perhaps a measured sprinkling of jargon might not be a bad idea in an interview where you are asked about Dependency Injection 😉

Let’s take a look at what analogues for these three types would look like in React.

Type 3 IoC — Constructor Injection

As the name implies, this component would receive its dependencies via the constructor. Here’s what such a component would look like:

class Knight extends React.Component {
constructor(props) {
super(props);
this.state = {
weapon: props.weapon
};
}
render() {
return `🐴 ${this.state.weapon}`;
}
}

And you would use it like this:

<Knight weapon={sword} />

Of course, you should typically use the prop directly instead of duplicating it.

Type 2 IoC — Setter Injection

Instead of setting dependencies in the constructor, a component would have methods available that can be called after initialization, with dependencies passed in as the argument.

class Knight extends React.Component {
state = {};
setWeapon = (weapon) => this.setState({ weapon });
render() {
return `🐴 ${this.state.weapon}`;
}
}

Usage:

componentDidMount () {
this.knight.setWeapon(sword);
}
render () {
return <Knight ref={c => this.knight = c} />;
}

Again, you almost certainly would not want do this instead of passing dependencies directly via props.

Type 1 IoC — Interface Injection

The props of a component are its interface to its clients, thus “required props” would come the closest to an analogy for interface injection with React:

class Knight extends React.Component {
static propTypes = {
weapon: PropTypes.any.isRequired
};
render() {
return `🐴 ${this.props.weapon}`;
}
}

and you would use it simply as

<Knight weapon={sword} />

I hope these examples illustrate how commonplace Dependency Injection has become, and gave you some talking points should the topic ever comes up.

The Component + Props pattern injects dependencies on construction, continues to update (set) the dependencies past initialization, and can enforce dependencies to be passed via the props interface. It’s all three patterns in one, at least in React. (Constructor Injection is indeed still popular/unavoidable in modern Angular)

Perhaps discussions around Render Props / Functions as Children (for example, Michael Jackson’s “Use a Render Prop!”, Donavon West’s “Function as Child Components Are an Anti-Pattern”, and my own “Solving the problems of Higher Order Components …”) could be seen as an extension of this conversation, where even the render function of a component is a dependency that can be injected. Libraries like Downshift epitomize this philosophy taken to its logical conclusion. But I doubt if the authors of those articles and libraries ever needed to concern themselves with that specific term.

Thanks for reading!

Much thanks for feedback and editing notes from Jeffrey Burt and Alex Wilmer

You can find me on twitter @CheapSteak.

📬Subscribe to my newsletter to receive drafts of upcoming articles before they’re published.

This article is sponsored by my hobby project - npmcharts.com 📈
Compare npm package download counts over time to spot trends and see which to use and which to avoid!

Here’s an interactive download histogram for react-apollo and react-relay

More by Chang Wang

Topics of interest

More Related Stories