비즈니스 개체-컨테이너 또는 기능?


19

이것은 SO에 대해 잠시 물었던 질문이지만 여기서 더 잘 논의 될 수 있습니다 ...

내가 일하는 곳에서, 우리는이 주제에 대해 여러 번왔다 갔다하고 위생 검사를 찾고 있습니다. 질문은 다음과 같습니다. Business Objects가 DTO 와 같은 데이터 컨테이너 이거나 해당 오브젝트에서 일부 기능을 수행 할 수있는 논리도 포함해야합니다.

예-고객 객체를 가져 오십시오. 고객 객체에 함수 (Save, Calc 등)도 포함되어야하는 공통 속성 (Name, Id 등)이 포함되어 있습니까?

한 가지 추론은 개체를 기능 (단일 책임 주체)과 분리하고 해당 기능을 Business Logic 계층 또는 개체에 넣는다 고 말합니다.

다른 추론 라인은 아니요, 고객 객체가 있으면 Customer.Save를 호출하고 완료하기를 원한다고 말합니다. 객체를 소비하는 경우 고객을 구하기 위해 다른 클래스에 대해 알아야하는 이유는 무엇입니까?

우리의 마지막 두 프로젝트는 객체와 기능을 분리했지만 새로운 프로젝트에 대한 논쟁이 다시 제기되었습니다.

어느 것이 더 의미가 있고 왜?


1
프로젝트에 대해 더 자세히 말씀해 주시겠습니까? 프로젝트의 성격에 따라 어떤 솔루션이 더 나은지 결정할 것입니다.

답변:


5

고객이 도메인 모델의 일부라고 생각하는 경우 해당 오브젝트에 대한 특성과 조작을 모두 갖는 것이 (특히 DDD의 컨텍스트 내에서) 의미가 있습니다.

그러나 그것이 말한 것처럼, 나는 당신이 사용한 예제가 좋지 않은 것이며, 주장의 원인이라고 생각합니다. 지속성에 대해 이야기하는 경우 고객은 일반적으로 자신을 '저장'하지 않습니다. 지속성을 위해 무엇을 사용하든 모든 종류의 지속성은 지속성 계층 / 파티션에 속해야한다는 것이 합리적입니다. 이는 일반적으로 리포지토리 패턴의 기본 개념입니다. ** Customer.UpgradeWarranty () 또는 Customer.PromoteToPreferred ()와 같은 메서드는 인수를 더 명확하게 만듭니다.

이것은 또한 DTO 를 가질 가능성을 제거하지 않습니다 . 예를 들어 고객 정보를 원격 서비스에 전달할 상황을 고려하십시오. 고객이 전송을 위해 자체 DTO를 작성하는 것은 이치에 맞지 않을 수 있습니다. 이는 구조적 문제이지만 지속성 또는 네트워크 계층 / 파티션 / 코드 / 무엇을했는지에 대한 사례가있을 수 있습니다. 이 경우 그러한 객체는 다음과 같은 메소드를 가질 수 있습니다

public static CustomerDTO GetDTO(Customer c) { /* ... */ }

public static Customer GetCustomer(CustomerDTO cdto) { /* ... */ }

따라서 요약하면 도메인의 논리적 작업과 일치하는 도메인 개체에 대한 작업을 수행하는 것이 좋습니다.

문제에 대한 여러 가지 좋은 토론을위한 '지속성 무지'에 대한 Google ( 이 SO 질문 및 허용되는 답변은 시작하기에 좋은 장소입니다).

** 이는 '저장'방법이있는 영구 기반에서 강제로 상속되는 특정 OR / M 소프트웨어로 약간 혼란스러워집니다.


3

실제로 최근에 객체와 데이터를 분리하기 위해 일부 코드를 다시 작성했습니다. 그 이유는 데이터가 별도의 서비스를 통해 획득되기 때문에 전체 객체를 앞뒤로 전달하고 서버의 유효성 검사 오류를 처리하는 대신 원시 데이터를 서버와주고받는 것이 훨씬 쉽습니다.

