La limpieza de flujo de control cuando se trata de argumentos de línea de comandos [C #]
-
21-09-2019 - |
Pregunta
Estoy tratando con un programa que hace un montón de si ... otra ramificación basado en argumentos de línea de comandos. Esto es en C #, pero estoy seguro de que es aplicable a Java, C ++, etc. Aquí está el esquema general:
if (args.Length == 0)
{
//do something
}
if (args.Length > 0 && args.Length < 2)
{
Console.WriteLine("Only one argument specified. Need two arguments");
return 0;
}
else if (args.Length > 0 && args.Length >= 2)
{
//Process file - Argument 1
if(args[0].Trim() == PROCESS_OPTION_ONE
|| args[0].Trim() == PROCESS_OPTION_TWO)
{
//Process file - Argument 2
if(args[1].Trim() == PROCESS_CUSTOMER
|| args[1].Trim() == PROCESS_ADMIN
|| args[1].Trim() == PROCESS_MEMBER
|| args[1].Trim() == PROCESS_GUEST
|| args[1].Trim() == PROCESS_USER
)
{
Así como se puede decir, que es un poco un lío. ¿Hay un patrón de diseño o dos que sería más aplicable a la limpieza de las cosas un poco? patrón de comando, tal vez? Gracias por el consejo y las extremidades.
Solución
Soy parcial a la utilización de sentencias switch en la matriz de argumentos y la configuración de las propiedades de una clase de configuración de algún tipo para cada argumento anticipado. Parece que usted está esperando una cadena argumento muy especialmente formateado en lugar de permitir valores establecidos, podría intentar:
if(args[0].Trim() == PROCESS_OPTION_ONE || args[0].Trim() == PROCESS_OPTION_TWO)
{
//Process file - Argument 2
switch(args[1].Trim()
{
case PROCESS_CUSTOMER, PROCESS_ADMIN, PROCESS_MEMBER, PROCESS_GUEST, PROCESS_USER:
// Do stuff
break;
default:
// Do other stuff
break;
}
}
Mi método preferido sería algo así como
foreach(string arg in args)
{
switch(arg)
{
case PROCESS_CUSTOMER:
// Set property
break;
...
default:
// Exception?
break;
}
}
NOTA: args.length == 1 es más rápido que args.length> 0 && args.length <2. También es un poco más fácil de leer
Otros consejos
Detener anidación.
Se puede cambiar como dijo (1) Joel, o simplemente puede romper su lógica en las llamadas a métodos claros.
if(args.Length <= 1)
{
Console.WriteLine("Need 2 args kthx");
return;
}
if(args.Length > 2)
{
Console.WriteLine("More than 2 args don't know what do");
return;
}
var arg1 = args[0].Trim();
var arg2 = args[1].Trim();
switch(arg1)
{
case PROCESS_OPTION_ONE:
ProcessOptionOne(arg2);
break;
case PROCESS_OPTION_TWO:
ProcessOptionTwo(arg2);
break;
default:
Console.WriteLine("First arg unknown I give up");
return;
}
A continuación, en sus métodos de proceso ...
private static void ProcessOptionTwo(string argumentTwo)
{
if(argumentTwo == PROCESS_CUSTOMER ||
argumentTwo == PROCESS_ADMIN ||
/* etc blah blah */
}
Mantenga sus métodos tan simple como sea posible y romper más, confundiendo algoritmos en llamadas a métodos distintos que, a través de su nombre, dan una indicación clara de lo que están haciendo.
No es necesario el else
si ya has regresado. Eso podría cortar una gran cantidad de su anidación. También podría tratar de usar un interruptor en lugar de un montón de ifs anidados.
el código de este artículo Proyecto de Código hace mucho tiempo e hice mi propia versión del mismo para usar en aplicaciones de línea de comandos. Hice mis propias modificaciones a la misma, como la fabricación de la clase hereda de diccionario, etc, pero la parte de expresiones regulares del código es muy bueno, y hace que este tipo de línea de comandos muy fácil.