Php &引用;“提前返回”;最佳实践和干燥

Php &引用;“提前返回”;最佳实践和干燥,php,dry,Php,Dry,我想知道,在某些情况下,是否有更好的方法“刹车”出方法。让我用代码更好地解释一下: function execute($context) { // some init actions $event = new BeforeOperationOne(); $this->dispatch($event); if ($event->accessGranted()) { $context->setUser($this->user)

我想知道,在某些情况下,是否有更好的方法“刹车”出方法。让我用代码更好地解释一下:

function execute($context)
{
    // some init actions

    $event = new BeforeOperationOne();
    $this->dispatch($event);
    if ($event->accessGranted()) {
        $context->setUser($this->user);
        // other repeated code

        return;
    }

    $result = $this->operationOne();

    // some other code

    $event = new BeforeOperationTwo();
    $this->dispatch($event);
    if ($event->accessGranted()) {
        $context->setUser($this->user);
        // other repeated code

        return;
    }

    // this is not important what is access checker, 
    // this is just to show that all following code uses data
    // computed in previous steps
    $accessChecker = new AccessChecker($result);
    $this->operationTwo(accessChecker);

    // some other code

    $event = new BeforeOperationThree();
    $this->dispatch($event);
    if ($event->accessGranted()) {
        $context->setUser($this->user);
        // other repeated code

        return;
    }

    $this->operationThree();

    // some other code
}
我们在这里重复了这个条件,当用户可以从事件访问时,在上下文中设置用户。我可以考虑的选择是:

  • 丑陋的人做的时候(假)或去(我最好还是保持现在的样子)
  • 将其提取到方法,并将条件更改为
    if(!$this->handleEvent($event,$context)){return;}
    -这没有多大帮助,也不能认为更好的名称句柄不表示它返回了什么
  • 为操作构建闭包数组,并通过检查循环它。我们可以假设所有事件类都是从带有accessgrated方法的公共类派生的。这可能很难看,因为一些操作需要来自前面“步骤”的数据,我必须将它们放在外面并传递它们
  • 抛出并捕获用户有权访问的异常-另一个糟糕的解决方案

  • 你有没有办法把它写得更好?

    @Greg我在想这样的事情:

    abstract class Handler
    {
        protected $nextHandler = null;
    
        abstract public function Request($request);
    
        public function setNextHandler(Handler $handler)
        {
            $this->nextHandler = $handler;
        }
    
        protected function someOperations($event)
        {
            //i copied this section, so you must shape that
            $this->dispatch($event);
            if ($event->accessGranted()) {
                $context->setUser($this->user);
                // other repeated code
    
                return true;
            }
    
            return false;
        }
    }
    
    class BeforeOperationOneHandler extends Handler
    {
        public function Request($request)
        {
              if ($this->someOperations(new BeforeOperationOne())) {
                  return;
              }
    
              $result = $this->operationOne(); // shape this too
    
              return $this->nextHandler->Request($result);
        }
    }
    
    class BeforeOperationTwoHandler extends Handler
    {
        public function Request($request)
        {
              if ($this->someOperations(new BeforeOperationTwo())) {
                  return;
              }
    
              $accessChecker = new AccessChecker($result); // shape this too
              $result = $this->operationTwo(accessChecker);
    
              return $this->nextHandler->Request($result);
        }
    }
    
    class BeforeOperationThreeHandler extends Handler
    {
        public function Request($request)
        {
              if ($this->someOperations(new BeforeOperationThree())) {
                  return;
              }
    
              $result = $this->operationThree(); // shape this too
    
              return $this->nextHandler->Request($result);
        }
    }
    
    class DefaultHandler extends Handler
    {
        public function Request($request)
        {
              // this is the last step
        }
    }
    
    
    
    
    function execute($context)
    {
        // some init actions
        $beforeOperationOneHandler = new BeforeOperationOneHandler();
        $beforeOperationTwoHandler = new BeforeOperationTwoHandler();
        $beforeOperationThreeHandler = new BeforeOperationThreeHandler();
        $defaultHandler = new DefaultHandler();
    
        // set the sequence of the elements
        // BeforeOperationOneHandler > BeforeOperationTwoHandler > BeforeOperationThreeHandler> DefaultHandler
        $beforeOperationOneHandler->setNextHandler($beforeOperationTwoHandler);
        $beforeOperationTwoHandler->setNextHandler($beforeOperationThreeHandler);
        $beforeOperationThreeHandler->setNextHandler($defaultHandler);
    
        return $beforeOperationOneHandler->Request($some_init);
    }
    
    这只是快速编写的“责任链”模式,所以我无意中复制了您的一些代码片段

    我希望这将引导您找到更好的解决方案

    您的问题将得到许多基于意见的答案。但是,请看一看,并清理代码手册-第3章-功能。最后,正确的术语是“可能”责任链模式将是有用的?我试图实际做的是提供使用事件系统钩住方法的可能性,如果有可能提前完成方法,以避免用户访问不必要的繁重计算。感谢澄清。这让我重新思考解决方案。我走这边。