你认为这种技术“坏”? [英] Do you consider this technique "BAD"?

查看:102
本文介绍了你认为这种技术“坏”?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有时,您需要在某些非关键错误条件下跳过执行方法的一部分。您可以使用例外,但是通常不会在正常的应用程序逻辑中推荐异常。



像这样:

  do 
{
bool isGood = true;

....一些代码

if(!isGood)
break;

....一些更多的代码

if(!isGood)
break;

....一些更多的代码

} while(false);

.....一些其他代码,必须执行。

我使用一个假循环,它将运行一次,



我的一些同事不喜欢这样,他们称之为不良做法。我个人觉得这种方法很光滑。

解决方案

不好的做法,这取决于。



我在这段代码中看到的是一个非常有创意的方式,用较少含硫的关键字写goto。



这个代码有多种替代方法,



您的do / while解决方案



您的解决方案很有趣如果你有很多代码,但会在一些有限的点评估这个处理的退出:

  do 
{
bool isError = false;

/ *一些代码,可能设置isError为true * /
if(isError)break;
/ *一些代码,可能设置isError为true * /
if(isError)break;
/ *一些代码,可能设置isError为true * /
}
while(false);

//其他代码

问题是你不能很容易使用你的if(isError)break;是一个循环,因为它只会退出内循环,而不是你的do / while块。



当然,如果失败是在另一个函数内,函数必须返回某种错误代码,并且您的代码不能忘记正确解释错误代码。



我不会讨论使用ifs或嵌套ifs的替代,因为,after



调用goto a ... goto



也许你应该清楚地在桌子上显示你使用goto的事实,并记录你选择这个解决方案的原因与其他原因。



至少,将显示代码可能出错,并提示审阅者验证或使您的解决方案无效。



您必须仍然打开一个块,而不是打破,使用goto 。

  {
//等
if(/ * some failure condition * /)goto MY_EXIT ;
//等

while(/ * etc。* /)
{
//等等
for(/ * etc。* / )
{
//等
if(/ * some failure condition * /)goto MY_EXIT;
//等
}
//等
if(/ * some failure condition * /)goto MY_EXIT;
//等
}

//等
}

MY_EXIT:

一些其他代码

这样,当你通过goto退出块时,使用goto(这是C ++禁止的)绕过一些对象构造函数。



这个问题解决了从嵌套循环中退出的过程问题(使用goto退出嵌套循环由B. Stroustrup给出的一个例子作为goto的有效使用,但它不会解决一些函数调用可能失败并被忽略的事实(因为有人无法正确测试他们的返回代码,如果有的话)。



当然,现在,你可以从多个点退出你的进程,从多个循环嵌套的深度,所以如果它是一个问题...



try / catch



如果代码不应该失败(因此,失败是例外),或者即使代码结构可能失败,过度复杂退出,那么以下方法可以更清楚:

  try 
{
//全部你的代码
//你可以抛出一些失败的东西
//注意你可以调用函数,使用reccursion,
//有多个循环等,它不会改变
// anything:如果你想退出进程,
//然后抛出一个MyExitProcessException异常。

if(/ * etc. * /)
{
//等等
while(/ * etc。* /)
{
//等
for(/ * etc。* /)
{
//等等
if(/ * some failure condition * /)throw MyExitProcessException ;
//等
}
//等。

callSomeFunction();
//如果满足条件函数将抛出
//所以不需要测试返回代码

//等
}
//等
}

//等
}
catch(const MyExitProcessException& e)
{
// To避免捕获其他异常,你应该
//定义一个MyExitProcessException异常
}

//其他代码

如果上述代码中的某些条件或上述代码调用的某些函数内部不满足,则抛出异常。



这比do / while解决方案有些重要,但是具有相同的优点,甚至可以中止从内部循环或从内部调用的函数的处理。



讨论



您的需求似乎来自于您可以有一个复杂的过程来执行(代码,函数调用,循环等),但是你想要在一些条件(可能是失败,或者因为它比成功比成功)中断它。如果你可以用不同的方式重写它,你应该做。



如果你可以编写代码它与try / catch,做它:要中断一个复杂的代码,抛出异常是正确的解决方案(事实上,你可以添加失败/成功信息在你的异常对象不应低估)。



现在,如果你处于一个速度瓶颈,解决你抛出的异常作为退出的问题不是最快的方法



没有人可以否认你的解决方案是一个荣耀的goto。将不会有一个goto-spaghetti代码,因为do / while不会让你这样做,但它仍然是一个语义goto。这可能是一些人可能发现这个代码坏的原因:他们闻到goto没有找到它的关键字清楚。



在这种情况下(在这个性能,验证)的情况下,你的解决方案似乎确定,并优于替代使用if),但质量较差(IMHO)比goto解决方案,至少,不隐藏自己背后一个错误循环。



结论



就我而言,我发现你的解决方案有创意,但我会坚持抛出的异常解决方案。 p>

因此,按照偏好顺序:


    <
  1. 使用goto

  2. 使用do / while循环

  3. 使用ifs /嵌套ifs


