2011-05-11 15 views
5

Actualmente estoy refabricando mi código para que todas las clases importantes implementen una interfaz (para la capacidad de prueba de la unidad). Encontré una clase que implementa IComparable (sin plantilla); algo así como:Implementación de una interfaz según la cual los genéricos se basan en la interfaz

public MyClass : IComparable 
{ 
    public int CompareTo(object obj) 
    { 
     MyClass cObj = obj as MyClass; 
     if (cObj == null) { throw new ArgumentException(); } 
     // etc. 
    } 
} 

Quiero interactuar y usar genéricos mientras estoy en eso; algo como esto:

public IMyClass : IComparable<IMyClass> 
{ 
    // Other methods here 
} 

public MyClass : IMyClass 
{ 
    public CompareTo<IMyClass>(IMyClass other) 
    { 
     ... 
    } 
    // Other methods here 
} 

Pero entonces, idealmente, deberían aplicar MyClassIComparable<MyClass> (y luego subclases de MyClass deben implementar IComparable<MySubClass>).

Todo esto para hacer varias preguntas:

¿Qué opinas del enfoque que he descrito? ¿Hay una mejor manera de hacer esta refactorización? ¿Hay algún punto en hacer que MyClass también implemente IComparable<MyClass>, o es inútil ya que implementamos IComparable<IMyClass>? ¿Alguna sugerencia o "mejores" prácticas que pueda conocer?

Respuesta

0

Respuesta corta: depende.

En su ejemplo específico, diría que casi siempre es incorrecto hacer una interfaz innecesaria (IMyClass en este caso) porque simplemente crea trabajo para usted. Regla general: use interfaces solo cuando más de una clase las implemente. Y como usted señala, esta interfaz en particular ni siquiera logra el objetivo de hacer que su clase sea directamente comparable.

En cuanto a qué clases debe implementar IComparable, genéricas o de otro tipo, depende completamente de cuáles sean sus necesidades de comparación. Si la comparación siempre se hace entre las referencias a la clase base, la clase derivada no necesita implementar la interfaz ya que nunca se llamará.

+0

No estoy seguro de estar de acuerdo con su regla de oro, la razón por la que estoy interactuando con esto es porque puedo probar las clases que lo usan. Significa que puedo burlarme de esta clase (aunque podría decirse que eso significa que * estoy * de acuerdo con su regla de oro, ya que la implementaré en las pruebas unitarias). – Smashery

+0

@Smashery: su caso de uso no dejó eso en claro. Ese es un uso perfectamente válido de interfaces que "sigue la regla". :-) –

2

¿Realmente tiene sentido tener varios objetos de diferentes tipos que sean comparables entre sí? El lenguaje lo permite, pero puedo contar con 0 manos la cantidad de veces que he tenido que usarlo.

Recomendaría usar IClass sin ser IComparable, y solo tiene las clases derivadas implementar IComparable.

P.S. También estoy en contra de agregar interfaces "para la capacidad de prueba de la unidad". Si el diseño de su programa requiere un patrón de fábrica con acoplamiento solo de interfaz, entonces, sin dudas, codifique ese nivel de complejidad. Pero no lo haga abuse the design solo para facilitar sus pruebas; usa Moles en su lugar.

+0

Moles se ve muy interesante. Sin duda lo examinaré; ¡Gracias! – Smashery

+0

+1 para contar desde 0 ... :) –

Cuestiones relacionadas