도메인과 데이터베이스 계층 간의 통신을 처리하는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/549305

문제

비즈니스 로직 (도메인)과 데이터베이스 액세스 로직에 별도의 레이어를 사용하는 것이 상당히는 새로운 것이지만, 작업을 수행하는 동안 여전히 훌륭한 솔루션을 찾지 못한다고 생각하는 문제를 발견했습니다.

설명 기존 솔루션은 데이터 매퍼를 사용하여 데이터베이스 상호 작용을 직접 처리합니다. 그러나이 문제를 더 조사한 결과 많은 사람들이 도메인 계층이 실제로 데이터베이스 상호 작용을 수행하는 데이터 매퍼와 직접 통신하거나 포함해서는 안된다고 제안했습니다. 그렇기 때문에 도메인과 필요한 데이터 매퍼 사이에 저장소 객체를 배치했지만 자연 스럽거나 정확하지는 않습니다. 실제 질문은 도메인과 데이터 매퍼 사이의 통신을 처리하기 위해 자연스럽게 존재하는 계층입니다. 그것을 구조화하는 방법의 예는 감사 할 것입니다.

예를 들어:

  • 다른 도메인 객체의 컨텍스트 내에서 도메인 개체 모음 검색을 올바르게 처리하려면 어떻게해야합니까?
  • 다른 객체에 대해 수행 된 동작을 기반으로 단일 도메인 객체 또는 객체 모음을 삽입하는 방법은 어떻게하나요? 내가 현재 직면하고있는 사례는 사람이 캠페인에 첨부 될 때 해당 캠페인을 위해 그 사람을 위해 실행 해야하는 모든 이벤트를 삽입해야한다는 것입니다.
도움이 되었습니까?

해결책

가브리엘, 이것을 "임피던스 매칭 문제.

업데이트

자, 더 많은 정보없이 이것을 공격하는 방법을 정확히 알기가 어렵지만 여기에 기본적인 접근 방식이 있습니다.

이러한 종류의 건축 문제 중 하나는 성능과 같은 기능이없는 요구 사항에 의해 주도됩니다. 또한 여기에는 올바른 순서로 업데이트가 수행되도록해야한다는 점에서 정확성 문제가 있습니다. 그래서 당신은 작업량, 즉, 실제 응용 프로그램에서 사용 패턴입니다. 이를 염두에두고 기본적으로 몇 가지 문제가 있습니다. 첫째, 애플리케이션의 기본 데이터 유형은 데이터베이스에 올바르게 매핑되지 않을 수 있습니다 (예 : 코드에 표시된 Varchar 속성은 무엇입니까?) 두 번째 도메인 모델. 데이터베이스 모델에 깨끗하게 매핑 할 수 없습니다.

당신이 원하는 것은 데이터베이스와 dmain 모델이 작동하여 도메인 객체의 인스턴스가 데이터베이스 모델의 테이블 행이되도록하는 것입니다. 대규모 응용 프로그램에서는 기존 데이터베이스 모델에 의해 부과 된 성능 제약 또는 제약 조건으로 인해이를 거의 수행 할 수 없습니다.

이제 데이터베이스 모델을 완전히 제어하면 데이터베이스 모델이 도메인과 더 밀접하게 유사하게 만들 수 있기 때문에 다소 단순화됩니다. 이는 데이터베이스 모델이 다소 비정상화되었음을 의미 할 수 있지만, 그렇다면 (데이터베이스에 따라)보기로 처리하거나 완전히 정규화 된 데이터베이스가 없을 수 있습니다. 정규화는 유용한 이론적 구조이지만 실제 시스템에서이를 완화 할 수 없다는 것을 의미하지는 않습니다.

