triple tres tag simple patas pared luz interruptor instalar enchufes enchufe conectar como cambiar c# javascript refactoring switch-statement

c# - tres - como instalar un interruptor de pared



¿Cuál es la mejor alternativa a una declaración de interruptor fuera de control? (11)

Heredé un proyecto que tiene algunos bloques de instrucciones de cambio enormes, y algunos contienen hasta 20 casos. ¿Cuál es una buena manera de reescribir estos?


¿Por qué querrías reescribirlos en una estructura diferente? Si realmente tiene 20 casos que deben manejarse individualmente, un interruptor / caja es el camino a seguir. Una gran cadena de lógica si / entonces sería horrible de mantener.

El polimorfismo es otra opción si está utilizando un lenguaje orientado a objetos. Cada subclase implementaría su propia funcionalidad en el método.


Como otros han señalado, depende de la declaración del interruptor. Sin embargo, en el pasado he cambiado las declaraciones de cambio procediendo de la siguiente manera. Supongamos que tenemos una declaración de cambio como esta, con un montón de código repetitivo

switch(x){ case 1: makeitso("foo"); globalLog += "foo"; case 2: makeitso("bar"); globalLog += "bar"; case 3: makeitso("baz"); globalLog += "baz"; ... default: throw("input error"); }

lo primero que hay que hacer es reconocer las partes que son comunes (en el mundo real, esto probablemente será un poco más sustancial)

makeitso([some string]); globalLog += [some string];

y convertir eso en una función

function transformInput(somestring) { makeitso(somestring); globalLog += somestring; }

luego, para las partes que cambian en cada caso, use un hash o una matriz;

var transformvalues = ["foo", "bar", "baz"];

desde aquí podemos hacer esto:

var tvals = ["foo", "bar", "baz" ... ]; function transformInput(somestring) { makeitso(somestring); globalLog += somestring; } var tval = tvals[x]; if(tval!==undefined) { transformInput(tval); } else { throw ("invalid input"); }

Y con tvals excluidos de la declaración de cambio, incluso podría proporcionarse externamente para expandir el número de casos que puede manejar. O podrías construirlo dinámicamente. En el mundo real, la declaración de cambio a menudo tendrá casos especiales, sin embargo. Lo dejo como un ejercicio para el lector.


Depende de lo que esté haciendo la instrucción switch.

Si coincide con caracteres o cadenas, por ejemplo, en un analizador, y no tiene el mismo conjunto de patrones repetidos en todas partes en el código, entonces una instrucción de conmutación podría estar bien.

Si coincide (digamos) un número entero con una lista de valores permitidos, puede crear una clase base y un conjunto de clases derivadas para cada valor. Entonces, lo que genera los datos enteros, en primer lugar, puede crear una instancia de la clase derivada con todas las "respuestas" de la instrucción switch.

Una tercera opción es crear una estructura de datos que asigne patrones a acciones (es decir, funciones u objetos con métodos virtuales). Puede buscar el valor del interruptor en esta estructura de datos y ejecutar la acción apropiada.


Dependiendo de lo que evalúe la instrucción switch, es posible que desee refactorizarla utilizando el Patrón de estrategia. Eche un vistazo a esta publicación para ver un ejemplo de cómo reemplazar un interruptor en valores enum con clases separadas para manejar cada función.

También puede ser que usar el interruptor con 20 cajas sea en realidad el mejor curso de acción para ello. Mientras sea legible y cada resultado transmita claramente cuál es la acción, no hay necesidad de refactorizarla realmente.


En general, creo que debería refactorizar solo cuando lo necesite, como cuando desea agregar más funciones, pero el diseño actual no está preparado para la tarea. Luego debe refactorizar sin agregar la nueva funcionalidad, y solo luego agregar la nueva característica.

En otras circunstancias, no se moleste en refactorizar. Hazlo cuando lo necesites, de lo contrario, probablemente haya cosas más importantes que hacer.

Si realmente lo necesita, entonces el patrón de diseño del visitante es un reemplazo común de la caja del interruptor, aunque debe tener en cuenta que tiene inconvenientes. (es decir, echa un vistazo a www.objectmentor.com/resources/articles/acv.pdf )


No hay nada de malo en tener 20 casos en una declaración de cambio. Puede ordenar el código mediante refactorización y, como mínimo, mover el procesamiento de casos a métodos / funciones.




Tres sugerencias (haciéndose eco de algunas ya dadas):

  1. Quizás un cambio no es tan malo como crees. Puede ser feo si los bloques de la caja son grandes. Acórtelos extrayendo la lógica en métodos.

  2. En un lenguaje OO, el polimorfismo podría ser la respuesta, como muchos han señalado.

  3. En un lenguaje funcional, como Javascript, escriba una función que devuelva la función que necesita ejecutar para cualquier entrada. Eso podría usar una declaración de cambio en sí misma, o podría usar una tabla de búsqueda.


si funciona sin errores importantes (no es importante, es decir, no te obligan a quitarte el pelo) ¿por qué molestarse en refactorizarlo? No refaccionen todo.

Si lo desea, puede cambiarlo a polimorfismo, pero esta será una cirugía de disparo, probablemente tendrá que refactorizar mucho más que este bloque de interruptores.


Visita https://github.com/Pedram-Ahmadpour/Switch-Case

Lado del cliente

Cree una instancia de su Condición , luego pase una condición al objeto Condición por la función Cambiar () .

int sense = 2; ConditionSense conditionSense = new ConditionSense(); conditionSense.Switch(sense);

Lado del servidor

  1. Crea una acción de condición . Esta interfaz define cómo ejecutar una condición .

    public interface IAction { void Do(); }

  2. Crea la lista de casos que deseas. Estas clases deben implementar acción de condición e ICase ; Mantenlos ligeros.

    public class CaseCry : IAction, ICase<int?> { public int? Key { get { return 2; } } public void Do() { Sense.Cry cry = new Sense.Cry(); cry.Act(); } }

    • ICase solo tiene una clave que es utilizada por la función Switch () para navegar por los casos.

      public interface ICase<TCase> { TCase Key { get; } }

  3. Cree una clase de condición que hereda la clase abstracta genérica SwitchCase .

    • Agregue todos los casos que desee a la propiedad Cases .
    • Defina una función Switch () y navegue la propiedad Cases para buscar coincidencias de casos, luego ejecútelos como una acción de condición .

      public class ConditionSense : SwitchCase<int?> { public ConditionSense() { Cases = new List<ICase<int?>> { new CaseSmile(), new CaseCry() }; DefaultCases = new List<ICase<int?>> { new CaseNoSense() }; } public void Switch(int? key) { IEnumerable<IAction> matches = Cases.Where(p => p.Key.Equals(key)) .Select(p => p as IAction); if (matches.Count() > 0) foreach (IAction match in matches) match.Do(); else foreach (IAction defaultCase in DefaultCases) defaultCase.Do(); } }

Sonríe , llora ..., puede ser enorme, no te preocupes por el tamaño de ellos; condición de acción y ICase mantenerlos carga floja.

public class Sense { public class Smile { public void Act() { Console.WriteLine("I''m smiling :-)"); } } public class Cry { public void Act() { Console.WriteLine("I''m crying :-("); } } public class NoSense { public void Act() { Console.WriteLine("I''ve no sense :-|"); } } }