質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
DTO(Data Transfer Object)

DTO(Data Transfer Object)とは、データを転送するために定義されたクラスのこと。関連データを集約し、データの格納や読み出しのメソッドを定義したオブジェクトです。データを管理するためのフィールド群に対応したセッター・ゲッターで構成されています。

Q&A

2回答

1352閲覧

CleanArchitectureでの扱いについて

nostrils

総合スコア0

DTO(Data Transfer Object)

DTO(Data Transfer Object)とは、データを転送するために定義されたクラスのこと。関連データを集約し、データの格納や読み出しのメソッドを定義したオブジェクトです。データを管理するためのフィールド群に対応したセッター・ゲッターで構成されています。

0グッド

2クリップ

投稿2022/05/14 08:37

設計の勉強をしています。
Clean Architectureでアプリを作っていて、Viewにリストの内容を表示するために、ViewDataとして、配列を持っているのですが、これは、コレクションオブジェクトにした独自の構造体にした方がいいのでしょうか?例えばgithubのリポジトリ一覧を表示したいとき

swift

1class Repository{ 2 let title:String 3 let description:String 4 let isFavorite:Bool 5}

のような型があった場合、viewDataはコレクションオブジェクトで表現すると

swift

1struct RepositoryList{ 2 let elements:[Repository] 3}

のように表現するのかそれとも単に[Repository]という型で表現するのかどちらの方がいいのでしょうか??

また、上記のコレクションは一種のValue Objectだと思うのですが、お気に入りフラグ(isFavorite)を切り替えようとしたとき、どのような処理を書けばいいのでしょうか??ValueObjectはイミュータブルな処理のため、一つのリポジトリ情報更新ごとに新しい配列を返すようなメソッドがいいかなと思ったのですが、このような処理でいいのでしょうか??

swift

1struct RepositoryListViewDataModel{ 2 let elements:[Repository] 3 4 func updateBookmark(repository:Repository)->Self{ 5 if let index = elements.firstIndex(where: {$0 == repository}){ 6 var elements = elements 7 elements[index] = repository 8 return RepositoryListViewDataModel(elements: elements) 9 }else{ 10 throw Error 11 } 12 } 13}

また、DTOについて書籍で下記のように記載がありました。
これはDTO(Data Transfer Object)と言ってデータ転送用途に使われる設計パターンです。値変更の必要がないのでインスタンス変数はfinalで宣言し、コンストラクタで値が確定するようにします。参照系のみの用途であるため、更新系で使ってはいけません。更新系で用いると低凝集に陥ります。

これとValue Objectの違いがよくわからないのですが、どのような違いがあるのでしょうか?
また、上記のような ViewdataはDTOかVOのどちらなのでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

リポジトリ一覧の型

リポジトリのリストということなので、↓みたいな感じでいいかなと思います。

Swift

1class Repository{ 2 let title:String 3 let description:String 4 let isFavorite:Bool 5} 6 7typealias RepositoryList = [Repository]

実体はRepositoryクラスの配列ですが、typealiasでRepositoryListという名前を付けることで明示的な型を宣言できるところがポイントですね。

Value Objectの更新処理について

また、上記のコレクションは一種のValue Objectだと思うのですが、お気に入りフラグ(isFavorite)を切り替えようとしたとき、どのような処理を[...]

状態の更新をしたくなる場合、それはValue ObjectではなくEntityとして捉えた方がよいと思います。

素直にRepositoryクラスにお気に入りフラグ更新メソッドを持たせた方が処理がシンプルになり、可読性が高まると思いますね。

DTOとValue Objectの違いについて

実装的には特に違いはありませんが、利用する目的や文脈によって別の名前がついた概念と言えます。

DTOはレイヤー間のデータの受け渡しの為に使われることを意図しています。雑なイメージとしてはJSONでデータを受け渡しているのをイメージしてもらえるといいです。

実際、JSONの登場によってDTOを使った設計パターンは役割を終えた感がありますね。

一方、Clean ArchitectureやDDDの文脈におけるValue Objectは日付や金額などの型エイリアスとしての役割が強いです。

型エイリアスとしてValue Objectを定義することで、コードが分かりやすくなることを狙っています。上で述べたRepositoryListのような感じですね。

[...]また、上記のような ViewdataはDTOかVOのどちらなのでしょうか?

Entityとして捉えた方が自然だと思いますね。

投稿2022/05/14 20:37

madoka-t

総合スコア379

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nostrils

2022/05/15 05:21

ご回答ありがとうございます! 状態の更新をしたくなる場合、それはValue ObjectではなくEntityとして捉えた方がよいと思います。 とのことでしたが、上記のRepositoryListはViewに表示するようのViewDataであり、ドメイン知識を持ったEntityとは役割が違う気がするのですが、それでもEntityと捉える理由はなんでしょうか? また、DTOというのはミュータブルに扱ってもいいのでしょうか??
madoka-t

2022/05/16 00:11 編集

