2009-07-13 63 views
4

我刚刚写了一段代码,让我觉得它比嵌套要好得多。我想就如何改善这种风格提出建议,特别是要使它更符合“Flat比嵌套更好”。清理嵌套的尝试/例外

for app in apps: 
    if app.split('.', 1)[0] == 'zc': #only look for cron in zc apps 
     try: 
      a = app + '.cron' 
      __import__(a) 
      m = sys.modules[a] 

      try: 
       min = m.cron_minute() 
       for job in min: 
        k.add_interval_task(job[0], 'minute task', r(M_LB, M_UB), 
             60*job[1], 
             kronos.method.threaded,(),()) 
      except AttributeError: #no minute tasks 
       pass 

      try: 
       hour = m.cron_hour() 
       for job in hour: 
        k.add_daytime_task(job[0], 'day task', range(1, 8), None, 
             (job[1], r(H_LB, H_UB)), 
             kronos.method.threaded,(),()) 
      except AttributeError: #no hour tasks 
       pass 

     except ImportError: #no cron jobs for this module 
      pass 

编辑: 结合从下面的建议,这是我的改写形式。

for app in apps: 
    if app.split('.', 1)[0] != 'zc': #only look for cron in zc apps 
     continue 

    try: 
     a = app + '.cron' 
     __import__(a) 
    except ImportError: #no cron jobs for this module, continue to next one 
     continue 

    m = sys.modules[a] 
    if hasattr(m, 'cron_minute'): 
     min = m.cron_minute() 
     for job in min: 
      k.add_interval_task(job[0], 'minute task', r(M_LB, M_UB), 
           60*job[1], 
           kronos.method.threaded,(),()) 

    if hasattr(m, 'cron_hour'): 
     hour = m.cron_hour() 
     for job in hour: 
      k.add_daytime_task(job[0], 'day task', range(1, 8), None, 
           (job[1], r(H_LB, H_UB)), 
           kronos.method.threaded,(),()) 

回答

9

主要的问题是你的try子句太宽泛,尤其是最外面的一个:有了这种习惯,你迟早会遇到一个神秘的bug,因为你的try/except之一意外地隐藏了一个意外的异常从你打电话的其他功能中“冒泡”。

所以我建议,而不是:

for app in apps: 
    if app.split('.', 1)[0] != 'zc': #only look for cron in zc apps 
     continue 

    try: 
     a = app + '.cron' 
     __import__(a) 
    except ImportError: #no cron jobs for this module 
     continue 

    # etc etc 

顺便说一句,我也将“扁平比嵌套好”以另一种方式(不依赖于任何的try /除外),这是“如果在循环的这一段我没有更多要做的事情,继续[即继续到下一个循环],而不是“如果我有事情要做”,然后是大量的嵌套代码。总是倾向于将这种风格(if/continue或if/return)嵌套在提供诸如continue(基本上所有现代的语言,因为C具有它;-)之类的语言中嵌套if。

B这是一个简单的“扁平VS嵌套”风格偏好,问题的实质是:让你的尝试子句小!最糟糕的情况是,当你只是不能简单地继续或返回except子句时,你可以使用try/except/else:把try子句放在绝对必须存在的地方 - 可能和期望的一小段代码然后在else子句中放入以下代码的其余部分(不应该或不应该引发的部分)。这不会改变嵌套,但在降低意外隐藏不期望的异常的风险方面做出巨大的改变!

+0

谢谢,这正是我所需要的。我忘记了以这种方式继续使用。 您的建议是保持尽可能小的尝试是有道理的。使用继续允许我这样做。重写的形式更加明确。 – 2009-07-13 03:06:24

0

您可以创建一个执行主逻辑函数,并调用该函数,与尝试...除了语句包裹它的另一个功能。然后,在主应用程序中,您可以调用那些已经处理异常的函数。 (根据“Clean Code”书的建议)。

+0

此代码只被调用一次。我可以写几个函数来完成它,但这实际上只是生成意大利面条代码,而不是实际上改进布局。 – 2009-07-13 02:42:42

0

那么,这里的诀窍是弄清楚它们是否坏了。那就是处理部分异常处理。我的意思是,至少打印一条警告,说明评论的假设。在实际处理之前担心过多的嵌套看起来像是在超越自己。在时尚之前担心自己的权利。

+0

你误解了代码的作用。如果发现异常,应该什么也不做 - 如果被检查的东西不存在,那么这不是一个错误(事实上,在大多数情况下,它们不会)。我不希望打印任何可选功能的实例没有发现警告。 – 2009-07-13 02:41:57

1

我想知道,如果每个时间单位的工作实际上被打破了,他们会提出一个AttibuteError还是其他一些异常?特别是,如果有关于某项工作真的遭到破坏的事情,你可能不应该抓住他们。

另一个可以帮助的选择是只用try-catch包装有问题的代码,尽可能地将异常处理程序尽可能接近异常。这里有一个刺:

for app in apps: 
    if app.split('.', 1)[0] == 'zc': #only look for cron in zc apps 
     try: 
      a = app + '.cron' 
      __import__(a) 
      m = sys.modules[a] 
     except ImportError: #no cron jobs for this module 
          #exception is silently ignored 
          #since no jobs is not an error 
      continue 
     if hasattr(m, "cron_minute"): 
      min = m.cron_minute() 
      for job in min: 
       k.add_interval_task(job[0], 'minute task', r(M_LB, M_UB), 
            60*job[1], 
            kronos.method.threaded,(),()) 

     if hasattr(m, "cron_hour"): 
      hour = m.cron_hour() 
      for job in hour: 
       k.add_daytime_task(job[0], 'day task', range(1, 8), None, 
            (job[1], r(H_LB, H_UB)), 
            kronos.method.threaded,(),()) 

通知只存在一个异常处理程序在这里,我们处理由正确忽略。 因为我们可以预测没有一个属性或另一个属性的可能性,我们 显式检查它,这有助于使代码更清晰。否则,它不是 真的很明显,为什么你要捕捉AttributeError,或者什么是提高它。

+0

啊谢谢你!这里使用hasattr()比try/except更简洁。 – 2009-07-13 03:10:43

相关问题