テックカリキュラム

レガシーVBコードの解析・分解・再設計

レガシーVBコードの解析・分解・再設計

本章では、長年運用されてきたVB.NETやVB6由来のレガシーコードを解析し、安全に分解・再設計する方法を学習します。

レガシーVBシステムでは、1つのFormに数千行のコードが書かれていたり、ボタンクリックイベントの中に入力チェック、業務ロジック、SQL、ファイル出力、ログ処理がすべて混在していたりすることがあります。 また、CommonUtilのような巨大共通クラス、DataTableの全層使い回し、SQL直書き、COMコンポーネント依存などもよく見られます。

このようなコードをいきなり理想的なアーキテクチャへ全面改修しようとすると、既存機能を壊す危険があります。 そのため、まず現状を解析し、影響範囲を把握し、小さな単位で安全に分解していくことが重要です。

本章のゴールは、壊せないレガシーVB資産を、安全に解析・分解・再設計し、長期保守可能な構造へ少しずつ改善できるようになることです。


1. レガシーVBコードの特徴

レガシーVBコードとは、古い技術や古い設計思想で作られ、長期間運用されてきたVB系のコードを指します。 古いから必ず悪いというわけではありません。 しかし、仕様変更や保守を重ねる中で、構造が複雑化し、変更しにくくなっていることが多くあります。

代表的な特徴

  • Formクラスが巨大化している
  • 画面イベントに業務ロジックが集中している
  • SQLが画面に直接書かれている
  • DataTableやDataSetを全層で使い回している
  • CommonUtilに何でも入っている
  • Option Strict Offに依存している
  • 例外処理がOn ErrorやCatch空処理になっている
  • COMコンポーネントやActiveXに依存している
  • 仕様書が古く、実装と一致していない
  • 特定担当者しか分からない処理がある

レガシーコードで最も危険なこと

レガシーコードで最も危険なのは、「汚いから全部書き直す」と判断してしまうことです。 長年動いているコードには、仕様書に残っていない業務ルールや例外対応が含まれている可能性があります。

そのため、最初に行うべきことは書き換えではなく、理解です。 現行コードが何をしているのか、どの業務に使われているのか、どのデータを更新しているのかを把握してから改善します。


2. 巨大Form解析

VB.NETのWindows Formsアプリケーションでは、Formクラスに処理が集中しやすいです。 画面イベント、入力チェック、DBアクセス、業務判断、ファイル出力、帳票出力が1つのFormに混在すると、数千行規模の巨大Formになります。

巨大Formで起きる問題

  • どこに何が書かれているか分からない
  • 1つの修正が別処理へ影響しやすい
  • 単体テストが難しい
  • 同じ処理が複数イベントに重複する
  • 画面変更と業務ロジック変更が分離できない
  • 新人や引き継ぎ担当者が理解しづらい

巨大Formの悪い例

Private Sub btnRegister_Click(sender As Object, e As EventArgs) Handles btnRegister.Click

    If txtCustomerName.Text = "" Then
        MessageBox.Show("顧客名を入力してください。")
        Return
    End If

    If txtAmount.Text = "" Then
        MessageBox.Show("金額を入力してください。")
        Return
    End If

    Dim amount As Decimal = Decimal.Parse(txtAmount.Text)

    Using connection As New SqlClient.SqlConnection(connectionString)
        connection.Open()

        Dim transaction = connection.BeginTransaction()

        Try
            Dim sql As String =
                "INSERT INTO Orders (CustomerName, Amount) VALUES (@CustomerName, @Amount)"

            Using command As New SqlClient.SqlCommand(sql, connection, transaction)
                command.Parameters.Add("@CustomerName", SqlDbType.NVarChar, 100).Value = txtCustomerName.Text
                command.Parameters.Add("@Amount", SqlDbType.Decimal).Value = amount
                command.ExecuteNonQuery()
            End Using

            transaction.Commit()

            MessageBox.Show("登録しました。")

        Catch ex As Exception
            transaction.Rollback()
            MessageBox.Show("登録に失敗しました。")
        End Try
    End Using

End Sub

このコードは一見普通に見えますが、画面、入力チェック、型変換、DB接続、トランザクション、SQL、メッセージ表示がすべて混在しています。

まず切り出すべき処理

  • 入力値の取得
  • 入力チェック
  • DTO作成
  • 業務処理
  • DBアクセス
  • メッセージ表示

