2011-03-25 19 views
7

Actualmente estoy usando IoC para proporcionar implementaciones concretas de repositorios en un proyecto. Todos los ejemplos que he leído usan una interfaz como definición del servicio. Sin embargo, habiendo leído las recomendaciones de Microsoft, se recomienda prefer abstract classes over interfaces.¿Clase o interfaz abstracta para el servicio de IoC?

He encontrado que esto útil en conjunción con el patrón de plantilla para reducir la repetición. Por ejemplo dar una clase Product con una propiedad IsActive podría utilizar una interfaz para el repositorio tales como:

interface IProductRepository 
{ 
    IEnumerable<Product> Load(); 
} 

Si una tarea común es cargar productos activos entonces yo tendría que hacer:

IEnumerable<Product> activeProducts = repository.Load().Where(x => x.IsActive); 

Donde repository es una implementación concreta. Si usara una clase abstracta, tales como:

abstract class ProductRepository 
{ 
    protected abstract IEnumerable<Product> LoadCore(); 

    public IEnumerable<Product> Load() 
    { 
     return LoadCore().Where(x => x.IsActive); 
    } 
} 

Entonces podría cargar productos activos usando

IEnumerable<Product> activeProducts = repository.Load(); 

Toda la aplicación para cargar la información del producto está dentro de la clase Contrete que deriva ProductRepository lo que no hay acoplamiento a la capa de persistencia. Si se encuentra que hay otra actividad comúnmente realizada, entonces esto podría agregarse a la clase base como un cambio sin interrupciones que no podría hacerse utilizando una interfaz.

¿Hay alguna ventaja de utilizar una interfaz en lugar de una clase abstracta? ¿Qué desventajas potenciales para usar clases abstractas podría encontrar?

estoy usando el castillo de Windsor como el controlador de la COI y .Net Framework 3.5.

Respuesta

7

No creo que esta pregunta dependa de IoC; a la mayoría de estos marcos no les importa cuál uses.

El gran problema entre el uso de las interfaces más clases base abstractas es que interfaces cannot be versioned well.

Las clases base abstractas suelen ser la mejor opción debido a esto. No creo que haya ninguna desventaja al usar una clase base abstracta, aparte de recibir preguntas de soporte como "¿por qué no puedo crear una instancia de este tipo?"

+1

1 Estoy totalmente de acuerdo en que la cuestión de si debe o no utilizar interfaces o clases abstractas es completamente ortogonal al uso de abstracciones en DI ... No estoy de acuerdo en la valoración cualitativa de las clases base abstractas, sin embargo. .. Hay muchos inconvenientes, pero esa es otra discusión :) –

+0

@mark ¿Cuáles son algunos de los inconvenientes? Honestamente, no puedo pensar en ninguna de la parte superior de mi cabeza ... – Will

+4

Bueno, en general, sabemos que debemos 'favorecer la composición sobre la herencia' así que usar las clases base que van en contra de consejo. En un nivel más concreto, las interfaces de roles tienden a proporcionar mejores abstracciones que las interfaces de encabezado. Sin embargo, el beneficio real de una interfaz de rol es que una clase puede implementar múltiples interfaces. Eso no es posible con la herencia, por lo que el uso de las clases base nos lleva en la dirección de las interfaces de encabezado y, por lo tanto, las malas abstracciones. –

2

La recomendación viene de la Framework Design Guidelines. Esta recomendación de Microsoft existe especialmente para bibliotecas de clases reutilizables. En otras palabras: marcos como el .NET framework en sí mismo. Si está creando una aplicación de línea de negocio, esta directriz no se aplica. No se aplica porque es poco probable que tenga problemas de versiones en una aplicación de línea de negocios, porque tiene control sobre todo el código del cliente que habla con sus clases/interfaces. Por supuesto, este no es el caso para las bibliotecas reutilizables.

Incluso the article of Phil Haack, donde las referencias a Will describe esto:

Una vez más, estas pautas son específicos para el desarrollo Marco (por lenguas tipos estáticos), y no a otros tipos de software desarrollo.

Por lo tanto, la eliminación de problemas de control de versiones no es un buen argumento para usar clases base. Sin embargo, mantener el código DRY podría ser. Sin embargo, usar clases base e interfaces no son mutuamente excluyentes; puede dejar que su abstract class ProductRepository implemente IProductRepository. Sin embargo, si hace esto, exponer cualquier cosa que no sea IProductRepository sería una mala idea.

Cuestiones relacionadas