Когда вы используете инверсию управления, вы помогаете сделать свой класс как можно меньше. Допустим, у вас есть служба Windows, которая ждет файлов, а затем выполняет ряд процессов в файле. Один из процессов - преобразовать его в ZIP, затем отправить по электронной почте.
public class ZipProcessor : IFileProcessor
{
IZipService ZipService;
IEmailService EmailService;
public void Process(string fileName)
{
ZipService.Zip(fileName, Path.ChangeFileExtension(fileName, ".zip"));
EmailService.SendEmailTo(................);
}
}
Почему этот класс нужно на самом деле сделать проносясь и электронной почтой, когда вы могли бы посвящены занятия, чтобы сделать это для вас? Очевидно, вы бы этого не сделали, но это только доводка до моей точки :-)
В дополнение к тому, что вы не используете Zip и электронную почту, почему класс должен знать, какой класс реализует эту услугу? Если вы передаете интерфейсы конструктору этого процессора, ему никогда не нужно создавать экземпляр определенного класса, ему предоставляется все необходимое для выполнения задания.
Использование D.I.C. вы можете настроить, какие классы реализуют определенные интерфейсы, а затем просто заставить его создать экземпляр для вас, он будет вводить зависимости в класс.
var processor = Container.Resolve<ZipProcessor>();
Так что теперь не только вы четко разделяются функциональные возможности класса от общей функциональности, но вы также предотвратить потребителя/поставщика от наличия каких-либо конкретных знаний друг о друге. Это упрощает понимание кода чтения, поскольку в то же время учитывается меньше факторов.
И, наконец, при модульном тестировании вы можете переходить в издеваемую зависимость. Когда вы тестируете свой ZipProcessor, ваши издевавшиеся службы просто утверждают, что класс попытался отправить электронное письмо, а не пытаться его отправить.
//Mock the ZIP
var mockZipService = MockRepository.GenerateMock<IZipService>();
mockZipService.Expect(x => x.Zip("Hello.xml", "Hello.zip"));
//Mock the email send
var mockEmailService = MockRepository.GenerateMock<IEmailService>();
mockEmailService.Expect(x => x.SendEmailTo(.................);
//Test the processor
var testSubject = new ZipProcessor(mockZipService, mockEmailService);
testSubject.Process("Hello.xml");
//Assert it used the services in the correct way
mockZipService.VerifyAlLExpectations();
mockEmailService.VerifyAllExceptions();
Итак, короче говоря. Вы хотели бы сделать это до 01: Предотвратите, чтобы потребители знали, какой провайдер реализует необходимые ему услуги, а это значит, что вы сразу понимаете, когда читаете код. 02: Сделать модульное тестирование проще.
Пит
, но как насчет отсутствия конфигурации вообще (как в google guice) - как вы определяете «роли компонента»? – JohnIdol
В прошлый раз, когда я смотрел на изображение, ему не хватало аспект «соглашения по конфигурации», который вы можете получить, смешивая аннотации, xml и роли, что также является причиной того, что я не использую Spring javaconfig. Я действительно предпочитаю смешанную парадигму. Замена xml кодом, который делает то же самое, не сокращает его для меня, возможно, это просто я, будучи близким, но я не вижу, как настройка на основе кода добавит мне ценность. Но я не знаю, можете ли вы создать схему, основанную на соглашениях, в виде. – krosenvold