web-dev-qa-db-ja.com

データ指向インターフェースへのプログラミング

次のスタイルで記述されたコードベースの一部があります。

// 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を使用するだけの利点があるのか​​と思いました。

9
walpen

これが私の2セントです。

  • DTOが少なくとも少しだけ動作することは決してないでしょう。ですから私にとっては、将来振る舞いをするかもしれないし、持たないかもしれないオブジェクトがあります。
  • 単一実装クラスが非常に多い原因の1つとして考えられるのは、設計の欠如です、たとえば、ScheduledTaskScheduledJobScheduledEventが表示されない、ScheduledInspectionなどは、1つの分離されたSchedulableインターフェースのみで、実装者をスケジュール可能にする必要があります。
  • 最初にインターフェースを作成することは非常に良い習慣であり、必要なものについての洞察を提供します。多くのインターフェースは、実装がないことから始まります。次に、誰かが1つの実装を記述し、その実装があります。 2番目のポイントで言及したことを回避すると、単一の実装の状態は一時的なものになります。 一部のインターフェイスで2番目の実装が2番目になることはないことを事前にどのように知っていますか?
  • よく考えられたインターフェースに付ける名前は、将来変更されない傾向があるため、そのインターフェースへの依存関係は影響を受けません。一方、具象クラスは、実装方法に重要な変更があった場合に名前が変更される傾向があります。たとえば、TaxSheetという具象クラスは、大幅なオーバーホールが行われたためにSessionAwareTaxSheetに変更される可能性があります。しかし、インターフェースITaxSheetの名前はそれほど簡単には変更されないでしょう。

ボトムライン:

  • 優れた設計プラクティスはDTOにも適用されます。
  • DTOは、将来的に少し動作を追加できます。
  • すべてのインターフェースは、1つの実装のみから始まります。
  • 一方、1つのインターフェイス、1つのクラスのコンボが多すぎる場合は、デザインの不足が指摘される可能性があります。 あなたの関心事は正当化されるかもしれません
5

インターフェイスを使用する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!

これを維持することは困難であり、もつれたりリファクタリングしようとすると混乱します。 IMO、DTOに行動を追加すると、単一責任の原則に違反します。 DTOの目的は、永続化フレームワークによって永続化および入力できる形式でデータを表すことです。

DTOはドメインモデルではありません。 DTOが貧血であるかどうかを心配する必要はありません。引用するには Martin Fowlerによる貧血ドメインモデルの議論

ドメインオブジェクトに動作を設定することも強調する価値があります。 階層化を使用してドメインロジックを永続性などから分離するという堅固なアプローチと矛盾しないようにする必要があります とプレゼンテーションの責任。

1
Erik