1

我正在处理一些最初设计用于处理两种不同类型文件的旧代码。我最近的任务是在这段代码中添加一种新的文件。我的大部分问题都通过用一个新条目填写一个扩展的 XML 文件来解决,该条目处理从列表命名到文件如何以复数小写形式编写的所有内容。但这最终还是不够的,因为在 24 个不同的代码文件中可能有 50 个不同的地方,我必须更新仅针对原始两种文件类型分支的硬编码开关语句。

不幸的是,这没有一致性。有些方法一半来自 XML 文件,一半来自硬编码。一些看起来可以从 XML 文件中操作的文件不需要,而一些我希望我需要更新硬代码的文件不需要它。因此,找到其中大部分的唯一方法是在整个系统只有部分运行时运行测试,找到修复的一步(当我很幸运错误日志实际上告诉我发生了什么时),然后再次运行整个事情。这浪费了时间测试已经确认可以工作的代码部分,最好把时间花在测试我必须添加的新部分上。

这是一个麻烦半,幸运的是,我可以预期在不久的将来我将不得不添加另一种新的文件。

有没有可以帮助这种努力的解决方案?我可以输入当前功能的一些参数,记录整个代码项目中实际需要更新的点,并在下次需要向代码添加新功能时运行一些不错的东西。它甚至不需要完全自动化,这将帮助我直接导航到所有内容的特定点,甚至可能记录需要加载的参数类型。

怀疑它特别重要,但代码由 ASP.NET 页面、一些 ASP.NET 控件、数百个 C# 代码文件和一些额外的 XML 文件组成。目前这一切都在几个大型 Visual Studio 2008 项目中。

4

2 回答 2

0

我完全同意关于使用 Michael Feathers 的书来学习如何将新测试插入遗留代码的评论。我也强烈推荐 Martin Fowler 的 Refactoring。听起来您需要为代码做的是实现“用多态性替换条件”重构。

我想你今天的代码看起来有点像这样:

if (filetype == 23)
{
  type23parser.parse(file);
}
else if (filetype == 69)
{
  filestore = type69reader.read(file);
  File newfile = convertFSto23(filestore);
  type23parser.parse(newfile);
}

您要做的是将所有“if (type == foo)”类型的逻辑抽象为在工厂中创建的策略模式。

class FileRules : pReader(NULL), pParser(NULL)
{
private:
  FileReaderRules *pReader;
  FileParserRules *pParser;
public:
  void read(File* inFile) {pReader->read(inFile);};
  void parse(File* inFile) {pParser->parse(inFile);};
};

class FileRulesFactory
{
  FileRules* GetRules(int inputFiletype, int parserType)
  {
    switch (inputFiletype)
    {
    case 23: 
      pReader = new ASCIIReader;
      break;
    case 69:
      pReader = new EBCDICReader;
      break;
    }
    switch (parserType)
    ... etc...

那么您的主要代码行如下所示:

  FileRules* rules = FileRulesFactory.GetRules(filetype, parsertype);
  rules.read(file);
  rules.parse(file);

完成这种重构,并添加一组新的文件类型、解析器、读取器等,就像为新类型编写一个专有文件一样简单。

当然,去看看书。我在这里大大简化了它,并且可能弄错了,但是您应该从中大致了解如何处理它。我还可以推荐另一本书,“Head First Design Patterns”,其中有一个关于工厂模式的精彩部分(如果你喜欢那些“Head First”类型的书。)

于 2010-06-05T06:43:32.740 回答
0

不完全是您所描述的,但是如果您可以在代码中引入一个接缝并放置一些您可以突破和模拟的接口,那么一套单元/集成测试将大大帮助您修改您可能无法修改的旧代码完全理解好。

于 2010-06-04T18:49:04.807 回答