2012-04-11 2 views
27

Morphia 및 Hibernate와 같은 지속성 프레임 워크는 도메인 객체에 대한 주석을 사용하여 마법을 실현합니다. 어떤 수준에서는 도메인 계층에 지속성 문제를 삽입하는 것으로 보입니다.이 도메인 계층은 피하기 위해 노력해야한다고 생각합니다.도메인 객체의 영속성 주석은 나쁜 습관입니까?

아마도 외부 구성 파일을 사용하거나 도메인 모델에서 DTO를 분리하여 피하려고 시도해야 할 것입니까? 또는 일반적으로 허용되는 것으로 간주되는 지속성 및 도메인 계층 사이의 작은 누출이 있습니까?

+2

이 프레젠테이션보기 http://www.infoq.com/presentations/Clean-Model-Tim-McCarthy – MikeSW

+0

감사합니다. 이것은 훌륭한 프리젠 테이션입니다! 지금보고있는 것 ... – HolySamosa

답변

12

Spring과 Hibernate를 사용하는 기존 시스템의 최신 반복에서 유사한 문제로 이동하기 시작했습니다. Hibernate 모델을 처음으로 구현할 때, 나는 서비스 클래스의 애플리케이션 로직을 데이터 액세스 객체를 통해 퍼시스턴스 로직과 분리하려고 노력했다. 작년에 새로운 시스템을 만들 때, 대부분의 영속성 객체가 도메인 객체로 사용되도록 허용했습니다. 이는 편의상 솔루션 이었기 때문입니다.

그러나 변화하는 비즈니스 요구 사항에 비추어이 동일한 시스템을 다시 설계하고 있으며, 나는 이러한 우려를 분리하는 방향으로 다시 기울어 져 있습니다. 새 디자인을 시작한 지 며칠 밖에되지 않았지만, 이미 인 - 메모리 관련 객체를 나타내는 객체 하나와 데이터베이스에 상태 변경 사항을 저장하는 데 별도의 지속성 기반 객체를 사용하는 편이 더 좋습니다. 예를 들어, 지속성을 위해 Lead을 가지고 있고, 트랜잭션을 가로 질러 살아있는 병렬 인 ActiveLead을 가지고 있습니다.

아직까지는 이것이 최선의 방법이라고 확신하지는 못하지만, 직감 수준에서는 의미가 있습니다. 난 지속성에 의존하지 않는 컬렉션을 원했고 - 영속성 - 무지한 - 표준 CRUD 단순화에 관계없이 데이터베이스 트랜잭션에서 메모리 상주 상태로 남아있는 객체 세트. 그러나 나는 결국 모든 데이터베이스 작업이 CRUD로 구현된다는 것을 이해합니다. 두 세계가 충돌해야하며,이 트릭은 조화롭게 춤을 추고 있습니다.

도메인 객체에 대한 Hibernate 어노테이션? 이는 구현의 용이함과 유지 관리의 용이함 사이의 훌륭한 절충안입니다.

+2

이것은 또한 지속성 객체와 메모리 내 상태의 상태에 대해보다 엄격하고 덜 엄격 할 수있는 기회를 제공합니다. 나는 인터페이스의 입력과 출력을 극도로 잘 인식하려고 노력하며 이러한 방식으로 이러한 우려를 분리하는 것은 가능합니다. – alexwen

4

제 생각에는 도메인 객체를 복제하여 퍼시스턴스 레이어에서 분리 할 필요가 없습니다. 그것은 중복 된 코드를 사용하며 DTO와 같은 객체를 사용하면 완벽하게 수행 할 수 있습니다. 필요하다면 필요하다면 항상 별도의 수업을 사용할 수 있지만, 엄지 손가락으로 만들지는 않을 것입니다. 시간이 걸리므로 시간이 가치 있다는 것을 압니다.

+3

나는 동의하지 않는다. 도메인 객체는 퍼시스턴스 모델 객체와 본질적으로 다르며 목적이 다릅니다. 때로는 도메인이 실제로 domin이 아니고 영속성 엔티티가 직접 사용될 수 있다면, 이는 간단한 우연 일 뿐이며 구현 세부 사항입니다. 아이디어는 도메인의 모델링을 시작하고 함께 지속성을 무시한다는 것입니다. 최근에 나는이 상황에 대해 정확히 블로깅했다. http://www.sapiensworks.com/blog/post/2012/04/07/Just-Stop-It!-The-Domain-Model-Is-Not-The-Persistence-Model. aspx – MikeSW

