명령 핸들러 및 DDD


10

쿼리 서비스를 사용하여 데이터를 가져오고 명령 서비스를 사용하여 명령을 보내는 ASP.NET MVC 응용 프로그램이 있습니다. 내 질문은 명령 부분에 관한 것입니다.

요청이 들어 오면 명령 서비스는 명령을 지정된 명령 핸들러로 라우트하는 명령 디스패처를 사용합니다. 이 명령 핸들러는 먼저 comand의 유효성을 검사하고 모든 것이 허용 가능한 경우 명령을 실행합니다.

구체적인 예 : AddCommentToArticleCommandHandler는 ArticleId, CommentText 및 EmailAddress가있는 AddCommentToArticleCommand를 수신합니다.

먼저; -기사가 있는지 확인-기사가 닫혀 있지 않은지 확인-주석 텍스트가 채워지고 20-500 자 사이인지 확인-이메일 주소가 입력되어 있고 유효한 형식인지 확인하십시오.

이 유효성 검사를 어디에 넣을지 궁금합니다.

1 / 명령 처리기 자체에서. 그러나 다른 명령 핸들러에서는 재사용 할 수 없습니다.

도메인 엔터티에서 2 / 그러나 도메인 엔터티는 리포지토리 또는 서비스에 대해 알지 못하므로 필요한 유효성 검사를 수행 할 수 없습니다 (기사가 있는지 여부를 확인할 수 없음). 그러나 한편으로 엔티티에 로직이 포함되어 있지 않은 경우 DDD 원칙을 따르지 않는 단순한 데이터 컨테이너가됩니다.

3 / 명령 핸들러는 유효성 검증기를 사용하므로 다른 명령 핸들러에서 유효성 검증을 재사용 할 수 있습니다.

4 / 다른 메커니즘?

이 특정 예제에 대한 책임 체인과 어떤 개체 (엔터티, 리포지토리 등)가 그 역할을 수행 하는지를 찾고 있습니다.

커맨드 핸들러에서 리포지토리에 이르기까지이를 구현하는 방법에 대한 아이디어가 있습니까?


"하지만 도메인 엔터티는 리포지토리 나 서비스를 알지 못하므로 필요한 유효성 검사를 수행 할 수 없습니다"? 왜 안돼? DDD의 어떤 원칙이 이것을 요구합니까?
S.Lott

나는 엔티티가 리포지토리 또는 다른 것에 대해 알아야 할 모든 것을 읽었습니다.
L-Four

무엇을 읽었는지에 대한 인용문, 링크 또는 예를 제공 할 수 있습니까? 우리는 당신이 읽고있는 DDD에 대한 설명을 모른다.
S.Lott


Jimmy Bogard는이 주제에 대한 견해를 공유했습니다 ... lostechies.com/jimmybogard/2009/02/15/validation-in-a-ddd-world
Mayo

답변:


4

이 경우 두 가지 유형의 유효성 검사를 분리해야한다고 생각합니다. 도메인 유효성 검사응용 프로그램 유효성 검사 .

