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

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

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

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

デザインパターン

デザインパターンは、ソフトウェアのデザインでよく起きる問題に対して、解決策をノウハウとして蓄積し再利用出来るようにした設計パターンを指します。

コーディング規約

コーディング規約とは、コードの書き方についての決め事のことです。 文法のことではなく、そのチームなどの中の約束事としてどのような書き方で行うかを定めるもの。 項目の例として、関数や変数の命名規則、コーディングのスタイル、括弧やインデントの書き方などが挙げられます。

Q&A

2回答

2918閲覧

クラス内のメンバのまとめ方

hiramaru

総合スコア48

C#

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

デザインパターン

デザインパターンは、ソフトウェアのデザインでよく起きる問題に対して、解決策をノウハウとして蓄積し再利用出来るようにした設計パターンを指します。

コーディング規約

コーディング規約とは、コードの書き方についての決め事のことです。 文法のことではなく、そのチームなどの中の約束事としてどのような書き方で行うかを定めるもの。 項目の例として、関数や変数の命名規則、コーディングのスタイル、括弧やインデントの書き方などが挙げられます。

0グッド

1クリップ

投稿2016/02/06 14:49

お世話になっています。

クラスの分割、メンバの配置についてご意見を伺いたく投稿します。

・メンバ変数はまとめて宣言すべきか(統合クラス1)
・メンバは部品ごとにわけるべきか(統合クラス2)
・メンバは扱うオブジェクトごとに分けるべきか(統合クラス3)
・子オブジェクトのメンバを親オブジェクトで再定義するのは冗長なので子オブジェクトへの参照を公開すべきか(統合クラス4)

などのさまざまなパターン、自分ならばこうするといったご意見をいただければ幸いです。

どうぞよろしくお願いします。

C#

1 2// 値を保持するクラス 3public class ComponentA 4{ 5 public int intValue; 6 public string stringValue; 7} 8 9// クラスAの値を表示するクラス 10public class ComponentB 11{ 12 readonly ComponentA componentA; 13 14 public ComponentB( ComponentA componentA ) { this.componentA = componentA; } 15 16 public void ShowIntValue() { Console.WriteLine( string.Format( "Parent Int Value is {0}", componentA.intValue ) ); } 17 public void ShowStringValue() { Console.WriteLine( string.Format( "Parent String Value is {0}", componentA.stringValue ) ); } 18} 19 20// クラスAの値を更新するクラス 21public class ComponentC 22{ 23 readonly ComponentA componentA; 24 25 public ComponentC( ComponentA componentA ) { this.componentA = componentA; } 26 27 public void UpdateIntValue() { componentA.intValue = 256; } 28 public void UpdateStringValue() { componentA.stringValue = "text"; } 29} 30 31// 統合クラス パターン1 32public class IntegratedClass1 33{ 34 readonly ComponentA componentA; 35 readonly ComponentB componentB; 36 readonly ComponentC componentC; 37 38 public IntegratedClass1() 39 { 40 componentA = new ComponentA(); 41 componentB = new ComponentB( componentA ); 42 componentC = new ComponentC( componentA ); 43 } 44 45 // ComponentA 46 public int intValue { get { return componentA.intValue; } } 47 public string stringValue { get { return componentA.stringValue; } } 48 49 // ComponentB 50 public void ShowIntValue() { componentB.ShowIntValue(); } 51 public void ShowStringValue() { componentB.ShowStringValue(); } 52 53 // ComponentC 54 public void UpdateIntValue() { componentC.UpdateIntValue(); } 55 public void UpdateStringValue() { componentC.UpdateStringValue(); } 56} 57 58// 統合クラス パターン2 59public class IntegratedClass2 60{ 61 public IntegratedClass2() 62 { 63 componentA = new ComponentA(); 64 componentB = new ComponentB( componentA ); 65 componentC = new ComponentC( componentA ); 66 } 67 68 // ComponentA 69 readonly ComponentA componentA; 70 public int intValue { get { return componentA.intValue; } } 71 public string stringValue { get { return componentA.stringValue; } } 72 73 // ComponentB 74 readonly ComponentB componentB; 75 public void ShowIntValue() { componentB.ShowIntValue(); } 76 public void ShowStringValue() { componentB.ShowStringValue(); } 77 78 // ComponentC 79 readonly ComponentC componentC; 80 public void UpdateIntValue() { componentC.UpdateIntValue(); } 81 public void UpdateStringValue() { componentC.UpdateStringValue(); } 82} 83 84// 統合クラス パターン3 85public class IntegratedClass3 86{ 87 public IntegratedClass3() 88 { 89 componentA = new ComponentA(); 90 componentB = new ComponentB( componentA ); 91 componentC = new ComponentC( componentA ); 92 } 93 94 // IntValue 95 public int intValue { get { return componentA.intValue; } } 96 public void ShowIntValue() { componentB.ShowIntValue(); } 97 public void UpdateIntValue() { componentC.UpdateIntValue(); } 98 99 // StringValue 100 public string stringValue { get { return componentA.stringValue; } } 101 public void ShowStringValue() { componentB.ShowStringValue(); } 102 public void UpdateStringValue() { componentC.UpdateStringValue(); } 103 104 // Components 105 readonly ComponentA componentA; 106 readonly ComponentB componentB; 107 readonly ComponentC componentC; 108} 109 110// 統合クラス パターン4 111public class IntegratedClass4 112{ 113 public IntegratedClass4() 114 { 115 componentA = new ComponentA(); 116 componentB = new ComponentB( componentA ); 117 componentC = new ComponentC( componentA ); 118 } 119 120 // Components 121 public readonly ComponentA componentA; 122 public readonly ComponentB componentB; 123 public readonly ComponentC componentC; 124} 125

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

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

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

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

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

