2017-07-17 8 views
1

私はValueObjectでコーディングを学ぼうとしています。私はVOの抽象実装を持つことについて疑問を持ち、子クラスはそれを拡張します。子供は与えられた値(電子メール、ユーザー名など)に対してのみ検証メソッドを実装します。 私の最初のVOは、コンストラクタで検証されているビジネスルールを使って下の行に表示されます。ValueObjectの抽象化

final class Email { 
    private $email; 

    public function __construct(string $email) 
    { 
     $this->validateEmail($email); 

     $this->email = $email; 
    } 

    public function value() : string 
    { 
     return $this->email; 
    } 

    private function validateEmail(string $email) : void 
    { 
     if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { 
      throw new IncorrectEmailException(); 
     } 
    } 
} 

Iが第二VOを書いていた私が異なるのみ検証規則(方式validate)であるいくつかのパターンを発見しました。だから、パターンを実装する抽象クラスについて考え、子が検証ルールを洗練させるようにしました。

abstract class ValueObject { 

    protected $value; 

    public function __construct($value) 
    { 
     $this->validate($value); 

     $this->value = $value; 
    } 

    public function value() 
    { 
     return $value; 
    } 

    abstract protected function validate($value) : void; 
} 

final class Email extends ValueObject { 
    protected function validate($value) : void 
    { 
     if (!is_string($value)) { 
      throw new \InvalidArgumentException(); 
     } 

     if (!filter_var($value, FILTER_VALIDATE_EMAIL)) { 
      throw new IncorrectEmailException(); 
     } 
    } 
} 

いくつかのメソッドと入力または出力(たとえば、メソッド 'value')を入力しなくなりました。 PHPにはジェネリック型がなく、文字列のような値の型を検証する必要があります。私はそれがビジネスルール(私は思うが、私は間違っている可能性があります)ではないので、それを行うには適切な場所であるとは思っていません誰かが私にどのオプションが良かったと教えていいですか?

+0

はたぶん、あなたはhttps://github.com/nicolopignatelli/valueobjectsのクローンである、https://github.com/teneleven/valueobjectsを見てみたいです。 git(作者によって削除された) – localheinz

答えて

4

私は理由のカップルのためにそれをしないだろう。これはコンストラクタにパラメータを1つだけ持っている値オブジェクトでのみ動作します

  1. コンストラクタ内のパラメータは従わないだろう
  2. ユビキタス言語から命名ゲッターが
  3. ユビキタス言語から命名に従わないと、彼らはベースクラス
  4. に不明であるとして、あなたは、コンストラクタのパラメータのタイプヒンティングを持っていません。
  5. ドメインオブジェクトの継承は避けてください。ドメインオブジェクトを他のクラスに結合し、プログラマの認知努力を高めるために、絶対に必要でない限り(ほとんどありません)、ベースクラスの動作を知る必要があります子供階級を理解する。私はfavor composition over inheritanceしようとします。

あなたのコンストラクタの中にvalidate()を呼び出さないようにしてください。

5

は、関連していない概念の継承を使用しません。バリューオブジェクトは実世界の概念ではありません。プログラムで使用される手法です。

次いでEmailPhoneNumberにより拡張される抽象基底クラスValueObjectPostalAddress a.s.o.を備えない点がありません

これらの概念ごとに1つのクラスを作成し、単純にしておきます。たとえば、別の検証方法は必要ありません。検証をコンストラクタに入れて、__toString()(該当する場合)および/またはカプセル化された値をフォーマットするその他のメソッドを実装します。例えば

final class EmailAddress 
{ 
    private $email; 

    public function __construct(string $email) 
    { 
     if (! filter_var($email, FILTER_VALIDATE_EMAIL)) { 
      throw new InvalidArgumentException(sprintf("Invalid email '%s'", $email)); 
     } 

     $this->email = $email; 
    } 

    public function __toString() : string 
    { 
     return $this->email; 
    } 

    // For some statistics 
    public function getDomain() : string 
    { 
     // write code here to return only the part after '@' 
    } 
}