태그 보관물: design

design

데이터 지향 인터페이스 프로그래밍 작성되었습니다. // IScheduledTask.cs public interface IScheduledTask {

코드베이스의 일부는 다음과 같은 스타일로 작성되었습니다.

// IScheduledTask.cs
public interface IScheduledTask
{
    string TaskName { get; set; }
    int TaskPriority { get; set; }
    List<IScheduledTask> Subtasks { get; set; }
    // ... several more properties in this vein
}

// ScheduledTaskImpl.cs
public class ScheduledTaskImpl : IScheduledTask
{
    public string TaskName { get; set; }
    public int TaskPriority { get; set; }
    public List<IScheduledTask> Subtasks { get; set; }
    // ... several more properties in this vein,
    // perhaps a constructor or two for convenience.
}

즉, 자동 속성으로이를 구현하는 유일한 해당 구현으로 각각 동작이없는 속성 세트 만 지정하는 많은 인터페이스가 있습니다. 이 코드는 상당히 상급자 (나 자신보다 훨씬 많은 사람)에 의해 작성되었으며 합리적인 절차 적 코드 인터페이스 사용과는 별개입니다. 다른 사람 이이 스타일을 만났거나 사용했는지, 인터페이스없이 어디서나 구체적인 DTO를 사용하는 것보다 이점이 있는지 궁금합니다.



답변

여기 내 두 센트가 있습니다 :

  • 우리는 DTO가 최소한 약간의 행동을하지 않을 것이라고 확신하지 않습니다. 그래서 저에게는 앞으로 행동 할 수도 있고 없을 수도있는 물건들이 있습니다.
  • 많은 단독 구현 클래스를 갖는 한 가지 가능한 원인은 디자인의 부족 것을 볼 실패 예를 들어 ScheduledTask, ScheduledJob, ScheduledEvent, ScheduledInspection, 등, 하나는 분리해야 Schedulable어떤 구현의 스케줄을 인터페이스를 제공합니다.
  • 인터페이스를 먼저 만드는 것은 매우 좋은 방법이며 필요한 정보를 제공합니다. 많은 인터페이스는 전혀 구현하지 않아도 시작됩니다. 그런 다음 누군가가 하나의 구현을 작성하고 그 구현을 가지고 있습니다. 두 번째 요점에서 언급 한 것을 피하면 단독 구현 상태는 일시적입니다. 어떤 인터페이스가 결코 두 번째 구현을 절대로 갖지 않을 것이라는 것을 어떻게 미리 알고 있습니까?
  • 우리가 잘 생각하는 인터페이스를 위해 선택한 이름은 미래에 변경되지 않는 경향이 있으므로 해당 인터페이스에 대한 종속성은 영향을받지 않습니다. 반면에 구체적인 클래스는 예를 들어 그 변경 사항을 구현하는 방식에 중요한 일이라는 구체적인 클래스 때 이름이 변경 될 경향 TaxSheet에 변경 될 수 있습니다 SessionAwareTaxSheet중요한 정밀 검사가되었다하지만 인터페이스가 있기 때문에 ITaxSheet아마 그렇게 쉽게 이름을 바꿀 수 없습니다.

결론 :

  • 우수한 설계 관행은 DTO에도 적용됩니다.
  • DTO는 약간의 행동을 추가 할 수 있습니다.
  • 모든 인터페이스는 하나의 구현으로 시작됩니다.
  • 반면에 하나의 인터페이스-일-클래스 콤보가 너무 많으면 지적해야 할 디자인이 부족할 수 있습니다. 당신의 선입견이 정당화 될 수 있습니다 .

답변

인터페이스를 사용하는 DTO에서 본 특정 문제는 다음을 허용한다는 것입니다.

public interface ISomeDTO { string SomeProperty { get; set; }}

public class SomeDTO : ISomeDTO
{
    public string SomeProperty { get; set; }
    string ISomeDTO.SomeProperty { get { /* different behavior */ } set { SomeProperty = value; } }
}

이 패턴이 중요한 행동을 구현하기 위해 빠르고 더러운 핵으로 적용되는 것을 보았습니다. 이것은 매우 혼란스러운 행동을 할 수있는 코드로 이어집니다.

SomeDTO a = GetSomeDTO();
ISomeDTO ia = a;
Assert.IsTrue(a.SomeProperty == ia.SomeProperty); // assert fails!

이것은 풀거나 리팩토링을 유지하기가 어렵고 혼란 스럽습니다. DTO에 행동을 추가하는 IMO는 단일 책임 원칙을 위반합니다. DTO의 목적은 지속성 프레임 워크에 의해 유지되고 채워질 수있는 형식으로 데이터를 표현하는 것입니다.

DTO는 도메인 모델이 아닙니다. DTO가 빈혈 인 경우 걱정하지 않아도됩니다. 빈혈 도메인 모델에 대한 Martin Fowler의 논의 를 인용 하면 :

또한 도메인 객체에 동작을 넣는 것이 지속성 및 표현 책임과 같은 것에서 도메인 로직을 분리하기 위해 계층화를 사용하는 확실한 접근 방식과 모순되지 않아야한다는 점을 강조 할 가치가 있습니다.


답변