Prototype Members vs Static Members vs Instance Members (and Dependency Injection)

I’m building a job scheduling system where a Schedule contains many ScheduleItems. Each of these ScheduleItems as various dependencies that need to be resolved before the SchduleItem’s “job” is able to run. When a ScheduleItem’s dependencies are all resolved the ScheduleItem will trigger an event and let the parent Schedule know that the Item’s dependencies are resolved. The Schedule can then go about it’s business, saying the job is ready, etc. 

The problem I faced in this setup was needing each ScheduleItem to trigger an event, with a potential for hundreds or thousands of ScheduleItems to be part of a Schedule. I saw a couple of options for this, tried them both, didn’t like either of them. I kept feeling like I was getting 1,000 paper cuts.

Paper set 550809 01 small

But, in the end, found a solution that I do like thanks to Dave Mosher.

Instance Members: Death By 1,000 Paper Cuts

My first solution was to have ScheduleItem inherit from EventEmitter.

In this setup, each ScheduleItem is an instance of an EventEmitter through the magic of util.inherits. That’s cool. It works. I’ve used util.inherits a bunch of times and I like the way it works with EventEmitters, to give me events in my objects. But, this turned out to be bad idea #1. I had to loop through each of the ScheduleItems in my Schedule and have the Schedule attach to the same event on each of them.

That’s potentially 1,000+ event emitter instances with the same number of event handlers being set up. No thanks. 

Dependency Injection: One Paper Cut 1,000 Times

The next trick I tried was injecting a single EventEmitter in to each of my ScheduleItem objects. Sure, I still have to loop through all of my ScheduleItems in order to inject the EventEmitter but that seemed like less of a problem since I would only have 1 EventEmitter.

This turned out to be bad idea #2 because the ScheduleItems are not created by the Schedule itself. They, themselves, are injected in to the Schedule from an external party (they ultimately come from a database). That meant the external party would then be responsible for injecting the EventEmitter in to both the Schedule and the ScheduleItems – far too much knowledge and responsibility leaking out of the Schedule / Item at that point. This totally breaks the encapsulation of the relationship between Schedule and ScheduleItem. 

This is ultimately one paper cut… but it’s one paper cut on 1,000+ objects, being controlled by something that doesn’t feel the pain of those objects. Sounds like torture to me. No thanks.

Static (Type Level) Members: A Paper Cut That Will Never Heal

In C# we call static members “untestable static dependencies” because that’s what they are – a dependency that is “static” to a class somewhere, that cannot be properly tested because it’s static. It starts out looking good, but quickly devolves in to making sure each test resets the static thing properly or working around the left-over static value from the previous tests that ran.

But this is JavaScript, right? It’s dynamic. We can work around those problems and use a “static” member for our event emitter (and by “static”, I mean attributes and methods that are attached to the Type definition). So I did.

Well, it turns out “static” members in JavaScript are just as bad. Yes, it’s true we can just replace the “static” thing in JavaScript whenever we need to. This ends up in the same situation as C#. We’re stuck constantly having to reset or re-initialize the static thing at the beginning of each test because we can’t be sure of what was left-over from the previous test suite. And if you don’t reset it… well, then you end up with things like the EventEmitter “on” limits, which is what I ran in to pretty quickly.

“Static” members, then, are a bad idea in this case (though not in all cases). It’s like a paper cut that will never heals – you think you’ve covered it up and it’s healing, but the next time you look at it, it’s an open wound again, seeping blood. No thanks.

Prototypes: Neosporin For My Paper Cuts

Around this time, I’m annoyed and am looking something better than what I’ve got. So I do my usual thing and blast a question out to twitter, expecting 1,000 people to give me fresh new paper cuts by completely misunderstanding what I’m looking for. By some miracle, though, Dave Mosher manages to understand what I’m asking (in spite of twitter’s limitation on context in 140 characters) and sends me this little gem of a tweet:

