在Heuristically Unreachable Code中投掷危险吗?

时间:2013-09-18 18:48:48

标签: c# resharper

我有一种方法,由于一些非直观的业务需求,需要广泛的评论。我不得不重构它不那么简洁(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会自动抑制自己的“代码是启发式无法访问”警告。

我的问题是:这种方法是否存在意外的副作用?即性能损失,或我无视的可维护性问题,或其他意外情况?我知道我可以重新考虑方法,使其更稳定;但我担心这会以牺牲理解为代价。

2 个答案:

答案 0 :(得分:1)

在某些时候自检代码是可以的,我建议System.Diagnostics.Debug.Assert()在这里。

但验证这种逻辑条件更好地通过外部测试来处理,即单元测试或(尚未非常成熟的)代码契约。

因为你只能测试一个方法的结果,所以这将是一个将它重构成更小块的论据。

答案 1 :(得分:1)

Henk的回答让我朝着正确的方向前进:我非常专注于重构这一方法,但我并没有想到这实际上需要两种不同的方法。

现在我有了:

public IEnumerable<Condition> DetermineConditionsToTest()
{
    //determine what conditions to return
}

public bool CheckIfAnyConditionIsMet(IEnumerable<Condition> conditionsToCheck)
{
    // check if any condition is met.
}

现在我对每个都进行了单元测试。经验教训是:如果你认为你不能对某些东西进行单元测试;继续打破它,直到可以。