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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C#

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

オブジェクト指向

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

Q&A

解決済

2回答

2576閲覧

【オブジェクト指向】クラス設計で、インスタンス変数にするか、戻り値にするか他

HelloWorld2

総合スコア32

C#

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

オブジェクト指向

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

0グッド

1クリップ

投稿2019/05/07 07:06

編集2019/05/07 07:08

処理概要

  • APIを実行してデータを取得し、2つの異なる格納先にInsertします。(DBと別のストレージ、具体的にはAzureのTableStorage。ストレージはバックアップ用)
  • APIは複数回実行するため、「API実行→DB用エンティティ作成・リストに追加→ストレージ用エンティティ作成・リストに追加」の処理をすべて実行した後、最後に2つのリスト内のエンティティをループしてInsertします。(コネクションを1回にするため)

クラス

作成するクラスは以下を想定します。(下記の質問で一部まとめたりしています)

  • 呼び出し元クラス(コントローラ)
  • API実行クラス
  • DBエンティティ作成クラス
  • ストレージエンティティ作成クラス
  • DBInsertクラス
  • ストレージInsertクラス

質問内容・シーケンス図

試行錯誤して、いくつかシーケンス図を作ってみましたが、何がベストプラクティスかがわかりません。

  • リストを保持すべきクラスはどこでしょうか?(コントローラか、エンティティ作成クラスか、Insertクラスか)
  • API実行、DBエンティティ生成、ストレージエンティティ生成の呼び出し元はどこが良いのでしょう?(呼び出しは依存させた方がよいのか、させない方がよいのか、実行順序が重要な場合は依存させた方が良い・・・?)
  • 各エンティティクラスのinデータはJSONデータがよいのでしょうか?(同じようなJSONデータの取り出し処理をするのは嫌だなぁという感覚です)
  • エンティティ生成と登録処理は、同じクラスがよいのでしょうか?(凝集性的には同じクラスが良いと思いますが、単一責任原則的には別の方が良いのかなと。また、エンティティ作成処理は20~30行の処理なので、行数的にも分けた方が良いのかなと)

イメージ説明
イメージ説明
イメージ説明
(一番下のシーケンス図が良いのかなと考えています)

その他

これが絶対に正解!というものはないかもしれませんが、一般的に良いとされる設計がどのようなものか、知りたい次第でございます。煩雑で申し訳ございませんが、よろしくお願いいたします。

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

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

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

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

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

guest

回答2

0

ベストアンサー

メッセージの設計がまだ曖昧だからでしょう。
メッセージの内容が具体的になると、継承させた方が良いとか、クラスの構成もまた変わってくると思います。

クラス設計の場合、ロジック部分よりもデータに主眼を置いて設計する方が良いと思いますよ。

投稿2019/05/07 07:26

sazi

総合スコア25174

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

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

HelloWorld2

2019/05/07 07:35

ご回答ありがとうございます。 追加で質問ですが、「メッセージ」とは何を指していますか・・・?
HelloWorld2

2019/05/07 07:58

なるほど、ありがとうございます。 「メッセージ設計が曖昧」というのは、「jsonデータ」のデータの内容を把握できていないという意味でしょうか? 上記の意味合いでしたら、jsonデータの内容は明確にはなっています。(一応動くものはできていて、リファクタリングしているところです) (たぶんクラス設計の知識が不足しすぎているため、そう認識してしまったかと思います、すみません) jsonデータが明確になった後の次の工程は何でしょうか?
sazi

2019/05/07 08:20

メッセージの構成要素である項目はクラス内でどのように拠出されるのかを明確にします。 画面での入力なのかDBなのかなどを検討しつつ画面遷移も合わせて検討することになります。 メッセージの形式をどうするかはクラス間の連携の方式に依存しますので、副次的なものです。 ここで言いたいのは、メッセージをどのように持ち回るかを考えると良いだろうという事です。 どのタイミングでDBに格納する必要があるかとか、セッション情報に保持しておくべき情報であるとか。
sazi

2019/05/07 08:24 編集

リファクタリングするなら、尚の事、俯瞰的にデータからのアプローチをすると良いと思います。
HelloWorld2

2019/05/07 08:59

> ここで言いたいのは、メッセージをどのように持ち回るかを考えると良いだろうという事です。 > どのタイミングでDBに格納する必要があるかとか、セッション情報に保持しておくべき情報であるとか。 なるほど、「ロジック部分よりもデータに主眼を置いて設計する」の意味が分かりました。 が、処理をどのクラスから呼び出すか、データをどう持ちまわるかの選択肢はいくつもあると思いますが、どのような基準で選択すればよいのでしょうか?この疑問が今回の質問の主となる部分です。
sazi

2019/05/07 09:19

