데이터 객체에 의존성 주입을 사용합니까?


11

나는 의존성 주입에 대해 배우고 있으며 무언가에 붙어 있습니다. Dependency Injection은 생성자를 통해 종속 클래스를 보내는 것이 좋지만 데이터 객체에 필요한지 궁금합니다. 단위 테스트 가능성은 DI의 주요 이점 중 하나이므로 데이터 만 저장하고 데이터를 저장하는 절차는 수행하지 않는 데이터 객체가 될 수 있습니다. 데이터 객체?

Class DO{
    DO(){
        DataObject2List = new List<DO2>();
    }

    public string Field1;
    public string Field2;
    public List<DO2> DataObject2List;
}

Class DO2{
    public DateTime Date;
    public double Value;
}

"데이터 객체"란 정확히 무엇을 의미합니까? 그것은 표준 용어가 아닙니다. DTO 에 대해 이야기하고 있습니까, 아니면 도메인 모델의 특히 지루한 부분과 같이 메소드가없는 클래스 만 언급하고 있습니까? 둘 사이에는 큰 차이가 있습니다.
Aaronaught

물론, 나는 메소드가없는 클래스, 데이터를 저장하는 클래스를 의미합니다. Data Object가 이것에 대한 올바른 용어가 아닌 경우, 아니면 메소드가없는 클래스라고 불리는가?
sooprise

@sooprise 이것은 좋은 질문입니다. 좋은 생각이야
Matthew Rodatus 2016 년

@sooprise 아마도 내 대답은 기본이 아닐 것입니다. CRUD 방법을 어디에 두겠습니까? 별도의 데이터 액세스 클래스에서 데이터 객체를 가져 와서 데이터베이스 테이블에 유지합니까? 즉 DataAccess.Create (<DataObject>)?
Matthew Rodatus 2016 년

1
@Matthew, 이것은 데이터 액세스 객체 일 것입니다 -실제로 OP가 말하고있는 것이면 전혀 명확하지 않습니다. 현대의 구현은 어쨌든이 패턴에서 벗어나 경향이 있으며 저장소 및 / 또는 작업 단위에 의존합니다.
Aaronaught

답변:


7

여기서 사용하고있는 일부 용어, 특히 "의존성"및 "의존성 주입"에 대한 설명을 제안하고자합니다.

의존:

"종속성"은 일반적으로 다른 클래스가 의존해야하는 일부 기능을 수행하는 복잡한 개체입니다. 일부 전형적인 예는 로거, 데이터베이스 접근 자 또는 특정 비즈니스 로직을 처리하는 일부 구성 요소입니다.

데이터 만 그들이 일부 필요한 기능을 수행하지 않는 이후 DTO 또는 값 오브젝트 등 오브젝트는 전형적으로, "의존성"이라하지 않는다.

당신이 그것을 이런 식으로 보면 일단 당신이 (당신의 예에서 무엇을하고 있는지 구성DO 의 목록과 객체 D02생성자를 통해 객체) 모두에서 "실행 종속 주입"으로 간주되어서는 안된다. 그냥 속성을 설정하는 것입니다. 생성자 또는 다른 방법으로 제공하는지 여부는 사용자에게 달려 있지만 생성자를 통해 전달하면 종속성 주입이되지 않습니다.

의존성 주입 :

DO2클래스가 실제로 DO클래스에 필요한 몇 가지 추가 기능을 제공하는 경우 실제로 종속성이됩니다. 이 경우 종속 클래스 DO는 인터페이스 (ILogger 또는 IDataAccessor와 같은)에 의존해야하며 호출 코드에 의존하여 해당 인터페이스를 제공합니다 (즉, DO인스턴스 에 '주입' ).

이러한 방식으로 종속성을 주입하면 DO각각의 다른 컨텍스트가 DO객체에 대한 자체 인터페이스 구현을 제공 할 수 있으므로 객체가 더 유연 해 집니다. (단위 테스트를 생각하십시오.)