응용 프로그램 유효성 검사는 명령 속성 'text'가 20 ~ 200 자 사이인지 확인한 경우 보유한 것입니다. 따라서 GUI와 POST 후에 서버에서 실행되는 view-model-validator를 사용하여이를 검증합니다. 전자 메일도 마찬가지입니다. (btw,`32.d + "Hello World .42"@ mindomän.local "과 같은 전자 메일이 RFC에 따라 유효하다는 것을 알고 싶습니다.)

그런 다음 다른 유효성 검사가 있습니다. 기사가 존재하는지 확인-GUI에 주석을 첨부하는 명령이 실제로 전송 된 경우 기사가 존재하지 않아야하는 이유를 스스로에게 질문해야합니다. GUI가 결국 일관성이 있었으며 데이터 저장소에서 물리적으로 삭제할 수있는 집약 루트 기사가 있습니까? 이 경우 명령 핸들러가 집계 루트를로드하지 못하므로 명령을 오류 큐로 이동하면됩니다.

위의 경우 포이즌 메시지를 처리하는 인프라가 있습니다. 예를 들어 메시지를 1 ~ 5 회 다시 시도한 다음 메시지 모음을 수동으로 검사하고 관련 메시지를 다시 배포 할 수있는 위치 큐로 옮깁니다. 모니터링하는 것이 좋습니다.

이제 우리는 논의했습니다 :

  • 응용 프로그램 검증

    • GUI에서 자바 스크립트 사용
    • 웹 서버에서 MVC 유효성 검사
  • 집계 루트 + 포이즌 큐 누락

도메인과 동기화되지 않은 명령은 어떻습니까? 어쩌면 도메인 로직에 기사에 대한 5 개의 주석 후에 400 자 미만의 주석 만 허용되지만 한 사람이 5 번째 주석에 너무 늦어서 6 번째가되어야한다고 말하는 규칙이있을 수 있습니다. 명령을 보내는 시점에서 도메인과 일치하지 않았습니다.이 경우 도메인 로직의 일부로 '유효성 검증 실패'가 발생하여 해당 실패 이벤트를 반환합니다.

이벤트는 메시지 브로커 또는 사용자 정의 디스패처에 대한 메시지 형식 일 수 있습니다. 응용 프로그램이 모 놀리 식인 경우 웹 서버는 언급 된 성공 이벤트와 실패 이벤트를 동 기적으로 수신하고 적절한보기 / 부분을 표시 할 수 있습니다.

많은 유형의 명령에서 실패를 의미하는 사용자 지정 이벤트가있는 경우가 종종 있으며,이 이벤트는 웹 서버의 관점에서 구독하는 경우입니다.

우리가 작업하고있는 시스템에서 MassTransit + RabbitMQ 메시지 버스 + 브로커를 통해 명령 / 이벤트로 요청-응답을하고 있으며이 특정 도메인 (일부 워크 플로우 모델링)에 이벤트가 있습니다 InvalidStateTransitionError. 상태 그래프에서 가장자리를 따라 이동하려고하는 대부분의 명령으로 인해이 이벤트가 발생할 수 있습니다. 우리는 궁극적으로 일관된 패러다임 후에 GUI를 모델링하고 있으므로 사용자를 '명령 수락'페이지로 보낸 후 웹 서버의보기를 이벤트 구독을 통해 수동으로 업데이트 할 수 있습니다. 우리는 또한 전체 뿌리에서 이벤트 소싱을 수행하고 있으며 또한 가스를 위해 일할 것임을 언급해야합니다.

따라서 많은 검증은 실제 도메인 로직이 아니라 실제로 애플리케이션 유형의 검증입니다. 도메인은 단순하지만 DDD를 수행하는 경우 간단한 도메인 모델을 갖는 데 아무런 문제가 없습니다. 그러나 도메인 모델링을 계속하면 도메인이 처음 나온 것만 큼 간단하지 않을 수 있습니다. 대부분의 경우 집계 루트 / 엔티티는 명령으로 인한 메소드 호출을 승인하고 유효성 검증을 수행하지 않고도 상태의 일부를 변경할 수 있습니다. 특히 웹 서버에서 명령을 유효성 검증하면 명령을 신뢰하는 경우 당신은 통제합니다.

Norwegian Developer Conference 2011 에서 DDD에 대한 두 가지 프레젠테이션 과 Öredev 2010 에서 Greg의 프레젠테이션을 볼 것을 권합니다 .

건배, 헨케


감사! 유효성 검증에 대한 한 가지 : 현재이 유효성 검증은 Comment 엔티티 자체의 Validate ()를 사용하는 UI (서비스에 Validate (명령) 요청을 발행하여)에 의해 트리거됩니다. 그런 다음 명령이 유효한 경우 클라이언트는 Execute 명령을 실행하여 Validate ()를 다시 실행하고 유효한 경우 실제 명령이 실행됩니다. 따라서 모든 컨텍스트에서 유효성 검사는 동일하므로 (이메일은 항상 유효해야하며, 주석 텍스트는 너무 길지 않아야합니다.) 이것이 좋은 접근 방법입니까?
L-Four

당신이 묘사하고있는 검증은 2 단계 검증 프로토콜로 모델링을 보증하지 않는 것 같습니다. 물론 단위 테스트에서 테스트 할 것처럼 엔티티에서 메소드 호출의 매개 변수를 검증하십시오. 응용 프로그램 계층 / GUI는 도메인에 명령을 보내지 않고도 설명하고있는 규칙을 쉽게 확인할 수 있습니다. 이모. 클라이언트가 악의적이지 않으면 명령이 작동합니다. 클라이언트가 악의적 인 경우 명령이 실패하고 읽기 모델이 해당 이벤트를받지 못하므로 오류 대기열에서 문제가있는 명령을 검사 할 수 있습니다.
Henrik

UI (ASP.NET MVC)에서 모든 유효성 검사를 수행하기 위해 유효성 검사 속성을 사용하고 있습니다. 따라서이 유효성 검사가 성공하면 도메인에서 다시 유효성 검사를 수행 할 필요가 없지만 명령을 실행하면됩니까?
L-Four

1
예, 명령을 실행하지만 응용 프로그램 계층과 도메인 모두에서 명령이 유효하지 않은지 확인하십시오.
Henrik

0

편집 : WaybackMachine 링크 : http://devlicio.us/blogs/billy_mccafferty/archive/2009/02/17/a-response-to-validation-in-a-ddd-world.aspx

팻 답변이 없습니다.

유효성 검사가 수행되는 위치에 대답하려고 할 때 명쾌한 두 가지 프로젝트 시나리오가 있습니다. 첫 번째는 DTO 계층을 사용하여 뷰와 도메인 계층간에 정보를 전송하는 것입니다. 예를 들어, 도메인 계층에 고객 개체가 있고 고객 정보를 매핑 할 다른 계층에 관련 고객 DTO가있는 경우 고객에게 고객 정보를 제공하기위한보기를 제공 할 수 있습니다.

두 번째 시나리오는 도메인 계층 내의 엔티티가 뷰와 직접 공유되어 데이터를 사용자에게 제공하는 프로젝트입니다. 예를 들어 별도의 DTO 계층을 유지 관리하고 도메인 개체를 DTO에 매핑하여 뷰에 제공하는 대신 뷰에 고객 개체를 직접 제공 할 수 있습니다. 따라서 별도로 유지 관리되는 DTO를 통해 고객의 이름을 표시하는 대신, 고객 객체 자체에 정보를 요청하면됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.