拠出元が同じデータ(例えばDB)に何度もアクセスしているような場合は、その必要が無いようにインスタンス内にメンバーとして保持するとか、同じデータを別々に保持しているものを統合する等の、アクセス効率を考えてリファクタリングすれば良いのじゃないかと思います。
guest

0

とりあえず↓サイトを参考にどうぞ
インフラストラクチャの永続レイヤーの設計

DBエンティティ作成クラス/ストレージエンティティ作成クラスの戻り値のエンティティがどういうものを想定しているのかわからないのですが、
以下は作成クラスの処理内容がJSONからDTOへのマッピング、という前提で話をしてます

API実行、DBエンティティ生成、ストレージエンティティ生成の呼び出し元はどこが良いのでしょう?(呼び出しは依存させた方がよいのか、させない方がよいのか、実行順序が重要な場合は依存させた方が良い・・・?)

まず処理の目的はなんなのか分析してみたらどうでしょうか
例えばユーザー(コントローラーを呼び出す側)のやりたいことが、データを取得して後に利用するため保持しておきたいだけならば
“API”を用いて取得することや、DBへの登録/ストレージへのバックアップという(どこにどうやって保存するなどの)詳細は関心事ではない
というような分析です

このような分析なら、データ取得処理の抽象化/永続化処理の抽象化をしてあげるとよいでしょう

C#の場合、インターフェースを使うことになるでしょう
例えば、データの永続化処理は別namespaceに分けて、それにはインターフェースを通してアクセスする形式にするなどです
テストのモックも作りやすくなりそうですね

エンティティ生成と登録処理は、同じクラスがよいのでしょうか?(凝集性的には同じクラスが良いと思いますが、単一責任原則的には別の方が良いのかなと。また、エンティティ作成処理は20~30行の処理なので、行数的にも分けた方が良いのかなと)

一般に、単一責任原則を満たすと凝縮度は高くなると言えますから、ちょっと混乱している印象を受けました

以下、単一責任原則の参考にどうぞ
https://code.tutsplus.com/ja/tutorials/solid-part-1-the-single-responsibility-principle--net-36074

単一責任原則的には、エンティティ登録処理を呼び出す側が単一であれば一クラスにまとめてよいと思います
つまり、取得されるJSONの形式が一部異なることがあるとか、JSON以外の形式のデータを取得する場合があるとかで、登録処理にくっついた生成処理の中に分岐を作るような可能性がなければありです

ただ、僕個人としてはたぶんマッピング専用クラスを作っちゃいますね
データの登録と、JSONからDTOへの変換、を密に結合する必要は大抵の場合ないと思います
マッピングクラスは特別な事情がなければstaticなものにします
できれば自動生成する仕組みを用意してあげるとよいでしょう

各エンティティクラスのinデータはJSONデータがよいのでしょうか?(同じようなJSONデータの取り出し処理をするのは嫌だなぁという感覚です)

括弧内の意味がちょっとよくわからなかったのですが、各エンティティクラスとは、登録するクラスのことですか?
その場合、↑で何度か述べていますが、その登録クラスのInputになるデータの形式が将来的にJSON以外もありえるか検討しましょう

僕個人としては、JSONよりもDTOの方が取り回しが良いかと思います

また、単体テストの難易度がどうなるか、という観点で考えてみるとよいでしょう
例えば、ローカル環境で実際にテーブルアクセスして登録できたか確かめるテストを作成するとき、InputとしてJSONを作成するのは簡単ですか?また、変更があった時、テストのメンテはしやすいでしょうか?

リストを保持すべきクラスはどこでしょうか?(コントローラか、エンティティ作成クラスか、Insertクラスか)

コネクション/トランザクションの管理をどう行っているのか不明なのであまりはっきりとしたことは言えませんが、
ループでリストを作って、そのリストを別のループで回してInsertするよりは、一つのループ内で済ませてしまうほうが良いかと思います

フレームワークの制約などでそのようにできない場合は、

エンティティ作成クラスは単純なMapperであった方がいいと思うので、コントローラか各Insertクラスに持たせてしまうとよいでしょうね
コントローラに持たせる場合、普通のローカル変数で、データ取得処理で取得したものをMapperで変換しながらどんどん追加していき、最後にInsertクラスで処理する感じになりますかね

あるいは、各InsertクラスにQueueの性質を持たせることも考えられます
単一のDTOを引数にとるputメソッド的なものを持たせて、Insertクラス内のプロパティにどんどん追加していき、最後にInsertメソッドを実行するようなイメージです

アーキテクチャ設計(MVCやクリーンアーキテクチャなど)がどうなっているかでもまた変わってきますが、とりあえず以上です

投稿2019/05/16 12:50

編集2019/05/16 12:58
kanaria007

総合スコア67

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問