Byrefの引数の値の変更について

タグの編集
投稿者 社会人  (社会人) 投稿日時 2008/11/14 06:19:50
第34回 値型と参照型
http://homepage1.nifty.com/rucio/main/dotnet/shokyu/standard34.htm
にて

>みなさんは本当に必要のない限りメソッドやプロパティの中で引数の値を変更するのは避けるようにしましょう。そのような方法でプログラムしていると、プログラムが巨大になるほど収拾がつかなくなってしまいます。

との記載がありますが、
「グローバル変数はだめ」というのは良く言われているので
アプリケーション内で共通の設定(変数)をひとつのクラスにまとめて
アプリ内の各クラスやプロシージャに対して、BYREFで引数として設定を渡しています
よって、Byrefでの引数である「設定」情報を各クラスから変更しています
これはあまりよくないことなのでしょうか?


投稿者   (社会人) 投稿日時 2008/11/14 06:59:24
こんにちは。



んと、まず、クラスインスタンスを生成してるんですよね?byrefじゃなくてよろしいのでは?参照渡しと値渡しを復習なされることをオススメします。

本題。
アプリケーション全体の設定の変更を別の機構から行うことの是非ですが、これは時と場合によると思います。

あなたがまだオブジェクト指向プログラミングについて造詣が深くないとすれば、クラス間の関係が切り放せてない可能性も十分にありますが、そうでないとしても、必然性があれば、やっても問題ないと思います。

僕も、例えば、
いずれ作る予定のクラスに実装するつもりだけど、
優先順位の高い他のクラスを早いとこコーディングしなきゃならないから
後回しにしたい簡単なメソッドとかは、
とりあえずMY名前空間にモジュールを作って
一時的しのぎしたりしてます。



とまぁ、あなたの状況がよくわからないので、僕の例を参考までに。
投稿者 うたひこ  (社会人) 投稿日時 2008/11/14 06:59:37
こんにちは。



んと、まず、クラスインスタンスを生成してるんですよね?byrefじゃなくてよろしいのでは?参照渡しと値渡しを復習なされることをオススメします。

本題。
アプリケーション全体の設定の変更を別の機構から行うことの是非ですが、これは時と場合によると思います。

あなたがまだオブジェクト指向プログラミングについて造詣が深くないとすれば、クラス間の関係が切り放せてない可能性も十分にありますが、そうでないとしても、必然性があれば、やっても問題ないと思います。

僕も、例えば、
いずれ作る予定のクラスに実装するつもりだけど、
優先順位の高い他のクラスを早いとこコーディングしなきゃならないから
後回しにしたい簡単なメソッドとかは、
とりあえずMY名前空間にモジュールを作って
一時的しのぎしたりしてます。



とまぁ、あなたの状況がよくわからないので、僕の例を参考までに。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2008/11/14 07:13:07
グローバルな物が一概に駄目というわけではありません。
設定情報としては、「My.Settings.~」がよく用いられますが、
これもある意味では、アプリケーション全体にグローバルと言えますし。


> 共通の設定(変数)をひとつのクラスにまとめて
その共通設定クラスが、どのように管理されているのかが重要かと思います。
たとえば、アプリ内では、常に唯一の設定情報しかないように実装する場合もあれば、
複数の設定を用意しておき、それらを切り替えて使えるようにする場合もあるでしょう。

また、どのクラスがどのタイミングで生成されるのか/各設定値は読取専用になっているのか
それとも書換可能になっているのか…といった点も考慮して設計されると良いでしょう。


> BYREFで引数として設定を渡しています
まずは本当に ByRef でなければならないのかを確認してみてください。
共通設定クラスのメンバ操作を行うだけであれば、ByVal で十分なはずです。

一般論で言えば、ByRef 引数が必要になることは稀だと思います。
.NET Framework の標準クラスを眺めて見ても、ByRef はあまり使われておらず、
引数を書き換える必要がある場合(TryParse など)にのみ利用されている程度です。


> Byrefでの引数である「設定」情報を各クラスから変更しています
「各クラス」というのがどのような物であるのか分かりませんが、個人的には、
共通設定があちこちのクラスから変更されるような設計は、避けておいた方が
良いと思いますよ。管理が煩雑になってしまいますから。

共通設定を、(書き換えるのではなく)利用するだけであるならば、各クラスのメソッドに
引数として逐一渡すのではなく、コンストラクタで最初に渡しておくというのも手です。
投稿者 うたひこ  (社会人) 投稿日時 2008/11/14 07:25:45
あ、すみません、また魔界の仮面弁士さんとかぶってしまいました。

その上二重投稿してしまいました。(削除すると怪しまれるので致しません。)

大変失礼いたしました。
投稿者 社会人(質問者)  (社会人) 投稿日時 2008/11/15 14:20:43
みなさまレスありがとうございます

現在作っているアプリはエクセルみたいな表ソフトなのですが

設定クラス
メインフォームクラス
表示用のパネルクラス
全行クラス =(list(of 行クラス))
各行クラス
セルクラス

といった感じでクラスを作っています

「クラス間の関係が切り放せてない」というのがどいうことかはコードを見ないとわからないかもしれませんが
セルクラスは各行クラスをBYREFで参照していますし
各行クラスは全行クラスをBYREFで参照しています
また、セルクラスの挙動はメインフォーム内で作成した設定クラスのインスタンスをBYREFで参照しています

