我有一个实用程序类库。其中一个类执行类似于 tar 的文件归档,因为.NET已经有 gz 。
归档类使用magic numbers进行版本控制,因此它可以支持使用此库的旧版本压缩的文件。这是一个例子:
public void ExtractTo(DirectoryInfo directory, bool overwrite = false)
{
// removed sanity checks, try/catch, etc. for brevity
using (FileStream archiveStream =
new FileStream(this.archivefile.FullName, FileMode.Open))
{
byte[] magicNumber = new byte[8];
archiveStream.Read(magicNumber, 0, 8);
string ArchiveLib_Version = Encoding.UTF8.GetString(magicNumber);
switch (ArchiveLib_Version)
{
case "ALib0000":
ExtractTo_v0(archiveStream, dirInfo);
break;
case "ALib0001":
ExtractTo_v1(archiveStream, dirInfo);
break;
default:
throw new IOException("Archive file invalid.");
}
}
}
但是,版本化方法依赖于库中可能在将来更改的其他例程,例如我的Stream.SubStream扩展方法:
protected void ExtractTo_v1(FileStream archiveStream, DirectoryInfo dirInfo)
{
// ...
foreach (ArchiveFileInfo arcInfo in archiveHeader)
{
Stream sourceBytes = archiveStream.SubStream(
arcInfo.archivePosition, arcInfo.archiveLength);
using (GZipStream gz = new GZipStream(sourceBytes,
CompressionMode.Decompress, true))
{
// ...
}
}
}
我是否需要对整个库进行版本控制,创建依赖方法列表,还要做其他事情吗?
在库中保持向后兼容性的最佳做法是什么?
答案 0 :(得分:2)
您有两个广泛的选择:
在维护向后兼容性的同时修改现有代码
您可以继续修改SubStream
(以及其他相关方法)的实施,以用于较新版本的存档。这种方法可以帮助您最大限度地减少代码库中重复代码的数量,从而帮助您遵守DRY原则。
Unit tests可用于确保SubStream
(以及其他相关方法)继续适用于旧存档版本。您可以编写一组测试,使用mock流调用SubStream
,提供旧的存档数据,并确保它为您提供预期的结果。当您为新的存档版本更改实施SubStream
时,一系列测试可以让您确信您没有为旧存档版本打破它。
这里的缺点是你必须花费精力维护一套测试。
或强>
为新版本编写新代码并单独留下旧代码
此方法以Open/Closed principle为模型。如果您的SubStream
方法已关闭以进行修改,则它将永远不会中断。如果您需要使用SubStream
方法中的新功能或不同功能来创建新的存档版本,则可以为新格式编写新的SubStream
方法,并继续使用旧的,未触及的SubStream
旧格式的方法。
这比上述选项要少得多 - 不需要进行全面的回归测试,只需继续为新功能编写新代码并将其称为一天。缺点是您可能最终在代码库中出现重复的代码。如果您发现影响方法的多个版本的缺陷,则可能会出现问题 - 您必须在每个版本中找到并修复错误,而不是仅仅将其修复到一个位置。
你采取哪种方法完全取决于你:)