目前:
void deleteCase(caseId, version){
var case = getCase(caseId);
if(case is null) throw ArgumentNullException(caseId);
if(verifyVersion(case, version) == false) return;
return delete(case);
}
bool verifyVersion(case, version){
if(version is null) throw ArgumentNullException(version);
// call db to verify the version is mathching
}
deleteCase(1, null)
=> 它会抛出异常,因为版本不能是 null
问题:现在我们有一种情况,我们可以在不提供版本的情况下删除案例,这意味着可以在不提供
deleteCase
的情况下调用version
。
解决方案1:添加一个可选标志,指示不需要检查版本
void deleteCase(caseId, version, checkVersion = true){
var case = getCase(caseId);
if(case is null) throw ArgumentNullException(caseId);
if(checkVersion == true AND verifyVersion(case, version) == false) return;
return delete(case);
}
旧电话:
deleteCase(1, null)
=> 按之前的预期工作,因为 checkVersion 默认为 true
deleteCase(1, "1.0")
=> 按之前的预期工作,因为 checkVersion 默认为 true
新来电:
deleteCase(1, null, true)
=> 按之前的预期工作
deleteCase(1, null, false)
=> 按我们想要的方式工作
deleteCase(1)
=> 按我们想要的方式工作
问题是我们添加了一个新参数来控制另一个参数=>不被接受。 而且我们也不应该能够做到
deleteCase(1, "1.0", false)
哪个版本是多余的
解决方案2:重载deleteCase,使其不带版本参数
void deleteCase(caseId){
var case = getCase(caseId);
if(case is null) throw ArgumentNullException(caseId);
return delete(case);
}
void deleteCase(caseId, version){
var case = getCase(caseId);
if(case is null) throw ArgumentNullException(caseId);
if(verifyVersion(case, version) == false) return;
return deleteCase(caseId);
}
现在任何
deleteCase
调用都可以按预期工作。但唯一的问题是,如果版本通过,getCase
会被调用两次,这使得它性能不佳。
知道我们可以做什么来拨打一个电话吗?
一种解决方案是创建一个私有方法,该方法接受 case 对象并删除它。两个公共deleteCase方法都会调用私有方法。您将进行 DRY 练习。
但我想警告您有关在第一个解决方案中传递控制标志的问题。这确实是一个坏主意,因为决策关注点转移到了客户端,并且会将逻辑泄漏给客户端代码。
另一方面,您应该使这两种方法变得特殊,以便开发人员清楚地知道为什么他们会使用其中一种或另一种。我的意思是使用该方法的另一个名称来指示在什么情况下使用该方法,例如 deleteCaseForSpecificVersion。 或者引入一个工厂来选择删除策略也许会更好。