Php 提取到返回为空的方法

Php 提取到返回为空的方法,php,refactoring,Php,Refactoring,所以我有一个更新客户状态的方法。这个方法也在进行一些验证,我认为验证应该分开,并且updateCustomerStatus方法应该只更新(出于单一责任的目的) 如果firstCondition或secondCondition保持不变,那么我什么也不做。否则,状态将更新,这将针对客户id列表运行。另外,我将这些条件分开,因为每个条件的消息都是特定的 因此,我有如下几点: private function updateCustomerStatus($customerId) { $custom

所以我有一个更新客户状态的方法。这个方法也在进行一些验证,我认为验证应该分开,并且
updateCustomerStatus
方法应该只更新(出于单一责任的目的)

如果
firstCondition
secondCondition
保持不变,那么我什么也不做。否则,状态将更新,这将针对客户id列表运行。另外,我将这些条件分开,因为每个条件的消息都是特定的

因此,我有如下几点:

private function updateCustomerStatus($customerId) {
    $customer = findCustomerById($customerId); 
    
    [...]

    if (firstCondition($customer)) {
        echo "first condition text"; // not actually a echo, so I can't simply return the text
        return ;  
    }

    if (secondCondition($customer)) {
        echo "second condition text";  // same as above 
        return ;  
    }

    updateCustomer($customerId); 
}
如何将条件提取到方法中

我尝试过重构它,但由于我有空的返回(
return;
),我似乎无法理解它,而且我也无法删除它们,因为当特定条件成立时,应该显示特定消息,而它实际上不是回显,这是用于显示消息的另一个无效方法

提前谢谢

我该怎么做:

interface CustomerValidationInterface
{
    public function isValid(Customer $customer): bool;
}

class CustomerFooValidator implements CustomerValidationInterface
{
    public function isValid(Customer $customer)
    {
        return $customer->foo === 'FOO';
    }
}

class CustomerBarValidator implements CustomerValidationInterface
{
    public function isValid(Customer $customer)
    {
        return $customer->bar === 'BAR';
    }
}

class CustomerValidator
{
    private $validators;

    /**
     * @param CustomerValidationInterface[] $validators
     */
    public function __construct(array $validators)
    {
        $this->validators = $validators;
    }

    public function check(Customer $customer)
    {
        foreach ($this->validators as $validator) {
            if ($validator->isValid($customer) === false) {
                return 'error';
            }
        }

        return 'success'
    }
}
您可以对代码进行未来验证,如果将来需要验证更多内容,只需创建一个实现接口的新类并传递给主验证器类

更新客户状态IMHO应该按照它说的做,更新客户状态,而不是检查验证。在此之前,您应该执行验证1步。

我将如何执行:

interface CustomerValidationInterface
{
    public function isValid(Customer $customer): bool;
}

class CustomerFooValidator implements CustomerValidationInterface
{
    public function isValid(Customer $customer)
    {
        return $customer->foo === 'FOO';
    }
}

class CustomerBarValidator implements CustomerValidationInterface
{
    public function isValid(Customer $customer)
    {
        return $customer->bar === 'BAR';
    }
}

class CustomerValidator
{
    private $validators;

    /**
     * @param CustomerValidationInterface[] $validators
     */
    public function __construct(array $validators)
    {
        $this->validators = $validators;
    }

    public function check(Customer $customer)
    {
        foreach ($this->validators as $validator) {
            if ($validator->isValid($customer) === false) {
                return 'error';
            }
        }

        return 'success'
    }
}
您可以对代码进行未来验证,如果将来需要验证更多内容,只需创建一个实现接口的新类并传递给主验证器类


更新客户状态IMHO应该按照它说的做,更新客户状态,而不是检查验证。在此之前,您应该执行验证1步。

我建议重构代码,使updateCustomerStatus()方法只包含业务逻辑,即在允许更新之前检查客户的不变量

当前,您将在此方法内调用UI逻辑(即使回音发生在单独的方法中)。我想将UI的实际呈现移出updateCustomerStatus()

我甚至会更进一步,将数据库访问部分(findCustomerById())移出业务逻辑方法

通过这种方式,您还可以单独测试业务逻辑,而无需担心UI和数据库

因此,在重构代码时,我会朝着这个方向前进:

因此,让我们从自上而下的一些虚构的公共方法开始,该方法协调步骤并调用您的私有方法:

public function doUpdateCustomerStatusStuff(string $customerId): void
{
    $customer = $this->findCustomerById($customerId);
    $operationResult = $this->updateCustomerStatus($customer);

    if ($operationResult->failed()) {
        $this->showMessage($operationResult->getMessage());
    }
}
如您所见,它首先从数据库中获取客户,这样您的业务逻辑现在就可以在客户对象上运行,而不必依赖数据库

在下一步中,我们将研究重构的updateCustomerStatus()方法:

我现在传入Customer对象而不是id,这样逻辑代码就可以完成它的工作了

现在转到原始问题:

我没有调用UI方法(使用echo语句),而是返回一些Result对象,指示操作是成功还是失败,并提供可选消息。为了方便起见,我向OperationResult类添加了一些静态方法

让我们看一看这个类,它并不复杂,但它完成了它的工作:

class OperationResult
{
    /**
     * @var bool
     */
    private $success;
    /**
     * @var string
     */
    private $message;

    private function __construct(bool $success)
    {

        $this->success = $success;
    }

    private function setMessage(string $message)
    {
        $this->message = $message;
    }

    public static function fail(string $message)
    {
        $result = new OperationResult(false);
        $result->setMessage($message);
    }

    public static function succeed()
    {
        return new OperationResult(true);
    }

    public function failed()
    {
        return !$this->success;
    }

    public function succeeded()
    {
        return $this->success;
    }
}
现在回到虚构的DoUpdateCustomerStatusTuff()方法:

现在,您可以控制在执行带有所有检查和更新规则的业务逻辑后,何时以及如何输出消息(如果有)

您甚至可以更进一步,将所有业务逻辑方法(例如updateCustomerStatus()移动到一个只包含业务逻辑的单独类中)


注意:我只是假设firstCondition()和secondCondition()将检查错误条件。但是如果不是这样的话,您当然也可以执行消息的输出,这取决于doUpdateCustomerStatusTuff()方法中是否有消息。

我建议重构您的代码,使updateCustomerStatus()方法只包含业务逻辑,即,在允许更新之前检查客户的不变量

当前,您将在此方法内调用UI逻辑(即使回音发生在单独的方法中)。我想将UI的实际呈现移出updateCustomerStatus()

我甚至会更进一步,将数据库访问部分(findCustomerById())移出业务逻辑方法

通过这种方式,您还可以单独测试业务逻辑,而无需担心UI和数据库

因此,在重构代码时,我会朝着这个方向前进:

因此,让我们从自上而下的一些虚构的公共方法开始,该方法协调步骤并调用您的私有方法:

public function doUpdateCustomerStatusStuff(string $customerId): void
{
    $customer = $this->findCustomerById($customerId);
    $operationResult = $this->updateCustomerStatus($customer);

    if ($operationResult->failed()) {
        $this->showMessage($operationResult->getMessage());
    }
}
如您所见,它首先从数据库中获取客户,这样您的业务逻辑现在就可以在客户对象上运行,而不必依赖数据库

在下一步中,我们将研究重构的updateCustomerStatus()方法:

我现在传入Customer对象而不是id,这样逻辑代码就可以完成它的工作了

现在转到原始问题:

我没有调用UI方法(使用echo语句),而是返回一些Result对象,指示操作是成功还是失败,并提供可选消息。为了方便起见,我向OperationResult类添加了一些静态方法

让我们看一看这个类,它并不复杂,但它完成了它的工作:

class OperationResult
{
    /**
     * @var bool
     */
    private $success;
    /**
     * @var string
     */
    private $message;

    private function __construct(bool $success)
    {

        $this->success = $success;
    }

    private function setMessage(string $message)
    {
        $this->message = $message;
    }

    public static function fail(string $message)
    {
        $result = new OperationResult(false);
        $result->setMessage($message);
    }

    public static function succeed()
    {
        return new OperationResult(true);
    }

    public function failed()
    {
        return !$this->success;
    }

    public function succeeded()
    {
        return $this->success;
    }
}
现在回到虚构的DoUpdateCustomerStatusTuff()方法:

现在,您可以通过所有检查和更新rul来控制在业务逻辑之后何时以及如何输出消息(如果有)