Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you have an interface be dependent on a class?

I'm studying SOLID principles and have a question about dependency management in relation to interfaces.

An example from the book I'm reading (Adaptive Code via C# by Gary McLean Hall) shows a TradeProcessor class that will get the trade data, process it, and store it in the database. The trade data is modeled by a class called TradeRecord. A TradeParser class will handle converting the trade data that is received into a TradeRecord instance(s). The TradeProcessor class only references an ITradeParser interface so that it is not dependent on the TradeParser implementation.

The author has the Parse method (in the ITradeParser interface) return an IEnumerable<TradeRecord> collection that holds the processed trade data. Doesn't that mean that ITradeParser is now dependent on the TradeRecord class?

Shouldn't the author have done something like make an ITradeRecord interface and have Parse return a collection of ITradeRecord instances? Or am I missing something important?

Here's the code (the implementation of TradeRecord is irrelevant so it is omitted):

TradeProcessor.cs

public class TradeProcessor {     private readonly ITradeParser tradeParser;      public TradeProcessor(ITradeParser tradeParser)     {         this.tradeParser = tradeParser;     }      public void ProcessTrades()     {         IEnumerable<string> tradeData = "Simulated trade data..."         var trades = tradeParser.Parse(tradeData);          // Do something with the parsed data...     } } 

ITradeParser.cs

public interface ITradeParser {     IEnumerable<TradeRecord> Parse(IEnumerable<string> tradeData); } 
like image 772
Lews Therin Avatar asked Apr 28 '16 16:04

Lews Therin


People also ask

Does an interface need a class?

Since an interface contains no executable code, you cannot create an instance of an interface. You need to write a class to implement the methods before you can make use of it.

Can interface inherits from class?

Classes cannot inherit from an interface, since an interface is by definition empty: it only dictates the mandatory implementation of certain members. From the MSDN about interfaces: "An interface contains definitions for a group of related functionalities that a class or a struct can implement."

Can an interface be defined in a class?

Yes, you can define an interface inside a class and it is known as a nested interface. You can't access a nested interface directly; you need to access (implement) the nested interface using the inner class or by using the name of the class holding this nested interface.

Can an interface have dependencies?

An interface isn't necessarily a contract of dependencies, it's a contract of functionality. Any implementation can expose its dependencies via constructor(s). But in the event that a different implementation has different (or no) dependencies, it still implements the interface and exposes the functionality.


2 Answers

This is a good question that goes into the tradeoff between purity and practicality.

Yes, by pure principal, you can say that ITradeParser.Parse should return a collection of ITraceRecord interfaces. After all, why tie yourself to a specific implementation?

However, you can take this further. Should you accept an IEnumerable<string>? Or should you have some sort of ITextContainer? I32bitNumeric instead of int? This is reductio ad absurdum, of course, but it shows that we always, at some point, reach a point where we're working on something, a concrete object (number, string, TraceRecord, whatever), not an abstraction.

This also brings up the point of why we use interfaces in the first place, which is to define contracts for logic and functionality. An ITradeProcessor is a contract for an unknown implementation that can be replaced or updated. A TradeRecord isn't a contract for implementation, it is the implementation. If it's a DTO object, which it seems to be, there would be no difference between the interface and the implementation, which means there's no real purpose in defining this contract - it's implied in the concrete class.

like image 151
Avner Shahar-Kashtan Avatar answered Sep 30 '22 04:09

Avner Shahar-Kashtan


The author has the Parse method (in the ITradeParser interface) return an IEnumerable collection that holds the processed trade data.

Doesn't that mean that ITradeParser is now dependent on the TradeRecord class?

Yes, ITradeParser is now tightly coupled with TradeRecord. Given the more academic approach of this question, I can see where you are coming from. But what is TradeRecord? A record, by definition, is generally a simple, non-intelligent piece of data (sometimes called POCO, DTO, or Model).

At some point, the potential gain of abstraction is less valuable than the complexities it causes. This approach is pretty common in practice - Models (as I refer to them) are sealed types that flow through the layers of an application. Layers that act upon the models are abstracted to interfaces, so that each layer may be mocked and tested separately.

For example, a client application may have a View, ViewModel, and Repository layer. Each layer knows how to work with the concrete record type. But the ViewModel could be wired up to work with a mocked IRepository, which builds up the concrete types with hardcoded, mocked data. There's no benefit to an abstracted IModel at this point - it just has straight data.

like image 39
Jonesopolis Avatar answered Sep 30 '22 04:09

Jonesopolis