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でどのように進めるかわかりません。

更新:try / catchはforeachループ内にネストされているため、例外がスローされると、例外が処理され、ループを終了するのではなく、ループ内の次の反復に実行が続行されます。

4

2 に答える 2

2

例外の良いところは、他の例外と同じように渡すことができるオブジェクトであるということです。したがって、多くの変更を加えることなく、重複するコード(基本的なボイラープレートを除く)を削除できます。

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

あなたは簡単にthingsdoer1そしてthingsdoer2そして多分抽象的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 に答える