7

나는 문제의 혼란을 극복하기 위해 최선을 다할 것입니다.

우선 "데이터 개체"는 의미있는 용어가 아닙니다. 이 객체 의 유일한 정의 특성에 메소드가없는 것이라면 전혀 존재하지 않아야합니다 . 유용한 동작이없는 객체는 다음 하위 범주 중 하나 이상에 적합해야합니다.

  • 가치 객체 또는 "레코드"는 전혀 정체성이 없습니다. 환경이이를 지원한다고 가정 할 때 복사시 참조 시맨틱 이있는 값 유형 이어야 합니다. 이들은 고정 된 구조이기 때문에 VO는 기본 유형이거나 고정 된 기본 시퀀스이어야합니다. 따라서 VO에는 종속성 이나 연관 이 없어야합니다 . 기본이 아닌 생성자는 값을 초기화 할 목적으로 만 존재합니다. 즉, 리터럴로 표현할 수 없기 때문입니다.

  • 데이터 전송 개체 는 종종 실수로 값 개체와 혼동됩니다. DTO들은 ID가, 또는 적어도 그들은 할 수 있습니다 . DTO의 유일한 목적은 한 도메인에서 다른 도메인으로 정보를 쉽게 전달하는 것입니다. 그들은 "의존성"을 갖지 않습니다. 그것들 은 연관 (즉, 배열 또는 컬렉션)을 가질 있지만 대부분의 사람들은 그것들을 편평하게 만드는 것을 선호합니다. 기본적으로 이들은 데이터베이스 쿼리 출력의 행과 유사합니다. 그들은 일반적으로 그러므로 지속 또는 직렬화 할 필요가 있고, 과도 객체있어 수없는 이 그들을 사용할 수 없게하는 것처럼, 어떤 추상적 인 유형을 참조하십시오.

  • 마지막으로, 데이터 액세스 개체 는 어떤 종류의 데이터베이스에 래퍼 또는 외관을 제공합니다. 이것들은 분명히 의존성을 가지고 있습니다-데이터베이스 연결 및 / 또는 지속성 구성 요소에 의존합니다. 그러나 이들의 종속성은 거의 항상 외부에서 관리되며 발신자에게는 보이지 않습니다. 에서 액티브 레코드 패턴이 구성을 통해 모든 것을 관리하는 프레임 워크입니다; 구형 (오늘날의 표준에 따라) DAO 모델에서는 컨테이너를 통해서만 이들을 구성 할 수있었습니다. 생성자 주입으로 이것들 중 하나를 본다면, 나는 매우 걱정할 것입니다.

또한 생각 될 수 있습니다 엔티티 객체 또는 "비즈니스 오브젝트" ,이 경우 당신은 수 있지만 당신이 생각하는 방식이나 당신이 생각하는 이유, 지원 의존성 주입합니다. 이것은 사용자 코드 의 이익을위한 것이 아니라 , 엔티티 관리자 또는 ORM의 이익을위한 것이며, 쿼리 이해 또는 게으른 로딩과 같은 멋진 작업을 수행하기 위해 가로채는 프록시 를 자동으로 주입합니다 .

이 경우 일반적으로 주입을위한 생성자를 제공 하지 않습니다 . 대신 속성을 가상으로 만들고 추상 유형 (예 : IList<T>대신 List<T>)을 사용해야합니다 . 나머지는 무대 뒤에서 일어나고 아무도 현명하지 않습니다.

따라서 "데이터 객체"에 적용되는 가시적 DI 패턴은 불필요하며 아마도 붉은 깃발이라고 말할 수 있습니다. 그러나 대부분 은 객체의 존재 가 데이터베이스에서 데이터를 나타내는 데 특별히 사용되는 경우를 제외하고는 빨간색 플래그이기 때문입니다. 거의 모든 경우에 코드 냄새, 일반적으로 Anemic Domain Model 의 시작 또는 최소한 Poltergeist 입니다.