分解後のForm例

Private Sub btnRegister_Click(sender As Object, e As EventArgs) Handles btnRegister.Click

    Dim request = CreateRequest()

    Dim result = _registerOrderUseCase.Execute(request)

    If result.Success Then
        MessageBox.Show("登録しました。")
    Else
        MessageBox.Show(result.Message)
    End If

End Sub

Private Function CreateRequest() As RegisterOrderRequest

    Return New RegisterOrderRequest With {
        .CustomerName = txtCustomerName.Text,
        .AmountText = txtAmount.Text
    }

End Function

最初から完全なクリーンアーキテクチャにする必要はありません。 まずはFormの責務を減らし、業務処理を外へ出すことが第一歩です。


3. 共通関数地獄の整理

レガシーVBシステムでは、Common、CommonUtil、Utility、Module1のような共通クラスに、あらゆる処理が詰め込まれていることがあります。

よくあるCommonUtilの中身

  • 日付フォーマット
  • 文字列変換
  • 入力チェック
  • DB接続
  • SQL実行
  • 帳票出力
  • CSV出力
  • 承認判定
  • 権限判定
  • メール送信

悪い例

Public Module CommonUtil

    Public Function FormatDate(value As DateTime) As String
        Return value.ToString("yyyy/MM/dd")
    End Function

    Public Function IsAdmin(userId As Integer) As Boolean
        ' DBを見て管理者か判定
        Return True
    End Function

    Public Sub ExportInvoice(orderId As Integer)
        ' 請求書出力
    End Sub

    Public Sub RegisterOrder()
        ' 受注登録
    End Sub

End Module

このような共通クラスは、何を変更するとどこへ影響するのか分かりにくくなります。 また、業務ロジックと汎用処理が混ざるため、再利用もしづらくなります。

整理方針

処理内容分離先の例
日付フォーマットDateTimeFormatter
文字列整形StringNormalizer
入力チェックValidator
DB接続Repository / DbConnectionFactory
帳票出力ReportService
権限判定AuthorizationService
業務登録処理Application Service / UseCase

整理後の例

Public Class DateTimeFormatter

    Public Function ToDateText(value As DateTime) As String
        Return value.ToString("yyyy/MM/dd")
    End Function

End Class
Public Class AuthorizationService

    Public Function CanManageUser(user As LoginUser) As Boolean
        Return user.Role = UserRole.Admin
    End Function

End Class

共通化は便利ですが、「何でも入れる場所」を作ると保守性が落ちます。 意味のある単位で分割し、名前から責務が分かるようにすることが重要です。


4. SQL直書きの分離

レガシーVBシステムでは、FormイベントやService内にSQLが直接書かれていることがあります。 小規模な処理では問題に見えなくても、機能が増えるとSQLの重複、修正漏れ、テスト困難、セキュリティリスクにつながります。

SQL直書きの問題

  • 同じSQLが複数画面に重複する
  • テーブル変更時の影響範囲が分かりにくい
  • SQLインジェクション対策が漏れやすい
  • 単体テストしづらい
  • 画面処理とDB処理が密結合する

悪い例

Private Sub btnSearch_Click(sender As Object, e As EventArgs) Handles btnSearch.Click

    Dim sql As String =
        "SELECT UserId, UserName, Email FROM Users WHERE UserName LIKE '%" &
        txtKeyword.Text &
        "%'"

    Dim table As New DataTable()

    Using connection As New SqlClient.SqlConnection(connectionString)
        Using adapter As New SqlClient.SqlDataAdapter(sql, connection)
            adapter.Fill(table)
        End Using
    End Using

    DataGridView1.DataSource = table

End Sub

このコードでは、SQLが文字列連結で作られており、SQLインジェクションの危険があります。 また、DBアクセスが画面に直接書かれています。

Repositoryへ分離する例

Public Class UserRepository

    Private ReadOnly _connectionString As String

    Public Sub New(connectionString As String)
        _connectionString = connectionString
    End Sub

    Public Function Search(keyword As String) As List(Of User)

        Dim users As New List(Of User)()

        Dim sql As String =
            "SELECT UserId, UserName, Email FROM Users WHERE UserName LIKE @Keyword"

        Using connection As New SqlClient.SqlConnection(_connectionString)
            connection.Open()

            Using command As New SqlClient.SqlCommand(sql, connection)
                command.Parameters.Add("@Keyword", SqlDbType.NVarChar, 100).Value = "%" & keyword & "%"

                Using reader = command.ExecuteReader()
                    While reader.Read()
                        users.Add(New User With {
                            .UserId = CInt(reader("UserId")),
                            .UserName = CStr(reader("UserName")),
                            .Email = CStr(reader("Email"))
                        })
                    End While
                End Using
            End Using
        End Using

        Return users

    End Function

