php – 如何减少IF语句的数量?

我有很多IF句子,每个句子都开始一个功能.
是否有一种明显的方法可以更简单地编写此代码?
每个IF都会启动不同的功能,但它仍然看起来像是一种矫枉过正.

    if ($this->machine == '' AND $this->date_from == '' AND $this->date_to == '' AND $this->date_like == '' AND $this->article_or_tool == '') {
        $this->AllTime();
    }
    if ($this->machine <> 0 AND $this->date_from == '' AND $this->date_to == '' AND $this->date_like == '' AND $this->article_or_tool == '') {
        $this->ByMachine();
    }
    if ($this->machine == '' AND $this->date_from <> 0 AND $this->date_to <> 0 AND $this->date_like == '' AND $this->article_or_tool == '') {
        $this->ByDate();
    }
    if ($this->machine <> 0 AND $this->date_from <> 0 AND $this->date_to <> 0 AND $this->date_like == '' AND $this->article_or_tool == '') {
        $this->ByMachineByDate();
    }
    if ($this->machine == '' AND $this->date_from == '' AND $this->date_to == '' AND $this->date_like <> 0 AND $this->article_or_tool == '') {
        $this->ByDateLike();
    }
    if ($this->machine <> 0 AND $this->date_from == '' AND $this->date_to == '' AND $this->date_like <> 0 AND $this->article_or_tool == '') {
        $this->ByMachineByDateLike();
    }
    if ($this->machine == '' AND $this->date_from == '' AND $this->date_to == '' AND $this->date_like == '' AND $this->article_or_tool <> 0) {
        $this->ByArticle();
    }
    if ($this->machine <> 0 AND $this->date_from == '' AND $this->date_to == '' AND $this->date_like == '' AND $this->article_or_tool <> 0) {
        $this->ByMachineByArticle();
    }
    if ($this->machine == '' AND $this->date_from <> 0 AND $this->date_to <> 0 AND $this->date_like == '' AND $this->article_or_tool <> 0) {
        $this->ByDateByArticle();
    }
    if ($this->machine == '' AND $this->date_from == '' AND $this->date_to == '' AND $this->date_like <> 0 AND $this->article_or_tool <> 0) {
        $this->ByDateLikeByArticle();
    }
    if ($this->machine <> 0 AND $this->date_from <> 0 AND $this->date_to <> 0 AND $this->date_like == '' AND $this->article_or_tool <> 0) {
        $this->ByMachineByDateByArticle();
    }
    if ($this->machine <> 0 AND $this->date_from == '' AND $this->date_to == '' AND $this->date_like <> 0 AND $this->article_or_tool <> 0) {
        $this->ByMachineByDateLikeByArticle();
    }


以下是重构后的代码:

function MethodPicker() {
    $machine            = $this->machine            <> 0;
    $date_from          = $this->date_from          <> 0;
    $date_to            = $this->date_to            <> 0;
    $date_like          = $this->date_like          <> 0;
    $article_or_tool    = $this->article_or_tool    <> 0;

    $decision  = array($machine, $date_from, $date_to, $date_like, $article_or_tool);
    $decisions = array(
                    'AllTime' =>                        array(false,    false,  false,  false,  false   ),
                    'ByMachine' =>                      array(true,     false,  false,  false,  false   ),
                    'ByDate' =>                         array(false,    true,   true,   false,  false   ),
                    'ByMachineByDate' =>                array(true,     true,   true,   false,  false   ),
                    'ByDateLike' =>                     array(false,    false,  false,  true,   false   ),
                    'ByMachineByDateLike' =>            array(true,     false,  false,  true,   false   ),
                    'ByArticle' =>                      array(false,    false,  false,  false,  true    ),
                    'ByMachineByArticle' =>             array(true,     false,  false,  false,  true    ),
                    'ByDateByArticle' =>                array(false,    true,   true,   false,  true    ),
                    'ByDateLikeByArticle' =>            array(false,    false,  false,  true,   true    ),
                    'ByMachineByDateByArticle' =>       array(true,     true,   true,   false,  true    ),
                    'ByMachineByDateLikeByArticle' =>   array(true,     false,  false,  true,   true    ),
    );
    $method = array_keys($decisions, $decision, true);
    $method && list($method) = $method;
    $method && $this->$method();
}

解决方法:

首先,我会做一些标准的重构.不知道为什么我这样做,但这是什么:

>用属性替换属性,例如

$machine = $this->machine;

>同样适用于条件但是更接近条件时,很明显只有每个变量有两个状态,所以这实际上只是每个变量的一个条件(见Type Juggling),这会导致真或假.相反,分配条件:

$machine = $this->machine == '' || $this->machine == 0;

(对于正确的条件,积分转到martinstoeckli)

这将是一个开始. if条款到现在为止已经改变了,并且会更加紧凑.但是,为何停在这里?目前有一个决定:

$decision  = [$machine, $date_from, $date_to, $date_like, $article_or_tool];

并且有一系列决定可供选择:

$decisions = [
    'AllTime' => [true, true, true, true, true],
    ...
];

所以需要做的就是找到决定并执行方法:

$method = array_keys($decisions, $decision, true);
$method && $this->$method();

if块已变为矩阵.该函数已映射到它的一个状态.

你松开了字段上的名字,但是,你可以通过评论解决这个问题:

    $decisions = [
        //            machine  from  to    like  article
        'AllTime' => [true   , true, true, true, true],
        ...
    ];

乍看上去:

$machine = $this->machine == '' || $this->machine == 0;
... # 4 more times

$decision  = [$machine, $date_from, $date_to, $date_like, $article_or_tool];

$decisions = [
    'AllTime' => [true, true, true, true, true],
    ... # 11 more times
];

$method = array_keys($decisions, $decision, true);
$method && $this->$method();

如果它所在的类表示一个值对象,我建议您将决策移动到它自己的类型中,然后将该决策类型用作单个方法对象.将使您以后能够更轻松地做出不同的决策.

上一篇:java – 我的Wicket验证规则能否以DRY方式记录给用户?


下一篇:第一阶段:Python开发基础 day42  数据库基础扩展内容