+0

@MikeSW 내 경험에 의하면 도메인 객체와 테이블은 그다지 다르지 않습니다. 오지 않는 차이점은 ORM의 사용자 지정 옵션을 통해 쉽게 번역 할 수 있어야합니다. 내 의견으로는, 좋은 ORM은 이것을 쉽게하는 데 도움이 될 것입니다. – Timo

+0

@MikeSW와 그의 블로그 게시물에 완전히 동의합니다. 예를 들어 ORM 요구 사항을 만족시키기 위해 도메인 모델에 추한 getters/setter를 사용하도록 강요 받고 싶지는 않습니다. 내 도메인 모델이 지속성의 세계에서 어떤 제약없이 부끄러워하기를 바랍니다. – Mik378

7

저는 최근에 분리 된 퍼시스턴스 레이어가있는 비교적 복잡한 시스템에서 작업했습니다. 엉덩이에 큰 고통이 있었고 유지 관리가 어려웠습니다. 기본적으로 YAGNI의 원칙과 Single Responsibility의 원칙이 서로 상충됩니다. 내 의견으로는, YAGNI는 더 중요한 것 (아아, 더 자주 무시되는 것)이기도합니다.

나는 대부분의 경우에 말할 것

, 당신이 구체적인 요구 사항이없는 한 지속성 엔티티를 강제 다르게 구성 할, 당신은 ORM을 사용하는 경우 도메인 객체를 직접 유지하는 것이 훨씬 낫다 (그들이 경우 똑같은 구조를 가졌다면 상아탑 주장을 제외하고는 그것들을 분리 할 이유가 없다.)

항상은 별도의 서비스/DAO 계층에서 실제 지속성 항목 (ORM 기능 호출)을 수행합니다! 그렇게하면 나중에 필요할 때 지속성 레이어를 쉽게 도입 할 수 있습니다.

+1

동일한 개체를 사용하는 데 문제가있는 경우는 여러 스레드/서버에서 낙관적으로 잠금을 설정하는 것입니다. 예를 들어'firstName'에 변경 사항을 저장하려고 시도하고 다른 누군가가 객체를 변경했다는 것을 알게되면 변경을 위해 객체를 다시로드해야합니다. 새로로드되고 수정 된 객체를 도메인 객체 트리에 어떻게 다시 삽입합니까? –

+2

아래로 투표 한, 나는 동의하지 않는다. 언급 된 주석이 너무 많아서 여러 번 클래스 구조를 다른 방향으로 강제하는 경향이있는 너무 많은 관심사와 동작이 클래스를 읽기 및 유지 관리하기가 어렵고 나쁜 것입니다. – dalvarezmartinez1

+0

@dalvarezmartinez - 주석이 데이터 지속성 문제뿐만 아니라 도메인 관련 문제로 사용되는 경우 어떻게해야합니까? 예를 들면 : 도메인 객체의'Name' 속성을'[Required]'로 표시하면 필드가 필수라는 것을 분명히 알 수 있습니다. 또한 유효성 검사 레이어 DB 레이어에 null 값을 허용해서는 안됨을 알립니다. – Sam

3

짧은 답변 : 나는 지속적이고 풍부한 도메인 개체를 좋아합니다.

긴 대답 : 나는 봄과 최대 절전 모드를 사용하여 상당히 큰 시스템 ~ 50 만에 LOC에 근무 거의 10 년 동안

. 처음에는 우리가 Hibernate를 아주 신뢰하지 않았기 때문에 부분적으로 "트랜잭션 스크립트"(Fowler 참조) 접근 방식으로 시작했습니다. 그러나 잠깐 동안 우리는 Hibernate를 신뢰하게되었고 상당히 초기의 OO에 대한 훨씬 이전의 훈련으로 인해 나는 Domain Driven Design 접근법과 결합 된 일시적인 영속성을 크게 믿었습니다. 우리는 기본적으로 우리 시스템이 ODBMS (작은 누수가 많은 :-)로 뒷받침되는 것으로 생각하게되었습니다.

저는 DDD라는 책이 아직 작성되지 않았기 때문에이 아키텍처를 "도메인 커널"이라고 불렀습니다. 이것은 Hibernate 초기에 있었으므로 도메인 모델은 주석으로 오염되지 않았습니다. 지속성에 대한 별도의 관심은 XML 매핑에서 별도로 유지되었습니다.

