none
同じような機能を持つFormを作成するときのよい実装方法について RRS feed

  • 質問

  • いつもお世話になります。mkmarimoと申します。

     

    今回、件名にあるようなことについてアドバイスをいただきたいと思い投稿させていただきました。

     

    同じようなGUI、内部処理を持つFormを2つ作成するとき、

    普通にコーディングしていけば、ほとんど同じイベントハンドラや

    クラス構造になり、同じような内容のコードが複数個所にできてしまい、

    メンテナンス時に1個所直すと、残りの個所も直さなければならなくなってしまいますが、

    このような要件があるとき、どのように実装するのが効率がよいでしょうか?

     

    ちなみに今回の場合、同じようなといっても完全に同じではなく、6~7割程度同じです。

     

    なにかよい方法があればアドバイスください。

     

    以上、よろしくお願いします。

    2008年10月28日 22:02

回答

  • いろいろと方法はあると思いますが、解答のひとつとしてDI+AOPを挙げます。

    かなり簡単に表現すると、Strategyパターンの進化形で、フォームのコードを分離するようにします。.NETベースでもいくつかDIコンテナがありますから、それを利用すると良いでしょう。Seasar.NETやSpring.NETが有名でしょうか。

    2008年10月28日 23:46
  • まず共通の機能を実装したFormを作成し、実際のFormはそのFormを継承したFormとして作成すると良いのではないでしょうか。

    デザイナでイベントハンドラを作成するときなど、若干の注意が必要になりますが。

    2008年10月29日 0:23
  • 参考になるかわかりませんが・・・

     

    ○基底クラスを活用する方法

    ひとつ基底クラスとしてのFormを作成します。共通ロジックはそこに記述します。

    この基底クラスを継承したFormを2つ作成し、そこに共通ロジックで網羅しきれない独自ロジックを記述します。

     

    ○処理にあわせた別のクラスを活用する方法

    画面に依存しないようなロジック、例えばある値が0~100までの範囲にあるかなどといったロジックであれば、別のクラスを用意して、そこにロジックを集中化させます。

     

    一応こんな感じでやってきましたね~。

    いずれにしても同じものを2つ書かないように書かないように心がけるのは、ひとつの手だと思います。

    2008年10月29日 4:14
  •  mkmarimo さんからの引用
    やはり継承ですか。

     

    UI 的な継承は Form でやるのは嫌いなので私の場合は UserControl にします。

    2008年10月29日 8:55

