una puede modificadores interfaz interfaces implementacion heredar declaracion clase caracteristicas acceso abstracta c# dependency-management solid-principles

c# - puede - modificadores de acceso java



¿Puedes tener una interfaz dependiente de una clase? (2)

Estoy estudiando los principios de SOLID y tengo una pregunta sobre la administración de dependencias en relación con las interfaces.

Un ejemplo del libro que estoy leyendo ( Código adaptativo a través de C # por Gary McLean Hall) muestra una clase de TradeProcessor que obtendrá los datos comerciales, los procesará y los almacenará en la base de datos. Los datos comerciales están modelados por una clase llamada TradeRecord . Una clase de TradeParser manejará la conversión de los datos de comercio que se reciben en una (s) instancia (s) de TradeRecord . La clase TradeProcessor solo hace referencia a una interfaz ITradeParser , por lo que no depende de la implementación de TradeParser .

El autor tiene el método Parse (en la interfaz ITradeParser ) devuelve una IEnumerable<TradeRecord> que contiene los datos comerciales procesados. ¿No significa eso que ITradeParser ahora depende de la clase TradeRecord ?

¿No debería el autor haber hecho algo así como hacer una interfaz ITradeRecord y hacer que Parse devuelva una colección de instancias de ITradeRecord ? ¿O me estoy perdiendo algo importante?

Aquí está el código (la implementación de TradeRecord es irrelevante por lo que se omite):

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); }


El autor tiene el método Parse (en la interfaz ITradeParser) que devuelve una colección IEnumerable que contiene los datos comerciales procesados.

¿No significa eso que ITradeParser ahora depende de la clase TradeRecord?

Sí, ITradeParser ahora está estrechamente acoplado con TradeRecord . Dado el enfoque más académico de esta pregunta, puedo ver de dónde viene. Pero, ¿qué es TradeRecord ? Un registro, por definición, es generalmente un dato simple, no inteligente (a veces llamado POCO, DTO o Modelo).

En algún momento, la ganancia potencial de la abstracción es menos valiosa que las complejidades que causa. Este enfoque es bastante común en la práctica: los modelos (como me refiero a ellos) son tipos sellados que fluyen a través de las capas de una aplicación. Las capas que actúan sobre los modelos se abstraen en interfaces, de modo que cada capa se puede simular y probar por separado.

Por ejemplo, una aplicación cliente puede tener una capa View, ViewModel y Repository. Cada capa sabe cómo trabajar con el tipo de registro concreto. Pero el ViewModel podría estar conectado para trabajar con un repositorio de IR simulado, que construye los tipos concretos con datos codificados y burlados. No hay ningún beneficio para un IModel abstraído en este momento, solo tiene datos directos.


Esta es una buena pregunta que entra en el intercambio entre la pureza y la practicidad.

Sí, por principio, puedes decir que ITradeParser.Parse debería devolver una colección de interfaces ITraceRecord . Después de todo, ¿por qué atarse a una implementación específica?

Sin embargo, puede llevar esto más lejos. ¿Debería aceptar una IEnumerable<string> ? ¿O debería tener algún tipo de ITextContainer ? I32bitNumeric lugar de int ? Por supuesto, esto es reductio ad absurdum , pero muestra que siempre, en algún momento, llegamos a un punto en el que estamos trabajando en algo , un objeto concreto (número, cadena, TraceRecord, lo que sea), no una abstracción.

Esto también resalta el motivo por el cual usamos interfaces en primer lugar, que es definir contratos para la lógica y la funcionalidad. Un ITradeProcessor es un contrato para una implementación desconocida que se puede reemplazar o actualizar. Un TradeRecord no es un contrato de implementación, es la implementación. Si se trata de un objeto DTO, que parece ser, no habría diferencia entre la interfaz y la implementación, lo que significa que no hay un propósito real en la definición de este contrato; está implícito en la clase concreta.