🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

Q&A

解決済

1回答

4912閲覧

オブジェクト指向で設計したクラスのプロパティとメソッドの分離について

comet7360

総合スコア9

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

0グッド

1クリップ

投稿2021/03/01 09:03

編集2021/03/01 11:27

質問は以下の2つです。

1.以下のようなPersonクラスを、プロパティだけを定義したクラス、メソッドだけを定義したクラスに
分離することは、クラス設計の考え方としてアリでしょうか。ナシでしょうか。
※プロパティのみ定義したクラスに分けることで、保守性を高める、など
そういったデザインパターンがあるのでしょうか

2.GetFather()メソッドのように、自分のインスタンスとは直接関係の無いデータを提供するメソッドは、
Personクラスの中に定義してはダメでしょうか。(オブジェクト指向に違反しているのでしょうか)

記載内容に不足ありましたら、ご指摘いただけると幸いです。
何卒よろしくおねがいいたしますm(_ _)m

■補足情報
使用している技術は、.NET Frameworkと、WPFです。
MVVMで設計し、ViewのDatagridに、List<Person>を表示することを想定しています。
※Entity FrameworkやDataTableは使いません。

C#

1class Person{ 2 // 名前 3 public string FirstName{get; set;} 4 // 苗字 5 public string LastName{get; set;} 6 // 子ども 7 public List<Person> Children{get; set;} 8 9 // コンストラクタ 10 public Person(){ 11 this.FirstName = string.Empty; 12 this.LastName = string.Empty; 13 this.Children = new List<Person>(); 14 } 15 // 氏名を返します 16 public string GetFullName(){ 17 string FullName = this.FirstName + this.LastName; 18 19 return FullName; 20 } 21 22 // 引数のpeopleから父親を返します 23 // 見つからない場合はnullを返します 24 public Person GetFather(List<Person> people){ 25 // Fatherをnullで初期化します 26 Person Father = null; 27 28 foreach(Person person in people){ 29 // personの子どもを確認していきます。 30 foreach(Person child in person.Children){ 31 // 子と自分の氏名が一致した場合は、子の親が自分の父親です 32 if(child.GetFullName() == this.GetFullName()){ 33 Father = person; 34 break; 35 } 36 } 37 } 38 39 return Father; 40 } 41} 42 43

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

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

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

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

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

Zuishin

2021/03/01 09:21

データベースへのアクセスかと思いますが、どのような技術を使っているかを書いた方が回答がつきやすいのではないかと思います。 Entity Framework や DataTable を使わないということですよね?
comet7360

2021/03/01 09:35

ご質問ありがとうございます。 はい、Entity FrameworkやDataTableは使用しません。 使用している技術としては、.NET Framework, WPFです。 WPF画面のDataGridにPersonクラスのリストを表示することを想定しています。
Zuishin

2021/03/01 09:41

よく意味がわかりませんが、DTO と DAO はそれぞれ何の略で何に使うものですか? データベースではなさそうですが。
comet7360

2021/03/01 09:48

■DTO:data transfer object  プロパティのみ定義し、メソッドは定義しない。 ■DAO: data access object  dtoを利用するメソッドのみ定義し、プロパティは定義しない。 になります。オブジェクト指向のオブジェクトを、更に細分化する感じでしょうか。。 (すみません、私自身もよく分かっていなく。。)
Zuishin

2021/03/01 09:56 編集

> オブジェクト指向のオブジェクトを、更に細分化する感じでしょうか。。 いえ、データアクセスの目的に使うために特定のデザインパターンに沿うよう作るものです。C# ではあまり使われません。 というと語弊がありますね。DAO を自分で作ることはめったにありません。
comet7360

2021/03/01 10:01

ありがとうございます。 ということは、質問のようなPersonクラスをDTOやDAOに分けること自体、 そもそもナンセンスということなのでしょうか。
Zuishin

2021/03/01 10:11

オブジェクトを DTO と DAO に分けるというのはどこからの情報なんでしょうか?
comet7360

2021/03/01 10:17

どこからの情報、ということはないのですが、 オブジェクトをDTOやDAOに書き分けるとしたら、どのようになるのかを知りたかったです。 そもそも、そういう分け方が不可能というか、考え方がおかしいのでしょうか。。
Zuishin

2021/03/01 10:28

そうですね。どこからの情報かというのがわかるなら真意を読み解くこともできるかもしれませんが、それがないのであれば、どうしてそうなったのかわかりません。
comet7360

2021/03/01 10:35

ありがとうございます。 >>真意を読み解くこともできるかもしれません この質問を起票した発端としては、「プロパティとメソッドを分離したい」という個人的な考えからです。 色々と調べたところ、DTOやDAOというの考え方が在ると知ったのですが、 実際にそれをPersonクラスに適用するにはどうすればよいか分からず、質問をさせていただきました。 そもそも「プロパティとメソッドに分ける」という考えがおかしい場合はその旨をご指摘いただけると助かります。
comet7360

2021/03/01 11:09

ありがとうございます。質問1の内容を訂正しました。 記載内容に不足ありましたらご指摘いただけると幸いです。
Zuishin

2021/03/01 11:11

> 1.以下のようなPersonクラスを、DAO/DTOパターンに書き分けることは可能でしょうか。 書き分けるというところにまず違和感があります。DAO/DTO パターンがどういうものか概略をまず知らなければどうにもならないと思うので、それを尋ねたらどうかという提案でした。
comet7360

2021/03/01 11:21

なるほどです。すみません。よくよく考えると私としては、 DAO/DTOパターンを知りたいというよりも、Personクラスをプロパティクラスと メソッドクラスに書き分けるという考え方が、アリかナシかを尋ねたいものでした。 (それをDAO/DTOという言葉に勝手に置き換えてしまっていました) 上記に沿って、質問の内容を訂正しようと思います。
BluOxy

2021/03/01 20:48

回答後になりますが、 > 「プロパティとメソッドを分離したい」という個人的な考え なぜそう考えたか、分離することによって何の問題が解決すると考えているのかが知りたいです。するとその辺りに関する回答ができるかもしれません。
Zuishin

2021/03/02 02:04

DAO と DTO がなぜ分離されるかと言うと、データベースは複数の種類があり、その違いを吸収するためです。つまり、あるデータベースに依存した DAO を別の DAO に取り換えても DTO は変更の必要がありません。これにより保守性が高くなります。DTO はデータにのみ依存するのでメソッドが必要ないのです。 一方、GetFather や GetFullName は Person に依存しており、分割する意味がありませんし、取り換える意味もありません。 分割する時には、分割された双方の依存を可能な限り小さくし、部品の取り替えを容易にするよう心掛ける必要があります。何も考えず機械的にメソッドだからプロパティだからという理由で分けるというデザインパターンは無いと思います。あるとすればそれは人間ではなく、IDE などのツールからの使用を前提としたものでしょう。 ただし、それはオブジェクト指向の話です。関数型であればまた別のデザインパターンがありますから、それを主軸に据えて設計するのであれば、結果的にメソッドとプロパティが分離されるということもあるでしょう。しかしそれはあくまでも「結果として」であり、最初から目指すものでも、原理主義的にこうでなければならないとルール付けするものでもないと思います。
comet7360

2021/03/02 13:32

>>BlueOxyさん >なぜそう考えたか、分離することによって何の問題が解決すると考えているのか 分離することによるメリットとして考えていたことは、主に以下の2つです。 ただ、いま思うと、2つとも主観的な内容(個人的なこだわり)ばかりかなと思っております。。 1.プロパティのみ定義したクラスを作ることで、見栄えがスッキリする。 2.メソッドは開発途中にあれこれ追加/変更/削除がありそうですが、  プロパティはそうそう顔ぶれが変わることは無さそう?なので、  プロパティとメソッドでクラスを分けることで誤ってプロパティを変更してしまうリスクを避ける。
comet7360

2021/03/02 13:52

>>Zuishinさん ありがとうございます。DAOとDTOが分離されることと、 Personクラスのメソッドとプロパティを分離しようとすることは、全然意味が違うのですね。 DAO/DTOの考え方を、このPersonクラスに適用しようとすること自体が誤りであると理解でき、スッキリしました。 おっしゃるとおり、DAO/DTOパターンを意識しすぎるあまり、 「なぜ分離するのか」をきちんと理解せず、手段が目的になってしまっていました。 (意識している割に理解できていないところが更に情けないです)
guest

回答1

0

ベストアンサー

1.以下のようなPersonクラスを、プロパティだけを定義したクラス、メソッドだけを定義したクラスに

分離することは、クラス設計の考え方としてアリでしょうか。ナシでしょうか。

DTOのような特定のプロパティやメソッドに絞る意味・目的があればありです。
なければなしです。

プロパティだけを定義したクラスは、DTOや自動生成されたクラス以外で基本的に使われないと思います。

プロパティのみ定義したクラスに分けることで、保守性を高める、など

そういったデザインパターンがあるのでしょうか

ないでしょう。むしろ、アンチパターンかと思います。
これはDDDという設計手法に存在する概念ですが、ドメインモデル貧血症という言葉があります。

ドメインモデル貧血症
「ドメインモデル貧血症」を見かけたので、誤解しないように備忘録

しかし、私はオブジェクト指向を意識したコーディングをするのであれば、たとえDDDという設計手法を用いらないとしてもドメインモデル貧血症にはならないようにすべきと思います。
プロパティのみ定義したクラスが無意味に、目的もなく存在するとオブジェクト指向的に読みにくい・理解しにくいコードが生まれるからです。

オブジェクト指向ではとにかく命名が重要です。プロパティのみ定義したクラスには必要があればメソッドを定義すべきで、命名はそのアプリケーションの機能に関連するべきです。

2.GetFather()メソッドのように、自分のインスタンスとは直接関係の無いデータを提供するメソッドは、

Personクラスの中に定義してはダメでしょうか。(オブジェクト指向に違反しているのでしょうか)

thisが書いてあるので、関係がない訳ではないように見えます。
下記条件を満たしているのなら、定義しても良いかと思います。

  1. GetFatherメソッドを定義することでそのアプリケーションの1機能を満たすこと
  2. 複数人で開発している場合は、このメソッドの命名から中のソースコードを見ずとも戻り値を大体イメージしてもらえること

ちなみに、私ならGetFatherメソッドを使うのではなくChildrenプロパティと同じようにプロパティで定義すると思います
※ところで、Personクラスには性別に相当する状態が定義されていませんが、どのようにしてFatherかMotherか判別するのでしょうか

DTOやDAOというの考え方が在ると知ったのですが、

実際にそれをPersonクラスに適用するにはどうすればよいか分からず

まず、comet7360さんの目的と選ぼうとしている手段に注目しましょう。

comet7360さんの目的はViewのDatagridに、List<Person>を表示することです。

それに対して、DAOを使うという手段は適切ではありません。
DAOはデータベースにアクセスするためのインターフェースを提供するためのオブジェクトです。
Viewでデータベースにアクセスしてはいけません。
ですから、Viewに表示することが目的であれば、むしろDAOを使ってはいけません

DTOを使うという手段も適切ではありません。
DTOとは、アプリケーション間で通信を行うのに用いるオブジェクトです。
Viewでアプリケーション間で通信を行ってはいけません。
ですから、Viewに表示することが目的であれば、むしろDTOを使ってはいけません

よって、PersonクラスへDAO/DTOの考えを適用する必要はありません。

オブジェクト指向ではたくさんのデザインパターンや考え方がありますが、それ等を知るときは名前やどんなものか(WHAT)だけを知るのではなく、なぜ・何のためにそれが生まれたのか(WHY)、その経緯を知りましょう。

経緯を知るとそのデザインパターンや考え方を適用したときにどんな目的を達成できるようになるのかが分かるようになります。

それも分かれば、現在抱えている自身の問題に対してそのデザインパターンや考え方を適用すべきか否かが判断できるようになります。

今回に関しても「Viewにデータを表示したい」という達成すべき目的、「データベースにアクセスしたい/アプリケーション間の通信に使いたい」という達成できる目的が合致していないことに気付くことができ、自己解決できるようになります。

投稿2021/03/01 20:38

編集2021/03/02 01:43
BluOxy

総合スコア2663

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

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

comet7360

2021/03/02 14:24

ご回答いただき、ありがとうございます。 ■質問1について このPersonクラスの内容と、私の目的を考慮した場合、プロパティとメソッドを分離する意味が無く、 むしろ可読性が下がるので分離すべきでない、ということを理解いたしました。 「プロパティとメソッドを部分クラスで書き分けてはどうか」 「プロパティのみ定義したクラスに拡張メソッドを追加してはどうか」 などと考えておりましたが、手段が目的になってしまっていました。 ■質問2について メソッド定義のガイドラインについて、ありがとうございます。 熟読して、自分の中に刻み込もうと思います。 GetFatherメソッドを、Fatherプロパティにしていない理由ですが、 このPersonクラスは、頻繁にChildrenの内容が置き換わることを想定しております。 ですので、Childrenの内容が変わるたびに、Fatherプロパティを更新する手間を省くため、 Fatherプロパティとせず、GetFather()としていました。 完全な後だし情報かつ、推測不可能な背景で申し訳ないです。 また、性別の属性が無いのでFatherかMotherか不明な点は、ご指摘の通りです。 質問させていただく材料として不十分だったと反省しております。 今回ご質問をさせていただいたことで、未だオブジェクト指向を理解出来ていないことが良くわかりました。 Zuishinさんも、私の容量を得ない回答に辛抱強くお付き合いくださり、本当にありがとうございましたm(_ _)m
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問