Nettoyage de flux de contrôle lorsqu'ils traitent avec des arguments de ligne de commande [C #]
-
21-09-2019 - |
Question
Je fais face à un programme qui fait beaucoup de si ... autre ramification basée sur des arguments de ligne de commande. Ceci est en C #, mais je suis sûr qu'il est applicable à Java, C ++, etc. Voici les grandes lignes:
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
)
{
Comme vous pouvez le dire, il est un peu un gâchis. Y at-il un modèle de conception ou deux autres qui seraient plus applicables sur le nettoyage des choses un peu? modèle de commande, peut-être? Merci pour les conseils et astuces.
La solution
Je suis partie à l'aide d'instructions de commutation sur le tableau d'arguments et la définition des propriétés dans une classe de configuration d'une sorte pour chaque argument attendu. Il semble que vous vous attendez à une chaîne d'argument très formaté spécifiquement plutôt que de laisser des valeurs de consigne, vous pouvez essayer:
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;
}
}
Ma méthode préférée serait quelque chose comme
foreach(string arg in args)
{
switch(arg)
{
case PROCESS_CUSTOMER:
// Set property
break;
...
default:
// Exception?
break;
}
}
NOTE: args.length == 1 est plus rapide que args.length> 0 && args.length <2. Il est aussi un peu plus lisible
Autres conseils
imbrication d'arrêt.
Vous pouvez passer comme (+1) Joel dit, ou vous pouvez simplement briser votre logique dans les appels de méthode claire.
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;
}
puis, dans vos méthodes de processus ...
private static void ProcessOptionTwo(string argumentTwo)
{
if(argumentTwo == PROCESS_CUSTOMER ||
argumentTwo == PROCESS_ADMIN ||
/* etc blah blah */
}
Gardez vos méthodes aussi simple que possible et briser plus, les algorithmes de confusion dans les appels de méthode distincts qui, par leur nom, donnent une indication claire de ce qu'ils font.
Vous n'avez pas besoin else
si vous avez déjà retourné. Cela pourrait couper beaucoup de votre imbrication. Vous pouvez également essayer d'utiliser un commutateur au lieu d'un tas de ifs imbriquées.
Je pris le code de ce Code article du projet il y a longtemps et fait ma propre version à utiliser pour les applications en ligne de commande. Je l'ai fait mes propres modifications à elle, comme faire la classe hériter de dictionnaire, etc. Mais la partie regex du code est très bon, et fait ce genre de ligne de commande passe simple comme bonjour.