소규모 프로젝트의 경우 객체에 비즈니스 논리가 포함되어 있고 데이터가 적합 할 수 있지만 대규모 프로젝트 또는 시간이 지남에 따라 확장 될 수있는 프로젝트의 경우 계층을 확실히 분리해야합니다.


3

나는 그것을하는 두 가지 방법이 장점을 가질 수 있다고 생각하지만 객체 지향 또는 도메인 중심의 관점에서 볼 것입니다. 다른 클래스와 객체의 책임은 무엇입니까?

따라서 구체적인 경우에는 고객에게 스스로를 구하는 방법을 알아야합니까?

나에게 대답은 '아니오'입니다. 논리적으로는 나에게는 이해가되지 않으며, 고객은 지속성 프레임 워크에 대해 전혀 알 필요가 없습니다 (책임 분리).

Customer.UpgradeWarranty () 또는 Customer.PromoteToPreferred ()가 포함 된 SnOrfus의 예는 Customer.Save ()보다 비즈니스 로직 지향적입니다. 이에 대한 여러 가지 접근 방식이 있지만 고객이 보증을 업그레이드 할 수 있는지 여부를 스스로에게 묻는다면 어떻게 보느냐에 따라 대답이 예 또는 아니요 일 수 있습니다.

  • 예 : 고객은 물론 보증을 업그레이드 할 수 있습니다
  • 아니요 : 고객이 업그레이드를 요청할 수 있지만 업그레이드는 다른 사람이 수행합니다.

원래 질문으로 돌아 가기 어느 쪽이 더 의미가 있는지는 아마도 당신이 요구하는 사람과 선호하는 방법에 달려있을 것이지만, 가장 중요한 것은 아마도 한 가지 방법을 고수하는 것입니다.

그러나 내 경험상 데이터와 (비즈니스) 논리를 분리하면 아키텍처는 단순하지만 흥미롭지는 않습니다.


2

ActiveRecord패턴과 패턴 의 차이점에 대해 구체적으로 이야기하고 있다고 생각합니다 Repository. 전자의 경우 엔티티는 자신을 유지하는 방법을 알고 있으며 후자는 저장소에 대한 지속성을 알고 있습니다. 나는 후자가 더 나은 관심사 분리를 제공한다고 생각합니다.

넓은 의미에서 엔터티가 데이터 구조처럼 작동하면 동작이 없어야하지만 동작이있는 경우 데이터 구조처럼 사용하면 안됩니다. 예:

데이터 구조 :

class CustomerController
{
    public int MostRecentOrderLines(Customer customer)
    {
        var o = (from order in customer.Orders
                orderby order.OrderDate desc
                select order).First();
        return o.OrderLines.ToList().Count;
    }
}

비 데이터 구조 :

class Customer
{
    public int MostRecentOrderLines()
    {
        // ... same ...
    }
}

첫 번째 경우, 작업 코드의 어느 곳에서나 문제없이 모델의 데이터 구조 트리를 탐색 할 수 있습니다. 데이터 구조처럼 취급하기 때문에 괜찮습니다. 후자의 경우 고객은 특정 고객에 대한 서비스와 유사하므로 결과에 대해 메소드를 호출하지 않아야합니다. 고객에 대해 알고 싶은 모든 것은 고객 객체에서 메소드를 호출하여 사용할 수 있어야합니다.

엔터티가 데이터 구조 또는 서비스가 되길 원하십니까? 일관성을 유지하려면 하나를 고수하는 것이 좋습니다. 전자의 경우 "서비스"유형 논리를 엔티티가 아닌 다른 곳에 놓으십시오.


1

나는 당신의 질문에 실제로 대답 할 수는 없지만 우리가 학교 프로젝트 중 하나 에서이 토론을하고 있다는 것이 재미 있다는 것을 알았습니다. 나 자신은 데이터에서 논리를 분리하고 싶다. 그러나 많은 동급생들은 그 물체가 모든 논리와 데이터를 가지고 있어야한다고 말합니다.

