Re:Dependency injection is dynamic scoping in disguise
by hvidgaard on Thursday October 31, 2019 @10:16AM
(#21409040)
We have that style of "Master-Pattern" and no matter how small a team you have it introduces problems. It's still a hidden dependency, so you don't know if you've forgotten to initialize it before you get an exception. At least for us we ran into the problem that we wanted to make some changes that meant it was no longer a singleton - but now we had to perform a major refactoring.
So you could use a good DI framework such as SimpleInjector and get all the benefits without all the problems. You only have to initialize once, and then it's injected into constructors when needed, and you can inject different implementations depending on context.
Re:Dependency injection is dynamic scoping in disguise
by UK-Al05 on Thursday October 31, 2019 @10:06AM
(#21408901)
This is the service locator pattern. Biggist complaint is implicit dependencies, and it's hard to control lifetimes.
So this has the advantages and disadvantages of that.
Re:Dependency injection is dynamic scoping in disguise
by bluejekyll on Thursday October 31, 2019 @09:55AM
(#21408762)
How do you test? One of the things you get with dependency injection is a method to replace dependencies with other objects specifically to do thing like unit testing with mocks or integration testing with objects that provide specific failure modes.
This is much harder to do when everything is a static.
Edit: some typos.
Re:Dependency injection is dynamic scoping in disguise
by zubspace on Thursday October 31, 2019 @10:00AM
(#21408831)
All fields in the Master class are interfaces. You simply assign Mock-Implementations in the testing scenario, once in a startup routine. Done.
Re:Dependency injection is dynamic scoping in disguise
by tmk1108 on Thursday October 31, 2019 @10:27AM
(#21409157)
How do you deal with parallel tests execution? Given that they are all static, you can't have multiple tests running at the same time setting up the mocks or they might overlap
Re:Dependency injection is dynamic scoping in disguise
by zubspace on Thursday October 31, 2019 @10:51AM
(#21409441)
You can add a static "InitTest" method somewhere which initializes the modules. Use a double checked locking pattern [1] in there to make sure, that you instantiate and assign the modules used for testing exactly once.
Re:Dependency injection is dynamic scoping in disguise
by glun on Thursday October 31, 2019 @02:05PM
(#21411783)
This also isn't thread safe, but that's not a problem if you don't run parallel tests in the same process. Using the same stateless test doubles in all tests also solves the problem. I often find myself wanting stateful test doubles though.
Re:Dependency injection is dynamic scoping in disguise
by maaaats on Thursday October 31, 2019 @10:00AM
(#21408834)
> * It is fast. In release builds you can even try to replace the interfaces with the actual classes implementing it for a straight method call.*
Isn't the interface mainly for the compiler, and in runtime it's just a straight method call anyways?
So why not make it a singleton? Or even better, make it a static class with some static properties?
Yes I know, I said something evil! But before you take out the pitchforks, bear with me:
This is C# and I actually LOVE this pattern. I have seen it referred to as Master-Pattern, but I don't know the correct term. It solves a lot of problems:* You don't have to pass essential modules around anymore. You can initialize the Master once and access them everywhere without caring about their implementation.
* Code completion does wonders on this one. You simply type "Mast..." and it will show you ALL available modules. You don't have to remember anything. It's awesome for new team members.
* It is fast. In release builds you can even try to replace the interfaces with the actual classes implementing it for a straight method call.
It introduces a few problems:
* You increase coupling. Once you add a module, removing it or significantly changing the interface is tricky.
* You need to be careful to NOT couple modules to each other, and if you do, do it rarely. Otherwise you will have to instantiate the modules in a specific order which gets cumbersome.
In my opinion: If you are a small team and have sane teammates, give this one a try. It reduces boilerplate a lot and reduces the amount of arguments you need to pass around everywhere.