C# WinFormsリファクタリング — Tim Coreyによる詳細な解説
リファクタリングは、単に動作するコードを維持可能で柔軟で将来に準備ができた状態に分けるトピックの一つです。 "C# App From Start to Finish"シリーズの第24レッスンで、ティムコーリーは実際のWinFormsアプリケーション内で実用的なリファクタリングセッションを行います。 理論ではなく、ティムは既存のプロジェクトをリファクタリングし、変更が必要な理由と安全にそれに接近する方法を説明します。
この記事では、C# WinFormsのリファクタリングをティムのビデオの説明に忠実に従って詳しく見ていきます。
この授業でリファクタリングが意味すること
0:02に、ティムは24レッスンを紹介し、リファクタリングがコードを同じタスクをより良いやり方で実行するように作り直すことだと説明します。 彼はすでにアプリケーションが動作しているが、"ガラクタ"や標準に達していない箇所があると指摘します。 ティムによれば、これはプロジェクトがさらに成長する前に物事を整えれ始めるのに適切な時期です。
彼は、リファクタリングは機能を追加することではなく、構造、可読性、長期的な保守性を改善しながら、動作は同じに保つことだと強調します。
インターフェースにおける不要な戻り値のクリーンアップ
0:31から、ティムはインターフェースのメソッドシグネチャの修正という最初のリファクターに入ります。 彼はプロジェクトの初期段階で、メソッドが不必要にモデルを返していたことを説明します。 オブジェクトはすでに参照で渡されているため、同じモデルを再度返すことは実質的に目的を持ちません。
ティムはこれらのメソッドをvoidに変更する方法を示し、これは直ちに実装を破壊します。 彼はなぜこれが起こるのか説明します:インターフェースが変更されると、すべて実装クラスは新しいシグネチャに完全に対応しなければならないのです。 彼はSQLコネクタとテキストコネクタを修正して、新しいインターフェースに対応させる方法を歩いて説明します。
2:33に、ティムはVisual Studioがインターフェースを自動実装する場合に起こることを示します。 彼は重複したメソッド名が発生する理由を説明し、戻り値の型だけではメソッドシグネチャを区別するのに十分ではないことを明確にします。
リファクタリングによって引き起こされたビルドエラーの修正
4:00に、ティムはソリューションをビルドし、意図的に表示されるエラーを示します。 彼はこれらのエラーが予想され、有用であることを説明します。 たとえば、以前はモデルを返すことを期待していたコードは、今やメソッドがvoidを返すため失敗します。
ティムは不要な代入を除去し、ソリューションを再構築することでこれを修正します。 彼は、リファクタリングはしばしば短期的なブレイクを引き起こしますが、各エラーは改善が必要なコードを直接指摘することを強調します。
ファイル名定数をGlobalConfigに移動する
5:25から始めるとティムはテキストコネクタのファイル名ハンドリングをリファクタリングします。 以前は、ファイルパスがクラス内のプライベート文字列定数として保存されていました。 ティムは、これらはもはや必要なく、既にGlobalConfigにファイル名が存在していると説明します。
彼はローカル定数をGlobalConfig.PeopleFile、GlobalConfig.PrizesFile、および似たプロパティと置き換えます。 ティムはこの変更が設定を中心化し、アプリケーション全体が一貫したファイルパスを使用することを保証することを説明します。
彼はまた、いっぺんにあまりに多くのことをリファクタリングしないようにと重要なポイントを伝えます。 彼はその他の改善が可能であることを見つけた際には、はっきりと後でそれに戻ると示しています。
テキストコネクタプロセッサのリファクタリング
7:44に、ティムはテキストコネクタプロセッサ内のメソッドから複数のファイル名パラメータを削除することでリファクタリングを続けます。 ファイル名がすでにGlobalConfigに存在するため、それらを渡すことは冗長です。
ティムは慎重にメソッドシグネチャを更新し、パラメータをGlobalConfig参照と置き換え、Visual Studioのエラーリストに頼って彼を導きます。 彼は、リファクタリング中に多くのエラーを見るのは通常のことであり、パニックを感じるべきではないと説明します。
13:16に、彼はリアルタイムのエラートラッキングがプロジェクト全体のメソッドコールを体系的にクリーンアップする際にどれだけ役立つかを指摘します。
過剰に多くを行っているUIロジックの特定
15:24に、ティムは大きな設計問題を強調します:UIイベントハンドラ内の過剰なロジック。 彼はボタンクリックイベントを進めて、それがイベントが含むべき以上のコードを含んでいると説明します。 Windows Formsでは、ボタンクリックなどのユーザーアクションはイベントハンドラによって処理され、イベントが発生したときに実行される具体的なアクションを定義します。
ティムは、UIコードはユーザーインタラクションのみに集中するべきだと説明します。 Windows Formsはイベント駆動のプログラミングモデルを使用し、ユーザーアクションがコードを処理するアプリケーションコードによってトリガーされます。 ビジネスロジック、たとえばトーナメントのスコアリングと勝者の進行は、クラスライブラリに属します。 この区分によって、同じロジックを後にWebアプリやWPFアプリケーションで再利用できるようになります。
トーナメントロジックをクラスライブラリへ抽出する
17:55から、ティムはトーナメントのスコアリングロジックをトーナメントロジッククラス内の新しい公開メソッドに移動します。 彼はそれをUpdateTournamentResultsと名付け、トーナメントのモデル全体を受け入れる理由を説明し、単一の対戦ではありません。
彼はロジックをフォームからコピーし、クラスライブラリに貼り付け、UI要素に依存せずに動作するように調整します。 このリファクタリングにより、トーナメントのルールが1箇所に収まり、どこでも再利用可能になります。
対戦のスコアリングと不戦勝の正しい処理
21:37に、ティムは対戦がスコアリングされる方法をリファクタリングします。 単一の対戦を扱う代わりに、全ラウンドを回り、スコアリングが必要な対戦のリストを作成します。
彼は完成したゲームの検出と不戦勝の原理を説明します。 ティムは、以前は不戦勝が架空のスコアを割り当てる"ハッキー"な方法で処理されていたことを指摘します。 リファクタリングにより、不戦勝を明確でクリーンに処理できるようになります。
スコアリングをプライベートメソッドに抽出する
28:17に、ティムはスコアリングロジックをプライベートメソッドに抽出します。 彼はフォーカスされた小さなメソッドがコードを理解しやすくし、保守しやすくすることを説明します。
彼はメソッド名をそれが何をするかを反映するように変更し、例えばスコアリングロジックを"対戦の中で勝者をマークする"に変えます。
設定可能な勝者決定
29:58から、ティムは勝者決定ロジックをリファクタリングし、高スコアが勝つまたは低スコアが勝つシナリオの両方に対応できるようにします。 彼は新しいアプリケーション設定を導入し、設定がハードコーディングされたルールよりも優れている理由を説明します。
彼はこの値をトーナメントモデルに保存する別のデザインについて議論し、その変更がこの授業の範囲外である理由を説明します。
勝者を進行させて結果を保存する
45:40に、ティムは勝者を次のラウンドへ進行させることに移ります。 彼は勝者を親マッチアップに一致させる方法と、正しい時にデータを保存することが重要である理由を説明します。
52:10頃には、彼はマッチアップを更新するための簡潔なForEachアプローチを示し、それが伝統的なループと機能的に同等であるがよりコンパクトであることを説明します。
リファクタリングによって導入されたバグの修正
58:33に、ティムはデータベースで不正確なデータを発見し、その問題をトーナメントが保存される前の論理呼び出しに追跡します。 彼はリファクタリングが新しいバグを生むのではなく隠されたバグを露見させる場合があることを説明します。
更新ロジックを永続化後に正しい場所へ移動することで、Timは問題を解決し、アプリケーションを再テストします。
リファクタリングに関する最終的な考え
1:09:00に、Timはこのレッスンでリファクタリングが達成したことをまとめて締めくくります。 彼はリファクタリングが単なるコードの整理以上のものであり、エッジケースの処理、設計上の欠陥の修正、将来の変更への準備をも意味すると説明します。
彼はリファクタリングが継続的なプロセスであることを強調し、次のレッスンではエラー処理に焦点を当てることを示唆します。
締めの言葉
このレッスンは、リファクタリングが実際のプロジェクトでどのように行われるかを正確に示しています:段階的でありながら時には複雑で最終的には報われる。 Tim Coreyのステップバイステップのアプローチに従うことで、機能を損なうことなく、そして次に何をすべきかを推測することなくWinFormsアプリケーションを改善するための実践的な設計図を手に入れることができます。

