良好的程序设计/最佳实践,以避免多次冗余检查(例如在C ++中)

时间:2013-06-25 04:24:10

标签: c++

假设我有一些函数(例如method1()method2()),并且只有在满足某些条件时才应执行这些函数中的每一个(对于这个简单的示例,请调用此函数)检查布尔值)。为了隔离条件检查,我将检查放在每个函数中 - 例如

void method1()
{
    if (bDoSomething) {
        doSomething1();
        doSomething2();
    }
}

void method2()
{
    if (bDoSomething) {
        doSomething1();
        doSomething3();
    }
}

但是,doSomethingN()函数也可以在method1()method2()之外自行调用,因此我将条件检查添加到每个doSomethingN()函数中 - 例如

void doSomething1() {
    if (bDoSomething) {
        doWork1();
    }
} 

此外,假设method1()method2()可以在同一个函数中调用 - 例如。

void func1() {
    method1();
    method2();
}

这会导致在调用func1()method1()method2()时对相同条件进行多次检查。为避免多次检查,最好的方法是什么?

关于如何最好地设计/构建程序以最小化这类事情,是否有任何好的资源?

5 个答案:

答案 0 :(得分:0)

取决于您问题的具体细节。您可以做的一件事是将检查放在doSomething函数中。

void doSomething1() {
    if(!bDoSomething) return;

    ....
} 

您无需检查外部函数中的条件,只需调用相应的函数,它们将在需要时执行。您仍然可以将其保留以进行自我记录。

您的代码也可能比需要的更复杂。要诊断您需要更多细节和全局。

p.s您可以尝试我的检查方式,即返回为负,而不是进行积极处理,这可能会使代码有时更清晰,但会降低缩进级别。

答案 1 :(得分:0)

假设您有两个类:PrivateCaptain。让我们以Captain s命令Private的方式使用它们。 Captain想要什么,Private s。我们有一个例子:

void Captain::HaveSomethingDone() {
   if(AmIAtAnAdvantage()) {
       for(Private& p : m_privates) {
           p.Attack();
       }
   }
   else if(IsSituationStalemate()) {
       for(Private& p : m_privates) {
           p.Hold();
       }
   }
   else if(IsALosingBattle()) {
       for(Private& p : m_privates) {
           p.Retreat();
       }
   }
}

在上面的示例中,Private无条件地 {em} Captain想要什么,因为Captain知道它在做什么。通过这种方式,我们可以明确(呃)分离关注点

另一个,现在用于方法。以此为例:

void DoSomething() {
    if(ShouldPrint()) {
        Print();
    }

    if(ShouldCleanUp()) {
        CleanUp();
    }

    // ...
}

在上面的示例中,DoSomething()知道它应该做什么。是决定应该做什么的人。因此,Print()CleanUp()方法应该无条件地执行它的意图。 Print()打印。 CleanUp()清理。

现在考虑。

答案 2 :(得分:0)

我认为避免多次条件检查的最佳方法是在代码中实现State设计模式。此设计模式只允许您将代码用作状态机,这意味着根据对象状态的状态,您可以调用所需的方法。您可以在此处获取更多信息http://en.wikipedia.org/wiki/State_pattern

答案 3 :(得分:0)

嗯,我猜你的支票很重,否则我不会担心双重通话,因为你的代码会更清洁。

我有两件事:

  • 在班级的某个地方缓存第一个检查结果。

  • 创建调用者对象,只有在条件为真时才能创建。

类似的东西:

class ConditionalCaller
{
public:
    void Method1();
    void Method2();
};

class YourClass
{
public:
    ConditionalCaller* GetCaller()
    {
        if (CanGetCaller())
            return new ConditionalCaller();

        return NULL;
    }

    bool CanGetCaller();
};

答案 4 :(得分:0)

有几种不同的情况:

  1. method1method2是私有的,您可以控制它们的调用位置,并且可以保证检查所有前置条件。在这种情况下,您可以在这些方法中避免这些测试。
  2. method1method2是公开的,并且您记录了一些前提条件,必须满足几个条件(例如在std中的容器中)。
  3. method1 amd method2检查他们的前提条件并作出相应的回应(抛出和例外,什么都不做,......)。
  4. 您创建方法的已检查和未检查版本(混合其他变体),并通过不同的名称*_checked或其他参数(例如非新增)区分它们。
  5. 但请记住Scott Meyers:使接口易于正确使用且难以正确使用。

    所以你做出决定并记录下来。