私が遭遇したWindows Formsアプリケーションのほとんどは、存在しないか、単体テストのカバレッジが非常に低いです。また、メンテナンスが難しく、プロジェクト内のさまざまなFormクラスのコードの背後には数百行から数千行のコードがありますが、そうする必要はありません。Windows Formsが“レガシー”テクノロジーであるからといって、メンテナンス不可能な混乱を引き起こす運命にあるわけではありません。保守可能でテスト可能なWindows Formsアプリケーションを作成するための10のヒントを紹介します。
1. ユーザーコントロールでユーザーインターフェイスを分離する。
まず、1つのフォームに多くのコントロールを置かないでください。多くの場合、アプリケーションの主なフォームは論理領域(ビューと呼ぶことができます)に分解できます。これらのゾーンの各ゾーンのコントロールを独自のコンテナに入れると、自分の生活が楽になります。Windowsフォームでは、ユーザーコントロールを使用するのが最も簡単です。したがって、左側にツリービュー、右側に詳細ビューがあるエクスプローラー形式のアプリケーションがある場合、Tree Viewを独自のUser Controlに配置し、可能な右側ビューごとにUser Controlを作成します。同様に、タブコントロールがある場合は、タブコントロール内の各ページに個別のUser Controlを作成します。
これにより、クラスの管理が難しくなるのを防ぐだけでなく、サイズ変更やタブの順序設定などが可能になり、タスクが簡単になります。また、必要に応じてユーザーインターフェイス全体を一度に無効にすることもできます。また、ユーザーインターフェイスを論理的にグループ化されたコントロールを含む小さなユーザーコントロールに分割すると、アプリケーションのUIレイアウトを再設計することが容易になります。
2. UI以外のコードを後続のコードから除外する。
Windows Formsアプリケーションでは、ネットワーク、データベース、またはファイルシステムにアクセスするコードは、フォームの背後にあるコードに常にあります。これは“単一責任原則”に違反している。FormまたはUser Controlクラスは、ユーザーインターフェイスのみに焦点を当てる必要があります。したがって、背後にあるコードにUIとは無関係なコードがあることを検出したら、単一の責任を持つクラスにリファクタリングします。したがって、PreferencesManagerクラス、または特定のWebサービスを呼び出すクラスを作成できます。その後、これらのクラスをUIコンポーネントに依存関係として注入することができます(これは最初のステップですが、アイデアをさらに拡張することができます。
3. インタフェースによるパッシブ·ビューの作成
特に便利なテクニックの1つは、作成するすべてのフォームとユーザーコントロールにビューインターフェイスを実装することです。このインターフェイスには、ビュー内のコントロールの状態とコンテンツを設定して取得できるプロパティが含まれます。また、ボタンのクリックやスライダーの移動など、ユーザーの操作を報告するイベントも含まれます。目標は、これらのビューインターフェイスの実装が完全に受動的であることです。理想的には、フォームとUser Controlsの背後にあるコードに条件付きロジックがないはずです。
以下は、新しいユーザーエントリービューのビューインターフェイスの例です。この視点の実装は重要ではありません。ビジネスロジックは後続のコードには属しません(それが属する場所については後述します)。
interface INewUserView
{
string FirstName { get; set; }
string LastName { get; set; }
event EventHandler SaveClicked;
}
ビューの実装をできるだけシンプルにすることで、新しいテクノロジーでビューを再作成するだけであるため、WPFなどの代替UIフレームワークに最大限に移行することができます。他のコードはすべて再利用可能です。
4. presentersを使用したビューの制御
したがって、すべてのビューをパッシブにしてインターフェイスを実装した場合は、アプリケーションのビジネスロジックを実装し、ビューを制御する何かが必要です。これを“プレゼンター”クラスと呼ぶことができます。これは“Model View Presentator”またはMVPと呼ばれるパターンです。
Model View Presenterでは、ビューは完全に受動的であり、Presenterは表示するデータをビューに示します。また、ビューがプレゼンターと通信できるようになります。上の例では、イベントを発生させることで行いましたが、通常はこのパターンを使用して、ビューがプレゼンターを直接呼び出すことができます。
绝对不允许视图开始直接操作模型(包括你的业务实体、数据库层等)。如果你遵循 MVP 模式,你的应用程序中的所有业务逻辑都可以轻松测试,因为它位于 Presenter 或其他非 UI 类中。
5. エラーレポート用サービスの作成
通常、プレゼンタークラスはエラーメッセージを表示します。しかし、MessageBox.ShowをUI以外のクラスに入れないでください。このメソッドを単体テストできなくします。代わりに、問題を報告する必要があるときにプレゼンターが呼び出すことができるサービス(IErrorDisplay Serviceなど)を作成します。これにより、プレゼンターユニットをテスト可能にし、将来ユーザーにエラーを表示する方法を変更する柔軟性を提供します。
6. コマンドモードの使用
アプリケーションにユーザーがクリックできる多数のボタンを備えたツールバーがある場合は、コマンドモードが最適です。コマンドパターンでは、コマンドごとにクラスを作成することができます。これには大きな利点があります。コードを小さなクラスに分割し、それぞれに責任があります。また、特定のコマンドに関連するすべてのことを集中することもできます。このコマンドを有効にすべきですか?目に見えるはずですか?そのツールチップとショートカットキーは何ですか?実行するには特別な権限や許可が必要ですか?コマンド実行時にスローされる例外はどうすればよいですか?
コマンドモードを使用すると、アプリケーション内のすべてのコマンドに共通する各問題の処理方法を標準化できます。コマンドオブジェクトにはExecuteメソッドがあり、実際にはコマンドに必要な動作を実行するコードが含まれています。多くの場合、これは他のオブジェクトやビジネスサービスを呼び出す必要があるため、コマンドオブジェクトに依存関係として注入する必要があります。コマンドオブジェクト自体は単体テストが可能(そして直接)である必要がある。
7. IoCコンテナを使用した依存関係管理
PresenterクラスとCommandクラスを使用している場合、それらが依存するクラスの数が時間とともに増加していることがわかります。UnityやStructureMapのような制御反転コンテナが本当に役立つのは、ここです。依存関係のレベルに関係なく、ビューやプレゼンターを簡単に構築できます。
8. イベントアグリゲータ·モードの使用
Windowsフォームアプリケーションで非常に便利なもう1つのデザインパターンは、イベントアグリゲーターパターン(“メッセンジャー”または“イベントバス”と呼ばれることもあります)です。これは、イベントの開始者とイベントハンドラが互いに結合する必要がないパターンです。コード内で他の場所で処理する必要のある“イベント”が発生した場合は、イベントアグリゲーターにメッセージを発行するだけです。メッセージに応答する必要があるコードは、誰が発信したかを心配することなくサブスクライブして処理できます。
たとえば、ユーザーがUI内で現在どこにいるかの詳細を含む“ヘルプをリクエスト”メッセージを送信したとします。次に、別のサービスがメッセージを処理し、Webブラウザでヘルプドキュメント内の正しいページが起動されることを確認します。もう一つの例はナビゲーション。アプリケーションに複数の画面がある場合は、[ナビゲート]メッセージをイベントアグリゲーターに公開し、購読者は新しい画面がユーザーインターフェイスに表示されることを確認してメッセージに応答できます。
イベントアグリゲーターは、イベントのパブリッシャーとサブスクライバを根本的に分離することに加えて、単体テストが容易なコードを作成するという大きな利点があります。
9. AsyncとAwaitを使ったスレッド処理
NET 4以降をターゲットにしており、Visual Studio 12以降を使用している場合は、新しいasyncキーワードとawaitキーワードを使用できることを忘れないでください。これにより、アプリケーション内のスレッドコードが大幅に簡素化され、UIスレッドへのループバックタスクが完了したときに自動的に処理されます。また、複数のバックグラウンドタスクのチェーンにまたがる例外処理を大幅に簡素化します。Windowsフォームアプリケーションに最適で、まだお持ちでない場合は試す価値があります。
10.遅すぎない。
可以将我上面描述的所有模式和技术改造为现有的 Windows 窗体应用程序,但我可以从痛苦的经验告诉你,这可能需要大量工作,尤其是当窗体背后的代码达到数千行时。如果你开始使用 MVP、事件聚合器和命令模式等模式构建应用程序,你会发现随着它们变得越来越大,维护起来会少很多痛苦。你还可以对所有业务逻辑进行单元测试,这对于持续的可维护性至关重要。
著者:マーク·ヒース
原文へのリンク:https://markheath.net/post/maintainable-winforms
投稿者: OneByOneDotNet
公開番号の記事へのリンクhttps//mp.weixin.qq.com/s/ks_ghCRxMmOQPYFib0cb3g