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

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

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

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

Q&A

解決済

2回答

661閲覧

Classの設計で悩んでいます。

meshkit

総合スコア72

C#

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

0グッド

0クリップ

投稿2018/02/28 05:43

編集2018/03/01 02:40

前提・実現したいこと

Classの設計で悩んでいます。
WindowsFormのアプリケーションを開発しています。
MenuWindow(一覧)から、複数の子フォームを開きます。
子フォームはそのデータの詳細を表示します。
ModelをPerson(People)として、

該当のソースコード

C#

1namespace PersonModel 2{ 3 public class Person 4 { 5 public string Name { get; set; } 6 public DateTime Birthday { get; set; } 7 public List<Bottle> Bottles = new List<Bottle>(); 8 } 9}

C#

1namespace PersonModel 2{ 3 public class Bottle 4 { 5 string BottleName { get; set; } 6 int BottlePower { get; set; } 7 } 8}
private void OpenChild_Click(object sender, EventArgs e) { Form2 form2 = new Form2(); form2.Show(); }
としてMainWindowからForm2を開きます。 この場合、 (1)子フォームに表示するPerson2は、どこにもつのがよいか? (2)Form2にPerson2をもつとしたら、Person2のInitializeはどこでおこなうのがよいか? (2-1)Form2のコンストラクタ? (2-2)MainWindowのOpenChild_Click

C#

1 private void OpenChild_Click(object sender, EventArgs e) 2 { 3 Form2 form2 = new Form2(); 4 form2.Person2 = new Person(); 5 form2.Person2.Name= "桐生戦兎", 6 form2.Person2.Birthday = new DateTime(1994, 06, 13), 7 form2.Show(); 8 }

###追記
Personのインスタンスはいくつ必要か?->Personは画面と一致しているので約10です。
Personへの入力はどの画面か?->MenuFormとForm2です。基本情報をMenuでいれて、詳細をForm2で入れます。
Personを表示するのはどの画面か?->名前だけはMenuForm、詳細はForm2です。

補足情報(FW/ツールのバージョンなど)

Visual Studio 2015 Pro

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

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

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

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

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

kikukiku

2018/02/28 07:06

Personのインスタンスはいくつ必要か?Personへの入力はどの画面か?Personを表示するのはどの画面か?などの外部仕様を明確にする必要があると思います。
guest

回答2

0

ベストアンサー

私がよく採用するのは、UIとデータインスタンスを分離する方法です。

データインスタンスを集中的に管理するクラス(以降Contextクラスとします)を定義し、そのインスタンスをアプリケーションの開始時(またはメインフォームの初期処理など)で生成します。

Contextクラスには Person や Bottle などのインスタンスを生成したり、現在生成されているインスタンスを保持したりする機能を実装します。

Form2 を開く前にPerson インスタンスを生成し(もしくは保持されている中から対象を取得し)、Form2のコンストラクタを通じて Person のインスタンスを渡します。

投稿2018/03/01 03:37

masa_n

総合スコア110

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

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

meshkit

2018/03/01 04:25

コメントありがとうございます。 UIとデータインスタンスは分けたいです。 やはりMainFormの初期処理でContextを全部作る方向ですよね。 これだと、MainForm中にPerson2,3,...のContextを置くことになりませんか? Form2,3...でそれを呼ぶのなら、Form2にPerson2があるほうが自然に思えるんです。 今回の場合、MainFormの初期処理ではContextを初期化はできるのですが、Context(Person2,3...)の細かいプロパティは、MainFormとForm2,3,...で入力し、その入力値を保持しなければならないのです。 実際には、個別のForm2のclassnameは、 Rider2018MainRiderForm とかで、 Rider2018MainRiderPersonModel とかなので、並べて書くと Rider2018MainRiderForm.Rider2018MainRiderPersonModel.RiderName = "桐生戦兎", Rider2018MainRiderForm.Rider2018MainRiderPersonModel.Birthday = Rider2018MainRiderForm.Rider2018MainRiderPersonModel.Bottles.Add(new Bottle("ラビット")); Rider2018MainRiderForm.Rider2018MainRiderPersonModel.Bottles.Add(new Bottle("タンク")); とかになってしまい、なんというか。可読性が。 ClassNameはこれは例で、実際には、 接頭辞2+業務コード3+業務名(英語)約30文字+Form.cs とかなのです。これはもう省略しようもなく。 つけたのは自分ですが、業務名は全部初めての単語で毎日見ているうちに覚えました。 覚えるためにはこれがいちばんよかったです。個人の感想ですけど。 でも長いのがなー。 略語を使う気はありませんでした。もともと初めての用語なので、略すともうちんぷんかんぷんです。
masa_n