나는 그들이 가져온 사실을 여름 화하려고 노력할 것이다.

  • 비즈니스 클래스 개체는 사물을 나타내므로 모든 데이터와 논리가 포함되어야합니다. (예를 들어 문을 열려면 직접 문을 열고 다른 사람에게 묻지 마십시오. 내가 알고있는 나쁜 예)

  • bu 객체의 코드와 기능을 쉽게 이해할 수 있습니다.

  • 디자인의 복잡성 감소

나는 그들이 게으르다는 것을 말하고 있으며 다음과 같이 만들 것입니다.

  • 예, 비즈니스 클래스는 사물을 나타내므로 데이터를 보유합니다. 그러나 자신을 구하거나 심지어 복사하는 것은 잘못된 생각입니다. rl에서 그렇게 할 수 없습니다.

  • 물체를 모든 것에 책임을지게하면 미래의 내구성과 유지 보수에 좋지 않습니다. 저장을 담당하는 별도의 클래스가있는 경우 디자인에 새 객체를 추가하면 저장 기능을 쉽게 구현할 수 있습니다. 그 클래스에서 다시 코딩하는 대신.

  • 하나의 개체가 데이터를 유지할 수있게하면 해당 개체는 데이터베이스 연결을 유지할 수 있으며 모든 데이터베이스 트래픽은 해당 개체로 안내됩니다. (기본적으로 데이터 액세스 계층) 그렇지 않으면 모든 Business Object가 연결을 보유해야합니다. (복잡성을 추가합니다)

어쨌든 나는 선생님에게 물어볼 것입니다. 내가 그 일을 할 때, 원한다면 그의 답변도 여기에 게시 할 것입니다. ;)

편집하다:

나는이 프로젝트가 서점에 관한 것이라고 언급하는 것을 잊었다.


동급생은 비즈니스 논리를 다른 형태의 논리 (이 경우 아키텍처 또는 지속성 논리)와 혼동한다는 점을 제외하고는 옳습니다.
Steven Evers

1

대답은 실제로 아키텍처 / 디자인이 무엇인지에 달려 있습니다. 도메인 모델이있는 DDD 아키텍처는 객체 디자인과 관련하여 CRUD 데이터 중심 모델과는 매우 다릅니다.

그러나 일반적으로 객체 지향 디자인에서는 상태를 캡슐화하고 동작을 노출하려고합니다. 즉, 일반적으로 가능한 한 행동에 가까운 행동과 관련된 상태를 얻으려고 시도합니다.이를 수행하지 않으면 상태를 한 형태 또는 다른 형태로 노출해야합니다.

도메인 모델에서는 비즈니스 모델을 인프라 문제와 분리하려고합니다. 따라서 '.Save'와 같은 방법을 피하고 싶을 것입니다. 고객을 실제로 저장 한 마지막 시간은 기억 나지 않습니다!

CRUD 응용 프로그램에서 데이터는 일류 시민이므로 ".Save"는 전적으로 적합합니다.

대부분의 상당한 실제 응용 프로그램에는 이러한 패러다임이 혼합되어 있습니다. 빠르게 변화하거나 복잡한 비즈니스 규칙이있는 도메인 모델, 경계를 넘어 데이터를 전송하기위한 DTO, CRUD (또는 CRUD와 ActiveRecord와 같은 도메인 모델 사이의 다른 곳). 모든 규칙에 맞는 단일 크기는 없습니다.


0

나는 한동안 같은 질문을 던지고 있었다. 나는 데이터 구성 요소와 논리 구성 요소가 분리되어 있어야한다고 생각한다. 나는 이것이 의미를 제공하는 데이터에 대한 인터페이스로서 비즈니스 로직과 관련하여 올바른 마음의 틀에 들어가기 때문에 이것을 믿는다.

또한 Scott Whitlock의 요점을 위에서부터 수정했습니다 (새 멤버가 아닌 점은 제외). 데이터 또는 비즈니스 논리 클래스는 실제로 객체가 어떻게 저장되는지에 대해 걱정할 필요가 없습니다.

즉, 기존의 제품을 다루는 경우 깨끗하고 계약적인 인터페이스가있는 한 괜찮습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.