web-dev-qa-db-ja.com

C#.Net Core APIの設計-インターフェイスとDTO

私は.netコアを使用して比較的シンプルなWebアプリケーションを設計しています。私はこれまでのところ、主にデスクトップ開発を行ってきたので、デスクトップ開発とWeb開発の間のニュアンスに少し慣れています。

このアプリケーションには、ビジネスロジックレイヤーとプレゼンテーションロジックレイヤーがあり、ビジネスロジックを使用して、プロパティをマークアップされたサーバー側の出力に変換し、Web APIを介してクライアントにデータを返します。

使用しているコントロールとアプリケーションの構造により、この "プレゼンテーションロジック"レイヤーをサーバー側に配置することは理にかなっています。プレゼンテーションの一部の側面は実際のビジネスロジック要件であるためです(ほとんどのプレゼンテーションはビュー、部分ビュー、およびビューコンポーネント)。

現在、これを処理する方法は、ビジネスロジッククラスをプレゼンテーションロジッククラスに挿入し、APIコントローラーにインターフェイスをプレゼンテーションロジッククラスに返すようにすることです。

アプローチの簡単な例:

public class BusinessLogic
{
  public string PropertyA { get; set; }

  public string PropertyB { get; set; }

  public void DoSomeLogic() { // some code here }
}

public class PresentationLogic : IPresented
{
  private BusinessLogic businessLogic;

  public PresentationLogic(BusinessLogic businessLogic)
  {
    this.businessLogic = businessLogic;
  }

  public string PresentationPropertyA
  {
    get
    {
      return "<span class='businesslogicspecificclass'>" + this.businessLogic.PropertyA + "</span>";
    }
  }
}

public interface IPresented
{
  string PresentationPropertyA { get; }
}

[Route("api/[controller]")]
public class MyController
{
  [HttpGet]
  public IPresented Get()
  {
    var businessLogic = new BusinessLogic();
    // manipulate businessLogic
    return new PresentationLogic(businessLogic);
  }
}

APIは、PresentationLogicクラスによって実装されるインターフェースを公開します。私が理解しているように、これらのインターフェースはJSONにシリアル化され、そのコントロール内で使用するためにページに返されます。

同じ問題を解決する別のアプローチは、DTOを作成し、PresentationLogicクラスでビジネスロジックを取得してDTOを吐き出し、DTOの作成中にプロパティに追加のマークアップを追加することです。例えば:

public class PresentationLogic
{
  public Dto GetDtoFromBusinessLogic(BusinessLogic businessLogic)
  {
    return new Dto { PresentationPropertyA = "<span class='businesslogicspecificclass'>" + this.businessLogic.PropertyA + "</span>" };
  }
}

public class Dto
{
  public PresentationPropertyA { get; set; }
}

[Route("api/[controller]")]
public class MyController
{
  [HttpGet]
  public Dto Get()
  {
    var businessLogic = new BusinessLogic();
    // manipulate businessLogic
    var presentationLogic = new PresentationLogic();
    return presentationLogic.GetDtoFromBusinessLogic(businessLogic);
  }
}

私が知りたいのは、各アプローチの利点と欠点です。

私が理解しているように、両方のコントローラーメソッドは同じJSONを呼び出しページに効果的に返します。

最初のアプローチは、次の理由で私にとってより自然に感じられます。

  • DTOは貧血ドメインモデルを奨励する傾向があると思うので、絶対に必要でない限り、DTOは好きではありません。
  • プレゼンテーションロジッククラスは、ビジネスロジックとビューの間に位置するアダプタクラスになります。明確に定義された責任があります。
  • 純粋に戻り値の型として機能する目的でクラスを作成したことはありません。無駄なコードが少ないように感じます。
  • バージョン2で変更が必要な場合は、PresentationLogicクラスに新しいプロパティを追加し、新しいインターフェイスを実装する可能性があります。
  • インターフェイスは、C#コードを抽象化するための自然なツールのように感じられます。

私はこれについて他の開発者と話し合っており、彼らはDTOを返すことがこの問題に取り組むためのより標準的な方法であると提案していました。これがより良いアプローチである理由がいくつかあります。

  • DTOはそのように明確にマークされており、破壊的なロジックを追加しようとする人はいません。
  • それが標準的な方法である場合、それは新しい開発者がスピードに慣れるのに役立ちます。
  • 新しいバージョンを追加すると、新しいDTOクラスの使用が強制されます。つまり、互換性を破る変更が導入される可能性が低くなります(これは、必要に応じて他の方法でも実行できます)。

この質問は一般に、特にこのプロジェクトに対する私のニーズよりも、階層化されたWebアーキテクチャに関するものであることに注意してください。プレゼンテーションロジックをサーバー側に追加する必要がない場合、この質問はビジネスロジックと永続化ロジッククラスに関するものである可能性があります。

それではどちらが良いですか-Web APIでDTOを使用するか、Web APIで複雑なオブジェクトのインターフェイスを使用するか?

2
Stephen

ここで、ADMは正しいアプローチです。

  1. コントローラーメソッドからメソッドを持つオブジェクトを返す意味はありません。オブジェクトはすぐにシリアル化され、ネットワーク経由で送信されます。メソッドを受信するものはありません。

  2. コントローラーアクションは、各リクエストで再利用するさまざまなサービスへの依存関係を共有します。これらをコントローラーに挿入すると、リクエストごとに再作成する必要がなくなります。

  3. コントローラーアクションの受信パラメーターは、逆シリアル化する純粋なデータオブジェクトです。メソッドをアタッチする場合、それは意味上の理由のみです。

そのため、本質的には、データオブジェクトのストリームが入っており、それぞれに作用し、応答として別のデータオブジェクトを返す永続的なサービスがあります。

この場合、ビジネスルールを含むドメインオブジェクトはサービスであり、データではありません。

これで、クライアント側では、APIのクライアントが注入され、メソッドの実装に使用されるObject.BusinessLogic()を使用する可能性があります(人々が実際の例を使用しない場合は大変です)。

Objectオブジェクトは永続化されて渡されるため、ここではクラシックOOPを使用することは理にかなっています。

2
Ewan