質問: C#、WPFで作成している、とあるアプリケーションの該当の画面を開いた時の 初期化処理のタイミングについて悩んでいます。 皆さんの意見を求めます。 ### そのアプリケーションの目的 **設定ファイルを編集する。** 目的を達成するには * ファイルを作成する * 既存のファイルを読み込む * 既存のファイルを上書きで保存する これらのことができれば良いと考えました。 ### 作ったアプリケーションの概要 その該当の画面を構成するコントロールは * 本ウィンドウ(Window) * 入力フォーム複数個(TextBox) * 更新(ファイル上書き保存)ボタン(Button) が存在します。 行っている初期化処理は * 設定ファイルを読み込む * 設定ファイル内の値を取得する * 取得した値を入力フォームに反映する(前回の設定値として) 初期化処理後、ユーザーは入力フォームを任意で入力し、 更新ボタンを押下できる。 更新ボタンを押下すると入力フォームの値をもとに 設定ファイルが新たに上書き保存される。 その後、本ウィンドウは閉じられる。 という至ってシンプルなアプリケーションです。 ### 悩んでいる内容 初期化するタイミングの問題です。 いきなりプログラミングチックな内容になります。 Windowコントロールのイベントは * Initialized * Loaded * ContentRendered などがあり、 私が把握している限りの実行されるメソッドを時系列順で列挙すると * Initilizedイベントハンドラ * View(Window)のコンストラクタ * ViewModelのコンストラクタ * Loadedイベントハンドラ * ContentRenderedイベントハンドラ(このイベントが発生するまでに画面が表示される) があります。 ※一応MVVMで作成しているつもりです。 このアプリケーションの初期化処理 * 設定ファイルを読み込む * 設定ファイル内の値を取得する * 取得した値を入力フォームに反映する(前回の設定値として) タイミングについて上記のどのメソッド内でそれぞれを実行すべきか悩んでいます。 ### 自分の考え **初期化の処理時間の長さによって変わる?** まず、ユーザーが入力するのは、ウィンドウが表示された後かなと考えました。 ユーザーが入力する前までには、入力フォームに前回の値を入力している状態 (初期化完了)になっていればよいと考えました。 そのため、上記のメソッドのうちであれば、ViewModelのコンストラクタやViewのコンストラクタで初期化すれば良いと判断しました。 しかし、初期化処理が長くなる場合、ウィンドウが数秒表示されずに ユーザーにストレスを与えてしまう可能性を考えました。 そうなるとウィンドウはさっさと表示して、ウィンドウが表示された直後は 前回の値が反映されるまで入力フォームはユーザー入力を受け付けないようにし 読み込みが終わったらユーザー入力を受け付けるようにする。 (受け付けないうちは、読み込み中であることをインジケーター等でユーザーに伝える) つまり、ContentRenderedイベント後、入力フォームは無効化し、 ファイルを読み込み、値を反映し終えたら入力フォームを有効化する。 ということです。 ### 自分なりの結論 処理時間が短い場合、コンストラクタで初期化 長い場合は、画面表示後に初期化 が良いのではないかと考えました。 ### 結論づけておいてアレなので皆さんにお聞きします。 処理時間の長さによって変わると自分で結論付けておいて、いまいちピンときていません。 ピンとこない理由もわかりませんが、コンピュータや環境によって処理の時間なんて多少変わってしまうし、もっと明確な判断基準があるのではないかなぁ と思っております。 ※尚、以下の記事で、ユーザーは「ページ表示の待ち時間が2秒を超えるとイライラし始める」 ということを言ってましたので今は2秒という値を基準にしています。 ページ表示2秒でイライラし始め、3分の1は「もういいや」となる (1/2) - ITmedia ビジネスオンライン **皆さんは、初期化処理をどこに記述していますか。**
回答: 私の方針としてはこんな感じで実装しています。 ・設定の読み書きはアプリケーション内部のサービスとしてDIコンテナに放り込んでおく。 ・ViewModelではViewで使う(表示に利用する)データだけを保持する。 ・処理時間が長い場合は短くする。 DIコンテナを使うとリソース毎に時間的スコープを細かく設定できますし、まとめて書けるので見通しが良くなります。 巨大データはDBMSを利用するなどして、必要なものを必要な時に必要な分だけ取り出すようにすると読み込む時間を短縮できます。 それでも時間がかかる初期化は、裏で読んでおくなどViewやViewModel以外の責務として実装することをお勧めします。