我有一个测试脚本,它对一个对象执行某些操作,然后对第二个对象执行相同的操作。这种情况持续了很长一段时间。有了这么多可预测的重复,以至于自动化似乎已经成熟,但我无法弄清楚如何。我不会那么在乎,除非重复这么多,否则使用错误的变量很容易忽略(例如:当prodXyz用于时,stagingXyz。)
以下详细信息无关紧要。重要的是模式。
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");
}
}
我不想通过,例如,替换此
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));
用这个
var stagingTableColumns = doStuff(stagingTable, matchedColumns);
var prodTableColumns = doStuff(prodTable, matchedColumns);
因为我必须确保第一行中的所有内容都是stagingXyz
,第二行是prodXyz
。对于1行来说并不是那么糟糕,但是测试脚本非常庞大,只能执行以下两项操作之一:
同样地,将这些项目包装在一个数组中并且doStuff[0]; doStuff[1];
包含同样容易出错的错字错误,只有0与1的拼写错误才会更难以一目了然。
我想过制作2个容器对象(一个用于分段,一个用于prod)并将这两个对象放在一个集合中,但我担心这会导致一个非常难以维护的无数小环。
无论如何要简化这个并且仍然具有可读性和可维护性吗?
答案 0 :(得分:0)
编辑 - 阅读完评论后,我发现问题现在更加清晰了。我认为问题更多的是一个大功能的清晰度与提出解决可读性问题的时髦方法。我认为你把它分成更小的功能越多,它就越清晰。
如果主要功能被分解成这样的东西:
public void mainMethod(DB prodDB, DB stagingDB)
{
doPart1(prodDB, stagingDB);
doPart2(prodDB, stagingDB);
}
......并且每个部分都有如此明确的命名输入:
public void doPart1(DB prodDB, DB stagingDB)
{
// Code...
}
随着您的工作越来越精细,事情会变得清晰起来。在doPart1方法中工作的任何人只需要关注它的少量代码,并且在主要部分工作的任何人都不应该有一百万件事需要查看。我理解这听起来有点过于简单,但听起来你正试图解决一个问题,如果代码被正确分解,这个问题应该不存在。
如果有一个方法如此庞大且难以理解,以至于另一个开发人员无法弄清楚只有两个变量发生了什么,那么就会出现一个不同的问题。
答案 1 :(得分:0)
你能生成测试脚本吗?输入可能读取类似
的内容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);
...
}
包含%% AB %%的行可能会扩展为同一行的两个副本,一个带有“A”替换,另一个带有“B”替换,其中%% A %%或%% B %% by本身可能会被取代。