guest

回答2

0

私の場合は、どのようなクラスにすべきかの前にどのように利用したいかを考えます。

統合クラスを作る意味がわからないです。

統合クラスを利用するクラスー>統合クラスー>コンポーネントBCー>コンポーネントA

というのは、どのような利点があるのでしょうか?

私の場合は

呼び出し側->コンポーネントA

と簡潔にします。その上で下記の様なコードにします。

C#

1public class Component 2{ 3 private int i; 4 private string s; 5 public Component(int i, string s){this.i = i; this.s = s;} 6 public int Int{ 7 get{return i;} 8 set{i = value;} 9 } 10 public int String{ 11 get{return s;} 12 set{s = value;} 13 } 14}

どうして1つのクラスにまとめた方が良いかというと、例えばComponentクラスと非同期処理に対応される場合、もともとのComponetCクラスで更新中にComponentBクラスでが呼び出された時変更前の値が表示されるか、変更後の値が表示されるかわかりません。

それを避けるためにはComponetCクラスで更新中はComponentAをロックする必要があります。ところがComponentAクラスの変数はpublicになっているため、スレッドセーフにはできません。そのため、ComponetAとComponentCは統合され、更新中の表示はロック出来るようにしておく必要があります。

これだけでなく実際の更新処理で様々な整合性を考える場合が多く、整合性が必要な範囲で、値を隠蔽化して更新する際への注意をクラス内に閉じ込めておく必要があると私は考えます。

値が隠蔽化されているため、直接変更はできなくなりましたが、現在の値を知る必要がある場合もあるでしょうしその利用のされ方はComponentAが管理すべきではありません。ということで、ConponentBは標準出力に値を返せるだけでなく、呼び出し元でどのような利用の仕方も許すべきと考え、統合されたComponentACに統合すべきだと考えました。

ただし、これはComponentAが扱う変数が2つであるためで、変数がもっと増えてくれば、統合されたConponetクラスを分割することを検討します。

投稿2016/02/07 14:49

iwamoto_takaaki

総合スコア2883

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

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

0

こんにちは。

う~ん、ComponentA, B, Cのように分割すると折角のクラスの良さを享受できませんね。
なので、そのように分割すること自体が私はほぼないです。(たぶん99.9%くらい?)
ですので、パターン3は私の選択肢には入らないです。
パターン4はそもそもクラス化する意味がないので、namespaceを使います。

