[ProgClub list] What is IoC?

John Elliot jj5 at progclub.org
Thu Oct 13 03:18:47 AEDT 2011


On 13/10/2011 2:09 AM, Stuart Laughlin wrote:
> What does that code look like?

Like most of my code: an unfinished poorly conceived difficult to 
understand disaster. :)

I'm still hoping that maybe one day I'll get better. :P

> Reading your description I can't work
> out whether Notifier's static CreateInstance() method would receive an
> IMessageClient parameter, or if that method would obtain an instance
> from the factory (in which case I can't work out how you get the
> factory into Notifier).

Yeah, I've done it a number of different ways. One way would be to make 
the factory a singleton and have Notifier's factory method grab a 
message client implementation from the factory and pass it to its 
constructor. Or maybe the singleton factory isn't asked for an 
IMessageClient during construction of Notifier but much later during 
NotifyUser where the actual work is done. Another way I've done it is to 
wrap the abstract factory up as a member of a more general 'application 
context' class and then pass that context object into the NotifyUsers 
call which will use the factory (or not) to create a message client. 
Sometimes I've passed the factory directly to the 
Notifier.CreateInstance method. I'm left feeling like I've done 
everything I could possibly dream of trying. Not sure I can rank 
approaches. :P

Any of the above will still leave you in a pretty good position to 
switch out your implementation of IMessageClient for testing or 
production builds, and those are really the only two kinds of 
implementation there are. I have to say, I code up my interfaces and 
implementations like this, but in reality I rarely get around to writing 
the test suites that would use the mock components, so I'm not entirely 
sure why I bother, except that I feel like my system is well factored, 
even if it really needn't be. This might mean my code isn't really 
up-to-scratch, because it hasn't been incorporated into testing 
frameworks that prove it is a valid approach.

I'm a little bit suspect about our example, because I don't think I'd 
have both a Notifier and a set of *Sender classes implementing 
IMessageClient, I'd probably just have two *Notifier classes 
implementing IMessageClient and get my factory to select (and if 
necessary configure) one.

So I'll give you an example of how I'd implement it. As I mentioned 
above there are other ways which might seem more suitable in various 
contexts (especially if having your factory as a singleton is going to 
create an issue for you, although I have trouble contriving an example 
where that might be the case.)

public interface IFactory {
   IMessageClient CreateMessageClient();
}

public interface IMessageClient {
   void Notify( IUser user, String message );
}

public static class Factory {
   private static IFactory _Instance;
   public static IFactory Instance {
     get { return _Instance; }
     set { _Instance = value; }
   }
}

public sealed class ProductionFactory : IFactory {
   IMessageClient IFactory.CreateMessageClient( return 
ProductionMessageClient.Create(); }
}

public sealed class TestFactory : IFactory {
   IMessageClient IFactory.CreateMessageClient( return 
TestMessageClient.Create();
}

// note: I would probably put factory methods on the factory
// implementations too, although I'm not sure I could justify why I
// pretty much always do that, and I've elided it here for brevity

public sealed class ProductionMessageClient : IMessageClient {
   private ProductionMessageClient() {}
   public IMessageClient Create() { return new ProductionMessageClient(); }
   void IMessageClient.Notify( IUser user, String message ) {
     // send email
   }
}

public sealed class TestMessageClient : IMessageClient {
   private TestMessageClient() {}
   public IMessageClient Create() { return new TestMessageClient(); }
   void IMessageClient.Notify( IUser user, String message ) {
     // log to console
   }
}

public static class Program {
   public static void Main() {
     Factory.Instance = new ProductionFactory();
     // ...
     IMessageClient mc = Factory.Instance.CreateMessageClient();
     mc.Notify( user, "Hello world" );
   }
}

> You mentioned earlier that this factory/config scenario essentially
> fills the role of an IoC container, and I would tend to agree.
> However, so far it appears to me that an IoC container accomplishes
> this in a more simple and elegant way, according to my tastes anyway.
> I'll keep going with my explanation and see if you agree.

Cool man, very much looking forward to hearing the rest of your 
explanation. I feel like you've raised more questions than you've 
answered just at the moment. The main question being: what on earth is a 
container and what does it do? Maybe one day I'll reach the point of 
understanding, but I'm not there yet! Thanks for your patience.



More information about the list mailing list