從驗證到不變性保護機制

xuding發表於2021-09-06

本文轉載自【何以解耦】:codedecoupled.com/invariant.html

在應用程式中,無效狀態是造成 Bug 出現的主要原因之一。特別是在像 PHP 這樣的動態語言中,應用程式中尤其容易出現無效狀態的物件。

舉個例子,我們有建立了一個 EmailService 類,它可以傳送郵件 EmailService::send()

class EmailService {
    public function send(string $email)
    {
        // 傳送郵件邏輯
    }
}

以上程式碼有一個很大的隱患,它沒有處理 $email 的無效的情況:$email 可能為 null,空或者無效的郵箱格式。

驗證

處理類似問題的常見方案是採用驗證,我們建立一個 EmailValidator 類:

class EmailValidator {
    public function isValid(string $email)
    {
        // 驗證邏輯
    }
}

在使用 $email 之間,我們對其進行驗證,比如在 EmailService 中,我們首先驗證 $email,只有在它有效的情況下才傳送郵件:

class EmailService {
    public function send(string $email)
    {
        if (!$this->emailValidator->isValid($email)){
            return;
        }

        // 傳送郵件邏輯
    }
}

以上程式碼仍然有一個隱患:在程式碼層面,我們無法保證其他協同開發者會使用 EmailValidator 來驗證 $email。不用提其他開發者,可能作者本人在過段時間後也可能疏忽大意。

不變性保護機制

與其在程式執行中對變數進行驗證,為什麼不在變數建立時保證其狀態的有效性?這種模式便是不變性保護機制。

驗證是第三方行為,而保護不變性是變數自身的機制。

使用不變性保護機制重構以上程式碼:

class Email
{
    private string $stringVal;

    public function __construct(string $stringVal)
    {
        if (!$this->isValid($stringVal)) {
            throw new \DomainException('Invalid email address');
        }
        $this->stringVal = $stringVal;
    }

    public function toString()
    {
        return $this->stringVal;
    }

}

class EmailService {
    public function send(Email $email)
    {
        // 傳送郵件邏輯
    }
}

使用不變性保護機制不僅解決了上述已有問題,整體程式碼的重複使用性也得到了提高,同時 Email 類還提供了一個統一位置來管理郵箱地址,更不用提這種模式如何改善了單元測試的質量。

本文轉載自【何以解耦】: codedecoupled.com/invariant.html ,如果你也對 TDD,DDD 以及簡潔程式碼感興趣,歡迎關注公眾號【何以解耦】,一起探索軟體開發之道。

本作品採用《CC 協議》,轉載必須註明作者和本文連結
Know how, know why meanwhile.

相關文章