¿Es un mal hábito el no usar interfaces? [cerrado]

39

Raramente uso interfaces y las encuentro comunes en otros códigos.

También creo subclases y súper clases (mientras creo mis propias clases) rara vez en mi código.

  • ¿Es algo malo?
  • ¿Sugerirías cambiar este estilo?
  • ¿Este estilo tiene efectos secundarios?
  • ¿Esto es porque no he trabajado en ningún proyecto grande?
pregunta jineesh joseph 19.06.2011 - 18:47

11 respuestas

35

Hay varias razones por las que podrías querer usar interfaces:

  1. Las interfaces son adecuadas para situaciones en las que tu aplicaciones requieren muchos posiblemente tipos de objetos no relacionados para proporcionar cierta funcionalidad.
  2. Las interfaces son más flexibles que clases base porque puedes definir una sola implementación que puede implementar múltiples interfaces.
  3. Las interfaces son mejores en situaciones en el que no es necesario heredar implementación desde una clase base.
  4. Las interfaces son útiles en casos donde no se puede utilizar la herencia de clase. Por ejemplo, las estructuras no pueden Heredan de las clases, pero pueden implementar interfaces.

enlace

Las interfaces son como cualquier otra cosa en la programación. Si no los necesitas, no los uses. Los he visto usados extensivamente como una cuestión de estilo, pero si no necesita las propiedades y capacidades especiales que proporciona una interfaz, no veo el beneficio de usarlas "solo porque sí".

    
respondido por el Robert Harvey 19.06.2011 - 18:55
17

Tanto la herencia de clase como las interfaces tienen su lugar. Herencia significa "es un" mientras que una interfaz proporciona un contrato que define cómo se comporta algo ".

Yo diría que usar interfaces con más frecuencia no es una mala práctica. Actualmente estoy leyendo "C # efectivo - 50 formas específicas para mejorar tu C #" por Bill Wagner. El artículo número 22 dice, y cito, "Prefiero definir e implementar interfaces a la herencia".

Generalmente, uso clases básicas cuando necesito definir una implementación específica de comportamiento común entre tipos relacionados conceptualmente. Más a menudo utilizo interfaces. De hecho, normalmente comienzo por definir una interfaz para una clase cuando empiezo a crear una ... incluso si al final no compilo la interfaz, creo que es útil comenzar definiendo la API pública de clase desde el principio Si encuentro que tengo varias clases implementando la interfaz, y la lógica de implementación es idéntica, solo entonces me preguntaré si tendría sentido o no implementar una clase base común entre los tipos.

Un par de citas del libro de Bill Wagners ...

"Las clases base abstractas pueden proporcionar alguna implementación para tipos derivados, además de describir el comportamiento común. Puede especificar miembros de datos, métodos concretos, implementación para métodos virtuales, propiedades, eventos e indizadores. Una clase base puede proporcionar implementación Para algunos de los métodos, se proporciona una reutilización de implementación común. Cualquiera de los elementos puede ser virtual, abstracto o no virtual. Una clase base abstracta puede proporcionar una implementación para cualquier comportamiento concreto; las interfaces no. Esta reutilización de implementación brinda otro beneficio: agregue un método a la clase base, todas las clases derivadas se mejoran automática e implícitamente. En ese sentido, las clases base brindan una manera de extender el comportamiento de varios tipos de manera eficiente a lo largo del tiempo: al agregar e implementar la funcionalidad en la clase base, todas las clases derivadas incorpore inmediatamente ese comportamiento. Agregar un miembro a una interfaz rompe todas las clases que implementan esa interfaz. Mantener el nuevo método y ya no compilará. Cada implementador debe actualizar ese tipo para incluir al nuevo miembro. La elección entre una clase base abstracta y una interfaz es una cuestión de cómo apoyar mejor sus abstracciones a lo largo del tiempo. Las interfaces son fijas: libera una interfaz como un contrato para un conjunto de funciones que cualquier tipo puede implementar. Las clases base pueden extenderse en el tiempo. Esas extensiones se convierten en parte de cada clase derivada. Los dos modelos se pueden mezclar para reutilizar el código de implementación al mismo tiempo que admiten múltiples interfaces ".

"Las interfaces de codificación ofrecen mayor flexibilidad a otros desarrolladores que la codificación a tipos de clase base".

"El uso de interfaces para definir API para una clase proporciona una mayor flexibilidad".

"Cuando su tipo expone las propiedades como tipos de clase, expone la interfaz completa a esa clase. Usando interfaces, puede elegir exponer solo los métodos y propiedades que desea que usen los clientes."

"Las clases base describen e implementan comportamientos comunes en los tipos concretos relacionados. Las interfaces describen piezas atómicas de funcionalidad que pueden implementar los tipos concretos no relacionados. Ambos tienen su lugar. Las clases definen los tipos que creas. Las interfaces describen el comportamiento de esos tipos como piezas de funcionalidad. Si comprende las diferencias, creará diseños más expresivos que sean más resistentes ante el cambio. Use jerarquías de clase para definir tipos relacionados. Expóngalo mediante interfaces implementadas en esos tipos ".

    
respondido por el John Connelly 19.06.2011 - 19:36
8

Una cosa que no se ha mencionado es la prueba: en todas las bibliotecas de simulacros de C #, así como en algunas de Java, las clases no se pueden burlar a menos que implementen una interfaz. Esto lleva a muchos proyectos que siguen a Agile / TDD practica para dar a cada clase su propia interfaz.

Algunas personas consideran esta mejor práctica porque "reduce el acoplamiento", pero no estoy de acuerdo. Creo que es solo una solución a una deficiencia en el idioma.

Creo que las interfaces se utilizan mejor cuando tienes dos o más clases que, de manera abstracta, hacen "lo mismo", pero de diferentes maneras.

