2017-12-08 2 views
2

이전에는 생성자 내에서 내 개체의 유효성 검사를 수행했으며 유효성 검사가 실패하면 예외가 발생했습니다. 예를 들어 :알림 패턴을 사용하여 도메인 유효성 검사

내 객체가 일관성을 시행하고이를 보장 할 책임이있다 나는이 방법을 좋아하는 동안
class Name 
{ 
    const MIN_LENGTH = 1; 

    const MAX_LENGTH = 120; 

    private $value; 

    public function __construct(string $name) 
    { 
     if (!$this->isValidNameLength($name)) { 
      throw new InvalidArgumentException(
       sprintf('The name must be between %d and %d characters long', self::MIN_LENGTH, self::MAX_LENGTH) 
      ); 
     } 
     $this->value = $name; 
    } 

    public function changeName(string $name) 
    { 
     return new self($name); 
    } 

    private function isValidNameLength(string $name) 
    { 
     return strlen($name) >= self::MIN_LENGTH && strlen($name) <= self::MAX_LENGTH; 
    } 
} 

은 항상 유효합니다, 나는 예외의 사용에 대해 지나치게 열정적 적이 없습니다. 위와 같이 예외 사용을 반대하는 사람들이 있지만 여러 객체에 대해 유효성 검사를 수행 할 때 반환 할 수있는 유효성 검사 메시지의 수는 제한됩니다. 예를 들어 :

class Room 
{ 
    private $name; 

    private $description; 

    public function __construct(Name $name, Description $description) 
    { 
     $this->name = $name; 
     $this->description = $description; 
    } 
} 

class Name 
{ 
    public function __construct(string $name) 
    { 
     // do some validation 
    } 
} 

class Description 
{ 
    public function __construct(string $description) 
    { 
     // do some validation 
    } 
} 

모두 NameDescription이 유효성 검사에 실패한 경우, 나는 두 개체에 대한 개체가 첫 번째 실패 중에서 단지 하나의 예외 오류 메시지를 반환 할 수 있어야합니다.

notification pattern에서 약간의 독서를 했더니 내 시나리오에 잘 어울리는 것 같았습니다. 내가 붙어있는 곳은 유효성 검증을 수행하는 방법이며, 유효성 검사가 실패하면 유효하지 않은 상태로 들어가는 것을 방지합니다.

class Name 
{ 
    const MIN_LENGTH = 1; 

    const MAX_LENGTH = 120; 

    private $notification; 

    private $value; 

    public function __construct(string $name, Notification $notification) 
    { 
     $this->notification = $notification; 
     $this->setName($name); 
    } 

    private function setName(string $name) 
    { 
     if ($this->isValidNameLength($name)) { 
      $this->value = $name; 
     } 
    } 

    private function isValidNameLength(string $name) 
    { 
     if (strlen($name) < self::MIN_LENGTH || strlen($name) > self::MAX_LENGTH) { 
      $this->notification->addError('NAME_LENGTH_INVALID'); 
      return false; 
     } 
     return true; 
    } 

    public function hasError() 
    { 
     return $this->notification->hasError(); 
    } 

    public function getError() 
    { 
     return $this->notification->getError(); 
    } 
} 

내가 위의 대한 몇 가지 문제가 있습니다 유효성 검사가 실패 할 경우

  1. 를 다음 개체가 아직 구성되어 있지만 $value는 유효한 상태하지 않은 null이다.
  2. Name을 생성 한 후 hasError으로 전화하여 유효성 검사 오류가 발생했는지 확인해야합니다.
  3. 지금 내 도메인 개체를 hasError/getError 기능으로 조정하고 있는데 잘 모르겠습니다.

누락 된 퍼즐이 있습니까? 알림 패턴을 어떻게 활용할 수 있습니까?하지만 객체가 유효하지 않은 상태로 들어 가지 않도록 할 수 있습니까?

답변

1

같은 것을 어떻게 알림 패턴을 사용하지만 내 개체가 잘못된 상태를 입력 할 수 있도록 보장에 대해 가지고 것인가?

공장 패턴 - 당신은 자신의 불변을 보존 할 수없는 가치를 창출하고 싶지는 않을 - 일명 "라는 생성자"

당신은 생성자 검증이있다 둡니다.

그러나 공용 API에서 생성자를 가져 와서 클라이언트 코드가 팩터 리에서 메소드를 호출하도록 정렬합니다. 알림 수집을 포함하는 장애 유형을 반환 통지 수집

  • 을 포함하는 예외를 던지는 후 notifications 및 중

    • 모두를 수집 - 그 공장은 객체를 생성 할 수있는 실패를 관리하는 방법을 결정하기 위해 도착

    예외 흐름이나 차별화 된 공용 흐름을 선호하는지 여부에 따라 다릅니다.

  • +0

    'Factory'는 어떤 객체,'Room'? 이'RoomFactory (문자열 이름, 문자열 설명)'에서'Name'과'Description' 객체를 만들고 각각에 대해 'hasError'를 검사하여 유효성을 확인합니다. 그것은 여전히 ​​잘못된 불변량을 허용하지 않습니까? – Unflux

    0

    notification.hasError 함수를 호출하고 나중에 예외를 throw하는 것은 어떨까요?

    이 방법을 사용하면 알림 처리를 사용하여 오류를 처리 할 수 ​​있으며 예외적으로 유효한 개체가 없다는 것을 보장합니다.

    +0

    정확히 어디에서'notification.hasError()'를 호출할까요? – Unflux

    0

    글쎄, 당신은 이미 그랬지만, 하나의 validate() 메소드에서 모든 유효성 검증을 공유하면 비즈니스 로직을 진행하기 전에 호출 할 수 있습니다.

    그래서

    if (model.validate()) 
    { 
        // You can safely proceed 
    } 
    
    After this you can for example throw an exception so you will know that you have an object in an invalid state. 
    
    +0

    하지만'validate()'메소드를 호출하여 코드를 페 블링하지 않아도되도록 '생성자'에서 유효성 검사를 수행하는 다른 방법이 있는지 살펴볼 생각입니다. – Unflux

    +0

    그 다음에 무엇을 원합니까? 통지 패턴을 들여다 보았다고했는데 충분하지 않습니다. 오브젝트에 유효하지 않은 매개 변수가있는 경우 생성자에서 예외를 throw하려고했습니다. 외부 코드에서 호출 할 공용 유효성 검사 메소드가 충분하지 않습니다. 당신이 정말로 원하는 것은 무엇입니까? – tjugg

    +0

    이 옵션이 '충분하지 않다'는 것은 아닙니다. 어떤 사람들에게는 이것이 완벽하게 수용 가능하며'model.validate()'를 사용하게 될 수도 있습니다. 나는 잠재적 인 대안 (있는 경우)을보고 배우는 것입니다. 나는 그것이 작동하기 때문에 무언가를 '길'로 받아들이는 것이 싫어서 대안이 있는지 알고 싶다. – Unflux

    관련 문제