3

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

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

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

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

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

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

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

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

有没有关于如何最好地设计/构建程序以最小化这种事情的好资源?

4

5 回答 5

0

假设您有两个类:PrivateCaptainCaptain让我们以s 命令s的方式使用它们Private。想要什么CaptainPrivate就做什么。让我们来看一个例子:

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();
       }
   }
}

在上面的例子中,Privates无条件地做他们Captain想做的事情,因为他们Captain知道自己在做什么。这样,我们就有了清晰的(呃)关注点分离

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

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

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

    // ...
}

在上面的例子中,DoSomething()知道它应该做什么。它是决定它应该做什么的人。因此,Print()andCleanUp()方法应该无条件地做它应该做的事情。Print()印刷。CleanUp()清理。

现在考虑。

于 2013-06-25T04:39:53.010 回答
0

有几种不同的情况:

  1. method1并且method2是私有的,您可以控制调用它们的位置,并且可以保证检查所有前置条件。在这种情况下,您可以在这些方法中避免这些测试。
  2. method1并且method2是公开的,并且您记录了作为先决条件必须满足的几个条件(例如在 std 中的容器中)。
  3. method1amdmethod2检查它们的先决条件并做出相应的响应(抛出和异常,什么都不做,...)。
  4. 您创建方法的检查和未检查版本(混合其他变体)并通过不同的名称*_checked或附加参数(如 notthrow new )区分它们。

但请记住 Scott Meyers:使界面易于正确使用和难以正确使用。

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

于 2013-06-25T07:22:44.107 回答
0

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

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

    ....
} 

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

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

ps 你可以试试我的检查方式,即return-if-negative,而不是process-if-positive,这有时可能会使代码更干净一些,但会降低缩进级别。

于 2013-06-25T04:32:13.303 回答
0

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

于 2013-06-25T05:09:23.043 回答
0

好吧,我猜你的检查很重,否则我不会担心双重调用,因为你的代码会更干净。

我有两个想法:

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

  • 制作调用者对象,仅当您的条件为真时才能创建。

像这样的东西:

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

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

        return NULL;
    }

    bool CanGetCaller();
};
于 2013-06-25T05:26:29.240 回答