End Class

Form側

Private Sub btnSearch_Click(sender As Object, e As EventArgs) Handles btnSearch.Click

    Dim users = _userRepository.Search(txtKeyword.Text)

    DataGridView1.DataSource = users

End Sub

Repositoryへ分離することで、画面はSQLの詳細を知らなくてよくなります。 また、SQLインジェクション対策もRepository内で統一しやすくなります。


5. DataTable依存の削減

VB.NET業務システムでは、DataTableやDataSetが便利なため、画面、Service、Repository、帳票、CSV出力まで全層で使われていることがあります。

DataTableは柔軟ですが、型安全性が低く、業務ルールを表現しづらいという問題があります。

DataTable依存の問題

  • 列名を文字列で指定するためミスに弱い
  • 型が実行時まで分かりにくい
  • 業務ルールを持たせにくい
  • どの列が必要か分かりにくい
  • 層をまたいでDB構造が漏れやすい
  • 単体テストしづらい

DataTableを使い回す例

Public Function CalculateTotal(table As DataTable) As Decimal

    Dim total As Decimal = 0

    For Each row As DataRow In table.Rows
        total += CDec(row("Amount"))
    Next

    Return total

End Function

このコードでは、Amountという列が存在する前提になっています。 列名変更やNULL混入に弱く、コンパイル時に検出できません。

DTOへ変換する例

Public Class OrderDto
    Public Property OrderId As Integer
    Public Property Amount As Decimal
End Class
Public Function CalculateTotal(orders As List(Of OrderDto)) As Decimal

    Return orders.Sum(Function(order) order.Amount)

End Function

DTOやEntityを使うことで、プロパティ名や型をコンパイル時に確認できます。 また、業務処理の意図も分かりやすくなります。

DataTableを残してよい場所

  • DataGridViewに直接バインドする一時的な表示処理
  • SqlBulkCopyへ渡す中間データ
  • 古い帳票ライブラリがDataTableを要求する場合
  • 既存資産との互換性を保つ必要がある場合

DataTable依存を減らす進め方

1. まずRepositoryの戻り値をDataTableからDTOへ変換する
2. Service層ではDTOやEntityを使う
3. DomainロジックからDataTableを排除する
4. 画面表示が必要な箇所だけDataTableへ変換する
5. 帳票ライブラリ都合のDataTableはAdapterで吸収する

DataTableを完全に禁止する必要はありません。 ただし、業務ロジックの中心にDataTableを置くと保守性が下がるため、利用範囲を意識的に限定することが重要です。


6. COM依存の切り離し

VB6や古いVB.NETシステムでは、COMコンポーネントやActiveXへの依存が残っていることがあります。 帳票、Excel操作、バーコード、スキャナ、FAX、外部機器、古い業務ライブラリなどで使われることがあります。

COM依存で起きる問題

  • 新しいOSで動作しない可能性がある
  • 32bit / 64bit問題が発生する
  • インストールや登録が属人化する
  • COM解放漏れでプロセスが残る
  • サーバー実行に向かない
  • 自動テストが難しい
  • 提供元のサポートが終了している場合がある

COMを直接呼び出す悪い例

Public Class InvoiceService

    Public Sub PrintInvoice(invoiceId As Integer)

        Dim report As Object = CreateObject("LegacyReport.Component")

        report.Load(invoiceId)
        report.Print()

    End Sub

End Class

このコードでは、InvoiceServiceがCOMコンポーネントに直接依存しています。 COMを差し替えたい場合やテストしたい場合に影響が大きくなります。

インターフェースで包む例

Public Interface IInvoicePrinter
    Sub Print(invoiceId As Integer)
End Interface
Public Class ComInvoicePrinter
    Implements IInvoicePrinter

    Public Sub Print(invoiceId As Integer) Implements IInvoicePrinter.Print

        Dim report As Object = Nothing

        Try
            report = CreateObject("LegacyReport.Component")
            report.Load(invoiceId)
            report.Print()

        Finally
            If report IsNot Nothing Then
                Runtime.InteropServices.Marshal.ReleaseComObject(report)
            End If
        End Try

    End Sub

