일반 Old CLR 개체와 데이터 전송 개체


405

POCO = 일반 Old CLR (또는 그 이상 : Class) Object

DTO = 데이터 전송 객체

게시물 에는 차이점이 있지만 필자가 읽은 대부분의 블로그는 DTO가 정의 된 방식으로 POCO를 설명합니다. DTO는 응용 프로그램 계층간에 데이터를 이동하는 데 사용되는 간단한 데이터 컨테이너입니다.

POCO와 DTO는 같은 것입니까?


5
"POCO = 일반 Old CLR (또는 그 이상 : 클래스) 개체" 따라서 VB.NET에서 이러한 특성의 개체는 POVO가 아니라 POCO이기도합니다.
J. Polfer 2016 년

답변:


568

POCO는 OOP의 규칙을 따릅니다. 상태 행동 이 있어야합니다 (그러나 반드시 그런 것은 아닙니다) . POCO 마틴 파울러 [화폐로 주조 POJO에서 온다 일화 여기 ]. 그는 프레임 워크가 많은 EJB 구현을 거부하는 것을보다 섹시하게 만드는 방법으로 POJO라는 용어를 사용했습니다. POCO는 .Net의 동일한 컨텍스트에서 사용해야합니다. 프레임 워크가 객체의 디자인을 지시하지 않도록하십시오.

DTO의 유일한 목적은 상태를 이전하는 것이며 행동이 없어야합니다. 이 패턴의 사용 예는 Martin Fowler의 DTO 설명을 참조하십시오 .

차이점은 다음과 같습니다. POCO는 프로그래밍에 대한 접근 방식 (좋은 구식 객체 지향 프로그래밍)을 설명합니다. 여기서 DTO는 객체를 사용하여 "데이터를 전송"하는 데 사용되는 패턴 입니다.

POCO를 DTO처럼 취급 할 수는 있지만 빈 도메인 모델 을 만들 경우 위험이 따릅니다 . 또한 DTO는 비즈니스 영역의 실제 구조를 나타내지 않고 데이터를 전송하도록 설계되어야하므로 구조가 일치하지 않습니다. 그 결과 DTO는 실제 도메인보다 평평한 경향이 있습니다.

합리적으로 복잡한 도메인에서는 별도의 도메인 POCO를 만들어 DTO로 변환하는 것이 좋습니다. DDD (도메인 기반 디자인)는 부패 방지 계층 ( 여기 다른 링크 이지만 책을 구입하는 것이 가장 좋습니다 )을 정의합니다 . 이는 분리를 명확하게하는 좋은 구조입니다.


나는 여기서 Martin Fowler를 많이 언급했지만 POJO라는 용어를 만들었고 DTO에 대한 명확한 참조 인 PoEAA 책을 썼습니다.
Michael Meadows

DTO에 행동이 없어야할지 모르겠습니다. Martin Fowler의 다이어그램으로 판단하면 DTO에 행동이있을 수 있습니다.
Beatles1692

39
@ Beatles1692에서 묘사 된 방법은 직렬화 코드입니다. 아마도 "행동이 없다"고 말하기에는 너무 광범위합니다. "비즈니스 로직 없음"은 어떻습니까? 직렬화 코드 및 해시 코드, 동등성 및 tostring과 같은 저수준 객체는 허용됩니다.
Michael Meadows

1
@PositiveGuy 모델은 DTO와 다른 용도로 사용됩니다. DTO는 한 도메인에서 다른 도메인으로 데이터를 전송하기위한 것이어야합니다 (동일한 런타임에 있는지 여부에 관계없이). 모델은 화면, 서비스 또는 데이터 소스와 같은 도메인의 측면을 "나타냅니다". 모델에는 모델링 대상을 나타내는 상태 및 동작이 포함됩니다.
Michael Meadows

2
특히 앱이 대부분 CRUD 인 경우 빈혈 도메인 모델이 반드시 나쁘지는 않습니다. Martin Fowler보다 단순성을 선호하십시오.
Mariusz Jamro

50

내 블로그 기사에서 내 입장을 이미 언급 한 이후에 기여하는 것은 아마도 중복 일 수 있지만, 그 기사의 마지막 단락이 요약됩니다.