만약 너라면 ~하지 않다 데이터베이스 모델을 완전히 제어하면 매핑을 만드는 객체 레이어가 필요합니다. 구현에서 선택할 수있는 여러 가지 옵션이 있습니다. 데이터베이스에서 뷰 또는 피의 테이블을 구축 할 수 있거나 중간 객체를 빌드하거나 둘 다를 수행하거나 두 단계의 여러 단계를 가질 수 있습니다 (즉,). 피소화 된 테이블에 액세스하는 중간 물체.)

그러나 그 시점에서, 당신은 "자신을 반복하지 마십시오"와 "가장 간단한 일을 할 수있는 가장 간단한 일을하십시오"와 관련된 문제를 해결합니다. 변화 할 가능성이 가장 높은 것이 무엇인지 생각하십니까? 도메인 모델? 강력한 도메인 모델을 가지고 있다면 비즈니스가 상대적으로 거의 변경 될 가능성이 적습니다. 데이터베이스에서 데이터의 정확한 표현? 조금 더 일반적입니다. 또는 가장 일반적으로, 정확한 사용 패턴 (동시 업데이트를 처리 할 필요성을 발견하는 것과 같이). 따라서 생각할 때 가장 일반적인 변화를 처리하기 위해 가능한 한 쉽게하기 위해 무엇을해야합니까?

나는 이것이 당신에게 매우 정확한 지침을 제공하지 않는다는 것을 알고 있지만, 나는 당신의 응용 프로그램에 대해 많은 것을 알지 못하고 정확한 지침을 제공 할 수 있다고 생각하지 않습니다. 그러나 나는 또한 당신이 이것을 다루는 "올바른"방법이 무엇인지에 대해 궁금해하는 인상을 얻는 반면, 당신은 이미 일을하는 일을 이미 작업하고 있습니다. 그래서 나는 "당신은 지금 무엇에 불만을 가지고 있습니까?" 그리고 "어떻게 그것을 해결하고 싶습니까?"

다른 팁

도메인 모델과 IT 구현 사이에는 차이가 있습니다. 모델이 관계를 보여주기 때문입니다 Person ---> Campaign ---> Event 이런 식으로 구현해야한다는 의미는 아닙니다. IOW, 귀하의 모델은 분석 및 디자인을 객체 지향 방식으로 보여 주지만 OOP에서 해당 모델을 구현하여 해당 모델이 코드에서 얼마나 잘 복제 할 수 있는지에 제한이 있습니다.

다음을 고려하세요.

Person a의 소유권으로 정의되지 않습니다 Campaign, 따라서 캠페인은 지식의 책임에서 제외 될 수 있습니다. 반면에, a Campaign is defined by the Event실행의 일환으로 발생하므로 캠페인 내에서 이벤트 모음을 보는 것이 공정합니다. 내가하고있는 요점은 각 수업이 그것을 전체적으로 만들기에 충분한 행동과 지식을 가져야한다는 것입니다.

도메인과 지속성 계층 간의 통신에 관해서는, 이들을 다른 것과 관련이없는 두 가지 매우 고유 한 시스템으로 간주하십시오. 그들 각각은 모든 것이 그 책임이 무엇인지, 그리고 그것이 어떤 발표를하는지입니다. 예를 들어, 지속성 계층은 데이터가 전달 된 데이터를 지속하는 방법을 알고 데이터가 저장되었다고 발표합니다. 그러나 지속성 층이 반드시 도메인 객체를 이해할 필요는 없습니다. 마찬가지로 도메인 층은 이해합니다 Person, Campaign, 그리고 Event 그러나 끈기에 대해 아무것도 모릅니다.

위의 의미는 도메인 층이 전체적이어야하며 데이터의 지속성 계층에 의존해서는 안된다는 것입니다. 그러나 책임을 수행하기 위해 여전히 데이터가 제공되어야합니다. 해당 데이터는 사용자 인터페이스 또는 데이터베이스에서 나올 수 있으며 도메인과 지속성 계층에 대해 알고있는 타사를 통해 전달됩니다.

