Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert this code so it now uses the Dependency Injection pattern?

Ok, So I have the following situation. I originally had some code like this:

public class MainBoard {
    private BoardType1 bt1;
    private BoardType2 bt2;
    private BoardType3 bt3;
    ...
    private readonly Size boardSize;

    public MainBoard(Size boardSize) {
        this.boardSize = boardSize;

        bt1 = new BoardType1(boardSize);
        bt2 = new BoardType2(boardSize);
        bt3 = new BoardType3(boardSize);
    }
}

Now, I decided to refactor that code so the classes' dependencies are injected, instead:

public class MainBoard {
    private IBoardType1 bt1;
    private IBoardType2 bt2;
    private IBoardType3 bt3;
    ...
    private Size boardSize;

    public MainBoard(Size boardSize, IBoardType1 bt1, IBoardType2 bt2, IBoardType3 bt3) {
        this.bt1 = bt1;
        this.bt2 = bt2;
        this.bt3 = bt3;
    }
}

My question is what to do about Board Size? I mean, in the first case, I just passed the class the desired board size, and it would do everything to create the other kinds of boards with the correct size. In the dependency injection case, that might not be more the case. What do you guys do in this situation? Do you put any kind of checking on the MainBoard's constructor so to make sure that the correct sizes are being passed in? Do you just assume the class' client will be responsible enough to pass the 3 kinds of boards with the same size, so there is no trouble?

Edit

Why am I doing this? Because I need to Unit-Test MainBoard. I need to be able to set the 3 sub-boards in certain states so I can test that my MainBoard is doing what I expect it to.

Thanks

like image 742
devoured elysium Avatar asked Aug 05 '10 12:08

devoured elysium


2 Answers

I would say the boardSize parameter is unnecessary in the second case, but I would add an assertion to ensure that the 3 board sizes are really equal.

But overall, the second case seems dubious to me. I would suggest the first approach, unless you really really need to inject different kinds of boards to the main board. Even so, I would consider using e.g. a board factory instead of passing 3 board parameters to the constructor, e.g.

public interface IBoardBuilderFactory {
    public IBoardType1 createBoardType1(Size boardSize);
    public IBoardType2 createBoardType2(Size boardSize);
    public IBoardType3 createBoardType3(Size boardSize);
}

This would ensure the consistency of the 3 boards regarding both "board family" and size.

We should know more about the context / domain model, specicifcally the relationship of the main board and the child boards in order to decide whether or not DI is the right choice here.

like image 112
Péter Török Avatar answered Sep 22 '22 07:09

Péter Török


It is questionable whether Dependency Injection (or Dependency Inversion) should be applied in this case at all. It appears to me that your MainBoard is responsible for managing the lifecycle of the BoardTypes it created in the first sample. If you now do inject your BoardTypes this responsibility must be handled by the consumers of MainBoard.

It is a tradeof between flexibility and additional duties on the consumer side.

On the other hand, if it is sensible to have the lifecycle of BoardTypes be handled externally, it is fine to use Dependency Inversion. Your constructor on MainBoard then needs to ensure it's dependencies are properly statisfied. This would include checking that their Size is equal.

like image 44
Johannes Rudolph Avatar answered Sep 24 '22 07:09

Johannes Rudolph