色々と論点があるので箇条書きにしますね。 ・ViewDataがEntityであっては*いけない*という理由がない(Clean Architectureでもプレゼンテーション層からドメイン層への依存は禁止されていない) ・言語がSwiftということはIOSアプリ開発の文脈だと思われるが、GUIアプリケーションは本質的に状態を持つものである(Viewの状態はイミュータブルにはならない) ・ViewData(ViewModel?)がドメインの知識を持っていることは別におかしなことではない(UIの制御にドメイン知識が必要になる場面は当然ある) ・Viewに渡すデータをイミュータブルなDTOにする設計はWEBアプリケーションかつCQRSを意識した設計のように思えるが、GUIアプリにそのまま当てはめるべきかは疑問が残る ・DTOをミュータブルに扱ってよいかについては、完全に設計ポリシーで決める問題なので唯一の答はない(上述したようにWEBアプリケーションではイミュータブルであることが望ましいが、そうでない場合もある) ・DTOをレイヤー間のデータのやりとりに使う場合、DTOの内容を更新して元のレイヤーに投げ返すということは十分考えられる ・Clean Architecture的な設計に従うのであれば、ViewData(ViewModel?)の変化はControllerを経由してドメイン層に伝えることになるので、やはりViewDataはイミュータブルにはならないはず といった感じでしょうか。
guest

0

Clean Architectureはちゃんと勉強したことがないのですが(すみません。。)、
Value Object(値オブジェクト)やData Transfer Object(DTO)はClean Architectureに限ったものではないようにも思いましたので、
一緒に勉強させていただきたい気持ちもあって、回答してみました。


これとValue Objectの違いがよくわからないのですが、どのような違いがあるのでしょうか?
また、上記のような ViewdataはDTOかVOのどちらなのでしょうか?

質問欄に色々「?」がありましたが、まず、最後の2行についてだけ書いてみます。

ドメインモデルとして挙げられていなかった概念を値オブジェクトにすべきかどうかの判断基準として、筆者は「そこにルールが存在しているか」という点と「それ単体で扱いたいか」という点を重要視しています。
たとえば氏名には「姓と名で構成される」というルールがあります。
また本文で例示したように単体で取り扱っています。
筆者の判断基準に照らし合わせると値オブジェクトとして定義されます。
では姓や名はどうでしょうか。
いまのところ性や名にシステム上の制限はありません。
姓だけを取り扱ったり、名だけを利用するシーンもいまのところありません。
筆者の判断基準からするとこれらはまだ値オブジェクトにしないでしょう。
『ドメイン駆動設計入門 P.030』

.

cs

1class FullName : IEquatable<FullName> 2{ 3 private readonly string firstName; 4 private readonly string lastName; 5 public FullName(string firstName, string lastName) 6 { 7 if (firstName == null) throw new ArgumentNullException(nameof(firstName)); 8 if (lastName == null) throw new ArgumentNullException(nameof(lastName)); 9 if (!ValidateName(firstName)) throw new ArgumentException("許可されていない文字が使われています。", nameof(firstName)); 10 if (!ValidateName(lastName)) throw new ArgumentException("許可されていない文字が使われています。", nameof> (lastName)); 11 this.firstName = firstName; 12 this.lastName = lastName; 13 } 14 private bool ValidateName(string value) 15 { 16 // アルファベットに限定する 17 return Regex.IsMatch(value, @"^[a-zA-Z+$"); 18 } 19 // (...略...) 20}

『ドメイン駆動設計入門 P.031』

.

値オブジェクトのコンセプトは「システム固有の値を作ろう」という単純なものです。
システムには、そのシステムならではの値が必ずあるはずです。
もちろん、プリミティブな値だけでソフトウェアを構築することは可能です。
しかし、プリミティブ型は汎用的すぎて、どうしても表現力が乏しくなってしまいます。
『ドメイン駆動設計入門 P.046』

.

そこで筆者がお勧めするのはドメインオブジェクトを直接公開しない方針です。
ドメインオブジェクトを非公開としたとき、クライアントにはデータ転送用オブジェクト(DTO、Data Transfer Object)にデータを差し替えて返却します。
『ドメイン駆動設計入門 P.122』

.

凝集度の低いモジュールは、関係性のない仕事をこなしたり、仕事が多すぎたりする特徴があります。
これは以下のような問題を発生させます。

  • コードが理解しにくい。
  • コードが保守しにくい。
  • コードが再利用しにくい。
  • コードが脆弱で、変更による影響を絶えず受ける。

『プリンシプル オブ プログラミング P.189』


入門の書籍しか読んだことはないのですが、役割の違いがあるように思いました。
(引用した書籍はC#なのですがすみません。。)

個人的に書籍を読む前は、Value Object(値オブジェクト)は、広い意味ですとイミュータブル的なものを全てそう呼ぶような印象でした。
でも、『ドメイン駆動設計入門』を読みますと、狭い意味ではルールのある項目がValue Objectになるように思いました。
『ドメイン駆動設計入門』では、値オブジェクトを持っているのがエンティティになるようでした。
同じレイヤーの中でエンティティの中に保持されるルールのある項目が値オブジェクトという感じです。

それに対してDTOは、レイヤー間でデータを受け渡しする役割があるように思います。

値オブジェクトとDTOは別の役割があると思いますので、役割が違うようでしたらそれぞれ存在する感じで実装するのが教科書的な印象でした。

また、上記のような ViewdataはDTOかVOのどちらなのでしょうか?

あまり自信はないですが、エンティティ的な印象かなと思いました。。

十分に回答できていないと思いますので、コメントをもらえると嬉しいです。

投稿2022/05/14 10:04

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問