그래서 코드 (pseudo-c#)에서 ...

namespace DomainLayer
{
    interface IDomainListener 
    {
        void PersonCreated(Person person);
    }

    class Person
    {
        private string name;

        public Person(string name)
        {
            this.name = name;
        }

        public string Name
        {
            get { return name; }
        }
    }

    class Domain 
    {
        private IDomainListener listener;

        public Domain(IDomainListener listener) {
            this.listener = listener;
        }

        public void CreatePerson(string name) {
            Person person = new Person(name);
            listener.PersonCreated(person);
        }
    }
}


namespace PersistenceLayer
{
    interface IPersistenceListener
    {
        void PersonDataSaved(int id, object data);
    }

    class Persistence
    {
        private IPersistenceListener listener;

        public Persistence(IPersistenceListener listener) 
        {
            this.listener = listener;
        }

        public void SaveData(object data)
        {
            int id = ...; // save data and return identifier
            listener.DataSaved(id, data);
        }
    }
}

namespace MyApplication
{
    class MyController : IDomainListener, IPersistenceListener
    {
        public void CreatePersonButton_Clicked()
        {
            Domain domain = new Domain(this);
            domain.CreatePerson(NameTextbox.Text);
        }

        public void PersonCreated(Person person)
        {
            Persistence persistence = new Persistence(this);
            persistence.SavePersonData(person.Name);
        }

        public void DataSaved(int id, object data)
        {
            // display data on UI
        }
    }   
}

보시다시피, 네임 스페이스는 다른 계층을 나타냅니다. 그만큼 XYZListener 인터페이스는 XYZ 층. 이 공지 사항에 관심이 있고 응답 할 다른 계층은 우리와 마찬가지로 이러한 인터페이스를 구현해야합니다. MyApplication 층.

"작성 버튼"을 클릭하면 컨트롤러가 Domain 도메인 레이어의 외관 객체 및 자체를 리스너로 등록합니다. 그런 다음 호출합니다 CreatePerson 인스턴스화하는 방법 a Person 그런 다음 새 인스턴스를 통과하여 이것이 완료되었다고 발표합니다. 컨트롤러는이 발표에 응답합니다 PersonCreated 지속성 층의 외관을 생성하고 다시 청취자로 등록하는 경우 구현. 그런 다음 호출합니다 SaveData 메소드가 포함됩니다 DataSaved 완료 될 때. 그런 다음 해당 방법의 구현은 UI에 데이터를 표시합니다.

보시다시피, 도메인 층과 지속성 계층은 각각 tmemselves 만 인식하고 다른 사람의 책임과 관련이 없습니다. 여기서는 컨트롤러로 나타나는 응용 프로그램 논리입니다.

특정 문제로 돌아가서 방법을 가질 수 있습니다. FindPerson 끈기에 대해 발표 할 것입니다 PersonFound(int id). 컨트롤러의 응답은 지속성 계층을 호출하여 캠페인 및 이벤트에 대한 데이터를 검색 한 다음 해당 데이터와 함께 도메인 레이어를 호출하여 Person.

긴 대답에 대해 죄송합니다 ...

많은 시스템은 독립적 인 데이터 계층을 사용하여 데이터베이스와의 지속성을 처리합니다. 그러한 계층의 구성을위한 몇 가지 모델이 있습니다. 일부는 일종의 공장과 유사한 구현을 사용하고 다른 일부는 도메인 클래스 당 하나의 데이터 계층 클래스와 함께 일대일 매핑을 사용합니다.

데이터 계층의 모델은 종종 스타일과 선호도에 따라 다릅니다. 중요한 것은 지속성 계층을 도메인 층으로부터 분리하는 것입니다. 이 계층을 생성하는 데 도움이되는 도구가 있다고 생각하지만 PHP 지식은 얇아서 PHP의 이름을 지정할 수 없습니다.

Phpcake와 Symfony가 사용하는 데이터 추상 레이어를 살펴 봅니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top