결론적으로 POCO를 사랑하는 법을 배우고 DTO와 같은 것에 대해 잘못된 정보를 퍼 뜨리지 않도록하십시오. DTO는 응용 프로그램 계층간에 데이터를 이동하는 데 사용되는 간단한 데이터 컨테이너입니다. POCO는 본격적인 비즈니스 객체로, 지속성 무지 (하나 이상의 저장 방법이 없음)라는 하나의 요구 사항이 있습니다. 마지막으로, 지미 닐슨 (Jimmy Nilsson)의 책을 아직 체크 아웃하지 않았다면, 해당 지역의 대학 스택에서 픽업하십시오. C #에 예제가 있으며 잘 읽습니다.

BTW, Patrick 저는 POCO를 라이프 스타일 기사로 읽었으며 완전히 동의합니다. 환상적인 기사입니다. 실제로 내가 추천 한 Jimmy Nilsson 책의 섹션입니다. 온라인에서 사용할 수 있다는 것을 몰랐습니다. 그의 책은 실제로 POCO / DTO / Repository / 및 기타 DDD 개발 사례에서 찾은 최고의 정보원입니다.


4
블로그 기사 링크 : rlacovara.blogspot.com/2009/03/…
Jamie Ide

28

POCO는 단순히 외부 프레임 워크에 의존하지 않는 객체입니다. 평야입니다.

POCO의 행동 여부는 중요하지 않습니다.

DTO는 도메인 객체 (일반적으로 동작이 풍부한)와 마찬가지로 POCO 일 수 있습니다.

일반적으로 DTO는 일반적으로 시스템의 경계를 벗어나는 직렬화 목적으로 외부 프레임 워크 (예 : 특성)에 종속 될 가능성이 높습니다.

일반적인 양파 스타일 아키텍처 (종종 광범위하게 DDD 방식으로 사용됨)에서 도메인 레이어는 중앙에 배치되므로이 시점에서 객체의 레이어 외부에 종속성이 없어야합니다.



6

DTO가 POCO가 될 수 있다고 생각합니다. DTO는 객체 사용에 관한 것이지만 POCO는 객체의 스타일에 가깝습니다 (건축 개념과 분리됨).

POCO가 DTO와 다른 한 가지 예는 도메인 모델 / 비즈니스 로직 모델 내부에서 POCO에 대해 이야기 할 때입니다. 이는 문제 도메인의 멋진 OO 표현입니다. 전체 응용 프로그램에서 POCO를 사용할 수 있지만 지식 유출과 같은 바람직하지 않은 부작용이 발생할 수 있습니다. DTO는 예를 들어 UI와 통신하는 서비스 계층에서 사용되며 DTO는 데이터를 평평하게 표현하며 UI에 데이터를 제공하고 변경 사항을 서비스 계층으로 다시 전달하는 데만 사용됩니다. 서비스 계층은 DTO의 두 가지 방법을 POCO 도메인 개체에 매핑하는 역할을합니다.

업데이트 마틴 파울러는 말했다 이 방법을 취할 무거운 도로이며, 도메인 층과 사용자 인터페이스 사이에 상당한 불일치가있는 경우에만 수행되어야한다.


2
@David Landman, 포함 된 링크는 로컬 DTO 패턴을위한 것이며, 이는 시스템 경계 내에서 DTO가 전송 상태에 사용되는 경우입니다. 이 경우 시스템 내에 공유 할 수있는 잘 정의 된 도메인이 있어야하므로 매우주의해야합니다. 시스템 경계를 넘어 상태를 전송할 때 DTO는 피하기 어렵고 모든 경우에 매우 적합합니다.
Michael Meadows

@Michal Meadows, 그렇습니다. 링크는 실제로 문제의 다른 하위 집합에 대해 이야기합니다. 그러나 시스템 경계를 넘어 상태를 이전하는 경우 변환 서비스를 사용하여 한 컨텍스트에서 다른 컨텍스트의 POCO로 POCO를 맵핑해야한다고 생각합니다. 아니면 시스템 수준에서 경계에 대해 이야기하고 있습니까?
Davy Landman

1

