[design-patterns] 내 도메인 엔터티를 프레젠테이션 레이어에서 분리해야하는 이유는 무엇입니까?

세부 사항이 많지 않은 것으로 보이는 도메인 중심 설계의 한 부분은 도메인 모델을 인터페이스에서 분리하는 방법과 이유입니다. 동료들에게 이것이 좋은 습관이라고 설득하려고 노력하고 있지만 많은 진전이없는 것 같습니다 …

그들은 프레젠테이션 및 인터페이스 레이어에서 원하는 곳에서 도메인 엔티티를 사용합니다. 내가 그들에게 디스플레이 모델이나 DTO를 사용하여 인터페이스 레이어로부터 도메인 레이어를 격리해야한다고 주장 할 때, 그들은 그런 일을 할 때 비즈니스 가치를 보지 못한다고 반박합니다. 왜냐하면 이제는 유지할 UI 개체가 있기 때문입니다. 원래 도메인 개체도 마찬가지입니다.

그래서 저는 이것을 백업하는 데 사용할 수있는 몇 가지 구체적인 이유를 찾고 있습니다. 구체적으로 특별히:

  1. 프레젠테이션 레이어에서 도메인 개체를 사용하지 않는 이유는 무엇입니까?
    (답이 명백한 ‘디커플링’이라면이 맥락에서 이것이 왜 중요한지 설명해주세요)
  2. 인터페이스에서 도메인 개체를 격리하기 위해 추가 개체 또는 구성을 사용해야합니까?



답변

간단히 말해서 그 이유는 구현과 드리프트 중 하나입니다. 예, 프레젠테이션 계층은 비즈니스 개체를 제대로 표현할 수 있도록 비즈니스 개체에 대해 알아야합니다. 예, 처음에는 두 가지 유형의 객체 구현간에 많은 겹침이있는 것처럼 보입니다. 문제는 시간이 지남에 따라 양측에 모든 것이 추가된다는 것입니다. 프레젠테이션 변경 및 프레젠테이션 레이어의 요구 사항은 비즈니스 레이어와 완전히 독립적 인 항목 (예 : 색상)을 포함하도록 진화합니다. 한편, 도메인 개체는 시간이 지남에 따라 변경되며, 인터페이스에서 적절한 분리가없는 경우 비즈니스 개체를 겉보기에 무해하게 변경하여 인터페이스 계층을 망칠 위험이 있습니다.

개인적으로, 사물에 접근하는 가장 좋은 방법은 엄격하게 시행되는 인터페이스 패러다임을 통하는 것입니다. 즉, 비즈니스 개체 계층은 통신 할 수있는 유일한 방법 인 인터페이스를 노출합니다. 인터페이스에 대한 구현 세부 정보 (예 : 도메인 개체)가 노출되지 않습니다. 예, 이것은 두 위치에서 도메인 개체를 구현해야 함을 의미합니다. 인터페이스 계층과 BO 계층에 있습니다. 그러나 이러한 재 구현은 처음에는 추가 작업처럼 보일 수 있지만 향후 언젠가 작업 톤을 절약 할 수있는 분리를 강화하는 데 도움이됩니다.


답변

나는 이것으로 나 자신을 고투했다. 프레젠테이션에서 DTO를 사용하는 것이 합당한 경우가 있습니다. 시스템에서 회사 드롭 다운을 표시하고 값을 바인딩 할 회사 ID가 필요하다고 가정 해 보겠습니다.

구독에 대한 참조가 있거나 다른 정보를 알고있는 CompanyObject를로드하는 대신 이름과 ID와 함께 DTO를 다시 보낼 수 있습니다. 이것은 IMHO를 잘 사용합니다.

이제 다른 예를 들어 보겠습니다. 견적을 나타내는 개체가 있습니다.이 견적은 노동력, 장비 등으로 구성 될 수 있습니다. 사용자가 정의한 많은 계산을 통해 이러한 모든 항목을 가져와 합계 할 수 있습니다 (각 견적은 유형에 따라 다를 수 있음). 계산). 이 객체를 두 번 모델링해야하는 이유는 무엇입니까? 내 UI가 계산을 열거하고 표시하도록 할 수없는 이유는 무엇입니까?