반복해서 :

  1. "데이터 개체"를 만들지 마십시오.
  2. "데이터 오브젝트"를 작성해야하는 경우 명확하게 정의 된 목적을 가지고 있는지 확인하십시오 . 그 목적 은 DI가 적절한 지 아닌지를 알려줍니다. 처음에는 존재하지 않아야하는 객체에 대해 의미있는 디자인 결정을 내릴 수 없습니다.

지느러미.


0

귀하의 예에서, DO기능적 종속성이 없습니다 (기본적으로 아무것도하지 않기 때문에). 구체적 타입에 의존 DO2하므로 abstract에 인터페이스를 도입 DO2하여 소비자가 자식 클래스의 구체적인 구현을 구현할 수 있습니다.

실제로 여기에 어떤 의존성을 주입 하시겠습니까?


내가 대답 한 그의 또 다른 질문에 따르면, 질문은 CRUD 작업이 통합 된 데이터 객체를 의미한다고 생각합니다. 데이터베이스 종속성이 데이터 개체에 어떻게 / 어디에 주입됩니까? 방법에서? 생성자에서? 다른 방법? 의존성은 메소드 본문에 숨겨져서는 안된다는 가정하에, 데이터 객체를 단위로 테스트 할 수 있도록 데이터 객체에서 데이터베이스 종속성을 분리하지 못하게합니다.
Matthew Rodatus 2016 년

@ Matthew Rodatus-알겠습니다. 그렇습니다.이 경우 지속성 서비스를 주입하거나 DOPersister지속 방법을 알고있는 다른 클래스를 작성 DO하여 엄격하게 데이터 전용 객체로 남겨 두십시오 (제 생각에는 더 낫습니다). 후자의 경우 DOPersister데이터베이스 종속성이 주입됩니다.
Scott Whitlock 2016 년

그의 질문을 다시 읽은 후에는 확실하지 않습니다. 내 분석이 잘못되었을 수 있습니다. 그는 자신의 질문에 자신의 DO에 어떤 절차도 없을 것이라고 말했습니다. 이는 DO에서 지속성이 발생하지 않음을 의미합니다. 이 경우, 귀하의 답변이 옳습니다. 주입 할 종속성이 없습니다.
Matthew Rodatus 2016 년

0

이는 데이터 액세스 계층의 데이터 개체이므로 데이터베이스 서비스에 직접 의존해야합니다. 생성자에 DatabaseService를 지정할 수 있습니다.

DataObject dataObject = new DataObject(new DatabaseService());
dataObject.Update();

그러나 주입은 생성자에있을 필요는 없습니다. 또는 각 CRUD 방법을 통해 종속성을 제공 할 수 있습니다. 데이터 객체는 실제로 유지할 필요가있을 때까지 데이터 객체의 위치를 ​​알 필요가 없기 때문에이 방법을 이전 방법보다 선호합니다.

DataObject dataObject = new DataObject();
dataObject.Update(new DatabaseService());

CRUD 방법으로 구성을 숨기고 싶지 않습니다 !

public void Update()
{
    // DON'T DO THIS!
    using (DatabaseService dbService = new DatabaseService())
    {
        ...
    }
}

대체 옵션은 재정의 가능한 클래스 메서드를 통해 DatabaseService를 구성하는 것입니다.

public void Update()
{
    // GetDatabaseService() is protected virtual, so in unit testing
    // you can subclass the Data Object and return your own
    // MockDatabaseService.
    using (DatabaseService dbService = GetDatabaseService())
    {
        ...
    }
}

마지막 대안은 싱글 톤 스타일의 ServiceLocator를 사용하는 것입니다. 이 옵션을 싫어하지만 단위 테스트가 가능합니다.

public void Update()
{
    // The ServiceLocator would not be a real singleton. It would have a setter
    // property so that unit tests can swap it out with a mock implementation
    // for unit tests.
    using (DatabaseService dbService = ServiceLocator.GetDatabaseService())
    {
        ...
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.