1

我有一个带有methodA的类,它的现有结构如下

function methodA() {
  $providers = $this->getFirstSetOfProviders();
  foreach ($providers as $provider) {
    try {
      $this->method1($provider);
    } catch ( Exception $e ) {
      // exception handling
    }
  }

  $providers = $this->getSecondSetOfProviders();
  foreach ($providers as $provider) {
    try {
      $this->method2($provider);
    } catch ( Exception $e ) {
      // exception handling
    }
  }
}

catch 子句的内容是相同的。有没有办法组织代码以避免重复嵌套在 foreach 循环中的 try/catch 结构?从概念上讲,我正在尝试做

function methodA() {
  foreach ($providers as $provider) {
    $method1 = function($provider) {
      $this->method1($provider);
    }
    $this->withTryCatch($method1);
  }
  ...
}

function withTryCatch($method) {
  try {
    $method;  // invoke this method somehow
  } catch (Exception $e) {
    // exception handling
  }
}

这看起来类似于代码三明治,但我不确定如何在 php.ini 中进行。

更新: try/catch 嵌套在 foreach 循环内,因此当抛出异常时,它会被处理并继续执行循环中的下一次迭代,而不是终止循环。

4

2 回答 2

2

Exceptions 的好处是它们是可以像任何其他对象一样传递的对象。因此,您可以删除重复的代码(基本样板除外)而无需进行太多更改:

foreach ($providers as $provider) {
    try {
      $this->method1($provider);
    } catch ( Exception $e ) {
      $this->handleException($e);
    }
}

注意:如果您还需要异常处理中的一些上下文(即$provider),只需提供handleException()更多参数。

第 2 部分:重构整个方法

您想知道如何进一步删除重复。我不知道这在您的实际代码中是否有意义,它也可能是过度工程。你必须自己决定。以下是模板方法模式的实现。原谅粗俗的命名,但我试图效仿你的例子,我不知道你在做什么。

abstract class ClassThatDoesThingsWithProviders
{
    public function methodA($providers)
    {
        foreach($provicers as $provider) {
            try {
                $this->methodThatActuallyDoesSomethingWithProvider($provider);
            } catch(Exception $e) {
                $this->handleException($e);
            }
        }
    }
    protected function handleException(Exception $e)
    {
        // handle exception
    }
    abstract protected function methodThatActuallyDoesSomethingWithProvider($provider);
}
class ClassThatDoesThing1WithProviders extends ClassThatDoesThingsWithProviders
{
    protected function methodThatActuallyDoesSomethingWithProvider($provider)
    {
        // this is your method1()
    }
}
class ClassThatDoesThing2WithProviders extends ClassThatDoesThingsWithProviders
{
    protected function methodThatActuallyDoesSomethingWithProvider($provider)
    {
        // this is your method2()
    }
}

class YourOriginalClass
{
    protected $thingsdoer1;
    protected $thingsdoer2;

    public function __construct()
    {
        $this->thingsdoer1 = new ClassThatDoesThing1WithProviders;
        $this->thingsdoer2 = new ClassThatDoesThing2WithProviders;
    }
    public function methodA()
    {
        $this->thingsdoer1->methodA($this->getFirstSetOfProviders());
        $this->thingsdoer2->methodA($this->getSecondSetOfProviders());
    }
}

您可以轻松地从并且可能是抽象的thingsdoer1thingsdoer2旁边getFirstSetOfProviders创建getSecondSetOfProviders一个数组。另外我不知道实际的 method1 和 method2 实现依赖于什么,也许你不能像那样提取它们而不破坏凝聚力。

但是由于我不知道你的真实代码和你在做什么,我不能推荐一个具体的策略,把我上面的例子作为一个起点。

于 2013-01-22T14:35:30.067 回答
0
function methodA() {
  try {
      $providers = $this->getFirstSetOfProviders();
      foreach ($providers as $provider) {
          $this->method1($provider);
      }

      $providers = $this->getSecondSetOfProviders();
      foreach ($providers as $provider) {
          $this->method2($provider);
      }
  } catch ( Exception $e ) {
    // exception handling
  }

}
于 2013-01-22T06:35:25.053 回答