ai-driven-development legacy-migration blazor

WinForms の可視 / 活性制御を Blazor で再現するコツ

WinForms の `Visible` / `Enabled` を素朴に Blazor の `@if` / `disabled` に置き換えると、条件式が画面中に散らばって保守不能になります。「計算プロパティに寄せる」だけで世界が変わりました。

W
渡邊 賢

なぜ書いたか

WinFormsの業務画面は、ボタンやコントロールの Visible / Enabledイベントハンドラの中で都度書き換える スタイルが多いです。Blazor移行時にそれを写経すると、条件式が画面の各所に散らばって、後から「このボタンが押せる条件って結局何?」が誰にも分からなくなります。今回はその扱い方の話です。

やったこと

ルールはシンプルです。

可視 / 活性条件は、計算プロパティに1つずつ寄せる。

@code {
    private bool CanUseRestrictedDelete =>
        IsHistoryMode == false
        && CurrentRow?.IsDecided == false
        && CurrentUser.HasRole(Roles.HighPriv);

    private bool ShowReportColumns =>
        IsHistoryMode;
}

<button disabled="@(!CanUseRestrictedDelete)" @onclick="OnDelete">削除</button>

@if (ShowReportColumns)
{
    <th>世代番号</th>
    <th>履歴ステータス</th>
}

ボタン側のRazorには条件式を直接書かず、名前のついたフラグ を参照します。条件式の本体は @code の中に集約。

なぜこれが効くか

  • 可読性: 「このボタンはなぜ押せないのか」が CanUseRestrictedDelete の式を見れば分かる
  • 再利用性: 同じ条件を別の場所で参照したいとき、フラグを読むだけで済む
  • テスト容易性: 条件式が1箇所にまとまっているので、単体テストを書きやすい
  • AIレビューが効く: フラグ名と条件式が対応していれば、レビュー時に「条件のロジックが正しいか」だけ見ればいい

WinForms時代は btn_Delete.Visible = ... をハンドラのあちこちで書き換えていたので、最終的な状態を追うのが大変でした。Blazorの宣言的な記述と組み合わせると、これが劇的に楽になります。

わかったこと

  • 可視 / 活性の条件式を 名前付きフラグに寄せる だけで、画面の保守性がだいぶ上がります
  • AIに画面を作らせると、条件式をRazorの @if に直接書く傾向がある。「フラグに寄せて」と明示 しないと崩れます
  • フラグ名は 業務寄りの名前 にする。CanUseRestrictedDelete のように、何ができるかが名前から分かるように

ありがちな失敗

  • フラグ名が技術寄り(IsButton1Visible みたいなやつ)。誰も意味を覚えられない
  • フラグの中で別のフラグを呼びすぎて、依存関係が深くなる。1階層までで止めるのが目安
  • 副作用(API呼び出し)をフラグの中で走らせてしまう。フラグは 純粋関数 にする

次にやること / 未解決の問題

  • フラグの命名規約をまだ統一できていない。Can* / Show* / Is* の使い分けを決めたい
  • 似たフラグが画面間で重複しているケースがあり、共通モジュールに寄せるかどうか検討中
person

渡邊 賢

等差級数的Commit 運営 / ICD VIETNAM.LLC General Manager

AI駆動開発と段階的なレガシーモダン化をテーマに、日々の試行錯誤をこのブログに記録しています。

プロフィール詳細 arrow_forward

似たような課題に困っている方、一緒に考えませんか。

AI駆動開発・Vibe Coding・レガシーマイグレーションに関するご相談を受け付けています。