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


85

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

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

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

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

이 질문은 위키에 있어야합니다.
Syed Tayyab Ali

@ m4bwav-하나의 정답이 아닌 토론을 초대하는 방식으로 표현되기 때문에 위키 여야합니다.
Rob Allen

1
@ m4bwav : 귀하의 질문이 실제 질문보다 더 많은 의견 조각으로 나왔다고 생각합니다 ... 나는 그것을 수정하려고 노력했지만 (더 편집하고 싶을 수도 있습니다), 적절한주의 없이는 이것이 나타날 수 있음을 유의하십시오. 트롤링.
Shog9

5
좋아요, 백업, 합법적 인 질문입니다.이게 누구에게 어떻게 불쾌감을 줄까요? 내가 누구를 타겟팅하고 있습니까?
Mark Rogers

@ m4bwav : 당신은 스트로 맨을 표적으로 삼고 있습니다. 귀하의 질문에서이 문제를 논의하는 "많은 사람".
Shog9

답변:


48

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

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


2
"두 위치에 도메인 개체 구현"이란 무엇을 의미합니까?
jlembke

10
이것은 나에게 어리석은 것처럼 보입니다. 향후 작업을 절약 할 수있는 추가 작업을 수행하는 이유는 무엇입니까? 10 번 중 9 번은 작업의 "TONS"를 절약 할 수 있도록 변경할 필요가 없습니다.
경고음

13
@LuckyLindy : 100 점 만점에 99 번 (실제로 그 이상), 안전 벨트를 착용 할 필요는 없습니다. 그러나 내가 정말로 필요로 할 때, 그것은 나를 죽이거나 심하게 다치는 것을 막아 줄 것입니다. 1 온스의 예방은 1 파운드의 치료 가치가 있습니다. 더 많은 경험을 쌓은 후에 이에 대한 귀하의 의견이 바뀔 것이라고 생각합니다.
Paul Sonier

19

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

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

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

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

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

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

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

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


테넌트마다 레이블이 다르면 테넌트마다 다른 유비쿼터스 언어가 표시되지 않습니까? 메타 모델의 해석에 대한 번역 레이어를 가진 테넌트들간에 도메인을 공유하는 메타 모델의 개념이 필요하다고 생각합니다.
Kell

16

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

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

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


13

동의하지 않습니다.

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

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


귀하의 의견에 감사드립니다. 귀하의 출처를 알 수 있습니다. 이것이 성공적인 프로젝트를 만드는 무한한 방법이 아니라는 말은 아니지만, 유지 관리가 더 어려운 더 크고 복잡한 프로젝트를위한 "도메인 기반 디자인"스타일에 반하는 것처럼 보입니다. 장기적으로는.
Mark Rogers

아니요, 이것은 잘못된 것이며 정확히 많은 사이트가 SQL 주입에 취약한 이유입니다.
Remi

7

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


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

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

여기에 이미지 설명 입력


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

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

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

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

여기에 이미지 설명 입력


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

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

여기에 이미지 설명 입력


4

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

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

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

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


2
데이터 바인딩을 사용하려는 경우 linq 쿼리를 실행하고 익명 유형에 바인딩하십시오. 이를 통해 계층 구조를 병합하고 변경할 수 있습니다. 이것으로 필터링 및 정렬을 매우 잘 구현할 수도 있습니다.
JoshBerke

@Josh : 조언을 해주셔서 감사합니다. 이것은 부분적으로 작동 할 수 있습니다. 나는 GUI 프로그래머가 아니며 GUI 개념에 많이 관여하지 않습니다. 문제는 데이터가 조작되어 서버로 다시 전송되는 경우입니다.
Stefan Steinegger

3

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

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

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

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


3

젠장, 나는 이것이 끈기 있다고 맹세 합니다.

어쨌든, 그것은 같은 것의 또 하나의 사례입니다. Parnas의 법칙은 모듈이 비밀을 유지해야한다고 말하고 있으며 비밀은 변경 될 수있는 요구 사항입니다. (Bob Martin에는 이것의 또 다른 버전 인 규칙이 있습니다.) 이와 같은 시스템에서 프레젠테이션도메인과 독립적으로 변경 될 수 있습니다 . 예를 들어, 유로화로 가격을 유지하고 회사 사무실에서 프랑스어를 사용하지만 만다린 텍스트로 가격을 달러로 표시하려는 회사가 있습니다. 도메인은 동일하다; 프레젠테이션이 변경 될 수 있습니다. 따라서 시스템의 취약성을 최소화하기 위해, 즉 요구 사항 변경을 구현하기 위해 변경해야하는 항목의 수를 최소화하려면 우려 사항을 분리해야합니다.


2

프레젠테이션은 도메인 레이어를 참조 할 수 있지만 UI에서 도메인 개체로 직접 바인딩해서는 안됩니다. 도메인 개체는 적절하게 설계된 경우 데이터 표현이 아닌 동작을 기반으로하는 경우가 많기 때문에 UI 사용을위한 것이 아닙니다. UI와 도메인 사이에 매핑 레이어가 있어야합니다. MVVM 또는 MVP는이를위한 좋은 패턴입니다. UI를 도메인에 직접 바인딩하려고하면 많은 골칫거리가 될 것입니다. 두 가지 목적이 있습니다.


1

