tillda
tillda

Reputation: 18690

Where to put needed initialization code when using Dependency Injection?

When my constructors are pure arguments-to-propeties setters then I'm not sure where to put other code that a class needs to properly work.

For example in JavaScript I'm programming a WindowMessageController that processes message events on the window object.

In order for this to work, I must somewhere attach the handler:

var controller = this;
this.applicableWindow.addEventListener("message", function(event) {
    controller.messageAction(event.data);
} 

Where does this stuff correctly belongs?

  1. in the constructor
  2. in the .initialize() method - introduces temporal coupling
  3. in the WindowMessageControllerFactory.create(applicableWindow) - quite a distant place for so central piece of code. This means that even such a small class would be split into two pieces.
  4. in the composition root itself - this would multiply its size when doing all the time
  5. in some other class WindowMessageRouter that would have only one method, the constructor, with this code

EDIT

This case seems special because there is usually only one instance of such a controller in an app. However in more generalized case what would be the answer if I was creating an instances of Button class that would wrap over some DOM <button /> element? Suddeny a

button = buttonFactory.create(domButtonEl);

seems much more useful.

Upvotes: 0

Views: 349

Answers (3)

Daniel Steigerwald
Daniel Steigerwald

Reputation: 1101

  1. Do not put any real work into constructors. Constructors are hardly mockable. Remember, seams aka methods are mockable. Constructor are not mockable because inheritance and mocking.

  2. Initialize is a forbidden word, to much general.

  3. Maybe, but you can implement factory as a static method of class too, if you are scared of many classes ,)

  4. Composition root is just an ordinary factory. Except it is only one, because your app probably have just one entry point ,)

  5. Common, we are using Javascript. If you need just one factory method, why you need class for it? Remember, functions are first class objects.

And for edit. There is nothing special on singetons, unless they do NOT control own lifecycle.

Golden rule: Always (almost ,) do separation between app wiring and app logic. Factories are wiring. Just wiring, no logic, therefore nothing to test.

Upvotes: 2

Dmitriy Startsev
Dmitriy Startsev

Reputation: 1462

I think you need to create a Router class that will be responsible for events distribution. This Router should subscribe to all the events and distribute them among the controllers. It can use some kind of the message-controller map, injected into constructor.

Upvotes: 0

Augi
Augi

Reputation: 361

I would place this code into initialize(window) method but this method cannot be part of WindowMessageController's public API - it must be visible and called by direct users (so composition root and tests) only. So when DI container is returning WindowMessageController instance then it is container's responsibility that initialize method has been called.

Reply to EDIT: Yes, this factory seems to be the best way for me. Btw. don't forget that the factory should probably have a dispose method (i.e. unbinds the event handler in case of button)...

Upvotes: 1

Related Questions