views:

374

answers:

3

Hi,

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.

+9  A: 

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.

Bryan Watts
thanks Bryan - Does this mean there might be some more overhead of the IOC constructing things (e.g. logger) everytime? Also for the utils type classes, I'm wondering will this make refactoring harder as you refactor your helper functions amongst your helper classes? (I am using ReSharper myself) - thanks
Greg
Most IoC containers allow some sort of scoping. By this, I mean you indicate whether your object is created every time (factory), created once per context (unit of work), or once per application (singleton). This means you can register the logger such that it only gets created once.
Bryan Watts
Ultimately you want to eliminate the utility classes. Every method on each of those classes has the same coupling issues as the `HttpUtils.DoStuff` method above. For that reason, you don't want to require that *any* code depend directly on `static` members. Instead, take the body of `HttpUtils.DoStuff`, put it behind `IDoesStuff`, and delete the method entirely from `HttpUtils`. Now, any class which may have called the static method can instead accept `IDoesStuff` in its constructor. Viola: no more need for the utility class!
Bryan Watts
oh, one last question Bryan if I may: would you normally recommend packaging utils classes into their own VS class library - would this be a useful way to go?
Greg
I recommend you organize your project elements by feature, not by technical details. This means that web-specific utility classes would go with other web-related things, and data-specific utility classes would go with other data-related things. It wouldn't make much sense to mix web- and data-related utility classes just because they are utility classes. So to answer your question, there are other ways go to which are far more useful.
Bryan Watts
+1  A: 

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.

Anthony
+2  A: 

Static methods by definition do not need an instance. DI/IOC aims to satisfy interfaces with concrete classes and given that your static class along with its static methods by definition cant implement an interface or extend a class the question makes no sense. Theres no point in passing the helper class because one does not need the instance to use the static methods. You code will always execute the same static helperr methods even without an instance.

In an IOC/DI powered application one would define interfaces and have at least one implementation. Its all about managing instances and their dependencies.

mP