4

Symfony 2/Doctrine 2의 요점은 내가 너무 많은 비즈니스 로직을 구축했다는 것을 깨닫게 된 것입니다. 우리의 응용 서비스에 & 컨트롤러 - 충분하지 않은 모델입니다.Symfony 2에서 뚱뚱한 모델 만들기 - 구성 또는 상속 및 내 모델 레이어 구성 방법

행동을 수정하기 위해 모델에 서비스를 직접 액세스 할 수 있도록 모델을 구성하고 (동작을 수정하기 위해) 모델을 소개하고자합니다.

나는 다음과 같은 질문에 8 개의 upvotes와 함께 완전히 잘못된 답이 표시되어 있음을 알았습니다. 그래서 우리가 지금까지 취한 접근법 (빈혈 모델)이 '올바른'방법으로 간주됩니다. 많은 Symfony 2 사용자. 도메인 중심 디자인으로 더 많은 것을 읽은 후에 나는 그렇지 않다는 것을 안다.

Symfony2 MVC: where does my code belong?

나는 번들의 많은 모델의 동작을 정의하고 개체/문서에서이 확장을 참조하십시오. 이 패턴은 어느 정도까지는 작동하지만 추가 단계를 도입해야한다고 생각합니다. 우리 모델의 일부 동작은 선택 사항이며, 그 동작은 추가 번들이 우리 애플리케이션에 등록되어 있는지에 달려있다. 따라서 X 번들을 포함하면 애플리케이션이 더 많은 일을 할 수있다. 예제.

우리는 현재 택배 번들의 엔티티와 양방향 관계를 가지고있는 주문 객체를 가지고 있습니다. 즉, 의존성이 있습니다. 나는 이것을 분리하고 택배 번들 (들)에 주문에 행동을 선택적으로 추가하게하고 싶다. 이 메소드 호출을 고려하십시오.

// no courier bundle is registered 
$order->getShippingMethods(); 
// throws NoAvailableShippingMethodsException; 

// one bundle registered 
$order-getShippingMethods(); 
// returns an array with one shipping method 

etc.... 

지금 현재 우리는 단지 엔티티 관리자의 위에 앉는 OrderProvider 서비스가 - 그래서 당신은

$orderProvider->GetOrder($id); 

를 호출하는 경우 당신은 엔티티가 데이터베이스에서 '직접'반환받을. 제 질문은 여기서 pattens가 다른 사람들이 사용하는 것입니다. 나는 엔터티가 확장되는 모델 클래스로 모든 '비즈니스 로직'을 이동시키고, 엔터티를 끌어 내고 (데이터베이스와 getter의 속성을 가진 멍청한 레코드 인 엔터티) 구성을 사용하여 모델을 구성하는 방법에 대해 생각하고 있습니다. OrderProvider 서비스에 구성이 주입 됨) 모델의 동작을 수정합니다. 내가합니다 (OrderProvider 이내) 같은 것을 할 수 주어진 예 .. 들어

// trimmed down for example purposes by removing exceptions etc. 
public function getOrder($id) 
{ 
    $order = $this->orderRepository->findOneById($id); 
    if ($this->couriers){ 
     $order->addCouriers($couriers); 
    } 
    return $order; 
} 

// this function would be called by the courier bundle automatically using semantic configuration/tags/setter injection 
public function addCourier(CourierInterface $courier) 
{ 
    $this->couriers[] = $courier; 
} 

나는 새 유형의 객체 생성하는 것입니다있는 다른 옵션 - 기본 순서를 장식하고 이미 구성되어 (그와 같은 ITSELF는 DIC의 서비스로 정의 될 것입니다). 차이점은 미묘하고 양쪽 접근법 모두 효과적 일지 모르지만 어느 것이 가장 좋은 길인지 궁금합니다.

마침내 나는이 모든 것에 대해 내 머리를 얻을 수없는 한 가지 문제가 있습니다. 기본 기본 주문 엔티티가 다른 엔티티와 관계가 있고 그 엔티티를 구성해야하는 경우 -이 작업을 수행해야하는 위치는 무엇입니까? 예를 들어 고객에게 액세스하는 경우를 예로들 수 있습니다.

$order->getCustomer(); 

