重构(C)伪代码以删除goto

时间:2013-08-06 09:16:48

标签: java c goto

在Java中重构这个的最佳实践是什么?

while (1) {
  // initialisation

  for (int i = 0; i < MAX_ATTEMPT; i++) {
    if (try_something()) goto step2;
  }
  continue;

step2:  
  for (int i = 0; i < MAX_ATTEMPT; i++) {
    if (try_next_thing()) goto step3;
  }
  continue;

step3:
  ...
}    

7 个答案:

答案 0 :(得分:3)

首先要确定代码尝试完成的内容:

  • 一遍又一遍地执行以下操作:
  • 调用try_something()最多MAX_ATTEMPT次,如果它永远不会返回true则重新启动。
  • 将try_next_thing()调用至MAX_ATTEMPT次,如果永远不会返回true则重新启动。

然后,编写执行此操作的代码,例如:

while (true) {

    int i;

    for (i = 0; i < MAX_ATTEMPT && !try_something(); ++ i)
        ;
    if (i == MAX_ATTEMPT)
        continue;

    for (i = 0; i < MAX_ATTEMPT && !try_next_thing(); ++ i)
        ;
    if (i == MAX_ATTEMPT)
        continue;

    // etc.

}

还有很多其他方式可以表达这一点。例如,您可以将每个步骤分解为一个方法,并利用&amp;&amp; amp;&amp;当一个是假的时候会停止评估它的论点:

boolean doFirstThing () {
    int i;
    for (i = 0; i < MAX_ATTEMPTS && !try_something(); ++ i)
        ;
    return i < MAX_ATTEMPTS;
}

boolean doSecondThing () {
    int i;
    for (i = 0; i < MAX_ATTEMPTS && !try_other_thing(); ++ i)
        ;
    return i < MAX_ATTEMPTS;
}

// then, elsewhere
while (true)
    doFirstThing() && doSecondThing();

或者其他什么。我不确定我是否会将后者称为“最佳实践”,因为它有点混淆(这并不是说它在某些情况下不合适),但它只是一个例子。通常,当移植到另一种语言时:分析原始 - &gt;该怎么办? - &GT;重新实现目标语言。优先级是代码正确性,第二个(但不远)是清晰度。

答案 1 :(得分:2)

对于文字,但不是最好的翻译,你可以做。使用break作为goto不是一个好主意,除非你必须生成代码并且没有简单的方法。

while (true) {
    // initialisation

    step2:
    {
        for (int i = 0; i < MAX_ATTEMPT; i++) {
            if (try_something()) break step2;
        }
        continue;
    }

    step3:
    {
        for (int i = 0; i < MAX_ATTEMPT; i++) {
            if (try_next_thing()) break step3;
        }
        continue;
    }

    step4:
    ...
}

答案 2 :(得分:2)

我很想封装这些步骤并使用类似状态机的东西:

enum Step {
    STEP1 {
        @Override
        public Step attempt() {
            for (int i = 0; i < MAX_ATTEMPT; i++) {
                if (try_something()) return STEP2; // advance to next step
            }
            return STEP1; // return to step 1
        }
    },
    STEP2 {
        @Override
        public Step attempt() {
            for (int i = 0; i < MAX_ATTEMPT; i++) {
                if (try_next_thing()) return STEP3; // advance to next step
            }
            return STEP1; // return to step 1
        }
    },
    STEP3 { /* etc. */ },
    . . .
    ;
    public abstract Step attempt();
}

然后(如果我理解原始的意大利面条逻辑)你可以把你的循环编写为:

Step step = Step.STEP1;
while (1) {
    // initialisation

    step = step.attempt();
}

答案 3 :(得分:1)

也许不是最好的解决方案,但我通常会这样做:

boolean success = false;

for (int i = 0; i < MAX_ATTEMPT && !success; i++) {
    success = try_something()
}

if (success) {
    success = false;
    for (int i = 0; i < MAX_ATTEMPT && !success; i++) {
        success = try_next_thing();
    }
}

希望有所帮助。

答案 4 :(得分:0)

我首先将C代码重构为一些不那么重复的东西:

enum { STEP1, STEP2, STEP3, /*...*/ };

typedef int ThingToTry();

ThingToTry *things_to_try[MAX_STEP] = {
    try_something,
    try_next_thing,
    /*...*/
};

int next_step (int (*thing_to_try)(), int true_step, int false_step) {
    for (int i = 0; i < MAX_ATTEMPT; i++) {
        if (thing_to_try()) return true_step;
    }
    return false_step;
}

/*...*/

    step = STEP1;
    while (step != MAX_STEP) {
        if (step == STEP1) {
            /*...initialization */
        }
        step = next_step(things_to_try[step], step+1, STEP1);
    }

Java中的相应代码:

enum StepEnum { STEP1, STEP2, STEP3, //...
              }

interface ThingToTry {
   bool do_it ();
}

class TrySomething extends ThingToTry //...
class TryNextThing extends ThingToTry //...

StepEnum next_step (ThingToTry thing_to_try,
                    StepEnum true_step, StepEnum false_step) {
    for (int i = 0; i < MAX_ATTEMPTS; ++i) {
        if (thing_to_try.do_it()) return true_step;
    }
    return false_step;
}

//...
    ThingToTry[MAX_STEP] things_to_try = {
        new TrySomething,
        new TryNextThing,
        //...
    };

    while (step != MAX_STEP) {
        if (step == STEP1) {
            //...initialization
        }
        StepEnum true_step = StepEnum.values()[step.ordinal()+1];
        step = next_step(things_to_try[step.ordinal()], true_step, STEP1);
    }

答案 5 :(得分:0)

对我来说最有效的是在功能之间划分逻辑,这就是我的想法:

bool attempt_something() {
   for(int i = 0; i < MAX_ATTEMPT: i++) {
      if (try_something())
         return true;
   }
   return false;
}

bool attempt_something_else() {
   for(int i = 0; i < MAX_ATTEMPT: i++) {
      if (try_something_else())
         return true;
   }
   return false;
}

你的同时将成为

while (1) {
   if (!attempt_something())
      continue;
   if (!attempt_something_else())
      continue;
   ...
}

答案 6 :(得分:0)

首先将代码转换为C语言中的面向对象设计。您的代码本质上是一个状态机,因此您应该能够用一个代替它。

典型的基于函数指针的状态机示例:

typedef bool (state_t*)(void);

state_t state [STATES_N] = {   // array of function pointers
  &try_something,
  &try_next_thing,
  ...
};


int state = 0;  

while (1) {

  for (int i = 0; i < MAX_ATTEMPT; i++) {

    if(try[state]()) {
      state++;
      if(state == STATES_N) {
        state = 0;
      }
    }
  }
}

要将其转换为Java OO,我想你会将每个状态交换为类的对象,其中类具有try函数。