0

As I understand it, interfaces in C# can be thought of as a contract or promise that a derived class must follow. This allows different objects to behave in different ways when the an overridden method is called.

DI, how I understand it, offers the ability to reduce dependencies by being able to inject the dependency (usually through a container) though the ctor, property, or method.

It seems like they are 2 completely opposing forces between freedom and restraint. I can create a contract that says a derived class MUST follow these certain guidelines which is restrictive in nature versus DI which allows me to inject dependencies (I know that the dependency has to inherit the interface but still...) which is permissive in nature. I can make everything injectable and wildly and change the class.

I guess my question is what's your process in deciding how restrictive you want to be? When is it more important to use interfaces for polymorphism or DI when you want complete freedom? Where do you draw the line? Is it ok to use interfaces when you want the structure (methods and properties) to align among different derived classes and DI when the parameters can be wildly different?

EDIT:

Maybe DI was the wrong example. Let's say I have an IPlugin and Plugin Factory. All plugins need the same information, work the same, etc. So it would make sense to use an interface. Now, one plugin works the same but needs different parameters or different data but ultimately the same structure i.e. Load, Run, etc.

I wanted to pass a command object that can expose different parameters that the plugin will need (using DI) and then each plugin can use the properties of that command object but the fact that I can inject a command object with wildly different parameters kinda breaks the whole idea of having a contract in the first place. Would that be kosher?

Eitan
  • 1,434
  • 6
  • 21
  • 53
  • This is a question for softwareengineering, however they both live side by side, if you need a base class you just use a base class, if you want to inject some functionality like say logging, or services you just inject, i mean DI doesn't solve everything, however it lets you decouple things, base classes and interface are still very important, i mean inject in situations where you meed. and encapsulate, use interface contracts and inheritance where need want tightly coupled architecture , they really are 2 different things and you may be over thinking it a little – TheGeneral Jun 06 '18 at 23:17
  • Interfaces are used for "has-a" relationships, and defines an API for classes that implement it. It allows the consumers of these classes to treat them identically with regard to the interface API even though they may be very different base classes. Dependency injection allows the consumer of a class to pass an instance of some dependency to the class (giving control of the creation of the dependency to the consumer of the class rather than the class itself). I don't see them as competing in any way, but maybe I'm missing something. – Rufus L Jun 06 '18 at 23:19
  • 1
    Possible duplicate of [Dependency injection with interfaces or classes](https://stackoverflow.com/questions/10311571/dependency-injection-with-interfaces-or-classes) – Rufus L Jun 06 '18 at 23:26
  • @TheGeneral I probably am :) I was making a plugin framework and it got me thinking when I needed one of the plugins to receive completely different data. I could for example make everything dynamic or create a command object that has wildly different data and then inject it and bypass the whole contract idea but I don't know if that's right....it might be. – Eitan Jun 06 '18 at 23:26
  • @RufusL I don't see how the poster in your link answers my question. He's talking about the dependency between inherited classes and their interfaces and whether a base class is more appropriate. I'm asking more about the principles behind each method and how they coincide. – Eitan Jun 06 '18 at 23:36
  • Please don't edit your question in such a way as to invalidate any existing answers. DI was paramount in your question, de-emphasising it via edit as a footnote just leads to **two different questions** –  Jun 07 '18 at 01:50

2 Answers2

0

DI, how I understand it, offers the ability to reduce dependencies by being able to inject the dependency (usually through a container) though the ctor, property, or method.

Incorrect. Static code analysis shows the dependency is still there. DI just changes how you ended up with an instance to the object. If your ctor say is expecting objects of a particular class then you have a dependency to that type but you also have strong-coupling to a class which is bad. However if your ctor is expecting types of a certain interface, then you have a dependency to that contract definition but not to the actual implementation (lose coupling).

As I understand it, interfaces in C# can be thought of as a contract or promise that a derived class must follow. This allows different objects to behave in different ways when the an overridden method is called.

Yes, but they are also a way to abstract a component by hiding unnecessary details, something say a class cannot. That's why in reasonably large systems it's nice to have a MyContracts.dll in which you define all your interfaces; and say BusinessLogic.dll and ClientStuff.dll. ClientStuff depends on contracts but it doesn't care about the actual implementation and possible zillions of other dependencies BusinessLogic.dll may have (typical WPF or WCF application say).

When is it more important to use interfaces for polymorphism or DI when you want complete freedom? Where do you draw the line? Is it ok to use interfaces when you want the structure (methods and properties) to align among different derived classes and DI when the parameters can be wildly different?

DI does not offer any more freedom then a non-DI system. However I think you might be a little confused over terminology or concepts. DI is always good. Injecting interfaces over class types is better as I mentioned above.

I can create a contract that says a derived class MUST follow these certain guidelines which is restrictive in nature versus DI which allows me to inject dependencies

A contract is a contract is a contract whether it is in the form of an interface or abstract class. If the constructor (constructor-injection) or property (property injection) is asking for a MyDbConnection then that sets up a requirement as to what can be injected more so than say just expecting a IMyDbConnection.

I think you may have it wrong with regards to what DI does. DI does not always inject classes and interfaces are not just for polymorphism. The latter is a common mistake. DI has nothing to do with being "restrictive". That is up to you as to the type you are expecting to have injected.

In fact expecting a concrete class object or something derived by abstract class to be injected is more "restrictive" than injecting an interface by the very nature of how interfaces can be reused across more scenarios. e.g. Not that you would be injecting one but INotifyPropertyChanged pre-dated WPF but not plays a huge role in WPF and MVVM.

Restrictive:

public EditPatientViewModel (SqlPersistenceService svc) {}

Not so restrictive

public EditPatientViewModel (IPersistenceService svc) {}

Deciding between restriction and freedom (Interfaces and Dependency Injection)

That's completely up to you but if you inject interfaces then you will obtain:

  • decoupling between contract and implementation and all the baggage that goes with it
  • improved abstraction - hide away unnecessary details
  • Thanks for taking the time to answer me. I totally agree that interfaces can be less restrictive in certain cases especially as opposed to concrete classes and I like the idea of having dependencies on interfaces (or a dll of interfaces) as opposed to concrete classes. Maybe DI was a bad example, I added an edit to my original question to clarify what I meant. – Eitan Jun 07 '18 at 00:46
  • @Eitan Please don't edit your question in such a way as to invalidate any existing answers. DI was paramount in your question, de-emphasising it via edit as a footnote just leads to two different questions –  Jun 07 '18 at 01:51
  • It's not a different question, it's an explanation of my original question. If I can inject a dependency albeit through an interface, the consumer of an interface can bypass the whole reason of having the interface, i.e. being held to a contract – Eitan Jun 07 '18 at 12:56
0

I was reading "The Art of Unit Testing" by Roy Osherove and I think he answers my question.

He's talking about DI in testing and mentions, some people believe this hurts object oriented design principles (namely breaking encapsulation).

Object oriented principles are are there to enforce constraints on the end user of the API so that the object model is used properly and is protected from unintentional usage. Tests for example add another end user. Encapsulating these external dependencies somewhere without allowing anyone to change them, having private constructors or sealed classes, having non-virtual methods are all classic signs of overprotective design.

I think my problem was the fact that I feel like too many dependencies being injected were breaking encapsulation principles but adding these dependencies cater to the end user in a way where they actually need the functionality (like tests) and don't break any encapsulation rules.

Eitan
  • 1,434
  • 6
  • 21
  • 53