すべての返信

  • いろいろと方法はあると思いますが、解答のひとつとしてDI+AOPを挙げます。

    かなり簡単に表現すると、Strategyパターンの進化形で、フォームのコードを分離するようにします。.NETベースでもいくつかDIコンテナがありますから、それを利用すると良いでしょう。Seasar.NETやSpring.NETが有名でしょうか。

    2008年10月28日 23:46
  • まず共通の機能を実装したFormを作成し、実際のFormはそのFormを継承したFormとして作成すると良いのではないでしょうか。

    デザイナでイベントハンドラを作成するときなど、若干の注意が必要になりますが。

    2008年10月29日 0:23
  • 参考になるかわかりませんが・・・

     

    ○基底クラスを活用する方法

    ひとつ基底クラスとしてのFormを作成します。共通ロジックはそこに記述します。

    この基底クラスを継承したFormを2つ作成し、そこに共通ロジックで網羅しきれない独自ロジックを記述します。

     

    ○処理にあわせた別のクラスを活用する方法

    画面に依存しないようなロジック、例えばある値が0~100までの範囲にあるかなどといったロジックであれば、別のクラスを用意して、そこにロジックを集中化させます。

     

    一応こんな感じでやってきましたね~。

    いずれにしても同じものを2つ書かないように書かないように心がけるのは、ひとつの手だと思います。

    2008年10月29日 4:14
  • GX999さん、毘沙門天さん、CrimsonPorkさん

     

    ご回答ありがとうございます。

     

    >GX999さん

     

    恥ずかしながらDI+AOPは初めて聞きました。

    これから勉強してみます。

     

    >毘沙門天さん、CrimsonPorkさん

     

    やはり継承ですか。

    私も最初は継承を考えましたが、今回の場合、すでに片方のFormが完成しており、

    共通の基底クラスを作成するために、完成しているFormに手を入れるのに結構コストが

    かかると思い、ここで相談させていただきました。

     

    すでに完成しているFormを新たに作る同じような機能を持つFormの基底クラスとする

    という案もあるかとは思いますが、必要ない機能まで継承しそうだな~と思っています。

    実際はまだ試せていません。。。

     

    まず、継承の方向で試してみようと思っていますが、他によい案がもしあればご教授ください。

     

    >毘沙門天さん

     

    ちなみにFormを継承した場合、イベントハンドラの追加に注意点があるとのことですが、

    具体的のお教えいただけませんでしょうか?

     

    以上、よろしくお願いいたします。

     

    2008年10月29日 5:49
  • >ちなみにFormを継承した場合、イベントハンドラの追加に注意点があるとのことですが、

     

    たいした問題ではありませんが。

     

    FormAを継承して、FormBを作成したとします。

    デザイナで、継承したFormB上のボタンをクリックした場合、そのFormBに新しくイベントが追加されます。

    このときデザイナは継承元のFormAに同じボタンのイベントが登録されているかどうかはチェックしてくれません。

    したがって登録されていれば、そのボタンのイベントハンドラはFormAとFormBの2つに存在し、別々に呼ばれることになります。

     

    イベントハンドラが同じ名前で登録されればコンパイラから警告が出るのでしょうが、別の名前で作成されて、別々にクリックイベントに登録されるのです。

     

    各Formに共通したボタンを用意して動作は別にしたいときなど、イベントハンドラの追加の順番によって、どちらのイベントハンドラが先に動作するかも分かりにくくなりますので注意しましょう。

    2008年10月29日 7:26
  •  mkmarimo さんからの引用
    やはり継承ですか。

     

    UI 的な継承は Form でやるのは嫌いなので私の場合は UserControl にします。

    2008年10月29日 8:55
  • 毘沙門天さん、じゃんぬねっとさん

     

    ご回答ありがとうございます。mkmarimoです。

     

    >毘沙門天さん

     

    イベントハンドラ追加時の注意事項のご教授、ありがとうございました。

    勉強になりました。

     

     

    >じゃんぬねっとさん

     

     じゃんぬねっと さんからの引用

    UI 的な継承は Form でやるのは嫌いなので私の場合は UserControl にします。

     

    「UserControl」は私の中では初めて知る言葉です。

    簡単にMSDNで調べて、サンプルを動かしてみましたが、いいカンジですね。

     

    まだ、知識が浅いので、UserControlについてご質問させてほしいのですが、

    これは、カスタムコントロールを作るための基底クラスと思ってよいのでしょうか。

     

    Visual Studioのデザイナとかを使っても作ることはできるのでしょうか。

     

    UserControlの作り方、使い方のルールなどを解説してある

    Webページとかがあれば教えてください。

     

    以上、よろしくお願いいたします。

    2008年10月29日 12:01
  •  mkmarimo さんからの引用

    まだ、知識が浅いので、UserControlについてご質問させてほしいのですが、

    これは、カスタムコントロールを作るための基底クラスと思ってよいのでしょうか。

     

    「複合コントロール」 と呼ばれるものを作成するために基底クラスだと思って頂いて良いと思います。
    複合コントロールは字のごとくで、ユーザーコントロールをコンテナとして複数のコントロールが上に乗っている状態を想像して頂ければと思います。

    Visual Studioのデザイナとかを使っても作ることはできるのでしょうか。

     

    はい、新しい項目の追加で 「ユーザーコントロール」 を選択してプロジェクトに追加してください。
    雛形のソースが作成され、デザイナでコントロールを追加することができます。

     

    UserControlの作り方、使い方のルールなどを解説してある

    Webページとかがあれば教えてください。

     

    私の知る限りでは MSDN ライブラリが 1 番わかりやすいです。
    UI 的には Form のように、Panel のようなコンテナのように使えば良いです。

     

    使い方、ルールについては、たとえば上位へのイベントの伝播などが上げられますが、
    今回はあくまで統一するためのものですので、それほど意識しなくても使えると思います。

     

    UserControl は拡張予定のない共通部分を作成しておくと、Form を継承する必要がなくなります。
    Form より細かい単位で、データの入れ物 (たとえば、データクラスや DataTable など) を一対で管理できます。

     

    一度試作的に作成してみてお気に召しましたら使ってあげてください。

    2008年10月29日 12:17
  • じゃんぬねっとさん

     

    丁寧に教えていただきありがとうございます。

     

    今日、数時間しか時間がとれませんでしたが、UserControlを利用してみました。

     

    すでに完成しているあるフォーム上のコントロールを2つほど取り出し、

    UserControlにしてみたんですが、そのUserControlを新たなFormに

    乗せようとするとエラーが発生してしまいました。

     

    【エラー内容】

    コンポーネント 'XXXXXX' を生成できませんでした。エラーメッセージ:

    'System.NullReferenceException: インスタンス化されたオブジェクトがありません。

     場所 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     

    上記エラーメッセージの該当箇所では、あるメンバオブジェクトに別クラスのインスタンスを

    参照させようとしています。

    処理はUserControlのコンストラクタで行っています。

     

    ちなみに、フォームの継承でも同じようなエラーメッセージが出て、デザイナで表示できませんでした。

    ※ただ、こちらはデザイナで表示できないだけで、正常に動作しました。

     

    UserControlとかフォームの継承では、あまり、複雑な処理はできないのでしょうか?

    Visual Studioは2005 SP1です。

     

    もし、なにかご存じのことがあれば教えてください。

     

     

     

    2008年10月30日 11:31
  • ちょっとこれだけだとなかなか原因の確認や再現がしにくいと思いますので、できれば作成したUserControlのソースなどはないでしょうか?

     

    >UserControlとかフォームの継承では、あまり、複雑な処理はできないのでしょうか?

    私が思いつく限りだと、とくに制限はなかったように思います。

    2008年10月31日 1:00
  • CrimsonPorkさん

     

    ご回答ありがとうございます。mkmarimoです。

     

     CrimsonPork さんからの引用

    ちょっとこれだけだとなかなか原因の確認や再現がしにくいと思いますので、できれば作成したUserControlのソースなどはないでしょうか?

     

    確かにそのとおりですね。すみません。

     

    で、ソースなんですが、ちょっとネットに公開するのはマズイものなので、

    代わりになるサンプルを作成しようとしたんですが、同じ現象が出ず、

    公開できるようなソースを用意できませんでした。

     

    せっかく助けの手をさしのべていただいたのに、申し訳ございません。

     

    もう少しの間、この質問は閉め切らず置いておきますので、どなたか

    経験のある方がいらっしゃれば、ご教授ください。

     

    2008年10月31日 6:01
  • そういえば、ひとつだけ思い出しましたので、mkmarimoさんのケースに該当するかどうかわかりませんが、記載します。

     

    ユーザーコントロールを作成したのですが、そのコンストラクタかInitializeComponentの中で、データアクセスをする記述を書いてしまっていることがありました。

     

    アプリケーションを通常どおりに起動したときは、ユーザーコントロールのインスタンス化の前にデータアクセスに必要な情報がアプリケーション内で定義済みなので、正常にロジックが動くのですが、開発中にユーザーコントロールのデザイナを利用しようとすると、データアクセスに必要な情報は定義されないので、エラーになってしまい、デザイナ上で表示できなくなってしまったことがあったように思います。

     

    以下のどちらかで確か対処しました。

    ○データアクセスのタイミングを上記以外のタイミングにした

    ○データアクセスに必要な情報をあらかじめチェックし、エラーにならないようにした

    2008年10月31日 8:00
  • CrimsonPorkさん

     

    お世話になります。mkmarimoです。

     

     CrimsonPork さんからの引用

    ユーザーコントロールを作成したのですが、そのコンストラクタかInitializeComponentの中で、データアクセスをする記述を書いてしまっていることがありました。

     

    まさに、ビンゴでした。

    コンストラクタにてデータアクセスする記述をしておりました。

     

    ご提示いただいた対処方法で正常にデザイナで表示できるようになりました。

     

    お返事が遅くなり、申し訳ありませんでした。

    本質問はこれで締め切らせていただきます。

     

    ご回答くださった方々、まことにありがとうございました。

    2008年11月5日 0:19