Sometimes you need to skip execution of part of a method under certain non-critical error conditions. You can use exceptions for that, but exceptions generally are not recommended in normal application logic, only for abnormal situations.

So I do a trick like this:

do
{
   bool isGood = true;

   .... some code

   if(!isGood)
       break;

   .... some more code

   if(!isGood)
       break;

   .... some more code

 } while(false);

 ..... some other code, which has to be executed.

I use a "fake" loop which will run once, and I can abort it by break or continue.

Some of my colleagues did not like that, and they called it "bad practice". I personally find that approach pretty slick. But what do you think?

解决方案

Bad practice, it depends.

What I see in this code is a very creative way to write "goto" with less sulphur-smelling keywords.

There are multiple alternatives to this code, which can or can not be better, depending on the situation.

Your do/while solution

Your solution is interesting if you have a lot of code, but will evaluate the "exit" of this processing at some limited points:

do
{
   bool isError = false ;

   /* some code, perhaps setting isError to true */
   if(isError) break ;
   /* some code, perhaps setting isError to true */
   if(isError) break ;
   /* some code, perhaps setting isError to true */
}
while(false) ;

// some other code

The problem is that you can't easily use your "if(isError) break ;" is a loop, because it will only exit the inner loop, not your do/while block.

And of course, if the failure is inside another function, the function must return some kind of error code, and your code must not forget to interpret the error code correctly.

I won't discuss alternatives using ifs or even nested ifs because, after some thinking, I find them inferior solutions than your own for your problem.

Calling a goto a... goto

Perhaps you should put clearly on the table the fact you're using a goto, and document the reasons you choose this solution over another.

At least, it will show something could be wrong with the code, and prompt reviewers to validate or invalidate your solution.

You must still open a block, and instead of breaking, use a goto.

{
   // etc.
   if(/*some failure condition*/) goto MY_EXIT ;
   // etc.

   while(/* etc.*/)
   {
      // etc.
      for(/* etc.*/)
      {
         // etc.
         if(/*some failure condition*/) goto MY_EXIT ;
         // etc.
      }
      // etc.
      if(/*some failure condition*/) goto MY_EXIT ;
      // etc.
   }

   // etc.
}

MY_EXIT:

// some other code

This way, as you exit the block through the goto, there is no way for you to bypass some object constructor with the goto (which is forbidden by C++).

This problem solves the process exiting from nested loops problem (and using goto to exit nested loops is an example given by B. Stroustrup as a valid use of goto), but it won't solve the fact some functions calls could fail and be ignored (because someone failed to test correctly their return code, if any).

Of course, now, you can exit your process from multiple points, from multiple loop nesting depth, so if it is a problem...

try/catch

If the code is not supposed to fail (so, failure is exceptional), or even if the code structure can fail, but is overly complex to exit, then the following approach could be clearer:

try
{
   // All your code
   // You can throw the moment something fails
   // Note that you can call functions, use reccursion,
   // have multiple loops, etc. it won't change
   // anything: If you want to exit the process,
   // then throw a MyExitProcessException exception.

   if(/* etc. */)
   {
      // etc.
      while(/* etc.*/)
      {
         // etc.
         for(/* etc.*/)
         {
            // etc.
            if(/*some failure condition*/) throw MyExitProcessException() ;
            // etc.
         }
         // etc.

         callSomeFunction() ;
         // the function will throw if the condition is met
         // so no need to test a return code

         // etc.
      }
      // etc.
   }

   // etc.
}
catch(const MyExitProcessException & e)
{
   // To avoid catching other exceptions, you should
   // define a "MyExitProcessException" exception
}

// some other code

If some condition in the code above, or inside some functions called by the code above, is not met, then throw an exception.

This is somewhat weightier than your do/while solution, but has the same advantages, and can even abort the processing from inside loops or from inside called functions.

Discussion

Your need seems to come from the fact you can have a complex process to execute (code, functions calls, loops, etc.), but you want to interrupt it over some condition (probably either failure, or because it succeeded sooner than excepted). If you can rewrite it in a different way, you should do it. But perhaps, there is no other way.

Let's assume that.

If you can code it with a try/catch, do it: To interrupt a complex piece of code, throwing an exception is the right solution (the fact you can add failure/success info inside your exception object should not be underestimated). You will have a clearer code after that.

Now, if you're in a speed bottleneck, resolving your problem with thrown exceptions as an exit is not the fastest way to do it.

No one can deny your solution is a glorified goto. There won't be a goto-spaghetti code, because the do/while won't let you do that, but it is still a semantic goto. This can be the reasons some could find this code "bad": They smell the goto without finding its keyword clearly.

In this case (and in this performance, profiled-verified) case only, your solution seems Ok, and better than the alternative using if), but of lesser quality (IMHO) than the goto solution which at least, doesn't hide itself behind a false loop.

Conclusion

As far as I am concerned, I find your solution creative, but I would stick to the thrown exception solution.

So, in order of preference:

  1. Use try/catch
  2. Use goto
  3. Use your do/while loop
  4. Use ifs/nested ifs

这篇关于你认为这种技术“坏”?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