2010-10-14 5 views
0

J'ai un script de test qui fait quelque chose à un objet puis la même chose à un deuxième objet. Cela continue pendant un bon moment. Avec tant de répétitions prévisibles qu'il semble mûr pour l'automatisation, mais je ne peux pas comprendre comment. Je ne m'en soucierais pas si ce n'est qu'avec une telle répétition, il est facile d'oublier d'utiliser la mauvaise variable (ie: stagingXyz quand prodXyz était prévu.)Exécution du code identique sur 2 objets

Les détails ci-dessous ne sont pas pertinents. Ce qui est important est le motif.

var stagingDbs = cleanupDbs(stagingServer.Databases); 
var prodDbs = cleanupDbs(prodServer.Databases); 

printDiff(stagingDbs, prodDbs, "Databases mis-matched"); 

foreach (var db in stagingDbs.Intersect(prodDbs)) { 
    var stagingDb = stagingServer.Databases[db]; 
    var prodDb = prodServer.Databases[db]; 

    var stagingTables = cleanupTables(stagingDb.Tables); 
    var prodTables = cleanupTables(prodDb.Tables); 

    printDiff(stagingTables, prodTables, "Tables mis-matched on " + db); 

    foreach (var table in stagingTables.Intersect(prodTables)) { 
     var stagingTable = stagingDb.Tables[table]; 
     var prodTable = prodDb.Tables[table]; 

     var matchedColumns = stagingColumns.Intersect(prodColumns); 

     var stagingTableColumns = stagingTable.Columns 
      .Cast<Column>() 
      .Where(c => matchedColumns.Contains(c.Name)) 
      .Select(c => formatColumn(c)); 
     var prodTableColumns = prodTable.Columns 
      .Cast<Column>() 
      .Where(c => matchedColumns.Contains(c.Name)) 
      .Select(c => formatColumn(c)); 
     printDiff(stagingTableColumns, prodTableColumns, 
      "Columns mis-matched"); 
    } 
} 

Je ne veux pas passer par, par exemple, en remplaçant cette

 var stagingTableColumns = stagingTable.Columns 
      .Cast<Column>() 
      .Where(c => matchedColumns.Contains(c.Name)) 
      .Select(c => formatColumn(c)); 
     var prodTableColumns = prodTable.Columns 
      .Cast<Column>() 
      .Where(c => matchedColumns.Contains(c.Name)) 
      .Select(c => formatColumn(c)); 

avec ce

 var stagingTableColumns = doStuff(stagingTable, matchedColumns); 
     var prodTableColumns = doStuff(prodTable, matchedColumns); 

parce que je dois faire en sorte que tout dans la 1ère ligne est stagingXyz et la deuxième ligne est prodXyz. Pas si mal pour 1 ligne mais le script de test est énorme et ne fait jamais qu'une de ces 2 choses:

  • foo (stagingXyz); foo (prodXyz);
  • bar (stagingXyz, prodXyz);

De même, l'emballage avec ces éléments dans un tableau et ayant doStuff[0]; doStuff[1]; est soumis à la même erreur typo facile que une faute de frappe avec 0 vs 1 sera encore plus difficile à repérer un coup d'oeil. Je pensais à fabriquer 2 objets de conteneur (un pour la mise en scène, un pour la prod) et mettre ces 2 objets dans une collection mais je crains que cela conduise à un bazillion de minuscules boucles qui seront très difficiles à maintenir. Y a-t-il un moyen de simplifier cela et de le rendre lisible et maintenable?

Répondre

0

Pourriez-vous générer votre script de test?L'entrée peut lire quelque chose comme

var %%AB%%Dbs = cleanupDbs(%%AB%%Server.Databases); 
printDiff(%%A%%Dbs, %%B%%Dbs, "Databases mis-matched"); 
foreach (var db in %%A%%Dbs.Intersect(%%B%%Dbs)) { 

    var %%AB%%Db = %%AB%%Server.Databases[db]; 
    var %%AB%%Tables = cleanupTables(%%AB%%Db.Tables); 

    printDiff(%%A%%Tables, %%B%%Tables, "Tables mis-matched on " + db); 

    ... 
} 

Une ligne contenant %% %% AB pourrait étendre à deux exemplaires de la même ligne, l'un avec le remplacement « A » de remplacement et un avec le « B », où %% Un %% ou %% B %% peut être remplacé par lui-même.

0

Modifier - Après avoir lu vos commentaires, je vois le problème un peu plus clair maintenant. Je pense que le problème est plus la clarté de la grande fonction que de trouver une façon géniale de résoudre le problème de lisibilité. Je pense que plus vous le décomposeriez en fonctions plus petites, plus il serait clair.

Si la fonction principale a été divisé en quelque chose comme ceci:

public void mainMethod(DB prodDB, DB stagingDB) 
{ 
    doPart1(prodDB, stagingDB); 
    doPart2(prodDB, stagingDB); 
} 

... et chaque partie avait bien entrées nommé comme ceci:

public void doPart1(DB prodDB, DB stagingDB) 
{ 
    // Code...  
} 

Les choses se dissiper comme vous fait fonctionner les choses à un niveau de plus en plus granulaire. Quiconque travaille dans la méthode doPart1 doit seulement se préoccuper de sa petite quantité de code, et quiconque travaille dans la section principale ne devrait pas avoir un million de choses à regarder. Je comprends si cela peut sembler une réponse trop simplifiée, mais il semble que vous essayez de résoudre un problème qui ne devrait pas exister si le code est correctement divisé.

S'il existe une méthode tellement énorme et illisible qu'un autre développeur ne peut pas comprendre ce qui se passe avec seulement deux variables, alors il y a un problème différent.

+0

Je pense que la raison pour laquelle il n'est pas structuré de cette façon est déjà parce qu'il a besoin d'effectuer des opérations incrémentales sur cette PAIRE d'objets, pas tout faire pour l'un puis l'autre. – twon33

+0

il semble que votre suggestion serait tout pour obj1 puis tout pour obj2. Ce ne serait pas le même effet que dans l'exemple original; le plus notamment à l'intérieur des boucles. – Dinah

+0

Modifié pour mieux refléter la question posée. – Ocelot20

Questions connexes