End Class
Public Class InvoiceService

    Private ReadOnly _printer As IInvoicePrinter

    Public Sub New(printer As IInvoicePrinter)
        _printer = printer
    End Sub

    Public Sub PrintInvoice(invoiceId As Integer)
        _printer.Print(invoiceId)
    End Sub

End Class

COM依存をインターフェースの裏側に隠すことで、将来的にPDFライブラリやWeb帳票サービスへ置き換えやすくなります。

COM切り離しの進め方

  • COMを利用している箇所を一覧化する
  • 用途ごとに分類する
  • 代替可能なライブラリを調査する
  • すぐ置き換えられない場合はAdapterで包む
  • 新規コードからCOM直接参照を禁止する
  • 重要度の高い箇所から段階的に置き換える

7. 仕様不明コードの調査

レガシーシステムでは、なぜ存在するのか分からない条件分岐や、コメントのない特殊処理がよくあります。 このようなコードを不用意に削除すると、特定顧客、特定日付、特定業務だけで不具合が発生することがあります。

仕様不明コードの例

If customerCode = "9999" Then
    amount = 0
End If

この処理だけを見ると意味が分かりません。 しかし、過去の特別契約、テスト顧客、移行データ、例外運用など、何らかの業務理由がある可能性があります。

調査方法

  • コードコメントを確認する
  • コミット履歴を確認する
  • チケットや障害履歴を確認する
  • 利用者や業務担当者へ確認する
  • 本番データに該当ケースが存在するか確認する
  • ログから実際に通っている処理か確認する
  • 削除前にテストを作る

調査メモの例

対象箇所不明内容調査結果対応方針
OrderService.CalculateAmountcustomerCode = 9999 の特別処理旧テスト顧客用。現在本番利用なし削除候補。回帰テスト後に撤去
InvoiceForm.Load特定部署のみ税率を変更過去契約の特例。現在も利用中仕様として明文化しDomainへ移動

仕様不明コードは、すぐ削除するのではなく、調査し、記録し、必要であれば正式な業務仕様として再定義します。


8. 影響範囲分析

レガシーコードを修正する際は、影響範囲分析が非常に重要です。 あるメソッドが複数画面から呼ばれていたり、共通関数が多くの機能で利用されていたりするためです。

影響範囲として確認するもの

  • 呼び出し元画面
  • 呼び出し先メソッド
  • 利用テーブル
  • 更新対象データ
  • 帳票出力
  • CSV出力
  • 外部API連携
  • バッチ処理
  • 権限設定
  • 関連するテストケース

影響範囲メモの例

変更対象呼び出し元DB影響帳票影響テスト対象
UserService.RegisterUserForm、CsvImportBatchUsers、UserRolesなしユーザー登録、CSV取込
InvoiceCommon.CalculateTaxInvoiceForm、InvoiceBatch、ReportServiceInvoices請求書PDF請求計算、帳票出力

影響範囲分析のポイント

  • 検索だけでなく実行経路も確認する
  • 共通関数の変更は特に慎重に行う
  • DB更新を伴う処理は関連テーブルを確認する
  • 画面・バッチ・帳票で同じ処理を使っていないか確認する
  • 影響範囲に応じてリグレッションテストを増やす

9. ストラングラーパターン

ストラングラーパターンとは、既存システムを一気に作り直すのではなく、新しい構造を外側から少しずつ導入し、古い部分を段階的に置き換えていく移行手法です。

巨大なレガシーVBシステムを一括刷新するのはリスクが高いため、実務では段階的な置き換えが現実的です。

ストラングラーパターンの考え方

既存システム
    ↓
一部機能を新Serviceへ分離
    ↓
新機能は新構造で実装
    ↓
既存機能を順次置き換え
    ↓
古い機能を停止
    ↓
旧コードを削除

適用例

  • 新しい受注登録だけ新Serviceで作る
  • 帳票出力だけ新ライブラリへ置き換える
  • CSV取込だけ新バッチへ移行する
  • 検索APIだけWeb API化する
  • DBアクセス層だけRepository化する

