我有一种方法,由于一些非直观的业务需求,需要广泛的评论。我不得不重构它不那么简洁(defactor?),但是当我说我评论了以下方法的地方是必要的,以确保业务要求不会被意外更改时,请相信我:
public bool CheckBasedOnApplicableConditions()
{
bool conditionOne;
bool conditionTwo;
// Comments to explain why BusinessLogic is used
if (BusinessLogic())
{
//Comments discussing SecondaryBusinessLogic
conditionOne = true;
conditionTwo = SecondaryBusinessLogic();
}
else
{
//Comments discussing this scenario
conditionOne = DifferentBusinessLogic();
conditionTwo = !conditionOne;
}
//Comments about the CheckForCondition calls
if (conditionOne && CheckForConditionOne())
{
return true;
}
if (conditionTwo && CheckForConditionTwo())
{
return true;
}
return false;
}
我真的希望将此方法从未被开发人员打破(即一个月内的我)。我认为重要的是要强调业务要求包括必须必须中的至少一个。所以我在最终返回之前添加了以下代码:
//ReSharper normally points out this always evaluates to false,
// but because an exception is being thrown it does not complain.
if (!conditionOne && !conditionTwo)
{
throw new InvalidOperationException
("Condition One or Two must be applicable!");
}
预期的效果是,如果开发人员不小心违反业务要求,则抛出异常而不是静默返回false并创建需要时间跟踪的错误。这不是我之前见过的模式,但是当添加投掷时,ReSharper会自动抑制自己的“代码是启发式无法访问”警告。
我的问题是:这种方法是否存在意外的副作用?即性能损失,或我无视的可维护性问题,或其他意外情况?我知道我可以重新考虑方法,使其更稳定;但我担心这会以牺牲理解为代价。
答案 0 :(得分:1)
在某些时候自检代码是可以的,我建议System.Diagnostics.Debug.Assert()
在这里。
但验证这种逻辑条件更好地通过外部测试来处理,即单元测试或(尚未非常成熟的)代码契约。
因为你只能测试一个方法的结果,所以这将是一个将它重构成更小块的论据。
答案 1 :(得分:1)
现在我有了:
public IEnumerable<Condition> DetermineConditionsToTest()
{
//determine what conditions to return
}
public bool CheckIfAnyConditionIsMet(IEnumerable<Condition> conditionsToCheck)
{
// check if any condition is met.
}
现在我对每个都进行了单元测试。经验教训是:如果你认为你不能对某些东西进行单元测试;继续打破它,直到可以。