DRY 또는 Command-Query-Separation을 타협해야합니까?


10

최근에는 명령 및 쿼리 방법 인 방법을 리팩토링했습니다.

하나의 명령 방법과 하나의 쿼리 방법으로 분리 한 후 코드에서 명령을 호출 한 다음 쿼리에서 값을 얻는 여러 위치가 있음을 알았습니다. 이것은 DRY 원칙을 위반하는 것처럼 보입니다.

그러나 해당 공통 코드를 메소드로 랩핑하는 경우 해당 메소드는 명령과 쿼리입니다. 이것이 허용됩니까?


알았어, 나는 공동체가 합의에 있는지 알지 못했고이 주제에 관한 어떤 토론도 찾을 수 없었다.
Kris Welsh

더 일반적으로 CQRS라고합니다. google.com.au/…
Daniel Little

@DanielLittle-아닙니다. CQS와 CQRS는 분명히 다른 과목입니다. CQRS는 훨씬 더 복잡한 아키텍처 패턴이며 CQS는 더 많은 디자인 패턴이며 파악 및 구현이 훨씬 쉽습니다. codebetter.com/gregyoung/2009/08/13/command-query-separation
Erik Funkenbusch

@Erik Funkenbusch 당신이 맞아요
Daniel Little

답변:


11

상충되는 설계 원칙 사이에는 항상 고려해야 할 절충 사항이 있습니다. 이를 해결하는 방법은 원칙 뒤에있는 근본적인 이유를 살펴 보는 것입니다. 이 경우 명령을 실행하지 않고 쿼리를 실행할 수없는 것은 문제가되지만 쿼리를 실행하지 않고 명령을 실행할 수없는 것은 일반적으로 무해합니다. 쿼리를 독립 실행 형으로 실행할 수있는 한, 특히 다음과 같은 경우 쿼리 결과를 명령에 추가하지 않을 이유가 없습니다.

QueryResult command()
{
   // do command stuff
   return query();
}

4

CQS (Command-Query-Separation)에 대해 들어 보지 못했지만 단일 책임 원칙 (SRP)과 관련이있는 것으로 보입니다 .SRP (Single Responsibility Principle)는 함수 / 클래스가 한 가지 작업 만 수행하는 것이 이상적입니다. .

명령 코드가 20 줄의 코드이고 쿼리 코드가 다른 30 줄이고 모두 하나의 함수 본문에있는 경우 분명히 SRP를 위반하고 있으며 CQS도 가정 하고이 두 가지 논리가 서로 분리되어야한다고 가정합니다. .

그러나 가상의 예를 사용하면 명령과 쿼리를 결합하여 코드의 여러 위치에서 DRY가 위반되지 않는 래퍼 메서드를 만들 것입니다. 래퍼에는 여전히 하나의 책임이 있기 때문에 이것을 SRP (및 아마도 CQS) 위반으로 간주하지 않을 것입니다. 명령과 쿼리를 결합하고 소비하기 쉬운 높은 수준의 추상화를 만드는 것입니다.

래퍼 방법이 완벽하게 수용 가능한 해결책이라고 생각하고 그것을 설명하기 위해 한 단계 더 나아가 봅시다. 1 대신 2 개의 쿼리를 실행 한 다음이를 기반으로 명령 작업을 수행해야하는 경우 어떻게해야합니까? 따라서 두 줄의 코드는 6 또는 8입니다. 둘 사이에 데이터 유효성 검사 / 확인이 있었으므로 이제 15 줄의 코드가 있습니다. 15 줄을 여러 파일에 뿌리지 않고 모든 것을 수행하는 래퍼를 만드는 것에 대해 두 번 생각하십니까?


래퍼의 "단일 원칙"은 명령과 쿼리가 함께 필요한 다른 메소드를 DRY로 유지하는 것이어야한다고 생각합니다.
Droogans


이 문제에 대한 Karl의 솔루션이 더 좋지만 더 긴 래퍼 기능에 대한 정교함이 매우 좋은 지적입니다.
Kris Welsh

-3

DRY는 훨씬 더 근본적인 요구를 해결하므로 중복적이고 효과적으로 낭비되는 노력을 피하기 때문에 더 중요합니다. 이것은 근본적인 것입니다-그것을 이해하기 위해 프로그래머 일 필요는 없습니다.

CQS는 결과 추적과 결과에 대해 실행되는 코드를 이해하는 데있어 효과 추적을 지원하지 않는 언어의 난이도에 대한 응답입니다. 하나:

  1. 작은 단위에서 큰 프로그램을 작성하기위한 기초이기 때문에 결과에 대한 코드 실행의 필요성을 피할 수 없습니다.

  2. 수학 및 이론적 컴퓨터 과학 이외의 프로그램 실행의 가치는 우리가 관찰 할 수있는 일에 달려 있기 때문에 그 효과를 위해 코드를 실행해야 할 필요성도 피할 수 없습니다.

  3. 실제로는 동일한 코드에서 효과를 발생시키고 결과를 생성해야 할 필요성을 피할 수 없습니다. 실제로 실제로는 하나 또는 다른 것이 아니라 효과와 구성이 모두 필요하기 때문입니다.

비 보조 인간에게는 너무 어려운 추적 효과 문제에 대한 실제 해결책은 물론 컴퓨터가 인간을 도와주는 것입니다 ! 예외와 런타임 적용 계약이 (비) 솔루션을 구성하는 런타임 값 (예 : 배열 인덱스의 유효성) 간의 복잡한 관계추적 하는 것에 대해서도 비슷한 내용을 말할 수 있습니다 .

결론적으로, CQS와 같은 "솔루션"은 단지 현실에 기반한 건전한 원칙에 따라 프로그램을 설계하는 방식에 불과합니다. 건조하러 가십시오.


때로는 복잡성을 줄이기 위해 커플 링을 피해야합니다. CQRS를 살펴 봐야합니다.
Daniel Little

@Lavinski : 복잡성을 피할 수있는 가장 좋은 도구는 추상화가 아닙니다. 즉, 일반적인 문제의 특정 세부 사항에서 풀고있는 문제의 일반적인 본질을 분리하는 것입니다. 마법 레시피 (또는 "디자인 패턴"이라고도 함)는 디자인이 잘못 될 때 너무 많은 손상을 입히는 것을 방지 할 수 있지만 잘못된 디자인을 올바른 디자인으로 바꿀 수는 없습니다.
pyon

@Lavinski : 구체적으로 CQRS와 관련하여 개념적으로 올바른 대안 솔루션은 1. 데이터 모델을 이해하고 (필수를 제거 할 수있는 객체 계층의 양이 없음) 2. 데이터베이스 스키마에서 가능한 한 많은 정확성 속성을 인코딩하는 것입니다. (슬프게도, 가장 인기있는 RDBMS는 후자를 지원하는 데 제한적인 지원을 제공하지만 NoSQL은 말할 것도없이 더 잘못됩니다. 현재 진행중인 연구는 이에 대한 더 나은 솔루션을 제공하고 있습니다.)
pyon

CQRS는 Domain Driven Design과 완벽하게 연동됩니다. 약간의 연구를 제안합니다. 응용 프로그램 내부의 도메인은 데이터 저장소가 아닌 정확성을 강화해야합니다.
Daniel Little

1
@ EduardoLeón : 디자인이 올바른지 증명하려면 프로그램에 대한 테스트를 작성하십시오. CQS를 포기하면 그 노력을 방해 할뿐입니다.
Stefan Billiet '
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.