나는 일반적으로 DTO를 사용하여 내 UI에서 내 도메인 레이어를 격리하지 않습니다. 제어 할 수없는 경계에서 도메인 계층을 분리하는 데 사용합니다. 누군가가 자신의 비즈니스 객체에 탐색 정보를 넣을 것이라는 생각은 말도 안되며 비즈니스 객체를 오염시키지 마십시오.

누군가가 자신의 비즈니스 객체에 유효성 검사를 할 것이라는 생각? 저는 이것이 좋은 것이라고 말합니다. UI는 비즈니스 객체의 유효성을 검사 할 책임이 없어야합니다. 비즈니스 계층 자체 검증을 수행 해야 합니다.

왜 busienss 객체에 UI 생성 코드를 넣을까요? 제 경우에는 UI와 별도로 UI 코드를 생성하는 별도의 개체가 있습니다. 내 비즈니스 개체를 Xml로 렌더링하는 별도의 개체가 있습니다. 이러한 유형의 오염을 방지하기 위해 레이어를 분리해야한다는 생각은 저에게 너무 낯설습니다. 왜 비즈니스 개체에 HTML 생성 코드를 넣을까요?

편집
조금 더 생각해 보면 UI 정보가 도메인 레이어에 속할 수있는 경우가 있습니다. 그리고 이것은 도메인 레이어라고 부르는 것을 흐리게 할 수 있지만 UI 모양과 느낌과 기능적 워크 플로 모두 매우 다른 동작을 가진 멀티 테넌트 애플리케이션에서 작업했습니다. 다양한 요인에 따라. 이 경우 테넌트와 그 구성을 나타내는 도메인 모델이 있습니다. 그들의 구성에는 UI 정보가 포함되었습니다 (예 : 일반 필드에 대한 레이블).

개체를 지속 가능하도록 디자인해야한다면 개체도 복제해야합니까? 이제 새 필드를 추가하려는 경우 두 위치에 추가 할 수 있습니다. 아마도 이것은 DDD를 사용하는 경우 다른 질문을 제기 할 수 있습니다. 모든 영구 엔티티 도메인 객체입니까? 나는 내 예에서 그들이 있었다는 것을 압니다.


답변

ASP / JSP 페이지에서 SQL을 사용하지 않는 것과 동일한 이유로 수행합니다.

프레젠테이션 및 도메인 계층에서 사용하기 위해 하나의 도메인 개체 만 유지하면 해당 개체가 곧 모 놀리식이됩니다. UI 유효성 검사 코드, UI 탐색 코드 및 UI 생성 코드가 포함되기 시작합니다. 그런 다음 곧 그 위에 모든 비즈니스 계층 메서드를 추가합니다. 이제 비즈니스 계층과 UI가 모두 섞여 있고 모두 도메인 엔터티 계층에서 엉망이됩니다.

멋진 UI 위젯을 다른 앱에서 재사용하고 싶습니까? 이 이름,이 두 스키마,이 18 개의 테이블로 데이터베이스를 만들어야합니다. 또한 비즈니스 유효성 검사를 수행하려면 Hibernate 및 Spring (또는 선택한 프레임 워크)을 구성해야합니다. 아,이 85 개의 다른 비 관련 클래스도 포함해야합니다. 왜냐하면 그들은 같은 파일에있는 비즈니스 계층에서 참조되기 때문입니다.


답변

동의하지 않습니다.

가장 좋은 방법은 프레젠테이션 레이어의 도메인 개체로 시작하는 것입니다.

대중적인 믿음과는 달리, “도메인 객체”와 “가치 객체”는 프레젠테이션 레이어에서 행복하게 공존 할 수 있습니다. 이것이 최선의 방법입니다. 두 세계의 이점을 누리고 도메인 개체의 중복 (및 상용구 코드)을 줄입니다. 그리고 요청 전반에 걸쳐 가치 객체를 사용하는 맞춤화 및 개념적 단순화.


답변

답변은 응용 프로그램의 규모에 따라 다릅니다.


간단한 CRUD (생성, 읽기, 업데이트, 삭제) 애플리케이션

