& quot; Ранний возврат & quot; лучшая практика и СУХОЙ

Мне интересно, есть ли лучший способ «торможения» метода в некоторых условиях. Позвольте мне лучше объяснить это с помощью кода:

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
}

Мы повторили здесь условие, устанавливая пользователя в контексте, когда пользователь имеет доступ из события. Какие варианты я могу думать, это:

  1. Гадкий do-while (false) или goto (лучше оставить так, как сейчас)
  2. Извлеките это в метод и измените условие на if (!$this->handleEvent($event, $context)) { return; }— Это не помогает многим и не может думать, что лучший дескриптор имени не говорит, что он возвращает что-то
  3. Создайте массив замыканий для операций и выполните его проверку. Мы можем предположить, что все классы событий являются производными от общего класса с методами accessGranted. Это может быть некрасиво, так как некоторым операциям нужны данные из предыдущих «шагов», я должен был бы держать их снаружи и передавать их.
  4. Бросать и ловить исключения, которые пользователь имеет доступ — еще одно плохое решение.

У вас есть идеи, как написать это лучше?

0

Решение

@ Грег, я думал о чем-то таком:

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

Это только быстро записанная форма шаблона «цепочки ответственности», поэтому я бездумно скопировал некоторые из ваших фрагментов кода
Я надеюсь, что это приведет вас к лучшему решению

1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector