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

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

詳細はこちら
ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

C#

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

オブジェクト指向

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

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

4回答

4537閲覧

[設計]クラスを何階層か呼び出す場合のデータ受け渡し方法

J-GUN

総合スコア24

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

C#

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

オブジェクト指向

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

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/12/10 12:12

クラスAがクラスBを生成しそのメソッドbを呼び出す
メソッドb内でクラスBがクラスCを生成しそのメソッドcを呼び出す
・・・
という階層構造になっている場合、クラスAの外から与えられたデータはどのように下位のクラスに与えていくのがよいのでしょうか?
いくつか案は考えてみたものの、どれも一長一短というかしっくり来てないです。

仮にあるファイルにクラスA~Cが使うパラメータが保存されているとして
案1 クラスA~Cでそれぞれファイルを読み込む
→何度も同じファイルにアクセスしたくない、読み込むタイミング次第ではデータの整合性が怪しい、ファイルフォーマットが変わった場合にすべてのクラスが影響を受ける(ファイル読込を基底クラスにする手もありますが)など
案2 ファイル読込クラスを作成し、それがすべてのデータを持つ。読込クラスを引数やセット関数でクラスA→B→Cとリレーしていく
→仮にファイル読込からGUIでの設定に変わったら?などを考えるとクラス間の結合が強すぎる気がする
案3 ファイル読込クラスから、設定データ全てを保持するクラスにデータを渡し、それをクラスA→B→Cとリレーしていく
→(案2も同様ですが)クラスCからしたら関係ないAやBのパラメータが見えるのはどうなのか?
案4 クラスAにはA・B・Cが使うパラメータをすべて渡す、AからBにB・Cが使うパラメータをすべて渡す、BからCにCが使うパラメータを渡す
→処理が重複しているような・・・、階層が深くなると渡すデータが増える(仕方ない?)

どういう設計にするのが妥当なのでしょうか?
あるいは階層構造のように呼び出すこと自体を見直したほうが良いのでしょうか?

抽象的な質問で申し訳ありません。
クラス設計(以前の問題かもしれませんが)にお詳しい方がいましたらアドバイスいただけると助かります。
よろしくお願いいたします。

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

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

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

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

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

m.ts10806

2019/12/10 12:30

言語を限定しないのであれば言語のタグははずしてください
guest

回答4

0

ベストアンサー

ドメイン駆動設計(DDD)の思想を参照すると基本的に

  • 一番上にUI(ページやウィンドウなど)やAPIなどの「機能を実装する出口」があり
  • その下にデータや機能を集約するクラス(MVCで言えばコントローラー、DDDで言えばドメイン知識やユースケース)があり
  • さらに土台部分(MVCのモデル、DDDのリポジトリー)にデータ入出力処理の複雑さを隠蔽するクラスがある

ようなイメージです。

ファイル読み込みに関しては3番目の土台部分であり、リポジトリークラスによって「データの読み込み方法」をサポートします。そのリポジトリークラスを他の上位層のクラスが利用します。逆にリポジトリークラス等下位層のクラスは上位層の事情を一切知っている必要はありません。ここで関心の分離ができていることが重要です。

一方でファイルの変更監視はアプリ要件(上位層)に由来によるもので、DBアクセス等の下位層ではなく、2番目のユースケース層(または一番目のUI層)で実装します。

ファイル内容変更はイベントとして実装して、他の機能に変更通知をブロードキャストします。変更範囲を絞って上に上に伝播させる場合、その都度文脈を上書きして別のイベントとして実装する必要があるので手間が掛かります。

ですので

  1. ファイル変更を検知してファイル内容をクラスに変換する
  2. 変換したクラスをイベントとして他機能に伝播するa
  3. イベント経由で受け取った変換したクラスを使ってあれやこれやする

というようにシンプルに管理するといいように思います。

あるいは、ファイル変更からたくさんの作業が連なっているとするなら、その作業を集約し、作業の流れを管理するユースケースクラスを立てて、変更イベントを受け取る役目を少数に絞る形を取るのもいいかもしれません。


依存関係の管理は基本的に「Dependency Injection」(依存関係の注入)を扱うライブラリを使うとかなり便利です。抜け漏れが減ります。ただしここまで説明してきたドメイン駆動設計などのレイヤーを意識したクラスの依存関係管理が出来ていないと破綻します。(上位層が下位層を利用する、下位層は他に依存しない、という単方向の依存性が重要)

まずはドメイン駆動設計等の設計思想に触れてみるなど、複雑さを説明可能にする思考ツールを手に入れることをオススメしたいと思います。

投稿2019/12/11 01:11

tor4kichi

総合スコア769

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

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

J-GUN

2019/12/11 12:52

回答ありがとうございます 例のクラスA・B・Cから離れた説明のため若干とっつきにくかったですが、ドメイン駆動設計の図と比較して見てみると話の意図がつかめました ドメイン駆動設計に触れたことはなかったので、今後のために学んでみようと思います 今回の回答だけでなく、今後の方向性もアドバイスいただけたことからベストアンサーにさせていただきます
tor4kichi

2019/12/11 13:28

一方的な説明をしてしまったのでちょっぴり恐縮しているところです。 ついで、といってはなんですがドメイン駆動設計だけでなく「SOLID原則」もよい考え方ですのでオススメさせてください。 https://postd.cc/solid-principles-every-developer-should-know/ クラス設計、特に複数クラスを連携させるという場面でSOLID原則は非常に良い指針となると思います。設計理論の適用は実践を通して少しずつとなるかと思いますが、きっと良い武装になると思います。
J-GUN

2019/12/19 08:18

返信が遅くなり申し訳ありません わざわざありがとうございます SOLID原則についても時間を見つけて学んでみようと思います ご丁寧にありがとうございました
guest

0

クラスA,B,Cが、どのようにパラメータにアクセスするかという観点からみると、案1,2,3は基本的に同じで、実装の仕方だけが違っているように見えます。案2は、案1のファイルアクセスを抽象化してクラスにまとめただけですし、案3は、さらにファイルアクセスの実装と結果のデータを別のクラスに分離しただけです。この三つの中でどれを選択するかは、基本的にパラメータを保持しているデータソースの性格によるでしょう。ファイルフォーマットが変わる可能性があるのなら、案1はなしですね。もし、パラメータが実行中に変わり、A,B,Cの動作もそれに合わせて変えなければならないのなら、案2になります。

ちなみに、案2で

仮にファイル読込からGUIでの設定に変わったら?などを考えるとクラス間の結合が強すぎる気がする

とありますが、そんなことはないと思いますよ。ファイル読込クラスのインターフェースをきちんと設計すれば、ファイルフォーマットが変わってもも、データソースがファイルからGUIに替わっても、A,B,Cのコードを変更せずに済むはずです。(そういった意味では、ファイル読込クラスというより、パラメータクラスと言ったほうがいいかも)

もし、パラメータが必要なのが、最初にA,B,Cをインスタンス化するときだけに必要で、パラメータは変わらない、あるいは変わっても既存のインスタンスには関係ないのなら、案4も悪くないと思います。

階層が深くなると渡すデータが増える

とありますが、クラスAの利用者からはBやCを内部で使っていることは見えないはずで、つまり、利用者からはBの機能もCの機能もAの機能の一部に見えます。なので、Aに必要なデータをすべて渡すのは当然のことでしょう。「階層が深くなると渡すデータが増える」というのは、利用者からは「Aでやることが増えたのでデータが増える」ということです。もし、Aがなんでもかんでも処理するクラスで、訳が分からなくなっているのなら、A,B,Cクラスの見直しも視野に入れたほうがいいでしょう。

投稿2019/12/10 18:33

Bearded-Ockham

総合スコア430

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

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

J-GUN

2019/12/11 12:44

回答ありがとうございます たしかにパラメータクラスと考えれば、そのパラメータをファイルから取得するかGUIから取得するかはクラスA・B・Cからは関係ないため違和感はあまりなさそうですね またこの構造だと外から見たときAの仕事が多くて複雑化しているというのは薄々感じていたため、大元の見直しは(可能なら)したほうがよさそうですね ケースごとの説明がありわかりやすかったです、ありがとうございます
guest

0

私も同じようなことを考えることがありますが、ケースバイケースな上思想も混ざってくるので明確な答えは出ないと思います。
・A, B, Cの階層構造に本質的な意味があるのか
・A, B, Cを階層構造以外の構造で用いることはあるのか
・AはB, BはCを必ずもつのか
・パラメータ自体階層構造になっているのか(またはA, B, Cの設定が独立しているのか)
などの条件によって設計は大きく変わってくるはずです。

例えば階層構造以外にもB単体で利用することがあり得るのであれば案3は不適切です。
例えばAが実用上精々数個しか生成されないことが保証されており、階層が深くて複雑な場合などは思い切ってデータをstaticに管理してしまう方がスッキリすることもあります(何かの装置専用の小規模プログラムなど状況は限られると思いますが...案1みたいな発想が出る時点で以外と限定的な用途だったり?)

とりあえず案1, 案2はファイル読み込みの問題なのでこれはないかと。
データ保持クラスと「ファイル読み込み⇒データ保持クラスのインスタンス生成」を別個に作ればいいですし、例えばC#ならSerializerが用意されています(JsonなりXmlなりテキストで編集可能な形式で保存可)

投稿2019/12/10 14:23

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

J-GUN

2019/12/11 12:33

回答ありがとうございます 別の回答でもありましたが、やはりケース次第ということですね 基本的に限定的な用途のプログラムにかかわることが多いのでstaticにしてしまえば楽なのは間違いないですね、ただ楽に作れる反面「いいソース」からは遠ざかるので・・・ 案1・2はなし、案3は限定的にOKという感じでしょうか
退会済みユーザー

退会済みユーザー

2019/12/11 13:59

勿論楽するための安易なstaticはNGですが良いソースを考えるときに必ずしもstaticがNGという訳ではないと思います。 例えばプログラム上複数存在すると不都合が生じるものである場合はstaticにするして単一性を明示する方が良い場合があります。 何かのボードの制御用クラスのように、インスタンスが複数あると逆に問題が起きる可能性があるものなどです。 勿論Singletonパターンでも良いと思いますが、遅延初期化や継承を用いない場合は両者にあまり本質的な違いはないと思っています(間違っていたらすいません)
guest

0

こんにちは。

抽象的に考えると答えはでないと思います。
クラスA,B,Cがアクセスするデータが本質的に1塊なのか、そもそも独立したデータを1つにまとめているだけなのかで設計は変わってきますよ。

投稿2019/12/10 13:06

Chironian

総合スコア23272

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

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

J-GUN

2019/12/11 12:31 編集

回答ありがとうございます さすがに条件が抽象的すぎましたかね・・・一意に回答が決まるほど簡単ではないようで データの質を考えた設計が必要ということですね
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問