Рефакторинг петлю со многими логические условия


Я обычно тратил больше времени на рефакторинг, чем в развивающихся сама. Но этот маленький кусочек кода очень тяжело отрефакторить. Я хочу сохранить ее как можно короче, но это совсем undarstandable:

foreach($all_headers as $uid => $h) // Intera gli headers
{

    // Is the header valid?
    $isInbox   = $h->to == $mailbox->address;
    $hasPin    = ($pin = substr($h->subject, 0, 5)) !== false && is_numeric($pin);
    $hasTitle  = strlen($title = trim(substr($h->subject, 5))) > 0;
    $isAllowed = $hasPin && call_user_func($pincall, $mailbox->address, $h->from, $pin);

    $log->info("messaggio $uid: in:$isInbox pin:$hasPin alw:$isAllowed");

    // Skip this header if not vlaid
    if (!$isInbox || !$hasPin || !$isAllowed) continue;

    // Add some properties to current header
    $h->title = $hasTitle ? $title : null;
    $h->pin   = $pin;
    $valid_headers[$uid] = $h;

}

Поскольку я фильтрую $all_headers массива, один крутой идеей будет использовать array_filter с какой-либо механизм, чтобы добавить/удалить условий "на лету".

Спасибо народ, как всегда.



217
1
задан 30 ноября 2011 в 08:11 Источник Поделиться
Комментарии
1 ответ

Это не сделает его короче, но вы могли бы рассмотреть изменение состояния проверяю только фактической проверки при необходимости вместо того, чтобы делать их все сразу, что делает вас потерять преимущество короткого замыкания || оператора.

Е. Г.

if (!isInbox()) continue;
if (!hasPing()) continue;
...


Другая возможность, то есть даже меньше, короткий, заключается в создании фильтрующего итератора, например:

class ValidHeaderIterator extends FilterIterator 
{
private $mailbox;
private $pincall;

public function __construct($headers, $mailbox, $pincall)
{
$this->mailbox = $mailbox;
$this->pincall = $pincall;
parent::__construct(new ArrayIterator($headers));
}

public function accept()
{
$header = $this->getInnerIterator()->current();
return isInbox($header) && hasPin($header) && isAllowed($header);
}

public function isInbox($header)
{
return $header->to == $this->mailbox->address;
}

public function hasPin($header)
{
$pin = $this->getPin($header);
return $pin !== false && is_numeric($pin);
}

public function getPin($header)
{
return substr($header->subject, 0, 5));
}

public function isAllowed($header)
{
return call_user_func($this->pincall,
$this->mailbox->address,
$header->from,
$this->getPin());
}
}

Вызывающий код будет выглядеть:

foreach(new ValidHeaderIterator($headers, $mailbox, $pincall) as $header) {
// do stuff
}

4
ответ дан 30 ноября 2011 в 09:11 Источник Поделиться