このような他のクラスを参照しなければ動作しないようなクラスは
「クラス間の関係が切り放せてない」ということなのでしょうか
また値渡しで参照すれば切り離せているということになるのでしょうか

こういう場合は設定インスタンスはメインフォームでのみ変更するようにするのでしょうか

投稿者 うたひこ  (社会人) 投稿日時 2008/11/15 21:49:47
何か大きな部分で一般的認識とのズレがあるように思います。

わが道を行かれる方ならそれでも構わないのでしょうが、
であるならこのスレを立てたりなどの
一般的手法を追求する姿勢と矛盾がありますので、
そうではないと思ってお話します。



具体的には


>セルクラスは各行クラスをBYREFで参照していますし
>各行クラスは全行クラスをBYREFで参照しています
>また、セルクラスの挙動はメインフォーム内で作成した設定クラスのインスタンスをBYREFで参照しています


>また値渡しで参照すれば切り離せているということになるのでしょうか

の部分が、共通認識とズレています。


①は一般的には、下駄や雪駄の汗臭を装備します(←おふざけ)
ふざけないで言うと、プロパティとして実装します。

②はおっしゃっている意味が全くわかりません。
理解している者からは出てこない言葉だと思います。



上述のことから、あなたの認識がズレていると推理しましたが、
具体的にどのようにズレているかまでは、
いままでの情報からはわかりません。

①や②について、どのような処理結果を求めて
どのようなコードをお書きになったかを示していただければ、
具体的なことをお答えできると思います。
投稿者 るしぇ  (社会人) 投稿日時 2008/11/15 21:56:29
全行クラスの設定を「国の法律」として
各行クラスの設定を「県の条例」
セルクラスの設定を「学校の校則」とします。

基本的に上から下へ参照するだけでいいはずです。
下から上へ反映させる必要はありません。ところが
BYREFってことは変更を逆流させて反映させるってことでは?
つまり学校の校長が法律を変更するような処理があるのでは?

学校では「国の法律」を基本にして、都合が悪い部分は
「国の法律」を適用せず「学校の校則」で補えばいいでしょう。
学校で変更するのは「学校の校則」だけで十分で、「国の法律」
まで変更しないと処理できないという場合は何か間違ってます。

例えば「朝礼を8:20にする」と「国の法律」に書いてあるとか。
これは設定のある場所が間違っていますね?朝礼を8:40にしたい
学校は「国の法律」を変更する。。。おかしいでしょ?

>> BYREFで引数として設定を渡しています
>まずは本当に ByRef でなければならないのかを確認してみてください。
とあったと思います。なぜ逆流する処理が必要なのか、その目的か、
1つでいいので、もう少し具体的な処理内容を教えてください。


>現在作っているアプリはエクセルみたいな表ソフトなのですが
エクセルは。。。確かに参照しまくってる感もありますがw
VBの既存のクラス(DataGridView とか ListView)のクラス設計を
参考にしてみては?メソッド・プロパティ・イベントの一覧を
整理すればどんなクラス設計か見えてきませんか?
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2008/11/16 12:13:04
> 現在作っているアプリはエクセルみたいな表ソフトなのですが
表形式のデータとして管理されるクラスとしては、.NET では
DataTable / DataGridView / ListView などがありますね。

社会人さんのコードは、これらのいずれかと似た設計になっているのでしょうか?
それとも、全く異なるクラス設計になっているのでしょうか?


> 設定クラス
これは、どのような設定情報を持ち合わせていますか?

> メインフォームクラス
> 表示用のパネルクラス
パネルクラスというのは、どのような物でしょうか?

> 全行クラス =(list(of 行クラス))
これは、List(Of Row) のインスタンスという事でしょうか?
それとも、List(Of Row) な変数を内部に持つ自作クラスでしょうか?

> 各行クラス
> セルクラス
これらの親子関係は、どのようになっていますか?

・「すべての列」を表す事はできるのか? (それとも表す必要は無いのか?)
・どの行にも属さないセルはありえるのか? それとも、ひとつのセルは必ずいずれかの行に属するのか?
・どの全行クラスにも属さない行はありえるのか?
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2008/11/16 13:27:26
> こういう場合は設定インスタンスはメインフォームでのみ変更するようにするのでしょうか
設定インスタンスが持つ情報が何であるのかを説明してもらわないと回答できません。

ただ、DataGridView を例に取って、設定インスタンスというのを
セルの設定情報(DataGridViewCellStyle クラス)だと読み替えれば、

・設定インスタンスを管理するのは DataGridView (またはそれぞれのセル)の役割。フォームでは無い。

・設定情報を書き換えるのは、フォームの役割。DataGridView が自身のセルスタイルを勝手に書き換えたりはしない。

という事が言えるかと思います。


> セルクラスは各行クラスをBYREFで参照していますし
> 各行クラスは全行クラスをBYREFで参照しています

ByRef で参照させている理由を説明することはできますか?
それが分かれば、社会人さんのコードが適切であるかどうかが見えてきますし、
もし適切でないならば、どのように修正すべきかを考察できるかも。