DTO의 기본 사용 사례는 웹 서비스에서 데이터를 반환하는 것입니다. 이 경우 POCO와 DTO는 동일합니다. 웹 서비스에서 POCO를 반환하면 POCO의 모든 동작이 제거되므로 동작이 있는지 여부는 중요하지 않습니다.


5
당신의 대답은 약간의 일이 잘못되었다고 생각합니다. 웹 서비스의 경우, 객체의 노출 된 상태에 기초하여 프록시가 생성됩니다. 이는 POCO와 동일한 공개 상태를 갖는 POTO와 별도로 DTO가 생성됨을 의미합니다. 미묘 해 보일 수도 있지만 중요합니다. 그 이유는 프록시가 원본과 동일하더라도 실제로 동일한 클래스로 구성되지 않았기 때문입니다.
Michael Meadows

아뇨 하나는 DTO를 사용하여 계층 (이 경우 웹 서비스) 사이에서 데이터를 리턴 / 수신합니다. 데이터 만 있고 행동이 없기 때문에 DTO를 선택합니다. 프록시 클래스도 DTO 일 가능성이 있으며, 대신 POCO 클래스를 사용한 경우 프록시가 작성되었을 것입니다. 그러나이 경우 POCO 클래스는 사실상 DTO입니다. 왜냐하면 동작이 변환되지 않기 때문입니다. 나는 여전히 존재하지 않는 행동을 놓치지 않기 때문에 DTO를 사용한다고 말합니다.
John Saunders

5
** 의미 상 : 웹 서비스는 WSDL을 사용하여 객체 상태 백을 노출합니다. 이것들로부터 프록시가 생성됩니다. 여기에는 동작이 포함될 수 없습니다. 웹 서비스를 사용하는 경우 개체와 노출 된 도메인 개체 간의 유일한 관계는 검사를 기반으로 생성 된 동일한 공개 상태를 갖는 것입니다.
Michael Meadows

7
@ 존, 당신이 과잉 반응하고 있다고 생각합니다. 나는 당신이 옳다고 말하고 있지만 당신의 말은 오도합니다. "이 경우 POCO와 DTO는 동일합니다." 의미 상으로는 그렇지 않습니다. POCO는 DTO로 사용될 수 있지만 그 반대의 경우도 마찬가지입니다. 그렇다고해서 자동차와 픽업 트럭이 동등하지는 않습니다. 그것들은 겹치는 기능을 가지고 있지만, 식료품 여행의 상황에서도 통찰력이 F350과 동일하다는 것을 누군가에게 알려주 기란 쉽지 않습니다.
Michael Meadows

3
이 답변은 매우 잘못되었습니다. 웹 서비스는 일반적인 것이 아닙니다. 가장 중요한 것은 DTO가 POCO가 아니라는 것이 잘 확립 된 사실입니다. DTO는 데이터 컨테이너 인 반면 POCO는 속성으로서 개체이며 지속성에 무관합니다 (get 또는 save 메소드 없음).
Tom Stickel

1

일반적인 규칙은 다음과 같습니다. DTO == 악성 및 과도하게 엔지니어링 된 소프트웨어의 지표. POCO == 좋습니다. '기업'패턴은 Java EE 세계에서 많은 사람들의 두뇌를 파괴했습니다. .NET에서 실수를 반복하지 마십시오.


7
좀 더 자세히 설명해 주시겠습니까? 계약에서 구현 및 플랫폼 특정 사항을 피하기 위해 웹 서비스에서 데이터를 반환 할 때는 DTO가 필요합니다.
John Saunders

1
그렇습니다. John DTO는 여러분이 말하고 잘하는 것을 위해 고안되었습니다. 그러나 불행히도 단일 계층 웹 앱에서 필요하지 않을 때 종종 사용되며 가치가 거의 없습니다.
크레이그

9
@drscroogemcduck, DTO는 마지막 수단이 아닌 첫 번째 수단으로 사용되기 때문에 DTO를 싫어할 수도 있지만, 악명 높은 것은 아닙니다 . 사악한 것은 개발자의 목을 프레임 워크에 밀어 넣어 모든 것을위한 DTO를 만들도록 설계 한 건축가입니다. 그들이하는 일에 대해, 데이터 전송, DTO (정확하게 수행 된 경우)는 완벽하게 적합합니다.
Michael Meadows

0

