Estaba leyendo este artículo y me preguntaba: ¿nos deshacemos de todas las declaraciones de cambio al reemplazarlas con un Diccionario o una Fábrica para que no haya ninguna declaración de cambio en mis proyectos?
Algo no cuadró del todo.
La pregunta es, ¿las declaraciones de cambio tienen un uso real o seguimos adelante y las reemplazamos con un diccionario o un método de fábrica? usando la fábrica ... pero eso es todo).
refactoring
switch-statement
Kanini
fuente
fuente
Respuestas:
Tanto las
switch
declaraciones como el polimorfismo tienen su uso. Sin embargo, tenga en cuenta que también existe una tercera opción (en idiomas que admiten punteros / lambdas de funciones y funciones de orden superior): asignar los identificadores en cuestión a las funciones de controlador. Está disponible en, por ejemplo, C, que no es un lenguaje OO, y C #, que es *, pero no (todavía) en Java, que también es OO *.En algunas lenguas de procedimiento (que no tienen funciones polimorfismo ni de orden superior)
switch
/if-else
declaraciones eran la única manera de resolver una clase de problemas. Muchos desarrolladores, habiéndose acostumbrado a esta forma de pensar, continuaron usandoswitch
incluso en lenguajes OO, donde el polimorfismo es a menudo una mejor solución. Es por eso que a menudo se recomienda evitar / refactorizar lasswitch
declaraciones a favor del polimorfismo.En cualquier caso, la mejor solución siempre depende del caso. La pregunta es: ¿ qué opción le ofrece un código más limpio, más conciso y más sostenible a largo plazo?
Las declaraciones de cambio a menudo pueden volverse difíciles de manejar, teniendo docenas de casos, lo que dificulta su mantenimiento. Como debe mantenerlos en una sola función, esa función puede crecer enormemente. Si este es el caso, debe considerar la refactorización hacia una solución basada en mapas y / o polimórficos.
Si lo mismo
switch
comienza a aparecer en varios lugares, el polimorfismo es probablemente la mejor opción para unificar todos estos casos y simplificar el código. Especialmente si se espera agregar más casos en el futuro; Cuantos más lugares necesite actualizar cada vez, mayores serán las posibilidades de errores. Sin embargo, a menudo los manejadores de casos individuales son tan simples, o hay tantos de ellos, o están tan interrelacionados, que refactorizarlos en una jerarquía de clase polimórfica completa es excesivo, o resulta en una gran cantidad de código duplicado y / o enredado, difícil mantener la jerarquía de clases. En este caso, puede ser más simple usar funciones / lambdas en su lugar (si su idioma lo permite).Sin embargo, si tiene una
switch
en un solo lugar, con solo unos pocos casos haciendo algo simple, puede ser la mejor solución para dejarlo como está.* Uso el término "OO" libremente aquí; No me interesan los debates conceptuales sobre lo que es "real" o "puro" OO.
fuente
Aquí es donde vuelvo a ser un dinosaurio ...
Las declaraciones de cambio no son malas en sí mismas, es el uso que se hace de ellas lo que está en cuestión.
La más obvia es la "misma" declaración de cambio que se repite una y otra vez a través de su código que es malo (estado allí, hecho eso, haría todo lo posible para no volver a hacerlo), y es este último caso el que puede tratar. con el uso de polimorfismo. Por lo general, también hay algo bastante horrible en los casos anidados (solía tener un monstruo absoluto; no estoy del todo seguro de cómo tratarlo ahora que no sea "mejor").
El diccionario como interruptor me parece más desafiante, fundamentalmente sí, si su interruptor cubre el 100% de los casos, pero cuando desea tener casos predeterminados o sin acción, comienza a ser un poco más interesante.
Creo que es una cuestión de evitar la repetición y de asegurarnos de que estamos componiendo nuestros gráficos de objetos en los lugares correctos.
Pero también está el argumento de la comprensión (mantenibilidad) y esto corta en ambos sentidos: una vez que comprende cómo funciona todo (el patrón y la aplicación en la que se implementó) es fácil ... pero si llega a una sola línea de código donde tienes que agregar algo nuevo y luego tienes que saltar por todo el lugar para resolver lo que necesitas agregar / cambiar.
A pesar de que nuestros entornos de desarrollo son enormemente capaces, sigo sintiendo que es deseable poder comprender el código (como si fuera) impreso en papel. ¿Puede seguir el código con el dedo? Acepto que en realidad no, con muchas buenas prácticas hoy en día no se puede y por buenas razones, pero eso significa que ponerse al día con el código es más difícil de comenzar (o tal vez solo soy viejo ...)
fuente
Las declaraciones de cambio frente al polimorfismo de subtipo es un problema antiguo y a menudo se hace referencia en la comunidad de FP en los debates sobre el problema de expresión .
Básicamente, tenemos tipos (clases) y funciones (métodos). ¿Cómo codificamos cosas para que sea fácil agregar nuevos tipos o nuevos métodos más adelante?
Si programa en estilo OO, es difícil agregar un nuevo método (ya que eso significaría refactorizar todas las clases existentes), pero es muy fácil agregar nuevas clases que usan los mismos métodos que antes.
Por otro lado, si usa una declaración de cambio (o su equivalente OO, el Patrón de Observador), entonces es muy fácil agregar nuevas funciones, pero es difícil agregar nuevos casos / clases.
No es fácil tener una buena extensibilidad en ambas direcciones, por lo tanto, al escribir su código, determine si usará polimorfismo o cambiará las declaraciones dependiendo de en qué dirección es más probable que se extienda más adelante.
fuente
No. Tales absolutos rara vez son una buena idea.
En muchos lugares, un envío de diccionario / búsqueda / fábrica / polimórfico proporcionará un mejor diseño que una declaración de cambio, pero aún debe completar el diccionario. En ciertos casos, eso oscurecerá lo que realmente está sucediendo y simplemente tener la instrucción switch en línea es más fácil de leer y mantener.
fuente
Al ver cómo esto es independiente del lenguaje, el código de caída funciona mejor con las
switch
declaraciones:Equivalente a
if
, con un caso predeterminado muy incómodo. Y tenga en cuenta que cuanto más fallas haya, más larga será la lista de condiciones:(Sin embargo, dado lo que dicen algunas de las otras respuestas, siento que he perdido el punto de la pregunta ...)
fuente
switch
está en el mismo nivel que agoto
. Si el algoritmo que se va a realizar requiere flujos de control que se ajusten a las construcciones de programación estructuradas, uno debería usar tales construcciones, pero si el algoritmo no se ajusta a tales construcciones, usarlasgoto
puede ser mejor que intentar agregar indicadores u otra lógica de control para adaptarse a otras estructuras de control .Las declaraciones de cambio como diferenciación de casos tienen un uso real. Los lenguajes de programación funcional usan algo llamado coincidencia de patrones que le permite definir funciones de manera diferente según la entrada. Sin embargo, en los lenguajes orientados a objetos, se puede alcanzar el mismo objetivo de manera más elegante utilizando el polimorfismo. Simplemente llame al método y, según el tipo real del objeto, se ejecutará la implementación correspondiente del método. Esta es la razón detrás de la idea, que las declaraciones de cambio son un olor a código. Sin embargo, incluso en lenguajes OO, puede encontrarlos útiles para implementar el patrón abstracto de fábrica.
tl; dr: son útiles, pero a menudo puedes hacerlo mejor.
fuente