バターン1と2に近い悩みはあります。メンバ変数とそれを主に操作する変数を近くに記述するのか、メンバ変数をまとめて記述するのかについて、結構悩ましいです。
関係がより深いメンバ変数とメンバ関数が近くにあった方が追いかけやすいです。しかし、どんなメンバー変数を持つのか纏めて見たい時もあります。この両方を同時に満たせる案があるとよいのですが...
結局、この点については、方針を持っていませんが、現在はまとめて記述する方に気持ちは偏っています。

メンバ変数をまとめると見通しが悪くなるような大きなクラスはクラス分割するべきなのかも知れないからです。まだ確信はないです。統合的なクラスは、本質的に密接な関係にある機能をまとめたものですから、下手に分割するとクラス間I/Fが増えて、却って見通しが悪くなります。常にそうならないように分割できるのか?トライしている最中です。

投稿2016/02/06 16:22

Chironian

総合スコア23272

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

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

hiramaru

2016/02/06 17:21

ご回答ありがとうございます。 たしかにこのクラス分割の場合、データ、入力、出力を分けただけであまり良い例ではないかもしれませんね…難しいです。 実際に統合しているのはたとえば、 ・座標を保持するクラス ・座標の移動を非同期で行うクラス ・座標の情報をビューに反映するクラス などです。 パターン1と2は常に悩みます。 統一したほうがよいとは思うのですが、クラスによってどちらの記述に寄るか変わってくる気がします。 たしかにまとめて見通しが悪くなるということは、メンバ変数の粒度がばらばらだということなのかもしれません。 パターン3は記述としては変更箇所がばらばらに配置されてしまうので危険だと思います。 しかしこのようにグループ分けして確認したい場合も多々あるので悩みます。 私が知らないだけかもしれませんが、VisualStudioの機能でソースコードをリアルタイムで表や図にしてくれる機能があったりしないでしょうか……。 個人的にはパターン4も統合クラスの記述が減るので統合クラスのインスタンスを大量に生成する場合などは選択肢としてありかなと思っています。 オブジェクト.座標コンポーネント.x オブジェクト.移動コンポーネント.目標地点に移動( 目標地点, 時間 ) などと書けるためです。 ただ、統合クラスには公開したいが統合クラスを扱うクラスには公開したくないコンポーネントのメンバが公開されてしまうのは危険だとも思います。 それでも公開範囲の設定のためだけに public void 命令() { コンポーネント.命令(); } などと書くのは冗長だなと感じます。 言語仕様として宣言だけで public through コンポーネント.命令; などと書ければ便利だといつも思うのですが、これはメタプログラミングの分野でしょうか…。 試行錯誤中のご意見もいただきありがとうございます。 考える方向性が増えてたいへん参考になります。
Chironian

2016/02/07 01:37 編集

こんにちは。 > 実際に統合しているのはたとえば、 > ・座標を保持するクラス > ・座標の移動を非同期で行うクラス > ・座標の情報をビューに反映するクラス > などです。 なるほど。汎用的なクラスとそれを特定の目的で操作するクラスなのですね。 確かに、おっしゃるような構造になることがありますね。(0.1%よりは多そうです。統合クラス的なクラス1つに付き、従属するクラスは数10個あり、一部の統合クラスがそのような構造を持つので、たぶん全クラスの1%くらい?) その場合、私はComponentAのインスタンスは、統合クラス内のグローバル変数的な位置づけとなり、統合クラスが持つ各メンバへ配布します。なので、統合クラスのコンストラクタ付近に置いて、コンストラクタにて配布してます。 なお、ComponentB, Cのメンバ関数を単純に中継して統合クラスから公開することは少ないです。結果として統合クラスが何らかの加工して公開することが多いですので。 でも、ComponentB, Cの機能の一部をそのまま公開すれば良い時も稀にあり、手を抜いてComponentB, Cをインスタンス毎全部公開することもあります。 ただし、内部に閉じたクラス限定です。統合クラスを多くの人が使う場合は、不用意に公開するのはやはり避けます。後で自分が痛い目にあいますから。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問