6

I have in mind several deterministic functions that I'd like to put together, but I'm struggling with the full impllications of doing:

  1. Static class with static methods
  2. Instance of a class that can be injected into consumers

In both cases, the implementation would be the same, and as they are deterministic with no dependencies, I can unit test both without issue.

My main concern, is when it comes to testing consumers of either the static or injected functions. I feel that should I go with the inject-able route, I can much more easily test the consumers, but it means another thing to inject into all consumers. Going the static route, I can just consume them right from any class, but it will be more involved to test specific scenarios, as the consumers will be using literal implementations.

Any thoughts/advice? More information needed?

3

Rather than hard code, please use defaults.

Making every dependency injectable can lead to a mess. Even small classes soon get large constructors. The way out of the mess is sensible default values. The principle is called convention over configuration but it's really just about overrideable defaults.

If you're stuck in a language that doesn't allow named arguments (looking at you Java) you end up having to simulate them using something like the Josh Bloch Builder Pattern.

Once you have named arguments it's easy to use optional arguments because you can choose one of the many arguments to configure and not all of them. If you can do that it's much easier to keep up the habit of writing testable code because using it isn't such a pain.

  • So just to make sure I understand: your recommendation is to use dependency injection, but provide a default concretion that can be overridden should the consumer choose. This will allow for the easier construction of a class (assuming no IOC container is used) as the consumer could simply pass in no parameters, and they would get the class' intended default implementation across the board for all interfaces? – Kritner Nov 14 '16 at 12:56
  • @Kritner That's the gist of it. Inversion of Control (IoC) containers can help but aren't required and shouldn't force the class to have any idea they exist. Also, not every field has to have a default but when when a sensible default exists it should be used. – candied_orange Nov 14 '16 at 13:10
2

Later when your static class needs to have dependencies to support a new feature, converting it from static to injected singleton could be a nightmare.

I recently had to deal with this situation where there were many existing static classes calling each other and one of them needed to be modified to have a dependency injected. This meant that all the static classes that called it also had to be changed, and the rabbit hole just got deeper and deeper.

I have personally been avoiding static classes wherever possible for many years, and was very frustrated when resolving this issue took more than two weeks of valuable development resource.

I would strongly encourage you to take the injection route and save someone in the future from the nightmare I just experienced.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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