2011-08-24 4 views
21

Estoy revisando parte de mi código anterior (tengo algo de tiempo libre), y noté una instrucción switch bastante larga. Debido a la obtención de nuevos conocimientos, he puesto refactorizado de la siguiente forma:Uso de los diccionarios Action en lugar de las declaraciones switch

private Dictionary<string, Action> createView 
    { 
     get 
     { 
      return new Dictionary<string, Action>() 
      { 
       {"Standard", CreateStudySummaryView}, 
       {"By Group", CreateStudySummaryByGroupView}, 
       {"By Group/Time", CreateViewGroupByHour} 
      }; 
     } 
    } 

¿Consideraría esta buena práctica, o se trata simplemente de un caso de ser superfluo e innecesarios? Me gusta asegurarme de que aprendan nuevas técnicas, que no sean inteligentes por el simple hecho de hacerlo, y que realmente agreguen beneficios al código.

Gracias.

Respuesta

15

Las declaraciones de cambio largo son un mal olor clásico, y siempre son un objetivo para la refactorización.

El paso "estándar" para realizar aquí es Replace Conditional with Polymorphism. Este fue uno de los pasos enumerados en el libro de Martin Fowler Refactoring (publicado hace 11 años en 1999).

Ahora que es tan fácil tratar funciones como objetos (por ejemplo, con Acción) esta podría ser una buena solución.

Y no, no creo que esté siendo inteligente por el mero hecho de hacerlo. Si quisiera agregar otra opción en el futuro, puedo ver fácilmente lo que se debe hacer.

+0

+1 Gracias por el enlace, nunca me he encontrado con ese catálogo de refactorización antes - Lo leeré. –

2

Si el código, una vez escrito, es en gran medida estático y no está sujeto a demasiado cambio, entonces me hubiera quedado con un switch. Su enfoque de diccionario aquí, en la superficie al menos, se presta muy bien para ser más dinámico, sin embargo, hay más requisitos basados.

En cuanto a reemplazar interruptores en todas partes con código utilizando este enfoque, personalmente no lo haría en la mayoría de los casos. Mi honesta opinión es que sería inteligente por el mero hecho de hacerlo, pero aún es fácil de mantener. El gusto personal sobre las mejores prácticas es el factor más importante aquí, tal como lo veo.

Por otro lado, como han dicho otros, esta podría ser una solución viable para las instrucciones de conmutación larga. Por otra parte, algo como el Strategy Pattern también sería una buena manera de apoyar los cambios en el comportamiento.

7

Dependiendo de su aplicación, puede evitar construir siempre un nuevo objeto de diccionario, pero declararlo como un miembro de la clase, inicializar en el primer acceso y siempre devolver la misma instancia. Pero es difícil decir si realmente se ajusta a tus necesidades. como no quiero decir

public class MyClass 
{ 
    Dictionary<string, Action> dict = null; 

    private Dictionary<string, Action> createView 
    { 
     get 
     { 
      if(dict == null) 
      { 
       dict = new Dictionary<string, Action>() 
       { 
       {"Standard", CreateStudySummaryView}, 
       {"By Group", CreateStudySummaryByGroupView}, 
       {"By Group/Time", CreateViewGroupByHour} 
       }; 
      } 

      return dict; 
     } 
    } 

} 

EDITAR

De conceptual punto de vista, me reemplazando a largo swicth/case con el diccionario TryGetValue es una solución bastante buena.

Espero que esto ayude ...

5

Este enfoque es excelente.

Lo uso con algo más que Action. También es bastante efectivo para filtros y selectores. Algo como:

var filters = new Dictionary<string, Func<MyEntity, bool>>() 
{ 
    // ... 
}; 

var query = entities.Where(filters["X"]); 
+0

Ese es un buen enfoque también. Después de haber aprendido los conceptos básicos del idioma, ahora estoy mucho más cómodo aprendiendo más sobre las partes complejas, y es divertido descubrir estos pequeños trucos :) –

Cuestiones relacionadas