[ProgClub list] What is IoC?

Stuart Laughlin stuart at bistrotech.net
Tue Oct 11 07:14:03 AEDT 2011


Found a bug in Notifier.NotifySenders(). The 'this.' obviously
shouldn't be there. Therefore, the Notifier class should look like
this:

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

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


--Stuart

On Mon, Oct 10, 2011 at 11:57 AM, Stuart Laughlin <stuart at bistrotech.net> wrote:
> 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