시간이 흐르면서 동작을 도메인 계층으로 푸시하는 것이 좋습니다. 우리는 꽤 전통적인 컨트롤러 -> 서비스 -> dao -> 도메인 계층화 구성표를 컴파일 타임 의존성으로 시행했습니다. 시간이 지남에 따라 관찰 된 것은이 모델이 계획 설정, 거래, 회계, 컴플라이언스 테스트, 판매, 브랜딩 등을 포함한 401 (k) 계획 관리의 상당히 복잡한 영역의 모든면을 대표하는 시스템에서 매우 잘 작동한다는 것입니다. (상대적으로) 투명한 "마술"지속성을 지닌 풍부한 도메인 모델은 도메인 모델의 기존 기능과 관련하여 새로운 기능을 구축 할 수 있었던 핵심 요소였습니다.

우리의 서비스 계층은 기술 서비스 (예 : 전자 메일, 파일 I/O, 큐 등) 간의 상호 작용을 조정하고 필요한 경우 도메인 패키지를 확장하는 데 도움이되었습니다. 서비스 계층은 또한 트랜잭션 경계를 정의했다 (Spring을 통해). 서비스는 DTO 또는 프리미티브를 수신 또는 방출합니다. DRY의 중단으로 많은 사람들이 그것을 싫어하지만 서비스 인터페이스와이를 사용하는 코드를 정의 할 때 정직하게 생각하고 있습니다. 나중에 원격지에서도 매우 쉽게 사용할 수 있습니다.

이 접근 방식으로 우리는 꽤 작은 팀 (우리는 스크럼 팀이었습니다)과 함께 고품질의 소프트웨어를 만들 수있었습니다.

따라서 영구 도메인 객체를 믿는 사람이라고 생각해보십시오. 내 이야기가 도움이되는지 모르겠지만 공유하고 싶었습니다.

9

도메인 객체의 영속성 주석은 좋지 않습니까?

. NoSQL이 등장하면서 단일 지속성 전략에 의존 할 수 없습니다.

예를 들어, 오늘은 내 도메인 객체 (morphia 사용)를 MongoDB에 유지하고 있습니다. 내일 도메인 개체를 Neo4j으로 유지 하시겠습니까?

또는 도메인 개체를 관계형 (Postgres/MySQL), MongoDB (문서 저장소) 및 평가 용 Neo4J (그래프 데이터베이스)와 같은 3 가지 데이터베이스 모두에 유지하고자 할 수 있습니다. 도움이 될 전략 패턴으로 영구 전략을 전달 : 모든 경우에

, 더는 도메인에 의존하는

모범 사례 객체보다는 별도의 지속성 전략을 가지고있다. 그러나 클래스/객체를 설계 할 때주의해야합니다.

+0

나는 "if ... if ..."질문이 너무 많다고 생각합니다. 나는 데이터베이스를 변경하지 않고 추가 모듈/mapper 등의 유지 비용을 희생 할 수있는 단일 모듈에서 세 가지 다른 db 기술을 사용하는 프로젝트를 보지 않았습니다. 내 경험상 프로젝트는 간단히 주석으로 처리하는 대신이 접근법으로 시작하는 것이 훨씬 더 어렵습니다. 도메인 계층 – thilko

+0

@thilko 나는 당신이 공정하게 말하면, 실질적으로 말하기를.그럼에도 불구하고 이것은 ** 특히 DDD 및/또는 TDD와 관련하여 ** 저장소 패턴 **과 함께 지속성 프레임 워크를 적용하는 것이 더 쉽게 만들어 져야한다고 결론 내릴 수 있습니다. – Timo

0

어노테이션이있는 리치 도메인 오브젝트를 선호합니다.에반스도이 방법을 그의 sample app에서 사용합니다. 그는 Annotations 대신 XMl을 사용하지만 여전히 동일한 객체를 유지합니다.

아마도 도메인과 지속성을 분리하는 것이 더 깨끗 할 수도 있지만 나중에 다른 db 기술을 잠재적으로 선택할 수는 없어도됩니다. 그것은 복잡한 지옥에 이르는 길이고 YAGNI 씨는 당신을 물 것입니다.

4

내가 사용하려는 지속성 프레임 워크로 이미 결정된 경우 내 도메인에서 특수 효과를 사용 하겠지만 XML은 Hexagonal 아키텍처와 TDD를 따르면 더 편리 할 것입니다. 도메인에 특정 프레임 워크를 주석으로 추가하는 경우 지속성 통합과 결합하여 기술/프레임 워크에 무관심한 목표로 핵심 기능을 테스트 할 수 없습니다.

관련 문제