2018/03/01 04:49

context はいくつもつくるものではありません。データオブジェクトを集中的に管理するための器として紹介しました。 このようなクラス設計の考え方を学ぶなら「デザインパターン」に目を通してみてはいかがでしょうか。ネットを探ればいろいろな記事がありますし、書籍もでています。細かな要件は私にはわかりませんので推測になりますが、今回の場合、Flyweight+Factoryパターンが該当するような印象です。
meshkit

2018/03/01 04:53

ありがとうございます。参考にします。
meshkit

2018/03/01 05:07

まさにFlyweight パターンでした。ありがとうございます!!!!
guest

0

私がやるなら、
Form2のコンストラクタの引数に name と birthday を与えて、そのコンストラクタで生成、初期化しますねー

-- Form2 -- public Form2(string name , DateTime birthday) { Person2=new Person(); Person2.Name=name; Person2.Birthday=birthday; -- モロモロ -- }

投稿2018/02/28 07:06

編集2018/02/28 07:15
y_waiwai

総合スコア87749

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

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

meshkit

2018/03/01 00:44

ありがとうございます。 やはりコンストラクタですかね。 Person2のインスタンスは、Form2にStaticでもつ感じですか?
y_waiwai

2018/03/01 01:49

Parson2はstaticではなく通常のクラス変数で持ちます そうしないと、複数のForm2を生成/表示したり出来ませんね さらに言えば、可能であればPerson2は外部からは隠蔽するために privateをつけます。
meshkit

2018/03/01 02:42

なるほど。 ご回答いただいて頭を整理できてきました。 複数のForm2は作らないのです。 Form2はPerson2と完全に一体化していて、Person3にはForm3が、以下Person[n]とForm[n]が対応します。 大量のデータは、Person2のなかの、たとえばBottleModelとかで扱います。 なので、今回はstaticなのかなと。 追記しました。
masa_n

2018/03/01 03:52

> public Form2(string name , DateTime birthday) Personクラスにプロパティが増えたときの影響が大きくなりませんか? プロパティの値を呼び出し側で持っているなら、呼び出し側でインスタンスを生成して渡した方が利点が多いと思います。
meshkit

2018/03/01 04:09

masa_nさん、コメントありがとうございます。 そうですね。PersonClassは実際には30くらいプロパティやらなにやらを持っているので、渡すときにはインスタンスごと、ということになると思います。 呼び出し側(Menu)でインスタンスを生成することの悩みは、Menuは全体を見るものなのに、個別の10個の細かいデータがあることです。 30プロパティ*10人(=10画面)で300個も初期化しています。 これでソースの見通しが絶望的に悪く。 それでMenuでなく、個別の情報は個別のForm2,3...で扱いたいのだけど、それだとMenuに一覧を出せない。
y_waiwai

2018/03/01 04:15

永続的に使うもんなら、メインユニットで、たとえばParson のリストを生成してそこにおいといて、Form2やForm3にはCreate時に値(だけ)を渡して、Form2内でParsonのインスタンスを生成してその中だけで完結させます しょせんフォームというのは手足でしかありません。あらゆる処理を司るメインユニットはアタマとして分離しておき、手足が勝手にアタマのナカミをいじくるようなことをさせるのは間違い、ということにしておきます。 アタマは手足に必要なデータ(だけ)を与え、手足がそれを変更する必要があるなら、アタマにそれを通知し、アタマがそれを読み出し、アタマのナカミを修正する、という手順を踏むべき、という考え方ですねー #別回答のUIとデータインスタンスの分離、というのと同じことですね
masa_n

2018/03/01 04:15

ですので、UIとデータを分離したほうがいいのではないかという考え方に向かうのではないでしょうか。Person を Form に渡すのと同じ考え方で、Menu にも Person を渡すように考えることはできませんか?
Zuishin

2018/03/01 04:15

初期化するクラスを Menu から切り離して独立したクラスにすればいいのでは? 初期化データもコード内に直に埋め込むのではなく XML や JSON やデータベースを使って外部で保存し、ループを使って初期化するのが普通です。
meshkit

2018/03/01 04:29

みなさま、コメントありがとうございます。 いま悩んでいることをすこしmasa_nさんへのコメントで整理というか吐き出せました。 おっしゃるとおり、初期化はメソッドで分けてます。独立したClassにするのもありですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問