3
\$\begingroup\$

I have created a queue in javascript. This queue also has blocking take(). As you all probably know this is not really true, because javascript does not have threads. It just wait until element has been added to queue. You can view to source-code at https://gist.github.com/2467432. I try to write testable code. As you can see from my code below my constructor does real work?

var EventEmitter = require('events').EventEmitter,
    Queue = module.exports = function Queue() {
    /*  Constructor is doing work..?? 
    */
    var _emitter    = this._emitter     = new EventEmitter(),
        _awaiting   = this._awaiting    = [],
        _queue      = this._queue       = [];

    _emitter.on('offer', function (data) {
        _awaiting.shift()(data);
    });

};

My question is if this a code smell? I think this class(object) is a leaf of application graph(value-object), so maybe it is not such a big deal. This way I think I can keep my API clean(easy to use). I think my class is still easy to test as you can hopefully see from my test class.

Value-objects, these tend to have lots of getters / setters and are very easy to construct are never mocked, and probably don't need an interface. (Example: LinkedList, Map, User, EmailAddress, Email, CreditCard, etc...). (2) Service-objects which do the interesting work, their constructors ask for lots of other objects for colaboration, are good candidates for mocking, tend to have an interface and tend to have multiple implementations (Example: MailServer, CreditCardProcessor, UserAthenticator, AddressValidator).

If you think it is a code smell I would like to know how you would fix this(but still keep the tests pass without any modification if possible?)

\$\endgroup\$
1
  • \$\begingroup\$ PS: Your code does not actually work (Array.prototype.shift does not return a function). Also, starting a property name with _ does not make it private. \$\endgroup\$ Commented Jan 5, 2020 at 23:07

1 Answer 1

2
\$\begingroup\$

Personally the only issue I see with the code in terms of your constructor doing real work or testability is the instantiation of an EventEmitter object. Doing this in the constructor prevents you from mocking out or injecting a different class/instance for testing. You could use Dependency Injection as a simply way to resolve this:

var EventEmitter = require('events').EventEmitter,
    Queue = module.exports = function Queue( emitter ) {
    /*  Constructor is doing work..?? 
    */
    var _emitter    = this._emitter     = emitter,
        _awaiting   = this._awaiting    = [],
        _queue      = this._queue       = [];

    _emitter.on('offer', function (data) {
        _awaiting.shift()(data);
    });

};
\$\endgroup\$
2
  • \$\begingroup\$ I know about dependency injection. But I like to keep my API as simple as possible because I want to publish it as module for example. I think in that case a clean constructor would be best? I want to expose the class as in the test if possible. \$\endgroup\$
    – Alfred
    Commented Apr 25, 2012 at 5:26
  • 1
    \$\begingroup\$ In that case if you really care about it you could optionally pass in a emitter or just omit it altogether. Something like var _emitter = this._emitter = emitter || new EventEmitter(), \$\endgroup\$
    – Marc Gagne
    Commented Apr 25, 2012 at 12:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.