我有一個名為MachineId. 創建此類的實體時,我想確保建構式引數已驗證。
class MachineId
{
private $uid;
public function __construct(string $uid)
{
$this->uid = $uid;
}
public function validate() : bool
{
// check uid against specific format (by regex) and return true if valid and false if invalid
}
}
我的問題是:我應該什么時候進行驗證?
- 我應該在創建 MachineId 實體時進行驗證嗎?在這種情況下,將
validate方法設為私有是有意義的。這會使使用 Unittest 對其進行測驗變得困難。
// Validation WHILE instantiation
class MachineId
{
private $uid;
public function __construct(string $uid)
{
$this->uid = $uid;
if($this->validate() === false) {
// throw exception
}
}
private function validate() : bool
{
...
}
}
- 我應該在創建 MachineId 實體之前進行驗證嗎?這將使
validate通過 Unittest測驗該方法成為可能,需要在創建物件之前呼叫驗證。使該方法validate成為靜態方法(我試圖阻止)是有意義的。
// Validation BEFORE instantiation
class MachineId
{
private $uid;
public function __construct(string $uid)
{
$this->uid = $uid;
}
public static function validate(string $uid) : bool
{
...
}
}
if(MachineId::validate($uid) === false) {
// throw exception
};
$machineId = new MachineId($uid);
- Should I do the validation after I create an instance of MachineId? This would make it possible to test the validate method by Unittest, requires that validation is called after creating the object.
// Validation AFTER instantiation
class MachineId
{
private $uid;
public function __construct(string $uid)
{
$this->uid = $uid;
}
public function validate() : bool
{
...
}
}
$machineId = new MachineId($uid);
if($machineId->validate() === false) {
// throw exception
}
- Should I create an empty MachineId and then set the uid? In this case I would move the validation call into a
setUidmethod. And again it would make sense to make the validate method private and so it is difficult to test.
// Validation in set method
class MachineId
{
private $uid;
public function __construct()
{
$this->uid = null;
}
public function setUid(string $uid)
{
$this->uid = $uid;
if($this->validate() === false) {
// throw exception
}
}
private function validate() : bool
{
...
}
}
$machineId = new MachineId();
$machineId->setUid($uid);
- Should I create a validation class, that I also inject in the constructor?
// Validation with injecting a validation class
interface ValidatorInterface
{
public function validate(mixed $value) : bool;
}
class MachineIdValidator implements ValidatorInterface
{
public function validate($uid) : bool
{
...
}
}
class MachineId
{
private $uid;
public function __construct(string $uid, ValidatorInterface $validator)
{
if($validator->validate($uid) === false) {
// throw exception
}
$this->uid = $uid;
}
}
$machineId = new MachineId($uid, new MachineIdValidator());
I run into this issue already many times and want to ask, if someone has a suggestion for a case like this. How to validate the string, without having a static method, but it is still testable and should not be forgotten?
我最喜歡的解決方案是創建一個 MachineId 的新實體并提供 uid 字串作為建構式引數。uid 應該經過驗證,并且驗證方法也應該是可測驗的。
uj5u.com熱心網友回復:
我最喜歡的解決方案是創建一個 MachineId 的新實體并提供 uid 字串作為建構式引數。uid 應該經過驗證,并且驗證方法也應該是可測驗的。
我認為您正在尋找類似的東西:
// Validation WHILE instantiation
class MachineId
{
private $uid;
public function __construct(string $uid)
{
$this->uid = $uid;
if(MachineId::validate($uid) === false) {
// throw exception
};
}
public static function validate(string $uid) : bool
{
...
}
}
根據需要撰寫盡可能多的測驗,以確保 MachineId::validate 已正確實作。
推薦閱讀:
- Martin Fowler:公共介面與已發布介面
- Alexis King:決議,不驗證
uj5u.com熱心網友回復:
單元測驗是關于測驗行為而不是方法或類。
我建議將驗證保留在MachineId課堂上。這樣做將使您的客戶更容易,因為他們不必再次擔心驗證。我的首選方法是private創建建構式并創建一個靜態工廠方法。然后您可以在靜態工廠中實作驗證并在驗證成功時創建物件。測驗驗證行為就像測驗靜態工廠本身一樣簡單。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/334856.html