DTO 클래스는 다른 소스의 데이터를 직렬화 / 직렬화하는 데 사용됩니다. 소스에서 객체를 직렬화 해제하려면 서비스, 파일, 데이터베이스 등 외부 소스가 중요하지 않습니다. 서비스의 일부만 사용하고 싶을 수도 있지만 데이터를 직렬화 해제하는 쉬운 방법을 원할 수도 있습니다. 목적. 그런 다음 사용하려는 XModel에 해당 데이터를 복사합니다. 시리얼 라이저는 DTO 객체를로드하는 아름다운 기술입니다. 왜? 객체를로드 (직렬화)하는 함수는 하나만 필요합니다.


0

TL; DR :

DTO는 상태 이전 패턴을 설명합니다. POCO는 아무것도 설명하지 않습니다. OOP에서 "객체"를 말하는 또 다른 방법입니다. 마틴 파울러 (Martin Fowler)가 공동으로 만든 POJO (Java)에서 유래 한 것입니다.

DTO는 해당 계층간에 상태를 전송하는 데 사용되는 객체 패턴입니다. 동작이 상태를 변경하지 않는 한 동작 (기술적으로는 포코 일 수 있음)을 가질 수 있습니다. 예를 들어, 직렬화되는 메소드가있을 수 있습니다.

POCO는 평범한 대상이지만 '평범한'이라는 의미는 특별하지 않다는 것입니다. 암시적인 패턴이없는 CLR 객체라는 의미입니다. 일반적인 용어. 다른 프레임 워크에서는 작동하지 않습니다. [JsonProperty]예를 들어 POCO에 속성 또는 EF 장식 이 있으면 POCO가 아니라고 주장합니다.

다음은 비교할 다양한 종류의 객체 패턴에 대한 몇 가지 예입니다.

  • 뷰 모델 : 뷰의 데이터를 모델링하는 데 사용됩니다. 일반적으로 바인딩 및 유효성 검사를 지원하는 데이터 주석이 있습니다. MVVM에서는 컨트롤러 역할도합니다. 그것은 DTO 이상입니다
  • Value Object : 값을 나타내는 데 사용
  • 집계 루트 : 상태 및 불변량을 관리하는 데 사용
  • 처리기 : 이벤트 / 메시지에 응답하는 데 사용
  • 속성 : 교차 절단 문제를 해결하기 위해 장식으로 사용
  • 서비스 : 복잡한 작업 수행
  • 컨트롤러 : 요청 및 응답의 흐름을 제어하는 ​​데 사용
  • 팩토리 : 생성자가 충분하지 않을 때 사용하기 위해 복잡한 객체를 구성 및 / 또는 조립하는 데 사용됩니다. 또한 런타임에 어떤 오브젝트를 작성해야하는지 결정하는 데 사용됩니다.
  • 리포지토리 / DAO : 데이터 액세스에 사용

이것들은 모두 단지 객체이지만, 대부분은 일반적으로 패턴에 연결되어 있습니다. 그래서 당신은 그것들을 "객체"라고 부르거나 그것의 의도에 대해 더 구체적이고 그것을 무엇인가에 의해 그것을 부를 수 있습니다. 이것이 우리가 디자인 패턴을 갖는 이유이기도합니다. 몇 가지 작품에서 복잡한 개념을 설명합니다. DTO는 패턴입니다. 집계 루트는 패턴이고 뷰 모델은 패턴입니다 (예 : MVC & MVVM). POCO는 패턴이 아닙니다.

POCO는 패턴을 설명하지 않습니다. OOP에서 클래스 / 객체를 참조하는 다른 방법 일뿐입니다. 그것을 추상적 인 개념으로 생각하십시오. 그들은 무엇이든 언급 할 수 있습니다. IMO는 단방향 관계가 있지만 일단 객체가 한 가지 목적 만 깔끔하게 제공 할 수있는 지점에 도달하면 더 이상 POCO가 아닙니다. 예를 들어 클래스를 일부 프레임 워크에서 작동하도록 장식으로 마크 업하면 더 이상 POCO가 아닙니다. 따라서:

  • DTO는 POCO입니다
  • POCO는 DTO가 아닙니다
  • 뷰 모델은 POCO입니다
  • POCO는 뷰 모델이 아닙니다

