코어 포인트
도메인 구동 설계 (DDD)의 창고 모델은 도메인 모델과 데이터 매핑 계층 사이의 중개자 역할을하여 데이터 쿼리 관리를 향상시키고 복제를 최소화합니다. 창고는 도메인 모델에서 데이터 계층의 복잡성을 추상화하여 DDD 원칙과 일치하는 우려와 지속성 무지의 명확한 분리를 촉진합니다. 창고 구현에는 컬렉션과 같은 인터페이스 뒤에 데이터 액세스의 논리와 도메인 모델과의 상호 작용을 단순화 할 수 있습니다. - 창고는 관리 도메인 복잡성 및 격리 도메인 논리 및 데이터 지속성 세부 사항에서 상당한 이점을 제공하지만 간단한 응용 프로그램에는 구현이 너무 복잡 할 수 있습니다.
복잡한 쿼리 및 데이터 운영이 필요한 시스템에서는 창고의 실제 사용을 관찰 할 수 있으며, 여기서 도메인 중심 언어를 제공하고 도메인 모델로 인프라 누출을 줄입니다. - 전통적인 도메인 중심 디자인 (DDD) 아키텍처의 가장 일반적인 측면 중 하나는 도메인 모델에 의해 입증 된 필수 지속 불가지성입니다. 활성 레코드 또는 데이터 테이블 게이트웨이를 기반으로 한 일부 구현을 포함하여보다 보수적 인 설계 (매우기만적인 단순성을 추구하여 종종 인프라 오염 논리로 결국), 기본 스토리지 메커니즘, 일반적으로 관계형 데이터베이스에 대한 명확한 개념이 있습니다. 다른 한편으로, 도메인 모델은 개념적으로 처음부터 엄격하게 "저장 불가지론 적"특성으로 설계되어 경계를 넘어 지속성 논리를 이동시킵니다. 실제 세계에서 "데이터베이스"를 직접 언급 할 때 DDD가 다소 애매하다고 생각하더라도 도메인 모델은 결국 어떤 형태로 지속되어야하기 때문에 적어도 하나의 데이터베이스가 무대 뒤에서 실행되고있을 가능성이 높습니다. 따라서 모델과 데이터 액세스 계층 사이에 매핑 계층을 배포하는 것이 일반적입니다. 이것은 층 간의 상당한 분리 정도를 적극적으로 촉진 할뿐만 아니라 문제 레이어의 갭 사이를 앞뒤로 움직이는 클라이언트 코드의 모든 복잡한 세부 사항을 보호합니다.
mea culpa
공정하게 말하면, 데이터 맵퍼 계층의 특이성을 처리하는 것은 상당한 부담이며 "한 번 쓰기/영구적 인 사용"전략이 종종 채택된다고 말하는 것이 공정합니다. 그럼에도 불구하고, 위의 패턴은 다소 간단한 조건에서 잘 수행되는데, 여기서 소수의 도메인 클래스 만 소수의 맵퍼에 의해 처리됩니다. 그러나 모델이 부풀어 오르기 시작하고 더 복잡해지면 시간이 지남에 따라 추가 매퍼가 추가되기 때문에 상황이 더 어색해질 수 있습니다. 이것은 지속성 무시의 문을 여는 것이 여러 곳에서 비싼 객체 그래프를 만들지 않거나 반복적 인 구현의 경로에 착수하지 않는 경우, 지속성 방치의 문을 여는 것이 실제로 구현하기 어려울 수 있음을 시사합니다. 더 나쁜 것은, 다른 조건에 맞는 데이터베이스에서 비싼 집계 된 루트 세트를 추출 해야하는 대형 시스템에서는 전체 쿼리 프로세스 자체가 단일 진입 점을 통해 올바르게 집중하지 않으면 이러한 결함이있는 복제의 활성적이고 많은 활성화자가 될 수 있습니다.이 복잡한 사용 사례에서, 데이터 맵퍼와 도메인 모델 사이를 중재하는 추가 추상화 계층 (종종 DDD 전문가에서 창고라고 함)을 구현하면 쿼리 로직 복제를 효과적으로 최소화하면서 실제 메모리의 의미를 모델에 노출시키는 데 도움이됩니다. 그러나 Mappers (인프라의 일부인)와 달리 창고 자체는 모델과 밀접하게 연결되어 있기 때문에 모델의 언어로 특징 지어집니다. 그리고 매퍼에 대한 암시 적 의존성으로 인해 지속성 무지를 유지하여 도메인 객체에 더 가깝게 더 높은 수준의 추상화를 제공합니다. 불행히도, 가능한 모든 응용 프로그램이 창고의 이점을 쉽게 구현할 수있는 것은 아니므로 상황에 필요한 경우에만 구현할 가치가 있습니다. 어쨌든, 작은 창고를 처음부터 처음부터 건설하는 것이 매우 유익 할 것이므로 내부적으로 작동하는 방법을 확인하고 상당히 밀교적인 껍질 아래에 정확히 무엇이 있는지 알 수 있습니다.
예비 준비를 수행
창고 구현 프로세스는 실제로 일종의 지속적인 어댑터를 주입하는 단순화 된 컬렉션과 같은 API 후에 데이터 매퍼를 주입 및 처리하는 모든 세부 사항을 실제로 숨길 수 있기 때문에 매우 복잡 할 수 있습니다. 많은 양의 논리와 결합 된 이러한 종속성의 지속적인 주입은 일부 관점이 현재 개념과 다르더라도 창고가 종종 간단한 모습으로 간주되는 이유를 설명합니다. 두 경우 모두, 기능적 창고를 시작하고 실행하기 위해 수행 해야하는 첫 번째 단계는 기본 도메인 모델을 만드는 것입니다. 여기에 사용하려는 모델은 다음과 같이 기본 구조를 사용하여 일반 사용자를 모델링 할 책임이 있습니다.
이 경우, 도메인 모델은 다소 골격층이며, 자체 검증 할 수있는 간단한 데이터 홀더보다 거의 높지 않아 격리 된 인터페이스와 간단한 구현자를 통해서만 가상의 사용자의 데이터와 동작을 정의합니다. 간단하고 이해하기 쉽게 유지하기 위해 모델을 간소화 할 것입니다. 모델이 이미 쉽게 분리되어 실행되고 있으므로 다른 클래스를 추가하여 사용자 객체의 컬렉션을 처리하여 더 풍부하게 해 드리겠습니다. 이 "애드온"구성 요소는 Countable, ArrayAccess 및 IeratorAggage SPL 인터페이스를 구현하는 클래식 어레이 래퍼입니다.
실제로,이 배열 세트를 모델의 경계에 넣는 것은 완전히 선택 사항입니다. 일반 배열을 사용하면 거의 동일한 결과를 생성 할 수 있기 때문입니다. 그러나이 경우 독립 컬렉션 클래스에 의존함으로써 객체 지향 API를 통해 데이터베이스에서 추출한 사용자 객체 세트에 쉽게 액세스 할 수 있습니다. 또한 도메인 모델이 인프라에 설정된 기본 스토리지를 완전히 무시해야한다는 점을 고려할 때 다음으로 수행 해야하는 다음 논리적 단계는 데이터베이스와 잘 분리하는 매핑 계층을 구현하는 것입니다. 다음은이 레이어를 구성하는 요소입니다.<?php namespace Model;
interface UserInterface
{
public function setId($id);
public function getId();
public function setName($name);
public function getName();
public function setEmail($email);
public function getEmail();
public function setRole($role);
public function getRole();
}
로그인 후 복사
로그인 후 복사
<?php namespace Model;
class User implements UserInterface
{
const ADMINISTRATOR_ROLE = "Administrator";
const GUEST_ROLE = "Guest";
protected $id;
protected $name;
protected $email;
protected $role;
public function __construct($name, $email, $role = self::GUEST_ROLE) {
$this->setName($name);
$this->setEmail($email);
$this->setRole($role);
}
public function setId($id) {
if ($this->id !== null) {
throw new BadMethodCallException(
"The ID for this user has been set already.");
}
if (!is_int($id) || $id throw new InvalidArgumentException(
"The user ID is invalid.");
}
$this->id = $id;
return $this;
}
public function getId() {
return $this->id;
}
public function setName($name) {
if (strlen($name) 30) {
throw new InvalidArgumentException(
"The user name is invalid.");
}
$this->name = htmlspecialchars(trim($name), ENT_QUOTES);
return $this;
}
public function getName() {
return $this->name;
}
public function setEmail($email) {
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new InvalidArgumentException(
"The user email is invalid.");
}
$this->email = $email;
return $this;
}
public function getEmail() {
return $this->email;
}
public function setRole($role) {
if ($role !== self::ADMINISTRATOR_ROLE
&& $role !== self::GUEST_ROLE) {
throw new InvalidArgumentException(
"The user role is invalid.");
}
$this->role = $role;
return $this;
}
public function getRole() {
return $this->role;
}
}
로그인 후 복사
Unbox, Unbox, Usermpper가 수행하는 작업의 배치는 매우 간단하며 데이터베이스에서 사용자를 추출하고 CreateUser () 메소드를 통해 해당 엔터티를 재구성하는 몇 가지 일반 목적 파인더를 노출시키는 것으로 제한됩니다. 또한 이전에 일부 매핑을 탐구하고 자신의 매핑 걸작을 썼다면 위의 것은 확실히 이해하기 쉽습니다. 강조 할 가치가있는 유일한 미묘한 세부 사항은 아마도 UserCollectionInterface가 모델이 아닌 매핑 레이어에 배치되었다는 것입니다. 이런 식으로, 사용자 컬렉션이 의존하는 추상화 (프로토콜)는 의존성 반전 원칙에 의해 촉진 된 가이드와 일치하는 더 높은 수준의 usermapper에 의해 명시 적으로 선언되고 소유되기 때문에 의도적으로 수행합니다. 맵퍼가 이미 설정된 상태에서 상자에서 직접 사용하여 스토리지에서 일부 사용자 객체를 추출하여 모델이 즉시 수화 할 수 있습니다. 이것은 언뜻보기에 올바른 경로 인 것처럼 보이지만, 매핑 기는 실제로 인프라의 일부이기 때문에 실제로 인프라가 불필요하게 인프라로 인프라로 논리를 오염시키고 있습니다. 미래에 더 세분화 된 도메인 별 조건 (Mapper Finder에 의해 노출 된 일반적인 조건이 아니라)을 기반으로 사용자 엔티티를 쿼리해야한다면 어떨까요? 이 경우 매핑 계층 위에 추가 레이어를 배치해야하므로 더 높은 수준의 데이터 액세스를 제공 할뿐만 아니라 단일 지점을 통해 쿼리 로직 블록을 전달합니다. 궁극적으로 그것은 창고에서 기대하는 엄청난 양의 혜택입니다.
<<> 사용자 창고 구현 <🎜 🎜>
생산 환경에서 창고는 골재 루트의 메모리 세트를 모델에 노출시키기 위해 표면에서 생각할 수있는 거의 모든 것을 구현할 수 있습니다. 그러나이 경우, 우리가 구축 할 창고는 데이터베이스에서 사용자를 추출하는 데 책임이있는 다소 인공적인 구조가 될 것이기 때문에이 고가의 사치를 무료로 즐길 것으로 예상 할 수는 없습니다.
다소 가벼운 구조 위에 있지만, userrepository의 구현은 API를 통해 모델 언어와 밀접한 관련이있는 미세한 예측에 맞는 스토리지에서 사용자 객체 모음을 추출 할 수 있기 때문에 매우 직관적입니다. 또한 현재 상태에서 리포지토리는 일부 간단한 파인더를 클라이언트 코드에만 노출시켜 데이터 매퍼의 기능을 사용하여 스토리지에 액세스합니다. 보다 현실적인 환경에서 창고는 또한 집계 뿌리를 지속 할 수 있어야합니다. insert () 메소드 또는 기타 유사한 메소드를 userreepository에 추가하려면 자유롭게하십시오. 두 경우 모두 예제를 통해 창고를 사용하는 실제 장점을 포착하는 효과적인 방법은 다음과 같습니다.<?php namespace Model;
interface UserInterface
{
public function setId($id);
public function getId();
public function setName($name);
public function getName();
public function setEmail($email);
public function getEmail();
public function setRole($role);
public function getRole();
}
로그인 후 복사
로그인 후 복사
앞서 언급 한 바와 같이, 창고는 비즈니스 용어를 클라이언트 코드 (Eric Evans가 그의 책 "도메인 구동 설계"에서 만든 소위 "유니버설 언어")와 비즈니스 용어를 효과적으로 교차시킨다. 반면에 데이터 맵퍼 파인더에 존재하는 모호성과 달리, 창고 방법은 의심 할 여지없이 사용자 엔티티 모델링 속성의 일부인 "이름", "이메일"및 "역할"으로 설명합니다. 이 더 미세하고 높은 수준의 데이터 추상화와 복잡한 시스템에서 쿼리 로직을 캡슐화 할 때 필요한 전체 기능 세트는 의심 할 여지없이 창고가 다층 설계에서 더 매력적인 가장 매력적인 이유 중 하나입니다. 물론, 대부분의 경우, 이러한 혜택을 사전에 얻는 번거 로움과 추가 추상화 계층을 배포하는 데있어 암시적인 트레이드 오프가 있습니다 (이는 더 간단한 응용 프로그램에서 너무 부풀어 질 수 있음).
결론
도메인 중심 디자인의 핵심 개념 중 하나 인 는 Java 및 C#과 같은 다른 언어로 작성된 응용 프로그램에서 창고를 찾을 수 있습니다. 그러나 PHP에서는 여전히 상대적으로 알려지지 않았으며 세계의 첫 걸음을 내딛습니다. 그럼에도 불구하고 DDD 패러다임을 채택하는 데 도움이되는 Flow3 및 Doctrine 2.X와 같은 신뢰할 수있는 프레임 워크가 있습니다. 기존 개발 접근 방식과 마찬가지로 애플리케이션에서 리포지토리를 사용하거나 DDD 뒤의 개념 힙으로 불필요하게 분쇄 할 필요가 없습니다. 상식을 적용하고 필요에 적합하다고 생각하는 경우에만 선택하십시오. 그렇게 간단합니다. 기회 agrella / freerangestock.com의 사진
핸들링의 FAQ는 집계 된 루트 컬렉션 (FAQ) 입니다
도메인 중심 디자인의 집계 루트는 무엇입니까?
도메인 구동 설계 (DDD)에서 집계 루트는 단위로 간주되는 관련 객체의 모음입니다. 이 객체는 루트 엔티티 (집계 루트라고도 함)에 의해 함께 묶여 있습니다. 집계 루트는 외부 물체가 회원에 대한 참조를 유지하도록 금지함으로써 집계에 대한 변화의 일관성을 유지합니다.
집계 뿌리와 일반 실체의 차이는 어떻습니까?
집계 뿌리와 일반 실체의 주요 차이점은 그들의 책임입니다. 일반 엔티티는 행동과 상태를 캡슐화하는 반면, 집계 뿌리는 또한 구성원에 대한 액세스를 제어함으로써 전체 집계의 무결성을 보장합니다. 외부 객체가 참조를 유지할 수 있도록 집계의 유일한 멤버입니다.
내 도메인 모델에서 집계 루트를 식별하는 방법은 무엇입니까?
집계 루트를 식별하려면 비즈니스 영역에 대한 깊은 이해가 필요합니다. 일반적으로 글로벌 정체성을 가진 고급 엔티티이며 다른 엔티티와 가치 객체를 캡슐화합니다. 예를 들어, 전자 상거래 세계에서 순서는 라인 항목 및 전달 정보를 캡슐화하는 집계 루트가 될 수 있습니다.
집계 된 뿌리 모음을 다루는 방법은 무엇입니까?
집계 된 뿌리의 모음을 처리하는 것은 어려울 수 있습니다. 각 집계 루트는 일관성 경계이므로 하나의 집계 루트로의 변경은 다른 집계 루트에 영향을 미치지 않아야한다는 것을 기억하는 것이 중요합니다. 따라서 컬렉션을 처리 할 때 일반적으로 일관성을 위해 각 집계 루트를 별도로로드하고 지속하는 것이 좋습니다. 집계 뿌리가 다른 집계 루트를 언급 할 수 있습니까?
예, 집계 뿌리는 다른 집계 루트를 참조 할 수 있지만 식별에 의해서만 참조해야합니다. 즉, 다른 집계 루트 객체에 대한 직접적인 참조가 아니라 ID를 직접 참조해서는 안됩니다. 이를 통해 각 집계 루트의 일관성 경계를 유지하는 데 도움이됩니다.
집계 루트는 DDD의 창고와 어떻게 관련이 있습니까?
DDD에서 창고는 집계 뿌리를 검색하고 저장하는 방법을 제공합니다. 기본 저장 메커니즘을 추상화하여 도메인 모델이 데이터 지속성의 세부 사항을 무시할 수 있습니다. 각 집계 루트에는 일반적으로 자체 스토리지가 있습니다.
비즈니스 규칙을 실행할 때 집계 뿌리의 역할은 무엇입니까?
집계 뿌리는 비즈니스 규칙을 실행하는 데 중요한 역할을합니다. 그것은 집계의 모든 변경으로 인해 유효한 상태에 있습니다. 이는 여러 엔티티 또는 가치 객체에 걸친 비즈니스 규칙이 집계 루트에 의해 시행되어야 함을 의미합니다.
집계 루트는 도메인 모델의 복잡성을 줄이는 데 어떻게 도움이됩니까?
집계 루트는 일관성 경계 역할을하고 멤버에 대한 액세스를 제어함으로써 도메인 모델의 복잡성을 줄이는 데 도움이됩니다. 각 집계에 대해 단일 상호 작용 지점을 제공하여 모델을 단순화하여 시스템을 쉽게 이해할 수 있습니다.
골재 뿌리가 여러 집계의 일부가 될 수 있습니까?
아니요, 집계 뿌리는 여러 골재의 일부가되어서는 안됩니다. 이는 집계의 일관성 경계를 위반하고 도메인 모델에서 불일치로 이어질 수 있습니다.
집계 뿌리의 동시성 문제를 다루는 방법은 무엇입니까?
다양한 전략을 사용하여 낙관적 자물쇠 나 비관적 잠금 장치와 같은 집계 뿌리에서 동시성 문제를 처리 할 수 있습니다. 정책의 선택은 응용 프로그램의 특정 요구 사항과 직면 한 동시성 문제의 특성에 따라 다릅니다.
이 개정 된 출력은 원래 이미지 형식과 위치를 유지하고 표절을 피하기 위해 텍스트를 역설적으로 유지하며 핵심 의미를 항상 적절하게 인용해야합니다
위 내용은 집계 뿌리의 수집 - 저장소 패턴 처리의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!