기본 crud 응용 프로그램의 경우 기능이 없습니다. 엔티티 위에 DTO를 추가하는 것은 시간 낭비입니다. 확장 성을 증가시키지 않으면 서 복잡성을 증가시킬 것입니다.

여기에 이미지 설명 입력


다소 복잡한 Non-CRUD 애플리케이션

이 크기의 응용 프로그램에서는 실제 수명주기와 연관된 비즈니스 논리를 가진 엔터티가 거의 없습니다.

이 케이스에 DTO를 추가하는 것은 몇 가지 이유로 좋은 생각입니다.

  • 프레젠테이션 계층은 엔터티가있는 필드의 하위 집합 만 볼 수 있습니다. 엔티티를 캡슐화합니다.
  • 백엔드와 프런트 런트 간의 결합 없음
  • 엔터티 내부에 비즈니스 메서드가 있지만 DTO에는없는 경우 DTO를 추가하면 외부 코드가 엔터티의 상태를 망칠 수 없습니다.

여기에 이미지 설명 입력


복잡한 엔터프라이즈 애플리케이션

단일 엔티티에는 여러 가지 표현 방법이 필요할 수 있습니다. 각각 다른 필드 세트가 필요합니다. 이 경우 이전 예제에서와 동일한 문제가 발생하고 각 클라이언트에 대해 표시되는 필드의 양을 제어해야합니다. 각 클라이언트에 대해 별도의 DTO를 사용하면 표시 할 항목을 선택하는 데 도움이됩니다.

여기에 이미지 설명 입력


답변

우리는 서버와 UI에서 동일한 모델을 사용하고 있습니다. 그리고 그것은 고통입니다. 언젠가 리팩토링해야합니다.

문제는 주로 도메인 모델을 전체 데이터베이스를 참조하지 않고도 직렬화 할 수 있도록 더 작은 조각으로 잘라야하기 때문입니다. 이로 인해 서버에서 사용하기가 더 어려워집니다. 중요한 링크가 없습니다. 또한 일부 유형은 직렬화 할 수 없으며 클라이언트로 보낼 수 없습니다. 예를 들어 ‘Type’또는 모든 일반 클래스. 제네릭이 아니어야하며 유형은 문자열로 전송되어야합니다. 이것은 직렬화를위한 추가 속성을 생성하며 중복되고 혼란 스럽습니다.

또 다른 문제는 UI의 엔터티가 실제로 적합하지 않다는 것입니다. 우리는 데이터 바인딩을 사용하고 있으며 많은 엔터티에는 UI 용도로만 많은 중복 속성이 있습니다. 또한 엔터티 모델에는 ‘BrowsableAttribute’및 기타 항목이 많이 있습니다. 이것은 정말 나쁘다.

결국 어느 쪽이 더 쉬운 지 문제라고 생각합니다. 잘 작동하고 다른 DTO 모델을 작성할 필요가없는 프로젝트가있을 수 있습니다.


답변

대부분의 경우 종속성에 관한 것입니다. 조직의 핵심 기능 구조에는 자체 기능 요구 사항이 있으며 UI를 통해 사람들이 핵심을 수정하고 볼 수 있어야합니다. 하지만 코어 자체는 UI를 수용하는 데 필요하지 않습니다. (발생해야하는 경우 일반적으로 핵심이 설계되지 않은 자산임을 나타냅니다.)

내 회계 시스템에는 회사 운영을 모델링해야하는 구조와 내용 (및 데이터)이 있습니다. 그 구조는 실제적이고 내가 사용하는 회계 소프트웨어에 관계없이 존재합니다. (어쩔 수없이 주어진 소프트웨어 패키지에는 그 자체를위한 구조와 내용이 포함되어 있지만 문제의 일부는이 오버 헤드를 최소화하는 것입니다.)

기본적으로 사람은 할 일이 있습니다. DDD는 작업의 흐름 및 내용과 일치해야합니다. DDD는 수행해야하는 모든 작업을 최대한 완전하고 독립적으로 명시 적으로 만드는 것입니다. 그런 다음 UI는 가능한 한 투명하고 생산적으로 작업을 수행하는 데 도움이되기를 바랍니다.

인터페이스는 적절하게 모델링되고 변하지 않는 기능적 코어에 대해 제공되는 입력 및보기에 관한 것입니다.