Skip to content

Instantly share code, notes, and snippets.

@mxriverlynn
Created August 20, 2012 21:43
Show Gist options
  • Save mxriverlynn/3408167 to your computer and use it in GitHub Desktop.
Save mxriverlynn/3408167 to your computer and use it in GitHub Desktop.
constructor dependencies vs setters

I'm re-evaluating my thoughts on constructor based dependencies vs setter dependencies in JavaScript. I'm trying to see if the same reasons we avoid setter injection in static language like C# and Java still apply in JavaScript.

In other words, why is this:

var a = new A();
var b = new B();

var c = new C(a, b);

better than this:

var a = new A();
var b = new B();

var c = new C();
c.a = a;
c.b = b;

What are the reasons that you would choose constructor parameters vs setters, and why?

What other options are there for runtime composition of the c object, so that it can correctly make use of a and b? When would you choose those options?

@mxriverlynn
Copy link
Author

@mbriggs - good info. i especially like the bit about destructuring. that could still be done with a setter method (as opposed to just assigning an attribute), but I agree that the encapsulation feels better to me when it's in the constructor.

fwiw, though, I see IoC containers in JS as an anti-pattern. It's as if we've become so used to the necessity of them in languages like C# and Java that we forgot what problems they introduced when looking at what problems they solved. I've never found a legitimate need for them in JS. The times when I thought that it would be necessary or helpful were the times that I was ignoring the pain of the design I was implementing: object graph too deep, tight coupling between processes that should be separated, etc. Typically flattening the object graph by recognizing additional boundaries within our objects will make the need for an IoC container go away, IME.

@jbogard is right about having more options available in JavaScript and needing to explore and understand those options, when they're useful, when they're detrimental, etc (via our twitter conversation). and even though i react against his suggestion here, i end up doing that on a regular basis - mocking $.ajax calls, for example.

I still don't like setter injection, especially when it takes the form of foo.bar = baz. If I were going to do setter injection, I would create a setter method. This at least gives a legitimate API for the purpose of setting the dependency, which has more value in declaring the intention of the code than simple attribute assignment.

... so much to think about. so little time :P

@Encosia
Copy link

Encosia commented Aug 23, 2012

I'm not sure I understand the context 100% here due to the abstract object names. The relation between A, B, and C might make a difference in how I viewed the situation (e.g. if A and B only existed to hang off of Cs, then my opinion might change, but I'm not sure).

That said, I would almost always prefer to see something like this in code that I need to work with, assuming A and B are available at the time that you construct C:

var a = new A();
var b = new B();

var c = new C({
  A: a,
  B: b
});

Or, just:

var c = new C({
  A: new A(),
  B: new B()
});

To me, it feels like a more idiomatic approach that matches what I'm accustomed to from working with client-side libraries. I know it's essentially the original first choice rehashed, but seeing it that way makes the decision more clear to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment