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

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

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 reorganize this code so that class dependencies are added 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 with the size of the board? I mean, in the first case, I just passed the class to the desired board size, and he will do everything to create other types of boards with the correct size. In the case of dependency injection, this may not be the case. What are you doing in this situation? Do you put any checks into the MainBoard constructor to make sure the correct dimensions are passed? You just assume that the client of the class will be responsible enough to pass 3 types of boards with the same size, so there are no problems?

Edit

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

thanks

+7
java c # oop dependency-injection
source share
8 answers

I would say that the boardSize parameter boardSize not needed in the second case, but I would add a statement to make sure that the dimensions of board 3 are really equal.

But in general, the second case seems to me doubtful. I would suggest the first approach if you really do not need to introduce various boards on the main board. However, I would like to consider, for example, the factory board instead of passing three panel parameters to the constructor, for example

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

This will ensure the consistency of the three boards in terms of "board family" and size.

We need to know more about the context / domain model, in particular, about the ratio of the main board and daughter boards in order to decide whether this is the right choice.

+5
source share

There is no doubt whether dependency injection (or dependency inversion) should be used in this case at all. It seems to me that your MainBoard is responsible for managing the BoardTypes created in the first example. If you are introducing your BoardTypes now, this responsibility must be fulfilled by MainBoard consumers .

This is flexibility and additional responsibilities on the consumer side.

On the other hand, if it is reasonable for the BoardType life cycle to BoardType handled externally , it is great to use dependency inversion. Your MainBoard then needs to make sure its dependencies match correctly . This will include checking that their Size value is equal.

+3
source share

The main advantage of dependecy injection is isolation from changes to input objects. So in your case, one variable is obvious - that is size. You must add fees to the main board so that the main board no longer needs to know or worry about the size. Also, if your application does not have to support 3 different behaviors between different board types, I would suggest using one abstract definition for a board type interface.

 public class MainBoard { private IBoardType bt1; private IBoardType bt2; private IBoardType bt3; public MainBoard(IBoardType bt1, IBoardType bt2, IBoardType bt3) { this.bt1 = bt1; this.bt2 = bt2; this.bt3 = bt3; } } 

Responsibility for what the injection does (injection frame or assembly code) is responsible for ensuring that these boards get the correct size. This can be done in several ways: one example is the main board, and nested boards - they all get their size from one external source. Perhaps your application, in this case, is the size of the input boards relative to the main board.

So you can have external logic, for example:

 public class BoardAssembler { public static MainBoard assembleBoard(Size size) { Size innerBoardSize = deriveSizeOfInternalBoards(size); return new MainBoard(new BoardType1(innerBoardSize), new BoardType2(innerBoardSize), new BoardType3(innerBoardSize)); } } 

Essentially, you follow the inverse of the build logic wherever MainBoard is built. Start there and retrieve everything in the factory or some kind of evil singleton factory or static method. Ask yourself: "Where is MainBoard created?" Also ask: "What components and parameters are needed?" Once you have moved all the logic of creating an instance to a factory, it may be easier to maintain Mainboard and all its dependencies.

+2
source share

What type of information does the BoardTypeX class BoardTypeX ? Does it make sense to embed this object in your MainBoard. Dependency-Injection and patterns in general, this is not always a solution, and you should not use it just b / c, you can. factory might look better here.

 public class MainBoard { private IBoardType1 bt1; private IBoardType2 bt2; private IBoardType3 bt3; ... private Size boardSize; public MainBoard(IBoardBuilderFactory factory) { this.bt1 = factory.buildBoard(boardSize); //... } } 

And if the size of the board should be determined from the outside, perhaps you do not store it. Perhaps the factory determines which board size to use when it is designed elsewhere.

In any case, the fact is that design patterns will help you complete tasks in a clean and convenient way. They are not hard and fast rules that must be followed.

+1
source share

-EDIT- Deleted most of my answer because others beat me before him :)

Another option is factories. Depending on your requirements, you may find it better (or not) to use plants to solve your problem. There is a good SO discussion here about Vs DI factories. You can even consider passing facts through DI to your class constructor - therefore, your constructor accepts a class and a factory class and prefers the factory class (passing in size) to receive boards.

+1
source share

You can get paid from one of the boards that are transmitted via DI. This way you can lose the boardSize alltogether variable.

0
source share

You can have a BoardTypeFactory that creates BoardTypes as follows:

IBoardType bt1 = BoardTypeFactory.Create(boardSize);

Please note that there are tons of blog posts and SO answers on how to write a factory better, the above example is simple.

Then you can call

new MainBoard(boardSize, bt1, ....

transfers the size of the source used to create the boards.

0
source share

Within MainBoard boardSize is actually a constant. You only need one value to exist. You need a code like this:

 int boardSize = 24; // Or maybe you get this from reading a file or command line MainBoardScope mainBoardScope = new mainBoardScope( boardSize ); 

If you naively made 24 global or constant, you would have hard-to-reach dependencies here, because classes would rely on collecting this constant or global statically, and not through the declared interface (i.e. constructor).

mainBoardScope contains singletones for a group of objects that have the same lifetime. Unlike the old-school singleton, they are not global and are not available statically. Then consider this code that runs when the application starts (or this scope in a larger application) to plot the object:

  MainBoardFactory factory = new MainBoardFactory( mainBoardScope ); MainBoard board = factory.createMainBoard(); 

As part of this createMainBoard method createMainBoard you must use boardSize from the scope to create three boards:

  IBoardType1 b1 = injectBoardType1( myScope ); IBoardType2 b2 = injectBoardType2( myScope ); IBoardType3 b3 = injectBoardType3( myScope ); return new MainBoard( scope.getBoardSize, b1, b2, b3 ); 

Do you need MainBoard to verify the correct size of each of the three boards passed to the designer? If this is your whiteboard code, create a unit test for injectMainBoard() . This is not a MainBoard job to make sure it is built correctly. To work with factories to create it, this is a unit test in a factory job to verify that this is being done correctly.

0
source share

All Articles