이 둘을 구별하는 요점은 패턴을 명확하고 일관되게 유지하여 문제를 해결하지 않고 긴밀한 커플 링을 유도하는 것입니다. 예를 들어, 상태를 변경하는 메소드가있는 비즈니스 오브젝트가 있지만 API 엔드 포인트를 통해 다시 보낼 수 있도록 SQL Server 및 JsonProperty에 저장하기 위해 EF 데코레이션으로 지옥으로 장식되었습니다. 이 객체는 변경이 허용되지 않으며 다양한 속성 (예 : UserId, UserPk, UserKey, UserGuid)으로 인해 흩어질 수 있습니다. 여기서 일부는 DB에 저장되지 않도록 표시되고 다른 일부는 직렬화되지 않은 것으로 표시됩니다. API 엔드 포인트의 JSON).

그래서 만약 당신이 무언가 DTO라고 말한다면, 아마도 그것이 상태를 움직이는 것 이외의 다른 용도로 사용되지 않았는지 아마 확신 할 것입니다. 뷰 모델이라고 말하면 데이터베이스에 저장되지 않았는지 확인합니다. 도메인 모델이라고 말하면 도메인 외부에 의존하지 않는지 확인합니다. 그러나 당신이 나에게 뭔가 POCO라고 말하면, 당신은 나에게 전혀 말하지 않을 것입니다.


-13

그들을 DTO라고 부르지 마십시오. 그것들은 Models .... Period 라고 불립니다 . 모델에는 동작이 없습니다. 이 바보 같은 용어 DTO를 누가 만들 었는지 모르겠지만 .NET이어야합니다. MVC의 뷰 모델을 생각해보십시오. 같은 댐 **의 모델은 서버간에 또는 와이어 기간 동안 계층간에 상태를 전송하는 데 사용되며 모두 모델입니다. 데이터가있는 속성. 이들은 와이어를 통과시키는 모델입니다. 모델, 모델 모델. 그게 다야.

어리석은 용어 DTO가 우리의 어휘에서 사라지기를 바랍니다.


1
나는 모델에 결코 행동이 없다는이 아이디어를 어디서 얻었는지 모른다. 모델링 동작없이 CRUD 이외의 것을 어떻게 모델링합니까? ViewModel조차도 많은 경우, 특히 MVVM 앱에서 동작합니다. DTO는 목적을 정확하게 설명하기 때문에 유용한 용어입니다. 데이터를 전송합니다.
Gerald

9
사실 부정확하고 위태로운 태도에 대해
joedotnot

무의미한 말. 모델은 어리석은 용기 여야합니다. DTO는 없으며 MS 구성 용어입니다. 도메인, 서비스 및 앱간에 모델을 전송합니다. 기간. DTO는 필요하지 않으며 용어를 더 혼란스럽게 만드는 용어 낭비입니다. 모델, 모델 및 더 많은 모델입니다. 모델에는 동작이있을 수도 있고 없을 수도 있습니다. 뷰 모델은 안됩니다. 이 동작은 Model 클래스가 아닌 BL에 있어야합니다.
PositiveGuy

나는 DTO가 기능적으로 모델이라는 것에 동의합니다. ViewModel에는 동작이 있으며 MVVM에서 바인딩하는 것입니다. 그러나 내 모델이 더 지능적이고 (기본적으로 VM이지만 호출하기를 원하지 않는) 앱이 DTO 객체를 "수락"하는 앱을 작성했습니다. 이를 통해 프레임 워크에 더 많은 옵션을 제공 할 수있었습니다. 따라서 CRUD (또는 EF)에서 WCF 서비스를 통해 객체를 전송하고 DTO 객체를 수신하고 캡슐화합니다 (OnProp Change 추가 등). 내 ViewModel은 추가 캡슐화를 수행했으며 "모델"중 두 개 (또는 목록)를 허용했을 수 있습니다. 엄격한 정의는 VM입니다.
SQLMason

"도메인, 서비스 및 앱간에 모델을 전송합니다."설명하는이 동작에 대해 모델이라는 용어가 DTO라는 용어보다 더 적절하고 적합하다고 생각하는 이유는 무엇입니까?
caa
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.