本文轉載自【何以解耦】: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 協議》,轉載必須註明作者和本文連結