아마도 당신은 충분히 넓은 용어로 UI 레이어를 개념화하고 있지 않을 것입니다. 여러 형태의 응답 (웹 페이지, 음성 응답, 인쇄 된 편지 등)과 여러 언어 (영어, 프랑스어 등)의 관점에서 생각하십시오.

이제 전화 호출 시스템을위한 음성 엔진이 웹 사이트를 실행하는 컴퓨터 (예 : Windows)와 완전히 다른 유형의 컴퓨터 (예 : Mac)에서 실행된다고 가정합니다.

물론 "우리 회사에서는 영어에만 관심이 있고 LAMP (Linux, Apache, MySQL 및 PHP)에서 웹 사이트를 운영하고 모두가 동일한 버전의 Firefox를 사용합니다."라는 함정에 빠지기 쉽습니다. 하지만 5 년 또는 10 년 후에는 어떨까요?



1

뷰로 작업하는 동안 ' Value Injecter '와 같은 도구와 프레젠테이션 레이어의 ' Mappers '개념을 사용하면 각 코드를 훨씬 더 쉽게 이해할 수 있습니다. 약간의 코드가 있으면 즉시 이점을 볼 수 없지만 프로젝트가 점점 더 커질 때 서비스의 논리에 들어갈 필요가 없도록 뷰로 작업하는 동안 매우 행복 할 것입니다. 보기 모델을 이해하기위한 저장소. View Model은 반부패 계층의 방대한 세계에서 또 하나의 가드이며 장기 프로젝트에서 금으로 가치가 있습니다.

뷰 모델 사용의 이점이없는 유일한 이유는 프로젝트가 모델의 각 속성에 직접 바인딩 될 수있을만큼 작고 단순하기 때문입니다. 그러나 미래에 요구 사항 변경 및 뷰의 일부 컨트롤이 모델에 바인딩되지 않고 뷰 모델 개념이없는 경우 여러 위치에서 패치를 추가하기 시작하고 다음과 같은 레거시 코드를 갖게됩니다. 당신은 감사하지 않을 것입니다. 물론, view-viewmodel에서 view-model을 변환하기 위해 몇 가지 리팩토링을 수행하고 필요하지 않은 경우 코드를 추가하지 않고 YAGNI 원칙을 따를 수 있습니다.하지만 나 자신을 위해 따라야하는 모범 사례입니다. 뷰 모델 객체 만 노출하는 프리젠 테이션 레이어.


1

다음은 도메인 엔터티를 뷰에서 분리하는 것이 좋은 방법을 찾는 이유에 대한 실제 예입니다.

몇 달 전에 일련의 3 게이지를 통해 토양 샘플의 질소, 인 및 칼륨 값을 표시하는 간단한 UI를 만들었습니다. 각 게이지에는 빨간색, 녹색 및 빨간색 섹션이 있습니다. 즉, 각 구성 요소가 너무 적거나 많을 수 있지만 중간에 안전한 녹색 레벨이 있습니다.

별다른 생각없이 저는이 3 가지 화학 성분에 대한 데이터를 제공하기 위해 비즈니스 로직을 모델링하고 3 가지 사례 각각에서 허용되는 수준에 대한 데이터를 포함하는 별도의 데이터 시트 (예 : 몰 또는 백분율)를 사용했습니다. 그런 다음 매우 다른 모델을 사용하도록 UI를 모델링했습니다.이 모델은 게이지 레이블, 값, 경계 값 및 색상을 고려했습니다.

이것은 나중에 12 개의 구성 요소를 표시해야했을 때 추가 데이터를 12 개의 새로운 게이지 뷰 모델에 매핑하고 화면에 나타남을 의미했습니다. 또한 게이지 컨트롤을 쉽게 재사용하고 다른 데이터 세트를 표시 할 수 있다는 의미이기도합니다.

이 게이지를 내 도메인 엔터티에 직접 연결했다면 위의 유연성을 갖지 못했을 것이며 향후 수정은 골칫거리가 될 것입니다. UI에서 캘린더를 모델링 할 때 매우 유사한 문제가 발생했습니다. 참석자가 10 명 이상일 때 일정 약속이 빨간색으로 바뀌어야한다는 요구 사항이있는 경우이를 처리하기위한 비즈니스 논리는 비즈니스 계층에 남아 있어야하며 UI의 모든 일정은 빨간색으로 변하면 이유를 알 필요가 없습니다.


-1

일반화 된 의미 체계와 도메인 별 의미 체계 사이에 추가 매핑을 추가하는 유일한 이유는 도메인 의미 체계와 구별되는 일반화 된 (그러나 매핑 가능한) 의미 체계를 기반으로하는 기존 코드 (및 도구) 본문이 있기 때문입니다.

도메인 중심 설계는 ORM, GUI, 워크 플로 등의 직교 기능 도메인 프레임 워크 집합과 함께 사용할 때 가장 잘 작동합니다. 도메인 의미론이 노출되어야하는 것은 외부 계층 인접성에만 있음을 항상 기억하십시오. 일반적으로 이것은 프런트 엔드 (GUI) 및 영구 백엔드 (RDBM, ORM)입니다. 효과적으로 설계된 중간 계층은 도메인 불변이 될 수 있으며 그래야합니다.


para 1 : 별개의 앱간에 실제로 공유하지 않는 한 불필요한 추상화 (예 : 재사용 가능한 구성 요소)를 생성하지 마십시오. para 2 : 일반 GUI가 여러 도메인에서 어떻게 작동하는지 궁금합니다. 비고 :이 산업은 너무
무너져서
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.