[ProgClub list] What is IoC?

Stuart Laughlin stuart at bistrotech.net
Tue Oct 11 03:57:32 AEDT 2011


I intend to explain this over a few small bursts. I'm writing quickly
with minimal editing (and frankly I didn't even make sure my code
compiles) so apologies in advance for any wonkiness.
Interaction/comments are welcome.

~_~_~_~_~_~_~_~_~_~_~_~_~_~_~_~_~_

There are a lot of good articles on the web that attempt to explain
Inversion of Control [1]. This is my humble attempt. My audience is
primarily John Elliot, but maybe you'll find this helpful, too. All
code examples will be in C#.

First things first. As you have no doubt already perceived, IoC stands
for "Inversion of Control." Inversion of Control is not a technology
but rather a principle of software development that advocates
reversing the control structure commonly found in traditional software
design. Traditionally, a class instance creates the other components
on which it relies to do its work. Consider the following example code
(which is contrived but I think fairly representative), paying close
attention to the relationship between the Notifier class and the
EmailSender class.

public class EmailSender {
    public void Send(string message, User user) {
        string host = getHostFromConfig();

        /* send email using SmtpClient or similar */
        ...
    }
}

public class Notifier {
    public void NotifyUsers(IEnumerable<User> users, string message) {
        var sender = new EmailSender();

        foreach (var user in users) {
            this.sender.Send(message, user);
        }
    }
}

public class MainClass {
    public static void Main(string[] args) {
        var process = new SomeProcess();
        var result = process.Run();

        var admins = new List<User> {
                        new User {'sclaughl'},
                        new User {'jj5'}
        }

        var notifier = new Notifier();
        notifer.NotifyUsers(admins, result);
    }
}

First observe the Notifier class. The Notifier class depends upon the
EmailSender class to do the heavy lifting; therefore it instantiates
an object of type EmailSender directly. This approach has several
ramifications. First, the Notifier class potentially has a very
demanding dependency chain. It requires a reference to the assembly
containing EmailSender, as well as any/all assemblies referenced by
EmailSender (e.g. System.dll which contains
System.Net.Mail.SmtpClient) and their dependencies, all the way down
the line. In this simple example it may not cause much of an issue,
but it's not difficult to imagine deep and complicated dependency
chains resulting from this approach. Second, Notifier is not
polymorphic. It can notify users via email and by no other means.
Ideally we would like our Notifier to be able to use other means of
notification as well, perhaps via SMS, log file, or console output.
Finally, the combined effect of these issues is that too much control
is taken away from our Main method. Since our Main method is the entry
point and primary controlling mechanism of this simple application, we
would like it to maintain as much decision-making power as possible.
As we develop the classes that compose our system, we want to remain
as abstract as possible, thereby deferring as much control and
behavior as possible, pushing those decisions out to the edge of the
system where they can be specified by the concrete application.

Also observe the EmailSender class. The EmailSender requires a 'host'
setting in order to relay the email. Traditionally we might store this
setting in an application configuration file. While this approach
gives the desired flexibility, it ties the class to a configuration
file and makes unit testing more convoluted. Ideally the EmailSender
would simply rely on a 'host' variable being set, thereby giving us
the flexibility of providing the setting however we see fit,
configuration file or otherwise.


1: My favorite at the moment is by Martin Fowler at
http://www.martinfowler.com/articles/injection.html.

~_~_~_~_~_~_~_~_~_~_~_~_~_~_~_~_~

Next time we'll work on fixing some of these problems by applying the
principles of IoC.


--Stuart



More information about the list mailing list