メリット

  • 一括刷新よりリスクが低い
  • 業務を止めずに改善できる
  • 新旧比較しながら移行できる
  • 効果の高い箇所から着手できる
  • 失敗時に切り戻しやすい

注意点

  • 新旧システムの境界を明確にする
  • データ整合性を設計する
  • 同じ機能が二重管理にならないようにする
  • 移行途中の運用ルールを決める
  • 旧コードを残し続けない

ストラングラーパターンでは、「少しずつ置き換える」だけでなく、最終的に古いコードを削除する計画まで持つことが重要です。


10. 段階的リファクタリング

レガシーコードの改善では、一度に大きく書き換えるのではなく、小さな変更を積み重ねる段階的リファクタリングが有効です。

段階的リファクタリングの基本

  • 動作を変えない
  • 小さく変更する
  • 変更前後でテストする
  • 仕様変更と同時にやらない
  • 影響範囲を記録する
  • 元に戻せる単位で進める

改善の順番例

1. 変数名・メソッド名を分かりやすくする
2. 長いメソッドを小さく分ける
3. 入力チェックをValidatorへ分離する
4. DBアクセスをRepositoryへ分離する
5. 業務ルールをServiceまたはDomainへ移動する
6. DataTableをDTOへ置き換える
7. Interfaceを導入してテスト可能にする
8. 単体テストを追加する

メソッド抽出の例

Private Function ValidateInput() As List(Of String)

    Dim errors As New List(Of String)()

    If String.IsNullOrWhiteSpace(txtCustomerName.Text) Then
        errors.Add("顧客名を入力してください。")
    End If

    If String.IsNullOrWhiteSpace(txtAmount.Text) Then
        errors.Add("金額を入力してください。")
    End If

    Return errors

End Function

まずはこのような小さな切り出しで構いません。 小さく分けることで、次にValidatorクラスへ移動しやすくなります。

DTO化の例

Public Class RegisterOrderRequest
    Public Property CustomerName As String
    Public Property AmountText As String
End Class

画面コントロールを直接Serviceへ渡すのではなく、Request DTOへ変換することでUI依存を減らせます。


11. テストを先に作る

レガシーコードを安全に改善するには、既存動作を守るためのテストが重要です。 ただし、最初から全体を自動テスト化するのは難しいため、重要な処理からテストを追加します。

優先的にテストすべき処理

  • 金額計算
  • 税計算
  • 承認判定
  • 在庫引当
  • 権限制御
  • CSV取込
  • 帳票出力値
  • ステータス遷移

特性テスト

特性テストとは、現在の動作を仕様として固定するためのテストです。 たとえ内部実装がきれいでなくても、「今どう動いているか」をテストで記録し、リファクタリング後も同じ結果になることを確認します。

特性テストの例

<TestMethod>
Public Sub CalculateTax_CurrentBehavior_ReturnsExpectedAmount()

    Dim calculator As New LegacyTaxCalculator()

    Dim result = calculator.Calculate(1000D)

    Assert.AreEqual(100D, result)

End Sub

特性テストは、「本来あるべき仕様」を検証するというより、まず現在の動作を保護するために使います。 レガシーコード改善では非常に有効です。

テストなしで大改修しない

テストがない状態で大きく構造を変えると、既存動作を壊したかどうか判断できません。 自動テストが難しい場合でも、最低限の手動テストケースや現新比較データを用意してから修正します。


12. 再設計の判断基準

すべてのレガシーコードを完璧に再設計する必要はありません。 重要なのは、どこに時間をかけて改善すべきかを判断することです。

優先して改善すべき箇所

  • 変更頻度が高い
  • 障害が多い
  • 業務重要度が高い
  • 担当者が属人化している
  • テストが難しい
  • 外部連携に関係している
  • セキュリティリスクがある
  • 将来的な移行対象になっている

すぐに大きく直さなくてもよい箇所

  • ほとんど変更されない
  • 利用頻度が低い
  • 業務影響が小さい
  • 短期間で廃止予定
  • 周辺依存が多く変更リスクが高い

判断表の例

対象変更頻度業務重要度障害頻度改善優先度
受注登録
旧帳票出力
売上CSV取込

再設計は技術的な美しさだけで判断しません。 業務影響、変更頻度、障害リスク、移行計画を踏まえて優先順位を決めます。


13. 実務でありがちな失敗

動いているコードを理解せずに書き換える

