Перед любым проектировщиком и/или разработчиком более-менее сложного приложения встает вопрос: "Как уменьшить связность кода?" Собственно, уже давно ни для кого не секрет, что излишняя связность кода приложения - верный путь к увеличению энтропии и сложности поддержки. Особенно, если код криво написан, что, к сожалению, не редкость.
Одним из наиболее популярных (на мой взгляд - лучших) способов уменьшения связности кода является использование паттерна Inversion Of Control (Инверсия управления). Очень часто данный паттерн описывают основным правилом Голливуда: "не звони мне, я сам тебе позвоню". При всей философичности данного описания оно является правильным.
Без философии же данный паттерн описывается следующим образом: взаимодействовать должны не реализации (классы), а абстракции (интерфейсы). Не должно быть такого (без фанатизма конечно же), когда класс зависит от класса. Классы должны зависить от интерфейсов. Возникает вопрос - когда создавать инстансы интерфейсов, ведь понятно, что в рантайме интерфейсов не будет, а будут классы. Так вот, вся прелесть IoC проявляется именно в этом. Вы в одном месте описываете правила, по которым будут созданы объекты для реализации интерфейсов. Остальное за вас сделает используемая IoC-подсистема, в частности - IoC-контейнер.