我正在使用一些最初设计用于处理两种不同文件的旧代码。我最近负责为此代码添加一种新类型的文件。我的大部分问题都是通过填写一个新的条目来解决的,该文件包含一个新条目,该条目处理从命名列表到文件以多个小写形式写入的所有内容。但这最终还是不够,因为在24个不同的代码文件中可能有50个不同的地方,我不得不更新硬编码的switch语句,这些语句只对原始的两种文件类型进行分支。
不幸的是,这没有一致性;有一些方法可以从XML文件中运行一半,而且只有一半的硬编码。一些看起来像是在XML文件下运行的文件没有,而我希望我需要更新硬编码的一些文件不需要它。所以找到大部分这些的唯一方法是在只有部分操作时运行测试整个系统,找到一步修复(当我很幸运,错误记录实际上告诉我发生了什么),然后再次运行整个事情。这浪费时间测试已经确认可以工作的代码部分,花在测试我必须添加的新部件上的时间更长。
这是一个麻烦的一半,幸运的是,我预计在不久的将来我将不得不添加另一种新的文件。
有没有可以帮助这种努力的解决方案?我可以输入当前功能的一些参数,记录整个代码项目中实际需要更新的点,并在下次需要向代码添加新功能时运行一些不错的东西。它甚至不需要完全自动化,这将帮助我直接导航到所有内容中的特定点,甚至可以记录需要加载的参数类型。
怀疑它是否具体,但代码由ASP.NET页面,一些ASP.NET控件,数百个C#代码文件和一些其他XML文件组成。这些都是目前几个大型的Visual Studio 2008项目。
答案 0 :(得分:0)
不完全是你所描述的内容,但是如果你可以在代码中引入一个接缝并放置一些可以突破和模拟的接口,那么一套单元/集成测试将帮助你修改旧的代码你可能不太了解。
答案 1 :(得分: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”类型的书籍。)