Por ejemplo, el marco .Net tiene varias clases que almacenan listas de cosas , pero todas las almacenan de diferentes maneras. Por lo tanto, tiene sentido tener una interfaz IList<T> abstracta, que se puede implementar utilizando diferentes métodos.

También deberías usarlo cuando quieras que 2+ clases sean intercambiables o reemplazables en el futuro. Si aparece una nueva forma de almacenar listas en el futuro, AwesomeList<T> , entonces, suponiendo que haya usado IList<T> en todo su código, cambiarlo para usar AwesomeList<T> significaría solo cambiar unas pocas docenas de líneas, en lugar de unos pocos cientos / mil.

    
respondido por el BlueRaja - Danny Pflughoeft 20.06.2011 - 01:23
5

El resultado principal de no usar la herencia y las interfaces cuando son apropiadas es acoplamiento apretado . Esto puede ser un poco difícil de aprender a reconocer, pero generalmente el síntoma más obvio es cuando realiza un cambio, y con frecuencia tiene que pasar por un montón de otros archivos para realizar cambios en un efecto dominó.

    
respondido por el Karl Bielefeldt 19.06.2011 - 20:33
4

No, esto no es malo en absoluto. Las interfaces explícitas deben usarse, si y solo si, dos clases con una interfaz común deben ser intercambiables en tiempo de ejecución. Si no es necesario que sean intercambiables, no permita que se hereden. Es tan simple como eso. La herencia es frágil y debe evitarse siempre que sea posible. Si puede evitarlo o usar genéricos en su lugar, entonces hágalo.

El problema es que, en lenguajes como C # y Java con genéricos débiles en tiempo de compilación, puedes terminar violando DRY porque no hay manera de escribir un método que pueda lidiar con más de una clase a menos que todas las clases hereden de la misma base . Sin embargo, C # 4 dynamic puede lidiar con esto.

La cuestión es que la herencia es como las variables globales: una vez que la agregas y tu código depende de ella, Dios te ayuda a eliminarla. Sin embargo, puede agregarlo en cualquier momento, e incluso puede agregarlo sin alterar la clase base mediante un envoltorio de tipo.

    
respondido por el DeadMG 19.06.2011 - 20:32
3

Sí, no (o muy raramente) el uso de interfaces es probablemente algo malo. Las interfaces (en el sentido abstracto, y la construcción en lenguaje C # / Java es una buena aproximación de ese sentido abstracto) definen puntos de interacción explícitos entre sistemas y subsistemas. Esto ayuda a reducir el acoplamiento y hace que el sistema sea más fácil de mantener. Al igual que con todo lo que mejora la capacidad de mantenimiento, se vuelve más importante cuanto más grande es un sistema.

    
respondido por el Michael Borgwardt 19.06.2011 - 23:54
3

No he usado una interfaz en años. Por supuesto, esto se debe a que he estado programando casi exclusivamente en Erlang desde hace años y el concepto de una interfaz simplemente no existe. (Lo más cercano que obtienes es un "comportamiento" y eso no es realmente lo mismo a menos que entornes los ojos con fuerza y los mires por el rabillo del ojo).

Entonces, realmente, su pregunta depende del paradigma (POO en este caso) y, además, es muy dependiente del lenguaje (hay lenguajes OOP sin interfaces).

    
respondido por el JUST MY correct OPINION 20.06.2011 - 01:13
2

Si está hablando de usar Java, una razón para usar interfaces es que permiten el uso de objetos proxy sin bibliotecas de generación de código. Esto puede ser una ventaja sustancial cuando se trabaja con un marco complejo como Spring. Además, algunas funcionalidades requieren interfaces: RMI es el ejemplo clásico de esto, ya que tiene que describir la funcionalidad que está proporcionando en términos de interfaces (que heredan de java.rmi.Remote ), sin embargo, se trata de implementar ellos.

    
respondido por el Donal Fellows 19.06.2011 - 22:29
1

Las cosas están cambiando ( MS Moles ), pero la razón principal por la que creo que es buena El código casi exclusivamente para las interfaces es que son fáciles de simular y encajar naturalmente en una arquitectura IoC.

OMI, solo debería trabajar con interfaces o DAO completamente estúpidos siempre que sea posible. Una vez que entras en esta mentalidad, y comienzas a usar una biblioteca que no se expone a través de interfaces y hace todo a través de objetos concretos que tengo que ser honesto, todo se siente un poco torpe.

    
respondido por el user23157 19.06.2011 - 20:44
0

Para proyectos antiguos, uno usa interfaces para evitar referencias circulares, porque las referencias circulares podrían convertirse en un gran problema de mantenimiento a largo plazo.

Malo:

class B; // forward declaration
class A
{
  B* b;
};

class B
{
  A* a;
}

No está mal:

class PartOfClassB_AccessedByA
{
};

class A
{
  PartOfClassB_AccessedByA* b;
};

class B : public PartOfClassB_AccessedByA
{
  A* a;
}

Por lo general, A, B, PartOfClassB_AccessedByA implementado con archivos separados.

    
respondido por el 9dan 20.06.2011 - 13:32
0

La programación basada en la interfaz ayuda a hacer que el código sea más flexible y más fácil de probar. Las clases de implementación se pueden cambiar sin tocar el código del cliente [Flexibilidad]. Si bien el código de prueba puede reemplazar la programación real basada en interfaz, ayuda a que el código sea más flexible y fácil de probar. Las clases de implementación se pueden cambiar sin tocar el código del cliente [Flexibilidad]. Mientras se prueba el código, se puede reemplazar el objeto real con objetos simulados [Testability] .bject con objetos simulados [Testability].

    
respondido por el Amit Patel 20.06.2011 - 16:18

Lea otras preguntas en las etiquetas