My initial response is something along the lines of saying no I already tried those things. But then somewhere in the back of my mind “inheritance” clicks with “prototypes” and a thought crushed my mind like Obi-Want whispering from the ether: “Luke, use the prototype!”

So I take the best of static members and inheritance, super-collider them together and produce a boson that looks like it’s giving mass to each of my ScheduleItem instances when in reality, it’s just the prototype chain in action!

I now have a way for each ScheduleItem to call this.emit the way I originally wanted, while still allowing a single point of access for all of the ScheduleItem instances, from the Schedule itself. 

Problem Solved!

So remember kids: eat your Wheaties, don’t do drugs, and use prototypal inheritance to your advantage. It’s a good way to get access to a single thing from every instance of your objects, and can prove itself useful in situations where static members, instance members and dependency injection all seem to have more problems than they are worth. 

Granted, there is still potential for paper cuts in the prototypal setup. Each ScheduleItem looks like it is getting it’s own instance of an EventEmitter, but they are actually sharing the same instance. I have to make sure the events that any given ScheduleItem emits includes the ScheduleItem instance as the first parameter. That way the thing listening for the event can get a reference to the actual ScheduleItem that wanted to trigger the event. 

Over-all, though, the potential for paper cuts from this setup seems less than the massive, hemorrhaging paper cuts of the previous ideas. But for now, prototypes are providing a soothing salve to heal the wounds I previously inflicted on my code. 

Get The Best JavaScript Secrets!

Get the best kept secrets of JavaScript, and the most important career advice you'll ever hear!
Don't miss out: join my list to get all the inside info!

  • Fernando Zamora

    Nice. Thanks for sharing.

  • FeelLikeANut

    So… your final solution looks like a thinly veiled static member. You decided that static members were bad because when you create a new instance, there’s no way to know if there are any left over values from previous runs. So instead, now the emitter is on the prototype… which is shared across all instances… which means that when you create a new instance, there’s no way to know if there are any left over values from previous runs… just like a static value.

    • Derick Bailey

      yeah, it does look like that.. and sort of is. But being an attribute of the prototype, it isn’t as bad as an actual static. Each object instance can overwrite the prototype’s method which means my unit tests can mock the “emit” and “on” methods of the ScheduleItem instance and I don’t have to worry about the cleanup mess. Since the mock (spy) gets applied to the individual instance, no other instance will have a reference to the mocked method. This gets around all of the problems of the static mess with testing… nnnit’s certainly not perfect, but in this situation it seems to be the less of all the evils that I came up with.

      • FeelLikeANut

        I think your best bet is actually the DI pattern.nn var emitter = new Events.EventEmitter();n var scheduleItem = new ScheduleItem(emitter);nnThere’s no question that this kind of code would behave exactly the same on every run, because you control the emitter it uses.nnBut as you noted, you don’t want the external party to have to know the details of creating a ScheduleItem. Fortunately, there’s a pattern for that. :) Hiding complex creation logic is one of the motivations for the factory pattern.nn function ScheduleItemFactory() {n this._emitter = new Events.EventEmitter();n }nn ScheduleItemFactory.prototype.createScheduleItem = function () {n var scheduleItem = new ScheduleItem(this._emitter);nn return scheduleItem;n };nnYou would pass your external party an instance of ScheduleItemFactory, then the external party would invoke createScheduleItem to create a new ScheduleItem instance.

        • Derick Bailey

          for a small number of objects, i agree with this approach. nnni still this would be a bad idea in my case, due to the large number of objects that i’m creating. managing the references and the event relationships (the “on” and “removeListener” method calls) would be a bit nightmarish. having built apps that do it this way in the past, i’m gonna say no thanks in this case. it leads to memory leaks and slow code, in my experience. nnni do like the factory approach you’re recommending… just not in this specific instance.

        • Adam Nemitoff

          Now that FeelLikeANut has suggested the factory pattern I can breath a sigh of relief! The prototype pattern with “static” emitter just had too much code smell for me.