レガシーコードには、仕様書にない業務ルールが含まれていることがあります。 理解しないまま書き換えると、特定条件だけ壊れる危険があります。

一気に全部きれいにしようとする

全面改修は影響範囲が大きく、テストも困難です。 まずは変更頻度や障害頻度の高い箇所から小さく改善します。

共通関数を不用意に修正する

CommonUtilのような共通関数は、多数の画面やバッチから呼ばれている可能性があります。 修正前に呼び出し元と影響範囲を必ず確認します。

DataTableを一気に全廃しようとする

DataTableは古い設計で多用されがちですが、既存帳票やDataGridViewと密接に関係している場合があります。 一気に消すのではなく、業務ロジックから優先的に排除します。

COM依存を放置する

COMコンポーネントは、OS更新や64bit化で急に問題化することがあります。 すぐ置き換えられなくても、依存箇所を洗い出し、Adapterで包むなどの対策が必要です。

テストなしでリファクタリングする

テストがない状態で構造変更すると、動作が変わったか判断できません。 特性テストや現新比較を用意してから改善します。


14. 演習課題

演習1:巨大Formを解析する

1つのFormクラスに、入力チェック、DB登録、帳票出力、ログ出力が混在している想定で、 それぞれをどのクラスへ分離すべきか整理してください。

演習2:CommonUtilを分解する

日付処理、文字列処理、権限判定、CSV出力、請求計算が混在したCommonUtilを、 責務ごとのクラスへ分割してください。

演習3:SQL直書きをRepositoryへ分離する

Formイベント内に書かれているSELECT文とINSERT文をRepositoryクラスへ移動し、 Form側はRepositoryまたはServiceを呼び出すだけにしてください。

演習4:DataTable依存をDTOへ置き換える

DataTableを受け取って合計金額を計算している処理を、 List(Of OrderDto)を使う形へ修正してください。

演習5:COM依存をAdapterで包む

帳票出力COMコンポーネントを直接呼んでいる処理を、 IReportPrinterインターフェースとComReportPrinter実装に分離してください。

演習6:仕様不明コードを調査する

特定顧客コード、特定部署、特定日付だけ分岐しているコードを見つけ、 調査項目、確認先、対応方針を整理してください。

演習7:段階的リファクタリング計画を作成する

巨大Form、SQL直書き、DataTable依存、CommonUtil肥大化がある既存VB.NETシステムを想定し、 5段階の改善計画を作成してください。


15. まとめ

本章では、レガシーVBコードを解析し、安全に分解・再設計する方法を学習しました。

レガシーVBシステムでは、巨大Form、共通関数地獄、SQL直書き、DataTable依存、COM依存、仕様不明コードなどがよく見られます。 これらはすぐに障害になるとは限りませんが、長期保守や移行の大きな妨げになります。

重要なのは、いきなり全面改修しないことです。 まず現行コードの動作を理解し、機能、DB、帳票、外部連携、呼び出し元、利用状況を整理します。 そのうえで、影響範囲を確認しながら小さく改善していきます。

巨大Formは、入力値取得、入力チェック、業務処理、DBアクセス、メッセージ表示を分離することで改善できます。 CommonUtilは、日付処理、文字列処理、権限判定、帳票出力、業務処理など、責務ごとに分割することが重要です。

SQL直書きはRepositoryへ分離し、パラメータ化クエリを徹底します。 DataTableは便利ですが、業務ロジックの中心に置くと型安全性と保守性が下がるため、DTOやEntityへ段階的に置き換えます。

COMコンポーネントへの依存は、すぐに撤去できなくても、インターフェースやAdapterで包むことで影響範囲を限定できます。 将来的なOS更新、64bit化、.NET移行に備えて、依存箇所を可視化しておくことが重要です。

仕様不明コードは、不要に見えても過去の業務要件を支えている可能性があります。 削除や変更の前に、ログ、データ、利用者、履歴を調査し、必要であれば正式な仕様として明文化します。

ストラングラーパターンや段階的リファクタリングを活用すれば、業務を止めずに少しずつ新しい構造へ移行できます。 特に、変更頻度が高い機能、障害が多い機能、業務重要度が高い機能から改善するのが現実的です。

本章のゴールは、壊せないレガシーVB資産を、安全に解析・分解・再設計できるようになることです。 レガシー改善では、技術力だけでなく、既存業務への敬意、影響範囲を読む力、段階的に進める判断力が求められます。