나는 고객 (엔티티)을 얻는다. 이 방법의 행동이 내 응용 프로그램은 트위터 번들 또는 페이스 북 번들 또는 등록 여부에 따라 다를 수 있습니다 이제

$customer->getContactMethods(); 

같은 -하지만 내가 너무 고객 개체에 몇 가지 설정을 추가해야하는 경우가 있습니다 다른 것.위의 예에서 충분히 구성한 고객을 얻지는 않지만 "바닐라"기반 엔터티를 얻게됩니다. 나는이 문제를 볼 수있는 유일한 방법은 구성이 필요하고 CustomerProvider 서비스에서 엔티티를 가져 엔티티 사이의 관계를 절단하는 것입니다 :이 날 것으로 보인다

$customerProvider->getCustomerByOrder($order); 

모델 층에서 정보를 제거 할을하고 의존쪽으로 다시 이동 간단한 작업을 위해 여러 서비스를 사용하고 있습니다. 생각과 자원에 대한 링크는 높이 평가됩니다.

편집 : 관련 - 나는 왜이 질문을했습니다되어 매일 첫 번째 대답에 나와있는 단점을 참조 ->Anemic Domain Model: Pros/Cons 그것은 프로젝트의 복잡성 것 같다

답변

0

는 모듈화의 요구 사항입니다 - 응용 프로그램 행동은 번들을 통해 확장 가능해야합니다. Symfony 2/Doctrine 2에 익숙하지 않지만 일반적인 DDD 전술은 Order와 Customer 같은 도메인 엔티티가 번들 구성을 인식하지 못하도록하는 것입니다. 즉, 주변 서비스는 묶음 특정 동작을 엔터티에 추가하면 안됩니다. 엔티티에 대한 번들 인식에 대한 책임을 위임하면 엔티티가 너무 복잡해집니다. 포괄적 인 동작을 지원하기 위해 엔티티 클래스 계층을 조작하는 것은 너무 복잡합니다. 대신이 확장 성은 응용 프로그램 서비스에서 관리해야합니다. 응용 프로그램 서비스는로드되는 번들을 판별하고 그 결과로 적절한 엔티티를 조정합니다.

고려해야 할 또 다른 전략적 패턴은 bounded contexts입니다. 모듈과 정렬 된 바운드 컨텍스트로 애플리케이션을 분할 할 수 있습니까? 예를 들어 $order-getShippingMethods() 메서드를 처리하려면 두 개의 BC를 만들 수 있습니다. 하나는 getShippingMethods() 메서드가있는 주문 모델이 있고 다른 하나는없는 것입니다. 두 모델이 DRY의 위반처럼 보일 수 있지만 모델이 다른 것을 나타내는 경우 (즉, 데이터를 전달하는 주문과 그렇지 않은 주문) 실제로 아무것도 반복되지 않습니다.

+0

답변 해 주셔서 감사합니다. 나는 도메인 엔터티가 구성을 알지 못한다는 것을 제안하고있다. (그러나 엔티티 자체는 그들에게 구성을 부과 할 필요가있다. (현재 내가하고있는) 애플리케이션 서비스를 사용하는 것은 도메인이 부유해야한다는 점에서 좋은 객체 지향의 원칙에 어긋나는 것으로 보인다. 아마도 진정한 SoC와 완전히 풍부한 도메인 모델은 호환되지 않는 개념입니까? 두 번째 제안 (CourierAwareOrder)은 제가 생각한 것입니다. 그러나 그것은 단지 저를 queazy라고 느끼게합니다. 어쩌면 생각을 다시해야 할 필요가 있습니다. 입력을 주셔서 감사합니다. – calumbrodie

+0

빈혈 도메인 모델의 안티 패턴은 서비스가 엔티티가 할 수있는 작업을 수행 할 때 주로 발생합니다. 이것은 대개 어떤 동작에 대한 응답으로 엔티티의 상태를 수정하는 것과 같습니다. 엔티티 상태를 수정하는 것과 관련된 것은 엔티티에 의해 수행되어야합니다. 반면에 응용 프로그램 수준 구성 같은 것은 엔터티의 책임이 아니며 빈혈 도메인 모델과 관련이 없습니다. 제가 제안한 것은 엔티티에 구성을 부과하는 것을 피하기위한 시도입니다. 대신, 각 유스 케이스에 대한 특정 엔터티를 보유하십시오. – eulerfx