Just trying to still get my head around IOC principles.
Q1: Static Methods - Should util classes with static helper methods be wired up with IOC?
For example if I have a HttpUtils class with a number of static methods, should I be trying to pass it to other business logic classes via IOC?
Follow on questions for this might be:
Q2: Singletons - What about things like logging where you may typically get access to it via a Logger.getInstance() type call. Would you normally leave this as is, and NOT use IOC for injecting the logger into business classes that need it?
Q3: Static Classes - I haven't really used this concept, but are there any guidelines for how you'd typically handle this if you were moving to an IOC based approach.
Thanks in advance.
The funny thing about IoC is that objects written in the style are generally decoupled from those details.
Let's use the utility class as an example:
public class HttpUtils { public static void DoStuff(int someValue) { // ... } }
In a non-IoC-focused application, you might use that method directly:
public class Foo { public int Value { get; set; } public void DoStuff() { HttpUtils.DoStuff(Value); } }
However, that couples the definition of DoStuff
directly to its implementation. IoC strives to divorce those kinds of details, so instead we define the operation on its own:
public interface IDoesStuff { void DoStuff(int someValue); }
Then, we leave room in Foo
for the implementation to change:
public class Foo { private readonly IDoesStuff _doesStuff; public Foo(IDoesStuff doesStuff) { _doesStuff = doesStuff; } public int Value { get; set; } public void DoStuff() { _doesStuff.DoStuff(Value); } }
This decouples Foo
from HttpUtils
. The implementer of the concept of DoStuff
is now a configuration detail, and not an inherent dependency (as it is with the static method).
Notice that Foo
has no idea if its IDoesStuff
is a singleton or not. That lifetime is also a configuration detail, and not an inherent detail of Foo
.
To sum up, IoC and static
are generally at odds, since IoC promotes change and static
, by definition, prevents it. Declare your dependencies in your constructors, and you'll find you almost never have you use static
functionality.
An IoC container is typically useful to inject object that have state; or classes or interfaces that have more than one one implementation, even if the second implementation is a mock for testing purposes. If neither of these is true, you gain nothing by injecting it. the most common idiom these days is to have your class fronted by an interface that the real and mock implementation can both implement.
1) Static methods on helper classes - No, these do not often get injected by IoC. Typically they are stateless utilities.
To use a very simple example, you don't need two versions of a utility method called StringUtils.Reverse()
. You only need one, and you can easily write tests around it because it has no state or dependencies, so there's absolutely no benefit to mocking it out. Example test:
string reversedString = StringUtils.Reverse("input"); Assert.AreEqual("tupni", reversedString)
If the utility isn't really stateless (e.g. depends on HttpContext.Current), then you should make the dependency explicit by injecting it, and not making the utility static.
2) Singletons: Often yes, singletons are injected. But a good thing about IoC is that you worry less about whether there's only one of something or not. You gain flexibility in instancing by using IoC. The decision to have a particular type as singleton or new instance each time becomes part of the IoC container's config and nothing else in the code needs to change.
So singleton-hood stops being a separate concern that has to be coded into the class (and classes having multiple concerns when they don't have to is bad), and it becomes the concern of the IoC container. You don't code the class "as a singleton" with anything special like a private constructor and a public static GetInstance()
method any more, you just code it for the main concern, while the IoC container's config specifies if it's a singleton or not, or somewhere in between, like one instance per thread.
3) Static classes - are the natural home for static methods. Consider making the static methods extension methods where appropriate. You can't inject these classes, since you can't create them. Using static classes makes for procedural not object-oriented code. This isn't a bad thing for small helper methods, but if the majority of the code is like that, then you're not using the powerful OO features of the .Net platform.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With